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/. */
7 #ifndef nsSliderFrame_h__
8 #define nsSliderFrame_h__
10 #include "mozilla/Attributes.h"
11 #include "nsContainerFrame.h"
12 #include "nsRepeatService.h"
16 #include "nsIDOMEventListener.h"
19 class nsScrollbarFrame
;
23 class nsDisplaySliderMarks
;
25 } // namespace mozilla
27 nsIFrame
* NS_NewSliderFrame(mozilla::PresShell
* aPresShell
,
28 mozilla::ComputedStyle
* aStyle
);
30 class nsSliderMediator final
: public nsIDOMEventListener
{
34 nsSliderFrame
* mSlider
;
36 explicit nsSliderMediator(nsSliderFrame
* aSlider
) { mSlider
= aSlider
; }
38 void SetSlider(nsSliderFrame
* aSlider
) { mSlider
= aSlider
; }
40 NS_DECL_NSIDOMEVENTLISTENER
43 virtual ~nsSliderMediator() = default;
46 class nsSliderFrame final
: public nsContainerFrame
{
48 NS_DECL_FRAMEARENA_HELPERS(nsSliderFrame
)
51 friend class nsSliderMediator
;
52 friend class mozilla::nsDisplaySliderMarks
;
54 explicit nsSliderFrame(ComputedStyle
* aStyle
, nsPresContext
* aPresContext
);
55 virtual ~nsSliderFrame();
57 // Get the point associated with this event. Returns true if a single valid
58 // point was found. Otherwise false.
59 bool GetEventPoint(mozilla::WidgetGUIEvent
* aEvent
, nsPoint
& aPoint
);
60 // Gets the event coordinates relative to the widget associated with this
61 // frame. Return true if a single valid point was found.
62 bool GetEventPoint(mozilla::WidgetGUIEvent
* aEvent
,
63 mozilla::LayoutDeviceIntPoint
& aPoint
);
65 #ifdef DEBUG_FRAME_DUMP
66 nsresult
GetFrameName(nsAString
& aResult
) const override
{
67 return MakeFrameName(u
"SliderFrame"_ns
, aResult
);
71 void Reflow(nsPresContext
* aPresContext
, ReflowOutput
& aDesiredSize
,
72 const ReflowInput
& aReflowInput
,
73 nsReflowStatus
& aStatus
) override
;
76 void Destroy(DestroyContext
&) override
;
78 void BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
79 const nsDisplayListSet
& aLists
) override
;
81 void BuildDisplayListForThumb(nsDisplayListBuilder
* aBuilder
,
83 const nsDisplayListSet
& aLists
);
85 nsresult
AttributeChanged(int32_t aNameSpaceID
, nsAtom
* aAttribute
,
86 int32_t aModType
) override
;
88 void Init(nsIContent
* aContent
, nsContainerFrame
* aParent
,
89 nsIFrame
* aPrevInFlow
) override
;
91 nsresult
HandleEvent(nsPresContext
* aPresContext
,
92 mozilla::WidgetGUIEvent
* aEvent
,
93 nsEventStatus
* aEventStatus
) override
;
95 // nsContainerFrame overrides
96 void SetInitialChildList(ChildListID aListID
,
97 nsFrameList
&& aChildList
) override
;
98 void AppendFrames(ChildListID aListID
, nsFrameList
&& aFrameList
) override
;
99 void InsertFrames(ChildListID aListID
, nsIFrame
* aPrevFrame
,
100 const nsLineList::iterator
* aPrevFrameLine
,
101 nsFrameList
&& aFrameList
) override
;
102 void RemoveFrame(DestroyContext
&, ChildListID
, nsIFrame
*) override
;
104 nsresult
StartDrag(mozilla::dom::Event
* aEvent
);
107 void StartAPZDrag(mozilla::WidgetGUIEvent
* aEvent
);
109 static int32_t GetCurrentPosition(nsIContent
* content
);
110 static int32_t GetMinPosition(nsIContent
* content
);
111 static int32_t GetMaxPosition(nsIContent
* content
);
112 static int32_t GetIncrement(nsIContent
* content
);
113 static int32_t GetPageIncrement(nsIContent
* content
);
114 static int32_t GetIntegerAttribute(nsIContent
* content
, nsAtom
* atom
,
115 int32_t defaultValue
);
117 NS_IMETHOD
HandlePress(nsPresContext
* aPresContext
,
118 mozilla::WidgetGUIEvent
* aEvent
,
119 nsEventStatus
* aEventStatus
) override
;
121 NS_IMETHOD
HandleMultiplePress(nsPresContext
* aPresContext
,
122 mozilla::WidgetGUIEvent
* aEvent
,
123 nsEventStatus
* aEventStatus
,
124 bool aControlHeld
) override
{
129 NS_IMETHOD
HandleDrag(nsPresContext
* aPresContext
,
130 mozilla::WidgetGUIEvent
* aEvent
,
131 nsEventStatus
* aEventStatus
) override
{
135 NS_IMETHOD
HandleRelease(nsPresContext
* aPresContext
,
136 mozilla::WidgetGUIEvent
* aEvent
,
137 nsEventStatus
* aEventStatus
) override
;
139 // Return the ratio the scrollbar thumb should move in proportion to the
141 float GetThumbRatio() const;
143 // Notify the slider frame that an async scrollbar drag was started on the
144 // APZ side without consulting the main thread. The block id is the APZ
145 // input block id of the mousedown that started the drag.
146 void AsyncScrollbarDragInitiated(uint64_t aDragBlockId
);
148 // Notify the slider frame that an async scrollbar drag requested in
149 // StartAPZDrag() was rejected by APZ, and the slider frame should
150 // fall back to main-thread dragging.
151 void AsyncScrollbarDragRejected();
153 bool OnlySystemGroupDispatch(mozilla::EventMessage aMessage
) const override
;
155 // Returns the associated scrollframe that contains this slider if any.
156 nsIScrollableFrame
* GetScrollFrame();
159 bool GetScrollToClick();
160 nsScrollbarFrame
* Scrollbar();
161 bool ShouldScrollForEvent(mozilla::WidgetGUIEvent
* aEvent
);
162 bool ShouldScrollToClickForEvent(mozilla::WidgetGUIEvent
* aEvent
);
163 bool IsEventOverThumb(mozilla::WidgetGUIEvent
* aEvent
);
165 void PageUpDown(nscoord change
);
166 void SetCurrentThumbPosition(nsIContent
* aScrollbar
, nscoord aNewPos
,
167 bool aIsSmooth
, bool aMaySnap
);
168 void SetCurrentPosition(nsIContent
* aScrollbar
, int32_t aNewPos
,
170 void SetCurrentPositionInternal(nsIContent
* aScrollbar
, int32_t pos
,
172 void CurrentPositionChanged();
174 void DragThumb(bool aGrabMouseEvents
);
176 void RemoveListener();
177 bool isDraggingThumb() const;
179 void SuppressDisplayport();
180 void UnsuppressDisplayport();
183 nsRepeatService::GetInstance()->Start(Notify
, this, mContent
->OwnerDoc(),
187 nsRepeatService::GetInstance()->Stop(Notify
, this);
188 mCurrentClickHoldDestination
= Nothing();
191 static void Notify(void* aData
) {
192 (static_cast<nsSliderFrame
*>(aData
))->Notify();
194 void PageScroll(bool aClickAndHold
);
196 void SetupDrag(mozilla::WidgetGUIEvent
* aEvent
, nsIFrame
* aThumbFrame
,
197 nscoord aPos
, bool aIsHorizontal
);
199 nsPoint mDestinationPoint
;
200 // If we are in a scrollbar track click-and-hold, this is populated with
201 // the destination of the scroll started at the most recent tick of the
203 Maybe
<nsPoint
> mCurrentClickHoldDestination
;
204 RefPtr
<nsSliderMediator
> mMediator
;
213 nscoord mRepeatDirection
;
217 // true if an attribute change has been caused by the user manipulating the
218 // slider. This allows notifications to tell how a slider's current position
222 // true if we've handed off the scrolling to APZ. This means that we should
223 // ignore scrolling events as the position will be updated by APZ. If we were
224 // to process these events then the scroll position update would conflict
225 // causing the scroll position to jump.
226 bool mScrollingWithAPZ
;
228 // true if displayport suppression is active, for more performant
229 // scrollbar-dragging behaviour.
230 bool mSuppressionActive
;
232 // If APZ initiated a scrollbar drag without main-thread involvement, it
233 // notifies us and this variable stores the input block id of the APZ input
234 // block that started the drag. This lets us handle the corresponding
235 // mousedown event properly, if it arrives after the scroll position has
236 // been shifted due to async scrollbar drag.
237 Maybe
<uint64_t> mAPZDragInitiated
;
239 nscoord mThumbMinLength
;
241 static bool gMiddlePref
;
242 }; // class nsSliderFrame