diff --git a/Userland/Libraries/LibWeb/CSS/ComputedValues.h b/Userland/Libraries/LibWeb/CSS/ComputedValues.h index 8e207e10b20..d9537e79cde 100644 --- a/Userland/Libraries/LibWeb/CSS/ComputedValues.h +++ b/Userland/Libraries/LibWeb/CSS/ComputedValues.h @@ -33,6 +33,7 @@ public: static CSS::AlignItems align_items() { return CSS::AlignItems::FlexStart; } static CSS::Overflow overflow() { return CSS::Overflow::Visible; } static CSS::BoxSizing box_sizing() { return CSS::BoxSizing::ContentBox; } + static CSS::PointerEvents pointer_events() { return CSS::PointerEvents::Auto; } }; struct BorderData { @@ -64,6 +65,7 @@ public: CSS::Float float_() const { return m_noninherited.float_; } CSS::Clear clear() const { return m_noninherited.clear; } CSS::Cursor cursor() const { return m_inherited.cursor; } + CSS::PointerEvents pointer_events() const { return m_inherited.pointer_events; } CSS::Display display() const { return m_noninherited.display; } Optional const& z_index() const { return m_noninherited.z_index; } CSS::TextAlign text_align() const { return m_inherited.text_align; } @@ -129,6 +131,7 @@ protected: struct { Color color { InitialValues::color() }; CSS::Cursor cursor { InitialValues::cursor() }; + CSS::PointerEvents pointer_events { InitialValues::pointer_events() }; CSS::TextAlign text_align { InitialValues::text_align() }; CSS::TextTransform text_transform { InitialValues::text_transform() }; CSS::WhiteSpace white_space { InitialValues::white_space() }; @@ -189,6 +192,7 @@ class MutableComputedValues final : public ComputedValues { public: void set_color(const Color& color) { m_inherited.color = color; } void set_cursor(CSS::Cursor cursor) { m_inherited.cursor = cursor; } + void set_pointer_events(CSS::PointerEvents value) { m_inherited.pointer_events = value; } void set_background_color(const Color& color) { m_noninherited.background_color = color; } void set_background_repeat_x(CSS::Repeat repeat) { m_noninherited.background_repeat_x = repeat; } void set_background_repeat_y(CSS::Repeat repeat) { m_noninherited.background_repeat_y = repeat; } diff --git a/Userland/Libraries/LibWeb/CSS/Properties.json b/Userland/Libraries/LibWeb/CSS/Properties.json index 78172dab4e7..d53dcfcd21f 100644 --- a/Userland/Libraries/LibWeb/CSS/Properties.json +++ b/Userland/Libraries/LibWeb/CSS/Properties.json @@ -1073,7 +1073,11 @@ }, "pointer-events": { "inherited": true, - "initial": "auto" + "initial": "auto", + "valid-identifiers": [ + "auto", + "none" + ] }, "position": { "inherited": false, diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp index 18e7dce1f3f..02205a76f55 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp @@ -355,6 +355,22 @@ Optional StyleProperties::text_align() const } } +Optional StyleProperties::pointer_events() const +{ + auto value = property(CSS::PropertyID::PointerEvents); + if (!value.has_value()) + return {}; + + switch (value.value()->to_identifier()) { + case CSS::ValueID::Auto: + return CSS::PointerEvents::Auto; + case CSS::ValueID::None: + return CSS::PointerEvents::None; + default: + return {}; + } +} + Optional StyleProperties::white_space() const { auto value = property(CSS::PropertyID::WhiteSpace); diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.h b/Userland/Libraries/LibWeb/CSS/StyleProperties.h index b78782889fe..4f1b5308d59 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.h +++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.h @@ -67,6 +67,7 @@ public: Optional background_repeat_y() const; Optional box_shadow() const; CSS::BoxSizing box_sizing() const; + Optional pointer_events() const; Vector transformations() const; diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h index 8dfe0acf7b2..903f67dce66 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h @@ -211,6 +211,11 @@ enum class WhiteSpace { PreWrap, }; +enum class PointerEvents { + Auto, + None +}; + class StyleValue : public RefCounted { public: virtual ~StyleValue(); diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index 41d94142cd2..cb9b1122207 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -312,6 +312,10 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& specified_style) if (cursor.has_value()) computed_values.set_cursor(cursor.value()); + auto pointer_events = specified_style.pointer_events(); + if (pointer_events.has_value()) + computed_values.set_pointer_events(pointer_events.value()); + auto text_decoration_line = specified_style.text_decoration_line(); if (text_decoration_line.has_value()) computed_values.set_text_decoration_line(text_decoration_line.value()); diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp index 8acfe1711e3..8541269565c 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp @@ -184,10 +184,16 @@ bool EventHandler::handle_mousedown(const Gfx::IntPoint& position, unsigned butt } NonnullRefPtr document = *m_frame.active_document(); + + // TODO: Allow selecting element behind if one on top has pointer-events set to none. + auto result = layout_root()->hit_test(position, Layout::HitTestType::Exact); + auto pointer_events = result.layout_node->computed_values().pointer_events(); + if (pointer_events == CSS::PointerEvents::None) + return false; + RefPtr node; { - auto result = layout_root()->hit_test(position, Layout::HitTestType::Exact); if (!result.layout_node) return false; @@ -306,6 +312,10 @@ bool EventHandler::handle_mousemove(const Gfx::IntPoint& position, unsigned butt return false; } + auto pointer_events = result.layout_node->computed_values().pointer_events(); + if (pointer_events == CSS::PointerEvents::None) + return false; + hovered_node_changed = node != document.hovered_node(); document.set_hovered_node(node); if (node) { @@ -313,11 +323,13 @@ bool EventHandler::handle_mousemove(const Gfx::IntPoint& position, unsigned butt if (hovered_link_element) is_hovering_link = true; - auto cursor = result.layout_node->computed_values().cursor(); - if (node->is_text() && cursor == CSS::Cursor::Auto) - hovered_node_cursor = Gfx::StandardCursor::IBeam; - else - hovered_node_cursor = cursor_css_to_gfx(cursor); + if (node->is_text()) { + auto cursor = result.layout_node->computed_values().cursor(); + if (cursor == CSS::Cursor::Auto) + hovered_node_cursor = Gfx::StandardCursor::IBeam; + else + hovered_node_cursor = cursor_css_to_gfx(cursor); + } auto offset = compute_mouse_event_offset(position, *result.layout_node); node->dispatch_event(UIEvents::MouseEvent::create(UIEvents::EventNames::mousemove, offset.x(), offset.y(), position.x(), position.y()));