diff --git a/widget/windows/winrt/FrameworkView.cpp b/widget/windows/winrt/FrameworkView.cpp index e955c74e89d8..f4878363f273 100644 --- a/widget/windows/winrt/FrameworkView.cpp +++ b/widget/windows/winrt/FrameworkView.cpp @@ -368,6 +368,7 @@ FrameworkView::OnSoftkeyboardHidden(IInputPane* aSender, sKeyboardIsVisible = false; memset(&sKeyboardRect, 0, sizeof(Rect)); MetroUtils::FireObserver("metro_softkeyboard_hidden"); + aArgs->put_EnsuredFocusedElementInView(true); return S_OK; } @@ -381,6 +382,7 @@ FrameworkView::OnSoftkeyboardShown(IInputPane* aSender, sKeyboardIsVisible = true; aSender->get_OccludedRect(&sKeyboardRect); MetroUtils::FireObserver("metro_softkeyboard_shown"); + aArgs->put_EnsuredFocusedElementInView(true); return S_OK; } @@ -500,9 +502,14 @@ HRESULT FrameworkView::OnAutomationProviderRequested(ICoreWindow* aSender, IAutomationProviderRequestedEventArgs* aArgs) { + LogFunction(); if (!EnsureAutomationProviderCreated()) return E_FAIL; - aArgs->put_AutomationProvider(mAutomationProvider.Get()); + Log("OnAutomationProviderRequested %X", mAutomationProvider.Get()); + HRESULT hr = aArgs->put_AutomationProvider(mAutomationProvider.Get()); + if (FAILED(hr)) { + Log("put failed? %X", hr); + } return S_OK; } diff --git a/widget/windows/winrt/MetroAppShell.cpp b/widget/windows/winrt/MetroAppShell.cpp index 5ec1823209bf..c3761db3ec0d 100644 --- a/widget/windows/winrt/MetroAppShell.cpp +++ b/widget/windows/winrt/MetroAppShell.cpp @@ -124,12 +124,14 @@ ProcessNativeEvents(CoreProcessEventsOption eventOption) dispatcher->ProcessEvents(eventOption); } +// static void MetroAppShell::ProcessOneNativeEventIfPresent() { ProcessNativeEvents(CoreProcessEventsOption::CoreProcessEventsOption_ProcessOneIfPresent); } +// static void MetroAppShell::ProcessAllNativeEventsPresent() { diff --git a/widget/windows/winrt/MetroInput.cpp b/widget/windows/winrt/MetroInput.cpp index 9ab2f0e3287b..08a4ae62887e 100644 --- a/widget/windows/winrt/MetroInput.cpp +++ b/widget/windows/winrt/MetroInput.cpp @@ -10,6 +10,7 @@ #include "nsTArray.h" // Touch lists #include "nsIDOMSimpleGestureEvent.h" // Constants for gesture events #include "InputData.h" +#include "UIABridgePrivate.h" // System headers (alphabetical) #include // ABI::Window::UI::Core namespace diff --git a/widget/windows/winrt/MetroWidget.cpp b/widget/windows/winrt/MetroWidget.cpp index c3901c829e41..16cb3b6694b7 100644 --- a/widget/windows/winrt/MetroWidget.cpp +++ b/widget/windows/winrt/MetroWidget.cpp @@ -29,6 +29,7 @@ #ifdef MOZ_CRASHREPORTER #include "nsExceptionHandler.h" #endif +#include "UIABridgePrivate.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; @@ -54,8 +55,18 @@ extern PRLogModuleInfo* gWindowsLog; static uint32_t gInstanceCount = 0; const PRUnichar* kMetroSubclassThisProp = L"MetroSubclassThisProp"; +HWND MetroWidget::sICoreHwnd = NULL; static const UINT sDefaultBrowserMsgID = RegisterWindowMessageW(L"DefaultBrowserClosing"); +// WM_GETOBJECT id pulled from uia headers +#define UiaRootObjectId -25 + +namespace mozilla { +namespace widget { +namespace winrt { +extern ComPtr gProviderRoot; +} } } + namespace { void SendInputs(uint32_t aModifiers, INPUT* aExtraInputs, uint32_t aExtraInputsLen) @@ -675,6 +686,30 @@ MetroWidget::WindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLPara break; } + case WM_GETOBJECT: + { + DWORD dwObjId = (LPARAM)(DWORD) aLParam; + // Passing this to CallWindowProc can result in a failure due to a timing issue + // in winrt core window server code, so we call it directly here. Also, it's not + // clear Windows::UI::Core::WindowServer::OnAutomationProviderRequestedEvent is + // compatible with metro enabled desktop browsers, it makes an initial call to + // UiaReturnRawElementProvider passing the return result from FrameworkView + // OnAutomationProviderRequested as the hwnd (me scratches head) which results in + // GetLastError always being set to invalid handle (6) after CallWindowProc returns. + if (dwObjId == UiaRootObjectId) { + NS_ASSERTION(gProviderRoot.Get(), "gProviderRoot is null??"); + ComPtr simple; + gProviderRoot.As(&simple); + LRESULT res = UiaReturnRawElementProvider(aWnd, aWParam, aLParam, simple.Get()); + if (res) { + return res; + } + NS_ASSERTION(res, "UiaReturnRawElementProvider failed!"); + Log("UiaReturnRawElementProvider failed! GetLastError=%X", GetLastError()); + } + break; + } + default: { if (aWParam == WM_USER_TSF_TEXTCHANGE) { @@ -717,6 +752,7 @@ MetroWidget::FindMetroWindow() // subclass it SetSubclass(); + sICoreHwnd = mWnd; return; } diff --git a/widget/windows/winrt/MetroWidget.h b/widget/windows/winrt/MetroWidget.h index 46859d7652bd..7aa27491865b 100644 --- a/widget/windows/winrt/MetroWidget.h +++ b/widget/windows/winrt/MetroWidget.h @@ -66,6 +66,8 @@ public: NS_DECL_ISUPPORTS_INHERITED + static HWND GetICoreWindowHWND() { return sICoreHwnd; } + // nsWindowBase virtual void InitEvent(nsGUIEvent& aEvent, nsIntPoint* aPoint = nullptr) MOZ_OVERRIDE; virtual bool DispatchWindowEvent(nsGUIEvent* aEvent) MOZ_OVERRIDE; @@ -232,6 +234,7 @@ protected: nsIntRegion mInvalidatedRegion; nsCOMPtr mIdleService; HWND mWnd; + static HWND sICoreHwnd; WNDPROC mMetroWndProc; bool mTempBasicLayerInUse; Microsoft::WRL::ComPtr mMetroInput; diff --git a/widget/windows/winrt/UIABridge.cpp b/widget/windows/winrt/UIABridge.cpp index b50549b4510f..dbf4f4406854 100644 --- a/widget/windows/winrt/UIABridge.cpp +++ b/widget/windows/winrt/UIABridge.cpp @@ -6,6 +6,7 @@ #include "UIABridge.h" #include "MetroUtils.h" #include "UIABridgePrivate.h" +#include "MetroWidget.h" #include #include @@ -35,7 +36,6 @@ using namespace ABI::Windows::System; const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} MIDL_DEFINE_GUID(IID, IID_IUIABridge, 0xc78b35b5, 0x5db, 0x43aa, 0xae, 0x73, 0x94, 0xc2, 0x33, 0xa9, 0x3c, 0x98); - namespace mozilla { namespace widget { namespace winrt { @@ -43,7 +43,7 @@ namespace winrt { #define ProviderOptions_UseClientCoordinates (ProviderOptions)0x100 static int gIDIndex = 2; -static ComPtr gProviderRoot = nullptr; +ComPtr gProviderRoot = nullptr; static ComPtr gElement = nullptr; HRESULT @@ -113,6 +113,8 @@ UIABridge::Disconnect() mAccessible = nullptr; #endif mWindow = nullptr; + gElement = nullptr; + gProviderRoot = nullptr; return S_OK; } @@ -155,7 +157,7 @@ static bool ChildHasFocus(nsCOMPtr& aChild) { Accessible* access = (Accessible*)aChild.get(); - Log("Focus element flags: %d %d %d", + Log("Focus element flags: editable:%d focusable:%d readonly:%d", ((access->NativeState() & mozilla::a11y::states::EDITABLE) > 0), ((access->NativeState() & mozilla::a11y::states::FOCUSABLE) > 0), ((access->NativeState() & mozilla::a11y::states::READONLY) > 0)); @@ -163,37 +165,10 @@ ChildHasFocus(nsCOMPtr& aChild) ((access->NativeState() & mozilla::a11y::states::READONLY) == 0)); } -// Accessibility calls here to let us know about focus related changes. -// The only event we are concerned with is lost focus, so that we can -// signal UIA that the focus on our child has been lost. HRESULT UIABridge::FocusChangeEvent() { LogFunction(); - - if (!Connected()) { - return UIA_E_ELEMENTNOTAVAILABLE; - } - - nsCOMPtr child; - nsresult rv = mAccessible->GetFocusedChild(getter_AddRefs(child)); - if (!child) { - return S_OK; - } - - DumpChildInfo(child); - - if (!ChildHasFocus(child)) { - ComPtr element; - gElement.As(&element); - if (!element) { - return S_OK; - } - - element->ClearFocus(); - UiaRaiseAutomationEvent(this, UIA_AutomationFocusChangedEventId); - } - return S_OK; } @@ -225,6 +200,7 @@ UIABridge::GetFocus(IRawElementProviderFragment ** retVal) nsCOMPtr child; nsresult rv = mAccessible->GetFocusedChild(getter_AddRefs(child)); if (!child) { + Log("mAccessible->GetFocusedChild failed."); return S_OK; } @@ -233,6 +209,7 @@ UIABridge::GetFocus(IRawElementProviderFragment ** retVal) ComPtr element; gElement.As(&element); if (!element) { + Log("gElement as IUIAElement failed."); return S_OK; } @@ -259,15 +236,20 @@ UIABridge::Navigate(NavigateDirection direction, IRawElementProviderFragment ** switch(direction) { case NavigateDirection_Parent: + Log("UIABridge::Navigate NavigateDirection_Parent"); break; case NavigateDirection_NextSibling: + Log("UIABridge::Navigate NavigateDirection_NextSibling"); break; case NavigateDirection_PreviousSibling: + Log("UIABridge::Navigate NavigateDirection_PreviousSibling"); break; case NavigateDirection_FirstChild: + Log("UIABridge::Navigate NavigateDirection_FirstChild"); gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal)); break; case NavigateDirection_LastChild: + Log("UIABridge::Navigate NavigateDirection_LastChild"); gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal)); break; } @@ -279,6 +261,7 @@ UIABridge::Navigate(NavigateDirection direction, IRawElementProviderFragment ** HRESULT UIABridge::GetRuntimeId(SAFEARRAY ** retVal) { + LogFunction(); if (!Connected()) { return UIA_E_ELEMENTNOTAVAILABLE; } @@ -349,6 +332,7 @@ UIABridge::get_FragmentRoot(IRawElementProviderFragmentRoot ** retVal) HRESULT UIABridge::get_ProviderOptions(ProviderOptions * pRetVal) { + LogFunction(); if (!Connected()) { return E_FAIL; } @@ -373,16 +357,44 @@ UIABridge::GetPatternProvider(PATTERNID patternId, IUnknown **ppRetVal) HRESULT UIABridge::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal) { - LogFunction(); pRetVal->vt = VT_EMPTY; - // native hwnd - if (idProp == 30020) { - return S_OK; + switch (idProp) { + case UIA_AutomationIdPropertyId: + Log("UIABridge::GetPropertyValue: idProp=UIA_AutomationIdPropertyId"); + break; + case UIA_ControlTypePropertyId: + Log("UIABridge::GetPropertyValue: idProp=UIA_ControlTypePropertyId"); + break; + case UIA_IsKeyboardFocusablePropertyId: + Log("UIABridge::GetPropertyValue: idProp=UIA_IsKeyboardFocusablePropertyId"); + break; + case UIA_IsContentElementPropertyId: + Log("UIABridge::GetPropertyValue: idProp=UIA_IsContentElementPropertyId"); + break; + case UIA_IsControlElementPropertyId: + Log("UIABridge::GetPropertyValue: idProp=UIA_IsControlElementPropertyId"); + break; + case UIA_IsEnabledPropertyId: + Log("UIABridge::GetPropertyValue: idProp=UIA_IsEnabledPropertyId"); + break; + case UIA_HasKeyboardFocusPropertyId: + Log("UIABridge::GetPropertyValue: idProp=UIA_HasKeyboardFocusPropertyId"); + break; + case UIA_NamePropertyId: + Log("UIABridge::GetPropertyValue: idProp=UIA_NamePropertyId"); + break; + case UIA_IsPasswordPropertyId: + Log("UIABridge::GetPropertyValue: idProp=UIA_IsPasswordPropertyId"); + break; + case UIA_NativeWindowHandlePropertyId: + Log("UIABridge::GetPropertyValue: idProp=UIA_NativeWindowHandlePropertyId"); + break; + default: + Log("UIABridge::GetPropertyValue: idProp=%d", idProp); + break; } - Log("UIABridge::GetPropertyValue: idProp=%d", idProp); - if (!Connected()) { return E_FAIL; } @@ -422,6 +434,8 @@ UIABridge::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal) break; case UIA_NativeWindowHandlePropertyId: + pRetVal->vt = VT_I4; + pRetVal->lVal = (LONG)MetroWidget::GetICoreWindowHWND(); break; default: @@ -455,6 +469,9 @@ UIATextElement::SetFocusInternal(LONG_PTR aAccessible) LogFunction(); #if defined(ACCESSIBILITY) NS_ASSERTION(mAccessItem, "Bad accessible pointer"); + if (mAccessItem == (nsIAccessible*)aAccessible) { + return E_UNEXPECTED; + } mAccessItem = (nsIAccessible*)aAccessible; return S_OK; #endif @@ -496,6 +513,7 @@ UIATextElement::Navigate(NavigateDirection direction, IRawElementProviderFragmen HRESULT UIATextElement::GetRuntimeId(SAFEARRAY ** retVal) { + LogFunction(); int runtimeId[2] = { UiaAppendRuntimeId, mIndexID }; *retVal = SafeArrayCreateVector(VT_I4, 0, ARRAYSIZE(runtimeId)); if (*retVal != nullptr) { @@ -520,10 +538,13 @@ UIATextElement::get_BoundingRectangle(UiaRect * retVal) // bounds are in physical pixels int32_t docX = 0, docY = 0, docWidth = 0, docHeight = 0; mAccessItem->GetBounds(&docX, &docY, &docWidth, &docHeight); + retVal->left = (float)docX; retVal->top = (float)docY; retVal->width = (float)docWidth; retVal->height = (float)docHeight; + + Log("get_BoundingRectangle: left=%d top=%d right=%d bottom=%d", docX, docY, docX + docWidth, docY + docHeight); return S_OK; } @@ -587,15 +608,45 @@ UIATextElement::GetPatternProvider(PATTERNID patternId, IUnknown **ppRetVal) HRESULT UIATextElement::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal) { - LogFunction(); pRetVal->vt = VT_EMPTY; - // native hwnd + // native hwnd, we don't have one for elements if (idProp == 30020) { return S_OK; } - Log("UIATextElement::GetPropertyValue: idProp=%d", idProp); + switch (idProp) { + case UIA_AutomationIdPropertyId: + Log("UIATextElement::GetPropertyValue: idProp=UIA_AutomationIdPropertyId"); + break; + case UIA_ControlTypePropertyId: + Log("UIATextElement::GetPropertyValue: idProp=UIA_ControlTypePropertyId"); + break; + case UIA_IsKeyboardFocusablePropertyId: + Log("UIATextElement::GetPropertyValue: idProp=UIA_IsKeyboardFocusablePropertyId"); + break; + case UIA_IsContentElementPropertyId: + Log("UIATextElement::GetPropertyValue: idProp=UIA_IsContentElementPropertyId"); + break; + case UIA_IsControlElementPropertyId: + Log("UIATextElement::GetPropertyValue: idProp=UIA_IsControlElementPropertyId"); + break; + case UIA_IsEnabledPropertyId: + Log("UIATextElement::GetPropertyValue: idProp=UIA_IsEnabledPropertyId"); + break; + case UIA_HasKeyboardFocusPropertyId: + Log("UIATextElement::GetPropertyValue: idProp=UIA_HasKeyboardFocusPropertyId"); + break; + case UIA_NamePropertyId: + Log("UIATextElement::GetPropertyValue: idProp=UIA_NamePropertyId"); + break; + case UIA_IsPasswordPropertyId: + Log("UIATextElement::GetPropertyValue: idProp=UIA_IsPasswordPropertyId"); + break; + default: + Log("UIATextElement::GetPropertyValue: idProp=%d", idProp); + break; + } switch (idProp) { case UIA_AutomationIdPropertyId: @@ -605,7 +656,7 @@ UIATextElement::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal) case UIA_ControlTypePropertyId: pRetVal->vt = VT_I4; - pRetVal->lVal = UIA_DocumentControlTypeId; + pRetVal->lVal = UIA_EditControlTypeId; break; case UIA_IsTextPatternAvailablePropertyId: