1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/windows/winrt/UIABridge.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,807 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "UIABridge.h" 1.10 +#include "MetroUtils.h" 1.11 +#include "UIABridgePrivate.h" 1.12 +#include "MetroWidget.h" 1.13 +#include "WinUtils.h" 1.14 + 1.15 +#include <wrl.h> 1.16 +#include <OAIdl.h> 1.17 +#include <windows.graphics.display.h> 1.18 + 1.19 +#ifdef ACCESSIBILITY 1.20 +using namespace mozilla::a11y; 1.21 +#endif 1.22 +using namespace mozilla::widget; 1.23 +using namespace Microsoft::WRL; 1.24 +using namespace Microsoft::WRL::Wrappers; 1.25 +using namespace ABI::Windows::UI; 1.26 +using namespace ABI::Windows::UI::Core; 1.27 +using namespace ABI::Windows::Foundation; 1.28 +using namespace ABI::Windows::System; 1.29 + 1.30 +//#define DEBUG_BRIDGE 1.31 +#if !defined(DEBUG_BRIDGE) 1.32 +#undef LogThread 1.33 +#undef LogFunction 1.34 +#define LogThread() 1.35 +#define LogFunction() 1.36 +#define BridgeLog(...) 1.37 +#else 1.38 +#define BridgeLog(...) WinUtils::Log(__VA_ARGS__) 1.39 +#endif 1.40 + 1.41 +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ 1.42 + const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} 1.43 +MIDL_DEFINE_GUID(IID, IID_IUIABridge, 0xc78b35b5, 0x5db, 0x43aa, 0xae, 0x73, 0x94, 0xc2, 0x33, 0xa9, 0x3c, 0x98); 1.44 + 1.45 +namespace mozilla { 1.46 +namespace widget { 1.47 +namespace winrt { 1.48 + 1.49 +#define ProviderOptions_UseClientCoordinates (ProviderOptions)0x100 1.50 + 1.51 +static int gIDIndex = 2; 1.52 +ComPtr<IUIABridge> gProviderRoot = nullptr; 1.53 +static ComPtr<IUIAElement> gElement = nullptr; 1.54 + 1.55 +HRESULT 1.56 +UIABridge_CreateInstance(IInspectable **retVal) 1.57 +{ 1.58 + HRESULT hr = E_OUTOFMEMORY; 1.59 + *retVal = nullptr; 1.60 + ComPtr<UIABridge> spProvider = Make<UIABridge>(); 1.61 + if (spProvider != nullptr && 1.62 + SUCCEEDED(hr = spProvider.Get()->QueryInterface(IID_PPV_ARGS(retVal))) && 1.63 + SUCCEEDED(hr = spProvider.Get()->QueryInterface(IID_PPV_ARGS(&gProviderRoot)))) { 1.64 + return S_OK; 1.65 + } 1.66 + return hr; 1.67 +} 1.68 + 1.69 +HRESULT 1.70 +UIATextElement_CreateInstance(IRawElementProviderFragmentRoot* aRoot) 1.71 +{ 1.72 + LogFunction(); 1.73 + HRESULT hr = E_OUTOFMEMORY; 1.74 + ComPtr<UIATextElement> spProvider = Make<UIATextElement>(); 1.75 + if (spProvider != nullptr && 1.76 + SUCCEEDED(hr = spProvider.Get()->QueryInterface(IID_PPV_ARGS(&gElement)))) { 1.77 + spProvider->SetIndexID(gIDIndex++); 1.78 + return S_OK; 1.79 + } 1.80 + return hr; 1.81 +} 1.82 + 1.83 +// IUIABridge 1.84 + 1.85 +HRESULT 1.86 +UIABridge::Init(IInspectable* aView, IInspectable* aWindow, LONG_PTR aInnerPtr) 1.87 +{ 1.88 + LogFunction(); 1.89 + NS_ASSERTION(aView, "invalid framework view pointer"); 1.90 + NS_ASSERTION(aWindow, "invalid window pointer"); 1.91 + NS_ASSERTION(aInnerPtr, "invalid Accessible pointer"); 1.92 + 1.93 +#if defined(ACCESSIBILITY) 1.94 + // init AccessibilityBridge and connect to accessibility 1.95 + mAccBridge = new AccessibilityBridge(); 1.96 + if (!mAccBridge->Init(CastToUnknown(), (Accessible*)aInnerPtr)) { 1.97 + return E_FAIL; 1.98 + } 1.99 + 1.100 + aWindow->QueryInterface(IID_PPV_ARGS(&mWindow)); 1.101 + 1.102 + if (FAILED(UIATextElement_CreateInstance(this))) 1.103 + return E_FAIL; 1.104 + 1.105 + mAccessible = (Accessible*)aInnerPtr; 1.106 + 1.107 + return S_OK; 1.108 +#endif 1.109 + return E_FAIL; 1.110 +} 1.111 + 1.112 +HRESULT 1.113 +UIABridge::Disconnect() 1.114 +{ 1.115 + LogFunction(); 1.116 +#if defined(ACCESSIBILITY) 1.117 + mAccBridge->Disconnect(); 1.118 + mAccessible = nullptr; 1.119 +#endif 1.120 + mWindow = nullptr; 1.121 + gElement = nullptr; 1.122 + gProviderRoot = nullptr; 1.123 + return S_OK; 1.124 +} 1.125 + 1.126 +bool 1.127 +UIABridge::Connected() 1.128 +{ 1.129 + return !!mAccessible; 1.130 +} 1.131 + 1.132 +// IUIAElement 1.133 + 1.134 +HRESULT 1.135 +UIABridge::SetFocusInternal(LONG_PTR aAccessible) 1.136 +{ 1.137 + LogFunction(); 1.138 + return S_OK; 1.139 +} 1.140 + 1.141 +HRESULT 1.142 +UIABridge::ClearFocus() 1.143 +{ 1.144 + LogFunction(); 1.145 + return S_OK; 1.146 +} 1.147 + 1.148 +static void 1.149 +DumpChildInfo(nsCOMPtr<nsIAccessible>& aChild) 1.150 +{ 1.151 +#ifdef DEBUG 1.152 + if (!aChild) { 1.153 + return; 1.154 + } 1.155 + nsString str; 1.156 + aChild->GetName(str); 1.157 + BridgeLog("name: %ls", str.BeginReading()); 1.158 + aChild->GetDescription(str); 1.159 + BridgeLog("description: %ls", str.BeginReading()); 1.160 +#endif 1.161 +} 1.162 + 1.163 +static bool 1.164 +ChildHasFocus(nsCOMPtr<nsIAccessible>& aChild) 1.165 +{ 1.166 + Accessible* access = (Accessible*)aChild.get(); 1.167 + BridgeLog("Focus element flags: editable:%d focusable:%d readonly:%d", 1.168 + ((access->NativeState() & mozilla::a11y::states::EDITABLE) > 0), 1.169 + ((access->NativeState() & mozilla::a11y::states::FOCUSABLE) > 0), 1.170 + ((access->NativeState() & mozilla::a11y::states::READONLY) > 0)); 1.171 + return (((access->NativeState() & mozilla::a11y::states::EDITABLE) > 0) && 1.172 + ((access->NativeState() & mozilla::a11y::states::READONLY) == 0)); 1.173 +} 1.174 + 1.175 +HRESULT 1.176 +UIABridge::FocusChangeEvent() 1.177 +{ 1.178 + LogFunction(); 1.179 + if (!Connected()) { 1.180 + return UIA_E_ELEMENTNOTAVAILABLE; 1.181 + } 1.182 + 1.183 + nsCOMPtr<nsIAccessible> child; 1.184 + mAccessible->GetFocusedChild(getter_AddRefs(child)); 1.185 + if (!child) { 1.186 + return S_OK; 1.187 + } 1.188 + 1.189 + if (!ChildHasFocus(child)) { 1.190 + ComPtr<IUIAElement> element; 1.191 + gElement.As(&element); 1.192 + if (!element) { 1.193 + return S_OK; 1.194 + } 1.195 + element->ClearFocus(); 1.196 + UiaRaiseAutomationEvent(this, UIA_AutomationFocusChangedEventId); 1.197 + } 1.198 + 1.199 + return S_OK; 1.200 +} 1.201 + 1.202 +// IRawElementProviderFragmentRoot 1.203 + 1.204 +HRESULT 1.205 +UIABridge::ElementProviderFromPoint(double x, double y, IRawElementProviderFragment ** retVal) 1.206 +{ 1.207 + LogFunction(); 1.208 + *retVal = nullptr; 1.209 + if (!Connected()) { 1.210 + return UIA_E_ELEMENTNOTAVAILABLE; 1.211 + } 1.212 + gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal)); 1.213 + return S_OK; 1.214 +} 1.215 + 1.216 +// Windows calls this looking for the current focus element. Windows 1.217 +// will call here before accessible sends us any observer events through 1.218 +// the accessibility bridge, so update child focus information. 1.219 +HRESULT 1.220 +UIABridge::GetFocus(IRawElementProviderFragment ** retVal) 1.221 +{ 1.222 + LogFunction(); 1.223 + if (!Connected()) { 1.224 + return UIA_E_ELEMENTNOTAVAILABLE; 1.225 + } 1.226 + 1.227 + nsCOMPtr<nsIAccessible> child; 1.228 + nsresult rv = mAccessible->GetFocusedChild(getter_AddRefs(child)); 1.229 + if (!child) { 1.230 + BridgeLog("mAccessible->GetFocusedChild failed."); 1.231 + return S_OK; 1.232 + } 1.233 + 1.234 + DumpChildInfo(child); 1.235 + 1.236 + ComPtr<IUIAElement> element; 1.237 + gElement.As(&element); 1.238 + if (!element) { 1.239 + BridgeLog("gElement as IUIAElement failed."); 1.240 + return S_OK; 1.241 + } 1.242 + 1.243 + if (!ChildHasFocus(child)) { 1.244 + element->ClearFocus(); 1.245 + } else { 1.246 + element->SetFocusInternal((LONG_PTR)child.get()); 1.247 + element.Get()->QueryInterface(IID_PPV_ARGS(retVal)); 1.248 + } 1.249 + 1.250 + return S_OK; 1.251 +} 1.252 + 1.253 +// IRawElementProviderFragment 1.254 + 1.255 +HRESULT 1.256 +UIABridge::Navigate(NavigateDirection direction, IRawElementProviderFragment ** retVal) 1.257 +{ 1.258 + LogFunction(); 1.259 + if (!Connected()) { 1.260 + return UIA_E_ELEMENTNOTAVAILABLE; 1.261 + } 1.262 + *retVal = nullptr; 1.263 + 1.264 + switch(direction) { 1.265 + case NavigateDirection_Parent: 1.266 + BridgeLog("UIABridge::Navigate NavigateDirection_Parent"); 1.267 + break; 1.268 + case NavigateDirection_NextSibling: 1.269 + BridgeLog("UIABridge::Navigate NavigateDirection_NextSibling"); 1.270 + break; 1.271 + case NavigateDirection_PreviousSibling: 1.272 + BridgeLog("UIABridge::Navigate NavigateDirection_PreviousSibling"); 1.273 + break; 1.274 + case NavigateDirection_FirstChild: 1.275 + BridgeLog("UIABridge::Navigate NavigateDirection_FirstChild"); 1.276 + gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal)); 1.277 + break; 1.278 + case NavigateDirection_LastChild: 1.279 + BridgeLog("UIABridge::Navigate NavigateDirection_LastChild"); 1.280 + gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal)); 1.281 + break; 1.282 + } 1.283 + 1.284 + // For the other directions (parent, next, previous) the default of nullptr is correct 1.285 + return S_OK; 1.286 +} 1.287 + 1.288 +HRESULT 1.289 +UIABridge::GetRuntimeId(SAFEARRAY ** retVal) 1.290 +{ 1.291 + LogFunction(); 1.292 + if (!Connected()) { 1.293 + return UIA_E_ELEMENTNOTAVAILABLE; 1.294 + } 1.295 + 1.296 + int runtimeId[2] = { UiaAppendRuntimeId, 1 }; // always 1 1.297 + *retVal = SafeArrayCreateVector(VT_I4, 0, ARRAYSIZE(runtimeId)); 1.298 + if (*retVal != nullptr) { 1.299 + for (long index = 0; index < ARRAYSIZE(runtimeId); ++index) { 1.300 + SafeArrayPutElement(*retVal, &index, &runtimeId[index]); 1.301 + } 1.302 + } else { 1.303 + return E_OUTOFMEMORY; 1.304 + } 1.305 + return S_OK; 1.306 +} 1.307 + 1.308 +HRESULT 1.309 +UIABridge::get_BoundingRectangle(UiaRect * retVal) 1.310 +{ 1.311 + LogFunction(); 1.312 + if (!Connected() || !mWindow) { 1.313 + return UIA_E_ELEMENTNOTAVAILABLE; 1.314 + } 1.315 + 1.316 + // returns logical pixels 1.317 + Rect bounds; 1.318 + mWindow->get_Bounds(&bounds); 1.319 + 1.320 + // we need to return physical pixels 1.321 + retVal->left = WinUtils::LogToPhys(bounds.X); 1.322 + retVal->top = WinUtils::LogToPhys(bounds.Y); 1.323 + retVal->width = WinUtils::LogToPhys(bounds.Width); 1.324 + retVal->height = WinUtils::LogToPhys(bounds.Height); 1.325 + 1.326 + return S_OK; 1.327 +} 1.328 + 1.329 +HRESULT 1.330 +UIABridge::GetEmbeddedFragmentRoots(SAFEARRAY ** retVal) 1.331 +{ 1.332 + if (!Connected()) { 1.333 + return UIA_E_ELEMENTNOTAVAILABLE; 1.334 + } 1.335 + // doesn't apply according to msdn. 1.336 + *retVal = nullptr; 1.337 + return S_OK; 1.338 +} 1.339 + 1.340 +HRESULT 1.341 +UIABridge::SetFocus() 1.342 +{ 1.343 + LogFunction(); 1.344 + if (!Connected()) { 1.345 + return UIA_E_ELEMENTNOTAVAILABLE; 1.346 + } 1.347 + return S_OK; 1.348 +} 1.349 + 1.350 +HRESULT 1.351 +UIABridge::get_FragmentRoot(IRawElementProviderFragmentRoot ** retVal) 1.352 +{ 1.353 + // we are the fragment root. Our children return us for this call. 1.354 + return QueryInterface(IID_PPV_ARGS(retVal)); 1.355 +} 1.356 + 1.357 +// IRawElementProviderSimple 1.358 + 1.359 +HRESULT 1.360 +UIABridge::get_ProviderOptions(ProviderOptions * pRetVal) 1.361 +{ 1.362 + LogFunction(); 1.363 + if (!Connected()) { 1.364 + return E_FAIL; 1.365 + } 1.366 + *pRetVal = ProviderOptions_ServerSideProvider | 1.367 + ProviderOptions_UseComThreading | 1.368 + ProviderOptions_UseClientCoordinates; 1.369 + return S_OK; 1.370 +} 1.371 + 1.372 +HRESULT 1.373 +UIABridge::GetPatternProvider(PATTERNID patternId, IUnknown **ppRetVal) 1.374 +{ 1.375 + LogFunction(); 1.376 + BridgeLog("UIABridge::GetPatternProvider=%d", patternId); 1.377 + 1.378 + // The root window doesn't support any specific pattern 1.379 + *ppRetVal = nullptr; 1.380 + 1.381 + return S_OK; 1.382 +} 1.383 + 1.384 +HRESULT 1.385 +UIABridge::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal) 1.386 +{ 1.387 + pRetVal->vt = VT_EMPTY; 1.388 + 1.389 + switch (idProp) { 1.390 + case UIA_AutomationIdPropertyId: 1.391 + BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_AutomationIdPropertyId"); 1.392 + break; 1.393 + case UIA_ControlTypePropertyId: 1.394 + BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_ControlTypePropertyId"); 1.395 + break; 1.396 + case UIA_IsKeyboardFocusablePropertyId: 1.397 + BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsKeyboardFocusablePropertyId"); 1.398 + break; 1.399 + case UIA_IsContentElementPropertyId: 1.400 + BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsContentElementPropertyId"); 1.401 + break; 1.402 + case UIA_IsControlElementPropertyId: 1.403 + BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsControlElementPropertyId"); 1.404 + break; 1.405 + case UIA_IsEnabledPropertyId: 1.406 + BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsEnabledPropertyId"); 1.407 + break; 1.408 + case UIA_HasKeyboardFocusPropertyId: 1.409 + BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_HasKeyboardFocusPropertyId"); 1.410 + break; 1.411 + case UIA_NamePropertyId: 1.412 + BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_NamePropertyId"); 1.413 + break; 1.414 + case UIA_IsPasswordPropertyId: 1.415 + BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsPasswordPropertyId"); 1.416 + break; 1.417 + case UIA_NativeWindowHandlePropertyId: 1.418 + BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_NativeWindowHandlePropertyId"); 1.419 + break; 1.420 + default: 1.421 + BridgeLog("UIABridge::GetPropertyValue: idProp=%d", idProp); 1.422 + break; 1.423 + } 1.424 + 1.425 + if (!Connected()) { 1.426 + return E_FAIL; 1.427 + } 1.428 + 1.429 + switch (idProp) { 1.430 + case UIA_AutomationIdPropertyId: 1.431 + pRetVal->bstrVal = SysAllocString(L"MozillaAccessibilityBridge0001"); 1.432 + pRetVal->vt = VT_BSTR; 1.433 + break; 1.434 + 1.435 + case UIA_ControlTypePropertyId: 1.436 + pRetVal->vt = VT_I4; 1.437 + pRetVal->lVal = UIA_WindowControlTypeId; 1.438 + break; 1.439 + 1.440 + case UIA_IsKeyboardFocusablePropertyId: 1.441 + case UIA_IsContentElementPropertyId: 1.442 + case UIA_IsControlElementPropertyId: 1.443 + case UIA_IsEnabledPropertyId: 1.444 + pRetVal->boolVal = VARIANT_TRUE; 1.445 + pRetVal->vt = VT_BOOL; 1.446 + break; 1.447 + 1.448 + case UIA_HasKeyboardFocusPropertyId: 1.449 + pRetVal->vt = VT_BOOL; 1.450 + pRetVal->boolVal = VARIANT_FALSE; 1.451 + break; 1.452 + 1.453 + case UIA_NamePropertyId: 1.454 + pRetVal->bstrVal = SysAllocString(L"MozillaAccessibilityBridge"); 1.455 + pRetVal->vt = VT_BSTR; 1.456 + break; 1.457 + 1.458 + case UIA_IsPasswordPropertyId: 1.459 + pRetVal->vt = VT_BOOL; 1.460 + pRetVal->boolVal = VARIANT_FALSE; 1.461 + break; 1.462 + 1.463 + case UIA_NativeWindowHandlePropertyId: 1.464 + pRetVal->vt = VT_I4; 1.465 + pRetVal->lVal = (LONG)MetroWidget::GetICoreWindowHWND(); 1.466 + break; 1.467 + 1.468 + default: 1.469 + BridgeLog("UIABridge: Unhandled property"); 1.470 + break; 1.471 + } 1.472 + return S_OK; 1.473 +} 1.474 + 1.475 +HRESULT 1.476 +UIABridge::get_HostRawElementProvider(IRawElementProviderSimple **ppRetVal) 1.477 +{ 1.478 + // We only have this in the root bridge - this is our parent ICoreWindow. 1.479 + *ppRetVal = nullptr; 1.480 + if (mWindow != nullptr) { 1.481 + IInspectable *pHostAsInspectable = nullptr; 1.482 + if (SUCCEEDED(mWindow->get_AutomationHostProvider(&pHostAsInspectable))) { 1.483 + pHostAsInspectable->QueryInterface(ppRetVal); 1.484 + pHostAsInspectable->Release(); 1.485 + } 1.486 + } 1.487 + return S_OK; 1.488 +} 1.489 + 1.490 +/////////////////////////////////////////////////////////////////////////////// 1.491 +// Element 1.492 + 1.493 +HRESULT 1.494 +UIATextElement::SetFocusInternal(LONG_PTR aAccessible) 1.495 +{ 1.496 + LogFunction(); 1.497 +#if defined(ACCESSIBILITY) 1.498 + NS_ASSERTION(mAccessItem, "Bad accessible pointer"); 1.499 + if (mAccessItem == (nsIAccessible*)aAccessible) { 1.500 + return E_UNEXPECTED; 1.501 + } 1.502 + mAccessItem = (nsIAccessible*)aAccessible; 1.503 + return S_OK; 1.504 +#endif 1.505 + return E_FAIL; 1.506 +} 1.507 + 1.508 +HRESULT 1.509 +UIATextElement::ClearFocus() 1.510 +{ 1.511 + LogFunction(); 1.512 + mAccessItem = nullptr; 1.513 + return S_OK; 1.514 +} 1.515 + 1.516 +// IRawElementProviderFragment 1.517 + 1.518 +HRESULT 1.519 +UIATextElement::Navigate(NavigateDirection direction, IRawElementProviderFragment ** retVal) 1.520 +{ 1.521 + LogFunction(); 1.522 + 1.523 + *retVal = nullptr; 1.524 + switch(direction) { 1.525 + case NavigateDirection_Parent: 1.526 + gProviderRoot.Get()->QueryInterface(IID_PPV_ARGS(retVal)); 1.527 + break; 1.528 + case NavigateDirection_NextSibling: 1.529 + break; 1.530 + case NavigateDirection_PreviousSibling: 1.531 + break; 1.532 + case NavigateDirection_FirstChild: 1.533 + break; 1.534 + case NavigateDirection_LastChild: 1.535 + break; 1.536 + } 1.537 + return S_OK; 1.538 +} 1.539 + 1.540 +HRESULT 1.541 +UIATextElement::GetRuntimeId(SAFEARRAY ** retVal) 1.542 +{ 1.543 + LogFunction(); 1.544 + int runtimeId[2] = { UiaAppendRuntimeId, mIndexID }; 1.545 + *retVal = SafeArrayCreateVector(VT_I4, 0, ARRAYSIZE(runtimeId)); 1.546 + if (*retVal != nullptr) { 1.547 + for (long index = 0; index < ARRAYSIZE(runtimeId); ++index) { 1.548 + SafeArrayPutElement(*retVal, &index, &runtimeId[index]); 1.549 + } 1.550 + } else { 1.551 + return E_OUTOFMEMORY; 1.552 + } 1.553 + return S_OK; 1.554 +} 1.555 + 1.556 +HRESULT 1.557 +UIATextElement::get_BoundingRectangle(UiaRect * retVal) 1.558 +{ 1.559 + LogFunction(); 1.560 + 1.561 + if (!mAccessItem) { 1.562 + return UIA_E_ELEMENTNOTAVAILABLE; 1.563 + } 1.564 + 1.565 + // bounds are in physical pixels 1.566 + int32_t docX = 0, docY = 0, docWidth = 0, docHeight = 0; 1.567 + mAccessItem->GetBounds(&docX, &docY, &docWidth, &docHeight); 1.568 + 1.569 + retVal->left = (float)docX; 1.570 + retVal->top = (float)docY; 1.571 + retVal->width = (float)docWidth; 1.572 + retVal->height = (float)docHeight; 1.573 + 1.574 + BridgeLog("get_BoundingRectangle: left=%d top=%d right=%d bottom=%d", docX, docY, docX + docWidth, docY + docHeight); 1.575 + return S_OK; 1.576 +} 1.577 + 1.578 +HRESULT 1.579 +UIATextElement::GetEmbeddedFragmentRoots(SAFEARRAY ** retVal) 1.580 +{ 1.581 + *retVal = nullptr; 1.582 + return S_OK; 1.583 +} 1.584 + 1.585 +HRESULT 1.586 +UIATextElement::SetFocus() 1.587 +{ 1.588 + LogFunction(); 1.589 + return S_OK; 1.590 +} 1.591 + 1.592 +HRESULT 1.593 +UIATextElement::get_FragmentRoot(IRawElementProviderFragmentRoot ** retVal) 1.594 +{ 1.595 + return gProviderRoot.Get()->QueryInterface(IID_PPV_ARGS(retVal)); 1.596 +} 1.597 + 1.598 +// IRawElementProviderSimple 1.599 + 1.600 +HRESULT 1.601 +UIATextElement::get_ProviderOptions(ProviderOptions * pRetVal) 1.602 +{ 1.603 + *pRetVal = ProviderOptions_ServerSideProvider | 1.604 + ProviderOptions_UseComThreading | 1.605 + ProviderOptions_UseClientCoordinates; 1.606 + return S_OK; 1.607 +} 1.608 + 1.609 +HRESULT 1.610 +UIATextElement::GetPatternProvider(PATTERNID patternId, IUnknown **ppRetVal) 1.611 +{ 1.612 + LogFunction(); 1.613 + BridgeLog("UIATextElement::GetPatternProvider=%d", patternId); 1.614 + 1.615 + // UIA_ValuePatternId - 10002 1.616 + // UIA_TextPatternId - 10014 1.617 + // UIA_TextChildPatternId - 10029 1.618 + 1.619 + *ppRetVal = nullptr; 1.620 + if (patternId == UIA_TextPatternId) { 1.621 + BridgeLog("** TextPattern requested from element."); 1.622 + *ppRetVal = static_cast<ITextProvider*>(this); 1.623 + AddRef(); 1.624 + return S_OK; 1.625 + } else if (patternId == UIA_ValuePatternId) { 1.626 + BridgeLog("** ValuePattern requested from element."); 1.627 + *ppRetVal = static_cast<IValueProvider*>(this); 1.628 + AddRef(); 1.629 + return S_OK; 1.630 + } 1.631 + 1.632 + return S_OK; 1.633 +} 1.634 + 1.635 +HRESULT 1.636 +UIATextElement::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal) 1.637 +{ 1.638 + pRetVal->vt = VT_EMPTY; 1.639 + 1.640 + // native hwnd, we don't have one for elements 1.641 + if (idProp == 30020) { 1.642 + return S_OK; 1.643 + } 1.644 + 1.645 + switch (idProp) { 1.646 + case UIA_AutomationIdPropertyId: 1.647 + BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_AutomationIdPropertyId"); 1.648 + break; 1.649 + case UIA_ControlTypePropertyId: 1.650 + BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_ControlTypePropertyId"); 1.651 + break; 1.652 + case UIA_IsKeyboardFocusablePropertyId: 1.653 + BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsKeyboardFocusablePropertyId"); 1.654 + break; 1.655 + case UIA_IsContentElementPropertyId: 1.656 + BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsContentElementPropertyId"); 1.657 + break; 1.658 + case UIA_IsControlElementPropertyId: 1.659 + BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsControlElementPropertyId"); 1.660 + break; 1.661 + case UIA_IsEnabledPropertyId: 1.662 + BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsEnabledPropertyId"); 1.663 + break; 1.664 + case UIA_HasKeyboardFocusPropertyId: 1.665 + BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_HasKeyboardFocusPropertyId"); 1.666 + break; 1.667 + case UIA_NamePropertyId: 1.668 + BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_NamePropertyId"); 1.669 + break; 1.670 + case UIA_IsPasswordPropertyId: 1.671 + BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsPasswordPropertyId"); 1.672 + break; 1.673 + default: 1.674 + BridgeLog("UIATextElement::GetPropertyValue: idProp=%d", idProp); 1.675 + break; 1.676 + } 1.677 + 1.678 + switch (idProp) { 1.679 + case UIA_AutomationIdPropertyId: 1.680 + pRetVal->bstrVal = SysAllocString(L"MozillaDocument0001"); 1.681 + pRetVal->vt = VT_BSTR; 1.682 + break; 1.683 + 1.684 + case UIA_ControlTypePropertyId: 1.685 + pRetVal->vt = VT_I4; 1.686 + pRetVal->lVal = UIA_EditControlTypeId; 1.687 + break; 1.688 + 1.689 + case UIA_IsTextPatternAvailablePropertyId: 1.690 + case UIA_IsKeyboardFocusablePropertyId: 1.691 + case UIA_IsContentElementPropertyId: 1.692 + case UIA_IsControlElementPropertyId: 1.693 + case UIA_IsEnabledPropertyId: 1.694 + pRetVal->boolVal = VARIANT_TRUE; 1.695 + pRetVal->vt = VT_BOOL; 1.696 + break; 1.697 + 1.698 + case UIA_LocalizedControlTypePropertyId: 1.699 + case UIA_LabeledByPropertyId: 1.700 + break; 1.701 + 1.702 + case UIA_HasKeyboardFocusPropertyId: 1.703 + { 1.704 + if (mAccessItem) { 1.705 + uint32_t state, extraState; 1.706 + if (NS_SUCCEEDED(mAccessItem->GetState(&state, &extraState)) && 1.707 + (state & nsIAccessibleStates::STATE_FOCUSED)) { 1.708 + pRetVal->vt = VT_BOOL; 1.709 + pRetVal->boolVal = VARIANT_TRUE; 1.710 + return S_OK; 1.711 + } 1.712 + } 1.713 + pRetVal->vt = VT_BOOL; 1.714 + pRetVal->boolVal = VARIANT_FALSE; 1.715 + break; 1.716 + } 1.717 + 1.718 + case UIA_NamePropertyId: 1.719 + pRetVal->bstrVal = SysAllocString(L"MozillaDocument"); 1.720 + pRetVal->vt = VT_BSTR; 1.721 + break; 1.722 + 1.723 + case UIA_IsPasswordPropertyId: 1.724 + pRetVal->vt = VT_BOOL; 1.725 + pRetVal->boolVal = VARIANT_FALSE; 1.726 + break; 1.727 + 1.728 + default: 1.729 + BridgeLog("UIATextElement: Unhandled property"); 1.730 + break; 1.731 + } 1.732 + return S_OK; 1.733 +} 1.734 + 1.735 +HRESULT 1.736 +UIATextElement::get_HostRawElementProvider(IRawElementProviderSimple **ppRetVal) 1.737 +{ 1.738 + *ppRetVal = nullptr; 1.739 + return S_OK; 1.740 +} 1.741 + 1.742 +// ITextProvider 1.743 + 1.744 +HRESULT 1.745 +UIATextElement::GetSelection(SAFEARRAY * *pRetVal) 1.746 +{ 1.747 + LogFunction(); 1.748 + return E_NOTIMPL; 1.749 +} 1.750 + 1.751 +HRESULT 1.752 +UIATextElement::GetVisibleRanges(SAFEARRAY * *pRetVal) 1.753 +{ 1.754 + LogFunction(); 1.755 + return E_NOTIMPL; 1.756 +} 1.757 + 1.758 +HRESULT 1.759 +UIATextElement::RangeFromChild(IRawElementProviderSimple *childElement, ITextRangeProvider **pRetVal) 1.760 +{ 1.761 + LogFunction(); 1.762 + return E_NOTIMPL; 1.763 +} 1.764 + 1.765 +HRESULT 1.766 +UIATextElement::RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal) 1.767 +{ 1.768 + LogFunction(); 1.769 + return E_NOTIMPL; 1.770 +} 1.771 + 1.772 +HRESULT 1.773 +UIATextElement::get_DocumentRange(ITextRangeProvider **pRetVal) 1.774 +{ 1.775 + LogFunction(); 1.776 + return E_NOTIMPL; 1.777 +} 1.778 + 1.779 +HRESULT 1.780 +UIATextElement::get_SupportedTextSelection(SupportedTextSelection *pRetVal) 1.781 +{ 1.782 + LogFunction(); 1.783 + return E_NOTIMPL; 1.784 +} 1.785 + 1.786 +// IValueProvider 1.787 + 1.788 +IFACEMETHODIMP 1.789 +UIATextElement::SetValue(LPCWSTR val) 1.790 +{ 1.791 + LogFunction(); 1.792 + return E_NOTIMPL; 1.793 +} 1.794 + 1.795 +IFACEMETHODIMP 1.796 +UIATextElement::get_Value(BSTR *pRetVal) 1.797 +{ 1.798 + LogFunction(); 1.799 + return E_NOTIMPL; 1.800 +} 1.801 + 1.802 +IFACEMETHODIMP 1.803 +UIATextElement::get_IsReadOnly(BOOL *pRetVal) 1.804 +{ 1.805 + LogFunction(); 1.806 + *pRetVal = FALSE; 1.807 + return S_OK; 1.808 +} 1.809 + 1.810 +} } }