Преглед на файлове

LibWeb: Add initial version of pointer-events CSS property

huwdp преди 3 години
родител
ревизия
ec43f7a2b0

+ 4 - 0
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<int> 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; }

+ 5 - 1
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,

+ 16 - 0
Userland/Libraries/LibWeb/CSS/StyleProperties.cpp

@@ -355,6 +355,22 @@ Optional<CSS::TextAlign> StyleProperties::text_align() const
     }
 }
 
+Optional<CSS::PointerEvents> 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<CSS::WhiteSpace> StyleProperties::white_space() const
 {
     auto value = property(CSS::PropertyID::WhiteSpace);

+ 1 - 0
Userland/Libraries/LibWeb/CSS/StyleProperties.h

@@ -67,6 +67,7 @@ public:
     Optional<CSS::Repeat> background_repeat_y() const;
     Optional<CSS::BoxShadowData> box_shadow() const;
     CSS::BoxSizing box_sizing() const;
+    Optional<CSS::PointerEvents> pointer_events() const;
 
     Vector<CSS::Transformation> transformations() const;
 

+ 5 - 0
Userland/Libraries/LibWeb/CSS/StyleValue.h

@@ -211,6 +211,11 @@ enum class WhiteSpace {
     PreWrap,
 };
 
+enum class PointerEvents {
+    Auto,
+    None
+};
+
 class StyleValue : public RefCounted<StyleValue> {
 public:
     virtual ~StyleValue();

+ 4 - 0
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());

+ 18 - 6
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<DOM::Node> 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()));