diff --git a/layout/generic/ScrollbarActivity.cpp b/layout/generic/ScrollbarActivity.cpp index e1e86ef657b..dbe0faca144 100644 --- a/layout/generic/ScrollbarActivity.cpp +++ b/layout/generic/ScrollbarActivity.cpp @@ -14,16 +14,31 @@ #include "nsAString.h" #include "nsQueryFrame.h" #include "nsComponentManagerUtils.h" +#include "mozilla/LookAndFeel.h" namespace mozilla { namespace layout { NS_IMPL_ISUPPORTS1(ScrollbarActivity, nsIDOMEventListener) +void +ScrollbarActivity::QueryLookAndFeelVals() +{ + // Fade animation constants + mScrollbarFadeBeginDelay = + LookAndFeel::GetInt(LookAndFeel::eIntID_ScrollbarFadeBeginDelay); + mScrollbarFadeDuration = + LookAndFeel::GetInt(LookAndFeel::eIntID_ScrollbarFadeDuration); + // Controls whether we keep the mouse move listener so we can display the + // scrollbars whenever the user moves the mouse within the scroll area. + mDisplayOnMouseMove = + LookAndFeel::GetInt(LookAndFeel::eIntID_ScrollbarDisplayOnMouseMove); +} + void ScrollbarActivity::Destroy() { - StopListeningForEvents(); + StopListeningForEvents(true); UnregisterFromRefreshDriver(); CancelFadeBeginTimer(); } @@ -74,7 +89,7 @@ ScrollbarActivity::ActivityStopped() NS_IMETHODIMP ScrollbarActivity::HandleEvent(nsIDOMEvent* aEvent) { - if (!mIsActive) + if (!mDisplayOnMouseMove && !mIsActive) return NS_OK; nsAutoString type; @@ -153,26 +168,78 @@ ScrollbarActivity::HandleEventForScrollbar(const nsAString& aType, void ScrollbarActivity::StartListeningForEvents() { - if (mListeningForEvents) + StartListeningForScrollbarEvents(); + StartListeningForScrollAreaEvents(); +} + +void +ScrollbarActivity::StopListeningForEvents(bool aIsTeardown) +{ + StopListeningForScrollbarEvents(); + StopListeningForScrollAreaEvents(aIsTeardown); +} + +void +ScrollbarActivity::StartListeningForScrollbarEvents() +{ + if (mListeningForScrollbarEvents) return; - nsIFrame* scrollArea = do_QueryFrame(mScrollableFrame); - nsCOMPtr scrollAreaTarget = do_QueryInterface( - scrollArea->GetContent()); mHorizontalScrollbar = do_QueryInterface(GetHorizontalScrollbar()); mVerticalScrollbar = do_QueryInterface(GetVerticalScrollbar()); + AddScrollbarEventListeners(mHorizontalScrollbar); + AddScrollbarEventListeners(mVerticalScrollbar); + + mListeningForScrollbarEvents = true; +} + +void +ScrollbarActivity::StopListeningForScrollbarEvents() +{ + if (!mListeningForScrollAreaEvents) + return; + + RemoveScrollbarEventListeners(mHorizontalScrollbar); + RemoveScrollbarEventListeners(mVerticalScrollbar); + + mHorizontalScrollbar = nullptr; + mVerticalScrollbar = nullptr; + mListeningForScrollbarEvents = false; +} + +void +ScrollbarActivity::StartListeningForScrollAreaEvents() +{ + if (mListeningForScrollAreaEvents) + return; + + nsIFrame* scrollArea = do_QueryFrame(mScrollableFrame); + nsCOMPtr scrollAreaTarget + = do_QueryInterface(scrollArea->GetContent()); if (scrollAreaTarget) { scrollAreaTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), this, true); } - StartListeningForEventsOnScrollbar(mHorizontalScrollbar); - StartListeningForEventsOnScrollbar(mVerticalScrollbar); - mListeningForEvents = true; + mListeningForScrollAreaEvents = true; } void -ScrollbarActivity::StartListeningForEventsOnScrollbar(nsIDOMEventTarget* aScrollbar) +ScrollbarActivity::StopListeningForScrollAreaEvents(bool aIsTeardown) +{ + if ((mListeningForScrollAreaEvents && !mDisplayOnMouseMove) || + (mListeningForScrollAreaEvents && mDisplayOnMouseMove && aIsTeardown)) { + nsIFrame* scrollArea = do_QueryFrame(mScrollableFrame); + nsCOMPtr scrollAreaTarget = do_QueryInterface(scrollArea->GetContent()); + if (scrollAreaTarget) { + scrollAreaTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"), this, true); + } + mListeningForScrollAreaEvents = false; + } +} + +void +ScrollbarActivity::AddScrollbarEventListeners(nsIDOMEventTarget* aScrollbar) { if (aScrollbar) { aScrollbar->AddEventListener(NS_LITERAL_STRING("mousedown"), this, true); @@ -183,27 +250,7 @@ ScrollbarActivity::StartListeningForEventsOnScrollbar(nsIDOMEventTarget* aScroll } void -ScrollbarActivity::StopListeningForEvents() -{ - if (!mListeningForEvents) - return; - - nsIFrame* scrollArea = do_QueryFrame(mScrollableFrame); - nsCOMPtr scrollAreaTarget = do_QueryInterface(scrollArea->GetContent()); - - if (scrollAreaTarget) { - scrollAreaTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"), this, true); - } - StopListeningForEventsOnScrollbar(mHorizontalScrollbar); - StopListeningForEventsOnScrollbar(mVerticalScrollbar); - - mHorizontalScrollbar = nullptr; - mVerticalScrollbar = nullptr; - mListeningForEvents = false; -} - -void -ScrollbarActivity::StopListeningForEventsOnScrollbar(nsIDOMEventTarget* aScrollbar) +ScrollbarActivity::RemoveScrollbarEventListeners(nsIDOMEventTarget* aScrollbar) { if (aScrollbar) { aScrollbar->RemoveEventListener(NS_LITERAL_STRING("mousedown"), this, true); @@ -242,7 +289,7 @@ ScrollbarActivity::EndFade() } SetIsActive(false); UnregisterFromRefreshDriver(); - StopListeningForEvents(); + StopListeningForEvents(false); NS_ASSERTION(!mIsActive, "should have gone inactive after fade end"); NS_ASSERTION(!mIsFading, "shouldn't be fading anymore"); @@ -372,10 +419,11 @@ ScrollbarActivity::SetIsFading(bool aNewFading) void ScrollbarActivity::StartFadeBeginTimer() { - NS_ASSERTION(!mFadeBeginTimer, "timer already alive!"); - mFadeBeginTimer = do_CreateInstance("@mozilla.org/timer;1"); + if (!mFadeBeginTimer) { + mFadeBeginTimer = do_CreateInstance("@mozilla.org/timer;1"); + } mFadeBeginTimer->InitWithFuncCallback(FadeBeginTimerFired, this, - kScrollbarFadeBeginDelay, + mScrollbarFadeBeginDelay, nsITimer::TYPE_ONE_SHOT); } @@ -384,7 +432,6 @@ ScrollbarActivity::CancelFadeBeginTimer() { if (mFadeBeginTimer) { mFadeBeginTimer->Cancel(); - mFadeBeginTimer = nullptr; } } diff --git a/layout/generic/ScrollbarActivity.h b/layout/generic/ScrollbarActivity.h index 84f89af79f5..b025e97002a 100644 --- a/layout/generic/ScrollbarActivity.h +++ b/layout/generic/ScrollbarActivity.h @@ -63,10 +63,16 @@ public: , mNestedActivityCounter(0) , mIsActive(false) , mIsFading(false) - , mListeningForEvents(false) + , mListeningForScrollbarEvents(false) + , mListeningForScrollAreaEvents(false) + , mDisplayOnMouseMove(false) , mHScrollbarHovered(false) , mVScrollbarHovered(false) - {} + , mScrollbarFadeBeginDelay(0) + , mScrollbarFadeDuration(0) + { + QueryLookAndFeelVals(); + } NS_DECL_ISUPPORTS NS_DECL_NSIDOMEVENTLISTENER @@ -85,14 +91,12 @@ public: reinterpret_cast(aSelf)->BeginFade(); } - static const uint32_t kScrollbarFadeBeginDelay = 450; // milliseconds - static const uint32_t kScrollbarFadeDuration = 200; // milliseconds - protected: bool IsActivityOngoing() { return mNestedActivityCounter > 0; } bool IsStillFading(TimeStamp aTime); + void QueryLookAndFeelVals(); void HandleEventForScrollbar(const nsAString& aType, nsIContent* aTarget, @@ -107,10 +111,17 @@ protected: void StartFadeBeginTimer(); void CancelFadeBeginTimer(); + void StartListeningForEvents(); - void StartListeningForEventsOnScrollbar(nsIDOMEventTarget* aScrollbar); - void StopListeningForEvents(); - void StopListeningForEventsOnScrollbar(nsIDOMEventTarget* aScrollbar); + void StopListeningForEvents(bool aIsTeardown); + + void StartListeningForScrollbarEvents(); + void StopListeningForScrollbarEvents(); + void StartListeningForScrollAreaEvents(); + void StopListeningForScrollAreaEvents(bool aIsTeardown); + void AddScrollbarEventListeners(nsIDOMEventTarget* aScrollbar); + void RemoveScrollbarEventListeners(nsIDOMEventTarget* aScrollbar); + void RegisterWithRefreshDriver(); void UnregisterFromRefreshDriver(); @@ -122,8 +133,8 @@ protected: nsIContent* GetHorizontalScrollbar() { return GetScrollbarContent(false); } nsIContent* GetVerticalScrollbar() { return GetScrollbarContent(true); } - static const TimeDuration FadeDuration() { - return TimeDuration::FromMilliseconds(kScrollbarFadeDuration); + const TimeDuration FadeDuration() { + return TimeDuration::FromMilliseconds(mScrollbarFadeDuration); } nsIScrollbarOwner* mScrollableFrame; @@ -134,9 +145,15 @@ protected: int mNestedActivityCounter; bool mIsActive; bool mIsFading; - bool mListeningForEvents; + bool mListeningForScrollbarEvents; + bool mListeningForScrollAreaEvents; bool mHScrollbarHovered; bool mVScrollbarHovered; + + // LookAndFeel values we load on creation + bool mDisplayOnMouseMove; + int mScrollbarFadeBeginDelay; + int mScrollbarFadeDuration; }; } // namespace layout diff --git a/toolkit/themes/windows/global/xulscrollbars.css b/toolkit/themes/windows/global/xulscrollbars.css index 5a4d9fd78f1..666a8a1556b 100644 --- a/toolkit/themes/windows/global/xulscrollbars.css +++ b/toolkit/themes/windows/global/xulscrollbars.css @@ -23,6 +23,18 @@ scrollbar[orient="vertical"] -moz-appearance: scrollbartrack-vertical; } +@media all and (-moz-overlay-scrollbars) { + scrollbar { + position: relative; + z-index: 2147483647; + } + + scrollbar:not([active="true"]), + scrollbar[disabled="true"] { + visibility: hidden; + } +} + /* ::::: borders for thumb and buttons ::::: */ thumb, diff --git a/widget/LookAndFeel.h b/widget/LookAndFeel.h index 9f168c15ed5..f63fc5e0915 100644 --- a/widget/LookAndFeel.h +++ b/widget/LookAndFeel.h @@ -361,7 +361,7 @@ public: */ eIntID_ScrollbarButtonAutoRepeatBehavior, /** - * Dealy before showing a tooltip. + * Delay before showing a tooltip. */ eIntID_TooltipDelay, /* @@ -375,7 +375,19 @@ public: * home button. Used on gaia to determine whether a home button * is shown. */ - eIntID_PhysicalHomeButton + eIntID_PhysicalHomeButton, + + /* + * Controls whether overlay scrollbars display when the user moves + * the mouse in a scrollable frame. + */ + eIntID_ScrollbarDisplayOnMouseMove, + + /* + * Overlay scrollbar animation constants. + */ + eIntID_ScrollbarFadeBeginDelay, + eIntID_ScrollbarFadeDuration }; /** diff --git a/widget/cocoa/nsLookAndFeel.mm b/widget/cocoa/nsLookAndFeel.mm index 9fb1c9a8f0b..853c3fd9992 100644 --- a/widget/cocoa/nsLookAndFeel.mm +++ b/widget/cocoa/nsLookAndFeel.mm @@ -358,6 +358,15 @@ nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult) case eIntID_AllowOverlayScrollbarsOverlap: aResult = AllowOverlayScrollbarsOverlap() ? 1 : 0; break; + case eIntID_ScrollbarDisplayOnMouseMove: + aResult = 0; + break; + case eIntID_ScrollbarFadeBeginDelay: + aResult = 450; + break; + case eIntID_ScrollbarFadeDuration: + aResult = 200; + break; case eIntID_TreeOpenDelay: aResult = 1000; break; diff --git a/widget/windows/nsLookAndFeel.cpp b/widget/windows/nsLookAndFeel.cpp index 4a374fe199e..1374f187297 100644 --- a/widget/windows/nsLookAndFeel.cpp +++ b/widget/windows/nsLookAndFeel.cpp @@ -482,6 +482,21 @@ nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult) case eIntID_SwipeAnimationEnabled: aResult = 0; break; + case eIntID_UseOverlayScrollbars: + aResult = (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro); + break; + case eIntID_AllowOverlayScrollbarsOverlap: + aResult = 0; + break; + case eIntID_ScrollbarDisplayOnMouseMove: + aResult = 1; + break; + case eIntID_ScrollbarFadeBeginDelay: + aResult = 2500; + break; + case eIntID_ScrollbarFadeDuration: + aResult = 350; + break; default: aResult = 0; res = NS_ERROR_FAILURE; diff --git a/widget/xpwidgets/nsXPLookAndFeel.cpp b/widget/xpwidgets/nsXPLookAndFeel.cpp index 1032bb3e8a2..bd5fe687c18 100644 --- a/widget/xpwidgets/nsXPLookAndFeel.cpp +++ b/widget/xpwidgets/nsXPLookAndFeel.cpp @@ -51,6 +51,15 @@ nsLookAndFeelIntPref nsXPLookAndFeel::sIntPrefs[] = { "ui.useOverlayScrollbars", eIntID_UseOverlayScrollbars, false, 0 }, + { "ui.scrollbarDisplayOnMouseMove", + eIntID_ScrollbarDisplayOnMouseMove, + false, 0 }, + { "ui.scrollbarFadeBeginDelay", + eIntID_ScrollbarFadeBeginDelay, + false, 0 }, + { "ui.scrollbarFadeDuration", + eIntID_ScrollbarFadeDuration, + false, 0 }, { "ui.showHideScrollbars", eIntID_ShowHideScrollbars, false, 0 },