oleacc: Add support for retrieving an HWND from accNavigate to WindowFromAccessibleObject.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com> Signed-off-by: Piotr Caban <piotr@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
1621a5f427
commit
92fe1c3cf0
|
@ -30,6 +30,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(oleacc);
|
||||||
|
|
||||||
static const WCHAR lresult_atom_prefix[] = {'w','i','n','e','_','o','l','e','a','c','c',':'};
|
static const WCHAR lresult_atom_prefix[] = {'w','i','n','e','_','o','l','e','a','c','c',':'};
|
||||||
|
|
||||||
|
#define NAVDIR_INTERNAL_HWND 10
|
||||||
|
DEFINE_GUID(SID_AccFromDAWrapper, 0x33f139ee, 0xe509, 0x47f7, 0xbf,0x39, 0x83,0x76,0x44,0xf7,0x45,0x76);
|
||||||
|
|
||||||
extern HRESULT WINAPI OLEACC_DllGetClassObject(REFCLSID, REFIID, void**) DECLSPEC_HIDDEN;
|
extern HRESULT WINAPI OLEACC_DllGetClassObject(REFCLSID, REFIID, void**) DECLSPEC_HIDDEN;
|
||||||
extern BOOL WINAPI OLEACC_DllMain(HINSTANCE, DWORD, void*) DECLSPEC_HIDDEN;
|
extern BOOL WINAPI OLEACC_DllMain(HINSTANCE, DWORD, void*) DECLSPEC_HIDDEN;
|
||||||
extern HRESULT WINAPI OLEACC_DllRegisterServer(void) DECLSPEC_HIDDEN;
|
extern HRESULT WINAPI OLEACC_DllRegisterServer(void) DECLSPEC_HIDDEN;
|
||||||
|
@ -400,35 +403,71 @@ HRESULT WINAPI AccessibleObjectFromWindow( HWND hwnd, DWORD dwObjectID,
|
||||||
|
|
||||||
HRESULT WINAPI WindowFromAccessibleObject(IAccessible *acc, HWND *phwnd)
|
HRESULT WINAPI WindowFromAccessibleObject(IAccessible *acc, HWND *phwnd)
|
||||||
{
|
{
|
||||||
|
IServiceProvider *sp;
|
||||||
|
IAccessible *acc2;
|
||||||
IDispatch *parent;
|
IDispatch *parent;
|
||||||
IOleWindow *ow;
|
IOleWindow *ow;
|
||||||
|
VARIANT v, cid;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
TRACE("%p %p\n", acc, phwnd);
|
TRACE("%p %p\n", acc, phwnd);
|
||||||
|
|
||||||
IAccessible_AddRef(acc);
|
hres = IAccessible_QueryInterface(acc, &IID_IOleWindow, (void**)&ow);
|
||||||
|
if(SUCCEEDED(hres)) {
|
||||||
|
hres = IOleWindow_GetWindow(ow, phwnd);
|
||||||
|
IOleWindow_Release(ow);
|
||||||
|
if(SUCCEEDED(hres) && *phwnd)
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
VariantInit(&v);
|
||||||
|
variant_init_i4(&cid, CHILDID_SELF);
|
||||||
|
hres = IAccessible_accNavigate(acc, NAVDIR_INTERNAL_HWND, cid, &v);
|
||||||
|
if(SUCCEEDED(hres)) {
|
||||||
|
if(hres == S_OK && V_VT(&v) == VT_I4 && V_I4(&v)) {
|
||||||
|
*phwnd = LongToHandle(V_I4(&v));
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
/* native leaks v here */
|
||||||
|
VariantClear(&v);
|
||||||
|
}
|
||||||
|
|
||||||
|
hres = IAccessible_QueryInterface(acc, &IID_IServiceProvider, (void**)&sp);
|
||||||
|
if(SUCCEEDED(hres)) {
|
||||||
|
hres = IServiceProvider_QueryService(sp, &SID_AccFromDAWrapper,
|
||||||
|
&IID_IAccessible, (void**)&acc2);
|
||||||
|
IServiceProvider_Release(sp);
|
||||||
|
}
|
||||||
|
if(FAILED(hres)) {
|
||||||
|
acc2 = acc;
|
||||||
|
IAccessible_AddRef(acc2);
|
||||||
|
}
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
hres = IAccessible_QueryInterface(acc, &IID_IOleWindow, (void**)&ow);
|
hres = IAccessible_QueryInterface(acc2, &IID_IOleWindow, (void**)&ow);
|
||||||
if(SUCCEEDED(hres)) {
|
if(SUCCEEDED(hres)) {
|
||||||
hres = IOleWindow_GetWindow(ow, phwnd);
|
hres = IOleWindow_GetWindow(ow, phwnd);
|
||||||
IOleWindow_Release(ow);
|
IOleWindow_Release(ow);
|
||||||
IAccessible_Release(acc);
|
if(SUCCEEDED(hres)) {
|
||||||
return hres;
|
IAccessible_Release(acc2);
|
||||||
|
return hres;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hres = IAccessible_get_accParent(acc, &parent);
|
hres = IAccessible_get_accParent(acc, &parent);
|
||||||
IAccessible_Release(acc);
|
IAccessible_Release(acc2);
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
return hres;
|
return hres;
|
||||||
if(hres!=S_OK || !parent) {
|
if(!parent) {
|
||||||
*phwnd = NULL;
|
*phwnd = NULL;
|
||||||
return hres;
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
hres = IDispatch_QueryInterface(parent, &IID_IAccessible, (void**)&acc);
|
hres = IDispatch_QueryInterface(parent, &IID_IAccessible, (void**)&acc2);
|
||||||
IDispatch_Release(parent);
|
IDispatch_Release(parent);
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
return hres;
|
return hres;
|
||||||
|
acc = acc2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,9 +59,12 @@ DEFINE_EXPECT(Accessible_get_accChildCount);
|
||||||
DEFINE_EXPECT(Accessible_get_accChild);
|
DEFINE_EXPECT(Accessible_get_accChild);
|
||||||
DEFINE_EXPECT(Accessible_get_accName);
|
DEFINE_EXPECT(Accessible_get_accName);
|
||||||
DEFINE_EXPECT(Accessible_get_accParent);
|
DEFINE_EXPECT(Accessible_get_accParent);
|
||||||
|
DEFINE_EXPECT(Accessible_accNavigate);
|
||||||
DEFINE_EXPECT(Accessible_child_get_accName);
|
DEFINE_EXPECT(Accessible_child_get_accName);
|
||||||
DEFINE_EXPECT(Accessible_child_get_accParent);
|
DEFINE_EXPECT(Accessible_child_get_accParent);
|
||||||
|
DEFINE_EXPECT(Accessible_child_accNavigate);
|
||||||
|
|
||||||
|
#define NAVDIR_INTERNAL_HWND 10
|
||||||
DEFINE_GUID(SID_AccFromDAWrapper, 0x33f139ee, 0xe509, 0x47f7, 0xbf,0x39, 0x83,0x76,0x44,0xf7,0x45,0x76);
|
DEFINE_GUID(SID_AccFromDAWrapper, 0x33f139ee, 0xe509, 0x47f7, 0xbf,0x39, 0x83,0x76,0x44,0xf7,0x45,0x76);
|
||||||
|
|
||||||
static HANDLE (WINAPI *pGetProcessHandleFromHwnd)(HWND);
|
static HANDLE (WINAPI *pGetProcessHandleFromHwnd)(HWND);
|
||||||
|
@ -93,7 +96,11 @@ static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2)
|
||||||
return unk1 == unk2;
|
return unk1 == unk2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IAccessible Accessible;
|
||||||
static IAccessible Accessible_child;
|
static IAccessible Accessible_child;
|
||||||
|
static IOleWindow OleWindow;
|
||||||
|
static HWND Accessible_hwnd;
|
||||||
|
static HWND OleWindow_hwnd;
|
||||||
|
|
||||||
static HRESULT WINAPI Accessible_QueryInterface(
|
static HRESULT WINAPI Accessible_QueryInterface(
|
||||||
IAccessible *iface, REFIID riid, void **ppvObject)
|
IAccessible *iface, REFIID riid, void **ppvObject)
|
||||||
|
@ -106,6 +113,12 @@ static HRESULT WINAPI Accessible_QueryInterface(
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(IsEqualIID(riid, &IID_IOleWindow) && (iface == &Accessible)) {
|
||||||
|
*ppvObject = &OleWindow;
|
||||||
|
IOleWindow_AddRef(&OleWindow);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if(IsEqualIID(riid, &IID_IEnumVARIANT)) {
|
if(IsEqualIID(riid, &IID_IEnumVARIANT)) {
|
||||||
CHECK_EXPECT(Accessible_QI_IEnumVARIANT);
|
CHECK_EXPECT(Accessible_QI_IEnumVARIANT);
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
|
@ -157,11 +170,16 @@ static HRESULT WINAPI Accessible_get_accParent(
|
||||||
IAccessible *iface, IDispatch **ppdispParent)
|
IAccessible *iface, IDispatch **ppdispParent)
|
||||||
{
|
{
|
||||||
if(iface == &Accessible_child)
|
if(iface == &Accessible_child)
|
||||||
|
{
|
||||||
CHECK_EXPECT(Accessible_child_get_accParent);
|
CHECK_EXPECT(Accessible_child_get_accParent);
|
||||||
|
return IAccessible_QueryInterface(&Accessible, &IID_IDispatch,
|
||||||
|
(void **)ppdispParent);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
CHECK_EXPECT(Accessible_get_accParent);
|
CHECK_EXPECT(Accessible_get_accParent);
|
||||||
|
|
||||||
return E_NOTIMPL;
|
*ppdispParent = NULL;
|
||||||
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI Accessible_get_accChildCount(
|
static HRESULT WINAPI Accessible_get_accChildCount(
|
||||||
|
@ -297,7 +315,21 @@ static HRESULT WINAPI Accessible_accLocation(IAccessible *iface, LONG *pxLeft,
|
||||||
static HRESULT WINAPI Accessible_accNavigate(IAccessible *iface,
|
static HRESULT WINAPI Accessible_accNavigate(IAccessible *iface,
|
||||||
LONG navDir, VARIANT varStart, VARIANT *pvarEnd)
|
LONG navDir, VARIANT varStart, VARIANT *pvarEnd)
|
||||||
{
|
{
|
||||||
ok(0, "unexpected call\n");
|
if(iface == &Accessible_child)
|
||||||
|
CHECK_EXPECT(Accessible_child_accNavigate);
|
||||||
|
else
|
||||||
|
CHECK_EXPECT(Accessible_accNavigate);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Magic number value for retrieving an HWND. Used by DynamicAnnotation
|
||||||
|
* IAccessible wrapper.
|
||||||
|
*/
|
||||||
|
if(navDir == NAVDIR_INTERNAL_HWND && Accessible_hwnd) {
|
||||||
|
V_VT(pvarEnd) = VT_I4;
|
||||||
|
V_I4(pvarEnd) = HandleToULong(Accessible_hwnd);
|
||||||
|
return Accessible_hwnd ? S_OK : S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,8 +392,47 @@ static IAccessibleVtbl AccessibleVtbl = {
|
||||||
Accessible_put_accValue
|
Accessible_put_accValue
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static HRESULT WINAPI OleWindow_QueryInterface(IOleWindow *iface, REFIID riid, void **obj)
|
||||||
|
{
|
||||||
|
return IAccessible_QueryInterface(&Accessible, riid, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI OleWindow_AddRef(IOleWindow *iface)
|
||||||
|
{
|
||||||
|
return IAccessible_AddRef(&Accessible);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI OleWindow_Release(IOleWindow *iface)
|
||||||
|
{
|
||||||
|
return IAccessible_Release(&Accessible);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI OleWindow_GetWindow(IOleWindow *iface, HWND *hwnd)
|
||||||
|
{
|
||||||
|
if(OleWindow_hwnd) {
|
||||||
|
*hwnd = OleWindow_hwnd;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI OleWindow_ContextSensitiveHelp(IOleWindow *iface, BOOL f_enter_mode)
|
||||||
|
{
|
||||||
|
ok(0, "unexpected call\n");
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const IOleWindowVtbl OleWindowVtbl = {
|
||||||
|
OleWindow_QueryInterface,
|
||||||
|
OleWindow_AddRef,
|
||||||
|
OleWindow_Release,
|
||||||
|
OleWindow_GetWindow,
|
||||||
|
OleWindow_ContextSensitiveHelp
|
||||||
|
};
|
||||||
|
|
||||||
static IAccessible Accessible = {&AccessibleVtbl};
|
static IAccessible Accessible = {&AccessibleVtbl};
|
||||||
static IAccessible Accessible_child = {&AccessibleVtbl};
|
static IAccessible Accessible_child = {&AccessibleVtbl};
|
||||||
|
static IOleWindow OleWindow = {&OleWindowVtbl};
|
||||||
|
|
||||||
static void test_getroletext(void)
|
static void test_getroletext(void)
|
||||||
{
|
{
|
||||||
|
@ -1844,6 +1915,59 @@ static void test_default_edit_accessible_object(void)
|
||||||
DestroyWindow(hwnd);
|
DestroyWindow(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_WindowFromAccessibleObject(void)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
HWND hwnd;
|
||||||
|
|
||||||
|
/* Successfully retrieve an HWND from the IOleWindow interface. */
|
||||||
|
Accessible_hwnd = NULL;
|
||||||
|
OleWindow_hwnd = (HWND)0xdeadf00d;
|
||||||
|
hwnd = (HWND)0xdeadbeef;
|
||||||
|
hr = WindowFromAccessibleObject(&Accessible, &hwnd);
|
||||||
|
ok(hr == S_OK, "got %lx\n", hr);
|
||||||
|
ok(hwnd == (HWND)0xdeadf00d, "hwnd != 0xdeadf00d!\n");
|
||||||
|
|
||||||
|
/* Successfully retrieve an HWND from IAccessible::accNavigate. */
|
||||||
|
Accessible_hwnd = (HWND)0xdeadf00d;
|
||||||
|
OleWindow_hwnd = NULL;
|
||||||
|
hwnd = (HWND)0xdeadbeef;
|
||||||
|
SET_EXPECT(Accessible_accNavigate);
|
||||||
|
hr = WindowFromAccessibleObject(&Accessible, &hwnd);
|
||||||
|
ok(hr == S_OK, "got %lx\n", hr);
|
||||||
|
/* This value gets sign-extended on 64-bit. */
|
||||||
|
ok(hwnd == IntToPtr(0xdeadf00d), "hwnd != 0xdeadf00d!\n");
|
||||||
|
CHECK_CALLED(Accessible_accNavigate);
|
||||||
|
|
||||||
|
/* Don't return an HWND from either method. */
|
||||||
|
Accessible_hwnd = NULL;
|
||||||
|
OleWindow_hwnd = NULL;
|
||||||
|
hwnd = (HWND)0xdeadbeef;
|
||||||
|
SET_EXPECT(Accessible_accNavigate);
|
||||||
|
SET_EXPECT(Accessible_get_accParent);
|
||||||
|
hr = WindowFromAccessibleObject(&Accessible, &hwnd);
|
||||||
|
/* Return value from IAccessible::get_accParent. */
|
||||||
|
ok(hr == S_FALSE, "got %lx\n", hr);
|
||||||
|
ok(!hwnd, "hwnd %p\n", hwnd);
|
||||||
|
CHECK_CALLED(Accessible_accNavigate);
|
||||||
|
CHECK_CALLED(Accessible_get_accParent);
|
||||||
|
|
||||||
|
/* Successfully retrieve an HWND from a parent IAccessible's IOleWindow interface. */
|
||||||
|
Accessible_hwnd = NULL;
|
||||||
|
OleWindow_hwnd = (HWND)0xdeadf00d;
|
||||||
|
hwnd = (HWND)0xdeadbeef;
|
||||||
|
SET_EXPECT(Accessible_child_accNavigate);
|
||||||
|
SET_EXPECT(Accessible_child_get_accParent);
|
||||||
|
hr = WindowFromAccessibleObject(&Accessible_child, &hwnd);
|
||||||
|
ok(hr == S_OK, "got %lx\n", hr);
|
||||||
|
ok(hwnd == (HWND)0xdeadf00d, "hwnd != 0xdeadf00d!\n");
|
||||||
|
CHECK_CALLED(Accessible_child_accNavigate);
|
||||||
|
CHECK_CALLED(Accessible_child_get_accParent);
|
||||||
|
|
||||||
|
Accessible_hwnd = NULL;
|
||||||
|
OleWindow_hwnd = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(main)
|
START_TEST(main)
|
||||||
{
|
{
|
||||||
int argc;
|
int argc;
|
||||||
|
@ -1885,6 +2009,7 @@ START_TEST(main)
|
||||||
test_AccessibleObjectFromPoint();
|
test_AccessibleObjectFromPoint();
|
||||||
test_CreateStdAccessibleObject_classes();
|
test_CreateStdAccessibleObject_classes();
|
||||||
test_default_edit_accessible_object();
|
test_default_edit_accessible_object();
|
||||||
|
test_WindowFromAccessibleObject();
|
||||||
|
|
||||||
unregister_window_class();
|
unregister_window_class();
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
|
|
Loading…
Reference in New Issue