diff --git a/browser/metro/base/content/input.js b/browser/metro/base/content/input.js index e0bedf39d11c..7693d84a7692 100644 --- a/browser/metro/base/content/input.js +++ b/browser/metro/base/content/input.js @@ -1037,14 +1037,10 @@ var GestureModule = { */ var InputSourceHelper = { isPrecise: false, - touchIsActive: false, init: function ish_init() { - window.addEventListener("mousemove", this, true); - window.addEventListener("mousedown", this, true); - window.addEventListener("touchstart", this, true); - window.addEventListener("touchend", this, true); - window.addEventListener("touchcancel", this, true); + Services.obs.addObserver(this, "metro_precise_input", false); + Services.obs.addObserver(this, "metro_imprecise_input", false); }, _precise: function () { @@ -1061,37 +1057,17 @@ var InputSourceHelper = { } }, - handleEvent: function ish_handleEvent(aEvent) { - switch(aEvent.type) { - case "touchstart": + observe: function BrowserUI_observe(aSubject, aTopic, aData) { + switch (aTopic) { + case "metro_precise_input": + this._precise(); + break; + case "metro_imprecise_input": this._imprecise(); - this.touchIsActive = true; - break; - case "touchend": - case "touchcancel": - this.touchIsActive = false; - break; - default: - // Ignore mouse movement when touch is active. Prevents both mouse scrollbars - // and touch scrollbars from displaying at the same time. Also works around - // odd win8 bug involving an erant mousemove event after a touch sequence - // starts (bug 896017). - if (this.touchIsActive) { - return; - } - - switch (aEvent.mozInputSource) { - case Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE: - case Ci.nsIDOMMouseEvent.MOZ_SOURCE_PEN: - case Ci.nsIDOMMouseEvent.MOZ_SOURCE_ERASER: - case Ci.nsIDOMMouseEvent.MOZ_SOURCE_CURSOR: - this._precise(); - break; - } break; } }, - + fireUpdate: function fireUpdate() { if (this.isPrecise) { this._fire("MozPrecisePointer"); diff --git a/widget/windows/winrt/MetroInput.cpp b/widget/windows/winrt/MetroInput.cpp index 2318b2ff5277..5d96780f4c97 100644 --- a/widget/windows/winrt/MetroInput.cpp +++ b/widget/windows/winrt/MetroInput.cpp @@ -206,6 +206,7 @@ MetroInput::MetroInput(MetroWidget* aWidget, UI::Core::ICoreWindow* aWindow) : mWidget(aWidget), mChromeHitTestCacheForTouch(false), + mCurrentInputLevel(LEVEL_IMPRECISE), mWindow(aWindow) { LogFunction(); @@ -240,6 +241,51 @@ MetroInput::~MetroInput() UnregisterInputEvents(); } + +/** + * Tracks the current input level (precise/imprecise) and fires an observer + * when the mode changes. + */ +void +MetroInput::UpdateInputLevel(InputPrecisionLevel aInputLevel) +{ + // ignore mouse input if we have active touch input. + if (aInputLevel == LEVEL_PRECISE && mTouches.Count() > 0) { + return; + } + if (mCurrentInputLevel != aInputLevel) { + mCurrentInputLevel = aInputLevel; + MetroUtils::FireObserver(mCurrentInputLevel == LEVEL_PRECISE ? + "metro_precise_input" : "metro_imprecise_input"); + } +} + +/** + * Processes an IEdgeGestureEventArgs and returns the input source type + * for the event. Also updates input level via UpdateInputLevel. + */ +uint16_t +MetroInput::ProcessInputTypeForGesture(UI::Input::IEdgeGestureEventArgs* aArgs) +{ + MOZ_ASSERT(aArgs); + UI::Input::EdgeGestureKind kind; + aArgs->get_Kind(&kind); + switch(kind) { + case UI::Input::EdgeGestureKind::EdgeGestureKind_Touch: + UpdateInputLevel(LEVEL_PRECISE); + return nsIDOMMouseEvent::MOZ_SOURCE_TOUCH; + break; + case UI::Input::EdgeGestureKind::EdgeGestureKind_Keyboard: + return nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD; + break; + case UI::Input::EdgeGestureKind::EdgeGestureKind_Mouse: + UpdateInputLevel(LEVEL_IMPRECISE); + return nsIDOMMouseEvent::MOZ_SOURCE_MOUSE; + break; + } + return nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN; +} + /** * When the user swipes her/his finger in from the top of the screen, * we receive this event. @@ -263,8 +309,7 @@ MetroInput::OnEdgeGestureStarted(UI::Input::IEdgeGesture* sender, mModifierKeyState.Update(); mModifierKeyState.InitInputEvent(geckoEvent); geckoEvent.time = ::GetMessageTime(); - - geckoEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH; + geckoEvent.inputSource = ProcessInputTypeForGesture(aArgs); // Safe DispatchEventIgnoreStatus(&geckoEvent); @@ -295,8 +340,7 @@ MetroInput::OnEdgeGestureCanceled(UI::Input::IEdgeGesture* sender, mModifierKeyState.Update(); mModifierKeyState.InitInputEvent(geckoEvent); geckoEvent.time = ::GetMessageTime(); - - geckoEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH; + geckoEvent.inputSource = ProcessInputTypeForGesture(aArgs); // Safe DispatchEventIgnoreStatus(&geckoEvent); @@ -326,15 +370,7 @@ MetroInput::OnEdgeGestureCompleted(UI::Input::IEdgeGesture* sender, mModifierKeyState.Update(); mModifierKeyState.InitInputEvent(geckoEvent); geckoEvent.time = ::GetMessageTime(); - - UI::Input::EdgeGestureKind value; - aArgs->get_Kind(&value); - - if (value == UI::Input::EdgeGestureKind::EdgeGestureKind_Keyboard) { - geckoEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD; - } else { - geckoEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH; - } + geckoEvent.inputSource = ProcessInputTypeForGesture(aArgs); // Safe DispatchEventIgnoreStatus(&geckoEvent); @@ -391,6 +427,7 @@ MetroInput::OnPointerNonTouch(UI::Input::IPointerPoint* aPoint) { event->message = NS_MOUSE_BUTTON_UP; break; } + UpdateInputLevel(LEVEL_PRECISE); InitGeckoMouseEventFromPointerPoint(event, aPoint); DispatchAsyncEventIgnoreStatus(event); } @@ -430,6 +467,8 @@ MetroInput::OnPointerPressed(UI::Core::ICoreWindow* aSender, } // This is touch input. + UpdateInputLevel(LEVEL_IMPRECISE); + // Create the new touch point and add it to our event. uint32_t pointerId; currentPoint->get_PointerId(&pointerId); @@ -517,6 +556,8 @@ MetroInput::OnPointerMoved(UI::Core::ICoreWindow* aSender, } // This is touch input. + UpdateInputLevel(LEVEL_IMPRECISE); + // Get the touch associated with this touch point. uint32_t pointerId; currentPoint->get_PointerId(&pointerId); @@ -614,6 +655,8 @@ MetroInput::OnPointerReleased(UI::Core::ICoreWindow* aSender, } // This is touch input. + UpdateInputLevel(LEVEL_IMPRECISE); + // Get the touch associated with this touch point. uint32_t pointerId; currentPoint->get_PointerId(&pointerId); @@ -748,9 +791,11 @@ MetroInput::OnPointerEntered(UI::Core::ICoreWindow* aSender, WidgetMouseEvent* event = new WidgetMouseEvent(true, NS_MOUSE_ENTER, mWidget.Get(), WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal); + UpdateInputLevel(LEVEL_PRECISE); InitGeckoMouseEventFromPointerPoint(event, currentPoint.Get()); DispatchAsyncEventIgnoreStatus(event); } + UpdateInputLevel(LEVEL_IMPRECISE); return S_OK; } @@ -779,9 +824,11 @@ MetroInput::OnPointerExited(UI::Core::ICoreWindow* aSender, WidgetMouseEvent* event = new WidgetMouseEvent(true, NS_MOUSE_EXIT, mWidget.Get(), WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal); + UpdateInputLevel(LEVEL_PRECISE); InitGeckoMouseEventFromPointerPoint(event, currentPoint.Get()); DispatchAsyncEventIgnoreStatus(event); } + UpdateInputLevel(LEVEL_IMPRECISE); return S_OK; } diff --git a/widget/windows/winrt/MetroInput.h b/widget/windows/winrt/MetroInput.h index 6b38c00f01f8..f676b384263a 100644 --- a/widget/windows/winrt/MetroInput.h +++ b/widget/windows/winrt/MetroInput.h @@ -155,6 +155,14 @@ private: ModifierKeyState mModifierKeyState; + // Tracking input level + enum InputPrecisionLevel { + LEVEL_PRECISE, + LEVEL_IMPRECISE + }; + InputPrecisionLevel mCurrentInputLevel; + void UpdateInputLevel(InputPrecisionLevel aInputLevel); + // Initialization/Uninitialization helpers void RegisterInputEvents(); void UnregisterInputEvents(); @@ -174,6 +182,7 @@ private: Point const& aPosition, uint32_t aMagEventType, uint32_t aRotEventType); + uint16_t ProcessInputTypeForGesture(IEdgeGestureEventArgs* aArgs); // The W3C spec states that "whether preventDefault has been called" should // be tracked on a per-touchpoint basis, but it also states that touchstart