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 nsSliderFrame_h__ 8 #define nsSliderFrame_h__ 9 10 #include "mozilla/Attributes.h" 11 #include "nsRepeatService.h" 12 #include "nsBoxFrame.h" 13 #include "nsAtom.h" 14 #include "nsCOMPtr.h" 15 #include "nsITimer.h" 16 #include "nsIDOMEventListener.h" 17 18 class nsITimer; 19 class nsSliderFrame; 20 21 namespace mozilla { 22 class PresShell; 23 } // namespace mozilla 24 25 nsIFrame* NS_NewSliderFrame(mozilla::PresShell* aPresShell, 26 mozilla::ComputedStyle* aStyle); 27 28 class nsSliderMediator final : public nsIDOMEventListener { 29 public: 30 NS_DECL_ISUPPORTS 31 32 nsSliderFrame* mSlider; 33 nsSliderMediator(nsSliderFrame * aSlider)34 explicit nsSliderMediator(nsSliderFrame* aSlider) { mSlider = aSlider; } 35 SetSlider(nsSliderFrame * aSlider)36 virtual void SetSlider(nsSliderFrame* aSlider) { mSlider = aSlider; } 37 38 NS_DECL_NSIDOMEVENTLISTENER 39 40 protected: 41 virtual ~nsSliderMediator() = default; 42 }; 43 44 class nsSliderFrame final : public nsBoxFrame { 45 public: 46 NS_DECL_FRAMEARENA_HELPERS(nsSliderFrame) 47 NS_DECL_QUERYFRAME 48 49 friend class nsSliderMediator; 50 friend class nsDisplaySliderMarks; 51 52 explicit nsSliderFrame(ComputedStyle* aStyle, nsPresContext* aPresContext); 53 virtual ~nsSliderFrame(); 54 55 #ifdef DEBUG_FRAME_DUMP GetFrameName(nsAString & aResult)56 virtual nsresult GetFrameName(nsAString& aResult) const override { 57 return MakeFrameName(u"SliderFrame"_ns, aResult); 58 } 59 #endif 60 61 virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override; 62 virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override; 63 virtual nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState) override; 64 NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override; 65 66 // nsIFrame overrides 67 virtual void DestroyFrom(nsIFrame* aDestructRoot, 68 PostDestroyData& aPostDestroyData) override; 69 70 virtual void BuildDisplayListForChildren( 71 nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) override; 72 73 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, 74 const nsDisplayListSet& aLists) override; 75 76 virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute, 77 int32_t aModType) override; 78 79 virtual void Init(nsIContent* aContent, nsContainerFrame* aParent, 80 nsIFrame* asPrevInFlow) override; 81 82 virtual nsresult HandleEvent(nsPresContext* aPresContext, 83 mozilla::WidgetGUIEvent* aEvent, 84 nsEventStatus* aEventStatus) override; 85 86 // nsContainerFrame overrides 87 virtual void SetInitialChildList(ChildListID aListID, 88 nsFrameList& aChildList) override; 89 virtual void AppendFrames(ChildListID aListID, 90 nsFrameList& aFrameList) override; 91 virtual void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame, 92 const nsLineList::iterator* aPrevFrameLine, 93 nsFrameList& aFrameList) override; 94 virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override; 95 96 nsresult StartDrag(mozilla::dom::Event* aEvent); 97 nsresult StopDrag(); 98 99 void StartAPZDrag(mozilla::WidgetGUIEvent* aEvent); 100 101 static int32_t GetCurrentPosition(nsIContent* content); 102 static int32_t GetMinPosition(nsIContent* content); 103 static int32_t GetMaxPosition(nsIContent* content); 104 static int32_t GetIncrement(nsIContent* content); 105 static int32_t GetPageIncrement(nsIContent* content); 106 static int32_t GetIntegerAttribute(nsIContent* content, nsAtom* atom, 107 int32_t defaultValue); 108 void EnsureOrient(); 109 110 NS_IMETHOD HandlePress(nsPresContext* aPresContext, 111 mozilla::WidgetGUIEvent* aEvent, 112 nsEventStatus* aEventStatus) override; 113 HandleMultiplePress(nsPresContext * aPresContext,mozilla::WidgetGUIEvent * aEvent,nsEventStatus * aEventStatus,bool aControlHeld)114 NS_IMETHOD HandleMultiplePress(nsPresContext* aPresContext, 115 mozilla::WidgetGUIEvent* aEvent, 116 nsEventStatus* aEventStatus, 117 bool aControlHeld) override { 118 return NS_OK; 119 } 120 121 MOZ_CAN_RUN_SCRIPT HandleDrag(nsPresContext * aPresContext,mozilla::WidgetGUIEvent * aEvent,nsEventStatus * aEventStatus)122 NS_IMETHOD HandleDrag(nsPresContext* aPresContext, 123 mozilla::WidgetGUIEvent* aEvent, 124 nsEventStatus* aEventStatus) override { 125 return NS_OK; 126 } 127 128 NS_IMETHOD HandleRelease(nsPresContext* aPresContext, 129 mozilla::WidgetGUIEvent* aEvent, 130 nsEventStatus* aEventStatus) override; 131 132 // Return the ratio the scrollbar thumb should move in proportion to the 133 // scrolled frame. 134 float GetThumbRatio() const; 135 136 // Notify the slider frame that an async scrollbar drag was started on the 137 // APZ side without consulting the main thread. The block id is the APZ 138 // input block id of the mousedown that started the drag. 139 void AsyncScrollbarDragInitiated(uint64_t aDragBlockId); 140 141 // Notify the slider frame that an async scrollbar drag requested in 142 // StartAPZDrag() was rejected by APZ, and the slider frame should 143 // fall back to main-thread dragging. 144 void AsyncScrollbarDragRejected(); 145 146 bool OnlySystemGroupDispatch(mozilla::EventMessage aMessage) const override; 147 148 // Returns the associated scrollframe that contains this slider if any. 149 nsIScrollableFrame* GetScrollFrame(); 150 151 private: 152 bool GetScrollToClick(); 153 nsIFrame* GetScrollbar(); 154 bool ShouldScrollForEvent(mozilla::WidgetGUIEvent* aEvent); 155 bool ShouldScrollToClickForEvent(mozilla::WidgetGUIEvent* aEvent); 156 bool IsEventOverThumb(mozilla::WidgetGUIEvent* aEvent); 157 158 void PageUpDown(nscoord change); 159 void SetCurrentThumbPosition(nsIContent* aScrollbar, nscoord aNewPos, 160 bool aIsSmooth, bool aMaySnap); 161 void SetCurrentPosition(nsIContent* aScrollbar, int32_t aNewPos, 162 bool aIsSmooth); 163 void SetCurrentPositionInternal(nsIContent* aScrollbar, int32_t pos, 164 bool aIsSmooth); 165 void CurrentPositionChanged(); 166 167 void DragThumb(bool aGrabMouseEvents); 168 void AddListener(); 169 void RemoveListener(); 170 bool isDraggingThumb() const; 171 172 void SuppressDisplayport(); 173 void UnsuppressDisplayport(); 174 StartRepeat()175 void StartRepeat() { 176 nsRepeatService::GetInstance()->Start(Notify, this, mContent->OwnerDoc(), 177 "nsSliderFrame"_ns); 178 } StopRepeat()179 void StopRepeat() { nsRepeatService::GetInstance()->Stop(Notify, this); } 180 void Notify(); Notify(void * aData)181 static void Notify(void* aData) { 182 (static_cast<nsSliderFrame*>(aData))->Notify(); 183 } 184 void PageScroll(nscoord aChange); 185 186 nsPoint mDestinationPoint; 187 RefPtr<nsSliderMediator> mMediator; 188 189 float mRatio; 190 191 nscoord mDragStart; 192 nscoord mThumbStart; 193 194 int32_t mCurPos; 195 196 nscoord mChange; 197 198 bool mDragFinished; 199 200 // true if an attribute change has been caused by the user manipulating the 201 // slider. This allows notifications to tell how a slider's current position 202 // was changed. 203 bool mUserChanged; 204 205 // true if we've handed off the scrolling to APZ. This means that we should 206 // ignore scrolling events as the position will be updated by APZ. If we were 207 // to process these events then the scroll position update would conflict 208 // causing the scroll position to jump. 209 bool mScrollingWithAPZ; 210 211 // true if displayport suppression is active, for more performant 212 // scrollbar-dragging behaviour. 213 bool mSuppressionActive; 214 215 // If APZ initiated a scrollbar drag without main-thread involvement, it 216 // notifies us and this variable stores the input block id of the APZ input 217 // block that started the drag. This lets us handle the corresponding 218 // mousedown event properly, if it arrives after the scroll position has 219 // been shifted due to async scrollbar drag. 220 Maybe<uint64_t> mAPZDragInitiated; 221 222 static bool gMiddlePref; 223 static int32_t gSnapMultiplier; 224 }; // class nsSliderFrame 225 226 #endif 227