michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "UIABridge.h" michael@0: #include "MetroUtils.h" michael@0: #include "UIABridgePrivate.h" michael@0: #include "MetroWidget.h" michael@0: #include "WinUtils.h" michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #ifdef ACCESSIBILITY michael@0: using namespace mozilla::a11y; michael@0: #endif michael@0: using namespace mozilla::widget; michael@0: using namespace Microsoft::WRL; michael@0: using namespace Microsoft::WRL::Wrappers; michael@0: using namespace ABI::Windows::UI; michael@0: using namespace ABI::Windows::UI::Core; michael@0: using namespace ABI::Windows::Foundation; michael@0: using namespace ABI::Windows::System; michael@0: michael@0: //#define DEBUG_BRIDGE michael@0: #if !defined(DEBUG_BRIDGE) michael@0: #undef LogThread michael@0: #undef LogFunction michael@0: #define LogThread() michael@0: #define LogFunction() michael@0: #define BridgeLog(...) michael@0: #else michael@0: #define BridgeLog(...) WinUtils::Log(__VA_ARGS__) michael@0: #endif michael@0: michael@0: #define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ michael@0: const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} michael@0: MIDL_DEFINE_GUID(IID, IID_IUIABridge, 0xc78b35b5, 0x5db, 0x43aa, 0xae, 0x73, 0x94, 0xc2, 0x33, 0xa9, 0x3c, 0x98); michael@0: michael@0: namespace mozilla { michael@0: namespace widget { michael@0: namespace winrt { michael@0: michael@0: #define ProviderOptions_UseClientCoordinates (ProviderOptions)0x100 michael@0: michael@0: static int gIDIndex = 2; michael@0: ComPtr gProviderRoot = nullptr; michael@0: static ComPtr gElement = nullptr; michael@0: michael@0: HRESULT michael@0: UIABridge_CreateInstance(IInspectable **retVal) michael@0: { michael@0: HRESULT hr = E_OUTOFMEMORY; michael@0: *retVal = nullptr; michael@0: ComPtr spProvider = Make(); michael@0: if (spProvider != nullptr && michael@0: SUCCEEDED(hr = spProvider.Get()->QueryInterface(IID_PPV_ARGS(retVal))) && michael@0: SUCCEEDED(hr = spProvider.Get()->QueryInterface(IID_PPV_ARGS(&gProviderRoot)))) { michael@0: return S_OK; michael@0: } michael@0: return hr; michael@0: } michael@0: michael@0: HRESULT michael@0: UIATextElement_CreateInstance(IRawElementProviderFragmentRoot* aRoot) michael@0: { michael@0: LogFunction(); michael@0: HRESULT hr = E_OUTOFMEMORY; michael@0: ComPtr spProvider = Make(); michael@0: if (spProvider != nullptr && michael@0: SUCCEEDED(hr = spProvider.Get()->QueryInterface(IID_PPV_ARGS(&gElement)))) { michael@0: spProvider->SetIndexID(gIDIndex++); michael@0: return S_OK; michael@0: } michael@0: return hr; michael@0: } michael@0: michael@0: // IUIABridge michael@0: michael@0: HRESULT michael@0: UIABridge::Init(IInspectable* aView, IInspectable* aWindow, LONG_PTR aInnerPtr) michael@0: { michael@0: LogFunction(); michael@0: NS_ASSERTION(aView, "invalid framework view pointer"); michael@0: NS_ASSERTION(aWindow, "invalid window pointer"); michael@0: NS_ASSERTION(aInnerPtr, "invalid Accessible pointer"); michael@0: michael@0: #if defined(ACCESSIBILITY) michael@0: // init AccessibilityBridge and connect to accessibility michael@0: mAccBridge = new AccessibilityBridge(); michael@0: if (!mAccBridge->Init(CastToUnknown(), (Accessible*)aInnerPtr)) { michael@0: return E_FAIL; michael@0: } michael@0: michael@0: aWindow->QueryInterface(IID_PPV_ARGS(&mWindow)); michael@0: michael@0: if (FAILED(UIATextElement_CreateInstance(this))) michael@0: return E_FAIL; michael@0: michael@0: mAccessible = (Accessible*)aInnerPtr; michael@0: michael@0: return S_OK; michael@0: #endif michael@0: return E_FAIL; michael@0: } michael@0: michael@0: HRESULT michael@0: UIABridge::Disconnect() michael@0: { michael@0: LogFunction(); michael@0: #if defined(ACCESSIBILITY) michael@0: mAccBridge->Disconnect(); michael@0: mAccessible = nullptr; michael@0: #endif michael@0: mWindow = nullptr; michael@0: gElement = nullptr; michael@0: gProviderRoot = nullptr; michael@0: return S_OK; michael@0: } michael@0: michael@0: bool michael@0: UIABridge::Connected() michael@0: { michael@0: return !!mAccessible; michael@0: } michael@0: michael@0: // IUIAElement michael@0: michael@0: HRESULT michael@0: UIABridge::SetFocusInternal(LONG_PTR aAccessible) michael@0: { michael@0: LogFunction(); michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIABridge::ClearFocus() michael@0: { michael@0: LogFunction(); michael@0: return S_OK; michael@0: } michael@0: michael@0: static void michael@0: DumpChildInfo(nsCOMPtr& aChild) michael@0: { michael@0: #ifdef DEBUG michael@0: if (!aChild) { michael@0: return; michael@0: } michael@0: nsString str; michael@0: aChild->GetName(str); michael@0: BridgeLog("name: %ls", str.BeginReading()); michael@0: aChild->GetDescription(str); michael@0: BridgeLog("description: %ls", str.BeginReading()); michael@0: #endif michael@0: } michael@0: michael@0: static bool michael@0: ChildHasFocus(nsCOMPtr& aChild) michael@0: { michael@0: Accessible* access = (Accessible*)aChild.get(); michael@0: BridgeLog("Focus element flags: editable:%d focusable:%d readonly:%d", michael@0: ((access->NativeState() & mozilla::a11y::states::EDITABLE) > 0), michael@0: ((access->NativeState() & mozilla::a11y::states::FOCUSABLE) > 0), michael@0: ((access->NativeState() & mozilla::a11y::states::READONLY) > 0)); michael@0: return (((access->NativeState() & mozilla::a11y::states::EDITABLE) > 0) && michael@0: ((access->NativeState() & mozilla::a11y::states::READONLY) == 0)); michael@0: } michael@0: michael@0: HRESULT michael@0: UIABridge::FocusChangeEvent() michael@0: { michael@0: LogFunction(); michael@0: if (!Connected()) { michael@0: return UIA_E_ELEMENTNOTAVAILABLE; michael@0: } michael@0: michael@0: nsCOMPtr child; michael@0: mAccessible->GetFocusedChild(getter_AddRefs(child)); michael@0: if (!child) { michael@0: return S_OK; michael@0: } michael@0: michael@0: if (!ChildHasFocus(child)) { michael@0: ComPtr element; michael@0: gElement.As(&element); michael@0: if (!element) { michael@0: return S_OK; michael@0: } michael@0: element->ClearFocus(); michael@0: UiaRaiseAutomationEvent(this, UIA_AutomationFocusChangedEventId); michael@0: } michael@0: michael@0: return S_OK; michael@0: } michael@0: michael@0: // IRawElementProviderFragmentRoot michael@0: michael@0: HRESULT michael@0: UIABridge::ElementProviderFromPoint(double x, double y, IRawElementProviderFragment ** retVal) michael@0: { michael@0: LogFunction(); michael@0: *retVal = nullptr; michael@0: if (!Connected()) { michael@0: return UIA_E_ELEMENTNOTAVAILABLE; michael@0: } michael@0: gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal)); michael@0: return S_OK; michael@0: } michael@0: michael@0: // Windows calls this looking for the current focus element. Windows michael@0: // will call here before accessible sends us any observer events through michael@0: // the accessibility bridge, so update child focus information. michael@0: HRESULT michael@0: UIABridge::GetFocus(IRawElementProviderFragment ** retVal) michael@0: { michael@0: LogFunction(); michael@0: if (!Connected()) { michael@0: return UIA_E_ELEMENTNOTAVAILABLE; michael@0: } michael@0: michael@0: nsCOMPtr child; michael@0: nsresult rv = mAccessible->GetFocusedChild(getter_AddRefs(child)); michael@0: if (!child) { michael@0: BridgeLog("mAccessible->GetFocusedChild failed."); michael@0: return S_OK; michael@0: } michael@0: michael@0: DumpChildInfo(child); michael@0: michael@0: ComPtr element; michael@0: gElement.As(&element); michael@0: if (!element) { michael@0: BridgeLog("gElement as IUIAElement failed."); michael@0: return S_OK; michael@0: } michael@0: michael@0: if (!ChildHasFocus(child)) { michael@0: element->ClearFocus(); michael@0: } else { michael@0: element->SetFocusInternal((LONG_PTR)child.get()); michael@0: element.Get()->QueryInterface(IID_PPV_ARGS(retVal)); michael@0: } michael@0: michael@0: return S_OK; michael@0: } michael@0: michael@0: // IRawElementProviderFragment michael@0: michael@0: HRESULT michael@0: UIABridge::Navigate(NavigateDirection direction, IRawElementProviderFragment ** retVal) michael@0: { michael@0: LogFunction(); michael@0: if (!Connected()) { michael@0: return UIA_E_ELEMENTNOTAVAILABLE; michael@0: } michael@0: *retVal = nullptr; michael@0: michael@0: switch(direction) { michael@0: case NavigateDirection_Parent: michael@0: BridgeLog("UIABridge::Navigate NavigateDirection_Parent"); michael@0: break; michael@0: case NavigateDirection_NextSibling: michael@0: BridgeLog("UIABridge::Navigate NavigateDirection_NextSibling"); michael@0: break; michael@0: case NavigateDirection_PreviousSibling: michael@0: BridgeLog("UIABridge::Navigate NavigateDirection_PreviousSibling"); michael@0: break; michael@0: case NavigateDirection_FirstChild: michael@0: BridgeLog("UIABridge::Navigate NavigateDirection_FirstChild"); michael@0: gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal)); michael@0: break; michael@0: case NavigateDirection_LastChild: michael@0: BridgeLog("UIABridge::Navigate NavigateDirection_LastChild"); michael@0: gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal)); michael@0: break; michael@0: } michael@0: michael@0: // For the other directions (parent, next, previous) the default of nullptr is correct michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIABridge::GetRuntimeId(SAFEARRAY ** retVal) michael@0: { michael@0: LogFunction(); michael@0: if (!Connected()) { michael@0: return UIA_E_ELEMENTNOTAVAILABLE; michael@0: } michael@0: michael@0: int runtimeId[2] = { UiaAppendRuntimeId, 1 }; // always 1 michael@0: *retVal = SafeArrayCreateVector(VT_I4, 0, ARRAYSIZE(runtimeId)); michael@0: if (*retVal != nullptr) { michael@0: for (long index = 0; index < ARRAYSIZE(runtimeId); ++index) { michael@0: SafeArrayPutElement(*retVal, &index, &runtimeId[index]); michael@0: } michael@0: } else { michael@0: return E_OUTOFMEMORY; michael@0: } michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIABridge::get_BoundingRectangle(UiaRect * retVal) michael@0: { michael@0: LogFunction(); michael@0: if (!Connected() || !mWindow) { michael@0: return UIA_E_ELEMENTNOTAVAILABLE; michael@0: } michael@0: michael@0: // returns logical pixels michael@0: Rect bounds; michael@0: mWindow->get_Bounds(&bounds); michael@0: michael@0: // we need to return physical pixels michael@0: retVal->left = WinUtils::LogToPhys(bounds.X); michael@0: retVal->top = WinUtils::LogToPhys(bounds.Y); michael@0: retVal->width = WinUtils::LogToPhys(bounds.Width); michael@0: retVal->height = WinUtils::LogToPhys(bounds.Height); michael@0: michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIABridge::GetEmbeddedFragmentRoots(SAFEARRAY ** retVal) michael@0: { michael@0: if (!Connected()) { michael@0: return UIA_E_ELEMENTNOTAVAILABLE; michael@0: } michael@0: // doesn't apply according to msdn. michael@0: *retVal = nullptr; michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIABridge::SetFocus() michael@0: { michael@0: LogFunction(); michael@0: if (!Connected()) { michael@0: return UIA_E_ELEMENTNOTAVAILABLE; michael@0: } michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIABridge::get_FragmentRoot(IRawElementProviderFragmentRoot ** retVal) michael@0: { michael@0: // we are the fragment root. Our children return us for this call. michael@0: return QueryInterface(IID_PPV_ARGS(retVal)); michael@0: } michael@0: michael@0: // IRawElementProviderSimple michael@0: michael@0: HRESULT michael@0: UIABridge::get_ProviderOptions(ProviderOptions * pRetVal) michael@0: { michael@0: LogFunction(); michael@0: if (!Connected()) { michael@0: return E_FAIL; michael@0: } michael@0: *pRetVal = ProviderOptions_ServerSideProvider | michael@0: ProviderOptions_UseComThreading | michael@0: ProviderOptions_UseClientCoordinates; michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIABridge::GetPatternProvider(PATTERNID patternId, IUnknown **ppRetVal) michael@0: { michael@0: LogFunction(); michael@0: BridgeLog("UIABridge::GetPatternProvider=%d", patternId); michael@0: michael@0: // The root window doesn't support any specific pattern michael@0: *ppRetVal = nullptr; michael@0: michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIABridge::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal) michael@0: { michael@0: pRetVal->vt = VT_EMPTY; michael@0: michael@0: switch (idProp) { michael@0: case UIA_AutomationIdPropertyId: michael@0: BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_AutomationIdPropertyId"); michael@0: break; michael@0: case UIA_ControlTypePropertyId: michael@0: BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_ControlTypePropertyId"); michael@0: break; michael@0: case UIA_IsKeyboardFocusablePropertyId: michael@0: BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsKeyboardFocusablePropertyId"); michael@0: break; michael@0: case UIA_IsContentElementPropertyId: michael@0: BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsContentElementPropertyId"); michael@0: break; michael@0: case UIA_IsControlElementPropertyId: michael@0: BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsControlElementPropertyId"); michael@0: break; michael@0: case UIA_IsEnabledPropertyId: michael@0: BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsEnabledPropertyId"); michael@0: break; michael@0: case UIA_HasKeyboardFocusPropertyId: michael@0: BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_HasKeyboardFocusPropertyId"); michael@0: break; michael@0: case UIA_NamePropertyId: michael@0: BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_NamePropertyId"); michael@0: break; michael@0: case UIA_IsPasswordPropertyId: michael@0: BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsPasswordPropertyId"); michael@0: break; michael@0: case UIA_NativeWindowHandlePropertyId: michael@0: BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_NativeWindowHandlePropertyId"); michael@0: break; michael@0: default: michael@0: BridgeLog("UIABridge::GetPropertyValue: idProp=%d", idProp); michael@0: break; michael@0: } michael@0: michael@0: if (!Connected()) { michael@0: return E_FAIL; michael@0: } michael@0: michael@0: switch (idProp) { michael@0: case UIA_AutomationIdPropertyId: michael@0: pRetVal->bstrVal = SysAllocString(L"MozillaAccessibilityBridge0001"); michael@0: pRetVal->vt = VT_BSTR; michael@0: break; michael@0: michael@0: case UIA_ControlTypePropertyId: michael@0: pRetVal->vt = VT_I4; michael@0: pRetVal->lVal = UIA_WindowControlTypeId; michael@0: break; michael@0: michael@0: case UIA_IsKeyboardFocusablePropertyId: michael@0: case UIA_IsContentElementPropertyId: michael@0: case UIA_IsControlElementPropertyId: michael@0: case UIA_IsEnabledPropertyId: michael@0: pRetVal->boolVal = VARIANT_TRUE; michael@0: pRetVal->vt = VT_BOOL; michael@0: break; michael@0: michael@0: case UIA_HasKeyboardFocusPropertyId: michael@0: pRetVal->vt = VT_BOOL; michael@0: pRetVal->boolVal = VARIANT_FALSE; michael@0: break; michael@0: michael@0: case UIA_NamePropertyId: michael@0: pRetVal->bstrVal = SysAllocString(L"MozillaAccessibilityBridge"); michael@0: pRetVal->vt = VT_BSTR; michael@0: break; michael@0: michael@0: case UIA_IsPasswordPropertyId: michael@0: pRetVal->vt = VT_BOOL; michael@0: pRetVal->boolVal = VARIANT_FALSE; michael@0: break; michael@0: michael@0: case UIA_NativeWindowHandlePropertyId: michael@0: pRetVal->vt = VT_I4; michael@0: pRetVal->lVal = (LONG)MetroWidget::GetICoreWindowHWND(); michael@0: break; michael@0: michael@0: default: michael@0: BridgeLog("UIABridge: Unhandled property"); michael@0: break; michael@0: } michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIABridge::get_HostRawElementProvider(IRawElementProviderSimple **ppRetVal) michael@0: { michael@0: // We only have this in the root bridge - this is our parent ICoreWindow. michael@0: *ppRetVal = nullptr; michael@0: if (mWindow != nullptr) { michael@0: IInspectable *pHostAsInspectable = nullptr; michael@0: if (SUCCEEDED(mWindow->get_AutomationHostProvider(&pHostAsInspectable))) { michael@0: pHostAsInspectable->QueryInterface(ppRetVal); michael@0: pHostAsInspectable->Release(); michael@0: } michael@0: } michael@0: return S_OK; michael@0: } michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: // Element michael@0: michael@0: HRESULT michael@0: UIATextElement::SetFocusInternal(LONG_PTR aAccessible) michael@0: { michael@0: LogFunction(); michael@0: #if defined(ACCESSIBILITY) michael@0: NS_ASSERTION(mAccessItem, "Bad accessible pointer"); michael@0: if (mAccessItem == (nsIAccessible*)aAccessible) { michael@0: return E_UNEXPECTED; michael@0: } michael@0: mAccessItem = (nsIAccessible*)aAccessible; michael@0: return S_OK; michael@0: #endif michael@0: return E_FAIL; michael@0: } michael@0: michael@0: HRESULT michael@0: UIATextElement::ClearFocus() michael@0: { michael@0: LogFunction(); michael@0: mAccessItem = nullptr; michael@0: return S_OK; michael@0: } michael@0: michael@0: // IRawElementProviderFragment michael@0: michael@0: HRESULT michael@0: UIATextElement::Navigate(NavigateDirection direction, IRawElementProviderFragment ** retVal) michael@0: { michael@0: LogFunction(); michael@0: michael@0: *retVal = nullptr; michael@0: switch(direction) { michael@0: case NavigateDirection_Parent: michael@0: gProviderRoot.Get()->QueryInterface(IID_PPV_ARGS(retVal)); michael@0: break; michael@0: case NavigateDirection_NextSibling: michael@0: break; michael@0: case NavigateDirection_PreviousSibling: michael@0: break; michael@0: case NavigateDirection_FirstChild: michael@0: break; michael@0: case NavigateDirection_LastChild: michael@0: break; michael@0: } michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIATextElement::GetRuntimeId(SAFEARRAY ** retVal) michael@0: { michael@0: LogFunction(); michael@0: int runtimeId[2] = { UiaAppendRuntimeId, mIndexID }; michael@0: *retVal = SafeArrayCreateVector(VT_I4, 0, ARRAYSIZE(runtimeId)); michael@0: if (*retVal != nullptr) { michael@0: for (long index = 0; index < ARRAYSIZE(runtimeId); ++index) { michael@0: SafeArrayPutElement(*retVal, &index, &runtimeId[index]); michael@0: } michael@0: } else { michael@0: return E_OUTOFMEMORY; michael@0: } michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIATextElement::get_BoundingRectangle(UiaRect * retVal) michael@0: { michael@0: LogFunction(); michael@0: michael@0: if (!mAccessItem) { michael@0: return UIA_E_ELEMENTNOTAVAILABLE; michael@0: } michael@0: michael@0: // bounds are in physical pixels michael@0: int32_t docX = 0, docY = 0, docWidth = 0, docHeight = 0; michael@0: mAccessItem->GetBounds(&docX, &docY, &docWidth, &docHeight); michael@0: michael@0: retVal->left = (float)docX; michael@0: retVal->top = (float)docY; michael@0: retVal->width = (float)docWidth; michael@0: retVal->height = (float)docHeight; michael@0: michael@0: BridgeLog("get_BoundingRectangle: left=%d top=%d right=%d bottom=%d", docX, docY, docX + docWidth, docY + docHeight); michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIATextElement::GetEmbeddedFragmentRoots(SAFEARRAY ** retVal) michael@0: { michael@0: *retVal = nullptr; michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIATextElement::SetFocus() michael@0: { michael@0: LogFunction(); michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIATextElement::get_FragmentRoot(IRawElementProviderFragmentRoot ** retVal) michael@0: { michael@0: return gProviderRoot.Get()->QueryInterface(IID_PPV_ARGS(retVal)); michael@0: } michael@0: michael@0: // IRawElementProviderSimple michael@0: michael@0: HRESULT michael@0: UIATextElement::get_ProviderOptions(ProviderOptions * pRetVal) michael@0: { michael@0: *pRetVal = ProviderOptions_ServerSideProvider | michael@0: ProviderOptions_UseComThreading | michael@0: ProviderOptions_UseClientCoordinates; michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIATextElement::GetPatternProvider(PATTERNID patternId, IUnknown **ppRetVal) michael@0: { michael@0: LogFunction(); michael@0: BridgeLog("UIATextElement::GetPatternProvider=%d", patternId); michael@0: michael@0: // UIA_ValuePatternId - 10002 michael@0: // UIA_TextPatternId - 10014 michael@0: // UIA_TextChildPatternId - 10029 michael@0: michael@0: *ppRetVal = nullptr; michael@0: if (patternId == UIA_TextPatternId) { michael@0: BridgeLog("** TextPattern requested from element."); michael@0: *ppRetVal = static_cast(this); michael@0: AddRef(); michael@0: return S_OK; michael@0: } else if (patternId == UIA_ValuePatternId) { michael@0: BridgeLog("** ValuePattern requested from element."); michael@0: *ppRetVal = static_cast(this); michael@0: AddRef(); michael@0: return S_OK; michael@0: } michael@0: michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIATextElement::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal) michael@0: { michael@0: pRetVal->vt = VT_EMPTY; michael@0: michael@0: // native hwnd, we don't have one for elements michael@0: if (idProp == 30020) { michael@0: return S_OK; michael@0: } michael@0: michael@0: switch (idProp) { michael@0: case UIA_AutomationIdPropertyId: michael@0: BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_AutomationIdPropertyId"); michael@0: break; michael@0: case UIA_ControlTypePropertyId: michael@0: BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_ControlTypePropertyId"); michael@0: break; michael@0: case UIA_IsKeyboardFocusablePropertyId: michael@0: BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsKeyboardFocusablePropertyId"); michael@0: break; michael@0: case UIA_IsContentElementPropertyId: michael@0: BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsContentElementPropertyId"); michael@0: break; michael@0: case UIA_IsControlElementPropertyId: michael@0: BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsControlElementPropertyId"); michael@0: break; michael@0: case UIA_IsEnabledPropertyId: michael@0: BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsEnabledPropertyId"); michael@0: break; michael@0: case UIA_HasKeyboardFocusPropertyId: michael@0: BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_HasKeyboardFocusPropertyId"); michael@0: break; michael@0: case UIA_NamePropertyId: michael@0: BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_NamePropertyId"); michael@0: break; michael@0: case UIA_IsPasswordPropertyId: michael@0: BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsPasswordPropertyId"); michael@0: break; michael@0: default: michael@0: BridgeLog("UIATextElement::GetPropertyValue: idProp=%d", idProp); michael@0: break; michael@0: } michael@0: michael@0: switch (idProp) { michael@0: case UIA_AutomationIdPropertyId: michael@0: pRetVal->bstrVal = SysAllocString(L"MozillaDocument0001"); michael@0: pRetVal->vt = VT_BSTR; michael@0: break; michael@0: michael@0: case UIA_ControlTypePropertyId: michael@0: pRetVal->vt = VT_I4; michael@0: pRetVal->lVal = UIA_EditControlTypeId; michael@0: break; michael@0: michael@0: case UIA_IsTextPatternAvailablePropertyId: michael@0: case UIA_IsKeyboardFocusablePropertyId: michael@0: case UIA_IsContentElementPropertyId: michael@0: case UIA_IsControlElementPropertyId: michael@0: case UIA_IsEnabledPropertyId: michael@0: pRetVal->boolVal = VARIANT_TRUE; michael@0: pRetVal->vt = VT_BOOL; michael@0: break; michael@0: michael@0: case UIA_LocalizedControlTypePropertyId: michael@0: case UIA_LabeledByPropertyId: michael@0: break; michael@0: michael@0: case UIA_HasKeyboardFocusPropertyId: michael@0: { michael@0: if (mAccessItem) { michael@0: uint32_t state, extraState; michael@0: if (NS_SUCCEEDED(mAccessItem->GetState(&state, &extraState)) && michael@0: (state & nsIAccessibleStates::STATE_FOCUSED)) { michael@0: pRetVal->vt = VT_BOOL; michael@0: pRetVal->boolVal = VARIANT_TRUE; michael@0: return S_OK; michael@0: } michael@0: } michael@0: pRetVal->vt = VT_BOOL; michael@0: pRetVal->boolVal = VARIANT_FALSE; michael@0: break; michael@0: } michael@0: michael@0: case UIA_NamePropertyId: michael@0: pRetVal->bstrVal = SysAllocString(L"MozillaDocument"); michael@0: pRetVal->vt = VT_BSTR; michael@0: break; michael@0: michael@0: case UIA_IsPasswordPropertyId: michael@0: pRetVal->vt = VT_BOOL; michael@0: pRetVal->boolVal = VARIANT_FALSE; michael@0: break; michael@0: michael@0: default: michael@0: BridgeLog("UIATextElement: Unhandled property"); michael@0: break; michael@0: } michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: UIATextElement::get_HostRawElementProvider(IRawElementProviderSimple **ppRetVal) michael@0: { michael@0: *ppRetVal = nullptr; michael@0: return S_OK; michael@0: } michael@0: michael@0: // ITextProvider michael@0: michael@0: HRESULT michael@0: UIATextElement::GetSelection(SAFEARRAY * *pRetVal) michael@0: { michael@0: LogFunction(); michael@0: return E_NOTIMPL; michael@0: } michael@0: michael@0: HRESULT michael@0: UIATextElement::GetVisibleRanges(SAFEARRAY * *pRetVal) michael@0: { michael@0: LogFunction(); michael@0: return E_NOTIMPL; michael@0: } michael@0: michael@0: HRESULT michael@0: UIATextElement::RangeFromChild(IRawElementProviderSimple *childElement, ITextRangeProvider **pRetVal) michael@0: { michael@0: LogFunction(); michael@0: return E_NOTIMPL; michael@0: } michael@0: michael@0: HRESULT michael@0: UIATextElement::RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal) michael@0: { michael@0: LogFunction(); michael@0: return E_NOTIMPL; michael@0: } michael@0: michael@0: HRESULT michael@0: UIATextElement::get_DocumentRange(ITextRangeProvider **pRetVal) michael@0: { michael@0: LogFunction(); michael@0: return E_NOTIMPL; michael@0: } michael@0: michael@0: HRESULT michael@0: UIATextElement::get_SupportedTextSelection(SupportedTextSelection *pRetVal) michael@0: { michael@0: LogFunction(); michael@0: return E_NOTIMPL; michael@0: } michael@0: michael@0: // IValueProvider michael@0: michael@0: IFACEMETHODIMP michael@0: UIATextElement::SetValue(LPCWSTR val) michael@0: { michael@0: LogFunction(); michael@0: return E_NOTIMPL; michael@0: } michael@0: michael@0: IFACEMETHODIMP michael@0: UIATextElement::get_Value(BSTR *pRetVal) michael@0: { michael@0: LogFunction(); michael@0: return E_NOTIMPL; michael@0: } michael@0: michael@0: IFACEMETHODIMP michael@0: UIATextElement::get_IsReadOnly(BOOL *pRetVal) michael@0: { michael@0: LogFunction(); michael@0: *pRetVal = FALSE; michael@0: return S_OK; michael@0: } michael@0: michael@0: } } }