diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp index c35493b67fd9..c9ea91a63721 100644 --- a/dom/events/EventStateManager.cpp +++ b/dom/events/EventStateManager.cpp @@ -3119,6 +3119,14 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext, if (pluginFrame) { MOZ_ASSERT(pluginFrame->WantsToHandleWheelEventAsDefaultAction()); action = WheelPrefs::ACTION_SEND_TO_PLUGIN; + } else if (nsLayoutUtils::IsScrollFrameWithSnapping(frameToScroll)) { + // If the target has scroll-snapping points then we want to handle + // the wheel event on the main thread even if we have APZ enabled. Do + // so and let the APZ know that it should ignore this event. + if (wheelEvent->mFlags.mHandledByAPZ) { + wheelEvent->mFlags.mDefaultPrevented = true; + } + action = WheelPrefs::GetInstance()->ComputeActionFor(wheelEvent); } else if (wheelEvent->mFlags.mHandledByAPZ) { action = WheelPrefs::ACTION_NONE; } else { diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index e8bd59fdb49c..9250d8fba219 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -3281,6 +3281,12 @@ nsDisplayLayerEventRegions::AddFrame(nsDisplayListBuilder* aBuilder, if (pluginFrame && pluginFrame->WantsToHandleWheelEventAsDefaultAction()) { mDispatchToContentHitRegion.Or(mDispatchToContentHitRegion, borderBox); } + } else if (gfxPlatform::GetPlatform()->SupportsApzWheelInput() && + nsLayoutUtils::IsScrollFrameWithSnapping(aFrame->GetParent())) { + // If the frame is the inner content of a scrollable frame with snap-points + // then we want to handle wheel events for it on the main thread. Add it to + // the d-t-c region so that APZ waits for the main thread. + mDispatchToContentHitRegion.Or(mDispatchToContentHitRegion, borderBox); } // Touch action region diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 007e7867730d..8b1255a1f52e 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -8676,3 +8676,15 @@ nsLayoutUtils::GetSelectionBoundingRect(Selection* aSel) return res; } + +/* static */ bool +nsLayoutUtils::IsScrollFrameWithSnapping(nsIFrame* aFrame) +{ + nsIScrollableFrame* sf = do_QueryFrame(aFrame); + if (!sf) { + return false; + } + ScrollbarStyles styles = sf->GetScrollbarStyles(); + return styles.mScrollSnapTypeY != NS_STYLE_SCROLL_SNAP_TYPE_NONE || + styles.mScrollSnapTypeX != NS_STYLE_SCROLL_SNAP_TYPE_NONE; +} diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 9b2ce653025b..3b4416dda690 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -2773,6 +2773,12 @@ public: * @param aSel Selection to check */ static nsRect GetSelectionBoundingRect(mozilla::dom::Selection* aSel); + + /** + * Returns true if the given frame is a scrollframe and it has snap points. + */ + static bool IsScrollFrameWithSnapping(nsIFrame* aFrame); + private: static uint32_t sFontSizeInflationEmPerLine; static uint32_t sFontSizeInflationMinTwips;