summaryrefslogtreecommitdiffstats
path: root/third_party/WebKit/Source/platform/scroll/Scrollbar.h
blob: 9699332e446d74301c5384f741702c2fd6febcab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/*
 * Copyright (C) 2004, 2006 Apple Computer, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef Scrollbar_h
#define Scrollbar_h

#include "platform/Timer.h"
#include "platform/Widget.h"
#include "platform/graphics/paint/DisplayItem.h"
#include "platform/heap/Handle.h"
#include "platform/scroll/ScrollTypes.h"
#include "platform/scroll/ScrollbarThemeClient.h"
#include "wtf/MathExtras.h"
#include "wtf/PassRefPtr.h"

namespace blink {

class GraphicsContext;
class HostWindow;
class IntRect;
class PlatformGestureEvent;
class PlatformMouseEvent;
class ScrollAnimatorBase;
class ScrollableArea;
class ScrollbarTheme;

class PLATFORM_EXPORT Scrollbar : public Widget, public ScrollbarThemeClient {
public:
    static PassRefPtrWillBeRawPtr<Scrollbar> create(ScrollableArea*, ScrollbarOrientation, ScrollbarControlSize, HostWindow*);

    // Theme object ownership remains with the caller and it must outlive the scrollbar.
    static PassRefPtrWillBeRawPtr<Scrollbar> createForTesting(ScrollableArea*, ScrollbarOrientation, ScrollbarControlSize, ScrollbarTheme*);

    ~Scrollbar() override;

    // ScrollbarThemeClient implementation.
    int x() const override { return Widget::x(); }
    int y() const override { return Widget::y(); }
    int width() const override { return Widget::width(); }
    int height() const override { return Widget::height(); }
    IntSize size() const override { return Widget::size(); }
    IntPoint location() const override { return Widget::location(); }

    Widget* parent() const override { return Widget::parent(); }
    Widget* root() const override { return Widget::root(); }

    void setFrameRect(const IntRect&) override;
    IntRect frameRect() const override { return Widget::frameRect(); }

    ScrollbarOverlayStyle getScrollbarOverlayStyle() const override;
    void getTickmarks(Vector<IntRect>&) const override;
    bool isScrollableAreaActive() const override;

    IntPoint convertFromRootFrame(const IntPoint& pointInRootFrame) const override { return Widget::convertFromRootFrame(pointInRootFrame); }

    bool isCustomScrollbar() const override { return false; }
    ScrollbarOrientation orientation() const override { return m_orientation; }
    bool isLeftSideVerticalScrollbar() const override;

    int value() const override { return lroundf(m_currentPos); }
    float currentPos() const override { return m_currentPos; }
    int visibleSize() const override { return m_visibleSize; }
    int totalSize() const override { return m_totalSize; }
    int maximum() const override { return m_totalSize - m_visibleSize; }
    ScrollbarControlSize controlSize() const override { return m_controlSize; }

    ScrollbarPart pressedPart() const override { return m_pressedPart; }
    ScrollbarPart hoveredPart() const override { return m_hoveredPart; }

    void styleChanged() override { }
    void visibilityChanged() override;
    bool enabled() const override { return m_enabled; }
    void setEnabled(bool) override;

    int scrollbarThickness() const;

    // Called by the ScrollableArea when the scroll offset changes.
    // Will trigger paint invalidation if required.
    void offsetDidChange();

    void disconnectFromScrollableArea();
    ScrollableArea* getScrollableArea() const { return m_scrollableArea; }

    int pressedPos() const { return m_pressedPos; }

    virtual void setHoveredPart(ScrollbarPart);
    virtual void setPressedPart(ScrollbarPart);

    void setProportion(int visibleSize, int totalSize);
    void setPressedPos(int p) { m_pressedPos = p; }

    void paint(GraphicsContext&, const CullRect&) const final;

    bool isOverlayScrollbar() const override;
    bool shouldParticipateInHitTesting();

    void windowActiveChangedForSnowLeopardOnly();
    bool isWindowActive() const;

    // Return if the gesture event was handled. |shouldUpdateCapture|
    // will be set to true if the handler should update the capture
    // state for this scrollbar.
    bool gestureEvent(const PlatformGestureEvent&, bool* shouldUpdateCapture);

    // These methods are used for platform scrollbars to give :hover feedback.  They will not get called
    // when the mouse went down in a scrollbar, since it is assumed the scrollbar will start
    // grabbing all events in that case anyway.
    void mouseMoved(const PlatformMouseEvent&);
    void mouseEntered();
    void mouseExited();

    // Used by some platform scrollbars to know when they've been released from capture.
    void mouseUp(const PlatformMouseEvent&);
    void mouseDown(const PlatformMouseEvent&);

    ScrollbarTheme& theme() const { return m_theme; }

    IntRect convertToContainingWidget(const IntRect&) const override;
    IntRect convertFromContainingWidget(const IntRect&) const override;

    IntPoint convertToContainingWidget(const IntPoint&) const override;
    IntPoint convertFromContainingWidget(const IntPoint&) const override;

    void moveThumb(int pos, bool draggingDocument = false);

    float elasticOverscroll() const override { return m_elasticOverscroll; }
    void setElasticOverscroll(float elasticOverscroll) override { m_elasticOverscroll = elasticOverscroll; }

    // Use setNeedsPaintInvalidation to cause the scrollbar (or parts thereof)
    // to repaint.
    bool trackNeedsRepaint() const { return m_trackNeedsRepaint; }
    void clearTrackNeedsRepaint() { m_trackNeedsRepaint = false; }
    bool thumbNeedsRepaint() const { return m_thumbNeedsRepaint; }
    void clearThumbNeedsRepaint() { m_thumbNeedsRepaint = false; }

    bool overlapsResizer() const { return m_overlapsResizer; }
    void setOverlapsResizer(bool overlapsResizer) { m_overlapsResizer = overlapsResizer; }

    // DisplayItemClient methods.
    String debugName() const final { return m_orientation == HorizontalScrollbar ? "HorizontalScrollbar" : "VerticalScrollbar"; }
    // TODO(chrishtr): fix this.
    LayoutRect visualRect() const override { return LayoutRect(); }

    // Marks the scrollbar as needing to be redrawn.
    //
    // If invalid parts are provided, then those parts will also be repainted.
    // Otherwise, the ScrollableArea may redraw using cached renderings of
    // individual parts. For instance, if the scrollbar is composited, the thumb
    // may be cached in a GPU texture (and is only guaranteed to be repainted if
    // ThumbPart is invalidated).
    //
    // Even if no parts are invalidated, the scrollbar may need to be redrawn
    // if, for instance, the thumb moves without changing the appearance of any
    // part.
    void setNeedsPaintInvalidation(ScrollbarPart invalidParts);

    // Promptly unregister from the theme manager + run finalizers of derived Scrollbars.
    EAGERLY_FINALIZE();
#if ENABLE(OILPAN)
    DECLARE_EAGER_FINALIZATION_OPERATOR_NEW();
#endif
    DECLARE_VIRTUAL_TRACE();

protected:
    Scrollbar(ScrollableArea*, ScrollbarOrientation, ScrollbarControlSize, HostWindow* = 0, ScrollbarTheme* = 0);

    void autoscrollTimerFired(Timer<Scrollbar>*);
    void startTimerIfNeeded(double delay);
    void stopTimerIfNeeded();
    void autoscrollPressedPart(double delay);
    ScrollDirectionPhysical pressedPartScrollDirectionPhysical();
    ScrollGranularity pressedPartScrollGranularity();

    RawPtrWillBeMember<ScrollableArea> m_scrollableArea;
    ScrollbarOrientation m_orientation;
    ScrollbarControlSize m_controlSize;
    ScrollbarTheme& m_theme;
    RawPtrWillBeMember<HostWindow> m_hostWindow;

    int m_visibleSize;
    int m_totalSize;
    float m_currentPos;
    float m_dragOrigin;

    ScrollbarPart m_hoveredPart;
    ScrollbarPart m_pressedPart;
    int m_pressedPos;
    float m_scrollPos;
    bool m_draggingDocument;
    int m_documentDragPos;

    bool m_enabled;

    Timer<Scrollbar> m_scrollTimer;
    bool m_overlapsResizer;

    float m_elasticOverscroll;

private:
    bool isScrollbar() const override { return true; }

    void invalidate() override { setNeedsPaintInvalidation(AllParts); }
    void invalidateRect(const IntRect&) override { setNeedsPaintInvalidation(AllParts); }

    float scrollableAreaCurrentPos() const;
    float scrollableAreaTargetPos() const;
    bool thumbWillBeUnderMouse() const;

    bool m_trackNeedsRepaint;
    bool m_thumbNeedsRepaint;
};

DEFINE_TYPE_CASTS(Scrollbar, Widget, widget, widget->isScrollbar(), widget.isScrollbar());

} // namespace blink

#endif // Scrollbar_h