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

LibWeb: Move hit testing to the painting tree

This commit is contained in:
Andreas Kling 2022-03-11 00:03:28 +01:00
parent ba606d9057
commit 5779a910e5
18 changed files with 196 additions and 172 deletions

View file

@ -26,30 +26,10 @@ enum class LayoutMode {
OnlyRequiredLineBreaks,
};
struct HitTestResult {
RefPtr<Painting::Paintable> paintable;
int index_in_node { 0 };
enum InternalPosition {
None,
Before,
Inside,
After,
};
InternalPosition internal_position { None };
};
enum class HitTestType {
Exact, // Exact matches only
TextCursor, // Clicking past the right/bottom edge of text will still hit the text
};
class Node : public TreeNode<Node> {
public:
virtual ~Node();
virtual HitTestResult hit_test(const Gfx::IntPoint&, HitTestType) const;
bool is_anonymous() const { return !m_dom_node; }
const DOM::Node* dom_node() const { return m_dom_node; }
DOM::Node* dom_node() { return m_dom_node; }
@ -144,72 +124,6 @@ public:
SelectionState selection_state() const { return m_selection_state; }
void set_selection_state(SelectionState state) { m_selection_state = state; }
template<typename Callback>
void for_each_child_in_paint_order(Callback callback) const
{
// Element traversal using the order defined in https://www.w3.org/TR/CSS2/zindex.html#painting-order.
// Note: Some steps are skipped because they are not relevant to node traversal.
// 3. Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order
// (most negative first) then tree order.
// FIXME: This does not retrieve elements in the z-index order.
for_each_child([&](auto& child) {
if (!child.is_positioned() || !is<Box>(child))
return;
auto& box_child = verify_cast<Box>(child);
auto* stacking_context = box_child.paint_box()->stacking_context();
if (stacking_context && box_child.computed_values().z_index().has_value() && box_child.computed_values().z_index().value() < 0)
callback(child);
});
// 4. For all its in-flow, non-positioned, block-level descendants in tree order: If the element is a block, list-item,
// or other block equivalent:
for_each_child([&](auto& child) {
if (is<Box>(child) && verify_cast<Box>(child).paint_box()->stacking_context())
return;
if (!child.is_positioned())
callback(child);
});
// 5. All non-positioned floating descendants, in tree order. For each one of these, treat the element as if it created
// a new stacking context, but any positioned descendants and descendants which actually create a new stacking context
// should be considered part of the parent stacking context, not this new one.
for_each_child([&](auto& child) {
if (is<Box>(child) && verify_cast<Box>(child).paint_box()->stacking_context())
return;
if (child.is_positioned())
callback(child);
});
// 8. All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order. For those with 'z-index: auto', treat
// the element as if it created a new stacking context, but any positioned descendants and descendants which actually
// create a new stacking context should be considered part of the parent stacking context, not this new one. For those
// with 'z-index: 0', treat the stacking context generated atomically.
for_each_child([&](auto& child) {
if (!child.is_positioned() || !is<Box>(child))
return;
auto& box_child = verify_cast<Box>(child);
auto* stacking_context = box_child.paint_box()->stacking_context();
if (stacking_context && box_child.computed_values().z_index().has_value() && box_child.computed_values().z_index().value() == 0)
callback(child);
});
// 9. Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index order
// (smallest first) then tree order.
// FIXME: This does not retrieve elements in the z-index order.
for_each_child([&](auto& child) {
if (!child.is_positioned() || !is<Box>(child))
return;
auto& box_child = verify_cast<Box>(child);
auto* stacking_context = box_child.paint_box()->stacking_context();
if (stacking_context && box_child.computed_values().z_index().has_value() && box_child.computed_values().z_index().value() > 0)
callback(child);
});
}
protected:
Node(DOM::Document&, DOM::Node*);