When page scaling is in use position:fixed has incorrect results
[WebKit-https.git] / Source / WebCore / page / FrameView.h
1 /*
2    Copyright (C) 1997 Martin Jones (mjones@kde.org)
3              (C) 1998 Waldo Bastian (bastian@kde.org)
4              (C) 1998, 1999 Torben Weis (weis@kde.org)
5              (C) 1999 Lars Knoll (knoll@kde.org)
6              (C) 1999 Antti Koivisto (koivisto@kde.org)
7    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
8
9    This library is free software; you can redistribute it and/or
10    modify it under the terms of the GNU Library General Public
11    License as published by the Free Software Foundation; either
12    version 2 of the License, or (at your option) any later version.
13
14    This library is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    Library General Public License for more details.
18
19    You should have received a copy of the GNU Library General Public License
20    along with this library; see the file COPYING.LIB.  If not, write to
21    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22    Boston, MA 02110-1301, USA.
23 */
24
25 #ifndef FrameView_h
26 #define FrameView_h
27
28 #include "AdjustViewSizeOrNot.h"
29 #include "Color.h"
30 #include "LayoutTypes.h"
31 #include "PaintPhase.h"
32 #include "ScrollView.h"
33 #include <wtf/Forward.h>
34 #include <wtf/OwnPtr.h>
35 #include <wtf/text/WTFString.h>
36
37 namespace WebCore {
38
39 class Color;
40 class Element;
41 class Event;
42 class FloatSize;
43 class Frame;
44 class FrameActionScheduler;
45 class KURL;
46 class Node;
47 class Page;
48 class RenderBox;
49 class RenderEmbeddedObject;
50 class RenderLayer;
51 class RenderObject;
52 class RenderScrollbarPart;
53
54 typedef unsigned long long DOMTimeStamp;
55
56 class FrameView : public ScrollView {
57 public:
58     friend class RenderView;
59     friend class Internals;
60
61     static PassRefPtr<FrameView> create(Frame*);
62     static PassRefPtr<FrameView> create(Frame*, const IntSize& initialSize);
63
64     virtual ~FrameView();
65
66     virtual HostWindow* hostWindow() const;
67     
68     virtual void invalidateRect(const IntRect&);
69     virtual void setFrameRect(const IntRect&);
70
71 #if ENABLE(REQUEST_ANIMATION_FRAME)
72     void scheduleAnimation();
73 #endif
74
75     Frame* frame() const { return m_frame.get(); }
76     void clearFrame();
77
78     LayoutUnit marginWidth() const { return m_margins.width(); } // -1 means default
79     LayoutUnit marginHeight() const { return m_margins.height(); } // -1 means default
80     void setMarginWidth(LayoutUnit);
81     void setMarginHeight(LayoutUnit);
82
83     virtual void setCanHaveScrollbars(bool);
84     void updateCanHaveScrollbars();
85
86     virtual PassRefPtr<Scrollbar> createScrollbar(ScrollbarOrientation);
87
88     virtual bool avoidScrollbarCreation() const;
89     virtual void didAddHorizontalScrollbar(Scrollbar*);
90     virtual void willRemoveHorizontalScrollbar(Scrollbar*);
91
92     virtual void setContentsSize(const IntSize&);
93
94     void layout(bool allowSubtree = true);
95     bool didFirstLayout() const;
96     void layoutTimerFired(Timer<FrameView>*);
97     void scheduleRelayout();
98     void scheduleRelayoutOfSubtree(RenderObject*);
99     void unscheduleRelayout();
100     bool layoutPending() const;
101     bool isInLayout() const { return m_inLayout; }
102
103     RenderObject* layoutRoot(bool onlyDuringLayout = false) const;
104     int layoutCount() const { return m_layoutCount; }
105
106     bool needsLayout() const;
107     void setNeedsLayout();
108
109     bool needsFullRepaint() const { return m_doFullRepaint; }
110
111 #if ENABLE(REQUEST_ANIMATION_FRAME)
112     void serviceScriptedAnimations(DOMTimeStamp);
113 #endif
114
115 #if USE(ACCELERATED_COMPOSITING)
116     void updateCompositingLayers();
117     bool syncCompositingStateForThisFrame(Frame* rootFrameForSync);
118
119     void clearBackingStores();
120     void restoreBackingStores();
121
122     // Called when changes to the GraphicsLayer hierarchy have to be synchronized with
123     // content rendered via the normal painting path.
124     void setNeedsOneShotDrawingSynchronization();
125 #endif
126
127     bool hasCompositedContent() const;
128     bool hasCompositedContentIncludingDescendants() const;
129     bool hasCompositingAncestor() const;
130     void enterCompositingMode();
131     bool isEnclosedInCompositingLayer() const;
132
133     // Only used with accelerated compositing, but outside the #ifdef to make linkage easier.
134     // Returns true if the sync was completed.
135     bool syncCompositingStateIncludingSubframes();
136
137     // Returns true when a paint with the PaintBehaviorFlattenCompositingLayers flag set gives
138     // a faithful representation of the content.
139     bool isSoftwareRenderable() const;
140
141     void didMoveOnscreen();
142     void willMoveOffscreen();
143
144     void resetScrollbars();
145     void resetScrollbarsAndClearContentsSize();
146     void detachCustomScrollbars();
147     virtual void recalculateScrollbarOverlayStyle();
148
149     void clear();
150
151     bool isTransparent() const;
152     void setTransparent(bool isTransparent);
153
154     Color baseBackgroundColor() const;
155     void setBaseBackgroundColor(const Color&);
156     void updateBackgroundRecursively(const Color&, bool);
157
158     bool shouldUpdateWhileOffscreen() const;
159     void setShouldUpdateWhileOffscreen(bool);
160     bool shouldUpdate(bool = false) const;
161
162     void adjustViewSize();
163     
164     virtual IntRect windowClipRect(bool clipToContents = true) const;
165     IntRect windowClipRectForLayer(const RenderLayer*, bool clipToLayerContents) const;
166
167     virtual IntRect windowResizerRect() const;
168
169     virtual void setFixedVisibleContentRect(const IntRect&) OVERRIDE;
170     void setScrollPosition(const IntPoint&);
171     void scrollPositionChangedViaPlatformWidget();
172     virtual void repaintFixedElementsAfterScrolling();
173     virtual bool shouldRubberBandInDirection(ScrollDirection) const;
174
175     virtual void zoomAnimatorTransformChanged(float, float, float, ZoomAnimationState);
176
177     String mediaType() const;
178     void setMediaType(const String&);
179     void adjustMediaTypeForPrinting(bool printing);
180
181     void setCannotBlitToWindow();
182     void setIsOverlapped(bool);
183     bool isOverlapped() const { return m_isOverlapped; }
184     bool isOverlappedIncludingAncestors() const;
185     void setContentIsOpaque(bool);
186
187     void addSlowRepaintObject();
188     void removeSlowRepaintObject();
189
190     void addFixedObject();
191     void removeFixedObject();
192
193     // Functions for querying the current scrolled position, negating the effects of overhang
194     // and adjusting for page scale.
195     int scrollXForFixedPosition() const;
196     int scrollYForFixedPosition() const;
197     IntSize scrollOffsetForFixedPosition() const;
198
199     bool shouldLayoutFixedElementsRelativeToFrame() const { return m_shouldLayoutFixedElementsRelativeToFrame; }
200     void setShouldLayoutFixedElementsRelativeToFrame(bool);
201
202     void beginDeferredRepaints();
203     void endDeferredRepaints();
204     void checkStopDelayingDeferredRepaints();
205     void resetDeferredRepaintDelay();
206
207 #if ENABLE(DASHBOARD_SUPPORT)
208     void updateDashboardRegions();
209 #endif
210     void updateControlTints();
211
212     void restoreScrollbar();
213
214     void scheduleEvent(PassRefPtr<Event>, PassRefPtr<Node>);
215     void pauseScheduledEvents();
216     void resumeScheduledEvents();
217     void postLayoutTimerFired(Timer<FrameView>*);
218
219     bool wasScrolledByUser() const;
220     void setWasScrolledByUser(bool);
221
222     void addWidgetToUpdate(RenderEmbeddedObject*);
223     void removeWidgetToUpdate(RenderEmbeddedObject*);
224
225     virtual void paintContents(GraphicsContext*, const IntRect& damageRect);
226     void setPaintBehavior(PaintBehavior);
227     PaintBehavior paintBehavior() const;
228     bool isPainting() const;
229     bool hasEverPainted() const { return m_lastPaintTime; }
230     void setNodeToDraw(Node*);
231
232     virtual void paintOverhangAreas(GraphicsContext*, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect);
233     virtual void paintScrollCorner(GraphicsContext*, const IntRect& cornerRect);
234
235     Color documentBackgroundColor() const;
236
237     static double currentPaintTimeStamp() { return sCurrentPaintTimeStamp; } // returns 0 if not painting
238     
239     void updateLayoutAndStyleIfNeededRecursive();
240     void flushDeferredRepaints();
241
242     void incrementVisuallyNonEmptyCharacterCount(unsigned);
243     void incrementVisuallyNonEmptyPixelCount(const IntSize&);
244     void setIsVisuallyNonEmpty() { m_isVisuallyNonEmpty = true; }
245     bool isVisuallyNonEmpty() const { return m_isVisuallyNonEmpty; }
246     void enableAutoSizeMode(bool enable, const IntSize& minSize, const IntSize& maxSize);
247
248     void forceLayout(bool allowSubtree = false);
249     void forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor, AdjustViewSizeOrNot);
250
251     // FIXME: This method is retained because of embedded WebViews in AppKit.  When a WebView is embedded inside
252     // some enclosing view with auto-pagination, no call happens to resize the view.  The new pagination model
253     // needs the view to resize as a result of the breaks, but that means that the enclosing view has to potentially
254     // resize around that view.  Auto-pagination uses the bounds of the actual view that's being printed to determine
255     // the edges of the print operation, so the resize is necessary if the enclosing view's bounds depend on the
256     // web document's bounds.
257     // 
258     // This is already a problem if the view needs to be a different size because of printer fonts or because of print stylesheets.
259     // Mail/Dictionary work around this problem by using the _layoutForPrinting SPI
260     // to at least get print stylesheets and printer fonts into play, but since WebKit doesn't know about the page offset or
261     // page size, it can't actually paginate correctly during _layoutForPrinting.
262     //
263     // We can eventually move Mail to a newer SPI that would let them opt in to the layout-time pagination model,
264     // but that doesn't solve the general problem of how other AppKit views could opt in to the better model.
265     //
266     // NO OTHER PLATFORM BESIDES MAC SHOULD USE THIS METHOD.
267     void adjustPageHeightDeprecated(float* newBottom, float oldTop, float oldBottom, float bottomLimit);
268
269     bool scrollToFragment(const KURL&);
270     bool scrollToAnchor(const String&);
271     void maintainScrollPositionAtAnchor(Node*);
272     void scrollElementToRect(Element*, const IntRect&);
273
274     // Methods to convert points and rects between the coordinate space of the renderer, and this view.
275     virtual IntRect convertFromRenderer(const RenderObject*, const IntRect&) const;
276     virtual IntRect convertToRenderer(const RenderObject*, const IntRect&) const;
277     virtual IntPoint convertFromRenderer(const RenderObject*, const IntPoint&) const;
278     virtual IntPoint convertToRenderer(const RenderObject*, const IntPoint&) const;
279
280     bool isFrameViewScrollCorner(RenderScrollbarPart* scrollCorner) const { return m_scrollCorner == scrollCorner; }
281
282     void calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode);
283
284     // Normal delay
285     static void setRepaintThrottlingDeferredRepaintDelay(double p);
286     // Negative value would mean that first few repaints happen without a delay
287     static void setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p);
288     // The delay grows on each repaint to this maximum value
289     static void setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p);
290     // On each repaint the delay increses by this amount
291     static void setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p);
292
293     virtual IntPoint currentMousePosition() const;
294
295     // FIXME: Remove this method once plugin loading is decoupled from layout.
296     void flushAnyPendingPostLayoutTasks();
297
298     virtual bool shouldSuspendScrollAnimations() const;
299     virtual void scrollbarStyleChanged(int newStyle, bool forceUpdate);
300
301     void setAnimatorsAreActive();
302
303     RenderBox* embeddedContentBox() const;
304
305     void clearOwningRendererForCustomScrollbars(RenderBox*);
306     
307     void setTracksRepaints(bool);
308     bool isTrackingRepaints() const { return m_isTrackingRepaints; }
309     void resetTrackedRepaints() { m_trackedRepaintRects.clear(); }
310     const Vector<IntRect>& trackedRepaintRects() const { return m_trackedRepaintRects; }
311
312 protected:
313     virtual bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect);
314     virtual void scrollContentsSlowPath(const IntRect& updateRect);
315
316     virtual bool isVerticalDocument() const;
317     virtual bool isFlippedDocument() const;
318
319 private:
320     FrameView(Frame*);
321
322     void reset();
323     void init();
324
325     virtual bool isFrameView() const;
326
327     friend class RenderWidget;
328     bool useSlowRepaints(bool considerOverlap = true) const;
329     bool useSlowRepaintsIfNotOverlapped() const;
330     void updateCanBlitOnScrollRecursively();
331     bool contentsInCompositedLayer() const;
332
333     bool hasFixedObjects() const { return m_fixedObjectCount > 0; }
334
335     void applyOverflowToViewport(RenderObject*, ScrollbarMode& hMode, ScrollbarMode& vMode);
336
337     void updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow);
338
339     void paintControlTints();
340
341     void forceLayoutParentViewIfNeeded();
342     void performPostLayoutTasks();
343     void autoSizeIfEnabled();
344
345     virtual void repaintContentRectangle(const IntRect&, bool immediate);
346     virtual void contentsResized();
347     virtual void visibleContentsResized();
348
349     // Override ScrollView methods to do point conversion via renderers, in order to
350     // take transforms into account.
351     virtual IntRect convertToContainingView(const IntRect&) const;
352     virtual IntRect convertFromContainingView(const IntRect&) const;
353     virtual IntPoint convertToContainingView(const IntPoint&) const;
354     virtual IntPoint convertFromContainingView(const IntPoint&) const;
355
356     // ScrollableArea interface
357     virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
358     virtual bool isActive() const;
359     virtual void getTickmarks(Vector<IntRect>&) const;
360     virtual void scrollTo(const IntSize&);
361     virtual void didStartRubberBand(const IntSize&) const;
362     virtual void didCompleteRubberBand(const IntSize&) const;
363     virtual void didStartAnimatedScroll() const;
364     virtual void didCompleteAnimatedScroll() const;
365     virtual void setVisibleScrollerThumbRect(const IntRect&);
366     virtual bool isOnActivePage() const;
367     virtual ScrollableArea* enclosingScrollableArea() const;
368
369 #if USE(ACCELERATED_COMPOSITING)
370     virtual GraphicsLayer* layerForHorizontalScrollbar() const;
371     virtual GraphicsLayer* layerForVerticalScrollbar() const;
372     virtual GraphicsLayer* layerForScrollCorner() const;
373 #if PLATFORM(CHROMIUM) && ENABLE(RUBBER_BANDING)
374     virtual GraphicsLayer* layerForOverhangAreas() const;
375 #endif
376 #endif
377
378     virtual void notifyPageThatContentAreaWillPaint() const;
379     virtual void disconnectFromPage() { m_page = 0; }
380
381     virtual bool scrollAnimatorEnabled() const;
382
383     void deferredRepaintTimerFired(Timer<FrameView>*);
384     void doDeferredRepaints();
385     void updateDeferredRepaintDelay();
386     double adjustedDeferredRepaintDelay() const;
387
388     bool updateWidgets();
389     void updateWidget(RenderEmbeddedObject*);
390     void scrollToAnchor();
391     void scrollPositionChanged();
392
393     bool hasCustomScrollbars() const;
394
395     virtual void updateScrollCorner();
396
397     FrameView* parentFrameView() const;
398
399     virtual AXObjectCache* axObjectCache() const;
400     void notifyWidgetsInAllFrames(WidgetNotification);
401     
402     static double sCurrentPaintTimeStamp; // used for detecting decoded resource thrash in the cache
403
404     LayoutSize m_size;
405     LayoutSize m_margins;
406     
407     typedef HashSet<RenderEmbeddedObject*> RenderEmbeddedObjectSet;
408     OwnPtr<RenderEmbeddedObjectSet> m_widgetUpdateSet;
409     RefPtr<Frame> m_frame;
410
411     bool m_doFullRepaint;
412     
413     bool m_canHaveScrollbars;
414     bool m_cannotBlitToWindow;
415     bool m_isOverlapped;
416     bool m_contentIsOpaque;
417     bool m_shouldLayoutFixedElementsRelativeToFrame;
418     unsigned m_slowRepaintObjectCount;
419     unsigned m_fixedObjectCount;
420     int m_borderX;
421     int m_borderY;
422
423     Timer<FrameView> m_layoutTimer;
424     bool m_delayedLayout;
425     RenderObject* m_layoutRoot;
426     
427     bool m_layoutSchedulingEnabled;
428     bool m_inLayout;
429 #if ENABLE(SVG)
430     bool m_inLayoutParentView;
431 #endif
432     bool m_hasPendingPostLayoutTasks;
433     bool m_inSynchronousPostLayout;
434     int m_layoutCount;
435     unsigned m_nestedLayoutCount;
436     Timer<FrameView> m_postLayoutTasksTimer;
437     bool m_firstLayoutCallbackPending;
438
439     bool m_firstLayout;
440     bool m_isTransparent;
441     Color m_baseBackgroundColor;
442     LayoutSize m_lastLayoutSize;
443     float m_lastZoomFactor;
444
445     String m_mediaType;
446     String m_mediaTypeWhenNotPrinting;
447
448     OwnPtr<FrameActionScheduler> m_actionScheduler;
449
450     bool m_overflowStatusDirty;
451     bool m_horizontalOverflow;
452     bool m_verticalOverflow;    
453     RenderObject* m_viewportRenderer;
454
455     bool m_wasScrolledByUser;
456     bool m_inProgrammaticScroll;
457     
458     unsigned m_deferringRepaints;
459     unsigned m_repaintCount;
460     Vector<LayoutRect> m_repaintRects;
461     Timer<FrameView> m_deferredRepaintTimer;
462     double m_deferredRepaintDelay;
463     double m_lastPaintTime;
464     
465     bool m_isTrackingRepaints; // Used for testing.
466     Vector<IntRect> m_trackedRepaintRects;
467
468     bool m_shouldUpdateWhileOffscreen;
469
470     unsigned m_deferSetNeedsLayouts;
471     bool m_setNeedsLayoutWasDeferred;
472
473     RefPtr<Node> m_nodeToDraw;
474     PaintBehavior m_paintBehavior;
475     bool m_isPainting;
476
477     unsigned m_visuallyNonEmptyCharacterCount;
478     unsigned m_visuallyNonEmptyPixelCount;
479     bool m_isVisuallyNonEmpty;
480     bool m_firstVisuallyNonEmptyLayoutCallbackPending;
481
482     RefPtr<Node> m_maintainScrollPositionAnchor;
483
484     // Renderer to hold our custom scroll corner.
485     RenderScrollbarPart* m_scrollCorner;
486
487     Page* m_page;
488
489     // If true, automatically resize the frame view around its content.
490     bool m_shouldAutoSize;
491     bool m_inAutoSize;
492     // The lower bound on the size when autosizing.
493     IntSize m_minAutoSize;
494     // The upper bound on the size when autosizing.
495     IntSize m_maxAutoSize;
496
497     static double s_deferredRepaintDelay;
498     static double s_initialDeferredRepaintDelayDuringLoading;
499     static double s_maxDeferredRepaintDelayDuringLoading;
500     static double s_deferredRepaintDelayIncrementDuringLoading;
501 };
502
503 inline void FrameView::incrementVisuallyNonEmptyCharacterCount(unsigned count)
504 {
505     if (m_isVisuallyNonEmpty)
506         return;
507     m_visuallyNonEmptyCharacterCount += count;
508     // Use a threshold value to prevent very small amounts of visible content from triggering didFirstVisuallyNonEmptyLayout.
509     // The first few hundred characters rarely contain the interesting content of the page.
510     static const unsigned visualCharacterThreshold = 200;
511     if (m_visuallyNonEmptyCharacterCount > visualCharacterThreshold)
512         setIsVisuallyNonEmpty();
513 }
514
515 inline void FrameView::incrementVisuallyNonEmptyPixelCount(const IntSize& size)
516 {
517     if (m_isVisuallyNonEmpty)
518         return;
519     m_visuallyNonEmptyPixelCount += size.width() * size.height();
520     // Use a threshold value to prevent very small amounts of visible content from triggering didFirstVisuallyNonEmptyLayout
521     static const unsigned visualPixelThreshold = 32 * 32;
522     if (m_visuallyNonEmptyPixelCount > visualPixelThreshold)
523         setIsVisuallyNonEmpty();
524 }
525
526 } // namespace WebCore
527
528 #endif // FrameView_h