style: Implement <tabpanels> and <deck> without XUL layout

Gijs for front-end bits, layout for the new CSS properties and the
removal of nsDeckFrame / nsStackLayout, Jamie and Morgan for the a11y
changes.

As discussed in the bug, the main tricky part here is handling a11y
correctly. For <deck>, that's trivial (just use `visibility: hidden` to
hide the panels visually, while removing the unselected panels from the
a11y tree).

For <tabpanels> however we need to do something special. We do want to
hide stuff visually, but we want to preserve the contents in the a11y
tree.

For that, the easiest fix is introducing a new privileged CSS property
(-moz-subtree-hidden-only-visually), which takes care of not painting
the frame, but marks stuff offscreen in the accessibility tree. This is
not intended to be a property used widely.

Other than that, the changes are relatively straight-forward, though
some of the accessible/mac changes I could get a sanity-check on.

Differential Revision: https://phabricator.services.mozilla.com/D157875
This commit is contained in:
Emilio Cobos Álvarez 2022-09-27 04:18:16 +00:00 committed by Martin Robinson
parent 6fa8160633
commit 6cfdd989d5
7 changed files with 29 additions and 38 deletions

View file

@ -468,7 +468,7 @@ class Longhand(Property):
"LineBreak",
"LineClamp",
"MasonryAutoFlow",
"MozForceBrokenImageIcon",
"BoolInteger",
"text::MozControlCharacterVisibility",
"MathDepth",
"MozScriptMinSize",

View file

@ -108,11 +108,23 @@ ${helpers.predefined_type(
enabled_in="chrome",
)}
// Hack to allow chrome to hide stuff only visually (without hiding it from
// a11y).
${helpers.predefined_type(
"-moz-subtree-hidden-only-visually",
"BoolInteger",
"computed::BoolInteger::zero()",
engines="gecko",
animation_value_type="discrete",
spec="None (Nonstandard internal property)",
enabled_in="chrome",
)}
// TODO(emilio): Probably also should be hidden from content.
${helpers.predefined_type(
"-moz-force-broken-image-icon",
"MozForceBrokenImageIcon",
"computed::MozForceBrokenImageIcon::false_value()",
"BoolInteger",
"computed::BoolInteger::zero()",
engines="gecko",
animation_value_type="discrete",
spec="None (Nonstandard Firefox-only property)",

View file

@ -97,7 +97,7 @@ pub use self::transform::{Rotate, Scale, Transform, TransformOperation};
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
#[cfg(feature = "gecko")]
pub use self::ui::CursorImage;
pub use self::ui::{Cursor, MozForceBrokenImageIcon, UserSelect};
pub use self::ui::{Cursor, BoolInteger, UserSelect};
pub use super::specified::TextTransform;
pub use super::specified::ViewportVariant;
pub use super::specified::{BorderStyle, TextDecorationLine};

View file

@ -10,7 +10,7 @@ use crate::values::computed::Number;
use crate::values::generics::ui as generics;
pub use crate::values::specified::ui::CursorKind;
pub use crate::values::specified::ui::{MozForceBrokenImageIcon, UserSelect};
pub use crate::values::specified::ui::{BoolInteger, UserSelect};
/// A computed value for the `cursor` property.
pub type Cursor = generics::GenericCursor<CursorImage>;

View file

@ -90,8 +90,6 @@ pub enum DisplayInside {
#[cfg(feature = "gecko")]
MozBox,
#[cfg(feature = "gecko")]
MozDeck,
#[cfg(feature = "gecko")]
MozPopup,
}
@ -193,8 +191,6 @@ impl Display {
#[cfg(feature = "gecko")]
pub const MozInlineBox: Self = Self::new(DisplayOutside::Inline, DisplayInside::MozBox);
#[cfg(feature = "gecko")]
pub const MozDeck: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozDeck);
#[cfg(feature = "gecko")]
pub const MozPopup: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozPopup);
/// Make a raw display value from <display-outside> and <display-inside> values.
@ -559,8 +555,6 @@ impl Parse for Display {
#[cfg(feature = "gecko")]
"-moz-inline-box" if moz_display_values_enabled(context) => Display::MozInlineBox,
#[cfg(feature = "gecko")]
"-moz-deck" if moz_display_values_enabled(context) => Display::MozDeck,
#[cfg(feature = "gecko")]
"-moz-popup" if moz_display_values_enabled(context) => Display::MozPopup,
})
}

View file

@ -97,7 +97,7 @@ pub use self::transform::{Rotate, Scale, Transform};
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
#[cfg(feature = "gecko")]
pub use self::ui::CursorImage;
pub use self::ui::{Cursor, MozForceBrokenImageIcon, UserSelect};
pub use self::ui::{Cursor, BoolInteger, UserSelect};
pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent;
#[cfg(feature = "gecko")]

View file

@ -88,31 +88,32 @@ impl SpecifiedValueInfo for CursorImage {
ToResolvedValue,
ToShmem,
)]
pub struct MozForceBrokenImageIcon(pub bool);
#[repr(transparent)]
pub struct BoolInteger(pub bool);
impl MozForceBrokenImageIcon {
/// Return initial value of -moz-force-broken-image-icon which is false.
impl BoolInteger {
/// Returns 0
#[inline]
pub fn false_value() -> MozForceBrokenImageIcon {
MozForceBrokenImageIcon(false)
pub fn zero() -> Self {
Self(false)
}
}
impl Parse for MozForceBrokenImageIcon {
impl Parse for BoolInteger {
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<MozForceBrokenImageIcon, ParseError<'i>> {
) -> Result<Self, ParseError<'i>> {
// We intentionally don't support calc values here.
match input.expect_integer()? {
0 => Ok(MozForceBrokenImageIcon(false)),
1 => Ok(MozForceBrokenImageIcon(true)),
0 => Ok(Self(false)),
1 => Ok(Self(true)),
_ => Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
}
}
}
impl ToCss for MozForceBrokenImageIcon {
impl ToCss for BoolInteger {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
@ -121,22 +122,6 @@ impl ToCss for MozForceBrokenImageIcon {
}
}
impl From<u8> for MozForceBrokenImageIcon {
fn from(bits: u8) -> MozForceBrokenImageIcon {
MozForceBrokenImageIcon(bits == 1)
}
}
impl From<MozForceBrokenImageIcon> for u8 {
fn from(v: MozForceBrokenImageIcon) -> u8 {
if v.0 {
1
} else {
0
}
}
}
/// A specified value for `scrollbar-color` property
pub type ScrollbarColor = generics::ScrollbarColor<Color>;