diff --git a/Tests/LibWeb/Layout/expected/dialog-open-modal.txt b/Tests/LibWeb/Layout/expected/dialog-open-modal.txt new file mode 100644 index 00000000000000..df1052f8fda718 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/dialog-open-modal.txt @@ -0,0 +1,20 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x600 [BFC] children: not-inline + BlockContainer
at (196.671875,51) content-size 406.65625x17 children: inline - frag 0 from TextNode start: 0, length: 50, rect: [196.671875,51 406.65625x17] baseline: 13.296875 + BlockContainer at (196.671875,19) content-size 406.65625x562 positioned [BFC] children: not-inline + BlockContainer at (196.671875,35) content-size 406.65625x17 children: inline + frag 0 from TextNode start: 0, length: 50, rect: [196.671875,35 406.65625x17] baseline: 13.296875 "Dialog's layout node should be a child of viewport" TextNode <#text> ViewportPaintable (Viewport<#document>) [0,0 800x600] PaintableWithLines (BlockContainer) [0,0 800x16] PaintableWithLines (BlockContainer) [8,8 784x0] - PaintableWithLines (BlockContainer#dialog) [177.671875,16 444.65625x87] - PaintableWithLines (BlockContainer) [196.671875,51 406.65625x17] + PaintableWithLines (BlockContainer#dialog) [177.671875,0 444.65625x600] + PaintableWithLines (BlockContainer) [196.671875,35 406.65625x17] TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/input/dialog-open-modal.html b/Tests/LibWeb/Layout/input/dialog-open-modal.html new file mode 100644 index 00000000000000..492f2e89961513 --- /dev/null +++ b/Tests/LibWeb/Layout/input/dialog-open-modal.html @@ -0,0 +1,16 @@ + + + + I'm a node + + + \ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/dialog-open-non-modal.html b/Tests/LibWeb/Layout/input/dialog-open-non-modal.html new file mode 100644 index 00000000000000..36dce619484492 --- /dev/null +++ b/Tests/LibWeb/Layout/input/dialog-open-non-modal.html @@ -0,0 +1,9 @@ + + + + I'm a node + diff --git a/Userland/Libraries/LibWeb/CSS/PseudoClasses.json b/Userland/Libraries/LibWeb/CSS/PseudoClasses.json index 1523d1ad9b776d..22b5400875683a 100644 --- a/Userland/Libraries/LibWeb/CSS/PseudoClasses.json +++ b/Userland/Libraries/LibWeb/CSS/PseudoClasses.json @@ -71,6 +71,9 @@ "local-link": { "argument": "" }, + "modal": { + "argument": "" + }, "muted": { "argument": "" }, diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp index 1b7ed4eef084e1..535dd5366920fc 100644 --- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp +++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp @@ -542,6 +542,15 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla case CSS::PseudoClass::Open: case CSS::PseudoClass::Closed: return matches_open_state_pseudo_class(element, pseudo_class.type == CSS::PseudoClass::Open); + case CSS::PseudoClass::Modal: { + // https://drafts.csswg.org/selectors/#modal-state + if (is(element)) { + auto const& dialog_element = static_cast(element); + return dialog_element.is_modal(); + } + // FIXME: fullscreen elements are also modal. + return false; + } } return false; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h index 8055c7128436a1..63836cef0b6bcf 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h @@ -30,6 +30,8 @@ class HTMLDialogElement final : public HTMLElement { // https://www.w3.org/TR/html-aria/#el-dialog virtual Optional default_role() const override { return ARIA::Role::dialog; } + bool is_modal() const { return m_is_modal; } + private: HTMLDialogElement(DOM::Document&, DOM::QualifiedName);
at (196.671875,35) content-size 406.65625x17 children: inline + frag 0 from TextNode start: 0, length: 50, rect: [196.671875,35 406.65625x17] baseline: 13.296875 "Dialog's layout node should be a child of viewport" TextNode <#text> ViewportPaintable (Viewport<#document>) [0,0 800x600] PaintableWithLines (BlockContainer) [0,0 800x16] PaintableWithLines (BlockContainer
) [196.671875,51 406.65625x17] + PaintableWithLines (BlockContainer#dialog) [177.671875,0 444.65625x600] + PaintableWithLines (BlockContainer) [196.671875,35 406.65625x17] TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/input/dialog-open-modal.html b/Tests/LibWeb/Layout/input/dialog-open-modal.html new file mode 100644 index 00000000000000..492f2e89961513 --- /dev/null +++ b/Tests/LibWeb/Layout/input/dialog-open-modal.html @@ -0,0 +1,16 @@ + + + + I'm a node + + + \ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/dialog-open-non-modal.html b/Tests/LibWeb/Layout/input/dialog-open-non-modal.html new file mode 100644 index 00000000000000..36dce619484492 --- /dev/null +++ b/Tests/LibWeb/Layout/input/dialog-open-non-modal.html @@ -0,0 +1,9 @@ + + + + I'm a node + diff --git a/Userland/Libraries/LibWeb/CSS/PseudoClasses.json b/Userland/Libraries/LibWeb/CSS/PseudoClasses.json index 1523d1ad9b776d..22b5400875683a 100644 --- a/Userland/Libraries/LibWeb/CSS/PseudoClasses.json +++ b/Userland/Libraries/LibWeb/CSS/PseudoClasses.json @@ -71,6 +71,9 @@ "local-link": { "argument": "" }, + "modal": { + "argument": "" + }, "muted": { "argument": "" }, diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp index 1b7ed4eef084e1..535dd5366920fc 100644 --- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp +++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp @@ -542,6 +542,15 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla case CSS::PseudoClass::Open: case CSS::PseudoClass::Closed: return matches_open_state_pseudo_class(element, pseudo_class.type == CSS::PseudoClass::Open); + case CSS::PseudoClass::Modal: { + // https://drafts.csswg.org/selectors/#modal-state + if (is(element)) { + auto const& dialog_element = static_cast(element); + return dialog_element.is_modal(); + } + // FIXME: fullscreen elements are also modal. + return false; + } } return false; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h index 8055c7128436a1..63836cef0b6bcf 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h @@ -30,6 +30,8 @@ class HTMLDialogElement final : public HTMLElement { // https://www.w3.org/TR/html-aria/#el-dialog virtual Optional default_role() const override { return ARIA::Role::dialog; } + bool is_modal() const { return m_is_modal; } + private: HTMLDialogElement(DOM::Document&, DOM::QualifiedName);
) [196.671875,35 406.65625x17] TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/input/dialog-open-modal.html b/Tests/LibWeb/Layout/input/dialog-open-modal.html new file mode 100644 index 00000000000000..492f2e89961513 --- /dev/null +++ b/Tests/LibWeb/Layout/input/dialog-open-modal.html @@ -0,0 +1,16 @@ + + + + I'm a node + + + \ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/dialog-open-non-modal.html b/Tests/LibWeb/Layout/input/dialog-open-non-modal.html new file mode 100644 index 00000000000000..36dce619484492 --- /dev/null +++ b/Tests/LibWeb/Layout/input/dialog-open-non-modal.html @@ -0,0 +1,9 @@ + + + + I'm a node + diff --git a/Userland/Libraries/LibWeb/CSS/PseudoClasses.json b/Userland/Libraries/LibWeb/CSS/PseudoClasses.json index 1523d1ad9b776d..22b5400875683a 100644 --- a/Userland/Libraries/LibWeb/CSS/PseudoClasses.json +++ b/Userland/Libraries/LibWeb/CSS/PseudoClasses.json @@ -71,6 +71,9 @@ "local-link": { "argument": "" }, + "modal": { + "argument": "" + }, "muted": { "argument": "" }, diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp index 1b7ed4eef084e1..535dd5366920fc 100644 --- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp +++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp @@ -542,6 +542,15 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla case CSS::PseudoClass::Open: case CSS::PseudoClass::Closed: return matches_open_state_pseudo_class(element, pseudo_class.type == CSS::PseudoClass::Open); + case CSS::PseudoClass::Modal: { + // https://drafts.csswg.org/selectors/#modal-state + if (is(element)) { + auto const& dialog_element = static_cast(element); + return dialog_element.is_modal(); + } + // FIXME: fullscreen elements are also modal. + return false; + } } return false; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h index 8055c7128436a1..63836cef0b6bcf 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h @@ -30,6 +30,8 @@ class HTMLDialogElement final : public HTMLElement { // https://www.w3.org/TR/html-aria/#el-dialog virtual Optional default_role() const override { return ARIA::Role::dialog; } + bool is_modal() const { return m_is_modal; } + private: HTMLDialogElement(DOM::Document&, DOM::QualifiedName);