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:
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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">
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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, _),
|
||||||
|
|||||||
Reference in New Issue
Block a user