2 * Copyright 2022 Connor McAdams for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "uiautomation.h"
24 #include "wine/debug.h"
25 #include "wine/heap.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(uiautomation
);
29 static void variant_init_i4(VARIANT
*v
, int val
)
35 static void variant_init_bool(VARIANT
*v
, BOOL val
)
38 V_BOOL(v
) = val
? VARIANT_TRUE
: VARIANT_FALSE
;
41 static BOOL
msaa_check_acc_state(IAccessible
*acc
, VARIANT cid
, ULONG flag
)
47 hr
= IAccessible_get_accState(acc
, cid
, &v
);
48 if (SUCCEEDED(hr
) && V_VT(&v
) == VT_I4
&& (V_I4(&v
) & flag
))
54 static LONG
msaa_role_to_uia_control_type(LONG role
)
58 case ROLE_SYSTEM_TITLEBAR
: return UIA_TitleBarControlTypeId
;
59 case ROLE_SYSTEM_MENUBAR
: return UIA_MenuBarControlTypeId
;
60 case ROLE_SYSTEM_SCROLLBAR
: return UIA_ScrollBarControlTypeId
;
61 case ROLE_SYSTEM_INDICATOR
:
62 case ROLE_SYSTEM_GRIP
: return UIA_ThumbControlTypeId
;
63 case ROLE_SYSTEM_APPLICATION
:
64 case ROLE_SYSTEM_WINDOW
: return UIA_WindowControlTypeId
;
65 case ROLE_SYSTEM_MENUPOPUP
: return UIA_MenuControlTypeId
;
66 case ROLE_SYSTEM_TOOLTIP
: return UIA_ToolTipControlTypeId
;
67 case ROLE_SYSTEM_DOCUMENT
: return UIA_DocumentControlTypeId
;
68 case ROLE_SYSTEM_PANE
: return UIA_PaneControlTypeId
;
69 case ROLE_SYSTEM_GROUPING
: return UIA_GroupControlTypeId
;
70 case ROLE_SYSTEM_SEPARATOR
: return UIA_SeparatorControlTypeId
;
71 case ROLE_SYSTEM_TOOLBAR
: return UIA_ToolBarControlTypeId
;
72 case ROLE_SYSTEM_STATUSBAR
: return UIA_StatusBarControlTypeId
;
73 case ROLE_SYSTEM_TABLE
: return UIA_TableControlTypeId
;
74 case ROLE_SYSTEM_COLUMNHEADER
:
75 case ROLE_SYSTEM_ROWHEADER
: return UIA_HeaderControlTypeId
;
76 case ROLE_SYSTEM_CELL
: return UIA_DataItemControlTypeId
;
77 case ROLE_SYSTEM_LINK
: return UIA_HyperlinkControlTypeId
;
78 case ROLE_SYSTEM_LIST
: return UIA_ListControlTypeId
;
79 case ROLE_SYSTEM_LISTITEM
: return UIA_ListItemControlTypeId
;
80 case ROLE_SYSTEM_OUTLINE
: return UIA_TreeControlTypeId
;
81 case ROLE_SYSTEM_OUTLINEITEM
: return UIA_TreeItemControlTypeId
;
82 case ROLE_SYSTEM_PAGETAB
: return UIA_TabItemControlTypeId
;
83 case ROLE_SYSTEM_GRAPHIC
: return UIA_ImageControlTypeId
;
84 case ROLE_SYSTEM_STATICTEXT
: return UIA_TextControlTypeId
;
85 case ROLE_SYSTEM_TEXT
: return UIA_EditControlTypeId
;
86 case ROLE_SYSTEM_CLOCK
:
87 case ROLE_SYSTEM_BUTTONDROPDOWNGRID
:
88 case ROLE_SYSTEM_PUSHBUTTON
: return UIA_ButtonControlTypeId
;
89 case ROLE_SYSTEM_CHECKBUTTON
: return UIA_CheckBoxControlTypeId
;
90 case ROLE_SYSTEM_RADIOBUTTON
: return UIA_RadioButtonControlTypeId
;
91 case ROLE_SYSTEM_COMBOBOX
: return UIA_ComboBoxControlTypeId
;
92 case ROLE_SYSTEM_PROGRESSBAR
: return UIA_ProgressBarControlTypeId
;
93 case ROLE_SYSTEM_SLIDER
: return UIA_SliderControlTypeId
;
94 case ROLE_SYSTEM_SPINBUTTON
: return UIA_SpinnerControlTypeId
;
95 case ROLE_SYSTEM_BUTTONMENU
:
96 case ROLE_SYSTEM_MENUITEM
: return UIA_MenuItemControlTypeId
;
97 case ROLE_SYSTEM_PAGETABLIST
: return UIA_TabControlTypeId
;
98 case ROLE_SYSTEM_BUTTONDROPDOWN
:
99 case ROLE_SYSTEM_SPLITBUTTON
: return UIA_SplitButtonControlTypeId
;
100 case ROLE_SYSTEM_SOUND
:
101 case ROLE_SYSTEM_CURSOR
:
102 case ROLE_SYSTEM_CARET
:
103 case ROLE_SYSTEM_ALERT
:
104 case ROLE_SYSTEM_CLIENT
:
105 case ROLE_SYSTEM_CHART
:
106 case ROLE_SYSTEM_DIALOG
:
107 case ROLE_SYSTEM_BORDER
:
108 case ROLE_SYSTEM_COLUMN
:
109 case ROLE_SYSTEM_ROW
:
110 case ROLE_SYSTEM_HELPBALLOON
:
111 case ROLE_SYSTEM_CHARACTER
:
112 case ROLE_SYSTEM_PROPERTYPAGE
:
113 case ROLE_SYSTEM_DROPLIST
:
114 case ROLE_SYSTEM_DIAL
:
115 case ROLE_SYSTEM_HOTKEYFIELD
:
116 case ROLE_SYSTEM_DIAGRAM
:
117 case ROLE_SYSTEM_ANIMATION
:
118 case ROLE_SYSTEM_EQUATION
:
119 case ROLE_SYSTEM_WHITESPACE
:
120 case ROLE_SYSTEM_IPADDRESS
:
121 case ROLE_SYSTEM_OUTLINEBUTTON
:
122 WARN("No UIA control type mapping for MSAA role %ld\n", role
);
126 FIXME("UIA control type mapping unimplemented for MSAA role %ld\n", role
);
134 * UiaProviderFromIAccessible IRawElementProviderSimple interface.
136 struct msaa_provider
{
137 IRawElementProviderSimple IRawElementProviderSimple_iface
;
146 static inline struct msaa_provider
*impl_from_msaa_provider(IRawElementProviderSimple
*iface
)
148 return CONTAINING_RECORD(iface
, struct msaa_provider
, IRawElementProviderSimple_iface
);
151 HRESULT WINAPI
msaa_provider_QueryInterface(IRawElementProviderSimple
*iface
, REFIID riid
, void **ppv
)
154 if (IsEqualIID(riid
, &IID_IRawElementProviderSimple
) || IsEqualIID(riid
, &IID_IUnknown
))
157 return E_NOINTERFACE
;
159 IRawElementProviderSimple_AddRef(iface
);
163 ULONG WINAPI
msaa_provider_AddRef(IRawElementProviderSimple
*iface
)
165 struct msaa_provider
*msaa_prov
= impl_from_msaa_provider(iface
);
166 ULONG refcount
= InterlockedIncrement(&msaa_prov
->refcount
);
168 TRACE("%p, refcount %ld\n", iface
, refcount
);
173 ULONG WINAPI
msaa_provider_Release(IRawElementProviderSimple
*iface
)
175 struct msaa_provider
*msaa_prov
= impl_from_msaa_provider(iface
);
176 ULONG refcount
= InterlockedDecrement(&msaa_prov
->refcount
);
178 TRACE("%p, refcount %ld\n", iface
, refcount
);
182 IAccessible_Release(msaa_prov
->acc
);
183 heap_free(msaa_prov
);
189 HRESULT WINAPI
msaa_provider_get_ProviderOptions(IRawElementProviderSimple
*iface
,
190 enum ProviderOptions
*ret_val
)
192 TRACE("%p, %p\n", iface
, ret_val
);
193 *ret_val
= ProviderOptions_ServerSideProvider
| ProviderOptions_UseComThreading
;
197 HRESULT WINAPI
msaa_provider_GetPatternProvider(IRawElementProviderSimple
*iface
,
198 PATTERNID pattern_id
, IUnknown
**ret_val
)
200 FIXME("%p, %d, %p: stub!\n", iface
, pattern_id
, ret_val
);
205 HRESULT WINAPI
msaa_provider_GetPropertyValue(IRawElementProviderSimple
*iface
,
206 PROPERTYID prop_id
, VARIANT
*ret_val
)
208 struct msaa_provider
*msaa_prov
= impl_from_msaa_provider(iface
);
212 TRACE("%p, %d, %p\n", iface
, prop_id
, ret_val
);
214 VariantInit(ret_val
);
218 case UIA_ProviderDescriptionPropertyId
:
219 V_VT(ret_val
) = VT_BSTR
;
220 V_BSTR(ret_val
) = SysAllocString(L
"Wine: MSAA Proxy");
223 case UIA_ControlTypePropertyId
:
224 if (!msaa_prov
->control_type
)
226 hr
= IAccessible_get_accRole(msaa_prov
->acc
, msaa_prov
->cid
, &v
);
227 if (SUCCEEDED(hr
) && (V_VT(&v
) == VT_I4
))
228 msaa_prov
->control_type
= msaa_role_to_uia_control_type(V_I4(&v
));
231 if (msaa_prov
->control_type
)
232 variant_init_i4(ret_val
, msaa_prov
->control_type
);
236 case UIA_HasKeyboardFocusPropertyId
:
237 variant_init_bool(ret_val
, msaa_check_acc_state(msaa_prov
->acc
, msaa_prov
->cid
,
238 STATE_SYSTEM_FOCUSED
));
241 case UIA_IsKeyboardFocusablePropertyId
:
242 variant_init_bool(ret_val
, msaa_check_acc_state(msaa_prov
->acc
, msaa_prov
->cid
,
243 STATE_SYSTEM_FOCUSABLE
));
246 case UIA_IsEnabledPropertyId
:
247 variant_init_bool(ret_val
, !msaa_check_acc_state(msaa_prov
->acc
, msaa_prov
->cid
,
248 STATE_SYSTEM_UNAVAILABLE
));
251 case UIA_IsPasswordPropertyId
:
252 variant_init_bool(ret_val
, msaa_check_acc_state(msaa_prov
->acc
, msaa_prov
->cid
,
253 STATE_SYSTEM_PROTECTED
));
257 FIXME("Unimplemented propertyId %d\n", prop_id
);
264 HRESULT WINAPI
msaa_provider_get_HostRawElementProvider(IRawElementProviderSimple
*iface
,
265 IRawElementProviderSimple
**ret_val
)
267 FIXME("%p, %p: stub!\n", iface
, ret_val
);
272 static const IRawElementProviderSimpleVtbl msaa_provider_vtbl
= {
273 msaa_provider_QueryInterface
,
274 msaa_provider_AddRef
,
275 msaa_provider_Release
,
276 msaa_provider_get_ProviderOptions
,
277 msaa_provider_GetPatternProvider
,
278 msaa_provider_GetPropertyValue
,
279 msaa_provider_get_HostRawElementProvider
,
282 /***********************************************************************
283 * UiaProviderFromIAccessible (uiautomationcore.@)
285 HRESULT WINAPI
UiaProviderFromIAccessible(IAccessible
*acc
, long child_id
, DWORD flags
,
286 IRawElementProviderSimple
**elprov
)
288 struct msaa_provider
*msaa_prov
;
289 IServiceProvider
*serv_prov
;
293 TRACE("(%p, %ld, %#lx, %p)\n", acc
, child_id
, flags
, elprov
);
303 if (flags
!= UIA_PFIA_DEFAULT
)
305 FIXME("unsupported flags %#lx\n", flags
);
309 hr
= IAccessible_QueryInterface(acc
, &IID_IServiceProvider
, (void **)&serv_prov
);
314 hr
= IServiceProvider_QueryService(serv_prov
, &IIS_IsOleaccProxy
, &IID_IUnknown
, (void **)&unk
);
317 WARN("Cannot wrap an oleacc proxy IAccessible!\n");
318 IUnknown_Release(unk
);
319 IServiceProvider_Release(serv_prov
);
323 IServiceProvider_Release(serv_prov
);
326 hr
= WindowFromAccessibleObject(acc
, &hwnd
);
332 msaa_prov
= heap_alloc_zero(sizeof(*msaa_prov
));
334 return E_OUTOFMEMORY
;
336 msaa_prov
->IRawElementProviderSimple_iface
.lpVtbl
= &msaa_provider_vtbl
;
337 msaa_prov
->refcount
= 1;
338 msaa_prov
->hwnd
= hwnd
;
339 variant_init_i4(&msaa_prov
->cid
, child_id
);
340 msaa_prov
->acc
= acc
;
341 IAccessible_AddRef(acc
);
342 *elprov
= &msaa_prov
->IRawElementProviderSimple_iface
;