|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "UIABridge.h" |
|
7 #include "MetroUtils.h" |
|
8 #include "UIABridgePrivate.h" |
|
9 #include "MetroWidget.h" |
|
10 #include "WinUtils.h" |
|
11 |
|
12 #include <wrl.h> |
|
13 #include <OAIdl.h> |
|
14 #include <windows.graphics.display.h> |
|
15 |
|
16 #ifdef ACCESSIBILITY |
|
17 using namespace mozilla::a11y; |
|
18 #endif |
|
19 using namespace mozilla::widget; |
|
20 using namespace Microsoft::WRL; |
|
21 using namespace Microsoft::WRL::Wrappers; |
|
22 using namespace ABI::Windows::UI; |
|
23 using namespace ABI::Windows::UI::Core; |
|
24 using namespace ABI::Windows::Foundation; |
|
25 using namespace ABI::Windows::System; |
|
26 |
|
27 //#define DEBUG_BRIDGE |
|
28 #if !defined(DEBUG_BRIDGE) |
|
29 #undef LogThread |
|
30 #undef LogFunction |
|
31 #define LogThread() |
|
32 #define LogFunction() |
|
33 #define BridgeLog(...) |
|
34 #else |
|
35 #define BridgeLog(...) WinUtils::Log(__VA_ARGS__) |
|
36 #endif |
|
37 |
|
38 #define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ |
|
39 const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} |
|
40 MIDL_DEFINE_GUID(IID, IID_IUIABridge, 0xc78b35b5, 0x5db, 0x43aa, 0xae, 0x73, 0x94, 0xc2, 0x33, 0xa9, 0x3c, 0x98); |
|
41 |
|
42 namespace mozilla { |
|
43 namespace widget { |
|
44 namespace winrt { |
|
45 |
|
46 #define ProviderOptions_UseClientCoordinates (ProviderOptions)0x100 |
|
47 |
|
48 static int gIDIndex = 2; |
|
49 ComPtr<IUIABridge> gProviderRoot = nullptr; |
|
50 static ComPtr<IUIAElement> gElement = nullptr; |
|
51 |
|
52 HRESULT |
|
53 UIABridge_CreateInstance(IInspectable **retVal) |
|
54 { |
|
55 HRESULT hr = E_OUTOFMEMORY; |
|
56 *retVal = nullptr; |
|
57 ComPtr<UIABridge> spProvider = Make<UIABridge>(); |
|
58 if (spProvider != nullptr && |
|
59 SUCCEEDED(hr = spProvider.Get()->QueryInterface(IID_PPV_ARGS(retVal))) && |
|
60 SUCCEEDED(hr = spProvider.Get()->QueryInterface(IID_PPV_ARGS(&gProviderRoot)))) { |
|
61 return S_OK; |
|
62 } |
|
63 return hr; |
|
64 } |
|
65 |
|
66 HRESULT |
|
67 UIATextElement_CreateInstance(IRawElementProviderFragmentRoot* aRoot) |
|
68 { |
|
69 LogFunction(); |
|
70 HRESULT hr = E_OUTOFMEMORY; |
|
71 ComPtr<UIATextElement> spProvider = Make<UIATextElement>(); |
|
72 if (spProvider != nullptr && |
|
73 SUCCEEDED(hr = spProvider.Get()->QueryInterface(IID_PPV_ARGS(&gElement)))) { |
|
74 spProvider->SetIndexID(gIDIndex++); |
|
75 return S_OK; |
|
76 } |
|
77 return hr; |
|
78 } |
|
79 |
|
80 // IUIABridge |
|
81 |
|
82 HRESULT |
|
83 UIABridge::Init(IInspectable* aView, IInspectable* aWindow, LONG_PTR aInnerPtr) |
|
84 { |
|
85 LogFunction(); |
|
86 NS_ASSERTION(aView, "invalid framework view pointer"); |
|
87 NS_ASSERTION(aWindow, "invalid window pointer"); |
|
88 NS_ASSERTION(aInnerPtr, "invalid Accessible pointer"); |
|
89 |
|
90 #if defined(ACCESSIBILITY) |
|
91 // init AccessibilityBridge and connect to accessibility |
|
92 mAccBridge = new AccessibilityBridge(); |
|
93 if (!mAccBridge->Init(CastToUnknown(), (Accessible*)aInnerPtr)) { |
|
94 return E_FAIL; |
|
95 } |
|
96 |
|
97 aWindow->QueryInterface(IID_PPV_ARGS(&mWindow)); |
|
98 |
|
99 if (FAILED(UIATextElement_CreateInstance(this))) |
|
100 return E_FAIL; |
|
101 |
|
102 mAccessible = (Accessible*)aInnerPtr; |
|
103 |
|
104 return S_OK; |
|
105 #endif |
|
106 return E_FAIL; |
|
107 } |
|
108 |
|
109 HRESULT |
|
110 UIABridge::Disconnect() |
|
111 { |
|
112 LogFunction(); |
|
113 #if defined(ACCESSIBILITY) |
|
114 mAccBridge->Disconnect(); |
|
115 mAccessible = nullptr; |
|
116 #endif |
|
117 mWindow = nullptr; |
|
118 gElement = nullptr; |
|
119 gProviderRoot = nullptr; |
|
120 return S_OK; |
|
121 } |
|
122 |
|
123 bool |
|
124 UIABridge::Connected() |
|
125 { |
|
126 return !!mAccessible; |
|
127 } |
|
128 |
|
129 // IUIAElement |
|
130 |
|
131 HRESULT |
|
132 UIABridge::SetFocusInternal(LONG_PTR aAccessible) |
|
133 { |
|
134 LogFunction(); |
|
135 return S_OK; |
|
136 } |
|
137 |
|
138 HRESULT |
|
139 UIABridge::ClearFocus() |
|
140 { |
|
141 LogFunction(); |
|
142 return S_OK; |
|
143 } |
|
144 |
|
145 static void |
|
146 DumpChildInfo(nsCOMPtr<nsIAccessible>& aChild) |
|
147 { |
|
148 #ifdef DEBUG |
|
149 if (!aChild) { |
|
150 return; |
|
151 } |
|
152 nsString str; |
|
153 aChild->GetName(str); |
|
154 BridgeLog("name: %ls", str.BeginReading()); |
|
155 aChild->GetDescription(str); |
|
156 BridgeLog("description: %ls", str.BeginReading()); |
|
157 #endif |
|
158 } |
|
159 |
|
160 static bool |
|
161 ChildHasFocus(nsCOMPtr<nsIAccessible>& aChild) |
|
162 { |
|
163 Accessible* access = (Accessible*)aChild.get(); |
|
164 BridgeLog("Focus element flags: editable:%d focusable:%d readonly:%d", |
|
165 ((access->NativeState() & mozilla::a11y::states::EDITABLE) > 0), |
|
166 ((access->NativeState() & mozilla::a11y::states::FOCUSABLE) > 0), |
|
167 ((access->NativeState() & mozilla::a11y::states::READONLY) > 0)); |
|
168 return (((access->NativeState() & mozilla::a11y::states::EDITABLE) > 0) && |
|
169 ((access->NativeState() & mozilla::a11y::states::READONLY) == 0)); |
|
170 } |
|
171 |
|
172 HRESULT |
|
173 UIABridge::FocusChangeEvent() |
|
174 { |
|
175 LogFunction(); |
|
176 if (!Connected()) { |
|
177 return UIA_E_ELEMENTNOTAVAILABLE; |
|
178 } |
|
179 |
|
180 nsCOMPtr<nsIAccessible> child; |
|
181 mAccessible->GetFocusedChild(getter_AddRefs(child)); |
|
182 if (!child) { |
|
183 return S_OK; |
|
184 } |
|
185 |
|
186 if (!ChildHasFocus(child)) { |
|
187 ComPtr<IUIAElement> element; |
|
188 gElement.As(&element); |
|
189 if (!element) { |
|
190 return S_OK; |
|
191 } |
|
192 element->ClearFocus(); |
|
193 UiaRaiseAutomationEvent(this, UIA_AutomationFocusChangedEventId); |
|
194 } |
|
195 |
|
196 return S_OK; |
|
197 } |
|
198 |
|
199 // IRawElementProviderFragmentRoot |
|
200 |
|
201 HRESULT |
|
202 UIABridge::ElementProviderFromPoint(double x, double y, IRawElementProviderFragment ** retVal) |
|
203 { |
|
204 LogFunction(); |
|
205 *retVal = nullptr; |
|
206 if (!Connected()) { |
|
207 return UIA_E_ELEMENTNOTAVAILABLE; |
|
208 } |
|
209 gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal)); |
|
210 return S_OK; |
|
211 } |
|
212 |
|
213 // Windows calls this looking for the current focus element. Windows |
|
214 // will call here before accessible sends us any observer events through |
|
215 // the accessibility bridge, so update child focus information. |
|
216 HRESULT |
|
217 UIABridge::GetFocus(IRawElementProviderFragment ** retVal) |
|
218 { |
|
219 LogFunction(); |
|
220 if (!Connected()) { |
|
221 return UIA_E_ELEMENTNOTAVAILABLE; |
|
222 } |
|
223 |
|
224 nsCOMPtr<nsIAccessible> child; |
|
225 nsresult rv = mAccessible->GetFocusedChild(getter_AddRefs(child)); |
|
226 if (!child) { |
|
227 BridgeLog("mAccessible->GetFocusedChild failed."); |
|
228 return S_OK; |
|
229 } |
|
230 |
|
231 DumpChildInfo(child); |
|
232 |
|
233 ComPtr<IUIAElement> element; |
|
234 gElement.As(&element); |
|
235 if (!element) { |
|
236 BridgeLog("gElement as IUIAElement failed."); |
|
237 return S_OK; |
|
238 } |
|
239 |
|
240 if (!ChildHasFocus(child)) { |
|
241 element->ClearFocus(); |
|
242 } else { |
|
243 element->SetFocusInternal((LONG_PTR)child.get()); |
|
244 element.Get()->QueryInterface(IID_PPV_ARGS(retVal)); |
|
245 } |
|
246 |
|
247 return S_OK; |
|
248 } |
|
249 |
|
250 // IRawElementProviderFragment |
|
251 |
|
252 HRESULT |
|
253 UIABridge::Navigate(NavigateDirection direction, IRawElementProviderFragment ** retVal) |
|
254 { |
|
255 LogFunction(); |
|
256 if (!Connected()) { |
|
257 return UIA_E_ELEMENTNOTAVAILABLE; |
|
258 } |
|
259 *retVal = nullptr; |
|
260 |
|
261 switch(direction) { |
|
262 case NavigateDirection_Parent: |
|
263 BridgeLog("UIABridge::Navigate NavigateDirection_Parent"); |
|
264 break; |
|
265 case NavigateDirection_NextSibling: |
|
266 BridgeLog("UIABridge::Navigate NavigateDirection_NextSibling"); |
|
267 break; |
|
268 case NavigateDirection_PreviousSibling: |
|
269 BridgeLog("UIABridge::Navigate NavigateDirection_PreviousSibling"); |
|
270 break; |
|
271 case NavigateDirection_FirstChild: |
|
272 BridgeLog("UIABridge::Navigate NavigateDirection_FirstChild"); |
|
273 gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal)); |
|
274 break; |
|
275 case NavigateDirection_LastChild: |
|
276 BridgeLog("UIABridge::Navigate NavigateDirection_LastChild"); |
|
277 gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal)); |
|
278 break; |
|
279 } |
|
280 |
|
281 // For the other directions (parent, next, previous) the default of nullptr is correct |
|
282 return S_OK; |
|
283 } |
|
284 |
|
285 HRESULT |
|
286 UIABridge::GetRuntimeId(SAFEARRAY ** retVal) |
|
287 { |
|
288 LogFunction(); |
|
289 if (!Connected()) { |
|
290 return UIA_E_ELEMENTNOTAVAILABLE; |
|
291 } |
|
292 |
|
293 int runtimeId[2] = { UiaAppendRuntimeId, 1 }; // always 1 |
|
294 *retVal = SafeArrayCreateVector(VT_I4, 0, ARRAYSIZE(runtimeId)); |
|
295 if (*retVal != nullptr) { |
|
296 for (long index = 0; index < ARRAYSIZE(runtimeId); ++index) { |
|
297 SafeArrayPutElement(*retVal, &index, &runtimeId[index]); |
|
298 } |
|
299 } else { |
|
300 return E_OUTOFMEMORY; |
|
301 } |
|
302 return S_OK; |
|
303 } |
|
304 |
|
305 HRESULT |
|
306 UIABridge::get_BoundingRectangle(UiaRect * retVal) |
|
307 { |
|
308 LogFunction(); |
|
309 if (!Connected() || !mWindow) { |
|
310 return UIA_E_ELEMENTNOTAVAILABLE; |
|
311 } |
|
312 |
|
313 // returns logical pixels |
|
314 Rect bounds; |
|
315 mWindow->get_Bounds(&bounds); |
|
316 |
|
317 // we need to return physical pixels |
|
318 retVal->left = WinUtils::LogToPhys(bounds.X); |
|
319 retVal->top = WinUtils::LogToPhys(bounds.Y); |
|
320 retVal->width = WinUtils::LogToPhys(bounds.Width); |
|
321 retVal->height = WinUtils::LogToPhys(bounds.Height); |
|
322 |
|
323 return S_OK; |
|
324 } |
|
325 |
|
326 HRESULT |
|
327 UIABridge::GetEmbeddedFragmentRoots(SAFEARRAY ** retVal) |
|
328 { |
|
329 if (!Connected()) { |
|
330 return UIA_E_ELEMENTNOTAVAILABLE; |
|
331 } |
|
332 // doesn't apply according to msdn. |
|
333 *retVal = nullptr; |
|
334 return S_OK; |
|
335 } |
|
336 |
|
337 HRESULT |
|
338 UIABridge::SetFocus() |
|
339 { |
|
340 LogFunction(); |
|
341 if (!Connected()) { |
|
342 return UIA_E_ELEMENTNOTAVAILABLE; |
|
343 } |
|
344 return S_OK; |
|
345 } |
|
346 |
|
347 HRESULT |
|
348 UIABridge::get_FragmentRoot(IRawElementProviderFragmentRoot ** retVal) |
|
349 { |
|
350 // we are the fragment root. Our children return us for this call. |
|
351 return QueryInterface(IID_PPV_ARGS(retVal)); |
|
352 } |
|
353 |
|
354 // IRawElementProviderSimple |
|
355 |
|
356 HRESULT |
|
357 UIABridge::get_ProviderOptions(ProviderOptions * pRetVal) |
|
358 { |
|
359 LogFunction(); |
|
360 if (!Connected()) { |
|
361 return E_FAIL; |
|
362 } |
|
363 *pRetVal = ProviderOptions_ServerSideProvider | |
|
364 ProviderOptions_UseComThreading | |
|
365 ProviderOptions_UseClientCoordinates; |
|
366 return S_OK; |
|
367 } |
|
368 |
|
369 HRESULT |
|
370 UIABridge::GetPatternProvider(PATTERNID patternId, IUnknown **ppRetVal) |
|
371 { |
|
372 LogFunction(); |
|
373 BridgeLog("UIABridge::GetPatternProvider=%d", patternId); |
|
374 |
|
375 // The root window doesn't support any specific pattern |
|
376 *ppRetVal = nullptr; |
|
377 |
|
378 return S_OK; |
|
379 } |
|
380 |
|
381 HRESULT |
|
382 UIABridge::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal) |
|
383 { |
|
384 pRetVal->vt = VT_EMPTY; |
|
385 |
|
386 switch (idProp) { |
|
387 case UIA_AutomationIdPropertyId: |
|
388 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_AutomationIdPropertyId"); |
|
389 break; |
|
390 case UIA_ControlTypePropertyId: |
|
391 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_ControlTypePropertyId"); |
|
392 break; |
|
393 case UIA_IsKeyboardFocusablePropertyId: |
|
394 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsKeyboardFocusablePropertyId"); |
|
395 break; |
|
396 case UIA_IsContentElementPropertyId: |
|
397 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsContentElementPropertyId"); |
|
398 break; |
|
399 case UIA_IsControlElementPropertyId: |
|
400 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsControlElementPropertyId"); |
|
401 break; |
|
402 case UIA_IsEnabledPropertyId: |
|
403 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsEnabledPropertyId"); |
|
404 break; |
|
405 case UIA_HasKeyboardFocusPropertyId: |
|
406 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_HasKeyboardFocusPropertyId"); |
|
407 break; |
|
408 case UIA_NamePropertyId: |
|
409 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_NamePropertyId"); |
|
410 break; |
|
411 case UIA_IsPasswordPropertyId: |
|
412 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsPasswordPropertyId"); |
|
413 break; |
|
414 case UIA_NativeWindowHandlePropertyId: |
|
415 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_NativeWindowHandlePropertyId"); |
|
416 break; |
|
417 default: |
|
418 BridgeLog("UIABridge::GetPropertyValue: idProp=%d", idProp); |
|
419 break; |
|
420 } |
|
421 |
|
422 if (!Connected()) { |
|
423 return E_FAIL; |
|
424 } |
|
425 |
|
426 switch (idProp) { |
|
427 case UIA_AutomationIdPropertyId: |
|
428 pRetVal->bstrVal = SysAllocString(L"MozillaAccessibilityBridge0001"); |
|
429 pRetVal->vt = VT_BSTR; |
|
430 break; |
|
431 |
|
432 case UIA_ControlTypePropertyId: |
|
433 pRetVal->vt = VT_I4; |
|
434 pRetVal->lVal = UIA_WindowControlTypeId; |
|
435 break; |
|
436 |
|
437 case UIA_IsKeyboardFocusablePropertyId: |
|
438 case UIA_IsContentElementPropertyId: |
|
439 case UIA_IsControlElementPropertyId: |
|
440 case UIA_IsEnabledPropertyId: |
|
441 pRetVal->boolVal = VARIANT_TRUE; |
|
442 pRetVal->vt = VT_BOOL; |
|
443 break; |
|
444 |
|
445 case UIA_HasKeyboardFocusPropertyId: |
|
446 pRetVal->vt = VT_BOOL; |
|
447 pRetVal->boolVal = VARIANT_FALSE; |
|
448 break; |
|
449 |
|
450 case UIA_NamePropertyId: |
|
451 pRetVal->bstrVal = SysAllocString(L"MozillaAccessibilityBridge"); |
|
452 pRetVal->vt = VT_BSTR; |
|
453 break; |
|
454 |
|
455 case UIA_IsPasswordPropertyId: |
|
456 pRetVal->vt = VT_BOOL; |
|
457 pRetVal->boolVal = VARIANT_FALSE; |
|
458 break; |
|
459 |
|
460 case UIA_NativeWindowHandlePropertyId: |
|
461 pRetVal->vt = VT_I4; |
|
462 pRetVal->lVal = (LONG)MetroWidget::GetICoreWindowHWND(); |
|
463 break; |
|
464 |
|
465 default: |
|
466 BridgeLog("UIABridge: Unhandled property"); |
|
467 break; |
|
468 } |
|
469 return S_OK; |
|
470 } |
|
471 |
|
472 HRESULT |
|
473 UIABridge::get_HostRawElementProvider(IRawElementProviderSimple **ppRetVal) |
|
474 { |
|
475 // We only have this in the root bridge - this is our parent ICoreWindow. |
|
476 *ppRetVal = nullptr; |
|
477 if (mWindow != nullptr) { |
|
478 IInspectable *pHostAsInspectable = nullptr; |
|
479 if (SUCCEEDED(mWindow->get_AutomationHostProvider(&pHostAsInspectable))) { |
|
480 pHostAsInspectable->QueryInterface(ppRetVal); |
|
481 pHostAsInspectable->Release(); |
|
482 } |
|
483 } |
|
484 return S_OK; |
|
485 } |
|
486 |
|
487 /////////////////////////////////////////////////////////////////////////////// |
|
488 // Element |
|
489 |
|
490 HRESULT |
|
491 UIATextElement::SetFocusInternal(LONG_PTR aAccessible) |
|
492 { |
|
493 LogFunction(); |
|
494 #if defined(ACCESSIBILITY) |
|
495 NS_ASSERTION(mAccessItem, "Bad accessible pointer"); |
|
496 if (mAccessItem == (nsIAccessible*)aAccessible) { |
|
497 return E_UNEXPECTED; |
|
498 } |
|
499 mAccessItem = (nsIAccessible*)aAccessible; |
|
500 return S_OK; |
|
501 #endif |
|
502 return E_FAIL; |
|
503 } |
|
504 |
|
505 HRESULT |
|
506 UIATextElement::ClearFocus() |
|
507 { |
|
508 LogFunction(); |
|
509 mAccessItem = nullptr; |
|
510 return S_OK; |
|
511 } |
|
512 |
|
513 // IRawElementProviderFragment |
|
514 |
|
515 HRESULT |
|
516 UIATextElement::Navigate(NavigateDirection direction, IRawElementProviderFragment ** retVal) |
|
517 { |
|
518 LogFunction(); |
|
519 |
|
520 *retVal = nullptr; |
|
521 switch(direction) { |
|
522 case NavigateDirection_Parent: |
|
523 gProviderRoot.Get()->QueryInterface(IID_PPV_ARGS(retVal)); |
|
524 break; |
|
525 case NavigateDirection_NextSibling: |
|
526 break; |
|
527 case NavigateDirection_PreviousSibling: |
|
528 break; |
|
529 case NavigateDirection_FirstChild: |
|
530 break; |
|
531 case NavigateDirection_LastChild: |
|
532 break; |
|
533 } |
|
534 return S_OK; |
|
535 } |
|
536 |
|
537 HRESULT |
|
538 UIATextElement::GetRuntimeId(SAFEARRAY ** retVal) |
|
539 { |
|
540 LogFunction(); |
|
541 int runtimeId[2] = { UiaAppendRuntimeId, mIndexID }; |
|
542 *retVal = SafeArrayCreateVector(VT_I4, 0, ARRAYSIZE(runtimeId)); |
|
543 if (*retVal != nullptr) { |
|
544 for (long index = 0; index < ARRAYSIZE(runtimeId); ++index) { |
|
545 SafeArrayPutElement(*retVal, &index, &runtimeId[index]); |
|
546 } |
|
547 } else { |
|
548 return E_OUTOFMEMORY; |
|
549 } |
|
550 return S_OK; |
|
551 } |
|
552 |
|
553 HRESULT |
|
554 UIATextElement::get_BoundingRectangle(UiaRect * retVal) |
|
555 { |
|
556 LogFunction(); |
|
557 |
|
558 if (!mAccessItem) { |
|
559 return UIA_E_ELEMENTNOTAVAILABLE; |
|
560 } |
|
561 |
|
562 // bounds are in physical pixels |
|
563 int32_t docX = 0, docY = 0, docWidth = 0, docHeight = 0; |
|
564 mAccessItem->GetBounds(&docX, &docY, &docWidth, &docHeight); |
|
565 |
|
566 retVal->left = (float)docX; |
|
567 retVal->top = (float)docY; |
|
568 retVal->width = (float)docWidth; |
|
569 retVal->height = (float)docHeight; |
|
570 |
|
571 BridgeLog("get_BoundingRectangle: left=%d top=%d right=%d bottom=%d", docX, docY, docX + docWidth, docY + docHeight); |
|
572 return S_OK; |
|
573 } |
|
574 |
|
575 HRESULT |
|
576 UIATextElement::GetEmbeddedFragmentRoots(SAFEARRAY ** retVal) |
|
577 { |
|
578 *retVal = nullptr; |
|
579 return S_OK; |
|
580 } |
|
581 |
|
582 HRESULT |
|
583 UIATextElement::SetFocus() |
|
584 { |
|
585 LogFunction(); |
|
586 return S_OK; |
|
587 } |
|
588 |
|
589 HRESULT |
|
590 UIATextElement::get_FragmentRoot(IRawElementProviderFragmentRoot ** retVal) |
|
591 { |
|
592 return gProviderRoot.Get()->QueryInterface(IID_PPV_ARGS(retVal)); |
|
593 } |
|
594 |
|
595 // IRawElementProviderSimple |
|
596 |
|
597 HRESULT |
|
598 UIATextElement::get_ProviderOptions(ProviderOptions * pRetVal) |
|
599 { |
|
600 *pRetVal = ProviderOptions_ServerSideProvider | |
|
601 ProviderOptions_UseComThreading | |
|
602 ProviderOptions_UseClientCoordinates; |
|
603 return S_OK; |
|
604 } |
|
605 |
|
606 HRESULT |
|
607 UIATextElement::GetPatternProvider(PATTERNID patternId, IUnknown **ppRetVal) |
|
608 { |
|
609 LogFunction(); |
|
610 BridgeLog("UIATextElement::GetPatternProvider=%d", patternId); |
|
611 |
|
612 // UIA_ValuePatternId - 10002 |
|
613 // UIA_TextPatternId - 10014 |
|
614 // UIA_TextChildPatternId - 10029 |
|
615 |
|
616 *ppRetVal = nullptr; |
|
617 if (patternId == UIA_TextPatternId) { |
|
618 BridgeLog("** TextPattern requested from element."); |
|
619 *ppRetVal = static_cast<ITextProvider*>(this); |
|
620 AddRef(); |
|
621 return S_OK; |
|
622 } else if (patternId == UIA_ValuePatternId) { |
|
623 BridgeLog("** ValuePattern requested from element."); |
|
624 *ppRetVal = static_cast<IValueProvider*>(this); |
|
625 AddRef(); |
|
626 return S_OK; |
|
627 } |
|
628 |
|
629 return S_OK; |
|
630 } |
|
631 |
|
632 HRESULT |
|
633 UIATextElement::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal) |
|
634 { |
|
635 pRetVal->vt = VT_EMPTY; |
|
636 |
|
637 // native hwnd, we don't have one for elements |
|
638 if (idProp == 30020) { |
|
639 return S_OK; |
|
640 } |
|
641 |
|
642 switch (idProp) { |
|
643 case UIA_AutomationIdPropertyId: |
|
644 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_AutomationIdPropertyId"); |
|
645 break; |
|
646 case UIA_ControlTypePropertyId: |
|
647 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_ControlTypePropertyId"); |
|
648 break; |
|
649 case UIA_IsKeyboardFocusablePropertyId: |
|
650 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsKeyboardFocusablePropertyId"); |
|
651 break; |
|
652 case UIA_IsContentElementPropertyId: |
|
653 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsContentElementPropertyId"); |
|
654 break; |
|
655 case UIA_IsControlElementPropertyId: |
|
656 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsControlElementPropertyId"); |
|
657 break; |
|
658 case UIA_IsEnabledPropertyId: |
|
659 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsEnabledPropertyId"); |
|
660 break; |
|
661 case UIA_HasKeyboardFocusPropertyId: |
|
662 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_HasKeyboardFocusPropertyId"); |
|
663 break; |
|
664 case UIA_NamePropertyId: |
|
665 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_NamePropertyId"); |
|
666 break; |
|
667 case UIA_IsPasswordPropertyId: |
|
668 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsPasswordPropertyId"); |
|
669 break; |
|
670 default: |
|
671 BridgeLog("UIATextElement::GetPropertyValue: idProp=%d", idProp); |
|
672 break; |
|
673 } |
|
674 |
|
675 switch (idProp) { |
|
676 case UIA_AutomationIdPropertyId: |
|
677 pRetVal->bstrVal = SysAllocString(L"MozillaDocument0001"); |
|
678 pRetVal->vt = VT_BSTR; |
|
679 break; |
|
680 |
|
681 case UIA_ControlTypePropertyId: |
|
682 pRetVal->vt = VT_I4; |
|
683 pRetVal->lVal = UIA_EditControlTypeId; |
|
684 break; |
|
685 |
|
686 case UIA_IsTextPatternAvailablePropertyId: |
|
687 case UIA_IsKeyboardFocusablePropertyId: |
|
688 case UIA_IsContentElementPropertyId: |
|
689 case UIA_IsControlElementPropertyId: |
|
690 case UIA_IsEnabledPropertyId: |
|
691 pRetVal->boolVal = VARIANT_TRUE; |
|
692 pRetVal->vt = VT_BOOL; |
|
693 break; |
|
694 |
|
695 case UIA_LocalizedControlTypePropertyId: |
|
696 case UIA_LabeledByPropertyId: |
|
697 break; |
|
698 |
|
699 case UIA_HasKeyboardFocusPropertyId: |
|
700 { |
|
701 if (mAccessItem) { |
|
702 uint32_t state, extraState; |
|
703 if (NS_SUCCEEDED(mAccessItem->GetState(&state, &extraState)) && |
|
704 (state & nsIAccessibleStates::STATE_FOCUSED)) { |
|
705 pRetVal->vt = VT_BOOL; |
|
706 pRetVal->boolVal = VARIANT_TRUE; |
|
707 return S_OK; |
|
708 } |
|
709 } |
|
710 pRetVal->vt = VT_BOOL; |
|
711 pRetVal->boolVal = VARIANT_FALSE; |
|
712 break; |
|
713 } |
|
714 |
|
715 case UIA_NamePropertyId: |
|
716 pRetVal->bstrVal = SysAllocString(L"MozillaDocument"); |
|
717 pRetVal->vt = VT_BSTR; |
|
718 break; |
|
719 |
|
720 case UIA_IsPasswordPropertyId: |
|
721 pRetVal->vt = VT_BOOL; |
|
722 pRetVal->boolVal = VARIANT_FALSE; |
|
723 break; |
|
724 |
|
725 default: |
|
726 BridgeLog("UIATextElement: Unhandled property"); |
|
727 break; |
|
728 } |
|
729 return S_OK; |
|
730 } |
|
731 |
|
732 HRESULT |
|
733 UIATextElement::get_HostRawElementProvider(IRawElementProviderSimple **ppRetVal) |
|
734 { |
|
735 *ppRetVal = nullptr; |
|
736 return S_OK; |
|
737 } |
|
738 |
|
739 // ITextProvider |
|
740 |
|
741 HRESULT |
|
742 UIATextElement::GetSelection(SAFEARRAY * *pRetVal) |
|
743 { |
|
744 LogFunction(); |
|
745 return E_NOTIMPL; |
|
746 } |
|
747 |
|
748 HRESULT |
|
749 UIATextElement::GetVisibleRanges(SAFEARRAY * *pRetVal) |
|
750 { |
|
751 LogFunction(); |
|
752 return E_NOTIMPL; |
|
753 } |
|
754 |
|
755 HRESULT |
|
756 UIATextElement::RangeFromChild(IRawElementProviderSimple *childElement, ITextRangeProvider **pRetVal) |
|
757 { |
|
758 LogFunction(); |
|
759 return E_NOTIMPL; |
|
760 } |
|
761 |
|
762 HRESULT |
|
763 UIATextElement::RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal) |
|
764 { |
|
765 LogFunction(); |
|
766 return E_NOTIMPL; |
|
767 } |
|
768 |
|
769 HRESULT |
|
770 UIATextElement::get_DocumentRange(ITextRangeProvider **pRetVal) |
|
771 { |
|
772 LogFunction(); |
|
773 return E_NOTIMPL; |
|
774 } |
|
775 |
|
776 HRESULT |
|
777 UIATextElement::get_SupportedTextSelection(SupportedTextSelection *pRetVal) |
|
778 { |
|
779 LogFunction(); |
|
780 return E_NOTIMPL; |
|
781 } |
|
782 |
|
783 // IValueProvider |
|
784 |
|
785 IFACEMETHODIMP |
|
786 UIATextElement::SetValue(LPCWSTR val) |
|
787 { |
|
788 LogFunction(); |
|
789 return E_NOTIMPL; |
|
790 } |
|
791 |
|
792 IFACEMETHODIMP |
|
793 UIATextElement::get_Value(BSTR *pRetVal) |
|
794 { |
|
795 LogFunction(); |
|
796 return E_NOTIMPL; |
|
797 } |
|
798 |
|
799 IFACEMETHODIMP |
|
800 UIATextElement::get_IsReadOnly(BOOL *pRetVal) |
|
801 { |
|
802 LogFunction(); |
|
803 *pRetVal = FALSE; |
|
804 return S_OK; |
|
805 } |
|
806 |
|
807 } } } |