diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index 823d92c19624..4789d738f212 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -1919,36 +1919,8 @@ void nsChildView::DispatchAPZWheelInputEvent(InputData& aEvent, bool aCanTrigger return; } - PanGestureInput& panInput = aEvent.AsPanGestureInput(); - - event = panInput.ToWidgetEvent(this); - if (aCanTriggerSwipe && panInput.mOverscrollBehaviorAllowsSwipe) { - SwipeInfo swipeInfo = SendMayStartSwipe(panInput); - event.mCanTriggerSwipe = swipeInfo.wantsSwipe; - if (swipeInfo.wantsSwipe) { - if (result.GetStatus() == nsEventStatus_eIgnore) { - // APZ has determined and that scrolling horizontally in the - // requested direction is impossible, so it didn't do any - // scrolling for the event. - // We know now that MayStartSwipe wants a swipe, so we can start - // the swipe now. - TrackScrollEventAsSwipe(panInput, swipeInfo.allowedDirections); - } else { - // We don't know whether this event can start a swipe, so we need - // to queue up events and wait for a call to ReportSwipeStarted. - // APZ might already have started scrolling in response to the - // event if it knew that it's the right thing to do. In that case - // we'll still get a call to ReportSwipeStarted, and we will - // discard the queued events at that point. - mSwipeEventQueue = - MakeUnique(swipeInfo.allowedDirections, result.mInputBlockId); - } - } - } - - if (mSwipeEventQueue && mSwipeEventQueue->inputBlockId == result.mInputBlockId) { - mSwipeEventQueue->queuedEvents.AppendElement(panInput); - } + event = MayStartSwipeForAPZ(aEvent.AsPanGestureInput(), result, + CanTriggerSwipe{aCanTriggerSwipe}); break; } case SCROLLWHEEL_INPUT: { @@ -1977,48 +1949,10 @@ void nsChildView::DispatchAPZWheelInputEvent(InputData& aEvent, bool aCanTrigger nsEventStatus status; switch (aEvent.mInputType) { case PANGESTURE_INPUT: { - PanGestureInput panInput = aEvent.AsPanGestureInput(); - if (panInput.mType == PanGestureInput::PANGESTURE_MAYSTART || - panInput.mType == PanGestureInput::PANGESTURE_START) { - mCurrentPanGestureBelongsToSwipe = false; - } - if (mCurrentPanGestureBelongsToSwipe) { - // Ignore this event. It's a momentum event from a scroll gesture - // that was processed as a swipe, and the swipe animation has - // already finished (so mSwipeTracker is already null). - MOZ_ASSERT(panInput.IsMomentum(), - "If the fingers are still on the touchpad, we should still have a SwipeTracker, " - "and it should have consumed this event."); - return; - } - - event = panInput.ToWidgetEvent(this); - if (aCanTriggerSwipe) { - SwipeInfo swipeInfo = SendMayStartSwipe(panInput); - - // We're in the non-APZ case here, but we still want to know whether - // the event was routed to a child process, so we use InputAPZContext - // to get that piece of information. - ScrollableLayerGuid guid; - InputAPZContext context(guid, 0, nsEventStatus_eIgnore); - - event.mCanTriggerSwipe = swipeInfo.wantsSwipe; - DispatchEvent(&event, status); - if (swipeInfo.wantsSwipe) { - if (context.WasRoutedToChildProcess()) { - // We don't know whether this event can start a swipe, so we need - // to queue up events and wait for a call to ReportSwipeStarted. - mSwipeEventQueue = MakeUnique(swipeInfo.allowedDirections, 0); - } else if (event.TriggersSwipe()) { - TrackScrollEventAsSwipe(panInput, swipeInfo.allowedDirections); - } - } - - if (mSwipeEventQueue && mSwipeEventQueue->inputBlockId == 0) { - mSwipeEventQueue->queuedEvents.AppendElement(panInput); - } + if (MayStartSwipeForNonAPZ(aEvent.AsPanGestureInput(), CanTriggerSwipe{aCanTriggerSwipe})) { return; } + event = aEvent.AsPanGestureInput().ToWidgetEvent(this); break; } case SCROLLWHEEL_INPUT: { diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index 51d367d32a18..5bffe19b0c9d 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -2114,6 +2114,94 @@ nsBaseWidget::SwipeInfo nsBaseWidget::SendMayStartSwipe( return result; } +WidgetWheelEvent nsBaseWidget::MayStartSwipeForAPZ( + const PanGestureInput& aPanInput, const APZEventResult& aApzResult, + CanTriggerSwipe aCanTriggerSwipe) { + WidgetWheelEvent event = aPanInput.ToWidgetEvent(this); + if (aCanTriggerSwipe == CanTriggerSwipe::Yes && + aPanInput.mOverscrollBehaviorAllowsSwipe) { + SwipeInfo swipeInfo = SendMayStartSwipe(aPanInput); + event.mCanTriggerSwipe = swipeInfo.wantsSwipe; + if (swipeInfo.wantsSwipe) { + if (aApzResult.GetStatus() == nsEventStatus_eIgnore) { + // APZ has determined and that scrolling horizontally in the + // requested direction is impossible, so it didn't do any + // scrolling for the event. + // We know now that MayStartSwipe wants a swipe, so we can start + // the swipe now. + TrackScrollEventAsSwipe(aPanInput, swipeInfo.allowedDirections); + } else { + // We don't know whether this event can start a swipe, so we need + // to queue up events and wait for a call to ReportSwipeStarted. + // APZ might already have started scrolling in response to the + // event if it knew that it's the right thing to do. In that case + // we'll still get a call to ReportSwipeStarted, and we will + // discard the queued events at that point. + mSwipeEventQueue = MakeUnique( + swipeInfo.allowedDirections, aApzResult.mInputBlockId); + } + } + } + + if (mSwipeEventQueue && + mSwipeEventQueue->inputBlockId == aApzResult.mInputBlockId) { + mSwipeEventQueue->queuedEvents.AppendElement(aPanInput); + } + + return event; +} + +bool nsBaseWidget::MayStartSwipeForNonAPZ(const PanGestureInput& aPanInput, + CanTriggerSwipe aCanTriggerSwipe) { + if (aPanInput.mType == PanGestureInput::PANGESTURE_MAYSTART || + aPanInput.mType == PanGestureInput::PANGESTURE_START) { + mCurrentPanGestureBelongsToSwipe = false; + } + if (mCurrentPanGestureBelongsToSwipe) { + // Ignore this event. It's a momentum event from a scroll gesture + // that was processed as a swipe, and the swipe animation has + // already finished (so mSwipeTracker is already null). + MOZ_ASSERT(aPanInput.IsMomentum(), + "If the fingers are still on the touchpad, we should still have " + "a SwipeTracker, " + "and it should have consumed this event."); + return true; + } + + if (aCanTriggerSwipe == CanTriggerSwipe::No) { + return false; + } + + SwipeInfo swipeInfo = SendMayStartSwipe(aPanInput); + + // We're in the non-APZ case here, but we still want to know whether + // the event was routed to a child process, so we use InputAPZContext + // to get that piece of information. + ScrollableLayerGuid guid; + InputAPZContext context(guid, 0, nsEventStatus_eIgnore); + + WidgetWheelEvent event = aPanInput.ToWidgetEvent(this); + event.mCanTriggerSwipe = swipeInfo.wantsSwipe; + nsEventStatus status; + DispatchEvent(&event, status); + if (swipeInfo.wantsSwipe) { + if (context.WasRoutedToChildProcess()) { + // We don't know whether this event can start a swipe, so we need + // to queue up events and wait for a call to ReportSwipeStarted. + mSwipeEventQueue = + MakeUnique(swipeInfo.allowedDirections, 0); + } else if (event.TriggersSwipe()) { + TrackScrollEventAsSwipe(aPanInput, swipeInfo.allowedDirections); + } + } + + if (mSwipeEventQueue && mSwipeEventQueue->inputBlockId == 0) { + mSwipeEventQueue->queuedEvents.AppendElement(aPanInput); + } + + return true; +} + const IMENotificationRequests& nsIWidget::IMENotificationRequestsRef() { TextEventDispatcher* dispatcher = GetTextEventDispatcher(); return dispatcher->IMENotificationRequestsRef(); diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index 3985f6f9feb0..aea5a1602c9a 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -40,6 +40,7 @@ class LiveResizeListener; class FallbackRenderer; class SwipeTracker; struct SwipeEventQueue; +class WidgetWheelEvent; #ifdef ACCESSIBILITY namespace a11y { @@ -335,6 +336,21 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference { uint32_t allowedDirections; }; SwipeInfo SendMayStartSwipe(const mozilla::PanGestureInput& aSwipeStartEvent); + enum class CanTriggerSwipe : bool { + No = false, + Yes = true, + }; + // Returns a WidgetWheelEvent which needs to be handled by APZ regardless of + // whether |aPanInput| event was used for SwipeTracker or not. + mozilla::WidgetWheelEvent MayStartSwipeForAPZ( + const mozilla::PanGestureInput& aPanInput, + const mozilla::layers::APZEventResult& aApzResult, + CanTriggerSwipe aCanTriggerSwipe); + + // Returns true if |aPanInput| event was used for SwipeTracker, false + // otherwise. + bool MayStartSwipeForNonAPZ(const mozilla::PanGestureInput& aPanInput, + CanTriggerSwipe aCanTriggerSwipe); void NotifyWindowDestroyed(); void NotifySizeMoveDone();