1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef nsSliderFrame_h__
7 #define nsSliderFrame_h__
8 
9 #include "mozilla/Attributes.h"
10 #include "nsRepeatService.h"
11 #include "nsBoxFrame.h"
12 #include "nsIAtom.h"
13 #include "nsCOMPtr.h"
14 #include "nsITimer.h"
15 #include "nsIDOMEventListener.h"
16 
17 class nsITimer;
18 class nsSliderFrame;
19 
20 nsIFrame* NS_NewSliderFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
21 
22 class nsSliderMediator final : public nsIDOMEventListener
23 {
24 public:
25 
26   NS_DECL_ISUPPORTS
27 
28   nsSliderFrame* mSlider;
29 
nsSliderMediator(nsSliderFrame * aSlider)30   explicit nsSliderMediator(nsSliderFrame* aSlider) {  mSlider = aSlider; }
31 
SetSlider(nsSliderFrame * aSlider)32   virtual void SetSlider(nsSliderFrame* aSlider) { mSlider = aSlider; }
33 
34   NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) override;
35 
36 protected:
~nsSliderMediator()37   virtual ~nsSliderMediator() {}
38 };
39 
40 class nsSliderFrame : public nsBoxFrame
41 {
42 public:
43   NS_DECL_FRAMEARENA_HELPERS
44   NS_DECL_QUERYFRAME_TARGET(nsSliderFrame)
45   NS_DECL_QUERYFRAME
46 
47   friend class nsSliderMediator;
48 
49   explicit nsSliderFrame(nsStyleContext* aContext);
50   virtual ~nsSliderFrame();
51 
52 #ifdef DEBUG_FRAME_DUMP
GetFrameName(nsAString & aResult)53   virtual nsresult GetFrameName(nsAString& aResult) const override {
54     return MakeFrameName(NS_LITERAL_STRING("SliderFrame"), aResult);
55   }
56 #endif
57 
58   virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
59   virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
60   virtual nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState) override;
61   NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
62 
63   // nsIFrame overrides
64   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
65 
66   virtual void BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
67                                            const nsRect&           aDirtyRect,
68                                            const nsDisplayListSet& aLists) override;
69 
70   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
71                                 const nsRect&           aDirtyRect,
72                                 const nsDisplayListSet& aLists) override;
73 
74   virtual nsresult AttributeChanged(int32_t aNameSpaceID,
75                                     nsIAtom* aAttribute,
76                                     int32_t aModType) override;
77 
78   virtual void Init(nsIContent*       aContent,
79                     nsContainerFrame* aParent,
80                     nsIFrame*         asPrevInFlow) override;
81 
82 
83   virtual nsresult HandleEvent(nsPresContext* aPresContext,
84                                mozilla::WidgetGUIEvent* aEvent,
85                                nsEventStatus* aEventStatus) override;
86 
87   virtual nsIAtom* GetType() const override;
88 
89   // nsContainerFrame overrides
90   virtual void SetInitialChildList(ChildListID     aListID,
91                                    nsFrameList&    aChildList) override;
92   virtual void AppendFrames(ChildListID     aListID,
93                             nsFrameList&    aFrameList) override;
94   virtual void InsertFrames(ChildListID     aListID,
95                             nsIFrame*       aPrevFrame,
96                             nsFrameList&    aFrameList) override;
97   virtual void RemoveFrame(ChildListID     aListID,
98                            nsIFrame*       aOldFrame) override;
99 
100   nsresult StartDrag(nsIDOMEvent* aEvent);
101   nsresult StopDrag();
102 
103   bool StartAPZDrag();
104 
105   static int32_t GetCurrentPosition(nsIContent* content);
106   static int32_t GetMinPosition(nsIContent* content);
107   static int32_t GetMaxPosition(nsIContent* content);
108   static int32_t GetIncrement(nsIContent* content);
109   static int32_t GetPageIncrement(nsIContent* content);
110   static int32_t GetIntegerAttribute(nsIContent* content, nsIAtom* atom, int32_t defaultValue);
111   void EnsureOrient();
112 
113   NS_IMETHOD HandlePress(nsPresContext* aPresContext,
114                          mozilla::WidgetGUIEvent* aEvent,
115                          nsEventStatus* aEventStatus) override;
116 
HandleMultiplePress(nsPresContext * aPresContext,mozilla::WidgetGUIEvent * aEvent,nsEventStatus * aEventStatus,bool aControlHeld)117   NS_IMETHOD HandleMultiplePress(nsPresContext* aPresContext,
118                                  mozilla::WidgetGUIEvent* aEvent,
119                                  nsEventStatus* aEventStatus,
120                                  bool aControlHeld) override
121   {
122     return NS_OK;
123   }
124 
HandleDrag(nsPresContext * aPresContext,mozilla::WidgetGUIEvent * aEvent,nsEventStatus * aEventStatus)125   NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
126                         mozilla::WidgetGUIEvent* aEvent,
127                         nsEventStatus* aEventStatus) override
128   {
129     return NS_OK;
130   }
131 
132   NS_IMETHOD HandleRelease(nsPresContext* aPresContext,
133                            mozilla::WidgetGUIEvent* aEvent,
134                            nsEventStatus* aEventStatus) override;
135 
136   // Return the ratio the scrollbar thumb should move in proportion to the
137   // scrolled frame.
138   float GetThumbRatio() const;
139 
140 private:
141 
142   bool GetScrollToClick();
143   nsIFrame* GetScrollbar();
144   bool ShouldScrollForEvent(mozilla::WidgetGUIEvent* aEvent);
145   bool ShouldScrollToClickForEvent(mozilla::WidgetGUIEvent* aEvent);
146   bool IsEventOverThumb(mozilla::WidgetGUIEvent* aEvent);
147 
148   void PageUpDown(nscoord change);
149   void SetCurrentThumbPosition(nsIContent* aScrollbar, nscoord aNewPos, bool aIsSmooth,
150                                bool aMaySnap);
151   void SetCurrentPosition(nsIContent* aScrollbar, int32_t aNewPos, bool aIsSmooth);
152   void SetCurrentPositionInternal(nsIContent* aScrollbar, int32_t pos,
153                                   bool aIsSmooth);
154   void CurrentPositionChanged();
155 
156   void DragThumb(bool aGrabMouseEvents);
157   void AddListener();
158   void RemoveListener();
159   bool isDraggingThumb();
160 
StartRepeat()161   void StartRepeat() {
162     nsRepeatService::GetInstance()->Start(Notify, this);
163   }
StopRepeat()164   void StopRepeat() {
165     nsRepeatService::GetInstance()->Stop(Notify, this);
166   }
167   void Notify();
Notify(void * aData)168   static void Notify(void* aData) {
169     (static_cast<nsSliderFrame*>(aData))->Notify();
170   }
171   void PageScroll(nscoord aChange);
172 
173   nsPoint mDestinationPoint;
174   RefPtr<nsSliderMediator> mMediator;
175 
176   float mRatio;
177 
178   nscoord mDragStart;
179   nscoord mThumbStart;
180 
181   int32_t mCurPos;
182 
183   nscoord mChange;
184 
185   bool mDragFinished;
186 
187   // true if an attribute change has been caused by the user manipulating the
188   // slider. This allows notifications to tell how a slider's current position
189   // was changed.
190   bool mUserChanged;
191 
192   // true if we've handed off the scrolling to APZ. This means that we should
193   // ignore scrolling events as the position will be updated by APZ. If we were
194   // to process these events then the scroll position update would conflict
195   // causing the scroll position to jump.
196   bool mScrollingWithAPZ;
197 
198   // true if displayport suppression is active, for more performant
199   // scrollbar-dragging behaviour.
200   bool mSuppressionActive;
201 
202   static bool gMiddlePref;
203   static int32_t gSnapMultiplier;
204 }; // class nsSliderFrame
205 
206 #endif
207