Files
ladybird/Libraries/LibWeb/Painting/DisplayListRecordingContext.cpp
Jonathan Gamble 8f1cb4cbb0 LibWeb: Implement resizing for eligible elements and update scrollbars
Add ElementResizeAction to Page (maybe there's a better place). It's
just a mousemove delegate that updates styles on the target element.

Add ChromeMetrics for zoom-invariant chrome like scrollbar thumb
thickness, resize gripper size, paddings, etc. It's not user-stylable
but separates basic concerns in a way that a visually gifted
designer unlike myself can adjust to taste.

These values are pre-divided by zoom factor so that PaintableBox can
continue using device_pixels_per_css_pixel calls as normal.

The adjusted metrics are computed on demand from Page multiple times
per paint cycle, which is not ideal but avoids lifetime management and
atomics. Maybe someone with more surety about the painting flow control
can improve this, but it won't be a huge win. If profiling shows
this slowing paints, then Ladybird is in good shape.

Update PaintableBox to draw the resize gripper and deconflict
the scrollbars. Set apropriate cursors for scrollbars and gripper in
mousemove. We override EventHandler's cursor handling because nothing
should ever come between a man and his resize gripper.

Chrome metrics use the CSSPixels class. This is good because it's
broadly compatible but bad because they're actually different units
when zoom is not 1.0. If that's a problem, we could make a new type
or just use double.
2026-01-12 11:00:14 +00:00

108 lines
3.5 KiB
C++

/*
* Copyright (c) 2018-2022, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Painting/DisplayListRecordingContext.h>
namespace Web {
static u64 s_next_paint_generation_id = 0;
DisplayListRecordingContext::DisplayListRecordingContext(Painting::DisplayListRecorder& display_list_recorder, Palette const& palette, double device_pixels_per_css_pixel, ChromeMetrics const& chrome_metrics)
: m_display_list_recorder(display_list_recorder)
, m_palette(palette)
, m_device_pixel_converter(device_pixels_per_css_pixel)
, m_chrome_metrics(chrome_metrics)
, m_paint_generation_id(s_next_paint_generation_id++)
{
}
CSSPixelRect DisplayListRecordingContext::css_viewport_rect() const
{
return {
m_device_viewport_rect.x().value() / m_device_pixel_converter.device_pixels_per_css_pixel(),
m_device_viewport_rect.y().value() / m_device_pixel_converter.device_pixels_per_css_pixel(),
m_device_viewport_rect.width().value() / m_device_pixel_converter.device_pixels_per_css_pixel(),
m_device_viewport_rect.height().value() / m_device_pixel_converter.device_pixels_per_css_pixel()
};
}
DevicePixels DisplayListRecordingContext::rounded_device_pixels(CSSPixels css_pixels) const
{
return m_device_pixel_converter.rounded_device_pixels(css_pixels);
}
DevicePixels DisplayListRecordingContext::enclosing_device_pixels(CSSPixels css_pixels) const
{
return m_device_pixel_converter.enclosing_device_pixels(css_pixels);
}
DevicePixels DisplayListRecordingContext::floored_device_pixels(CSSPixels css_pixels) const
{
return m_device_pixel_converter.floored_device_pixels(css_pixels);
}
DevicePixelPoint DisplayListRecordingContext::rounded_device_point(CSSPixelPoint point) const
{
return m_device_pixel_converter.rounded_device_point(point);
}
DevicePixelPoint DisplayListRecordingContext::floored_device_point(CSSPixelPoint point) const
{
return m_device_pixel_converter.floored_device_point(point);
}
DevicePixelRect DisplayListRecordingContext::enclosing_device_rect(CSSPixelRect rect) const
{
return m_device_pixel_converter.enclosing_device_rect(rect);
}
DevicePixelRect DisplayListRecordingContext::rounded_device_rect(CSSPixelRect rect) const
{
return m_device_pixel_converter.rounded_device_rect(rect);
}
DevicePixelSize DisplayListRecordingContext::enclosing_device_size(CSSPixelSize size) const
{
return m_device_pixel_converter.enclosing_device_size(size);
}
DevicePixelSize DisplayListRecordingContext::rounded_device_size(CSSPixelSize size) const
{
return m_device_pixel_converter.rounded_device_size(size);
}
CSSPixels DisplayListRecordingContext::scale_to_css_pixels(DevicePixels device_pixels) const
{
return CSSPixels::nearest_value_for(device_pixels.value() / m_device_pixel_converter.device_pixels_per_css_pixel());
}
CSSPixelPoint DisplayListRecordingContext::scale_to_css_point(DevicePixelPoint point) const
{
return {
scale_to_css_pixels(point.x()),
scale_to_css_pixels(point.y())
};
}
CSSPixelSize DisplayListRecordingContext::scale_to_css_size(DevicePixelSize size) const
{
return {
scale_to_css_pixels(size.width()),
scale_to_css_pixels(size.height())
};
}
CSSPixelRect DisplayListRecordingContext::scale_to_css_rect(DevicePixelRect rect) const
{
return {
scale_to_css_point(rect.location()),
scale_to_css_size(rect.size())
};
}
}