Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/oleacc/client.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/dlls/oleacc/client.c b/dlls/oleacc/client.c index 0c2215fe62e..38611520b38 100644 --- a/dlls/oleacc/client.c +++ b/dlls/oleacc/client.c @@ -303,11 +303,35 @@ static HRESULT WINAPI Client_get_accKeyboardShortcut(IAccessible *iface, return S_OK; }
-static HRESULT WINAPI Client_get_accFocus(IAccessible *iface, VARIANT *pvarID) +static HRESULT WINAPI Client_get_accFocus(IAccessible *iface, VARIANT *focus) { Client *This = impl_from_Client(iface); - FIXME("(%p)->(%p)\n", This, pvarID); - return E_NOTIMPL; + GUITHREADINFO info; + HRESULT hr; + + TRACE("(%p)->(%p)\n", This, focus); + + V_VT(focus) = VT_EMPTY; + info.cbSize = sizeof(info); + if(GetGUIThreadInfo(0, &info) && info.hwndFocus) { + if(info.hwndFocus == This->hwnd) { + V_VT(focus) = VT_I4; + V_I4(focus) = CHILDID_SELF; + } + else if(IsChild(This->hwnd, info.hwndFocus)) { + IDispatch *disp; + + hr = AccessibleObjectFromWindow(info.hwndFocus, OBJID_WINDOW, + &IID_IDispatch, (void**)&disp); + if(FAILED(hr)) return hr; + if(!disp) return E_FAIL; + + V_VT(focus) = VT_DISPATCH; + V_DISPATCH(focus) = disp; + } + } + + return S_OK; }
static HRESULT WINAPI Client_get_accSelection(IAccessible *iface, VARIANT *pvarID)
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- -v2: Add more tests for returned IDispatch interfaces from get_accFocus. Most are todo's, because they rely upon the default window accessible object, which is mostly a stub at this point.
dlls/oleacc/tests/main.c | 99 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 2 deletions(-)
diff --git a/dlls/oleacc/tests/main.c b/dlls/oleacc/tests/main.c index 97fc625ac8b..180113b29f9 100644 --- a/dlls/oleacc/tests/main.c +++ b/dlls/oleacc/tests/main.c @@ -916,11 +916,11 @@ static DWORD WINAPI default_client_thread(LPVOID param)
static void test_default_client_accessible_object(void) { - IAccessible *acc; + IAccessible *acc, *win; IDispatch *disp; IOleWindow *ow; IEnumVARIANT *ev; - HWND chld, btn, hwnd, hwnd2; + HWND chld, chld2, btn, hwnd, hwnd2; HRESULT hr; VARIANT vid, v; BSTR str; @@ -939,6 +939,9 @@ static void test_default_client_accessible_object(void) btn = CreateWindowA("BUTTON", "btn &t &junk", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 50, 0, 50, 50, hwnd, NULL, NULL, NULL); ok(btn != NULL, "CreateWindow failed\n"); + chld2 = CreateWindowA("static", "static &t &junk", WS_CHILD | WS_VISIBLE, + 0, 0, 50, 50, chld, NULL, NULL, NULL); + ok(chld2 != NULL, "CreateWindow failed\n");
hr = CreateStdAccessibleObject(NULL, OBJID_CLIENT, &IID_IAccessible, (void**)&acc); ok(hr == E_FAIL, "got %x\n", hr); @@ -1013,6 +1016,94 @@ static void test_default_client_accessible_object(void) ok(hr == E_INVALIDARG, "get_accChild returned %x\n", hr); ok(disp == NULL, "disp = %p\n", disp);
+ /* Neither the parent nor any child windows have focus, VT_EMPTY. */ + hr = IAccessible_get_accFocus(acc, &v); + ok(hr == S_OK, "hr %#x\n", hr); + ok(V_VT(&v) == VT_EMPTY, "V_VT(&v) = %d\n", V_VT(&v)); + + /* Set the focus to the parent window. */ + ShowWindow(hwnd, SW_SHOW); + SetFocus(hwnd); + hr = IAccessible_get_accFocus(acc, &v); + ok(hr == S_OK, "hr %#x\n", hr); + ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v)); + ok(V_I4(&v) == CHILDID_SELF, "V_I4(&v) = %d\n", V_I4(&v)); + + /* Set focus to each child window. */ + SetFocus(btn); + hr = IAccessible_get_accFocus(acc, &v); + ok(hr == S_OK, "hr %#x\n", hr); + ok(V_VT(&v) == VT_DISPATCH, "V_VT(&v) = %d\n", V_VT(&v)); + ok(V_DISPATCH(&v) != NULL, "V_DISPATCH(&v) = %p\n", V_DISPATCH(&v)); + + hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IOleWindow, (void**)&ow); + ok(hr == S_OK, "got %x\n", hr); + hr = IOleWindow_GetWindow(ow, &hwnd2); + todo_wine ok(hr == S_OK, "got %x\n", hr); + todo_wine ok(btn == hwnd2, "hwnd2 = %p, expected %p\n", hwnd2, btn); + IOleWindow_Release(ow); + + hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IAccessible, (void**)&win); + ok(hr == S_OK, "got %x\n", hr); + IDispatch_Release(V_DISPATCH(&v)); + + V_VT(&vid) = VT_I4; + V_I4(&vid) = CHILDID_SELF; + hr = IAccessible_get_accRole(win, vid, &v); + todo_wine ok(hr == S_OK, "got %x\n", hr); + todo_wine ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v)); + todo_wine ok(V_I4(&v) == ROLE_SYSTEM_WINDOW, "V_I4(&v) = %d\n", V_I4(&v)); + IAccessible_Release(win); + + SetFocus(chld); + hr = IAccessible_get_accFocus(acc, &v); + ok(hr == S_OK, "hr %#x\n", hr); + ok(V_VT(&v) == VT_DISPATCH, "V_VT(&v) = %d\n", V_VT(&v)); + ok(V_DISPATCH(&v) != NULL, "V_DISPATCH(&v) = %p\n", V_DISPATCH(&v)); + + hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IOleWindow, (void**)&ow); + ok(hr == S_OK, "got %x\n", hr); + hr = IOleWindow_GetWindow(ow, &hwnd2); + todo_wine ok(hr == S_OK, "got %x\n", hr); + todo_wine ok(chld == hwnd2, "hwnd2 = %p, expected %p\n", hwnd2, chld); + IOleWindow_Release(ow); + + hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IAccessible, (void**)&win); + ok(hr == S_OK, "got %x\n", hr); + IDispatch_Release(V_DISPATCH(&v)); + + hr = IAccessible_get_accRole(win, vid, &v); + todo_wine ok(hr == S_OK, "got %x\n", hr); + todo_wine ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v)); + todo_wine ok(V_I4(&v) == ROLE_SYSTEM_WINDOW, "V_I4(&v) = %d\n", V_I4(&v)); + IAccessible_Release(win); + + /* Child of a child, still works on parent HWND. */ + SetFocus(chld2); + hr = IAccessible_get_accFocus(acc, &v); + ok(hr == S_OK, "hr %#x\n", hr); + ok(V_VT(&v) == VT_DISPATCH, "V_VT(&v) = %d\n", V_VT(&v)); + ok(V_DISPATCH(&v) != NULL, "V_DISPATCH(&v) = %p\n", V_DISPATCH(&v)); + + hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IOleWindow, (void**)&ow); + ok(hr == S_OK, "got %x\n", hr); + hr = IOleWindow_GetWindow(ow, &hwnd2); + todo_wine ok(hr == S_OK, "got %x\n", hr); + todo_wine ok(chld2 == hwnd2, "hwnd2 = %p, expected %p\n", hwnd2, chld2); + IOleWindow_Release(ow); + + hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IAccessible, (void**)&win); + ok(hr == S_OK, "got %x\n", hr); + IDispatch_Release(V_DISPATCH(&v)); + + hr = IAccessible_get_accRole(win, vid, &v); + todo_wine ok(hr == S_OK, "got %x\n", hr); + todo_wine ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v)); + todo_wine ok(V_I4(&v) == ROLE_SYSTEM_WINDOW, "V_I4(&v) = %d\n", V_I4(&v)); + IAccessible_Release(win); + + ShowWindow(hwnd, SW_HIDE); + hr = IAccessible_QueryInterface(acc, &IID_IEnumVARIANT, (void**)&ev); ok(hr == S_OK, "got %x\n", hr);
@@ -1195,6 +1286,10 @@ static void test_default_client_accessible_object(void) ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v)); ok(V_I4(&v) == STATE_SYSTEM_INVISIBLE, "V_I4(&v) = %x\n", V_I4(&v));
+ hr = IAccessible_get_accFocus(acc, &v); + ok(hr == S_OK, "hr %#x\n", hr); + ok(V_VT(&v) == VT_EMPTY, "V_VT(&v) = %d\n", V_VT(&v)); + hr = IAccessible_accHitTest(acc, 200, 200, &v); ok(hr == S_OK, "got %x\n", hr); ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));