1 /*
2  * Copyright (C) 2004, 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCROLL_SCROLLBAR_H_
27 #define THIRD_PARTY_BLINK_RENDERER_CORE_SCROLL_SCROLLBAR_H_
28 
29 #include "third_party/blink/public/platform/web_color_scheme.h"
30 #include "third_party/blink/renderer/core/core_export.h"
31 #include "third_party/blink/renderer/core/scroll/scroll_types.h"
32 #include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
33 #include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
34 #include "third_party/blink/renderer/platform/heap/handle.h"
35 #include "third_party/blink/renderer/platform/timer.h"
36 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
37 
38 namespace blink {
39 
40 class Element;
41 class GraphicsContext;
42 class IntRect;
43 class ChromeClient;
44 class ScrollableArea;
45 class ScrollbarTheme;
46 class WebGestureEvent;
47 class WebMouseEvent;
48 
49 class CORE_EXPORT Scrollbar : public GarbageCollected<Scrollbar>,
50                               public DisplayItemClient {
51  public:
52   // Theme object ownership remains with the caller and it must outlive the
53   // scrollbar.
CreateForTesting(ScrollableArea * scrollable_area,ScrollbarOrientation orientation,ScrollbarControlSize size,ScrollbarTheme * theme)54   static Scrollbar* CreateForTesting(ScrollableArea* scrollable_area,
55                                      ScrollbarOrientation orientation,
56                                      ScrollbarControlSize size,
57                                      ScrollbarTheme* theme) {
58     return MakeGarbageCollected<Scrollbar>(scrollable_area, orientation, size,
59                                            nullptr, nullptr, theme);
60   }
61 
62   Scrollbar(ScrollableArea*,
63             ScrollbarOrientation,
64             ScrollbarControlSize,
65             Element* style_source,
66             ChromeClient* = nullptr,
67             ScrollbarTheme* = nullptr);
68   ~Scrollbar() override;
69 
X()70   int X() const { return frame_rect_.X(); }
Y()71   int Y() const { return frame_rect_.Y(); }
Width()72   int Width() const { return frame_rect_.Width(); }
Height()73   int Height() const { return frame_rect_.Height(); }
Size()74   IntSize Size() const { return frame_rect_.Size(); }
Location()75   IntPoint Location() const { return frame_rect_.Location(); }
76 
77   void SetFrameRect(const IntRect&);
FrameRect()78   const IntRect& FrameRect() const { return frame_rect_; }
79 
80   ScrollbarOverlayColorTheme GetScrollbarOverlayColorTheme() const;
81   bool HasTickmarks() const;
82   Vector<IntRect> GetTickmarks() const;
83   bool IsScrollableAreaActive() const;
84 
85   IntPoint ConvertFromRootFrame(const IntPoint&) const;
86 
IsCustomScrollbar()87   virtual bool IsCustomScrollbar() const { return false; }
Orientation()88   ScrollbarOrientation Orientation() const { return orientation_; }
89   bool IsLeftSideVerticalScrollbar() const;
90 
Value()91   int Value() const { return static_cast<int>(lroundf(current_pos_)); }
CurrentPos()92   float CurrentPos() const { return current_pos_; }
VisibleSize()93   int VisibleSize() const { return visible_size_; }
TotalSize()94   int TotalSize() const { return total_size_; }
95   int Maximum() const;
GetControlSize()96   ScrollbarControlSize GetControlSize() const { return control_size_; }
97 
PressedPart()98   ScrollbarPart PressedPart() const { return pressed_part_; }
HoveredPart()99   ScrollbarPart HoveredPart() const { return hovered_part_; }
100 
StyleChanged()101   virtual void StyleChanged() {}
102   void SetScrollbarsHiddenFromExternalAnimator(bool);
Enabled()103   bool Enabled() const { return enabled_; }
104   virtual void SetEnabled(bool);
105 
106   // This returns device-scale-factor-aware pixel value.
107   // e.g. 15 in dsf=1.0, 30 in dsf=2.0.
108   // This returns 0 for overlay scrollbars.
109   // See also ScrolbarTheme::scrollbatThickness().
110   int ScrollbarThickness() const;
111 
112   // Called by the ScrollableArea when the scroll offset changes.
113   // Will trigger paint invalidation if required.
114   void OffsetDidChange(mojom::blink::ScrollType scroll_type);
115 
116   virtual void DisconnectFromScrollableArea();
GetScrollableArea()117   ScrollableArea* GetScrollableArea() const { return scrollable_area_; }
118 
PressedPos()119   int PressedPos() const { return pressed_pos_; }
120 
121   virtual void SetHoveredPart(ScrollbarPart);
122   virtual void SetPressedPart(ScrollbarPart, WebInputEvent::Type);
123 
124   void SetProportion(int visible_size, int total_size);
SetPressedPos(int p)125   void SetPressedPos(int p) { pressed_pos_ = p; }
126 
127   void Paint(GraphicsContext&, const IntPoint& paint_offset) const;
128 
129   virtual bool IsSolidColor() const;
130   virtual bool IsOverlayScrollbar() const;
131   bool ShouldParticipateInHitTesting();
132 
133   bool IsWindowActive() const;
134 
135   // Return if the gesture event was handled. |shouldUpdateCapture|
136   // will be set to true if the handler should update the capture
137   // state for this scrollbar.
138   bool GestureEvent(const WebGestureEvent&, bool* should_update_capture);
139 
140   // These methods are used for platform scrollbars to give :hover feedback.
141   // They will not get called when the mouse went down in a scrollbar, since it
142   // is assumed the scrollbar will start
143   // grabbing all events in that case anyway.
144   void MouseMoved(const WebMouseEvent&);
145   void MouseEntered();
146   void MouseExited();
147 
148   // Used by some platform scrollbars to know when they've been released from
149   // capture.
150   void MouseUp(const WebMouseEvent&);
151   void MouseDown(const WebMouseEvent&);
152 
GetTheme()153   ScrollbarTheme& GetTheme() const { return theme_; }
154 
155   IntRect ConvertToContainingEmbeddedContentView(const IntRect&) const;
156   IntPoint ConvertFromContainingEmbeddedContentView(const IntPoint&) const;
157 
158   void MoveThumb(int pos, bool dragging_document = false);
159 
ElasticOverscroll()160   float ElasticOverscroll() const { return elastic_overscroll_; }
SetElasticOverscroll(float elastic_overscroll)161   void SetElasticOverscroll(float elastic_overscroll) {
162     elastic_overscroll_ = elastic_overscroll;
163   }
164 
165   // Use SetNeedsPaintInvalidation to cause the scrollbar (or parts thereof)
166   // to repaint. Here "track" includes track, buttons and tickmarks, i.e. all
167   // things except the thumb.
TrackNeedsRepaint()168   bool TrackNeedsRepaint() const { return track_needs_repaint_; }
ClearTrackNeedsRepaint()169   void ClearTrackNeedsRepaint() { track_needs_repaint_ = false; }
ThumbNeedsRepaint()170   bool ThumbNeedsRepaint() const { return thumb_needs_repaint_; }
ClearThumbNeedsRepaint()171   void ClearThumbNeedsRepaint() { thumb_needs_repaint_ = false; }
172 
173   // DisplayItemClient methods.
DebugName()174   String DebugName() const final {
175     return orientation_ == kHorizontalScrollbar ? "HorizontalScrollbar"
176                                                 : "VerticalScrollbar";
177   }
VisualRect()178   IntRect VisualRect() const final { return visual_rect_; }
179 
SetVisualRect(const IntRect & r)180   virtual void SetVisualRect(const IntRect& r) { visual_rect_ = r; }
181 
182   // Marks the scrollbar as needing to be redrawn.
183   //
184   // If invalid parts are provided, then those parts will also be repainted.
185   // Otherwise, the ScrollableArea may redraw using cached renderings of
186   // individual parts. For instance, if the scrollbar is composited, the thumb
187   // may be cached in a GPU texture (and is only guaranteed to be repainted if
188   // ThumbPart is invalidated).
189   //
190   // Even if no parts are invalidated, the scrollbar may need to be redrawn
191   // if, for instance, the thumb moves without changing the appearance of any
192   // part.
193   void SetNeedsPaintInvalidation(ScrollbarPart invalid_parts);
194 
195   CompositorElementId GetElementId();
196 
197   float EffectiveZoom() const;
198   bool ContainerIsRightToLeft() const;
199 
200   // The Element that supplies our style information. If the scrollbar is
201   // for a document, this is either the <body> or <html> element. Otherwise, it
202   // is the element that owns our PaintLayerScrollableArea.
StyleSource()203   Element* StyleSource() const { return style_source_.Get(); }
204 
205   WebColorScheme UsedColorScheme() const;
206 
207   virtual void Trace(Visitor*);
208 
209  protected:
210   void AutoscrollTimerFired(TimerBase*);
211   void StartTimerIfNeeded(base::TimeDelta delay);
212   void StopTimerIfNeeded();
213   void AutoscrollPressedPart(base::TimeDelta delay);
214   bool HandleTapGesture();
215   void InjectScrollGestureForPressedPart(WebInputEvent::Type gesture_type);
216   void InjectGestureScrollUpdateForThumbMove(float single_axis_target_offset);
217   void InjectScrollGesture(WebInputEvent::Type type,
218                            ScrollOffset delta,
219                            ScrollGranularity granularity);
220   ScrollDirectionPhysical PressedPartScrollDirectionPhysical();
221   ScrollGranularity PressedPartScrollGranularity();
222 
223   Member<ScrollableArea> scrollable_area_;
224   ScrollbarOrientation orientation_;
225   ScrollbarControlSize control_size_;
226   ScrollbarTheme& theme_;
227   Member<ChromeClient> chrome_client_;
228 
229   int visible_size_;
230   int total_size_;
231   float current_pos_;
232   float drag_origin_;
233 
234   ScrollbarPart hovered_part_;
235   ScrollbarPart pressed_part_;
236   int pressed_pos_;
237   float scroll_pos_;
238   bool dragging_document_;
239   int document_drag_pos_;
240 
241   bool enabled_;
242 
243   TaskRunnerTimer<Scrollbar> scroll_timer_;
244 
245   float elastic_overscroll_;
246 
247  private:
248   float ScrollableAreaCurrentPos() const;
249   float ScrollableAreaTargetPos() const;
250   bool ThumbWillBeUnderMouse() const;
251   bool DeltaWillScroll(ScrollOffset delta) const;
252 
253   int theme_scrollbar_thickness_;
254   bool track_needs_repaint_;
255   bool thumb_needs_repaint_;
256   bool injected_gesture_scroll_begin_;
257 
258   // This is set based on the event modifiers. In scenarios like scrolling or
259   // layout, the element that the cursor is over can change without the cursor
260   // itself moving. In these cases, a "fake" mouse move may be dispatched (see
261   // MouseEventManager::RecomputeMouseHoverState) in order to apply hover etc.
262   // Such mouse events do not have the modifier set and hence, maintaining this
263   // additional state is necessary.
264   bool scrollbar_manipulation_in_progress_on_cc_thread_;
265 
266   IntRect visual_rect_;
267   IntRect frame_rect_;
268   Member<Element> style_source_;
269 };
270 
271 }  // namespace blink
272 
273 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_SCROLL_SCROLLBAR_H_
274