From 8657ceea273a452bd8c054af02c9424681753e6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 13 Oct 2019 09:16:26 +0000 Subject: [PATCH] Bug 1584859 - Make smooth scrolling conditional on reduced motion settings. r=dbaron We could put this change itself behind a pref too, if we considered that worth it. But probably not so. Differential Revision: https://phabricator.services.mozilla.com/D48010 --HG-- extra : moz-landing-system : lando --- gfx/layers/apz/src/APZInputBridge.cpp | 3 ++- gfx/layers/apz/src/AsyncPanZoomController.cpp | 2 +- layout/base/nsLayoutUtils.cpp | 19 +++++++++++++++++++ layout/base/nsLayoutUtils.h | 9 +++++++++ layout/generic/nsGfxScrollFrame.cpp | 10 +++++----- layout/generic/nsGfxScrollFrame.h | 2 -- modules/libpref/init/StaticPrefList.yaml | 2 ++ widget/cocoa/nsChildView.mm | 3 ++- widget/nsXPLookAndFeel.cpp | 3 +++ 9 files changed, 43 insertions(+), 10 deletions(-) diff --git a/gfx/layers/apz/src/APZInputBridge.cpp b/gfx/layers/apz/src/APZInputBridge.cpp index c5e16b227eda..6eed50916dbb 100644 --- a/gfx/layers/apz/src/APZInputBridge.cpp +++ b/gfx/layers/apz/src/APZInputBridge.cpp @@ -19,6 +19,7 @@ #include "mozilla/TouchEvents.h" // for WidgetTouchEvent #include "mozilla/WheelHandlingHelper.h" // for WheelDeltaHorizontalizer, // WheelDeltaAdjustmentStrategy +#include "nsLayoutUtils.h" // for IsSmoothScrollingEnabled namespace mozilla { namespace layers { @@ -116,7 +117,7 @@ APZEventResult APZInputBridge::ReceiveInputEvent(WidgetInputEvent& aEvent) { if (Maybe action = ActionForWheelEvent(&wheelEvent)) { ScrollWheelInput::ScrollMode scrollMode = ScrollWheelInput::SCROLLMODE_INSTANT; - if (StaticPrefs::general_smoothScroll() && + if (nsLayoutUtils::IsSmoothScrollingEnabled() && ((wheelEvent.mDeltaMode == dom::WheelEvent_Binding::DOM_DELTA_LINE && StaticPrefs::general_smoothScroll_mouseWheel()) || diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 1de5b2a00be3..8e953daa1f2b 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -2006,7 +2006,7 @@ nsEventStatus AsyncPanZoomController::OnKeyboard(const KeyboardInput& aEvent) { MaybeAdjustDestinationForScrollSnapping(aEvent, destination); // If smooth scrolling is disabled, then scroll immediately to the destination - if (!StaticPrefs::general_smoothScroll()) { + if (!nsLayoutUtils::IsSmoothScrollingEnabled()) { CancelAnimation(); ParentLayerPoint startPoint, endPoint; diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 0c913183cd61..2425cf05703b 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -27,6 +27,7 @@ #include "mozilla/StaticPrefs_apz.h" #include "mozilla/StaticPrefs_dom.h" #include "mozilla/StaticPrefs_font.h" +#include "mozilla/StaticPrefs_general.h" #include "mozilla/StaticPrefs_gfx.h" #include "mozilla/StaticPrefs_layers.h" #include "mozilla/StaticPrefs_layout.h" @@ -7976,9 +7977,27 @@ size_t nsLayoutUtils::SizeOfTextRunsForFrames(nsIFrame* aFrame, return total; } +RelaxedAtomicBool nsLayoutUtils::gSmoothScrollingEnabled; + +void nsLayoutUtils::RecomputeSmoothScrollingEnabled() { + MOZ_RELEASE_ASSERT(NS_IsMainThread(), + "You don't really want to call into widget " + "off the main thread, do you?"); + gSmoothScrollingEnabled = + StaticPrefs::general_smoothScroll_DoNotUseDirectly() && + !LookAndFeel::GetInt(LookAndFeel::eIntID_PrefersReducedMotion, 0); +} + +static void SmoothScrollPrefChanged(const char*, void*) { + nsLayoutUtils::RecomputeSmoothScrollingEnabled(); +} + /* static */ void nsLayoutUtils::Initialize() { nsComputedDOMStyle::RegisterPrefChangeCallbacks(); + Preferences::RegisterCallbackAndCall( + SmoothScrollPrefChanged, + nsDependentCString(StaticPrefs::GetPrefName_general_smoothScroll())); } /* static */ diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 64b87b6199a1..f3180b25e82a 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -2998,7 +2998,16 @@ class nsLayoutUtils { static bool FrameIsMostlyScrolledOutOfViewInCrossProcess( const nsIFrame* aFrame, nscoord aMargin); + static bool IsSmoothScrollingEnabled() { + return gSmoothScrollingEnabled; + } + + static void RecomputeSmoothScrollingEnabled(); + private: + + static mozilla::RelaxedAtomicBool gSmoothScrollingEnabled; + /** * Helper function for LogTestDataForPaint(). */ diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 753c653ae7d4..39e9ac94ddc2 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -2026,10 +2026,6 @@ void ScrollFrameHelper::AsyncScroll::InitSmoothScroll( mAnimationPhysics->Update(aTime, aDestination, aCurrentVelocity); } -bool ScrollFrameHelper::IsSmoothScrollingEnabled() { - return StaticPrefs::general_smoothScroll(); -} - class ScrollFrameActivityTracker final : public nsExpirationTracker { public: @@ -2347,7 +2343,7 @@ void ScrollFrameHelper::ScrollToWithOrigin( ? presContext->RefreshDriver()->MostRecentRefresh() : TimeStamp::Now(); bool isSmoothScroll = - aMode == ScrollMode::Smooth && IsSmoothScrollingEnabled(); + aMode == ScrollMode::Smooth && nsLayoutUtils::IsSmoothScrollingEnabled(); nsSize currentVelocity(0, 0); @@ -7188,6 +7184,10 @@ bool ScrollFrameHelper::SmoothScrollVisual( } bool ScrollFrameHelper::IsSmoothScroll(dom::ScrollBehavior aBehavior) const { + if (!nsLayoutUtils::IsSmoothScrollingEnabled()) { + return false; + } + if (aBehavior == dom::ScrollBehavior::Smooth) { return true; } diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 0b124b56fee2..104a028bb823 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -116,8 +116,6 @@ class ScrollFrameHelper : public nsIReflowCallback { void PostScrolledAreaEvent(); void FireScrolledAreaEvent(); - bool IsSmoothScrollingEnabled(); - /** * @note This method might destroy the frame, pres shell and other objects. */ diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index 81f4d591d977..f10babb55735 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -2959,10 +2959,12 @@ value: true mirror: always +# Use nsLayoutUtils::SmoothScrollingEnabled() instead. - name: general.smoothScroll type: RelaxedAtomicBool value: true mirror: always + do_not_use_directly: true # This pref and general.smoothScroll.stopDecelerationWeighting determine # the timing function. diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index 30d22dd46841..515a98d18444 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -4705,7 +4705,8 @@ static gfx::IntPoint GetIntegerDeltaForEvent(NSEvent* aEvent) { geckoChildDeathGrip->DispatchAPZWheelInputEvent(wheelEvent, false); } else { ScrollWheelInput::ScrollMode scrollMode = ScrollWheelInput::SCROLLMODE_INSTANT; - if (StaticPrefs::general_smoothScroll() && StaticPrefs::general_smoothScroll_mouseWheel()) { + if (nsLayoutUtils::IsSmoothScrollingEnabled() && + StaticPrefs::general_smoothScroll_mouseWheel()) { scrollMode = ScrollWheelInput::SCROLLMODE_SMOOTH; } ScrollWheelInput wheelEvent(eventIntervalTime, eventTimeStamp, modifiers, scrollMode, diff --git a/widget/nsXPLookAndFeel.cpp b/widget/nsXPLookAndFeel.cpp index 6059143ebdca..9ea82ea43d67 100644 --- a/widget/nsXPLookAndFeel.cpp +++ b/widget/nsXPLookAndFeel.cpp @@ -11,6 +11,7 @@ #include "nsLookAndFeel.h" #include "HeadlessLookAndFeel.h" #include "nsCRT.h" +#include "nsLayoutUtils.h" #include "nsFont.h" #include "mozilla/dom/ContentChild.h" #include "mozilla/Preferences.h" @@ -993,6 +994,8 @@ void nsXPLookAndFeel::RefreshImpl() { for (i = 0; i < uint32_t(ColorID::End); ++i) { InitColorFromPref(i); } + + nsLayoutUtils::RecomputeSmoothScrollingEnabled(); } nsTArray nsXPLookAndFeel::GetIntCacheImpl() {