diff options
Diffstat (limited to 'layout/generic/ScrollbarActivity.h')
-rw-r--r-- | layout/generic/ScrollbarActivity.h | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/layout/generic/ScrollbarActivity.h b/layout/generic/ScrollbarActivity.h new file mode 100644 index 0000000000..26615eea81 --- /dev/null +++ b/layout/generic/ScrollbarActivity.h @@ -0,0 +1,164 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ScrollbarActivity_h___ +#define ScrollbarActivity_h___ + +#include "mozilla/Attributes.h" +#include "nsCOMPtr.h" +#include "nsIDOMEventListener.h" +#include "mozilla/TimeStamp.h" +#include "nsRefreshObservers.h" + +class nsIContent; +class nsIScrollbarMediator; +class nsITimer; +class nsRefreshDriver; + +namespace mozilla { + +namespace dom { +class Element; +class EventTarget; +} // namespace dom + +namespace layout { + +/** + * ScrollbarActivity + * + * This class manages scrollbar behavior that imitates the native Mac OS X + * Lion overlay scrollbar behavior: Scrollbars are only shown while "scrollbar + * activity" occurs, and they're hidden with a fade animation after a short + * delay. + * + * Scrollbar activity has these states: + * - inactive: + * Scrollbars are hidden. + * - ongoing activity: + * Scrollbars are visible and being operated on in some way, for example + * because they're hovered or pressed. + * - active, but waiting for fade out + * Scrollbars are still completely visible but are about to fade away. + * - fading out + * Scrollbars are subject to a fade-out animation. + * + * Initial scrollbar activity needs to be reported by the scrollbar holder that + * owns the ScrollbarActivity instance. This needs to happen via a call to + * ActivityOccurred(), for example when the current scroll position or the size + * of the scroll area changes. + * + * As soon as scrollbars are visible, the ScrollbarActivity class manages the + * rest of the activity behavior: It ensures that mouse motions inside the + * scroll area keep the scrollbars visible, and that scrollbars don't fade away + * while they're being hovered / dragged. It also sets a sticky hover attribute + * on the most recently hovered scrollbar. + * + * ScrollbarActivity falls into hibernation after the scrollbars have faded + * out. It only starts acting after the next call to ActivityOccurred() / + * ActivityStarted(). + */ + +class ScrollbarActivity final : public nsIDOMEventListener, + public nsARefreshObserver { + public: + explicit ScrollbarActivity(nsIScrollbarMediator* aScrollableFrame) + : mScrollableFrame(aScrollableFrame), + mNestedActivityCounter(0), + mIsActive(false), + mIsFading(false), + mListeningForScrollbarEvents(false), + mListeningForScrollAreaEvents(false), + mHScrollbarHovered(false), + mVScrollbarHovered(false), + mDisplayOnMouseMove(false), + mScrollbarFadeBeginDelay(0), + mScrollbarFadeDuration(0) { + QueryLookAndFeelVals(); + } + + NS_DECL_ISUPPORTS + NS_DECL_NSIDOMEVENTLISTENER + + void Destroy(); + + void ActivityOccurred(); + void ActivityStarted(); + void ActivityStopped(); + + virtual void WillRefresh(TimeStamp aTime) override; + + static void FadeBeginTimerFired(nsITimer* aTimer, void* aSelf) { + RefPtr<ScrollbarActivity> scrollbarActivity( + reinterpret_cast<ScrollbarActivity*>(aSelf)); + scrollbarActivity->BeginFade(); + } + + protected: + virtual ~ScrollbarActivity() = default; + + bool IsActivityOngoing() { return mNestedActivityCounter > 0; } + bool IsStillFading(TimeStamp aTime); + void QueryLookAndFeelVals(); + + void HandleEventForScrollbar(const nsAString& aType, nsIContent* aTarget, + dom::Element* aScrollbar, + bool* aStoredHoverState); + + void SetIsActive(bool aNewActive); + bool SetIsFading(bool aNewFading); // returns false if 'this' was destroyed + + void BeginFade(); + void EndFade(); + + void StartFadeBeginTimer(); + void CancelFadeBeginTimer(); + + void StartListeningForScrollbarEvents(); + void StartListeningForScrollAreaEvents(); + void StopListeningForScrollbarEvents(); + void StopListeningForScrollAreaEvents(); + void AddScrollbarEventListeners(dom::EventTarget* aScrollbar); + void RemoveScrollbarEventListeners(dom::EventTarget* aScrollbar); + + void RegisterWithRefreshDriver(); + void UnregisterFromRefreshDriver(); + + bool UpdateOpacity(TimeStamp aTime); // returns false if 'this' was destroyed + void HoveredScrollbar(dom::Element* aScrollbar); + + nsRefreshDriver* GetRefreshDriver(); + dom::Element* GetScrollbarContent(bool aVertical); + dom::Element* GetHorizontalScrollbar() { return GetScrollbarContent(false); } + dom::Element* GetVerticalScrollbar() { return GetScrollbarContent(true); } + + const TimeDuration FadeDuration() { + return TimeDuration::FromMilliseconds(mScrollbarFadeDuration); + } + + nsIScrollbarMediator* mScrollableFrame; + TimeStamp mFadeBeginTime; + nsCOMPtr<nsITimer> mFadeBeginTimer; + nsCOMPtr<dom::EventTarget> mHorizontalScrollbar; // null while inactive + nsCOMPtr<dom::EventTarget> mVerticalScrollbar; // null while inactive + int mNestedActivityCounter; + bool mIsActive; + bool mIsFading; + bool mListeningForScrollbarEvents; + bool mListeningForScrollAreaEvents; + bool mHScrollbarHovered; + bool mVScrollbarHovered; + + // LookAndFeel values we load on creation + bool mDisplayOnMouseMove; + int mScrollbarFadeBeginDelay; + int mScrollbarFadeDuration; +}; + +} // namespace layout +} // namespace mozilla + +#endif /* ScrollbarActivity_h___ */ |