Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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/. */
6 /* rendering object to wrap rendering objects that should be scrollable */
8 #ifndef nsGfxScrollFrame_h___
9 #define nsGfxScrollFrame_h___
11 #include "mozilla/Attributes.h"
12 #include "nsContainerFrame.h"
13 #include "nsIAnonymousContentCreator.h"
14 #include "nsBoxFrame.h"
15 #include "nsIScrollableFrame.h"
16 #include "nsIStatefulFrame.h"
17 #include "nsThreadUtils.h"
18 #include "nsIReflowCallback.h"
19 #include "nsBoxLayoutState.h"
20 #include "nsQueryFrame.h"
21 #include "nsExpirationTracker.h"
23 class nsPresContext;
24 class nsIPresShell;
25 class nsIContent;
26 class nsIAtom;
27 class nsIScrollFrameInternal;
28 class nsPresState;
29 class nsIScrollPositionListener;
30 struct ScrollReflowState;
32 namespace mozilla {
33 namespace layout {
34 class ScrollbarActivity;
35 }
36 }
38 namespace mozilla {
40 class ScrollFrameHelper : public nsIReflowCallback {
41 public:
42 typedef mozilla::CSSIntPoint CSSIntPoint;
43 typedef mozilla::layout::ScrollbarActivity ScrollbarActivity;
45 class AsyncScroll;
47 ScrollFrameHelper(nsContainerFrame* aOuter, bool aIsRoot);
48 ~ScrollFrameHelper();
50 mozilla::ScrollbarStyles GetScrollbarStylesFromFrame() const;
52 // If a child frame was added or removed on the scrollframe,
53 // reload our child frame list.
54 // We need this if a scrollbar frame is recreated.
55 void ReloadChildFrames();
57 nsresult CreateAnonymousContent(
58 nsTArray<nsIAnonymousContentCreator::ContentInfo>& aElements);
59 void AppendAnonymousContentTo(nsBaseContentList& aElements, uint32_t aFilter);
60 nsresult FireScrollPortEvent();
61 void PostOverflowEvent();
62 void Destroy();
64 void BuildDisplayList(nsDisplayListBuilder* aBuilder,
65 const nsRect& aDirtyRect,
66 const nsDisplayListSet& aLists);
68 void AppendScrollPartsTo(nsDisplayListBuilder* aBuilder,
69 const nsRect& aDirtyRect,
70 const nsDisplayListSet& aLists,
71 bool& aCreateLayer,
72 bool aPositioned);
74 bool GetBorderRadii(nscoord aRadii[8]) const;
76 // nsIReflowCallback
77 virtual bool ReflowFinished() MOZ_OVERRIDE;
78 virtual void ReflowCallbackCanceled() MOZ_OVERRIDE;
80 /**
81 * @note This method might destroy the frame, pres shell and other objects.
82 * Called when the 'curpos' attribute on one of the scrollbars changes.
83 */
84 void CurPosAttributeChanged(nsIContent* aChild);
86 void PostScrollEvent();
87 void FireScrollEvent();
88 void PostScrolledAreaEvent();
89 void FireScrolledAreaEvent();
91 class ScrollEvent : public nsRunnable {
92 public:
93 NS_DECL_NSIRUNNABLE
94 ScrollEvent(ScrollFrameHelper *helper) : mHelper(helper) {}
95 void Revoke() { mHelper = nullptr; }
96 private:
97 ScrollFrameHelper *mHelper;
98 };
100 class AsyncScrollPortEvent : public nsRunnable {
101 public:
102 NS_DECL_NSIRUNNABLE
103 AsyncScrollPortEvent(ScrollFrameHelper *helper) : mHelper(helper) {}
104 void Revoke() { mHelper = nullptr; }
105 private:
106 ScrollFrameHelper *mHelper;
107 };
109 class ScrolledAreaEvent : public nsRunnable {
110 public:
111 NS_DECL_NSIRUNNABLE
112 ScrolledAreaEvent(ScrollFrameHelper *helper) : mHelper(helper) {}
113 void Revoke() { mHelper = nullptr; }
114 private:
115 ScrollFrameHelper *mHelper;
116 };
118 /**
119 * @note This method might destroy the frame, pres shell and other objects.
120 */
121 void FinishReflowForScrollbar(nsIContent* aContent, nscoord aMinXY,
122 nscoord aMaxXY, nscoord aCurPosXY,
123 nscoord aPageIncrement,
124 nscoord aIncrement);
125 /**
126 * @note This method might destroy the frame, pres shell and other objects.
127 */
128 void SetScrollbarEnabled(nsIContent* aContent, nscoord aMaxPos);
129 /**
130 * @note This method might destroy the frame, pres shell and other objects.
131 */
132 void SetCoordAttribute(nsIContent* aContent, nsIAtom* aAtom, nscoord aSize);
134 nscoord GetCoordAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aDefaultValue,
135 nscoord* aRangeStart, nscoord* aRangeLength);
137 /**
138 * @note This method might destroy the frame, pres shell and other objects.
139 * Update scrollbar curpos attributes to reflect current scroll position
140 */
141 void UpdateScrollbarPosition();
143 nsRect GetScrollPortRect() const { return mScrollPort; }
144 nsPoint GetScrollPosition() const {
145 return mScrollPort.TopLeft() - mScrolledFrame->GetPosition();
146 }
147 /**
148 * For LTR frames, the logical scroll position is the offset of the top left
149 * corner of the frame from the top left corner of the scroll port (same as
150 * GetScrollPosition).
151 * For RTL frames, it is the offset of the top right corner of the frame from
152 * the top right corner of the scroll port
153 */
154 nsPoint GetLogicalScrollPosition() const {
155 nsPoint pt;
156 pt.x = IsLTR() ?
157 mScrollPort.x - mScrolledFrame->GetPosition().x :
158 mScrollPort.XMost() - mScrolledFrame->GetRect().XMost();
159 pt.y = mScrollPort.y - mScrolledFrame->GetPosition().y;
160 return pt;
161 }
162 nsRect GetScrollRange() const;
163 // Get the scroll range assuming the scrollport has size (aWidth, aHeight).
164 nsRect GetScrollRange(nscoord aWidth, nscoord aHeight) const;
165 nsSize GetScrollPositionClampingScrollPortSize() const;
166 gfxSize GetResolution() const;
167 void SetResolution(const gfxSize& aResolution);
169 protected:
170 nsRect GetScrollRangeForClamping() const;
172 public:
173 static void AsyncScrollCallback(void* anInstance, mozilla::TimeStamp aTime);
174 /**
175 * @note This method might destroy the frame, pres shell and other objects.
176 * aRange is the range of allowable scroll positions around the desired
177 * aScrollPosition. Null means only aScrollPosition is allowed.
178 * This is a closed-ended range --- aRange.XMost()/aRange.YMost() are allowed.
179 */
180 void ScrollTo(nsPoint aScrollPosition, nsIScrollableFrame::ScrollMode aMode,
181 const nsRect* aRange = nullptr) {
182 ScrollToWithOrigin(aScrollPosition, aMode, nsGkAtoms::other, aRange);
183 }
184 /**
185 * @note This method might destroy the frame, pres shell and other objects.
186 */
187 void ScrollToCSSPixels(const CSSIntPoint& aScrollPosition);
188 /**
189 * @note This method might destroy the frame, pres shell and other objects.
190 */
191 void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition,
192 nsIAtom* aOrigin = nullptr);
194 CSSIntPoint GetScrollPositionCSSPixels();
195 /**
196 * @note This method might destroy the frame, pres shell and other objects.
197 */
198 void ScrollToImpl(nsPoint aScrollPosition, const nsRect& aRange, nsIAtom* aOrigin = nullptr);
199 void ScrollVisual(nsPoint aOldScrolledFramePosition);
200 /**
201 * @note This method might destroy the frame, pres shell and other objects.
202 */
203 void ScrollBy(nsIntPoint aDelta, nsIScrollableFrame::ScrollUnit aUnit,
204 nsIScrollableFrame::ScrollMode aMode, nsIntPoint* aOverflow, nsIAtom *aOrigin = nullptr);
205 /**
206 * @note This method might destroy the frame, pres shell and other objects.
207 */
208 void ScrollToRestoredPosition();
210 nsSize GetLineScrollAmount() const;
211 nsSize GetPageScrollAmount() const;
213 nsPresState* SaveState() const;
214 void RestoreState(nsPresState* aState);
216 nsIFrame* GetScrolledFrame() const { return mScrolledFrame; }
217 nsIFrame* GetScrollbarBox(bool aVertical) const {
218 return aVertical ? mVScrollbarBox : mHScrollbarBox;
219 }
221 void AddScrollPositionListener(nsIScrollPositionListener* aListener) {
222 mListeners.AppendElement(aListener);
223 }
224 void RemoveScrollPositionListener(nsIScrollPositionListener* aListener) {
225 mListeners.RemoveElement(aListener);
226 }
228 static void SetScrollbarVisibility(nsIFrame* aScrollbar, bool aVisible);
230 /**
231 * GetScrolledRect is designed to encapsulate deciding which
232 * directions of overflow should be reachable by scrolling and which
233 * should not. Callers should NOT depend on it having any particular
234 * behavior (although nsXULScrollFrame currently does).
235 *
236 * This should only be called when the scrolled frame has been
237 * reflowed with the scroll port size given in mScrollPort.
238 *
239 * Currently it allows scrolling down and to the right for
240 * nsHTMLScrollFrames with LTR directionality and for all
241 * nsXULScrollFrames, and allows scrolling down and to the left for
242 * nsHTMLScrollFrames with RTL directionality.
243 */
244 nsRect GetScrolledRect() const;
246 /**
247 * GetScrolledRectInternal is designed to encapsulate deciding which
248 * directions of overflow should be reachable by scrolling and which
249 * should not. Callers should NOT depend on it having any particular
250 * behavior (although nsXULScrollFrame currently does).
251 *
252 * Currently it allows scrolling down and to the right for
253 * nsHTMLScrollFrames with LTR directionality and for all
254 * nsXULScrollFrames, and allows scrolling down and to the left for
255 * nsHTMLScrollFrames with RTL directionality.
256 */
257 nsRect GetScrolledRectInternal(const nsRect& aScrolledOverflowArea,
258 const nsSize& aScrollPortSize) const;
260 uint32_t GetScrollbarVisibility() const {
261 return (mHasVerticalScrollbar ? nsIScrollableFrame::VERTICAL : 0) |
262 (mHasHorizontalScrollbar ? nsIScrollableFrame::HORIZONTAL : 0);
263 }
264 nsMargin GetActualScrollbarSizes() const;
265 nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState);
266 nscoord GetNondisappearingScrollbarWidth(nsBoxLayoutState* aState);
267 bool IsLTR() const;
268 bool IsScrollbarOnRight() const;
269 bool IsScrollingActive() const { return mScrollingActive || mShouldBuildScrollableLayer; }
270 bool IsProcessingAsyncScroll() const { return mAsyncScroll != nullptr; }
271 void ResetScrollPositionForLayerPixelAlignment()
272 {
273 mScrollPosForLayerPixelAlignment = GetScrollPosition();
274 }
276 bool UpdateOverflow();
278 void UpdateSticky();
280 bool IsRectNearlyVisible(const nsRect& aRect) const;
282 // adjust the scrollbar rectangle aRect to account for any visible resizer.
283 // aHasResizer specifies if there is a content resizer, however this method
284 // will also check if a widget resizer is present as well.
285 void AdjustScrollbarRectForResizer(nsIFrame* aFrame, nsPresContext* aPresContext,
286 nsRect& aRect, bool aHasResizer, bool aVertical);
287 // returns true if a resizer should be visible
288 bool HasResizer() { return mResizerBox && !mCollapsedResizer; }
289 void LayoutScrollbars(nsBoxLayoutState& aState,
290 const nsRect& aContentArea,
291 const nsRect& aOldScrollArea);
293 bool IsIgnoringViewportClipping() const;
295 bool ShouldClampScrollPosition() const;
297 bool IsAlwaysActive() const;
298 void MarkActive();
299 void MarkInactive();
300 nsExpirationState* GetExpirationState() { return &mActivityExpirationState; }
302 void ScheduleSyntheticMouseMove();
303 static void ScrollActivityCallback(nsITimer *aTimer, void* anInstance);
305 void HandleScrollbarStyleSwitching();
307 nsIAtom* OriginOfLastScroll() const { return mOriginOfLastScroll; }
308 uint32_t CurrentScrollGeneration() const { return mScrollGeneration; }
309 void ResetOriginIfScrollAtGeneration(uint32_t aGeneration) {
310 if (aGeneration == mScrollGeneration) {
311 mOriginOfLastScroll = nullptr;
312 }
313 }
314 bool WantAsyncScroll() const;
316 // owning references to the nsIAnonymousContentCreator-built content
317 nsCOMPtr<nsIContent> mHScrollbarContent;
318 nsCOMPtr<nsIContent> mVScrollbarContent;
319 nsCOMPtr<nsIContent> mScrollCornerContent;
320 nsCOMPtr<nsIContent> mResizerContent;
322 nsRevocableEventPtr<ScrollEvent> mScrollEvent;
323 nsRevocableEventPtr<AsyncScrollPortEvent> mAsyncScrollPortEvent;
324 nsRevocableEventPtr<ScrolledAreaEvent> mScrolledAreaEvent;
325 nsIFrame* mHScrollbarBox;
326 nsIFrame* mVScrollbarBox;
327 nsIFrame* mScrolledFrame;
328 nsIFrame* mScrollCornerBox;
329 nsIFrame* mResizerBox;
330 nsContainerFrame* mOuter;
331 nsRefPtr<AsyncScroll> mAsyncScroll;
332 nsRefPtr<ScrollbarActivity> mScrollbarActivity;
333 nsTArray<nsIScrollPositionListener*> mListeners;
334 nsIAtom* mOriginOfLastScroll;
335 uint32_t mScrollGeneration;
336 nsRect mScrollPort;
337 // Where we're currently scrolling to, if we're scrolling asynchronously.
338 // If we're not in the middle of an asynchronous scroll then this is
339 // just the current scroll position. ScrollBy will choose its
340 // destination based on this value.
341 nsPoint mDestination;
342 nsPoint mScrollPosAtLastPaint;
344 // A goal position to try to scroll to as content loads. As long as mLastPos
345 // matches the current logical scroll position, we try to scroll to mRestorePos
346 // after every reflow --- because after each time content is loaded/added to the
347 // scrollable element, there will be a reflow.
348 nsPoint mRestorePos;
349 // The last logical position we scrolled to while trying to restore mRestorePos, or
350 // 0,0 when this is a new frame. Set to -1,-1 once we've scrolled for any reason
351 // other than trying to restore mRestorePos.
352 nsPoint mLastPos;
354 // The current resolution derived from the zoom level and device pixel ratio.
355 gfxSize mResolution;
357 nsExpirationState mActivityExpirationState;
359 nsCOMPtr<nsITimer> mScrollActivityTimer;
360 nsPoint mScrollPosForLayerPixelAlignment;
362 // The scroll position where we last updated image visibility.
363 nsPoint mLastUpdateImagesPos;
365 bool mNeverHasVerticalScrollbar:1;
366 bool mNeverHasHorizontalScrollbar:1;
367 bool mHasVerticalScrollbar:1;
368 bool mHasHorizontalScrollbar:1;
369 bool mFrameIsUpdatingScrollbar:1;
370 bool mDidHistoryRestore:1;
371 // Is this the scrollframe for the document's viewport?
372 bool mIsRoot:1;
373 // True if we should clip all descendants, false if we should only clip
374 // descendants for which we are the containing block.
375 bool mClipAllDescendants:1;
376 // If true, don't try to layout the scrollbars in Reflow(). This can be
377 // useful if multiple passes are involved, because we don't want to place the
378 // scrollbars at the wrong size.
379 bool mSupppressScrollbarUpdate:1;
380 // If true, we skipped a scrollbar layout due to mSupppressScrollbarUpdate
381 // being set at some point. That means we should lay out scrollbars even if
382 // it might not strictly be needed next time mSupppressScrollbarUpdate is
383 // false.
384 bool mSkippedScrollbarLayout:1;
386 bool mHadNonInitialReflow:1;
387 // State used only by PostScrollEvents so we know
388 // which overflow states have changed.
389 bool mHorizontalOverflow:1;
390 bool mVerticalOverflow:1;
391 bool mPostedReflowCallback:1;
392 bool mMayHaveDirtyFixedChildren:1;
393 // If true, need to actually update our scrollbar attributes in the
394 // reflow callback.
395 bool mUpdateScrollbarAttributes:1;
396 // If true, we should be prepared to scroll using this scrollframe
397 // by placing descendant content into its own layer(s)
398 bool mScrollingActive:1;
399 // If true, the resizer is collapsed and not displayed
400 bool mCollapsedResizer:1;
402 // If true, the layer should always be active because we always build a
403 // scrollable layer. Used for asynchronous scrolling.
404 bool mShouldBuildScrollableLayer:1;
406 // True if this frame has been scrolled at least once
407 bool mHasBeenScrolled:1;
409 // True if the frame's resolution has been set via SetResolution or restored
410 // via RestoreState.
411 bool mIsResolutionSet:1;
413 protected:
414 /**
415 * @note This method might destroy the frame, pres shell and other objects.
416 */
417 void ScrollToWithOrigin(nsPoint aScrollPosition,
418 nsIScrollableFrame::ScrollMode aMode,
419 nsIAtom *aOrigin, // nullptr indicates "other" origin
420 const nsRect* aRange);
422 nsRect ExpandRect(const nsRect& aRect) const;
423 static void EnsureImageVisPrefsCached();
424 static bool sImageVisPrefsCached;
425 // The number of scrollports wide/high to expand when looking for images.
426 static uint32_t sHorzExpandScrollPort;
427 static uint32_t sVertExpandScrollPort;
428 // The fraction of the scrollport we allow to scroll by before we schedule
429 // an update of image visibility.
430 static int32_t sHorzScrollFraction;
431 static int32_t sVertScrollFraction;
432 };
434 }
436 /**
437 * The scroll frame creates and manages the scrolling view
438 *
439 * It only supports having a single child frame that typically is an area
440 * frame, but doesn't have to be. The child frame must have a view, though
441 *
442 * Scroll frames don't support incremental changes, i.e. you can't replace
443 * or remove the scrolled frame
444 */
445 class nsHTMLScrollFrame : public nsContainerFrame,
446 public nsIScrollableFrame,
447 public nsIAnonymousContentCreator,
448 public nsIStatefulFrame {
449 public:
450 typedef mozilla::ScrollFrameHelper ScrollFrameHelper;
451 typedef mozilla::CSSIntPoint CSSIntPoint;
452 friend nsIFrame* NS_NewHTMLScrollFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, bool aIsRoot);
454 NS_DECL_QUERYFRAME
455 NS_DECL_FRAMEARENA_HELPERS
457 // Called to set the child frames. We typically have three: the scroll area,
458 // the vertical scrollbar, and the horizontal scrollbar.
459 virtual nsresult SetInitialChildList(ChildListID aListID,
460 nsFrameList& aChildList) MOZ_OVERRIDE;
462 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
463 const nsRect& aDirtyRect,
464 const nsDisplayListSet& aLists) MOZ_OVERRIDE {
465 mHelper.BuildDisplayList(aBuilder, aDirtyRect, aLists);
466 }
468 bool TryLayout(ScrollReflowState* aState,
469 nsHTMLReflowMetrics* aKidMetrics,
470 bool aAssumeVScroll, bool aAssumeHScroll,
471 bool aForce, nsresult* aResult);
472 bool ScrolledContentDependsOnHeight(ScrollReflowState* aState);
473 nsresult ReflowScrolledFrame(ScrollReflowState* aState,
474 bool aAssumeHScroll,
475 bool aAssumeVScroll,
476 nsHTMLReflowMetrics* aMetrics,
477 bool aFirstPass);
478 nsresult ReflowContents(ScrollReflowState* aState,
479 const nsHTMLReflowMetrics& aDesiredSize);
480 void PlaceScrollArea(const ScrollReflowState& aState,
481 const nsPoint& aScrollPosition);
482 nscoord GetIntrinsicVScrollbarWidth(nsRenderingContext *aRenderingContext);
484 virtual bool GetBorderRadii(nscoord aRadii[8]) const MOZ_OVERRIDE {
485 return mHelper.GetBorderRadii(aRadii);
486 }
488 virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
489 virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
490 virtual nsresult GetPadding(nsMargin& aPadding) MOZ_OVERRIDE;
491 virtual bool IsCollapsed() MOZ_OVERRIDE;
493 virtual nsresult Reflow(nsPresContext* aPresContext,
494 nsHTMLReflowMetrics& aDesiredSize,
495 const nsHTMLReflowState& aReflowState,
496 nsReflowStatus& aStatus) MOZ_OVERRIDE;
498 virtual bool UpdateOverflow() MOZ_OVERRIDE {
499 return mHelper.UpdateOverflow();
500 }
502 // Because there can be only one child frame, these two function return
503 // NS_ERROR_FAILURE
504 virtual nsresult AppendFrames(ChildListID aListID,
505 nsFrameList& aFrameList) MOZ_OVERRIDE;
506 virtual nsresult InsertFrames(ChildListID aListID,
507 nsIFrame* aPrevFrame,
508 nsFrameList& aFrameList) MOZ_OVERRIDE;
510 virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
513 virtual nsresult RemoveFrame(ChildListID aListID,
514 nsIFrame* aOldFrame) MOZ_OVERRIDE;
516 virtual nsIScrollableFrame* GetScrollTargetFrame() MOZ_OVERRIDE {
517 return this;
518 }
520 virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
521 return mHelper.GetScrolledFrame()->GetContentInsertionFrame();
522 }
524 virtual bool DoesClipChildren() MOZ_OVERRIDE { return true; }
525 virtual nsSplittableType GetSplittableType() const MOZ_OVERRIDE;
527 virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild) MOZ_OVERRIDE
528 { nsPoint pt = aChild->GetPosition();
529 if (aChild == mHelper.GetScrolledFrame()) pt += GetScrollPosition();
530 return pt;
531 }
533 // nsIAnonymousContentCreator
534 virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) MOZ_OVERRIDE;
535 virtual void AppendAnonymousContentTo(nsBaseContentList& aElements,
536 uint32_t aFilter) MOZ_OVERRIDE;
538 // nsIScrollbarOwner
539 virtual nsIFrame* GetScrollbarBox(bool aVertical) MOZ_OVERRIDE {
540 return mHelper.GetScrollbarBox(aVertical);
541 }
543 virtual void ScrollbarActivityStarted() const MOZ_OVERRIDE;
544 virtual void ScrollbarActivityStopped() const MOZ_OVERRIDE;
546 // nsIScrollableFrame
547 virtual nsIFrame* GetScrolledFrame() const MOZ_OVERRIDE {
548 return mHelper.GetScrolledFrame();
549 }
550 virtual mozilla::ScrollbarStyles GetScrollbarStyles() const MOZ_OVERRIDE {
551 return mHelper.GetScrollbarStylesFromFrame();
552 }
553 virtual uint32_t GetScrollbarVisibility() const MOZ_OVERRIDE {
554 return mHelper.GetScrollbarVisibility();
555 }
556 virtual nsMargin GetActualScrollbarSizes() const MOZ_OVERRIDE {
557 return mHelper.GetActualScrollbarSizes();
558 }
559 virtual nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState) MOZ_OVERRIDE {
560 return mHelper.GetDesiredScrollbarSizes(aState);
561 }
562 virtual nsMargin GetDesiredScrollbarSizes(nsPresContext* aPresContext,
563 nsRenderingContext* aRC) MOZ_OVERRIDE {
564 nsBoxLayoutState bls(aPresContext, aRC, 0);
565 return GetDesiredScrollbarSizes(&bls);
566 }
567 virtual nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext,
568 nsRenderingContext* aRC) MOZ_OVERRIDE {
569 nsBoxLayoutState bls(aPresContext, aRC, 0);
570 return mHelper.GetNondisappearingScrollbarWidth(&bls);
571 }
572 virtual nsRect GetScrolledRect() const MOZ_OVERRIDE {
573 return mHelper.GetScrolledRect();
574 }
575 virtual nsRect GetScrollPortRect() const MOZ_OVERRIDE {
576 return mHelper.GetScrollPortRect();
577 }
578 virtual nsPoint GetScrollPosition() const MOZ_OVERRIDE {
579 return mHelper.GetScrollPosition();
580 }
581 virtual nsPoint GetLogicalScrollPosition() const MOZ_OVERRIDE {
582 return mHelper.GetLogicalScrollPosition();
583 }
584 virtual nsRect GetScrollRange() const MOZ_OVERRIDE {
585 return mHelper.GetScrollRange();
586 }
587 virtual nsSize GetScrollPositionClampingScrollPortSize() const MOZ_OVERRIDE {
588 return mHelper.GetScrollPositionClampingScrollPortSize();
589 }
590 virtual gfxSize GetResolution() const MOZ_OVERRIDE {
591 return mHelper.GetResolution();
592 }
593 virtual void SetResolution(const gfxSize& aResolution) MOZ_OVERRIDE {
594 return mHelper.SetResolution(aResolution);
595 }
596 virtual nsSize GetLineScrollAmount() const MOZ_OVERRIDE {
597 return mHelper.GetLineScrollAmount();
598 }
599 virtual nsSize GetPageScrollAmount() const MOZ_OVERRIDE {
600 return mHelper.GetPageScrollAmount();
601 }
602 /**
603 * @note This method might destroy the frame, pres shell and other objects.
604 */
605 virtual void ScrollTo(nsPoint aScrollPosition, ScrollMode aMode,
606 const nsRect* aRange = nullptr) MOZ_OVERRIDE {
607 mHelper.ScrollTo(aScrollPosition, aMode, aRange);
608 }
609 /**
610 * @note This method might destroy the frame, pres shell and other objects.
611 */
612 virtual void ScrollToCSSPixels(const CSSIntPoint& aScrollPosition) MOZ_OVERRIDE {
613 mHelper.ScrollToCSSPixels(aScrollPosition);
614 }
615 virtual void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition,
616 nsIAtom* aOrigin = nullptr) MOZ_OVERRIDE {
617 mHelper.ScrollToCSSPixelsApproximate(aScrollPosition, aOrigin);
618 }
619 /**
620 * @note This method might destroy the frame, pres shell and other objects.
621 */
622 virtual CSSIntPoint GetScrollPositionCSSPixels() MOZ_OVERRIDE {
623 return mHelper.GetScrollPositionCSSPixels();
624 }
625 /**
626 * @note This method might destroy the frame, pres shell and other objects.
627 */
628 virtual void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode,
629 nsIntPoint* aOverflow, nsIAtom *aOrigin = nullptr) MOZ_OVERRIDE {
630 mHelper.ScrollBy(aDelta, aUnit, aMode, aOverflow, aOrigin);
631 }
632 /**
633 * @note This method might destroy the frame, pres shell and other objects.
634 */
635 virtual void ScrollToRestoredPosition() MOZ_OVERRIDE {
636 mHelper.ScrollToRestoredPosition();
637 }
638 virtual void AddScrollPositionListener(nsIScrollPositionListener* aListener) MOZ_OVERRIDE {
639 mHelper.AddScrollPositionListener(aListener);
640 }
641 virtual void RemoveScrollPositionListener(nsIScrollPositionListener* aListener) MOZ_OVERRIDE {
642 mHelper.RemoveScrollPositionListener(aListener);
643 }
644 /**
645 * @note This method might destroy the frame, pres shell and other objects.
646 */
647 virtual void CurPosAttributeChanged(nsIContent* aChild) MOZ_OVERRIDE {
648 mHelper.CurPosAttributeChanged(aChild);
649 }
650 NS_IMETHOD PostScrolledAreaEventForCurrentArea() MOZ_OVERRIDE {
651 mHelper.PostScrolledAreaEvent();
652 return NS_OK;
653 }
654 virtual bool IsScrollingActive() MOZ_OVERRIDE {
655 return mHelper.IsScrollingActive();
656 }
657 virtual bool IsProcessingAsyncScroll() MOZ_OVERRIDE {
658 return mHelper.IsProcessingAsyncScroll();
659 }
660 virtual void ResetScrollPositionForLayerPixelAlignment() MOZ_OVERRIDE {
661 mHelper.ResetScrollPositionForLayerPixelAlignment();
662 }
663 virtual bool IsResolutionSet() const MOZ_OVERRIDE {
664 return mHelper.mIsResolutionSet;
665 }
666 virtual bool DidHistoryRestore() const MOZ_OVERRIDE {
667 return mHelper.mDidHistoryRestore;
668 }
669 virtual void ClearDidHistoryRestore() MOZ_OVERRIDE {
670 mHelper.mDidHistoryRestore = false;
671 }
672 virtual bool IsRectNearlyVisible(const nsRect& aRect) MOZ_OVERRIDE {
673 return mHelper.IsRectNearlyVisible(aRect);
674 }
675 virtual nsIAtom* OriginOfLastScroll() MOZ_OVERRIDE {
676 return mHelper.OriginOfLastScroll();
677 }
678 virtual uint32_t CurrentScrollGeneration() MOZ_OVERRIDE {
679 return mHelper.CurrentScrollGeneration();
680 }
681 virtual void ResetOriginIfScrollAtGeneration(uint32_t aGeneration) MOZ_OVERRIDE {
682 mHelper.ResetOriginIfScrollAtGeneration(aGeneration);
683 }
684 virtual bool WantAsyncScroll() const MOZ_OVERRIDE {
685 return mHelper.WantAsyncScroll();
686 }
688 // nsIStatefulFrame
689 NS_IMETHOD SaveState(nsPresState** aState) MOZ_OVERRIDE {
690 NS_ENSURE_ARG_POINTER(aState);
691 *aState = mHelper.SaveState();
692 return NS_OK;
693 }
694 NS_IMETHOD RestoreState(nsPresState* aState) MOZ_OVERRIDE {
695 NS_ENSURE_ARG_POINTER(aState);
696 mHelper.RestoreState(aState);
697 return NS_OK;
698 }
700 /**
701 * Get the "type" of the frame
702 *
703 * @see nsGkAtoms::scrollFrame
704 */
705 virtual nsIAtom* GetType() const MOZ_OVERRIDE;
707 #ifdef DEBUG_FRAME_DUMP
708 virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
709 #endif
711 #ifdef ACCESSIBILITY
712 virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE;
713 #endif
715 protected:
716 nsHTMLScrollFrame(nsIPresShell* aShell, nsStyleContext* aContext, bool aIsRoot);
717 void SetSuppressScrollbarUpdate(bool aSuppress) {
718 mHelper.mSupppressScrollbarUpdate = aSuppress;
719 }
720 bool GuessHScrollbarNeeded(const ScrollReflowState& aState);
721 bool GuessVScrollbarNeeded(const ScrollReflowState& aState);
723 bool IsScrollbarUpdateSuppressed() const {
724 return mHelper.mSupppressScrollbarUpdate;
725 }
727 // Return whether we're in an "initial" reflow. Some reflows with
728 // NS_FRAME_FIRST_REFLOW set are NOT "initial" as far as we're concerned.
729 bool InInitialReflow() const;
731 /**
732 * Override this to return false if computed height/min-height/max-height
733 * should NOT be propagated to child content.
734 * nsListControlFrame uses this.
735 */
736 virtual bool ShouldPropagateComputedHeightToScrolledContent() const { return true; }
738 private:
739 friend class mozilla::ScrollFrameHelper;
740 ScrollFrameHelper mHelper;
741 };
743 /**
744 * The scroll frame creates and manages the scrolling view
745 *
746 * It only supports having a single child frame that typically is an area
747 * frame, but doesn't have to be. The child frame must have a view, though
748 *
749 * Scroll frames don't support incremental changes, i.e. you can't replace
750 * or remove the scrolled frame
751 */
752 class nsXULScrollFrame : public nsBoxFrame,
753 public nsIScrollableFrame,
754 public nsIAnonymousContentCreator,
755 public nsIStatefulFrame {
756 public:
757 typedef mozilla::ScrollFrameHelper ScrollFrameHelper;
758 typedef mozilla::CSSIntPoint CSSIntPoint;
760 NS_DECL_QUERYFRAME
761 NS_DECL_FRAMEARENA_HELPERS
763 friend nsIFrame* NS_NewXULScrollFrame(nsIPresShell* aPresShell, nsStyleContext* aContext,
764 bool aIsRoot, bool aClipAllDescendants);
766 // Called to set the child frames. We typically have three: the scroll area,
767 // the vertical scrollbar, and the horizontal scrollbar.
768 virtual nsresult SetInitialChildList(ChildListID aListID,
769 nsFrameList& aChildList) MOZ_OVERRIDE;
771 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
772 const nsRect& aDirtyRect,
773 const nsDisplayListSet& aLists) MOZ_OVERRIDE {
774 mHelper.BuildDisplayList(aBuilder, aDirtyRect, aLists);
775 }
777 // XXXldb Is this actually used?
778 #if 0
779 virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
780 #endif
782 virtual bool UpdateOverflow() MOZ_OVERRIDE {
783 return mHelper.UpdateOverflow();
784 }
786 // Because there can be only one child frame, these two function return
787 // NS_ERROR_FAILURE
788 virtual nsresult AppendFrames(ChildListID aListID,
789 nsFrameList& aFrameList) MOZ_OVERRIDE;
790 virtual nsresult InsertFrames(ChildListID aListID,
791 nsIFrame* aPrevFrame,
792 nsFrameList& aFrameList) MOZ_OVERRIDE;
794 virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
796 virtual nsresult RemoveFrame(ChildListID aListID,
797 nsIFrame* aOldFrame) MOZ_OVERRIDE;
799 virtual nsIScrollableFrame* GetScrollTargetFrame() MOZ_OVERRIDE {
800 return this;
801 }
803 virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
804 return mHelper.GetScrolledFrame()->GetContentInsertionFrame();
805 }
807 virtual bool DoesClipChildren() MOZ_OVERRIDE { return true; }
808 virtual nsSplittableType GetSplittableType() const MOZ_OVERRIDE;
810 virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild) MOZ_OVERRIDE
811 { nsPoint pt = aChild->GetPosition();
812 if (aChild == mHelper.GetScrolledFrame())
813 pt += mHelper.GetLogicalScrollPosition();
814 return pt;
815 }
817 // nsIAnonymousContentCreator
818 virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) MOZ_OVERRIDE;
819 virtual void AppendAnonymousContentTo(nsBaseContentList& aElements,
820 uint32_t aFilter) MOZ_OVERRIDE;
822 virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE;
823 virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE;
824 virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE;
825 virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE;
827 NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE;
828 virtual nsresult GetPadding(nsMargin& aPadding) MOZ_OVERRIDE;
830 virtual bool GetBorderRadii(nscoord aRadii[8]) const MOZ_OVERRIDE {
831 return mHelper.GetBorderRadii(aRadii);
832 }
834 nsresult Layout(nsBoxLayoutState& aState);
835 void LayoutScrollArea(nsBoxLayoutState& aState, const nsPoint& aScrollPosition);
837 static bool AddRemoveScrollbar(bool& aHasScrollbar,
838 nscoord& aXY,
839 nscoord& aSize,
840 nscoord aSbSize,
841 bool aOnRightOrBottom,
842 bool aAdd);
844 bool AddRemoveScrollbar(nsBoxLayoutState& aState,
845 bool aOnRightOrBottom,
846 bool aHorizontal,
847 bool aAdd);
849 bool AddHorizontalScrollbar (nsBoxLayoutState& aState, bool aOnBottom);
850 bool AddVerticalScrollbar (nsBoxLayoutState& aState, bool aOnRight);
851 void RemoveHorizontalScrollbar(nsBoxLayoutState& aState, bool aOnBottom);
852 void RemoveVerticalScrollbar (nsBoxLayoutState& aState, bool aOnRight);
854 static void AdjustReflowStateForPrintPreview(nsBoxLayoutState& aState, bool& aSetBack);
855 static void AdjustReflowStateBack(nsBoxLayoutState& aState, bool aSetBack);
857 // nsIScrollbarOwner
858 virtual nsIFrame* GetScrollbarBox(bool aVertical) MOZ_OVERRIDE {
859 return mHelper.GetScrollbarBox(aVertical);
860 }
862 virtual void ScrollbarActivityStarted() const MOZ_OVERRIDE;
863 virtual void ScrollbarActivityStopped() const MOZ_OVERRIDE;
865 // nsIScrollableFrame
866 virtual nsIFrame* GetScrolledFrame() const MOZ_OVERRIDE {
867 return mHelper.GetScrolledFrame();
868 }
869 virtual mozilla::ScrollbarStyles GetScrollbarStyles() const MOZ_OVERRIDE {
870 return mHelper.GetScrollbarStylesFromFrame();
871 }
872 virtual uint32_t GetScrollbarVisibility() const MOZ_OVERRIDE {
873 return mHelper.GetScrollbarVisibility();
874 }
875 virtual nsMargin GetActualScrollbarSizes() const MOZ_OVERRIDE {
876 return mHelper.GetActualScrollbarSizes();
877 }
878 virtual nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState) MOZ_OVERRIDE {
879 return mHelper.GetDesiredScrollbarSizes(aState);
880 }
881 virtual nsMargin GetDesiredScrollbarSizes(nsPresContext* aPresContext,
882 nsRenderingContext* aRC) MOZ_OVERRIDE {
883 nsBoxLayoutState bls(aPresContext, aRC, 0);
884 return GetDesiredScrollbarSizes(&bls);
885 }
886 virtual nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext,
887 nsRenderingContext* aRC) MOZ_OVERRIDE {
888 nsBoxLayoutState bls(aPresContext, aRC, 0);
889 return mHelper.GetNondisappearingScrollbarWidth(&bls);
890 }
891 virtual nsRect GetScrolledRect() const MOZ_OVERRIDE {
892 return mHelper.GetScrolledRect();
893 }
894 virtual nsRect GetScrollPortRect() const MOZ_OVERRIDE {
895 return mHelper.GetScrollPortRect();
896 }
897 virtual nsPoint GetScrollPosition() const MOZ_OVERRIDE {
898 return mHelper.GetScrollPosition();
899 }
900 virtual nsPoint GetLogicalScrollPosition() const MOZ_OVERRIDE {
901 return mHelper.GetLogicalScrollPosition();
902 }
903 virtual nsRect GetScrollRange() const MOZ_OVERRIDE {
904 return mHelper.GetScrollRange();
905 }
906 virtual nsSize GetScrollPositionClampingScrollPortSize() const MOZ_OVERRIDE {
907 return mHelper.GetScrollPositionClampingScrollPortSize();
908 }
909 virtual gfxSize GetResolution() const MOZ_OVERRIDE {
910 return mHelper.GetResolution();
911 }
912 virtual void SetResolution(const gfxSize& aResolution) MOZ_OVERRIDE {
913 return mHelper.SetResolution(aResolution);
914 }
915 virtual nsSize GetLineScrollAmount() const MOZ_OVERRIDE {
916 return mHelper.GetLineScrollAmount();
917 }
918 virtual nsSize GetPageScrollAmount() const MOZ_OVERRIDE {
919 return mHelper.GetPageScrollAmount();
920 }
921 /**
922 * @note This method might destroy the frame, pres shell and other objects.
923 */
924 virtual void ScrollTo(nsPoint aScrollPosition, ScrollMode aMode,
925 const nsRect* aRange = nullptr) MOZ_OVERRIDE {
926 mHelper.ScrollTo(aScrollPosition, aMode, aRange);
927 }
928 /**
929 * @note This method might destroy the frame, pres shell and other objects.
930 */
931 virtual void ScrollToCSSPixels(const CSSIntPoint& aScrollPosition) MOZ_OVERRIDE {
932 mHelper.ScrollToCSSPixels(aScrollPosition);
933 }
934 virtual void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition,
935 nsIAtom* aOrigin = nullptr) MOZ_OVERRIDE {
936 mHelper.ScrollToCSSPixelsApproximate(aScrollPosition, aOrigin);
937 }
938 virtual CSSIntPoint GetScrollPositionCSSPixels() MOZ_OVERRIDE {
939 return mHelper.GetScrollPositionCSSPixels();
940 }
941 /**
942 * @note This method might destroy the frame, pres shell and other objects.
943 */
944 virtual void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode,
945 nsIntPoint* aOverflow, nsIAtom* aOrigin = nullptr) MOZ_OVERRIDE {
946 mHelper.ScrollBy(aDelta, aUnit, aMode, aOverflow, aOrigin);
947 }
948 /**
949 * @note This method might destroy the frame, pres shell and other objects.
950 */
951 virtual void ScrollToRestoredPosition() MOZ_OVERRIDE {
952 mHelper.ScrollToRestoredPosition();
953 }
954 virtual void AddScrollPositionListener(nsIScrollPositionListener* aListener) MOZ_OVERRIDE {
955 mHelper.AddScrollPositionListener(aListener);
956 }
957 virtual void RemoveScrollPositionListener(nsIScrollPositionListener* aListener) MOZ_OVERRIDE {
958 mHelper.RemoveScrollPositionListener(aListener);
959 }
960 /**
961 * @note This method might destroy the frame, pres shell and other objects.
962 */
963 virtual void CurPosAttributeChanged(nsIContent* aChild) MOZ_OVERRIDE {
964 mHelper.CurPosAttributeChanged(aChild);
965 }
966 NS_IMETHOD PostScrolledAreaEventForCurrentArea() MOZ_OVERRIDE {
967 mHelper.PostScrolledAreaEvent();
968 return NS_OK;
969 }
970 virtual bool IsScrollingActive() MOZ_OVERRIDE {
971 return mHelper.IsScrollingActive();
972 }
973 virtual bool IsProcessingAsyncScroll() MOZ_OVERRIDE {
974 return mHelper.IsProcessingAsyncScroll();
975 }
976 virtual void ResetScrollPositionForLayerPixelAlignment() MOZ_OVERRIDE {
977 mHelper.ResetScrollPositionForLayerPixelAlignment();
978 }
979 virtual bool IsResolutionSet() const MOZ_OVERRIDE {
980 return mHelper.mIsResolutionSet;
981 }
982 virtual bool DidHistoryRestore() const MOZ_OVERRIDE {
983 return mHelper.mDidHistoryRestore;
984 }
985 virtual void ClearDidHistoryRestore() MOZ_OVERRIDE {
986 mHelper.mDidHistoryRestore = false;
987 }
988 virtual bool IsRectNearlyVisible(const nsRect& aRect) MOZ_OVERRIDE {
989 return mHelper.IsRectNearlyVisible(aRect);
990 }
991 virtual nsIAtom* OriginOfLastScroll() MOZ_OVERRIDE {
992 return mHelper.OriginOfLastScroll();
993 }
994 virtual uint32_t CurrentScrollGeneration() MOZ_OVERRIDE {
995 return mHelper.CurrentScrollGeneration();
996 }
997 virtual void ResetOriginIfScrollAtGeneration(uint32_t aGeneration) MOZ_OVERRIDE {
998 mHelper.ResetOriginIfScrollAtGeneration(aGeneration);
999 }
1000 virtual bool WantAsyncScroll() const MOZ_OVERRIDE {
1001 return mHelper.WantAsyncScroll();
1002 }
1004 // nsIStatefulFrame
1005 NS_IMETHOD SaveState(nsPresState** aState) MOZ_OVERRIDE {
1006 NS_ENSURE_ARG_POINTER(aState);
1007 *aState = mHelper.SaveState();
1008 return NS_OK;
1009 }
1010 NS_IMETHOD RestoreState(nsPresState* aState) MOZ_OVERRIDE {
1011 NS_ENSURE_ARG_POINTER(aState);
1012 mHelper.RestoreState(aState);
1013 return NS_OK;
1014 }
1016 /**
1017 * Get the "type" of the frame
1018 *
1019 * @see nsGkAtoms::scrollFrame
1020 */
1021 virtual nsIAtom* GetType() const MOZ_OVERRIDE;
1023 virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
1024 {
1025 // Override bogus IsFrameOfType in nsBoxFrame.
1026 if (aFlags & (nsIFrame::eReplacedContainsBlock | nsIFrame::eReplaced))
1027 return false;
1028 return nsBoxFrame::IsFrameOfType(aFlags);
1029 }
1031 #ifdef DEBUG_FRAME_DUMP
1032 virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
1033 #endif
1035 protected:
1036 nsXULScrollFrame(nsIPresShell* aShell, nsStyleContext* aContext, bool aIsRoot,
1037 bool aClipAllDescendants);
1039 void ClampAndSetBounds(nsBoxLayoutState& aState,
1040 nsRect& aRect,
1041 nsPoint aScrollPosition,
1042 bool aRemoveOverflowAreas = false) {
1043 /*
1044 * For RTL frames, restore the original scrolled position of the right
1045 * edge, then subtract the current width to find the physical position.
1046 */
1047 if (!mHelper.IsLTR()) {
1048 aRect.x = mHelper.mScrollPort.XMost() - aScrollPosition.x - aRect.width;
1049 }
1050 mHelper.mScrolledFrame->SetBounds(aState, aRect, aRemoveOverflowAreas);
1051 }
1053 private:
1054 friend class mozilla::ScrollFrameHelper;
1055 ScrollFrameHelper mHelper;
1056 };
1058 #endif /* nsGfxScrollFrame_h___ */