mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
LibWeb: Add basic support for position:fixed
Fixed position elements have the ICB as their containing block. The magic of fixed positioning is implemented at the rendering stage, where we temporarily translate painting by the current scroll offset. Note that "absolutely positioned" includes both position:absolute and position:fixed.
This commit is contained in:
parent
bd33bfd120
commit
137f6d44ec
Notes:
sideshowbarker
2024-07-19 05:42:43 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/137f6d44ec4
8 changed files with 27 additions and 11 deletions
|
@ -29,6 +29,7 @@
|
|||
#include <LibWeb/DOM/Element.h>
|
||||
#include <LibWeb/Dump.h>
|
||||
#include <LibWeb/Layout/LayoutBlock.h>
|
||||
#include <LibWeb/Layout/LayoutDocument.h>
|
||||
#include <LibWeb/Layout/LayoutInline.h>
|
||||
#include <LibWeb/Layout/LayoutReplaced.h>
|
||||
#include <LibWeb/Layout/LayoutText.h>
|
||||
|
@ -67,10 +68,10 @@ void LayoutBlock::layout(LayoutMode layout_mode)
|
|||
compute_height();
|
||||
|
||||
if (layout_mode == LayoutMode::Default)
|
||||
layout_absolute_descendants();
|
||||
layout_absolutely_positioned_descendants();
|
||||
}
|
||||
|
||||
void LayoutBlock::layout_absolute_descendants()
|
||||
void LayoutBlock::layout_absolutely_positioned_descendants()
|
||||
{
|
||||
for (auto& box : m_absolutely_positioned_descendants) {
|
||||
box->layout(LayoutMode::Default);
|
||||
|
@ -441,9 +442,7 @@ void LayoutBlock::compute_width()
|
|||
|
||||
void LayoutBlock::compute_position()
|
||||
{
|
||||
// Absolutely positioned blocks are positioned by position_absolute_boxes()
|
||||
if (is_absolutely_positioned()) {
|
||||
dbg() << "Is abspos, adding to containing block " << containing_block()->node()->tag_name();
|
||||
const_cast<LayoutBlock*>(containing_block())->add_absolutely_positioned_descendant(*this);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ protected:
|
|||
void compute_width();
|
||||
void compute_position();
|
||||
void compute_height();
|
||||
void layout_absolute_descendants();
|
||||
void layout_absolutely_positioned_descendants();
|
||||
|
||||
private:
|
||||
virtual bool is_block() const override { return true; }
|
||||
|
|
|
@ -194,6 +194,10 @@ void LayoutBox::render(RenderingContext& context)
|
|||
if (!is_visible())
|
||||
return;
|
||||
|
||||
Gfx::PainterStateSaver saver(context.painter());
|
||||
if (is_fixed_position())
|
||||
context.painter().translate(context.scroll_offset());
|
||||
|
||||
#ifdef DRAW_BOXES_AROUND_LAYOUT_NODES
|
||||
context.painter().draw_rect(m_rect, Color::Blue);
|
||||
#endif
|
||||
|
|
|
@ -58,7 +58,7 @@ void LayoutDocument::layout(LayoutMode layout_mode)
|
|||
});
|
||||
set_height(lowest_bottom);
|
||||
|
||||
layout_absolute_descendants();
|
||||
layout_absolutely_positioned_descendants();
|
||||
|
||||
// FIXME: This is a total hack. Make sure any GUI::Widgets are moved into place after layout.
|
||||
// We should stop embedding GUI::Widgets entirely, since that won't work out-of-process.
|
||||
|
|
|
@ -72,7 +72,9 @@ const LayoutBlock* LayoutNode::containing_block() const
|
|||
if (is_text())
|
||||
return nearest_block_ancestor();
|
||||
|
||||
if (is_absolutely_positioned()) {
|
||||
auto position = style().position();
|
||||
|
||||
if (position == CSS::Position::Absolute) {
|
||||
auto* ancestor = parent();
|
||||
while (ancestor && !ancestor->can_contain_boxes_with_position_absolute())
|
||||
ancestor = ancestor->parent();
|
||||
|
@ -81,7 +83,7 @@ const LayoutBlock* LayoutNode::containing_block() const
|
|||
return to<LayoutBlock>(ancestor);
|
||||
}
|
||||
|
||||
if (style().position() == CSS::Position::Fixed)
|
||||
if (position == CSS::Position::Fixed)
|
||||
return &root();
|
||||
|
||||
return nearest_block_ancestor();
|
||||
|
@ -189,7 +191,13 @@ Gfx::FloatPoint LayoutNode::box_type_agnostic_position() const
|
|||
|
||||
bool LayoutNode::is_absolutely_positioned() const
|
||||
{
|
||||
return style().position() == CSS::Position::Absolute;
|
||||
auto position = style().position();
|
||||
return position == CSS::Position::Absolute || position == CSS::Position::Fixed;
|
||||
}
|
||||
|
||||
bool LayoutNode::is_fixed_position() const
|
||||
{
|
||||
return style().position() == CSS::Position::Fixed;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -171,6 +171,7 @@ public:
|
|||
virtual void render(RenderingContext&);
|
||||
|
||||
bool is_absolutely_positioned() const;
|
||||
bool is_fixed_position() const;
|
||||
|
||||
const LayoutBlock* containing_block() const;
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ void PageView::paint_event(GUI::PaintEvent& event)
|
|||
painter.translate(frame_thickness(), frame_thickness());
|
||||
painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
|
||||
|
||||
RenderingContext context(painter, palette());
|
||||
RenderingContext context(painter, palette(), { horizontal_scrollbar().value(), vertical_scrollbar().value() });
|
||||
context.set_should_show_line_box_borders(m_should_show_line_box_borders);
|
||||
context.set_viewport_rect(viewport_rect_in_content_coordinates());
|
||||
layout_root()->render(context);
|
||||
|
|
|
@ -34,9 +34,10 @@ namespace Web {
|
|||
|
||||
class RenderingContext {
|
||||
public:
|
||||
explicit RenderingContext(GUI::Painter& painter, const Palette& palette)
|
||||
explicit RenderingContext(GUI::Painter& painter, const Palette& palette, const Gfx::IntPoint& scroll_offset)
|
||||
: m_painter(painter)
|
||||
, m_palette(palette)
|
||||
, m_scroll_offset(scroll_offset)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -49,10 +50,13 @@ public:
|
|||
Gfx::IntRect viewport_rect() const { return m_viewport_rect; }
|
||||
void set_viewport_rect(const Gfx::IntRect& rect) { m_viewport_rect = rect; }
|
||||
|
||||
const Gfx::IntPoint& scroll_offset() const { return m_scroll_offset; }
|
||||
|
||||
private:
|
||||
GUI::Painter& m_painter;
|
||||
Palette m_palette;
|
||||
Gfx::IntRect m_viewport_rect;
|
||||
Gfx::IntPoint m_scroll_offset;
|
||||
bool m_should_show_line_box_borders { false };
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue