a237ef67447f0f086ab8e04c0f3bc6a14c5783cb
[platform/framework/web/crosswalk-tizen.git] /
1 /*
2  * Copyright (C) 2008, 2011 Apple 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 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 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 ScrollableArea_h
27 #define ScrollableArea_h
28
29 #include "platform/PlatformExport.h"
30 #include "platform/RuntimeEnabledFeatures.h"
31 #include "platform/geometry/FloatQuad.h"
32 #include "platform/geometry/LayoutRect.h"
33 #include "platform/graphics/Color.h"
34 #include "platform/heap/Handle.h"
35 #include "platform/scroll/ScrollAnimatorBase.h"
36 #include "platform/scroll/ScrollTypes.h"
37 #include "platform/scroll/Scrollbar.h"
38 #include "wtf/MathExtras.h"
39 #include "wtf/Noncopyable.h"
40 #include "wtf/Vector.h"
41
42 namespace blink {
43
44 class GraphicsLayer;
45 class HostWindow;
46 class LayoutBox;
47 class LayoutObject;
48 class ProgrammaticScrollAnimator;
49 struct ScrollAlignment;
50 class ScrollAnchor;
51 class ScrollAnimatorBase;
52 class CompositorAnimationTimeline;
53
54 enum IncludeScrollbarsInRect {
55   ExcludeScrollbars,
56   IncludeScrollbars,
57 };
58
59 class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
60   WTF_MAKE_NONCOPYABLE(ScrollableArea);
61
62  public:
63   static int pixelsPerLineStep(HostWindow*);
64   static float minFractionToStepWhenPaging();
65   static int maxOverlapBetweenPages();
66
67   // Convert a non-finite scroll value (Infinity, -Infinity, NaN) to 0 as
68   // per http://dev.w3.org/csswg/cssom-view/#normalize-non_finite-values.
69   static float normalizeNonFiniteScroll(float value) {
70     return std::isfinite(value) ? value : 0.0;
71   }
72
73   // The window that hosts the ScrollableArea. The ScrollableArea will
74   // communicate scrolls and repaints to the host window in the window's
75   // coordinate space.
76   virtual HostWindow* getHostWindow() const { return 0; }
77
78   virtual ScrollResult userScroll(ScrollGranularity, const ScrollOffset&);
79
80   virtual void setScrollOffset(const ScrollOffset&,
81                                ScrollType,
82                                ScrollBehavior = ScrollBehaviorInstant);
83   virtual void scrollBy(const ScrollOffset&,
84                         ScrollType,
85                         ScrollBehavior = ScrollBehaviorInstant);
86   void setScrollOffsetSingleAxis(ScrollbarOrientation,
87                                  float,
88                                  ScrollType,
89                                  ScrollBehavior = ScrollBehaviorInstant);
90
91   // Scrolls the area so that the given rect, given in the document's content
92   // coordinates, such that it's visible in the area. Returns the new location
93   // of the input rect relative once again to the document.
94   // Note, in the case of a Document container, such as FrameView, the output
95   // will always be the input rect since scrolling it can't change the location
96   // of content relative to the document, unlike an overflowing element.
97   virtual LayoutRect scrollIntoView(const LayoutRect& rectInContent,
98                                     const ScrollAlignment& alignX,
99                                     const ScrollAlignment& alignY,
100                                     ScrollType = ProgrammaticScroll,
101                                     ScrollBehavior = ScrollBehaviorInstant);
102
103   // Returns a rect, in the space of the area's backing graphics layer, that
104   // contains the visual region of all scrollbar parts.
105   virtual LayoutRect visualRectForScrollbarParts() const = 0;
106
107   static bool scrollBehaviorFromString(const String&, ScrollBehavior&);
108
109   void contentAreaWillPaint() const;
110   void mouseEnteredContentArea() const;
111   void mouseExitedContentArea() const;
112   void mouseMovedInContentArea() const;
113   void mouseEnteredScrollbar(Scrollbar&);
114   void mouseExitedScrollbar(Scrollbar&);
115   void mouseCapturedScrollbar();
116   void mouseReleasedScrollbar();
117   void contentAreaDidShow() const;
118   void contentAreaDidHide() const;
119
120   void finishCurrentScrollAnimations() const;
121
122   virtual void didAddScrollbar(Scrollbar&, ScrollbarOrientation);
123   virtual void willRemoveScrollbar(Scrollbar&, ScrollbarOrientation);
124
125   virtual void contentsResized();
126
127   bool hasOverlayScrollbars() const;
128   void setScrollbarOverlayColorTheme(ScrollbarOverlayColorTheme);
129   void recalculateScrollbarOverlayColorTheme(Color);
130   ScrollbarOverlayColorTheme getScrollbarOverlayColorTheme() const {
131     return static_cast<ScrollbarOverlayColorTheme>(
132         m_scrollbarOverlayColorTheme);
133   }
134
135   // This getter will create a ScrollAnimatorBase if it doesn't already exist.
136   ScrollAnimatorBase& scrollAnimator() const;
137
138   // This getter will return null if the ScrollAnimatorBase hasn't been created
139   // yet.
140   ScrollAnimatorBase* existingScrollAnimator() const {
141     return m_scrollAnimator;
142   }
143
144   ProgrammaticScrollAnimator& programmaticScrollAnimator() const;
145   ProgrammaticScrollAnimator* existingProgrammaticScrollAnimator() const {
146     return m_programmaticScrollAnimator;
147   }
148
149   virtual CompositorAnimationTimeline* compositorAnimationTimeline() const {
150     return nullptr;
151   }
152
153   // See Source/core/layout/README.md for an explanation of scroll origin.
154   const IntPoint& scrollOrigin() const { return m_scrollOrigin; }
155   bool scrollOriginChanged() const { return m_scrollOriginChanged; }
156
157   // This is used to determine whether the incoming fractional scroll offset
158   // should be truncated to integer. Current rule is that if
159   // preferCompositingToLCDTextEnabled() is disabled (which is true on low-dpi
160   // device by default) we should do the truncation.  The justification is that
161   // non-composited elements using fractional scroll offsets is causing too much
162   // nasty bugs but does not add too benefit on low-dpi devices.
163   // TODO(szager): Now that scroll offsets are floats everywhere, can we get rid
164   // of this?
165   virtual bool shouldUseIntegerScrollOffset() const {
166     return !RuntimeEnabledFeatures::fractionalScrollOffsetsEnabled();
167   }
168
169   virtual bool isActive() const = 0;
170   virtual int scrollSize(ScrollbarOrientation) const = 0;
171   void setScrollbarNeedsPaintInvalidation(ScrollbarOrientation);
172   virtual bool isScrollCornerVisible() const = 0;
173   virtual IntRect scrollCornerRect() const = 0;
174   void setScrollCornerNeedsPaintInvalidation();
175   virtual void getTickmarks(Vector<IntRect>&) const {}
176
177   // Convert points and rects between the scrollbar and its containing Widget.
178   // The client needs to implement these in order to be aware of layout effects
179   // like CSS transforms.
180   virtual IntRect convertFromScrollbarToContainingWidget(
181       const Scrollbar& scrollbar,
182       const IntRect& scrollbarRect) const {
183     return scrollbar.Widget::convertToContainingWidget(scrollbarRect);
184   }
185   virtual IntRect convertFromContainingWidgetToScrollbar(
186       const Scrollbar& scrollbar,
187       const IntRect& parentRect) const {
188     return scrollbar.Widget::convertFromContainingWidget(parentRect);
189   }
190   virtual IntPoint convertFromScrollbarToContainingWidget(
191       const Scrollbar& scrollbar,
192       const IntPoint& scrollbarPoint) const {
193     return scrollbar.Widget::convertToContainingWidget(scrollbarPoint);
194   }
195   virtual IntPoint convertFromContainingWidgetToScrollbar(
196       const Scrollbar& scrollbar,
197       const IntPoint& parentPoint) const {
198     return scrollbar.Widget::convertFromContainingWidget(parentPoint);
199   }
200
201   virtual Scrollbar* horizontalScrollbar() const { return nullptr; }
202   virtual Scrollbar* verticalScrollbar() const { return nullptr; }
203
204   // scrollPosition is the location of the top/left of the scroll viewport in
205   // the coordinate system defined by the top/left of the overflow rect.
206   // scrollOffset is the offset of the scroll viewport from its position when
207   // scrolled all the way to the beginning of its content's flow.
208   // For a more detailed explanation of scrollPosition, scrollOffset, and
209   // scrollOrigin, see core/layout/README.md.
210   FloatPoint scrollPosition() const {
211     return FloatPoint(scrollOrigin()) + scrollOffset();
212   }
213   virtual IntSize scrollOffsetInt() const = 0;
214   virtual ScrollOffset scrollOffset() const {
215     return ScrollOffset(scrollOffsetInt());
216   }
217   virtual IntSize minimumScrollOffsetInt() const = 0;
218   virtual ScrollOffset minimumScrollOffset() const {
219     return ScrollOffset(minimumScrollOffsetInt());
220   }
221   virtual IntSize maximumScrollOffsetInt() const = 0;
222   virtual ScrollOffset maximumScrollOffset() const {
223     return ScrollOffset(maximumScrollOffsetInt());
224   }
225
226   virtual IntRect visibleContentRect(
227       IncludeScrollbarsInRect = ExcludeScrollbars) const;
228   virtual int visibleHeight() const { return visibleContentRect().height(); }
229   virtual int visibleWidth() const { return visibleContentRect().width(); }
230   virtual IntSize contentsSize() const = 0;
231   virtual IntPoint lastKnownMousePosition() const { return IntPoint(); }
232
233   virtual bool shouldSuspendScrollAnimations() const { return true; }
234   virtual void scrollbarStyleChanged() {}
235   virtual bool scrollbarsCanBeActive() const = 0;
236
237   // Returns the bounding box of this scrollable area, in the coordinate system
238   // of the enclosing scroll view.
239   virtual IntRect scrollableAreaBoundingBox() const = 0;
240
241   virtual bool scrollAnimatorEnabled() const { return false; }
242
243   // NOTE: Only called from Internals for testing.
244   void updateScrollOffsetFromInternals(const IntSize&);
245
246   IntSize clampScrollOffset(const IntSize&) const;
247   ScrollOffset clampScrollOffset(const ScrollOffset&) const;
248
249   // Let subclasses provide a way of asking for and servicing scroll
250   // animations.
251   virtual bool scheduleAnimation();
252   virtual void serviceScrollAnimations(double monotonicTime);
253   virtual void updateCompositorScrollAnimations();
254   virtual void registerForAnimation() {}
255   virtual void deregisterForAnimation() {}
256
257   virtual bool usesCompositedScrolling() const { return false; }
258   virtual bool shouldScrollOnMainThread() const;
259
260   // Overlay scrollbars can "fade-out" when inactive.
261   virtual bool scrollbarsHidden() const;
262   virtual void setScrollbarsHidden(bool);
263
264   // Returns true if the GraphicsLayer tree needs to be rebuilt.
265   virtual bool updateAfterCompositingChange() { return false; }
266
267   virtual bool userInputScrollable(ScrollbarOrientation) const = 0;
268   virtual bool shouldPlaceVerticalScrollbarOnLeft() const = 0;
269
270   // Convenience functions
271   float scrollOffset(ScrollbarOrientation orientation) {
272     return orientation == HorizontalScrollbar ? scrollOffsetInt().width()
273                                               : scrollOffsetInt().height();
274   }
275   float minimumScrollOffset(ScrollbarOrientation orientation) {
276     return orientation == HorizontalScrollbar ? minimumScrollOffset().width()
277                                               : minimumScrollOffset().height();
278   }
279   float maximumScrollOffset(ScrollbarOrientation orientation) {
280     return orientation == HorizontalScrollbar ? maximumScrollOffset().width()
281                                               : maximumScrollOffset().height();
282   }
283   float clampScrollOffset(ScrollbarOrientation orientation, float offset) {
284     return clampTo(offset, minimumScrollOffset(orientation),
285                    maximumScrollOffset(orientation));
286   }
287
288 #if defined(TIZEN_VD_NATIVE_SCROLLBARS)
289   bool useNativeScrollbars() const;
290   virtual void scrollbarSizeDidChange() {}
291 #endif
292
293   virtual GraphicsLayer* layerForContainer() const;
294   virtual GraphicsLayer* layerForScrolling() const { return 0; }
295   virtual GraphicsLayer* layerForHorizontalScrollbar() const { return 0; }
296   virtual GraphicsLayer* layerForVerticalScrollbar() const { return 0; }
297   virtual GraphicsLayer* layerForScrollCorner() const { return 0; }
298   bool hasLayerForHorizontalScrollbar() const;
299   bool hasLayerForVerticalScrollbar() const;
300   bool hasLayerForScrollCorner() const;
301
302   void layerForScrollingDidChange(CompositorAnimationTimeline*);
303
304   void cancelScrollAnimation();
305   virtual void cancelProgrammaticScrollAnimation();
306
307   virtual ~ScrollableArea();
308
309   // Called when any of horizontal scrollbar, vertical scrollbar and scroll
310   // corner is setNeedsPaintInvalidation.
311   virtual void scrollControlWasSetNeedsPaintInvalidation() = 0;
312
313   // Returns the default scroll style this area should scroll with when not
314   // explicitly specified. E.g. The scrolling behavior of an element can be
315   // specified in CSS.
316   virtual ScrollBehavior scrollBehaviorStyle() const {
317     return ScrollBehaviorInstant;
318   }
319
320   // TODO(bokan): This is only used in FrameView to check scrollability but is
321   // needed here to allow RootFrameViewport to preserve wheelHandler
322   // semantics. Not sure why it's FrameView specific, it could probably be
323   // generalized to other types of ScrollableAreas.
324   virtual bool isScrollable() { return true; }
325
326   // TODO(bokan): FrameView::setScrollOffset uses updateScrollbars to scroll
327   // which bails out early if its already in updateScrollbars, the effect being
328   // that programmatic scrolls (i.e. setScrollOffset) are disabled when in
329   // updateScrollbars. Expose this here to allow RootFrameViewport to match the
330   // semantics for now but it should be cleaned up at the source.
331   virtual bool isProgrammaticallyScrollable() { return true; }
332
333   // Subtracts space occupied by this ScrollableArea's scrollbars.
334   // Does nothing if overlay scrollbars are enabled.
335   IntSize excludeScrollbars(const IntSize&) const;
336
337   virtual int verticalScrollbarWidth(
338       OverlayScrollbarClipBehavior = IgnoreOverlayScrollbarSize) const;
339   virtual int horizontalScrollbarHeight(
340       OverlayScrollbarClipBehavior = IgnoreOverlayScrollbarSize) const;
341
342   // Returns the widget associated with this ScrollableArea.
343   virtual Widget* getWidget() { return nullptr; }
344
345   virtual LayoutBox* layoutBox() const { return nullptr; }
346
347   // Maps a quad from the coordinate system of a LayoutObject contained by the
348   // ScrollableArea to the coordinate system of the ScrollableArea's visible
349   // content rect.  If the LayoutObject* argument is null, the argument quad is
350   // considered to be in the coordinate space of the overflow rect.
351   virtual FloatQuad localToVisibleContentQuad(const FloatQuad&,
352                                               const LayoutObject*,
353                                               unsigned = 0) const;
354
355   virtual bool isFrameView() const { return false; }
356   virtual bool isPaintLayerScrollableArea() const { return false; }
357   virtual bool isRootFrameViewport() const { return false; }
358
359   // Returns true if the scroller adjusts the scroll offset to compensate
360   // for layout movements (bit.ly/scroll-anchoring).
361   virtual bool shouldPerformScrollAnchoring() const { return false; }
362
363   // Need to promptly let go of owned animator objects.
364   EAGERLY_FINALIZE();
365   DECLARE_VIRTUAL_TRACE();
366
367   virtual void clearScrollableArea();
368
369   virtual ScrollAnchor* scrollAnchor() { return nullptr; }
370
371 #if defined(OS_TIZEN_TV_PRODUCT)
372   virtual void thumbPartFocusChanged(ScrollbarOrientation, bool) {}
373 #endif
374
375  protected:
376   ScrollableArea();
377
378   ScrollbarOrientation scrollbarOrientationFromDirection(
379       ScrollDirectionPhysical) const;
380   float scrollStep(ScrollGranularity, ScrollbarOrientation) const;
381
382   void setScrollOrigin(const IntPoint&);
383   void resetScrollOriginChanged() { m_scrollOriginChanged = false; }
384
385   // Needed to let the animators call scrollOffsetChanged.
386   friend class ScrollAnimatorCompositorCoordinator;
387   void scrollOffsetChanged(const ScrollOffset&, ScrollType);
388
389   bool horizontalScrollbarNeedsPaintInvalidation() const {
390     return m_horizontalScrollbarNeedsPaintInvalidation;
391   }
392   bool verticalScrollbarNeedsPaintInvalidation() const {
393     return m_verticalScrollbarNeedsPaintInvalidation;
394   }
395   bool scrollCornerNeedsPaintInvalidation() const {
396     return m_scrollCornerNeedsPaintInvalidation;
397   }
398   void clearNeedsPaintInvalidationForScrollControls() {
399     m_horizontalScrollbarNeedsPaintInvalidation = false;
400     m_verticalScrollbarNeedsPaintInvalidation = false;
401     m_scrollCornerNeedsPaintInvalidation = false;
402   }
403   void showOverlayScrollbars();
404
405   // Called when scrollbar hides/shows for overlay scrollbars. This callback
406   // shouldn't do any significant work as it can be called unexpectadly often
407   // on Mac. This happens because painting code has to set alpha to 1, paint,
408   // then reset to alpha, causing spurrious "visibilityChanged" calls.
409   virtual void scrollbarVisibilityChanged() {}
410
411  private:
412   void programmaticScrollHelper(const ScrollOffset&, ScrollBehavior);
413   void userScrollHelper(const ScrollOffset&, ScrollBehavior);
414
415   void fadeOverlayScrollbarsTimerFired(TimerBase*);
416
417   // This function should be overriden by subclasses to perform the actual
418   // scroll of the content.
419   virtual void updateScrollOffset(const ScrollOffset&, ScrollType) = 0;
420
421   virtual int lineStep(ScrollbarOrientation) const;
422   virtual int pageStep(ScrollbarOrientation) const;
423   virtual int documentStep(ScrollbarOrientation) const;
424   virtual float pixelStep(ScrollbarOrientation) const;
425
426   mutable Member<ScrollAnimatorBase> m_scrollAnimator;
427   mutable Member<ProgrammaticScrollAnimator> m_programmaticScrollAnimator;
428
429   std::unique_ptr<Timer<ScrollableArea>> m_fadeOverlayScrollbarsTimer;
430
431   unsigned m_scrollbarOverlayColorTheme : 2;
432
433   unsigned m_scrollOriginChanged : 1;
434
435   unsigned m_horizontalScrollbarNeedsPaintInvalidation : 1;
436   unsigned m_verticalScrollbarNeedsPaintInvalidation : 1;
437   unsigned m_scrollCornerNeedsPaintInvalidation : 1;
438   unsigned m_scrollbarsHidden : 1;
439   unsigned m_scrollbarCaptured : 1;
440
441   // There are 6 possible combinations of writing mode and direction. Scroll
442   // origin will be non-zero in the x or y axis if there is any reversed
443   // direction or writing-mode. The combinations are:
444   // writing-mode / direction     scrollOrigin.x() set    scrollOrigin.y() set
445   // horizontal-tb / ltr          NO                      NO
446   // horizontal-tb / rtl          YES                     NO
447   // vertical-lr / ltr            NO                      NO
448   // vertical-lr / rtl            NO                      YES
449   // vertical-rl / ltr            YES                     NO
450   // vertical-rl / rtl            YES                     YES
451   IntPoint m_scrollOrigin;
452 };
453
454 }  // namespace blink
455
456 #endif  // ScrollableArea_h