nsSliderFrame.h (7666B)
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 "nsAtom.h" 12 #include "nsCOMPtr.h" 13 #include "nsContainerFrame.h" 14 #include "nsIDOMEventListener.h" 15 #include "nsITimer.h" 16 #include "nsRepeatService.h" 17 18 class nsITimer; 19 class nsScrollbarFrame; 20 class nsSliderFrame; 21 22 namespace mozilla { 23 class nsDisplaySliderMarks; 24 class PresShell; 25 class ScrollContainerFrame; 26 } // namespace mozilla 27 28 nsIFrame* NS_NewSliderFrame(mozilla::PresShell* aPresShell, 29 mozilla::ComputedStyle* aStyle); 30 31 class nsSliderMediator final : public nsIDOMEventListener { 32 public: 33 NS_DECL_ISUPPORTS 34 35 nsSliderFrame* mSlider; 36 37 explicit nsSliderMediator(nsSliderFrame* aSlider) { mSlider = aSlider; } 38 39 void SetSlider(nsSliderFrame* aSlider) { mSlider = aSlider; } 40 41 NS_DECL_NSIDOMEVENTLISTENER 42 43 protected: 44 virtual ~nsSliderMediator() = default; 45 }; 46 47 class nsSliderFrame final : public nsContainerFrame { 48 public: 49 NS_DECL_FRAMEARENA_HELPERS(nsSliderFrame) 50 NS_DECL_QUERYFRAME 51 52 friend class nsSliderMediator; 53 friend class mozilla::nsDisplaySliderMarks; 54 55 explicit nsSliderFrame(ComputedStyle* aStyle, nsPresContext* aPresContext); 56 virtual ~nsSliderFrame(); 57 58 // Get the point associated with this event. Returns true if a single valid 59 // point was found. Otherwise false. 60 bool GetEventPoint(mozilla::WidgetGUIEvent* aEvent, nsPoint& aPoint); 61 // Gets the event coordinates relative to the widget associated with this 62 // frame. Return true if a single valid point was found. 63 bool GetEventPoint(mozilla::WidgetGUIEvent* aEvent, 64 mozilla::LayoutDeviceIntPoint& aPoint); 65 66 #ifdef DEBUG_FRAME_DUMP 67 nsresult GetFrameName(nsAString& aResult) const override { 68 return MakeFrameName(u"SliderFrame"_ns, aResult); 69 } 70 #endif 71 72 void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize, 73 const ReflowInput& aReflowInput, 74 nsReflowStatus& aStatus) override; 75 76 // nsIFrame overrides 77 void Destroy(DestroyContext&) override; 78 79 void BuildDisplayList(nsDisplayListBuilder* aBuilder, 80 const nsDisplayListSet& aLists) override; 81 82 void BuildDisplayListForThumb(nsDisplayListBuilder* aBuilder, 83 nsIFrame* aThumb, 84 const nsDisplayListSet& aLists); 85 86 void Init(nsIContent* aContent, nsContainerFrame* aParent, 87 nsIFrame* aPrevInFlow) override; 88 89 nsresult HandleEvent(nsPresContext* aPresContext, 90 mozilla::WidgetGUIEvent* aEvent, 91 nsEventStatus* aEventStatus) override; 92 93 // nsContainerFrame overrides 94 void SetInitialChildList(ChildListID aListID, 95 nsFrameList&& aChildList) override; 96 void AppendFrames(ChildListID aListID, nsFrameList&& aFrameList) override; 97 void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame, 98 const nsLineList::iterator* aPrevFrameLine, 99 nsFrameList&& aFrameList) override; 100 void RemoveFrame(DestroyContext&, ChildListID, nsIFrame*) override; 101 102 nsresult StartDrag(mozilla::dom::Event* aEvent); 103 nsresult StopDrag(); 104 105 void StartAPZDrag(mozilla::WidgetGUIEvent* aEvent); 106 107 NS_IMETHOD HandlePress(nsPresContext* aPresContext, 108 mozilla::WidgetGUIEvent* aEvent, 109 nsEventStatus* aEventStatus) override; 110 111 NS_IMETHOD HandleMultiplePress(nsPresContext* aPresContext, 112 mozilla::WidgetGUIEvent* aEvent, 113 nsEventStatus* aEventStatus, 114 bool aControlHeld) override { 115 return NS_OK; 116 } 117 118 MOZ_CAN_RUN_SCRIPT 119 NS_IMETHOD HandleDrag(nsPresContext* aPresContext, 120 mozilla::WidgetGUIEvent* aEvent, 121 nsEventStatus* aEventStatus) override { 122 return NS_OK; 123 } 124 125 NS_IMETHOD HandleRelease(nsPresContext* aPresContext, 126 mozilla::WidgetGUIEvent* aEvent, 127 nsEventStatus* aEventStatus) override; 128 129 // Return the ratio the scrollbar thumb should move in proportion to the 130 // scrolled frame. 131 float GetThumbRatio() const; 132 133 // Notify the slider frame that an async scrollbar drag was started on the 134 // APZ side without consulting the main thread. The block id is the APZ 135 // input block id of the mousedown that started the drag. 136 void AsyncScrollbarDragInitiated(uint64_t aDragBlockId); 137 138 // Notify the slider frame that an async scrollbar drag requested in 139 // StartAPZDrag() was rejected by APZ, and the slider frame should 140 // fall back to main-thread dragging. 141 void AsyncScrollbarDragRejected(); 142 143 bool OnlySystemGroupDispatch(mozilla::EventMessage aMessage) const override; 144 145 // Returns the associated scroll container frame that contains this slider if 146 // any. 147 mozilla::ScrollContainerFrame* GetScrollContainerFrame(); 148 void CurrentPositionChanged(); 149 150 private: 151 bool GetScrollToClick(); 152 nsScrollbarFrame* Scrollbar() const; 153 bool ShouldScrollForEvent(mozilla::WidgetGUIEvent* aEvent); 154 bool ShouldScrollToClickForEvent(mozilla::WidgetGUIEvent* aEvent); 155 bool IsEventOverThumb(mozilla::WidgetGUIEvent* aEvent); 156 157 void SetCurrentThumbPosition(nscoord aNewPos); 158 159 void DragThumb(bool aGrabMouseEvents); 160 void AddListener(); 161 void RemoveListener(); 162 bool IsDraggingThumb() const; 163 164 void SuppressDisplayport(); 165 void UnsuppressDisplayport(); 166 167 void StartRepeat() { 168 nsRepeatService::GetInstance()->Start(Notify, this, mContent->OwnerDoc(), 169 "nsSliderFrame"_ns); 170 } 171 void StopRepeat() { 172 nsRepeatService::GetInstance()->Stop(Notify, this); 173 mCurrentClickHoldDestination = Nothing(); 174 } 175 void Notify(); 176 static void Notify(void* aData) { 177 (static_cast<nsSliderFrame*>(aData))->Notify(); 178 } 179 void PageScroll(bool aClickAndHold); 180 181 void SetupDrag(mozilla::WidgetGUIEvent* aEvent, nsIFrame* aThumbFrame, 182 nscoord aPos, bool aIsHorizontal); 183 184 nsPoint mDestinationPoint; 185 // If we are in a scrollbar track click-and-hold, this is populated with 186 // the destination of the scroll started at the most recent tick of the 187 // repeat timer. 188 Maybe<nsPoint> mCurrentClickHoldDestination; 189 RefPtr<nsSliderMediator> mMediator; 190 191 float mRatio; 192 193 nscoord mDragStart; 194 nscoord mThumbStart; 195 nscoord mRepeatDirection; 196 197 bool mDragInProgress = false; 198 199 // true if we've handed off the scrolling to APZ. This means that we should 200 // ignore scrolling events as the position will be updated by APZ. If we were 201 // to process these events then the scroll position update would conflict 202 // causing the scroll position to jump. 203 bool mScrollingWithAPZ; 204 205 // true if displayport suppression is active, for more performant 206 // scrollbar-dragging behaviour. 207 bool mSuppressionActive; 208 209 // If APZ initiated a scrollbar drag without main-thread involvement, it 210 // notifies us and this variable stores the input block id of the APZ input 211 // block that started the drag. This lets us handle the corresponding 212 // mousedown event properly, if it arrives after the scroll position has 213 // been shifted due to async scrollbar drag. 214 Maybe<uint64_t> mAPZDragInitiated; 215 216 nscoord mThumbMinLength; 217 218 static bool gMiddlePref; 219 }; // class nsSliderFrame 220 221 #endif