1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 13:38:11 +00:00

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. :^)
This commit is contained in:
Andreas Kling 2019-10-14 17:54:17 +02:00
parent 605a225b53
commit 61ef17b87a
6 changed files with 52 additions and 1 deletions

View file

@ -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>

View file

@ -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>

View file

@ -90,6 +90,10 @@ a {
text-decoration: underline;
}
a:hover {
color: red;
}
hr {
margin-top: 4;
margin-bottom: 4;

View file

@ -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");

View file

@ -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();
}

View file

@ -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; }