blob: d44e74b1119467fcb36bf0d3b9a22c7775061eb9 [file] [log] [blame]
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* Copyright (C) 2006 Apple Computer, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_VIEW_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_VIEW_H_
#include <memory>
#include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/hit_test_cache.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_state.h"
#include "third_party/blink/renderer/core/scroll/scrollable_area.h"
#include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
class LayoutQuote;
class LocalFrameView;
class NamedPagesMapper;
class PaintLayerCompositor;
class ViewFragmentationContext;
// LayoutView is the root of the layout tree and the Document's LayoutObject.
//
// It corresponds to the CSS concept of 'initial containing block' (or ICB).
// http://www.w3.org/TR/CSS2/visudet.html#containing-block-details
//
// Its dimensions match that of the layout viewport. This viewport is used to
// size elements, in particular fixed positioned elements.
// LayoutView is always at position (0,0) relative to the document (and so isn't
// necessarily in view).
// See
// https://www.chromium.org/developers/design-documents/blink-coordinate-spaces
// about the different viewports.
//
// Because there is one LayoutView per rooted layout tree (or Frame), this class
// is used to add members shared by this tree (e.g. m_layoutState or
// m_layoutQuoteHead).
class CORE_EXPORT LayoutView final : public LayoutBlockFlow {
public:
explicit LayoutView(Document*);
~LayoutView() override;
void WillBeDestroyed() override;
// Called when the Document is shutdown, to have the compositor clean up
// during frame detach, while pointers remain valid.
void CleanUpCompositor();
// hitTest() will update layout, style and compositing first while
// hitTestNoLifecycleUpdate() does not.
bool HitTest(const HitTestLocation& location, HitTestResult&);
bool HitTestNoLifecycleUpdate(const HitTestLocation& location,
HitTestResult&);
// Returns the total count of calls to HitTest, for testing.
unsigned HitTestCount() const { return hit_test_count_; }
unsigned HitTestCacheHits() const { return hit_test_cache_hits_; }
void ClearHitTestCache();
const char* GetName() const override { return "LayoutView"; }
bool IsOfType(LayoutObjectType type) const override {
return type == kLayoutObjectLayoutView || LayoutBlockFlow::IsOfType(type);
}
PaintLayerType LayerTypeRequired() const override {
return kNormalPaintLayer;
}
bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override;
void UpdateLayout() override;
void UpdateLogicalWidth() override;
void ComputeLogicalHeight(LayoutUnit logical_height,
LayoutUnit logical_top,
LogicalExtentComputedValues&) const override;
// Based on LocalFrameView::LayoutSize, but:
// - checks for null LocalFrameView
// - returns 0x0 if using printing layout
// - scrollbar exclusion is compatible with root layer scrolling
IntSize GetLayoutSize(IncludeScrollbarsInRect = kExcludeScrollbars) const;
int ViewHeight(
IncludeScrollbarsInRect scrollbar_inclusion = kExcludeScrollbars) const {
return GetLayoutSize(scrollbar_inclusion).Height();
}
int ViewWidth(
IncludeScrollbarsInRect scrollbar_inclusion = kExcludeScrollbars) const {
return GetLayoutSize(scrollbar_inclusion).Width();
}
int ViewLogicalWidth(IncludeScrollbarsInRect = kExcludeScrollbars) const;
int ViewLogicalHeight(IncludeScrollbarsInRect = kExcludeScrollbars) const;
LayoutUnit ViewLogicalHeightForPercentages() const;
float ZoomFactor() const;
LocalFrameView* GetFrameView() const { return frame_view_; }
const LayoutBox& RootBox() const;
void UpdateAfterLayout() override;
// See comments for the equivalent method on LayoutObject.
bool MapToVisualRectInAncestorSpace(const LayoutBoxModelObject* ancestor,
PhysicalRect&,
MapCoordinatesFlags mode,
VisualRectFlags) const;
// |ancestor| can be nullptr, which will map the rect to the main frame's
// space, even if the main frame is remote (or has intermediate remote
// frames in the chain).
bool MapToVisualRectInAncestorSpaceInternal(
const LayoutBoxModelObject* ancestor,
TransformState&,
MapCoordinatesFlags,
VisualRectFlags) const;
bool MapToVisualRectInAncestorSpaceInternal(
const LayoutBoxModelObject* ancestor,
TransformState&,
VisualRectFlags = kDefaultVisualRectFlags) const override;
PhysicalOffset OffsetForFixedPosition() const;
PhysicalOffset PixelSnappedOffsetForFixedPosition() const;
void InvalidatePaintForViewAndCompositedLayers();
void Paint(const PaintInfo&) const override;
void PaintBoxDecorationBackground(
const PaintInfo&,
const PhysicalOffset& paint_offset) const override;
void CommitPendingSelection();
void AbsoluteQuads(Vector<FloatQuad>&,
MapCoordinatesFlags mode = 0) const override;
PhysicalRect ViewRect() const override;
PhysicalRect OverflowClipRect(const PhysicalOffset& location,
OverlayScrollbarClipBehavior =
kIgnoreOverlayScrollbarSize) const override;
// If either direction has a non-auto mode, the other must as well.
void SetAutosizeScrollbarModes(mojom::blink::ScrollbarMode h_mode,
mojom::blink::ScrollbarMode v_mode);
mojom::blink::ScrollbarMode AutosizeHorizontalScrollbarMode() const {
return autosize_h_scrollbar_mode_;
}
mojom::blink::ScrollbarMode AutosizeVerticalScrollbarMode() const {
return autosize_v_scrollbar_mode_;
}
void CalculateScrollbarModes(mojom::blink::ScrollbarMode& h_mode,
mojom::blink::ScrollbarMode& v_mode) const;
LayoutState* GetLayoutState() const { return layout_state_; }
bool CanHaveAdditionalCompositingReasons() const override { return true; }
CompositingReasons AdditionalCompositingReasons() const override;
void UpdateHitTestResult(HitTestResult&,
const PhysicalOffset&) const override;
ViewFragmentationContext* FragmentationContext() const {
return fragmentation_context_.get();
}
LayoutUnit PageLogicalHeight() const { return page_logical_height_; }
void SetPageLogicalHeight(LayoutUnit height) {
page_logical_height_ = height;
}
NamedPagesMapper* GetNamedPagesMapper() const {
return named_pages_mapper_.get();
}
PaintLayerCompositor* Compositor();
bool UsesCompositing() const;
PhysicalRect DocumentRect() const;
IntervalArena* GetIntervalArena();
void SetLayoutQuoteHead(LayoutQuote* head) { layout_quote_head_ = head; }
LayoutQuote* LayoutQuoteHead() const { return layout_quote_head_; }
// FIXME: This is a work around because the current implementation of counters
// requires walking the entire tree repeatedly and most pages don't actually
// use either feature so we shouldn't take the performance hit when not
// needed. Long term we should rewrite the counter and quotes code.
void AddLayoutCounter() {
layout_counter_count_++;
SetNeedsCounterUpdate();
}
void RemoveLayoutCounter() {
DCHECK_GT(layout_counter_count_, 0u);
layout_counter_count_--;
}
bool HasLayoutCounters() { return layout_counter_count_; }
void SetNeedsCounterUpdate() { needs_counter_update_ = true; }
void UpdateCounters();
bool BackgroundIsKnownToBeOpaqueInRect(
const PhysicalRect& local_rect) const override;
// Returns the viewport size in (CSS pixels) that vh and vw units are
// calculated from.
FloatSize ViewportSizeForViewportUnits() const;
void PushLayoutState(LayoutState& layout_state) {
layout_state_ = &layout_state;
}
void PopLayoutState() {
DCHECK(layout_state_);
layout_state_ = layout_state_->Next();
}
PhysicalRect LocalVisualRectIgnoringVisibility() const override;
// Invalidates paint for the entire view, including composited descendants,
// but not including child frames.
// It is very likely you do not want to call this method.
void SetShouldDoFullPaintInvalidationForViewAndAllDescendants();
bool ShouldPlaceBlockDirectionScrollbarOnLogicalLeft() const override;
PhysicalRect DebugRect() const override;
// Returns the coordinates of find-in-page scrollbar tickmarks. These come
// from DocumentMarkerController, unless overridden by OverrideTickmarks().
Vector<IntRect> GetTickmarks() const;
bool HasTickmarks() const;
// Sets the coordinates of find-in-page scrollbar tickmarks, bypassing
// DocumentMarkerController. This is used by the PDF plugin.
void OverrideTickmarks(const Vector<IntRect>&);
// Issues a paint invalidation on the layout viewport's vertical scrollbar
// (which is responsible for painting the tickmarks).
void InvalidatePaintForTickmarks();
bool RecalcLayoutOverflow() final;
// The visible background area, in the local coordinates. The view background
// will be painted in this rect. It's also the positioning area of fixed-
// attachment backgrounds.
PhysicalRect BackgroundRect() const {
return OverflowClipRect(PhysicalOffset());
}
// The previous BackgroundRect after the previous paint invalidation.
PhysicalRect PreviousBackgroundRect() const {
DCHECK_EQ(GetDocument().Lifecycle().GetState(),
DocumentLifecycle::kInPrePaint);
return previous_background_rect_;
}
void SetPreviousBackgroundRect(const PhysicalRect& r) const {
DCHECK_EQ(GetDocument().Lifecycle().GetState(),
DocumentLifecycle::kInPrePaint);
previous_background_rect_ = r;
}
void MapAncestorToLocal(const LayoutBoxModelObject*,
TransformState&,
MapCoordinatesFlags) const override;
bool ShouldUsePrintingLayout() const;
void MapLocalToAncestor(const LayoutBoxModelObject* ancestor,
TransformState&,
MapCoordinatesFlags) const override;
private:
const LayoutObject* PushMappingToContainer(
const LayoutBoxModelObject* ancestor_to_stop_at,
LayoutGeometryMap&) const override;
bool CanHaveChildren() const override;
void UpdateBlockLayout(bool relayout_children) override;
#if DCHECK_IS_ON()
void CheckLayoutState();
#endif
void UpdateFromStyle() override;
int ViewLogicalWidthForBoxSizing() const {
return ViewLogicalWidth(kIncludeScrollbars);
}
int ViewLogicalHeightForBoxSizing() const {
return ViewLogicalHeight(kIncludeScrollbars);
}
bool UpdateLogicalWidthAndColumnWidth() override;
UntracedMember<LocalFrameView> frame_view_;
// The page logical height.
// This is only used during printing to split the content into pages.
// Outside of printing, this is 0.
LayoutUnit page_logical_height_;
// LayoutState is an optimization used during layout.
// |m_layoutState| will be nullptr outside of layout.
//
// See the class comment for more details.
LayoutState* layout_state_;
std::unique_ptr<ViewFragmentationContext> fragmentation_context_;
std::unique_ptr<NamedPagesMapper> named_pages_mapper_;
std::unique_ptr<PaintLayerCompositor> compositor_;
scoped_refptr<IntervalArena> interval_arena_;
LayoutQuote* layout_quote_head_;
unsigned layout_counter_count_;
bool needs_counter_update_ = false;
unsigned hit_test_count_;
unsigned hit_test_cache_hits_;
Persistent<HitTestCache> hit_test_cache_;
// FrameViewAutoSizeInfo controls scrollbar appearance manually rather than
// relying on layout. These members are used to override the ScrollbarModes
// calculated from style. kScrollbarAuto disables the override.
mojom::blink::ScrollbarMode autosize_h_scrollbar_mode_;
mojom::blink::ScrollbarMode autosize_v_scrollbar_mode_;
Vector<IntRect> tickmarks_override_;
mutable PhysicalRect previous_background_rect_;
};
template <>
struct DowncastTraits<LayoutView> {
static bool AllowFrom(const LayoutObject& object) {
return object.IsLayoutView();
}
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_VIEW_H_