From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 65 ++++++++++++++++++++-- dlls/uiautomationcore/uia_provider.c | 39 +++++++++++++ 2 files changed, 100 insertions(+), 4 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index c735e7a0bd5..f3e4b89a120 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -59,6 +59,7 @@ DEFINE_EXPECT(winproc_GETOBJECT_CLIENT); DEFINE_EXPECT(Accessible_accNavigate); DEFINE_EXPECT(Accessible_get_accParent); DEFINE_EXPECT(Accessible_get_accRole); +DEFINE_EXPECT(Accessible_get_accState); DEFINE_EXPECT(Accessible_child_accNavigate); DEFINE_EXPECT(Accessible_child_get_accParent);
@@ -72,6 +73,14 @@ static BOOL check_variant_i4(VARIANT *v, int val) return FALSE; }
+static BOOL check_variant_bool(VARIANT *v, BOOL val) +{ + if (V_VT(v) == VT_BOOL && V_BOOL(v) == (val ? VARIANT_TRUE : VARIANT_FALSE)) + return TRUE; + + return FALSE; +} + static struct Accessible { IAccessible IAccessible_iface; @@ -82,6 +91,7 @@ static struct Accessible HWND acc_hwnd; HWND ow_hwnd; INT role; + INT state; } Accessible, Accessible_child;
static inline struct Accessible* impl_from_Accessible(IAccessible *iface) @@ -217,7 +227,18 @@ static HRESULT WINAPI Accessible_get_accRole(IAccessible *iface, VARIANT child_i static HRESULT WINAPI Accessible_get_accState(IAccessible *iface, VARIANT child_id, VARIANT *out_state) { - ok(0, "unexpected call\n"); + struct Accessible *This = impl_from_Accessible(iface); + + ok(This == &Accessible, "unexpected call\n"); + CHECK_EXPECT(Accessible_get_accState); + + if (This->state) + { + V_VT(out_state) = VT_I4; + V_I4(out_state) = This->state; + return S_OK; + } + return E_NOTIMPL; }
@@ -409,7 +430,7 @@ static struct Accessible Accessible = 1, NULL, 0, 0, - 0, + 0, 0, }; static struct Accessible Accessible_child = { @@ -418,7 +439,7 @@ static struct Accessible Accessible_child = 1, &Accessible.IAccessible_iface, 0, 0, - 0, + 0, 0, };
static LRESULT WINAPI test_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) @@ -749,12 +770,24 @@ static const struct msaa_role_uia_type msaa_role_uia_types[] = { { ROLE_SYSTEM_OUTLINEBUTTON, 0 }, };
+struct msaa_state_uia_prop { + INT acc_state; + INT prop_id; +}; + +static const struct msaa_state_uia_prop msaa_state_uia_props[] = { + { STATE_SYSTEM_FOCUSED, UIA_HasKeyboardFocusPropertyId }, + { STATE_SYSTEM_FOCUSABLE, UIA_IsKeyboardFocusablePropertyId }, + { ~STATE_SYSTEM_UNAVAILABLE, UIA_IsEnabledPropertyId }, + { STATE_SYSTEM_PROTECTED, UIA_IsPasswordPropertyId }, +}; + static void test_uia_prov_from_acc_properties(void) { IRawElementProviderSimple *elprov; HRESULT hr; VARIANT v; - int i; + int i, x;
/* MSAA role to UIA control type test. */ for (i = 0; i < ARRAY_SIZE(msaa_role_uia_types); i++) @@ -822,6 +855,30 @@ static void test_uia_prov_from_acc_properties(void) Accessible.role = 0; IRawElementProviderSimple_Release(elprov); ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref); + + 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); + + /* UIA PropertyId's that correspond directly to individual MSAA state flags. */ + for (i = 0; i < ARRAY_SIZE(msaa_state_uia_props); i++) + { + const struct msaa_state_uia_prop *state = &msaa_state_uia_props[i]; + + for (x = 0; x < 2; x++) + { + Accessible.state = x ? state->acc_state : ~state->acc_state; + SET_EXPECT(Accessible_get_accState); + hr = IRawElementProviderSimple_GetPropertyValue(elprov, state->prop_id, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(check_variant_bool(&v, x), "V_BOOL(&v) = %#x\n", V_BOOL(&v)); + CHECK_CALLED(Accessible_get_accState); + } + } + Accessible.state = 0; + + IRawElementProviderSimple_Release(elprov); + ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref); }
static void test_UiaProviderFromIAccessible(void) diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c index ab2b8305b10..dae0187596d 100644 --- a/dlls/uiautomationcore/uia_provider.c +++ b/dlls/uiautomationcore/uia_provider.c @@ -32,6 +32,25 @@ static void variant_init_i4(VARIANT *v, int val) V_I4(v) = val; }
+static void variant_init_bool(VARIANT *v, BOOL val) +{ + V_VT(v) = VT_BOOL; + V_BOOL(v) = val ? VARIANT_TRUE : VARIANT_FALSE; +} + +static BOOL msaa_check_acc_state(IAccessible *acc, VARIANT cid, ULONG flag) +{ + HRESULT hr; + VARIANT v; + + VariantInit(&v); + hr = IAccessible_get_accState(acc, cid, &v); + if (SUCCEEDED(hr) && V_VT(&v) == VT_I4 && (V_I4(&v) & flag)) + return TRUE; + + return FALSE; +} + static LONG msaa_role_to_uia_control_type(LONG role) { switch (role) @@ -214,6 +233,26 @@ HRESULT WINAPI msaa_provider_GetPropertyValue(IRawElementProviderSimple *iface,
break;
+ case UIA_HasKeyboardFocusPropertyId: + variant_init_bool(ret_val, msaa_check_acc_state(msaa_prov->acc, msaa_prov->cid, + STATE_SYSTEM_FOCUSED)); + break; + + case UIA_IsKeyboardFocusablePropertyId: + variant_init_bool(ret_val, msaa_check_acc_state(msaa_prov->acc, msaa_prov->cid, + STATE_SYSTEM_FOCUSABLE)); + break; + + case UIA_IsEnabledPropertyId: + variant_init_bool(ret_val, !msaa_check_acc_state(msaa_prov->acc, msaa_prov->cid, + STATE_SYSTEM_UNAVAILABLE)); + break; + + case UIA_IsPasswordPropertyId: + variant_init_bool(ret_val, msaa_check_acc_state(msaa_prov->acc, msaa_prov->cid, + STATE_SYSTEM_PROTECTED)); + break; + default: FIXME("Unimplemented propertyId %d\n", prop_id); break;