1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef ScrollbarActivity_h___ 8 #define ScrollbarActivity_h___ 9 10 #include "mozilla/Attributes.h" 11 #include "nsCOMPtr.h" 12 #include "nsIDOMEventListener.h" 13 #include "mozilla/TimeStamp.h" 14 #include "nsRefreshObservers.h" 15 16 class nsIContent; 17 class nsIScrollbarMediator; 18 class nsITimer; 19 class nsRefreshDriver; 20 21 namespace mozilla { 22 23 namespace dom { 24 class Element; 25 class EventTarget; 26 } // namespace dom 27 28 namespace layout { 29 30 /** 31 * ScrollbarActivity 32 * 33 * This class manages scrollbar behavior that imitates the native Mac OS X 34 * Lion overlay scrollbar behavior: Scrollbars are only shown while "scrollbar 35 * activity" occurs, and they're hidden with a fade animation after a short 36 * delay. 37 * 38 * Scrollbar activity has these states: 39 * - inactive: 40 * Scrollbars are hidden. 41 * - ongoing activity: 42 * Scrollbars are visible and being operated on in some way, for example 43 * because they're hovered or pressed. 44 * - active, but waiting for fade out 45 * Scrollbars are still completely visible but are about to fade away. 46 * - fading out 47 * Scrollbars are subject to a fade-out animation. 48 * 49 * Initial scrollbar activity needs to be reported by the scrollbar holder that 50 * owns the ScrollbarActivity instance. This needs to happen via a call to 51 * ActivityOccurred(), for example when the current scroll position or the size 52 * of the scroll area changes. 53 * 54 * As soon as scrollbars are visible, the ScrollbarActivity class manages the 55 * rest of the activity behavior: It ensures that mouse motions inside the 56 * scroll area keep the scrollbars visible, and that scrollbars don't fade away 57 * while they're being hovered / dragged. It also sets a sticky hover attribute 58 * on the most recently hovered scrollbar. 59 * 60 * ScrollbarActivity falls into hibernation after the scrollbars have faded 61 * out. It only starts acting after the next call to ActivityOccurred() / 62 * ActivityStarted(). 63 */ 64 65 class ScrollbarActivity final : public nsIDOMEventListener, 66 public nsARefreshObserver { 67 public: ScrollbarActivity(nsIScrollbarMediator * aScrollableFrame)68 explicit ScrollbarActivity(nsIScrollbarMediator* aScrollableFrame) 69 : mScrollableFrame(aScrollableFrame), 70 mNestedActivityCounter(0), 71 mIsActive(false), 72 mIsFading(false), 73 mListeningForScrollbarEvents(false), 74 mListeningForScrollAreaEvents(false), 75 mHScrollbarHovered(false), 76 mVScrollbarHovered(false), 77 mDisplayOnMouseMove(false), 78 mScrollbarFadeBeginDelay(0), 79 mScrollbarFadeDuration(0) { 80 QueryLookAndFeelVals(); 81 } 82 83 NS_DECL_ISUPPORTS 84 NS_DECL_NSIDOMEVENTLISTENER 85 86 void Destroy(); 87 88 void ActivityOccurred(); 89 void ActivityStarted(); 90 void ActivityStopped(); 91 92 virtual void WillRefresh(TimeStamp aTime) override; 93 FadeBeginTimerFired(nsITimer * aTimer,void * aSelf)94 static void FadeBeginTimerFired(nsITimer* aTimer, void* aSelf) { 95 RefPtr<ScrollbarActivity> scrollbarActivity( 96 reinterpret_cast<ScrollbarActivity*>(aSelf)); 97 scrollbarActivity->BeginFade(); 98 } 99 100 protected: 101 virtual ~ScrollbarActivity() = default; 102 IsActivityOngoing()103 bool IsActivityOngoing() { return mNestedActivityCounter > 0; } 104 bool IsStillFading(TimeStamp aTime); 105 void QueryLookAndFeelVals(); 106 107 void HandleEventForScrollbar(const nsAString& aType, nsIContent* aTarget, 108 dom::Element* aScrollbar, 109 bool* aStoredHoverState); 110 111 void SetIsActive(bool aNewActive); 112 bool SetIsFading(bool aNewFading); // returns false if 'this' was destroyed 113 114 void BeginFade(); 115 void EndFade(); 116 117 void StartFadeBeginTimer(); 118 void CancelFadeBeginTimer(); 119 120 void StartListeningForScrollbarEvents(); 121 void StartListeningForScrollAreaEvents(); 122 void StopListeningForScrollbarEvents(); 123 void StopListeningForScrollAreaEvents(); 124 void AddScrollbarEventListeners(dom::EventTarget* aScrollbar); 125 void RemoveScrollbarEventListeners(dom::EventTarget* aScrollbar); 126 127 void RegisterWithRefreshDriver(); 128 void UnregisterFromRefreshDriver(); 129 130 bool UpdateOpacity(TimeStamp aTime); // returns false if 'this' was destroyed 131 void HoveredScrollbar(dom::Element* aScrollbar); 132 133 nsRefreshDriver* GetRefreshDriver(); 134 dom::Element* GetScrollbarContent(bool aVertical); GetHorizontalScrollbar()135 dom::Element* GetHorizontalScrollbar() { return GetScrollbarContent(false); } GetVerticalScrollbar()136 dom::Element* GetVerticalScrollbar() { return GetScrollbarContent(true); } 137 FadeDuration()138 const TimeDuration FadeDuration() { 139 return TimeDuration::FromMilliseconds(mScrollbarFadeDuration); 140 } 141 142 nsIScrollbarMediator* mScrollableFrame; 143 TimeStamp mFadeBeginTime; 144 nsCOMPtr<nsITimer> mFadeBeginTimer; 145 nsCOMPtr<dom::EventTarget> mHorizontalScrollbar; // null while inactive 146 nsCOMPtr<dom::EventTarget> mVerticalScrollbar; // null while inactive 147 int mNestedActivityCounter; 148 bool mIsActive; 149 bool mIsFading; 150 bool mListeningForScrollbarEvents; 151 bool mListeningForScrollAreaEvents; 152 bool mHScrollbarHovered; 153 bool mVScrollbarHovered; 154 155 // LookAndFeel values we load on creation 156 bool mDisplayOnMouseMove; 157 int mScrollbarFadeBeginDelay; 158 int mScrollbarFadeDuration; 159 }; 160 161 } // namespace layout 162 } // namespace mozilla 163 164 #endif /* ScrollbarActivity_h___ */ 165