From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 119 +++++++++++++++++++++ dlls/uiautomationcore/uia_provider.c | 39 +++++++ 2 files changed, 158 insertions(+)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index ce3ee303fd1..ee0eb312642 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -3382,7 +3382,10 @@ static void test_uia_prov_from_acc_navigation(void)
static void test_uia_prov_from_acc_properties(void) { + BOOL is_win10_1809_or_above = FALSE; IRawElementProviderSimple *elprov; + RECT rect[2] = { 0 }; + HWND hwnd, hwnd2; HRESULT hr; VARIANT v; int i, x; @@ -3441,6 +3444,8 @@ static void test_uia_prov_from_acc_properties(void) ok(check_variant_i4(&v, UIA_ButtonControlTypeId) || broken(V_VT(&v) == VT_EMPTY), /* Windows < 10 1809 */ "MSAA role %d: V_I4(&v) = %ld\n", Accessible.role, V_I4(&v)); CHECK_CALLED(Accessible_get_accRole); + if (V_VT(&v) == VT_I4) + is_win10_1809_or_above = TRUE;
if (V_VT(&v) == VT_EMPTY) SET_EXPECT(Accessible_get_accRole); @@ -3506,6 +3511,120 @@ static void test_uia_prov_from_acc_properties(void)
IRawElementProviderSimple_Release(elprov); ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref); + + /* + * UIA_IsOffscreenPropertyId relies upon either STATE_SYSTEM_OFFSCREEN + * being set, or accLocation returning a location that is within the + * client area bounding box of the HWND it is contained within. + */ + hwnd = CreateWindowA("UiaProviderFromIAccessible class", "Test window 2", WS_OVERLAPPEDWINDOW, + 0, 0, 100, 100, NULL, NULL, NULL, NULL); + + hwnd2 = Accessible.ow_hwnd; + Accessible.ow_hwnd = hwnd; + hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref); + + set_accessible_props(&Accessible, 0, STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", 0, 0, 0, 0); + SET_EXPECT(Accessible_get_accState); + hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v)); + ok(check_variant_bool(&v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(&v)); + CHECK_CALLED(Accessible_get_accState); + + /* accLocation fails, will return FALSE. */ + set_accessible_props(&Accessible, 0, ~STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", 0, 0, 0, 0); + SET_EXPECT(Accessible_get_accState); + SET_EXPECT(Accessible_accLocation); + hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v)); + ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v)); + CHECK_CALLED(Accessible_get_accState); + CHECK_CALLED(Accessible_accLocation); + + /* Window is visible, Accessible is within its bounds. */ + ShowWindow(Accessible.ow_hwnd, SW_SHOW); + ok(GetClientRect(Accessible.ow_hwnd, &rect[0]), "GetClientRect returned FALSE\n"); + MapWindowPoints(Accessible.ow_hwnd, NULL, (POINT *)&rect[0], 2); + + set_accessible_props(&Accessible, 0, ~STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", rect[0].left, rect[0].top, + (rect[0].right - rect[0].left), (rect[0].bottom - rect[0].top)); + SET_EXPECT(Accessible_get_accState); + SET_EXPECT(Accessible_accLocation); + hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v)); + ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v)); + CHECK_CALLED(Accessible_get_accState); + CHECK_CALLED(Accessible_accLocation); + + /* + * Window is invisible, Accessible is within its bounds. Window visibility + * doesn't effect whether or not an IAccessible is considered offscreen. + */ + ShowWindow(Accessible.ow_hwnd, SW_HIDE); + set_accessible_props(&Accessible, 0, ~STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", rect[0].left, rect[0].top, + (rect[0].right - rect[0].left), (rect[0].bottom - rect[0].top)); + SET_EXPECT(Accessible_get_accState); + SET_EXPECT(Accessible_accLocation); + hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v)); + ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v)); + CHECK_CALLED(Accessible_get_accState); + CHECK_CALLED(Accessible_accLocation); + + /* Accessible now outside of its window's bounds. */ + set_accessible_props(&Accessible, 0, ~STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", rect[0].right, rect[0].bottom, + 10, 10); + SET_EXPECT(Accessible_get_accState); + SET_EXPECT(Accessible_accLocation); + hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v)); + ok(check_variant_bool(&v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(&v)); + CHECK_CALLED(Accessible_get_accState); + CHECK_CALLED(Accessible_accLocation); + + /* Accessible within window bounds, but not client area bounds. */ + ok(GetWindowRect(Accessible.ow_hwnd, &rect[1]), "GetClientRect returned FALSE\n"); + set_accessible_props(&Accessible, 0, ~STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", rect[1].left, rect[1].top, + rect[0].left - 1, rect[0].top - 1); + + SET_EXPECT(Accessible_get_accState); + SET_EXPECT(Accessible_accLocation); + hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v)); + ok(check_variant_bool(&v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(&v)); + CHECK_CALLED(Accessible_get_accState); + CHECK_CALLED(Accessible_accLocation); + + /* Accessible within window bounds, but window is now destroyed. */ + DestroyWindow(hwnd); + set_accessible_props(&Accessible, 0, ~STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", rect[1].left, rect[1].top, + rect[1].right, rect[1].bottom); + + VariantClear(&v); + SET_EXPECT(Accessible_get_accState); + SET_EXPECT(Accessible_accLocation); + hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v)); + ok(check_variant_bool(&v, TRUE) || /* Win10v1809 32-bit returns FALSE here for some reason. */ + broken(is_win10_1809_or_above && (sizeof(void *) == 4) && check_variant_bool(&v, FALSE)), + "Unexpected BOOL %#x\n", V_BOOL(&v)); + CHECK_CALLED(Accessible_get_accState); + CHECK_CALLED(Accessible_accLocation); + + IRawElementProviderSimple_Release(elprov); + ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref); + + DestroyWindow(hwnd); + Accessible.ow_hwnd = hwnd2; }
static void test_UiaProviderFromIAccessible(void) diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c index a7d41248abc..119a7e69abc 100644 --- a/dlls/uiautomationcore/uia_provider.c +++ b/dlls/uiautomationcore/uia_provider.c @@ -676,6 +676,45 @@ HRESULT WINAPI msaa_provider_GetPropertyValue(IRawElementProviderSimple *iface, break; }
+ case UIA_IsOffscreenPropertyId: + { + RECT rect[2] = { 0 }; + RECT intersect_rect; + LONG width, height; + + variant_init_bool(ret_val, FALSE); + if (msaa_check_acc_state(msaa_prov->acc, msaa_prov->cid, STATE_SYSTEM_OFFSCREEN)) + { + variant_init_bool(ret_val, TRUE); + break; + } + + hr = IAccessible_accLocation(msaa_prov->acc, &rect[0].left, &rect[0].top, &width, &height, msaa_prov->cid); + if (FAILED(hr)) + break; + + rect[0].right = rect[0].left + width; + rect[0].bottom = rect[0].top + height; + SetLastError(NOERROR); + if (!GetClientRect(msaa_prov->hwnd, &rect[1])) + { + if (GetLastError() == ERROR_INVALID_WINDOW_HANDLE) + variant_init_bool(ret_val, TRUE); + break; + } + + SetLastError(NOERROR); + if (!MapWindowPoints(msaa_prov->hwnd, NULL, (POINT *)&rect[1], 2) && GetLastError()) + { + if (GetLastError() == ERROR_INVALID_WINDOW_HANDLE) + variant_init_bool(ret_val, TRUE); + break; + } + + variant_init_bool(ret_val, !IntersectRect(&intersect_rect, &rect[0], &rect[1])); + break; + } + default: FIXME("Unimplemented propertyId %d\n", prop_id); break;
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 189 +++++++++++++++++++++ dlls/uiautomationcore/uia_client.c | 10 ++ dlls/uiautomationcore/uia_ids.c | 4 +- dlls/uiautomationcore/uia_private.h | 6 + dlls/uiautomationcore/uia_provider.c | 6 - 5 files changed, 208 insertions(+), 7 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index ee0eb312642..969ddec644e 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -1115,6 +1115,12 @@ struct Provider_value_pattern_data BOOL is_read_only; };
+struct Provider_legacy_accessible_pattern_data +{ + BOOL is_supported; + int child_id; +}; + static struct Provider { IRawElementProviderSimple IRawElementProviderSimple_iface; @@ -1122,6 +1128,7 @@ static struct Provider IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot_iface; IRawElementProviderHwndOverride IRawElementProviderHwndOverride_iface; IValueProvider IValueProvider_iface; + ILegacyIAccessibleProvider ILegacyIAccessibleProvider_iface; LONG ref;
const char *prov_name; @@ -1143,6 +1150,7 @@ static struct Provider int prop_override_count; struct UiaRect bounds_rect; struct Provider_value_pattern_data value_pattern_data; + struct Provider_legacy_accessible_pattern_data legacy_acc_pattern_data; } Provider, Provider2, Provider_child, Provider_child2; static struct Provider Provider_hwnd, Provider_nc, Provider_proxy, Provider_proxy2, Provider_override; static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd, BOOL initialize_nav_links); @@ -1571,6 +1579,8 @@ HRESULT WINAPI ProviderSimple_QueryInterface(IRawElementProviderSimple *iface, R *ppv = &This->IRawElementProviderHwndOverride_iface; else if (IsEqualIID(riid, &IID_IValueProvider)) *ppv = &This->IValueProvider_iface; + else if (IsEqualIID(riid, &IID_ILegacyIAccessibleProvider)) + *ppv = &This->ILegacyIAccessibleProvider_iface; else return E_NOINTERFACE;
@@ -1628,6 +1638,11 @@ HRESULT WINAPI ProviderSimple_GetPatternProvider(IRawElementProviderSimple *ifac *ret_val = (IUnknown *)iface; break;
+ case UIA_LegacyIAccessiblePatternId: + if (This->legacy_acc_pattern_data.is_supported) + *ret_val = (IUnknown *)iface; + break; + default: break; } @@ -2176,6 +2191,141 @@ static const IValueProviderVtbl ProviderValuePatternVtbl = { ProviderValuePattern_get_IsReadOnly, };
+static inline struct Provider *impl_from_ProviderLegacyIAccessiblePattern(ILegacyIAccessibleProvider *iface) +{ + return CONTAINING_RECORD(iface, struct Provider, ILegacyIAccessibleProvider_iface); +} + +static HRESULT WINAPI ProviderLegacyIAccessiblePattern_QueryInterface(ILegacyIAccessibleProvider *iface, REFIID riid, + void **ppv) +{ + struct Provider *Provider = impl_from_ProviderLegacyIAccessiblePattern(iface); + return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv); +} + +static ULONG WINAPI ProviderLegacyIAccessiblePattern_AddRef(ILegacyIAccessibleProvider *iface) +{ + struct Provider *Provider = impl_from_ProviderLegacyIAccessiblePattern(iface); + return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface); +} + +static ULONG WINAPI ProviderLegacyIAccessiblePattern_Release(ILegacyIAccessibleProvider *iface) +{ + struct Provider *Provider = impl_from_ProviderLegacyIAccessiblePattern(iface); + return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface); +} + +static HRESULT WINAPI ProviderLegacyIAccessiblePattern_Select(ILegacyIAccessibleProvider *iface, LONG select_flags) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProviderLegacyIAccessiblePattern_DoDefaultAction(ILegacyIAccessibleProvider *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProviderLegacyIAccessiblePattern_SetValue(ILegacyIAccessibleProvider *iface, LPCWSTR val) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProviderLegacyIAccessiblePattern_GetIAccessible(ILegacyIAccessibleProvider *iface, + IAccessible **out_acc) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_ChildId(ILegacyIAccessibleProvider *iface, int *out_cid) +{ + struct Provider *Provider = impl_from_ProviderLegacyIAccessiblePattern(iface); + + *out_cid = Provider->legacy_acc_pattern_data.child_id; + return S_OK; +} + +static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Name(ILegacyIAccessibleProvider *iface, BSTR *out_name) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Value(ILegacyIAccessibleProvider *iface, BSTR *out_value) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Description(ILegacyIAccessibleProvider *iface, + BSTR *out_description) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Role(ILegacyIAccessibleProvider *iface, DWORD *out_role) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_State(ILegacyIAccessibleProvider *iface, DWORD *out_state) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Help(ILegacyIAccessibleProvider *iface, BSTR *out_help) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_KeyboardShortcut(ILegacyIAccessibleProvider *iface, + BSTR *out_kbd_shortcut) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProviderLegacyIAccessiblePattern_GetSelection(ILegacyIAccessibleProvider *iface, + SAFEARRAY **out_selected) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_DefaultAction(ILegacyIAccessibleProvider *iface, + BSTR *out_default_action) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const ILegacyIAccessibleProviderVtbl ProviderLegacyIAccessiblePatternVtbl = { + ProviderLegacyIAccessiblePattern_QueryInterface, + ProviderLegacyIAccessiblePattern_AddRef, + ProviderLegacyIAccessiblePattern_Release, + ProviderLegacyIAccessiblePattern_Select, + ProviderLegacyIAccessiblePattern_DoDefaultAction, + ProviderLegacyIAccessiblePattern_SetValue, + ProviderLegacyIAccessiblePattern_GetIAccessible, + ProviderLegacyIAccessiblePattern_get_ChildId, + ProviderLegacyIAccessiblePattern_get_Name, + ProviderLegacyIAccessiblePattern_get_Value, + ProviderLegacyIAccessiblePattern_get_Description, + ProviderLegacyIAccessiblePattern_get_Role, + ProviderLegacyIAccessiblePattern_get_State, + ProviderLegacyIAccessiblePattern_get_Help, + ProviderLegacyIAccessiblePattern_get_KeyboardShortcut, + ProviderLegacyIAccessiblePattern_GetSelection, + ProviderLegacyIAccessiblePattern_get_DefaultAction, +}; + static struct Provider Provider = { { &ProviderSimpleVtbl }, @@ -2183,6 +2333,7 @@ static struct Provider Provider = { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, { &ProviderValuePatternVtbl }, + { &ProviderLegacyIAccessiblePatternVtbl }, 1, "Provider", NULL, NULL, @@ -2198,6 +2349,7 @@ static struct Provider Provider2 = { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, { &ProviderValuePatternVtbl }, + { &ProviderLegacyIAccessiblePatternVtbl }, 1, "Provider2", NULL, NULL, @@ -2213,6 +2365,7 @@ static struct Provider Provider_child = { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, { &ProviderValuePatternVtbl }, + { &ProviderLegacyIAccessiblePatternVtbl }, 1, "Provider_child", &Provider.IRawElementProviderFragment_iface, &Provider.IRawElementProviderFragmentRoot_iface, @@ -2228,6 +2381,7 @@ static struct Provider Provider_child2 = { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, { &ProviderValuePatternVtbl }, + { &ProviderLegacyIAccessiblePatternVtbl }, 1, "Provider_child2", &Provider.IRawElementProviderFragment_iface, &Provider.IRawElementProviderFragmentRoot_iface, @@ -2243,6 +2397,7 @@ static struct Provider Provider_hwnd = { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, { &ProviderValuePatternVtbl }, + { &ProviderLegacyIAccessiblePatternVtbl }, 1, "Provider_hwnd", NULL, NULL, @@ -2258,6 +2413,7 @@ static struct Provider Provider_nc = { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, { &ProviderValuePatternVtbl }, + { &ProviderLegacyIAccessiblePatternVtbl }, 1, "Provider_nc", NULL, NULL, @@ -2274,6 +2430,7 @@ static struct Provider Provider_proxy = { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, { &ProviderValuePatternVtbl }, + { &ProviderLegacyIAccessiblePatternVtbl }, 1, "Provider_proxy", NULL, NULL, @@ -2290,6 +2447,7 @@ static struct Provider Provider_proxy2 = { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, { &ProviderValuePatternVtbl }, + { &ProviderLegacyIAccessiblePatternVtbl }, 1, "Provider_proxy2", NULL, NULL, @@ -2306,6 +2464,7 @@ static struct Provider Provider_override = { &ProviderFragmentRootVtbl }, { &ProviderHwndOverrideVtbl }, { &ProviderValuePatternVtbl }, + { &ProviderLegacyIAccessiblePatternVtbl }, 1, "Provider_override", NULL, NULL, @@ -2323,6 +2482,7 @@ static struct Provider Provider_override = { &ProviderFragmentRootVtbl }, \ { &ProviderHwndOverrideVtbl }, \ { &ProviderValuePatternVtbl }, \ + { &ProviderLegacyIAccessiblePatternVtbl }, \ 1, \ "Provider_" # name "", \ NULL, NULL, \ @@ -5101,6 +5261,12 @@ static const struct prov_method_sequence get_pattern_prop_seq[] = { { 0 } };
+static const struct prov_method_sequence get_pattern_prop_seq2[] = { + { &Provider, PROV_GET_PATTERN_PROV }, + { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_TODO }, + { 0 } +}; + static const struct prov_method_sequence get_bounding_rect_seq[] = { NODE_CREATE_SEQ(&Provider_child), { &Provider_child, FRAG_GET_BOUNDING_RECT }, @@ -5556,6 +5722,28 @@ static void test_UiaGetPropertyValue(void) VariantClear(&v); }
+ /* ILegacyIAccessibleProvider pattern property IDs. */ + Provider.legacy_acc_pattern_data.is_supported = FALSE; + hr = UiaGetPropertyValue(node, UIA_LegacyIAccessibleChildIdPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v)); + ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v)); + ok_method_sequence(get_pattern_prop_seq2, NULL); + VariantClear(&v); + + Provider.legacy_acc_pattern_data.is_supported = TRUE; + for (i = 0; i < 2; i++) + { + Provider.legacy_acc_pattern_data.child_id = i; + + hr = UiaGetPropertyValue(node, UIA_LegacyIAccessibleChildIdPropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v)); + ok(V_I4(&v) == i, "Unexpected I4 %#lx\n", V_I4(&v)); + ok_method_sequence(get_pattern_prop_seq, NULL); + VariantClear(&v); + } + ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n"); ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref); initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE); @@ -9049,6 +9237,7 @@ static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd, prov->prop_override_count = 0; memset(&prov->bounds_rect, 0, sizeof(prov->bounds_rect)); memset(&prov->value_pattern_data, 0, sizeof(prov->value_pattern_data)); + memset(&prov->legacy_acc_pattern_data, 0, sizeof(prov->legacy_acc_pattern_data)); if (initialize_nav_links) { prov->frag_root = NULL; diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index dae78ea8ff4..95287179f92 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -1571,6 +1571,16 @@ static HRESULT uia_provider_get_pattern_prop_val(struct uia_provider *prov, break; }
+ case UIA_LegacyIAccessibleChildIdPropertyId: + { + int val; + + hr = ILegacyIAccessibleProvider_get_ChildId((ILegacyIAccessibleProvider *)pattern_prov, &val); + if (SUCCEEDED(hr)) + variant_init_i4(ret_val, val); + break; + } + default: break; } diff --git a/dlls/uiautomationcore/uia_ids.c b/dlls/uiautomationcore/uia_ids.c index d518b2dd44f..62f26de0982 100644 --- a/dlls/uiautomationcore/uia_ids.c +++ b/dlls/uiautomationcore/uia_ids.c @@ -152,7 +152,9 @@ static const struct uia_prop_info default_uia_properties[] = { { &RangeValue_SmallChange_Property_GUID, UIA_RangeValueSmallChangePropertyId, }, { &IsTextEditPatternAvailable_Property_GUID, UIA_IsTextEditPatternAvailablePropertyId, }, { &GridItem_Column_Property_GUID, UIA_GridItemColumnPropertyId, }, - { &LegacyIAccessible_ChildId_Property_GUID, UIA_LegacyIAccessibleChildIdPropertyId, }, + { &LegacyIAccessible_ChildId_Property_GUID, UIA_LegacyIAccessibleChildIdPropertyId, + PROP_TYPE_PATTERN_PROP, UIAutomationType_Int, + UIA_LegacyIAccessiblePatternId, }, { &Annotation_DateTime_Property_GUID, UIA_AnnotationDateTimePropertyId, }, { &IsTablePatternAvailable_Property_GUID, UIA_IsTablePatternAvailablePropertyId, }, { &SelectionItem_IsSelected_Property_GUID, UIA_SelectionItemIsSelectedPropertyId, }, diff --git a/dlls/uiautomationcore/uia_private.h b/dlls/uiautomationcore/uia_private.h index f7e991ee4fd..63c6f7dde22 100644 --- a/dlls/uiautomationcore/uia_private.h +++ b/dlls/uiautomationcore/uia_private.h @@ -99,6 +99,12 @@ static inline void variant_init_bool(VARIANT *v, BOOL val) V_BOOL(v) = val ? VARIANT_TRUE : VARIANT_FALSE; }
+static inline void variant_init_i4(VARIANT *v, int val) +{ + V_VT(v) = VT_I4; + V_I4(v) = val; +} + static inline BOOL uia_array_reserve(void **elements, SIZE_T *capacity, SIZE_T count, SIZE_T size) { SIZE_T max_capacity, new_capacity; diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c index 119a7e69abc..a950df599d8 100644 --- a/dlls/uiautomationcore/uia_provider.c +++ b/dlls/uiautomationcore/uia_provider.c @@ -28,12 +28,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(uiautomation);
DEFINE_GUID(SID_AccFromDAWrapper, 0x33f139ee, 0xe509, 0x47f7, 0xbf,0x39, 0x83,0x76,0x44,0xf7,0x45,0x76);
-static void variant_init_i4(VARIANT *v, int val) -{ - V_VT(v) = VT_I4; - V_I4(v) = val; -} - static BOOL msaa_check_acc_state(IAccessible *acc, VARIANT cid, ULONG flag) { HRESULT hr;
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 19 +++++++++++++++++-- dlls/uiautomationcore/uia_client.c | 10 ++++++++++ dlls/uiautomationcore/uia_ids.c | 4 +++- 3 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 969ddec644e..c13fa835fb6 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -1119,6 +1119,7 @@ struct Provider_legacy_accessible_pattern_data { BOOL is_supported; int child_id; + DWORD role; };
static struct Provider @@ -2269,8 +2270,10 @@ static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Description(ILegacyIA
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Role(ILegacyIAccessibleProvider *iface, DWORD *out_role) { - ok(0, "unexpected call\n"); - return E_NOTIMPL; + struct Provider *Provider = impl_from_ProviderLegacyIAccessiblePattern(iface); + + *out_role = Provider->legacy_acc_pattern_data.role; + return S_OK; }
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_State(ILegacyIAccessibleProvider *iface, DWORD *out_state) @@ -5744,6 +5747,18 @@ static void test_UiaGetPropertyValue(void) VariantClear(&v); }
+ for (i = 0; i < 2; i++) + { + Provider.legacy_acc_pattern_data.role = i; + + hr = UiaGetPropertyValue(node, UIA_LegacyIAccessibleRolePropertyId, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v)); + ok(V_I4(&v) == i, "Unexpected I4 %#lx\n", V_I4(&v)); + ok_method_sequence(get_pattern_prop_seq, NULL); + VariantClear(&v); + } + ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n"); ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref); initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE); diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 95287179f92..92ff41e2c71 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -1581,6 +1581,16 @@ static HRESULT uia_provider_get_pattern_prop_val(struct uia_provider *prov, break; }
+ case UIA_LegacyIAccessibleRolePropertyId: + { + DWORD val; + + hr = ILegacyIAccessibleProvider_get_Role((ILegacyIAccessibleProvider *)pattern_prov, &val); + if (SUCCEEDED(hr)) + variant_init_i4(ret_val, val); + break; + } + default: break; } diff --git a/dlls/uiautomationcore/uia_ids.c b/dlls/uiautomationcore/uia_ids.c index 62f26de0982..d23ba14c333 100644 --- a/dlls/uiautomationcore/uia_ids.c +++ b/dlls/uiautomationcore/uia_ids.c @@ -219,7 +219,9 @@ static const struct uia_prop_info default_uia_properties[] = { { &IsDialog_Property_GUID, UIA_IsDialogPropertyId, PROP_TYPE_ELEM_PROP, UIAutomationType_Bool, }, { &IsTextPatternAvailable_Property_GUID, UIA_IsTextPatternAvailablePropertyId, }, - { &LegacyIAccessible_Role_Property_GUID, UIA_LegacyIAccessibleRolePropertyId, }, + { &LegacyIAccessible_Role_Property_GUID, UIA_LegacyIAccessibleRolePropertyId, + PROP_TYPE_PATTERN_PROP, UIAutomationType_Int, + UIA_LegacyIAccessiblePatternId, }, { &Selection2_ItemCount_Property_GUID, UIA_Selection2ItemCountPropertyId, }, { &TableItem_RowHeaderItems_Property_GUID, UIA_TableItemRowHeaderItemsPropertyId, }, { &Styles_ExtendedProperties_Property_GUID, UIA_StylesExtendedPropertiesPropertyId, },
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 19 +++++++++++++++++++ dlls/uiautomationcore/uia_provider.c | 15 +++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index c13fa835fb6..5857f313b89 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -3558,6 +3558,9 @@ static void test_uia_prov_from_acc_properties(void) for (i = 0; i < ARRAY_SIZE(msaa_role_uia_types); i++) { const struct msaa_role_uia_type *role = &msaa_role_uia_types[i]; + ILegacyIAccessibleProvider *accprov; + DWORD role_val; + IUnknown *unk;
/* * Roles get cached once a valid one is mapped, so create a new @@ -3590,6 +3593,22 @@ static void test_uia_prov_from_acc_properties(void) if (!role->uia_control_type) CHECK_CALLED(Accessible_get_accRole);
+ hr = IRawElementProviderSimple_GetPatternProvider(elprov, UIA_LegacyIAccessiblePatternId, &unk); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!unk, "unk == NULL\n"); + + hr = IUnknown_QueryInterface(unk, &IID_ILegacyIAccessibleProvider, (void **)&accprov); + IUnknown_Release(unk); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!accprov, "accprov == NULL\n"); + + SET_EXPECT(Accessible_get_accRole); + hr = ILegacyIAccessibleProvider_get_Role(accprov, &role_val); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(role_val == Accessible.role, "role_val != Accessible.role\n"); + CHECK_CALLED(Accessible_get_accRole); + + ILegacyIAccessibleProvider_Release(accprov); IRawElementProviderSimple_Release(elprov); ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref); } diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c index a950df599d8..59be5d3782a 100644 --- a/dlls/uiautomationcore/uia_provider.c +++ b/dlls/uiautomationcore/uia_provider.c @@ -1066,8 +1066,19 @@ static HRESULT WINAPI msaa_acc_provider_get_Description(ILegacyIAccessibleProvid
static HRESULT WINAPI msaa_acc_provider_get_Role(ILegacyIAccessibleProvider *iface, DWORD *out_role) { - FIXME("%p, %p: stub!\n", iface, out_role); - return E_NOTIMPL; + struct msaa_provider *msaa_prov = impl_from_msaa_acc_provider(iface); + HRESULT hr; + VARIANT v; + + TRACE("%p, %p\n", iface, out_role); + + *out_role = 0; + VariantInit(&v); + hr = IAccessible_get_accRole(msaa_prov->acc, msaa_prov->cid, &v); + if (SUCCEEDED(hr) && V_VT(&v) == VT_I4) + *out_role = V_I4(&v); + + return S_OK; }
static HRESULT WINAPI msaa_acc_provider_get_State(ILegacyIAccessibleProvider *iface, DWORD *out_state)
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=131150
Your paranoid android.
=== debian11 (32 bit report) ===
mshtml: script.c:932: Test failed: L"/index.html?xhr.js: [iframes 2] unexpected order: 0,1,echo,sync_xhr(pre-send),sync_xhr(DONE),sync_xhr,blank(DONE)"
Esme Povirk (@madewokherd) commented about dlls/uiautomationcore/tests/uiautomation.c:
- VariantClear(&v);
- SET_EXPECT(Accessible_get_accState);
- SET_EXPECT(Accessible_accLocation);
- hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
- ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v));
- ok(check_variant_bool(&v, TRUE) || /* Win10v1809 32-bit returns FALSE here for some reason. */
broken(is_win10_1809_or_above && (sizeof(void *) == 4) && check_variant_bool(&v, FALSE)),
"Unexpected BOOL %#x\n", V_BOOL(&v));
- CHECK_CALLED(Accessible_get_accState);
- CHECK_CALLED(Accessible_accLocation);
- IRawElementProviderSimple_Release(elprov);
- ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
- DestroyWindow(hwnd);
This is a double-free of hwnd. I also don't think the test for a destroyed window is necessary. Nothing can be expected to work in that situation.