mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-10-19 07:33:20 +00:00

The overlay shown for the node hovered in the inspector is painted as part of the normal tree traversal of all paintables. This works well in most cases, but falls short in specific scenarios: * If the hovered node or one of its ancestors establishes a stacking context and there is another element that establishes a stacking context close by or overlapping it, the overlay and especially the tooltip can become partially hidden behind the second element. Ditto for elements that act as if they established a stacking context. * If the hovered node or one of its ancestors involves clipping, the clip is applied to the overlay and espicially the tooltip. This can cause them to be partially invisible. * Similarly, if the hovered node or one of its ancestors has a defined mask, the mask is applied to the overlay, often making it mostly invisible. * No overlays are shown for SVG nodes because they are painted differently from HTML documents. Some of these problems may be fixable with the current system. But some seem like they fundamentally cannot work fully when the overlays are painted as part of the regular tree traversal. Instead we pull out painting the overlay as a separate pass executed after the tree traversal. This way we ensure that the overlays are always painted last and therefore on top of everything else. This also makes sure that the overlays are unaffected by clips and masks. And since overlay painting is independent from painting the actual elements, it just works as well. However we need to be careful, because we still need to apply some of the steps of the tree traversal to get the correct result. Namely we need to apply scroll offsets and transforms. To do so, we collect all ancestors of the hovered node and apply those as if we were in the normal tree traversal.
73 lines
2.5 KiB
C++
73 lines
2.5 KiB
C++
/*
|
|
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <LibWeb/HTML/BrowsingContext.h>
|
|
#include <LibWeb/Layout/Label.h>
|
|
#include <LibWeb/Layout/LabelableNode.h>
|
|
#include <LibWeb/Page/EventHandler.h>
|
|
#include <LibWeb/Painting/TextPaintable.h>
|
|
|
|
namespace Web::Painting {
|
|
|
|
GC_DEFINE_ALLOCATOR(TextPaintable);
|
|
|
|
GC::Ref<TextPaintable> TextPaintable::create(Layout::TextNode const& layout_node)
|
|
{
|
|
return layout_node.heap().allocate<TextPaintable>(layout_node);
|
|
}
|
|
|
|
TextPaintable::TextPaintable(Layout::TextNode const& layout_node)
|
|
: Paintable(layout_node)
|
|
{
|
|
}
|
|
|
|
bool TextPaintable::wants_mouse_events() const
|
|
{
|
|
return layout_node().first_ancestor_of_type<Layout::Label>();
|
|
}
|
|
|
|
TextPaintable::DispatchEventOfSameName TextPaintable::handle_mousedown(Badge<EventHandler>, CSSPixelPoint position, unsigned button, unsigned)
|
|
{
|
|
auto* label = layout_node().first_ancestor_of_type<Layout::Label>();
|
|
if (!label)
|
|
return DispatchEventOfSameName::No;
|
|
const_cast<Layout::Label*>(label)->handle_mousedown_on_label({}, position, button);
|
|
navigable()->event_handler().set_mouse_event_tracking_paintable(this);
|
|
return DispatchEventOfSameName::Yes;
|
|
}
|
|
|
|
TextPaintable::DispatchEventOfSameName TextPaintable::handle_mouseup(Badge<EventHandler>, CSSPixelPoint position, unsigned button, unsigned)
|
|
{
|
|
auto* label = layout_node().first_ancestor_of_type<Layout::Label>();
|
|
if (!label)
|
|
return DispatchEventOfSameName::No;
|
|
|
|
const_cast<Layout::Label*>(label)->handle_mouseup_on_label({}, position, button);
|
|
navigable()->event_handler().set_mouse_event_tracking_paintable(nullptr);
|
|
return DispatchEventOfSameName::Yes;
|
|
}
|
|
|
|
TextPaintable::DispatchEventOfSameName TextPaintable::handle_mousemove(Badge<EventHandler>, CSSPixelPoint position, unsigned button, unsigned)
|
|
{
|
|
auto* label = layout_node().first_ancestor_of_type<Layout::Label>();
|
|
if (!label)
|
|
return DispatchEventOfSameName::No;
|
|
const_cast<Layout::Label*>(label)->handle_mousemove_on_label({}, position, button);
|
|
return DispatchEventOfSameName::Yes;
|
|
}
|
|
|
|
void TextPaintable::paint_inspector_overlay_internal(DisplayListRecordingContext& context) const
|
|
{
|
|
if (auto const* parent_paintable = as_if<PaintableWithLines>(parent())) {
|
|
for (auto const& fragment : parent_paintable->fragments()) {
|
|
if (&fragment.paintable() == this) {
|
|
paint_text_fragment_debug_highlight(context, fragment);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|