mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-30 11:07:29 +09:00
Issue #2472 - Part 5: Make modal versions of <dialog> work, and tune styles.
This adds a pseudo-class `:-moz-modal-dialog` to be able to track whether the dialog is in the top layer in CSS. This implements default styling for modal dialogs following the HTML standard. Slightly off-extreme color scheme chosen for unstyled <dialog> elements.
This commit is contained in:
parent
7a04afab4a
commit
7d34b285e0
5 changed files with 57 additions and 4 deletions
|
|
@ -291,6 +291,8 @@ private:
|
||||||
#define NS_EVENT_STATE_PLACEHOLDERSHOWN NS_DEFINE_EVENT_STATE_MACRO(52)
|
#define NS_EVENT_STATE_PLACEHOLDERSHOWN NS_DEFINE_EVENT_STATE_MACRO(52)
|
||||||
// Element has focus-within.
|
// Element has focus-within.
|
||||||
#define NS_EVENT_STATE_FOCUS_WITHIN NS_DEFINE_EVENT_STATE_MACRO(53)
|
#define NS_EVENT_STATE_FOCUS_WITHIN NS_DEFINE_EVENT_STATE_MACRO(53)
|
||||||
|
// Modal <dialog> element
|
||||||
|
#define NS_EVENT_STATE_MODAL_DIALOG NS_DEFINE_EVENT_STATE_MACRO(54)
|
||||||
|
|
||||||
#define DIR_ATTR_STATES (NS_EVENT_STATE_HAS_DIR_ATTR | \
|
#define DIR_ATTR_STATES (NS_EVENT_STATE_HAS_DIR_ATTR | \
|
||||||
NS_EVENT_STATE_DIR_ATTR_LTR | \
|
NS_EVENT_STATE_DIR_ATTR_LTR | \
|
||||||
|
|
@ -309,7 +311,8 @@ private:
|
||||||
#define ESM_MANAGED_STATES (DIR_ATTR_STATES | NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS | \
|
#define ESM_MANAGED_STATES (DIR_ATTR_STATES | NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS | \
|
||||||
NS_EVENT_STATE_HOVER | NS_EVENT_STATE_DRAGOVER | \
|
NS_EVENT_STATE_HOVER | NS_EVENT_STATE_DRAGOVER | \
|
||||||
NS_EVENT_STATE_URLTARGET | NS_EVENT_STATE_FOCUSRING | \
|
NS_EVENT_STATE_URLTARGET | NS_EVENT_STATE_FOCUSRING | \
|
||||||
NS_EVENT_STATE_FULL_SCREEN | NS_EVENT_STATE_FOCUS_WITHIN)
|
NS_EVENT_STATE_FULL_SCREEN | NS_EVENT_STATE_FOCUS_WITHIN | \
|
||||||
|
NS_EVENT_STATE_MODAL_DIALOG)
|
||||||
|
|
||||||
#define INTRINSIC_STATES (~ESM_MANAGED_STATES)
|
#define INTRINSIC_STATES (~ESM_MANAGED_STATES)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,9 @@ HTMLDialogElement::Close(const mozilla::dom::Optional<nsAString>& aReturnValue)
|
||||||
ErrorResult ignored;
|
ErrorResult ignored;
|
||||||
SetOpen(false, ignored);
|
SetOpen(false, ignored);
|
||||||
ignored.SuppressException();
|
ignored.SuppressException();
|
||||||
|
|
||||||
|
RemoveFromTopLayerIfNeeded();
|
||||||
|
|
||||||
RefPtr<AsyncEventDispatcher> eventDispatcher =
|
RefPtr<AsyncEventDispatcher> eventDispatcher =
|
||||||
new AsyncEventDispatcher(this, NS_LITERAL_STRING("close"), false);
|
new AsyncEventDispatcher(this, NS_LITERAL_STRING("close"), false);
|
||||||
eventDispatcher->PostDOMEvent();
|
eventDispatcher->PostDOMEvent();
|
||||||
|
|
@ -72,6 +75,26 @@ HTMLDialogElement::Show()
|
||||||
ignored.SuppressException();
|
ignored.SuppressException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HTMLDialogElement::IsInTopLayer() const {
|
||||||
|
return State().HasState(NS_EVENT_STATE_MODAL_DIALOG);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTMLDialogElement::RemoveFromTopLayerIfNeeded() {
|
||||||
|
if (!IsInTopLayer()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto predictFunc = [&](Element* element) { return element == this; };
|
||||||
|
|
||||||
|
DebugOnly<Element*> removedElement = OwnerDoc()->TopLayerPop(predictFunc);
|
||||||
|
MOZ_ASSERT(removedElement == this);
|
||||||
|
RemoveStates(NS_EVENT_STATE_MODAL_DIALOG);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTMLDialogElement::UnbindFromTree(bool aNullParent) {
|
||||||
|
RemoveFromTopLayerIfNeeded();
|
||||||
|
nsGenericHTMLElement::UnbindFromTree(aNullParent);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
HTMLDialogElement::ShowModal(ErrorResult& aError)
|
HTMLDialogElement::ShowModal(ErrorResult& aError)
|
||||||
{
|
{
|
||||||
|
|
@ -79,6 +102,10 @@ HTMLDialogElement::ShowModal(ErrorResult& aError)
|
||||||
aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!IsInTopLayer() && OwnerDoc()->TopLayerPush(this)) {
|
||||||
|
AddStates(NS_EVENT_STATE_MODAL_DIALOG);
|
||||||
|
}
|
||||||
|
|
||||||
SetOpen(true, aError);
|
SetOpen(true, aError);
|
||||||
aError.SuppressException();
|
aError.SuppressException();
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,14 @@ public:
|
||||||
{
|
{
|
||||||
mReturnValue = aReturnValue;
|
mReturnValue = aReturnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UnbindFromTree(bool aNullParent = true) /*override*/;
|
||||||
|
|
||||||
void Close(const mozilla::dom::Optional<nsAString>& aReturnValue);
|
void Close(const mozilla::dom::Optional<nsAString>& aReturnValue);
|
||||||
void Show();
|
void Show();
|
||||||
void ShowModal(ErrorResult& aError);
|
void ShowModal(ErrorResult& aError);
|
||||||
|
|
||||||
|
bool IsInTopLayer() const;
|
||||||
|
|
||||||
nsString mReturnValue;
|
nsString mReturnValue;
|
||||||
|
|
||||||
|
|
@ -52,6 +56,9 @@ protected:
|
||||||
virtual ~HTMLDialogElement();
|
virtual ~HTMLDialogElement();
|
||||||
JSObject* WrapNode(JSContext* aCx,
|
JSObject* WrapNode(JSContext* aCx,
|
||||||
JS::Handle<JSObject*> aGivenProto) override;
|
JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void RemoveFromTopLayerIfNeeded();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,12 @@ CSS_STATE_PSEUDO_CLASS(fullscreen, ":fullscreen",
|
||||||
NS_EVENT_STATE_FULL_SCREEN)
|
NS_EVENT_STATE_FULL_SCREEN)
|
||||||
CSS_STATE_PSEUDO_CLASS(mozFullScreen, ":-moz-full-screen", 0, "", NS_EVENT_STATE_FULL_SCREEN)
|
CSS_STATE_PSEUDO_CLASS(mozFullScreen, ":-moz-full-screen", 0, "", NS_EVENT_STATE_FULL_SCREEN)
|
||||||
|
|
||||||
|
// Matches if a <dialog> element is modal
|
||||||
|
CSS_STATE_PSEUDO_CLASS(mozModalDialog, ":-moz-modal-dialog",
|
||||||
|
CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS,
|
||||||
|
"",
|
||||||
|
NS_EVENT_STATE_MODAL_DIALOG)
|
||||||
|
|
||||||
// Matches if the element is focused and should show a focus ring
|
// Matches if the element is focused and should show a focus ring
|
||||||
CSS_STATE_PSEUDO_CLASS(mozFocusRing, ":-moz-focusring", 0, "", NS_EVENT_STATE_FOCUSRING)
|
CSS_STATE_PSEUDO_CLASS(mozFocusRing, ":-moz-focusring", 0, "", NS_EVENT_STATE_FOCUSRING)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -811,14 +811,15 @@ dialog {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset-inline-start: 0;
|
inset-inline-start: 0;
|
||||||
inset-inline-end: 0;
|
inset-inline-end: 0;
|
||||||
color: black;
|
|
||||||
margin: auto;
|
margin: auto;
|
||||||
border-width: initial;
|
border-width: initial;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: initial;
|
border-color: dimgrey;
|
||||||
border-image: initial;
|
border-image: initial;
|
||||||
|
border-radius: 5px;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
background: white;
|
color: #222; /*CanvasText*/
|
||||||
|
background: snow; /*Canvas*/
|
||||||
width: -moz-fit-content;
|
width: -moz-fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -826,6 +827,15 @@ dialog:not([open]) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dialog:-moz-modal-dialog {
|
||||||
|
-moz-top-layer: top !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* https://html.spec.whatwg.org/#flow-content-3 */
|
||||||
|
dialog::backdrop {
|
||||||
|
background: rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
/* emulation of non-standard HTML <marquee> tag */
|
/* emulation of non-standard HTML <marquee> tag */
|
||||||
marquee {
|
marquee {
|
||||||
inline-size: -moz-available;
|
inline-size: -moz-available;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue