зеркало из https://github.com/mozilla/gecko-dev.git
Bug 921504 - implement HTML:inert r=emilio,heycam
Differential Revision: https://phabricator.services.mozilla.com/D81701
This commit is contained in:
Родитель
0cae4293b6
Коммит
1c382cad65
|
@ -87,6 +87,7 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
|
|||
"image-orientation",
|
||||
"image-rendering",
|
||||
"ime-mode",
|
||||
"-moz-inert",
|
||||
"initial-letter",
|
||||
"isolation",
|
||||
"justify-content",
|
||||
|
|
|
@ -294,6 +294,8 @@ class EventStates {
|
|||
#define NS_EVENT_STATE_FOCUS_VISIBLE NS_DEFINE_EVENT_STATE_MACRO(52)
|
||||
// Modal <dialog> element
|
||||
#define NS_EVENT_STATE_MODAL_DIALOG NS_DEFINE_EVENT_STATE_MACRO(53)
|
||||
// Inert subtrees
|
||||
#define NS_EVENT_STATE_MOZINERT NS_DEFINE_EVENT_STATE_MACRO(54)
|
||||
|
||||
/**
|
||||
* NOTE: do not go over 63 without updating EventStates::InternalType!
|
||||
|
@ -329,7 +331,8 @@ class EventStates {
|
|||
NS_EVENT_STATE_DRAGOVER | NS_EVENT_STATE_FOCUS | NS_EVENT_STATE_FOCUSRING | \
|
||||
NS_EVENT_STATE_FOCUS_WITHIN | NS_EVENT_STATE_FULLSCREEN | \
|
||||
NS_EVENT_STATE_HOVER | NS_EVENT_STATE_URLTARGET | \
|
||||
NS_EVENT_STATE_FOCUS_VISIBLE | NS_EVENT_STATE_MODAL_DIALOG)
|
||||
NS_EVENT_STATE_FOCUS_VISIBLE | NS_EVENT_STATE_MODAL_DIALOG | \
|
||||
NS_EVENT_STATE_MOZINERT)
|
||||
|
||||
#define INTRINSIC_STATES (~EXTERNALLY_MANAGED_STATES)
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "mozilla/MouseEvents.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/TextEditor.h"
|
||||
#include "mozilla/StaticPrefs_html5.h"
|
||||
#include "mozilla/StaticPrefs_layout.h"
|
||||
|
||||
#include "nscore.h"
|
||||
|
@ -687,6 +688,13 @@ nsresult nsGenericHTMLElement::AfterSetAttr(
|
|||
SetFlags(NODE_HAS_ACCESSKEY);
|
||||
RegAccessKey();
|
||||
}
|
||||
} else if (aName == nsGkAtoms::inert &&
|
||||
StaticPrefs::html5_inert_enabled()) {
|
||||
if (aValue) {
|
||||
AddStates(NS_EVENT_STATE_MOZINERT);
|
||||
} else {
|
||||
RemoveStates(NS_EVENT_STATE_MOZINERT);
|
||||
}
|
||||
} else if (aName == nsGkAtoms::name) {
|
||||
if (aValue && !aValue->Equals(EmptyString(), eIgnoreCase)) {
|
||||
// This may not be quite right because we can have subclass code run
|
||||
|
|
|
@ -9743,7 +9743,8 @@ bool nsIFrame::IsFocusable(int32_t* aTabIndex, bool aWithMouse) {
|
|||
|
||||
if (mContent && mContent->IsElement() && IsVisibleConsideringAncestors() &&
|
||||
Style()->GetPseudoType() != PseudoStyleType::anonymousFlexItem &&
|
||||
Style()->GetPseudoType() != PseudoStyleType::anonymousGridItem) {
|
||||
Style()->GetPseudoType() != PseudoStyleType::anonymousGridItem &&
|
||||
StyleUI()->mInert != StyleInert::Inert) {
|
||||
const nsStyleUI* ui = StyleUI();
|
||||
if (ui->mUserFocus != StyleUserFocus::Ignore &&
|
||||
ui->mUserFocus != StyleUserFocus::None) {
|
||||
|
|
|
@ -97,6 +97,7 @@ rusty-enums = [
|
|||
"mozilla::StyleFloat",
|
||||
"mozilla::StyleImageOrientation",
|
||||
"mozilla::StyleImageRendering",
|
||||
"mozilla::StyleInert",
|
||||
"mozilla::StyleUserModify",
|
||||
"mozilla::StyleUserInput",
|
||||
"mozilla::StyleBoxDirection",
|
||||
|
|
|
@ -286,6 +286,12 @@ enum class StyleUserModify : uint8_t {
|
|||
WriteOnly,
|
||||
};
|
||||
|
||||
// -moz-inert
|
||||
enum class StyleInert : uint8_t {
|
||||
None,
|
||||
Inert,
|
||||
};
|
||||
|
||||
// -moz-window-dragging
|
||||
enum class StyleWindowDragging : uint8_t {
|
||||
Default,
|
||||
|
|
|
@ -3107,7 +3107,8 @@ LogicalSide nsStyleText::TextEmphasisSide(WritingMode aWM) const {
|
|||
//
|
||||
|
||||
nsStyleUI::nsStyleUI(const Document& aDocument)
|
||||
: mUserInput(StyleUserInput::Auto),
|
||||
: mInert(StyleInert::None),
|
||||
mUserInput(StyleUserInput::Auto),
|
||||
mUserModify(StyleUserModify::ReadOnly),
|
||||
mUserFocus(StyleUserFocus::None),
|
||||
mPointerEvents(StylePointerEvents::Auto),
|
||||
|
@ -3118,7 +3119,8 @@ nsStyleUI::nsStyleUI(const Document& aDocument)
|
|||
}
|
||||
|
||||
nsStyleUI::nsStyleUI(const nsStyleUI& aSource)
|
||||
: mUserInput(aSource.mUserInput),
|
||||
: mInert(aSource.mInert),
|
||||
mUserInput(aSource.mUserInput),
|
||||
mUserModify(aSource.mUserModify),
|
||||
mUserFocus(aSource.mUserFocus),
|
||||
mPointerEvents(aSource.mPointerEvents),
|
||||
|
@ -3179,7 +3181,7 @@ nsChangeHint nsStyleUI::CalcDifference(const nsStyleUI& aNewData) const {
|
|||
}
|
||||
}
|
||||
|
||||
if (mUserFocus != aNewData.mUserFocus) {
|
||||
if (mUserFocus != aNewData.mUserFocus || mInert != aNewData.mInert) {
|
||||
hint |= nsChangeHint_NeutralChange;
|
||||
}
|
||||
|
||||
|
|
|
@ -1730,6 +1730,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUI {
|
|||
|
||||
nsChangeHint CalcDifference(const nsStyleUI& aNewData) const;
|
||||
|
||||
mozilla::StyleInert mInert;
|
||||
mozilla::StyleUserInput mUserInput;
|
||||
mozilla::StyleUserModify mUserModify; // (modify-content)
|
||||
mozilla::StyleUserFocus mUserFocus; // (auto-select)
|
||||
|
|
|
@ -153,6 +153,11 @@
|
|||
outline: 1px dotted;
|
||||
}
|
||||
|
||||
/* Inert subtrees */
|
||||
*|*:-moz-inert {
|
||||
-moz-inert: inert;
|
||||
}
|
||||
|
||||
/* Miscellaneous */
|
||||
|
||||
*|*::-moz-cell-content {
|
||||
|
|
|
@ -94,6 +94,7 @@ const char* gInaccessibleProperties[] = {
|
|||
"-moz-context-properties",
|
||||
"-moz-control-character-visibility",
|
||||
"-moz-default-appearance",
|
||||
"-moz-inert",
|
||||
"-moz-list-reversed", // parsed by UA sheets only
|
||||
"-moz-script-level", // parsed by UA sheets only
|
||||
"-moz-script-size-multiplier",
|
||||
|
|
|
@ -23,6 +23,7 @@ const NON_CONTENT_ACCESSIBLE_PROPERTIES = [
|
|||
"-moz-min-font-size-ratio",
|
||||
"-moz-script-size-multiplier",
|
||||
"-moz-default-appearance",
|
||||
"-moz-inert",
|
||||
// TODO(emilio): Whenever we stop using `-moz-binding` in a gazillion tests
|
||||
// we should add it here.
|
||||
];
|
||||
|
|
|
@ -1137,6 +1137,7 @@ function runTests() {
|
|||
test_unbalanced_unparseable(":-moz-handler-crashed");
|
||||
|
||||
// We're not in a UA sheet, so this should be invalid.
|
||||
test_balanced_unparseable(":-moz-inert");
|
||||
test_balanced_unparseable(":-moz-native-anonymous");
|
||||
test_balanced_unparseable(":-moz-table-border-nonzero");
|
||||
|
||||
|
|
|
@ -4566,6 +4566,12 @@
|
|||
# Prefs starting with "html5."
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# Turn HTML:inert on or off.
|
||||
- name: html5.inert.enabled
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# Toggle which thread the HTML5 parser uses for stream parsing.
|
||||
- name: html5.offmainthread
|
||||
type: bool
|
||||
|
|
|
@ -145,6 +145,9 @@ bitflags! {
|
|||
///
|
||||
/// https://html.spec.whatwg.org/multipage/#centered-alignment
|
||||
const IN_MODAL_DIALOG_STATE = 1 << 53;
|
||||
|
||||
/// https://html.spec.whatwg.org/multipage/interaction.html#inert-subtrees
|
||||
const IN_MOZINERT_STATE = 1 << 54;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ macro_rules! apply_non_ts_list {
|
|||
("-moz-drag-over", MozDragOver, IN_DRAGOVER_STATE, _),
|
||||
("target", Target, IN_TARGET_STATE, _),
|
||||
("indeterminate", Indeterminate, IN_INDETERMINATE_STATE, _),
|
||||
("-moz-inert", MozInert, IN_MOZINERT_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
|
||||
("-moz-devtools-highlighted", MozDevtoolsHighlighted, IN_DEVTOOLS_HIGHLIGHTED_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
|
||||
("-moz-styleeditor-transitioning", MozStyleeditorTransitioning, IN_STYLEEDITOR_TRANSITIONING_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
|
||||
("fullscreen", Fullscreen, IN_FULLSCREEN_STATE, _),
|
||||
|
|
|
@ -2016,6 +2016,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
NonTSPseudoClass::Checked |
|
||||
NonTSPseudoClass::Fullscreen |
|
||||
NonTSPseudoClass::Indeterminate |
|
||||
NonTSPseudoClass::MozInert |
|
||||
NonTSPseudoClass::PlaceholderShown |
|
||||
NonTSPseudoClass::Target |
|
||||
NonTSPseudoClass::Valid |
|
||||
|
|
|
@ -29,6 +29,17 @@ ${helpers.single_keyword(
|
|||
gecko_enum_prefix="StylePointerEvents",
|
||||
)}
|
||||
|
||||
${helpers.single_keyword(
|
||||
"-moz-inert",
|
||||
"none inert",
|
||||
engines="gecko",
|
||||
gecko_ffi_name="mInert",
|
||||
gecko_enum_prefix="StyleInert",
|
||||
animation_value_type="discrete",
|
||||
enabled_in="ua",
|
||||
spec="Nonstandard (https://html.spec.whatwg.org/multipage/interaction.html#inert-subtrees)",
|
||||
)}
|
||||
|
||||
${helpers.single_keyword(
|
||||
"-moz-user-input",
|
||||
"auto none",
|
||||
|
|
|
@ -347,6 +347,7 @@ impl ToCss for NonTSPseudoClass {
|
|||
Fullscreen => ":fullscreen",
|
||||
Hover => ":hover",
|
||||
Indeterminate => ":indeterminate",
|
||||
MozInert => ":-moz-inert",
|
||||
Link => ":link",
|
||||
PlaceholderShown => ":placeholder-shown",
|
||||
ReadWrite => ":read-write",
|
||||
|
@ -436,6 +437,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
|
|||
"fullscreen" => Fullscreen,
|
||||
"hover" => Hover,
|
||||
"indeterminate" => Indeterminate,
|
||||
"-moz-inert" => MozInert,
|
||||
"link" => Link,
|
||||
"placeholder-shown" => PlaceholderShown,
|
||||
"read-write" => ReadWrite,
|
||||
|
|
|
@ -153,6 +153,56 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
/// https://html.spec.whatwg.org/multipage/interaction.html#inert-subtrees
|
||||
///
|
||||
/// If -moz-inert is applied then add:
|
||||
/// -moz-user-focus: none;
|
||||
/// -moz-user-input: none;
|
||||
/// -moz-user-modify: read-only;
|
||||
/// user-select: none;
|
||||
/// pointer-events: none;
|
||||
/// cursor: default;
|
||||
fn adjust_for_inert(&mut self) {
|
||||
use properties::longhands::_moz_inert::computed_value::T as Inert;
|
||||
use properties::longhands::_moz_user_focus::computed_value::T as UserFocus;
|
||||
use properties::longhands::_moz_user_input::computed_value::T as UserInput;
|
||||
use properties::longhands::_moz_user_modify::computed_value::T as UserModify;
|
||||
use properties::longhands::pointer_events::computed_value::T as PointerEvents;
|
||||
use properties::longhands::cursor::computed_value::T as Cursor;
|
||||
use crate::values::specified::ui::CursorKind;
|
||||
use crate::values::specified::ui::UserSelect;
|
||||
|
||||
let needs_update = {
|
||||
let ui = self.style.get_inherited_ui();
|
||||
if ui.clone__moz_inert() == Inert::None {
|
||||
return;
|
||||
}
|
||||
|
||||
ui.clone__moz_user_focus() != UserFocus::None ||
|
||||
ui.clone__moz_user_input() != UserInput::None ||
|
||||
ui.clone__moz_user_modify() != UserModify::ReadOnly ||
|
||||
ui.clone_pointer_events() != PointerEvents::None ||
|
||||
ui.clone_cursor().keyword != CursorKind::Default ||
|
||||
ui.clone_cursor().images != Default::default()
|
||||
};
|
||||
|
||||
if needs_update {
|
||||
let ui = self.style.mutate_inherited_ui();
|
||||
ui.set__moz_user_focus(UserFocus::None);
|
||||
ui.set__moz_user_input(UserInput::None);
|
||||
ui.set__moz_user_modify(UserModify::ReadOnly);
|
||||
ui.set_pointer_events(PointerEvents::None);
|
||||
ui.set_cursor(Cursor {
|
||||
images: Default::default(),
|
||||
keyword: CursorKind::Default,
|
||||
});
|
||||
}
|
||||
|
||||
if self.style.get_ui().clone_user_select() != UserSelect::None {
|
||||
self.style.mutate_ui().set_user_select(UserSelect::None);
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether we should skip any item-based display property blockification on
|
||||
/// this element.
|
||||
fn skip_item_display_fixup<E>(&self, element: Option<E>) -> bool
|
||||
|
@ -855,6 +905,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
|||
#[cfg(feature = "gecko")]
|
||||
{
|
||||
self.adjust_for_appearance(element);
|
||||
self.adjust_for_inert();
|
||||
}
|
||||
self.set_bits();
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
prefs: [html5.inert.enabled:true]
|
|
@ -1,4 +0,0 @@
|
|||
[inert-in-shadow-dom.tentative.html]
|
||||
[inert on Shadow host affects content in shadow]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[inert-inlines.tentative.html]
|
||||
[Tests that inert inlines do not receive mouse events. To test manually, click on all the "Click me"s. The test fails if you see red.]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[inert-label-focus.tentative.html]
|
||||
[Calling focus() on a label for a control which is in an inert subtree should have no effect.]
|
||||
expected: FAIL
|
||||
|
|
@ -5,12 +5,6 @@
|
|||
[Elements inside of inert subtrees return false when getting 'inert']
|
||||
expected: FAIL
|
||||
|
||||
[Button with inert atribute is unfocusable.]
|
||||
expected: FAIL
|
||||
|
||||
[All focusable elements inside inert subtree are unfocusable]
|
||||
expected: FAIL
|
||||
|
||||
[Can get inert via property]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -531,6 +531,7 @@ STATIC_ATOMS = [
|
|||
Atom("indent", "indent"),
|
||||
Atom("indeterminate", "indeterminate"),
|
||||
Atom("index", "index"),
|
||||
Atom("inert", "inert"),
|
||||
Atom("infinity", "infinity"),
|
||||
Atom("inherits", "inherits"),
|
||||
Atom("inheritOverflow", "inherit-overflow"),
|
||||
|
|
Загрузка…
Ссылка в новой задаче