mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-02 00:33:38 +00:00
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',':'};
|
||||
|
||||
#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 BOOL WINAPI OLEACC_DllMain(HINSTANCE, DWORD, 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)
|
||||
{
|
||||
IServiceProvider *sp;
|
||||
IAccessible *acc2;
|
||||
IDispatch *parent;
|
||||
IOleWindow *ow;
|
||||
VARIANT v, cid;
|
||||
HRESULT hres;
|
||||
|
||||
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) {
|
||||
hres = IAccessible_QueryInterface(acc, &IID_IOleWindow, (void**)&ow);
|
||||
hres = IAccessible_QueryInterface(acc2, &IID_IOleWindow, (void**)&ow);
|
||||
if(SUCCEEDED(hres)) {
|
||||
hres = IOleWindow_GetWindow(ow, phwnd);
|
||||
IOleWindow_Release(ow);
|
||||
IAccessible_Release(acc);
|
||||
return hres;
|
||||
if(SUCCEEDED(hres)) {
|
||||
IAccessible_Release(acc2);
|
||||
return hres;
|
||||
}
|
||||
}
|
||||
|
||||
hres = IAccessible_get_accParent(acc, &parent);
|
||||
IAccessible_Release(acc);
|
||||
IAccessible_Release(acc2);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
if(hres!=S_OK || !parent) {
|
||||
if(!parent) {
|
||||
*phwnd = NULL;
|
||||
return hres;
|
||||
}
|
||||
|
||||
hres = IDispatch_QueryInterface(parent, &IID_IAccessible, (void**)&acc);
|
||||
hres = IDispatch_QueryInterface(parent, &IID_IAccessible, (void**)&acc2);
|
||||
IDispatch_Release(parent);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
acc = acc2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,9 +59,12 @@ DEFINE_EXPECT(Accessible_get_accChildCount);
|
|||
DEFINE_EXPECT(Accessible_get_accChild);
|
||||
DEFINE_EXPECT(Accessible_get_accName);
|
||||
DEFINE_EXPECT(Accessible_get_accParent);
|
||||
DEFINE_EXPECT(Accessible_accNavigate);
|
||||
DEFINE_EXPECT(Accessible_child_get_accName);
|
||||
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);
|
||||
|
||||
static HANDLE (WINAPI *pGetProcessHandleFromHwnd)(HWND);
|
||||
|
@ -93,7 +96,11 @@ static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2)
|
|||
return unk1 == unk2;
|
||||
}
|
||||
|
||||
static IAccessible Accessible;
|
||||
static IAccessible Accessible_child;
|
||||
static IOleWindow OleWindow;
|
||||
static HWND Accessible_hwnd;
|
||||
static HWND OleWindow_hwnd;
|
||||
|
||||
static HRESULT WINAPI Accessible_QueryInterface(
|
||||
IAccessible *iface, REFIID riid, void **ppvObject)
|
||||
|
@ -106,6 +113,12 @@ static HRESULT WINAPI Accessible_QueryInterface(
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
if(IsEqualIID(riid, &IID_IOleWindow) && (iface == &Accessible)) {
|
||||
*ppvObject = &OleWindow;
|
||||
IOleWindow_AddRef(&OleWindow);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if(IsEqualIID(riid, &IID_IEnumVARIANT)) {
|
||||
CHECK_EXPECT(Accessible_QI_IEnumVARIANT);
|
||||
return E_NOINTERFACE;
|
||||
|
@ -157,11 +170,16 @@ static HRESULT WINAPI Accessible_get_accParent(
|
|||
IAccessible *iface, IDispatch **ppdispParent)
|
||||
{
|
||||
if(iface == &Accessible_child)
|
||||
{
|
||||
CHECK_EXPECT(Accessible_child_get_accParent);
|
||||
return IAccessible_QueryInterface(&Accessible, &IID_IDispatch,
|
||||
(void **)ppdispParent);
|
||||
}
|
||||
else
|
||||
CHECK_EXPECT(Accessible_get_accParent);
|
||||
|
||||
return E_NOTIMPL;
|
||||
*ppdispParent = NULL;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -360,8 +392,47 @@ static IAccessibleVtbl AccessibleVtbl = {
|
|||
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_child = {&AccessibleVtbl};
|
||||
static IOleWindow OleWindow = {&OleWindowVtbl};
|
||||
|
||||
static void test_getroletext(void)
|
||||
{
|
||||
|
@ -1844,6 +1915,59 @@ static void test_default_edit_accessible_object(void)
|
|||
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)
|
||||
{
|
||||
int argc;
|
||||
|
@ -1885,6 +2009,7 @@ START_TEST(main)
|
|||
test_AccessibleObjectFromPoint();
|
||||
test_CreateStdAccessibleObject_classes();
|
||||
test_default_edit_accessible_object();
|
||||
test_WindowFromAccessibleObject();
|
||||
|
||||
unregister_window_class();
|
||||
CoUninitialize();
|
||||
|
|
Loading…
Reference in a new issue