1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 04:17:35 +00:00

LibWeb: Clear the mouse event tracking node when it stops wanting events

This can occur if a mouse click on a mouse event tracking node causes a
page navigation. As the old document is torn down, the event handler may
have a stale reference to the tracking node. If a subsequent mouse event
occurs on that node, we would crash trying to access the node's styled
properties that are no longer valid.

To fix this, when we are deciding what node to send the event to, and we
have a mouse event tracking node, check if that node still wants the
event. If not, clear the tracking node.
This commit is contained in:
Timothy Flynn 2023-04-27 09:19:20 -04:00 committed by Andreas Kling
parent 8f0b7fa370
commit 806e08425a
2 changed files with 37 additions and 33 deletions

View file

@ -170,12 +170,8 @@ bool EventHandler::handle_mousewheel(CSSPixelPoint position, unsigned button, un
bool handled_event = false;
JS::GCPtr<Painting::Paintable> paintable;
if (m_mouse_event_tracking_layout_node) {
paintable = m_mouse_event_tracking_layout_node->paintable();
} else {
if (auto result = paint_root()->hit_test(position, Painting::HitTestType::Exact); result.has_value())
paintable = result->paintable;
}
if (auto result = target_for_mouse_position(position); result.has_value())
paintable = result->paintable;
if (paintable) {
paintable->handle_mousewheel({}, position, buttons, modifiers, wheel_delta_x, wheel_delta_y);
@ -218,12 +214,8 @@ bool EventHandler::handle_mouseup(CSSPixelPoint position, unsigned button, unsig
bool handled_event = false;
JS::GCPtr<Painting::Paintable> paintable;
if (m_mouse_event_tracking_layout_node) {
paintable = m_mouse_event_tracking_layout_node->paintable();
} else {
if (auto result = paint_root()->hit_test(position, Painting::HitTestType::Exact); result.has_value())
paintable = result->paintable;
}
if (auto result = target_for_mouse_position(position); result.has_value())
paintable = result->paintable;
if (paintable && paintable->wants_mouse_events()) {
if (paintable->handle_mouseup({}, position, button, modifiers) == Painting::Paintable::DispatchEventOfSameName::No)
@ -337,14 +329,10 @@ bool EventHandler::handle_mousedown(CSSPixelPoint position, unsigned button, uns
{
JS::GCPtr<Painting::Paintable> paintable;
if (m_mouse_event_tracking_layout_node) {
paintable = m_mouse_event_tracking_layout_node->paintable();
} else {
auto result = paint_root()->hit_test(position, Painting::HitTestType::Exact);
if (!result.has_value())
return false;
if (auto result = target_for_mouse_position(position); result.has_value())
paintable = result->paintable;
}
else
return false;
auto pointer_events = paintable->computed_values().pointer_events();
// FIXME: Handle other values for pointer-events.
@ -435,13 +423,10 @@ bool EventHandler::handle_mousemove(CSSPixelPoint position, unsigned buttons, un
JS::GCPtr<Painting::Paintable> paintable;
Optional<int> start_index;
if (m_mouse_event_tracking_layout_node) {
paintable = m_mouse_event_tracking_layout_node->paintable();
} else {
if (auto result = paint_root()->hit_test(position, Painting::HitTestType::Exact); result.has_value()) {
paintable = result->paintable;
start_index = result->index_in_node;
}
if (auto result = target_for_mouse_position(position); result.has_value()) {
paintable = result->paintable;
start_index = result->index_in_node;
}
const HTML::HTMLAnchorElement* hovered_link_element = nullptr;
@ -548,14 +533,10 @@ bool EventHandler::handle_doubleclick(CSSPixelPoint position, unsigned button, u
return false;
JS::GCPtr<Painting::Paintable> paintable;
if (m_mouse_event_tracking_layout_node) {
paintable = m_mouse_event_tracking_layout_node->paintable();
} else {
auto result = paint_root()->hit_test(position, Painting::HitTestType::Exact);
if (!result.has_value())
return false;
if (auto result = target_for_mouse_position(position); result.has_value())
paintable = result->paintable;
}
else
return false;
auto pointer_events = paintable->computed_values().pointer_events();
// FIXME: Handle other values for pointer-events.
@ -830,4 +811,20 @@ CSSPixelPoint EventHandler::compute_mouse_event_page_offset(CSSPixelPoint event_
// 3. Return the sum of offset and the value of the events clientX attribute.
return event_client_offset.translated(scroll_offset);
}
Optional<EventHandler::Target> EventHandler::target_for_mouse_position(CSSPixelPoint position)
{
if (m_mouse_event_tracking_layout_node) {
if (m_mouse_event_tracking_layout_node->paintable()->wants_mouse_events())
return Target { m_mouse_event_tracking_layout_node->paintable(), {} };
m_mouse_event_tracking_layout_node = nullptr;
}
if (auto result = paint_root()->hit_test(position, Painting::HitTestType::Exact); result.has_value())
return Target { result->paintable.ptr(), result->index_in_node };
return {};
}
}