|
67 | 67 | #include <LibWeb/Page/Page.h>
|
68 | 68 | #include <LibWeb/Painting/PaintableBox.h>
|
69 | 69 | #include <LibWeb/Painting/ViewportPaintable.h>
|
| 70 | +#include <LibWeb/Selection/Selection.h> |
70 | 71 | #include <LibWeb/WebIDL/AbstractOperations.h>
|
71 | 72 | #include <LibWeb/WebIDL/DOMException.h>
|
72 | 73 | #include <LibWeb/WebIDL/ExceptionOr.h>
|
@@ -2599,6 +2600,73 @@ bool Element::check_visibility(Optional<CheckVisibilityOptions> options)
|
2599 | 2600 | return true;
|
2600 | 2601 | }
|
2601 | 2602 |
|
| 2603 | +// https://drafts.csswg.org/css-contain/#proximity-to-the-viewport |
| 2604 | +void Element::determine_proximity_to_the_viewport() |
| 2605 | +{ |
| 2606 | + // An element that has content-visibility: auto is in one of three states when it comes to its proximity to the viewport: |
| 2607 | + |
| 2608 | + // - The element is close to the viewport: In this state, the element is considered "on-screen": its paint |
| 2609 | + // containment box's overflow clip edge intersects with the viewport, or a user-agent defined margin around the |
| 2610 | + // viewport. |
| 2611 | + auto viewport_rect = document().viewport_rect(); |
| 2612 | + // NOTE: This margin is meant to allow the user agent to begin preparing for an element to be in the |
| 2613 | + // viewport soon. A margin of 50% is suggested as a reasonable default. |
| 2614 | + viewport_rect.inflate(viewport_rect.width(), viewport_rect.height()); |
| 2615 | + // FIXME: We don't have paint containment or the overflow clip edge yet, so this is just using the absolute rect for now. |
| 2616 | + if (paintable_box()->absolute_rect().intersects(viewport_rect)) |
| 2617 | + m_proximity_to_the_viewport = ProximityToTheViewport::CloseToTheViewport; |
| 2618 | + |
| 2619 | + // FIXME: If a filter (see [FILTER-EFFECTS-1]) with non local effects includes the element as part of its input, the user |
| 2620 | + // agent should also treat the element as relevant to the user when the filter’s output can affect the rendering |
| 2621 | + // within the viewport (or within the user-agent defined margin around the viewport), even if the element itself is |
| 2622 | + // still off-screen. |
| 2623 | + |
| 2624 | + // - The element is far away from the viewport: In this state, the element’s proximity to the viewport has been |
| 2625 | + // computed and is not close to the viewport. |
| 2626 | + m_proximity_to_the_viewport = ProximityToTheViewport::FarAwayFromTheViewport; |
| 2627 | + |
| 2628 | + // - The element’s proximity to the viewport is not determined: In this state, the computation to determine the |
| 2629 | + // element’s proximity to the viewport has not been done since the last time the element was connected. |
| 2630 | + // NOTE: This function is what does the computation to determine the element’s proximity to the viewport, so this is not the case. |
| 2631 | +} |
| 2632 | + |
| 2633 | +// https://drafts.csswg.org/css-contain/#relevant-to-the-user |
| 2634 | +bool Element::is_relevant_to_the_user() |
| 2635 | +{ |
| 2636 | + // An element is relevant to the user if any of the following conditions are true: |
| 2637 | + |
| 2638 | + // The element is close to the viewport. |
| 2639 | + if (m_proximity_to_the_viewport == ProximityToTheViewport::CloseToTheViewport) |
| 2640 | + return true; |
| 2641 | + |
| 2642 | + // Either the element or its contents are focused, as described in the focus section of the HTML spec. |
| 2643 | + auto* focused_element = document().focused_element(); |
| 2644 | + if (focused_element && is_inclusive_ancestor_of(*focused_element)) |
| 2645 | + return true; |
| 2646 | + |
| 2647 | + // Either the element or its contents are selected, where selection is described in the selection API. |
| 2648 | + if (document().get_selection()->contains_node(*this, true)) |
| 2649 | + return true; |
| 2650 | + |
| 2651 | + // Either the element or its contents are placed in the top layer. |
| 2652 | + bool is_in_top_layer = false; |
| 2653 | + for_each_in_inclusive_subtree_of_type<Element>([&](auto& element) { |
| 2654 | + if (element.in_top_layer()) { |
| 2655 | + is_in_top_layer = true; |
| 2656 | + return TraversalDecision::Break; |
| 2657 | + } |
| 2658 | + |
| 2659 | + return TraversalDecision::Continue; |
| 2660 | + }); |
| 2661 | + if (is_in_top_layer) |
| 2662 | + return true; |
| 2663 | + |
| 2664 | + // FIXME: The element has a flat tree descendant that is captured in a view transition. |
| 2665 | + |
| 2666 | + // NOTE: none of the above conditions are true, so the element is not relevant to the user. |
| 2667 | + return false; |
| 2668 | +} |
| 2669 | + |
2602 | 2670 | bool Element::id_reference_exists(String const& id_reference) const
|
2603 | 2671 | {
|
2604 | 2672 | return document().get_element_by_id(id_reference);
|
|
0 commit comments