Bug 1771150 - Make fullscreen modal. r=smaug

As per https://github.com/w3c/csswg-drafts/issues/7311.

Differential Revision: https://phabricator.services.mozilla.com/D150335
This commit is contained in:
Emilio Cobos Álvarez
2022-07-06 00:16:28 +00:00
parent 409b9342eb
commit c72c6c699f
7 changed files with 26 additions and 26 deletions

View File

@@ -14573,7 +14573,7 @@ bool Document::PopFullscreenElement(UpdateViewport aUpdateViewport) {
} }
MOZ_ASSERT(removedElement->State().HasState(ElementState::FULLSCREEN)); MOZ_ASSERT(removedElement->State().HasState(ElementState::FULLSCREEN));
removedElement->RemoveStates(ElementState::FULLSCREEN); removedElement->RemoveStates(ElementState::FULLSCREEN | ElementState::MODAL);
NotifyFullScreenChangedForMediaElement(*removedElement); NotifyFullScreenChangedForMediaElement(*removedElement);
// Reset iframe fullscreen flag. // Reset iframe fullscreen flag.
if (auto* iframe = HTMLIFrameElement::FromNode(removedElement)) { if (auto* iframe = HTMLIFrameElement::FromNode(removedElement)) {
@@ -14586,23 +14586,20 @@ bool Document::PopFullscreenElement(UpdateViewport aUpdateViewport) {
} }
void Document::SetFullscreenElement(Element& aElement) { void Document::SetFullscreenElement(Element& aElement) {
aElement.AddStates(ElementState::FULLSCREEN); ElementState statesToAdd = ElementState::FULLSCREEN;
if (StaticPrefs::dom_fullscreen_modal() && !IsInChromeDocShell()) {
// Don't make the document modal in chrome documents, since we don't want
// the browser UI like the context menu / etc to be inert.
statesToAdd |= ElementState::MODAL;
}
aElement.AddStates(statesToAdd);
TopLayerPush(aElement); TopLayerPush(aElement);
NotifyFullScreenChangedForMediaElement(aElement); NotifyFullScreenChangedForMediaElement(aElement);
UpdateViewportScrollbarOverrideForFullscreen(this); UpdateViewportScrollbarOverrideForFullscreen(this);
} }
static ElementState TopLayerModalStates() {
ElementState modalStates = ElementState::MODAL_DIALOG;
if (StaticPrefs::dom_fullscreen_modal()) {
modalStates |= ElementState::FULLSCREEN;
}
return modalStates;
}
void Document::TopLayerPush(Element& aElement) { void Document::TopLayerPush(Element& aElement) {
const bool modal = const bool modal = aElement.State().HasState(ElementState::MODAL);
aElement.State().HasAtLeastOneOfStates(TopLayerModalStates());
auto predictFunc = [&aElement](Element* element) { auto predictFunc = [&aElement](Element* element) {
return element == &aElement; return element == &aElement;
@@ -14639,7 +14636,7 @@ void Document::TopLayerPush(Element& aElement) {
} }
void Document::AddModalDialog(HTMLDialogElement& aDialogElement) { void Document::AddModalDialog(HTMLDialogElement& aDialogElement) {
aDialogElement.AddStates(ElementState::MODAL_DIALOG); aDialogElement.AddStates(ElementState::MODAL);
TopLayerPush(aDialogElement); TopLayerPush(aDialogElement);
} }
@@ -14649,7 +14646,7 @@ void Document::RemoveModalDialog(HTMLDialogElement& aDialogElement) {
}; };
DebugOnly<Element*> removedElement = TopLayerPop(predicate); DebugOnly<Element*> removedElement = TopLayerPop(predicate);
MOZ_ASSERT(removedElement == &aDialogElement); MOZ_ASSERT(removedElement == &aDialogElement);
aDialogElement.RemoveStates(ElementState::MODAL_DIALOG); aDialogElement.RemoveStates(ElementState::MODAL);
} }
Element* Document::TopLayerPop(FunctionRef<bool(Element*)> aPredicate) { Element* Document::TopLayerPop(FunctionRef<bool(Element*)> aPredicate) {
@@ -14690,15 +14687,14 @@ Element* Document::TopLayerPop(FunctionRef<bool(Element*)> aPredicate) {
return nullptr; return nullptr;
} }
const ElementState modalStates = TopLayerModalStates(); const bool modal = removedElement->State().HasState(ElementState::MODAL);
const bool modal = removedElement->State().HasAtLeastOneOfStates(modalStates);
if (modal) { if (modal) {
removedElement->RemoveStates(ElementState::TOPMOST_MODAL); removedElement->RemoveStates(ElementState::TOPMOST_MODAL);
bool foundExistingModalElement = false; bool foundExistingModalElement = false;
for (const nsWeakPtr& weakPtr : Reversed(mTopLayer)) { for (const nsWeakPtr& weakPtr : Reversed(mTopLayer)) {
nsCOMPtr<Element> element(do_QueryReferent(weakPtr)); nsCOMPtr<Element> element(do_QueryReferent(weakPtr));
if (element && element->State().HasAtLeastOneOfStates(modalStates)) { if (element && element->State().HasState(ElementState::MODAL)) {
element->AddStates(ElementState::TOPMOST_MODAL); element->AddStates(ElementState::TOPMOST_MODAL);
foundExistingModalElement = true; foundExistingModalElement = true;
break; break;

View File

@@ -107,9 +107,9 @@ bitflags! {
const AUTOFILL = 1u64 << 40; const AUTOFILL = 1u64 << 40;
/// Non-standard & undocumented. /// Non-standard & undocumented.
const AUTOFILL_PREVIEW = 1u64 << 41; const AUTOFILL_PREVIEW = 1u64 << 41;
/// State that dialog element is modal, for centered alignment /// State for modal elements:
/// <https://html.spec.whatwg.org/multipage/#centered-alignment> /// <https://drafts.csswg.org/selectors-4/#modal-state>
const MODAL_DIALOG = 1u64 << 42; const MODAL = 1u64 << 42;
/// <https://html.spec.whatwg.org/multipage/#inert-subtrees> /// <https://html.spec.whatwg.org/multipage/#inert-subtrees>
const INERT = 1u64 << 43; const INERT = 1u64 << 43;
/// State for the topmost modal element in top layer /// State for the topmost modal element in top layer
@@ -164,7 +164,7 @@ bitflags! {
Self::FULLSCREEN.bits | Self::FULLSCREEN.bits |
Self::HOVER.bits | Self::HOVER.bits |
Self::URLTARGET.bits | Self::URLTARGET.bits |
Self::MODAL_DIALOG.bits | Self::MODAL.bits |
Self::INERT.bits | Self::INERT.bits |
Self::TOPMOST_MODAL.bits | Self::TOPMOST_MODAL.bits |
Self::REVEALED.bits; Self::REVEALED.bits;

View File

@@ -51,6 +51,9 @@ async function testFullscreenIsModal(modal) {
clickButton(/* expectEvent = */ !modal); clickButton(/* expectEvent = */ !modal);
ok(document.fullscreenElement.matches(":fullscreen"), "Fullscreen element matches :fullscreen");
is(document.fullscreenElement.matches(":modal"), modal, "Fullscreen element matches :modal");
await document.exitFullscreen(); await document.exitFullscreen();
clickButton(/* expectEvent = */ true); clickButton(/* expectEvent = */ true);
} }

View File

@@ -81,7 +81,7 @@ void HTMLDialogElement::Show() {
} }
bool HTMLDialogElement::IsInTopLayer() const { bool HTMLDialogElement::IsInTopLayer() const {
return State().HasState(ElementState::MODAL_DIALOG); return State().HasState(ElementState::MODAL);
} }
void HTMLDialogElement::AddToTopLayerIfNeeded() { void HTMLDialogElement::AddToTopLayerIfNeeded() {

View File

@@ -20,8 +20,9 @@
<p id="display"></p> <p id="display"></p>
<div id="content"> <div id="content">
</div> </div>
<div id="div"></div> <div id="div">
<input id="input" type="text" /> <input id="input" type="text" />
</div>
<pre id="test"> <pre id="test">
<script type="application/javascript"> <script type="application/javascript">
/* /*

View File

@@ -2404,7 +2404,7 @@
# This matches other browsers but historically not Gecko. # This matches other browsers but historically not Gecko.
- name: dom.fullscreen.modal - name: dom.fullscreen.modal
type: bool type: bool
value: false value: true
mirror: always mirror: always
# Whether the Gamepad API is enabled # Whether the Gamepad API is enabled

View File

@@ -53,7 +53,7 @@ macro_rules! apply_non_ts_list {
("-moz-devtools-highlighted", MozDevtoolsHighlighted, DEVTOOLS_HIGHLIGHTED, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), ("-moz-devtools-highlighted", MozDevtoolsHighlighted, DEVTOOLS_HIGHLIGHTED, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
("-moz-styleeditor-transitioning", MozStyleeditorTransitioning, STYLEEDITOR_TRANSITIONING, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), ("-moz-styleeditor-transitioning", MozStyleeditorTransitioning, STYLEEDITOR_TRANSITIONING, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
("fullscreen", Fullscreen, FULLSCREEN, _), ("fullscreen", Fullscreen, FULLSCREEN, _),
("modal", Modal, MODAL_DIALOG, _), ("modal", Modal, MODAL, _),
("-moz-topmost-modal", MozTopmostModal, TOPMOST_MODAL, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), ("-moz-topmost-modal", MozTopmostModal, TOPMOST_MODAL, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
("-moz-broken", MozBroken, BROKEN, _), ("-moz-broken", MozBroken, BROKEN, _),
("-moz-loading", MozLoading, LOADING, _), ("-moz-loading", MozLoading, LOADING, _),