diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-10-14 17:54:17 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-10-14 17:55:04 +0200 |
commit | 61ef17b87ad7e8003184c9635c1ea34d106562ee (patch) | |
tree | 91d6adc086ff06b2390db744aea2817f44c96da6 | |
parent | 605a225b53197089c09b14cc507ca7c6d816694c (diff) | |
download | serenity-61ef17b87ad7e8003184c9635c1ea34d106562ee.zip |
LibHTML: Implement basic :hover pseudo-class support
This is currently very aggressive. Whenever the Document's hovered node
changes, we invalidate all style and do a full relayout.
It does look cool though. So cool that I'm adding it to the default
stylesheet. :^)
-rw-r--r-- | Base/home/anon/www/hover.html | 13 | ||||
-rw-r--r-- | Base/home/anon/www/welcome.html | 1 | ||||
-rw-r--r-- | Libraries/LibHTML/CSS/Default.css | 4 | ||||
-rw-r--r-- | Libraries/LibHTML/CSS/SelectorEngine.cpp | 23 | ||||
-rw-r--r-- | Libraries/LibHTML/DOM/Document.cpp | 10 | ||||
-rw-r--r-- | Libraries/LibHTML/DOM/Document.h | 2 |
6 files changed, 52 insertions, 1 deletions
diff --git a/Base/home/anon/www/hover.html b/Base/home/anon/www/hover.html new file mode 100644 index 0000000000..9ef4b42ab6 --- /dev/null +++ b/Base/home/anon/www/hover.html @@ -0,0 +1,13 @@ +<html> + <head> + <title>Hover test!</title> +<style> +a:hover { + color: red; +} +</style> + </head> + <body> + <a href="hover.html">this is a link</a> + </body> +</html> diff --git a/Base/home/anon/www/welcome.html b/Base/home/anon/www/welcome.html index 4fb6ab1d52..1f60a17eb9 100644 --- a/Base/home/anon/www/welcome.html +++ b/Base/home/anon/www/welcome.html @@ -32,6 +32,7 @@ h1 { <li><a href="link.html">link element</a></li> <li><a href="blink.html">blink element</a></li> <li><a href="br.html">br element</a></li> + <li><a href="hover.html">hover element</a></li> <li><a href="http://www.serenityos.org/">www.serenityos.org</a></li> </ul> </body> diff --git a/Libraries/LibHTML/CSS/Default.css b/Libraries/LibHTML/CSS/Default.css index 103544b5b9..a03583a6e6 100644 --- a/Libraries/LibHTML/CSS/Default.css +++ b/Libraries/LibHTML/CSS/Default.css @@ -90,6 +90,10 @@ a { text-decoration: underline; } +a:hover { + color: red; +} + hr { margin-top: 4; margin-bottom: 4; diff --git a/Libraries/LibHTML/CSS/SelectorEngine.cpp b/Libraries/LibHTML/CSS/SelectorEngine.cpp index ef8ab33ab0..e8a55c94b1 100644 --- a/Libraries/LibHTML/CSS/SelectorEngine.cpp +++ b/Libraries/LibHTML/CSS/SelectorEngine.cpp @@ -1,10 +1,33 @@ #include <LibHTML/CSS/SelectorEngine.h> +#include <LibHTML/DOM/Document.h> #include <LibHTML/DOM/Element.h> namespace SelectorEngine { +static bool matches_hover_pseudo_class(const Element& element) +{ + auto* hovered_node = element.document().hovered_node(); + if (!hovered_node) + return false; + if (&element == hovered_node) + return true; + return element.is_ancestor_of(*hovered_node); +} + bool matches(const Selector::Component& component, const Element& element) { + switch (component.pseudo_class) { + case Selector::Component::PseudoClass::None: + break; + case Selector::Component::PseudoClass::Link: + ASSERT_NOT_REACHED(); + break; + case Selector::Component::PseudoClass::Hover: + if (!matches_hover_pseudo_class(element)) + return false; + break; + } + switch (component.type) { case Selector::Component::Type::Id: return component.value == element.attribute("id"); diff --git a/Libraries/LibHTML/DOM/Document.cpp b/Libraries/LibHTML/DOM/Document.cpp index 492b1b231a..9c0586ec1c 100644 --- a/Libraries/LibHTML/DOM/Document.cpp +++ b/Libraries/LibHTML/DOM/Document.cpp @@ -195,3 +195,13 @@ const LayoutDocument* Document::layout_node() const { return static_cast<const LayoutDocument*>(Node::layout_node()); } + +void Document::set_hovered_node(Node* node) +{ + if (m_hovered_node == node) + return; + + m_hovered_node = node; + invalidate_style(); +} + diff --git a/Libraries/LibHTML/DOM/Document.h b/Libraries/LibHTML/DOM/Document.h index 148d577417..5c9b42fb9d 100644 --- a/Libraries/LibHTML/DOM/Document.h +++ b/Libraries/LibHTML/DOM/Document.h @@ -38,7 +38,7 @@ public: virtual String tag_name() const override { return "#document"; } - void set_hovered_node(Node* node) { m_hovered_node = node; } + void set_hovered_node(Node*); Node* hovered_node() { return m_hovered_node; } const Node* hovered_node() const { return m_hovered_node; } |