mirror of
https://github.com/servo/servo.git
synced 2025-08-08 06:55:31 +01:00
This reverts commit 8e15389cae
.
This commit is contained in:
parent
8e15389cae
commit
d6ae8dc112
152 changed files with 4622 additions and 5862 deletions
|
@ -15,7 +15,7 @@ use crate::gecko_bindings::structs::{
|
|||
RawServoKeyframesRule, RawServoLayerBlockRule, RawServoLayerStatementRule, RawServoMediaList,
|
||||
RawServoMediaRule, RawServoMozDocumentRule, RawServoNamespaceRule, RawServoPageRule,
|
||||
RawServoScrollTimelineRule, RawServoStyleRule, RawServoStyleSheetContents,
|
||||
RawServoSupportsRule, RawServoContainerRule, ServoCssRules,
|
||||
RawServoSupportsRule, ServoCssRules,
|
||||
};
|
||||
use crate::gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI, Strong};
|
||||
use crate::media_queries::MediaList;
|
||||
|
@ -26,7 +26,7 @@ use crate::stylesheets::keyframes_rule::Keyframe;
|
|||
use crate::stylesheets::{
|
||||
CounterStyleRule, CssRules, DocumentRule, FontFaceRule, FontFeatureValuesRule, ImportRule,
|
||||
KeyframesRule, LayerBlockRule, LayerStatementRule, MediaRule, NamespaceRule, PageRule,
|
||||
ScrollTimelineRule, StyleRule, StylesheetContents, SupportsRule, ContainerRule,
|
||||
ScrollTimelineRule, StyleRule, StylesheetContents, SupportsRule,
|
||||
};
|
||||
use servo_arc::{Arc, ArcBorrow};
|
||||
use std::{mem, ptr};
|
||||
|
@ -98,9 +98,6 @@ impl_arc_ffi!(Locked<ScrollTimelineRule> => RawServoScrollTimelineRule
|
|||
impl_arc_ffi!(Locked<SupportsRule> => RawServoSupportsRule
|
||||
[Servo_SupportsRule_AddRef, Servo_SupportsRule_Release]);
|
||||
|
||||
impl_arc_ffi!(Locked<ContainerRule> => RawServoContainerRule
|
||||
[Servo_ContainerRule_AddRef, Servo_ContainerRule_Release]);
|
||||
|
||||
impl_arc_ffi!(Locked<DocumentRule> => RawServoMozDocumentRule
|
||||
[Servo_DocumentRule_AddRef, Servo_DocumentRule_Release]);
|
||||
|
||||
|
|
|
@ -129,12 +129,6 @@ impl StylesheetInDocument for GeckoStyleSheet {
|
|||
pub struct PerDocumentStyleDataImpl {
|
||||
/// Rule processor.
|
||||
pub stylist: Stylist,
|
||||
|
||||
/// A cache from element to resolved style.
|
||||
pub undisplayed_style_cache: crate::traversal::UndisplayedStyleCache,
|
||||
|
||||
/// The generation for which our cache is valid.
|
||||
pub undisplayed_style_cache_generation: u64,
|
||||
}
|
||||
|
||||
/// The data itself is an `AtomicRefCell`, which guarantees the proper semantics
|
||||
|
@ -149,8 +143,6 @@ impl PerDocumentStyleData {
|
|||
|
||||
PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl {
|
||||
stylist: Stylist::new(device, quirks_mode.into()),
|
||||
undisplayed_style_cache: Default::default(),
|
||||
undisplayed_style_cache_generation: 0,
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -185,6 +177,12 @@ impl PerDocumentStyleDataImpl {
|
|||
self.stylist.device().default_computed_values_arc()
|
||||
}
|
||||
|
||||
/// Returns whether visited styles are enabled.
|
||||
#[inline]
|
||||
pub fn visited_styles_enabled(&self) -> bool {
|
||||
unsafe { bindings::Gecko_VisitedStylesEnabled(self.stylist.device().document()) }
|
||||
}
|
||||
|
||||
/// Measure heap usage.
|
||||
pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
|
||||
self.stylist.add_size_of(ops, sizes);
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
|
||||
use crate::gecko_bindings::bindings;
|
||||
use crate::gecko_bindings::structs;
|
||||
use crate::queries::feature::{AllowsRanges, Evaluator, FeatureFlags, QueryFeatureDescription};
|
||||
use crate::queries::values::Orientation;
|
||||
use crate::media_queries::media_feature::{AllowsRanges, ParsingRequirements};
|
||||
use crate::media_queries::media_feature::{Evaluator, MediaFeatureDescription};
|
||||
use crate::media_queries::media_feature_expression::RangeOrOperator;
|
||||
use crate::media_queries::{Device, MediaType};
|
||||
use crate::values::computed::{Context, CSSPixelLength, Ratio, Resolution};
|
||||
use crate::values::computed::CSSPixelLength;
|
||||
use crate::values::computed::Ratio;
|
||||
use crate::values::computed::Resolution;
|
||||
use app_units::Au;
|
||||
use euclid::default::Size2D;
|
||||
|
||||
|
@ -23,56 +26,150 @@ fn device_size(device: &Device) -> Size2D<Au> {
|
|||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#width
|
||||
fn eval_width(context: &Context) -> CSSPixelLength {
|
||||
CSSPixelLength::new(context.device().au_viewport_size().width.to_f32_px())
|
||||
fn eval_width(
|
||||
device: &Device,
|
||||
value: Option<CSSPixelLength>,
|
||||
range_or_operator: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
RangeOrOperator::evaluate(
|
||||
range_or_operator,
|
||||
value.map(Au::from),
|
||||
device.au_viewport_size().width,
|
||||
)
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#device-width
|
||||
fn eval_device_width(context: &Context) -> CSSPixelLength {
|
||||
CSSPixelLength::new(device_size(context.device()).width.to_f32_px())
|
||||
fn eval_device_width(
|
||||
device: &Device,
|
||||
value: Option<CSSPixelLength>,
|
||||
range_or_operator: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
RangeOrOperator::evaluate(
|
||||
range_or_operator,
|
||||
value.map(Au::from),
|
||||
device_size(device).width,
|
||||
)
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#height
|
||||
fn eval_height(context: &Context) -> CSSPixelLength {
|
||||
CSSPixelLength::new(context.device().au_viewport_size().height.to_f32_px())
|
||||
fn eval_height(
|
||||
device: &Device,
|
||||
value: Option<CSSPixelLength>,
|
||||
range_or_operator: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
RangeOrOperator::evaluate(
|
||||
range_or_operator,
|
||||
value.map(Au::from),
|
||||
device.au_viewport_size().height,
|
||||
)
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#device-height
|
||||
fn eval_device_height(context: &Context) -> CSSPixelLength {
|
||||
CSSPixelLength::new(device_size(context.device()).height.to_f32_px())
|
||||
fn eval_device_height(
|
||||
device: &Device,
|
||||
value: Option<CSSPixelLength>,
|
||||
range_or_operator: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
RangeOrOperator::evaluate(
|
||||
range_or_operator,
|
||||
value.map(Au::from),
|
||||
device_size(device).height,
|
||||
)
|
||||
}
|
||||
|
||||
fn eval_aspect_ratio_for<F>(context: &Context, get_size: F) -> Ratio
|
||||
fn eval_aspect_ratio_for<F>(
|
||||
device: &Device,
|
||||
query_value: Option<Ratio>,
|
||||
range_or_operator: Option<RangeOrOperator>,
|
||||
get_size: F,
|
||||
) -> bool
|
||||
where
|
||||
F: FnOnce(&Device) -> Size2D<Au>,
|
||||
{
|
||||
let size = get_size(context.device());
|
||||
Ratio::new(size.width.0 as f32, size.height.0 as f32)
|
||||
// A ratio of 0/0 behaves as the ratio 1/0, so we need to call used_value()
|
||||
// to convert it if necessary.
|
||||
// FIXME: we may need to update here once
|
||||
// https://github.com/w3c/csswg-drafts/issues/4954 got resolved.
|
||||
let query_value = match query_value {
|
||||
Some(v) => v.used_value(),
|
||||
None => return true,
|
||||
};
|
||||
|
||||
let size = get_size(device);
|
||||
let value = Ratio::new(size.width.0 as f32, size.height.0 as f32);
|
||||
RangeOrOperator::evaluate_with_query_value(range_or_operator, query_value, value)
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#aspect-ratio
|
||||
fn eval_aspect_ratio(context: &Context) -> Ratio {
|
||||
eval_aspect_ratio_for(context, Device::au_viewport_size)
|
||||
fn eval_aspect_ratio(
|
||||
device: &Device,
|
||||
query_value: Option<Ratio>,
|
||||
range_or_operator: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
eval_aspect_ratio_for(
|
||||
device,
|
||||
query_value,
|
||||
range_or_operator,
|
||||
Device::au_viewport_size,
|
||||
)
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#device-aspect-ratio
|
||||
fn eval_device_aspect_ratio(context: &Context) -> Ratio {
|
||||
eval_aspect_ratio_for(context, device_size)
|
||||
fn eval_device_aspect_ratio(
|
||||
device: &Device,
|
||||
query_value: Option<Ratio>,
|
||||
range_or_operator: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
eval_aspect_ratio_for(device, query_value, range_or_operator, device_size)
|
||||
}
|
||||
|
||||
/// https://compat.spec.whatwg.org/#css-media-queries-webkit-device-pixel-ratio
|
||||
fn eval_device_pixel_ratio(context: &Context) -> f32 {
|
||||
eval_resolution(context).dppx()
|
||||
fn eval_device_pixel_ratio(
|
||||
device: &Device,
|
||||
query_value: Option<f32>,
|
||||
range_or_operator: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
eval_resolution(
|
||||
device,
|
||||
query_value.map(Resolution::from_dppx),
|
||||
range_or_operator,
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)]
|
||||
#[repr(u8)]
|
||||
enum Orientation {
|
||||
Landscape,
|
||||
Portrait,
|
||||
}
|
||||
|
||||
fn eval_orientation_for<F>(device: &Device, value: Option<Orientation>, get_size: F) -> bool
|
||||
where
|
||||
F: FnOnce(&Device) -> Size2D<Au>,
|
||||
{
|
||||
let query_orientation = match value {
|
||||
Some(v) => v,
|
||||
None => return true,
|
||||
};
|
||||
|
||||
let size = get_size(device);
|
||||
|
||||
// Per spec, square viewports should be 'portrait'
|
||||
let is_landscape = size.width > size.height;
|
||||
match query_orientation {
|
||||
Orientation::Landscape => is_landscape,
|
||||
Orientation::Portrait => !is_landscape,
|
||||
}
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#orientation
|
||||
fn eval_orientation(context: &Context, value: Option<Orientation>) -> bool {
|
||||
Orientation::eval(context.device().au_viewport_size(), value)
|
||||
fn eval_orientation(device: &Device, value: Option<Orientation>) -> bool {
|
||||
eval_orientation_for(device, value, Device::au_viewport_size)
|
||||
}
|
||||
|
||||
/// FIXME: There's no spec for `-moz-device-orientation`.
|
||||
fn eval_device_orientation(context: &Context, value: Option<Orientation>) -> bool {
|
||||
Orientation::eval(device_size(context.device()), value)
|
||||
fn eval_device_orientation(device: &Device, value: Option<Orientation>) -> bool {
|
||||
eval_orientation_for(device, value, device_size)
|
||||
}
|
||||
|
||||
/// Values for the display-mode media feature.
|
||||
|
@ -87,23 +184,25 @@ pub enum DisplayMode {
|
|||
}
|
||||
|
||||
/// https://w3c.github.io/manifest/#the-display-mode-media-feature
|
||||
fn eval_display_mode(context: &Context, query_value: Option<DisplayMode>) -> bool {
|
||||
fn eval_display_mode(device: &Device, query_value: Option<DisplayMode>) -> bool {
|
||||
match query_value {
|
||||
Some(v) => v == unsafe { bindings::Gecko_MediaFeatures_GetDisplayMode(context.device().document()) },
|
||||
Some(v) => v == unsafe { bindings::Gecko_MediaFeatures_GetDisplayMode(device.document()) },
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#grid
|
||||
fn eval_grid(_: &Context) -> bool {
|
||||
fn eval_grid(_: &Device, query_value: Option<bool>, _: Option<RangeOrOperator>) -> bool {
|
||||
// Gecko doesn't support grid devices (e.g., ttys), so the 'grid' feature
|
||||
// is always 0.
|
||||
false
|
||||
let supports_grid = false;
|
||||
query_value.map_or(supports_grid, |v| v == supports_grid)
|
||||
}
|
||||
|
||||
/// https://compat.spec.whatwg.org/#css-media-queries-webkit-transform-3d
|
||||
fn eval_transform_3d(_: &Context) -> bool {
|
||||
true
|
||||
fn eval_transform_3d(_: &Device, query_value: Option<bool>, _: Option<RangeOrOperator>) -> bool {
|
||||
let supports_transforms = true;
|
||||
query_value.map_or(supports_transforms, |v| v == supports_transforms)
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)]
|
||||
|
@ -114,33 +213,58 @@ enum Scan {
|
|||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#scan
|
||||
fn eval_scan(_: &Context, _: Option<Scan>) -> bool {
|
||||
fn eval_scan(_: &Device, _: Option<Scan>) -> bool {
|
||||
// Since Gecko doesn't support the 'tv' media type, the 'scan' feature never
|
||||
// matches.
|
||||
false
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#color
|
||||
fn eval_color(context: &Context) -> u32 {
|
||||
unsafe { bindings::Gecko_MediaFeatures_GetColorDepth(context.device().document()) }
|
||||
fn eval_color(
|
||||
device: &Device,
|
||||
query_value: Option<u32>,
|
||||
range_or_operator: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
let color_bits_per_channel =
|
||||
unsafe { bindings::Gecko_MediaFeatures_GetColorDepth(device.document()) };
|
||||
RangeOrOperator::evaluate(range_or_operator, query_value, color_bits_per_channel)
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#color-index
|
||||
fn eval_color_index(_: &Context) -> u32 {
|
||||
fn eval_color_index(
|
||||
_: &Device,
|
||||
query_value: Option<u32>,
|
||||
range_or_operator: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
// We should return zero if the device does not use a color lookup table.
|
||||
0
|
||||
let index = 0;
|
||||
RangeOrOperator::evaluate(range_or_operator, query_value, index)
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#monochrome
|
||||
fn eval_monochrome(context: &Context) -> u32 {
|
||||
fn eval_monochrome(
|
||||
device: &Device,
|
||||
query_value: Option<u32>,
|
||||
range_or_operator: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
// For color devices we should return 0.
|
||||
unsafe { bindings::Gecko_MediaFeatures_GetMonochromeBitsPerPixel(context.device().document()) }
|
||||
let depth =
|
||||
unsafe { bindings::Gecko_MediaFeatures_GetMonochromeBitsPerPixel(device.document()) };
|
||||
RangeOrOperator::evaluate(range_or_operator, query_value, depth)
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#resolution
|
||||
fn eval_resolution(context: &Context) -> Resolution {
|
||||
let resolution_dppx = unsafe { bindings::Gecko_MediaFeatures_GetResolution(context.device().document()) };
|
||||
Resolution::from_dppx(resolution_dppx)
|
||||
fn eval_resolution(
|
||||
device: &Device,
|
||||
query_value: Option<Resolution>,
|
||||
range_or_operator: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
let resolution_dppx = unsafe { bindings::Gecko_MediaFeatures_GetResolution(device.document()) };
|
||||
RangeOrOperator::evaluate(
|
||||
range_or_operator,
|
||||
query_value.map(|r| r.dppx()),
|
||||
resolution_dppx,
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)]
|
||||
|
@ -159,22 +283,10 @@ pub enum PrefersColorScheme {
|
|||
Dark,
|
||||
}
|
||||
|
||||
/// Values for the dynamic-range and video-dynamic-range media features.
|
||||
/// https://drafts.csswg.org/mediaqueries-5/#dynamic-range
|
||||
/// This implements PartialOrd so that lower values will correctly match
|
||||
/// higher capabilities.
|
||||
#[derive(Clone, Copy, Debug, FromPrimitive, Parse, PartialEq, PartialOrd, ToCss)]
|
||||
#[repr(u8)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum DynamicRange {
|
||||
Standard,
|
||||
High,
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-5/#prefers-reduced-motion
|
||||
fn eval_prefers_reduced_motion(context: &Context, query_value: Option<PrefersReducedMotion>) -> bool {
|
||||
fn eval_prefers_reduced_motion(device: &Device, query_value: Option<PrefersReducedMotion>) -> bool {
|
||||
let prefers_reduced =
|
||||
unsafe { bindings::Gecko_MediaFeatures_PrefersReducedMotion(context.device().document()) };
|
||||
unsafe { bindings::Gecko_MediaFeatures_PrefersReducedMotion(device.document()) };
|
||||
let query_value = match query_value {
|
||||
Some(v) => v,
|
||||
None => return prefers_reduced,
|
||||
|
@ -191,20 +303,19 @@ fn eval_prefers_reduced_motion(context: &Context, query_value: Option<PrefersRed
|
|||
#[derive(Clone, Copy, Debug, FromPrimitive, Parse, PartialEq, ToCss)]
|
||||
#[repr(u8)]
|
||||
pub enum PrefersContrast {
|
||||
/// More contrast is preferred.
|
||||
/// More contrast is preferred. Corresponds to an accessibility theme
|
||||
/// being enabled or Firefox forcing high contrast colors.
|
||||
More,
|
||||
/// Low contrast is preferred.
|
||||
Less,
|
||||
/// Custom (not more, not less).
|
||||
Custom,
|
||||
/// The default value if neither high or low contrast is enabled.
|
||||
NoPreference,
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-5/#prefers-contrast
|
||||
fn eval_prefers_contrast(context: &Context, query_value: Option<PrefersContrast>) -> bool {
|
||||
fn eval_prefers_contrast(device: &Device, query_value: Option<PrefersContrast>) -> bool {
|
||||
let prefers_contrast =
|
||||
unsafe { bindings::Gecko_MediaFeatures_PrefersContrast(context.device().document()) };
|
||||
unsafe { bindings::Gecko_MediaFeatures_PrefersContrast(device.document()) };
|
||||
match query_value {
|
||||
Some(v) => v == prefers_contrast,
|
||||
None => prefers_contrast != PrefersContrast::NoPreference,
|
||||
|
@ -223,8 +334,8 @@ pub enum ForcedColors {
|
|||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-5/#forced-colors
|
||||
fn eval_forced_colors(context: &Context, query_value: Option<ForcedColors>) -> bool {
|
||||
let forced = !context.device().use_document_colors();
|
||||
fn eval_forced_colors(device: &Device, query_value: Option<ForcedColors>) -> bool {
|
||||
let forced = !device.use_document_colors();
|
||||
match query_value {
|
||||
Some(query_value) => forced == (query_value == ForcedColors::Active),
|
||||
None => forced,
|
||||
|
@ -241,7 +352,7 @@ enum OverflowBlock {
|
|||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#mf-overflow-block
|
||||
fn eval_overflow_block(context: &Context, query_value: Option<OverflowBlock>) -> bool {
|
||||
fn eval_overflow_block(device: &Device, query_value: Option<OverflowBlock>) -> bool {
|
||||
// For the time being, assume that printing (including previews)
|
||||
// is the only time when we paginate, and we are otherwise always
|
||||
// scrolling. This is true at the moment in Firefox, but may need
|
||||
|
@ -249,7 +360,7 @@ fn eval_overflow_block(context: &Context, query_value: Option<OverflowBlock>) ->
|
|||
// billboard mode that doesn't support overflow at all).
|
||||
//
|
||||
// If this ever changes, don't forget to change eval_overflow_inline too.
|
||||
let scrolling = context.device().media_type() != MediaType::print();
|
||||
let scrolling = device.media_type() != MediaType::print();
|
||||
let query_value = match query_value {
|
||||
Some(v) => v,
|
||||
None => return true,
|
||||
|
@ -270,9 +381,9 @@ enum OverflowInline {
|
|||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#mf-overflow-inline
|
||||
fn eval_overflow_inline(context: &Context, query_value: Option<OverflowInline>) -> bool {
|
||||
fn eval_overflow_inline(device: &Device, query_value: Option<OverflowInline>) -> bool {
|
||||
// See the note in eval_overflow_block.
|
||||
let scrolling = context.device().media_type() != MediaType::print();
|
||||
let scrolling = device.media_type() != MediaType::print();
|
||||
let query_value = match query_value {
|
||||
Some(v) => v,
|
||||
None => return scrolling,
|
||||
|
@ -284,41 +395,13 @@ fn eval_overflow_inline(context: &Context, query_value: Option<OverflowInline>)
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)]
|
||||
#[repr(u8)]
|
||||
enum Update {
|
||||
None,
|
||||
Slow,
|
||||
Fast,
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#update
|
||||
fn eval_update(context: &Context, query_value: Option<Update>) -> bool {
|
||||
// This has similar caveats to those described in eval_overflow_block.
|
||||
// For now, we report that print (incl. print media simulation,
|
||||
// which can in fact update but is limited to the developer tools)
|
||||
// is `update: none` and that all other contexts are `update: fast`,
|
||||
// which may not be true for future platforms, like e-ink devices.
|
||||
let can_update = context.device().media_type() != MediaType::print();
|
||||
let query_value = match query_value {
|
||||
Some(v) => v,
|
||||
None => return can_update,
|
||||
};
|
||||
|
||||
match query_value {
|
||||
Update::None => !can_update,
|
||||
Update::Slow => false,
|
||||
Update::Fast => can_update,
|
||||
}
|
||||
}
|
||||
|
||||
fn do_eval_prefers_color_scheme(
|
||||
context: &Context,
|
||||
device: &Device,
|
||||
use_content: bool,
|
||||
query_value: Option<PrefersColorScheme>,
|
||||
) -> bool {
|
||||
let prefers_color_scheme =
|
||||
unsafe { bindings::Gecko_MediaFeatures_PrefersColorScheme(context.device().document(), use_content) };
|
||||
unsafe { bindings::Gecko_MediaFeatures_PrefersColorScheme(device.document(), use_content) };
|
||||
match query_value {
|
||||
Some(v) => prefers_color_scheme == v,
|
||||
None => true,
|
||||
|
@ -326,34 +409,15 @@ fn do_eval_prefers_color_scheme(
|
|||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme
|
||||
fn eval_prefers_color_scheme(context: &Context, query_value: Option<PrefersColorScheme>) -> bool {
|
||||
do_eval_prefers_color_scheme(context, /* use_content = */ false, query_value)
|
||||
fn eval_prefers_color_scheme(device: &Device, query_value: Option<PrefersColorScheme>) -> bool {
|
||||
do_eval_prefers_color_scheme(device, /* use_content = */ false, query_value)
|
||||
}
|
||||
|
||||
fn eval_content_prefers_color_scheme(
|
||||
context: &Context,
|
||||
device: &Device,
|
||||
query_value: Option<PrefersColorScheme>,
|
||||
) -> bool {
|
||||
do_eval_prefers_color_scheme(context, /* use_content = */ true, query_value)
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-5/#dynamic-range
|
||||
fn eval_dynamic_range(context: &Context, query_value: Option<DynamicRange>) -> bool {
|
||||
let dynamic_range =
|
||||
unsafe { bindings::Gecko_MediaFeatures_DynamicRange(context.device().document()) };
|
||||
match query_value {
|
||||
Some(v) => dynamic_range >= v,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
/// https://drafts.csswg.org/mediaqueries-5/#video-dynamic-range
|
||||
fn eval_video_dynamic_range(context: &Context, query_value: Option<DynamicRange>) -> bool {
|
||||
let dynamic_range =
|
||||
unsafe { bindings::Gecko_MediaFeatures_VideoDynamicRange(context.device().document()) };
|
||||
match query_value {
|
||||
Some(v) => dynamic_range >= v,
|
||||
None => false,
|
||||
}
|
||||
do_eval_prefers_color_scheme(device, /* use_content = */ true, query_value)
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
|
@ -365,15 +429,15 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
fn primary_pointer_capabilities(context: &Context) -> PointerCapabilities {
|
||||
fn primary_pointer_capabilities(device: &Device) -> PointerCapabilities {
|
||||
PointerCapabilities::from_bits_truncate(unsafe {
|
||||
bindings::Gecko_MediaFeatures_PrimaryPointerCapabilities(context.device().document())
|
||||
bindings::Gecko_MediaFeatures_PrimaryPointerCapabilities(device.document())
|
||||
})
|
||||
}
|
||||
|
||||
fn all_pointer_capabilities(context: &Context) -> PointerCapabilities {
|
||||
fn all_pointer_capabilities(device: &Device) -> PointerCapabilities {
|
||||
PointerCapabilities::from_bits_truncate(unsafe {
|
||||
bindings::Gecko_MediaFeatures_AllPointerCapabilities(context.device().document())
|
||||
bindings::Gecko_MediaFeatures_AllPointerCapabilities(device.document())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -402,13 +466,13 @@ fn eval_pointer_capabilities(
|
|||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#pointer
|
||||
fn eval_pointer(context: &Context, query_value: Option<Pointer>) -> bool {
|
||||
eval_pointer_capabilities(query_value, primary_pointer_capabilities(context))
|
||||
fn eval_pointer(device: &Device, query_value: Option<Pointer>) -> bool {
|
||||
eval_pointer_capabilities(query_value, primary_pointer_capabilities(device))
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#descdef-media-any-pointer
|
||||
fn eval_any_pointer(context: &Context, query_value: Option<Pointer>) -> bool {
|
||||
eval_pointer_capabilities(query_value, all_pointer_capabilities(context))
|
||||
fn eval_any_pointer(device: &Device, query_value: Option<Pointer>) -> bool {
|
||||
eval_pointer_capabilities(query_value, all_pointer_capabilities(device))
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)]
|
||||
|
@ -435,33 +499,54 @@ fn eval_hover_capabilities(
|
|||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#hover
|
||||
fn eval_hover(context: &Context, query_value: Option<Hover>) -> bool {
|
||||
eval_hover_capabilities(query_value, primary_pointer_capabilities(context))
|
||||
fn eval_hover(device: &Device, query_value: Option<Hover>) -> bool {
|
||||
eval_hover_capabilities(query_value, primary_pointer_capabilities(device))
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-4/#descdef-media-any-hover
|
||||
fn eval_any_hover(context: &Context, query_value: Option<Hover>) -> bool {
|
||||
eval_hover_capabilities(query_value, all_pointer_capabilities(context))
|
||||
fn eval_any_hover(device: &Device, query_value: Option<Hover>) -> bool {
|
||||
eval_hover_capabilities(query_value, all_pointer_capabilities(device))
|
||||
}
|
||||
|
||||
fn eval_moz_is_glyph(context: &Context) -> bool {
|
||||
context.device().document().mIsSVGGlyphsDocument()
|
||||
fn eval_moz_is_glyph(
|
||||
device: &Device,
|
||||
query_value: Option<bool>,
|
||||
_: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
let is_glyph = device.document().mIsSVGGlyphsDocument();
|
||||
query_value.map_or(is_glyph, |v| v == is_glyph)
|
||||
}
|
||||
|
||||
fn eval_moz_print_preview(context: &Context) -> bool {
|
||||
let is_print_preview = context.device().is_print_preview();
|
||||
fn eval_moz_print_preview(
|
||||
device: &Device,
|
||||
query_value: Option<bool>,
|
||||
_: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
let is_print_preview = device.is_print_preview();
|
||||
if is_print_preview {
|
||||
debug_assert_eq!(context.device().media_type(), MediaType::print());
|
||||
debug_assert_eq!(device.media_type(), MediaType::print());
|
||||
}
|
||||
is_print_preview
|
||||
query_value.map_or(is_print_preview, |v| v == is_print_preview)
|
||||
}
|
||||
|
||||
fn eval_moz_non_native_content_theme(context: &Context) -> bool {
|
||||
unsafe { bindings::Gecko_MediaFeatures_ShouldAvoidNativeTheme(context.device().document()) }
|
||||
fn eval_moz_non_native_content_theme(
|
||||
device: &Device,
|
||||
query_value: Option<bool>,
|
||||
_: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
let non_native_theme =
|
||||
unsafe { bindings::Gecko_MediaFeatures_ShouldAvoidNativeTheme(device.document()) };
|
||||
query_value.map_or(non_native_theme, |v| v == non_native_theme)
|
||||
}
|
||||
|
||||
fn eval_moz_is_resource_document(context: &Context) -> bool {
|
||||
unsafe { bindings::Gecko_MediaFeatures_IsResourceDocument(context.device().document()) }
|
||||
fn eval_moz_is_resource_document(
|
||||
device: &Device,
|
||||
query_value: Option<bool>,
|
||||
_: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
let is_resource_doc =
|
||||
unsafe { bindings::Gecko_MediaFeatures_IsResourceDocument(device.document()) };
|
||||
query_value.map_or(is_resource_doc, |v| v == is_resource_doc)
|
||||
}
|
||||
|
||||
/// Allows front-end CSS to discern platform via media queries.
|
||||
|
@ -487,7 +572,7 @@ pub enum Platform {
|
|||
WindowsWin10,
|
||||
}
|
||||
|
||||
fn eval_moz_platform(_: &Context, query_value: Option<Platform>) -> bool {
|
||||
fn eval_moz_platform(_: &Device, query_value: Option<Platform>) -> bool {
|
||||
let query_value = match query_value {
|
||||
Some(v) => v,
|
||||
None => return false,
|
||||
|
@ -496,22 +581,32 @@ fn eval_moz_platform(_: &Context, query_value: Option<Platform>) -> bool {
|
|||
unsafe { bindings::Gecko_MediaFeatures_MatchesPlatform(query_value) }
|
||||
}
|
||||
|
||||
fn eval_moz_windows_non_native_menus(context: &Context) -> bool {
|
||||
fn eval_moz_windows_non_native_menus(
|
||||
device: &Device,
|
||||
query_value: Option<bool>,
|
||||
_: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
let use_non_native_menus = match static_prefs::pref!("browser.display.windows.non_native_menus")
|
||||
{
|
||||
0 => false,
|
||||
1 => true,
|
||||
_ => {
|
||||
eval_moz_platform(context, Some(Platform::WindowsWin10)) &&
|
||||
eval_moz_platform(device, Some(Platform::WindowsWin10)) &&
|
||||
get_lnf_int_as_bool(bindings::LookAndFeel_IntID::WindowsDefaultTheme as i32)
|
||||
},
|
||||
};
|
||||
|
||||
use_non_native_menus
|
||||
query_value.map_or(use_non_native_menus, |v| v == use_non_native_menus)
|
||||
}
|
||||
|
||||
fn eval_moz_overlay_scrollbars(context: &Context) -> bool {
|
||||
unsafe { bindings::Gecko_MediaFeatures_UseOverlayScrollbars(context.device().document()) }
|
||||
fn eval_moz_overlay_scrollbars(
|
||||
device: &Device,
|
||||
query_value: Option<bool>,
|
||||
_: Option<RangeOrOperator>,
|
||||
) -> bool {
|
||||
let use_overlay =
|
||||
unsafe { bindings::Gecko_MediaFeatures_UseOverlayScrollbars(device.document()) };
|
||||
query_value.map_or(use_overlay, |v| v == use_overlay)
|
||||
}
|
||||
|
||||
fn get_lnf_int(int_id: i32) -> i32 {
|
||||
|
@ -540,15 +635,16 @@ fn get_scrollbar_end_forward(int_id: i32) -> bool {
|
|||
|
||||
macro_rules! lnf_int_feature {
|
||||
($feature_name:expr, $int_id:ident, $get_value:ident) => {{
|
||||
fn __eval(_: &Context) -> bool {
|
||||
$get_value(bindings::LookAndFeel_IntID::$int_id as i32)
|
||||
fn __eval(_: &Device, query_value: Option<bool>, _: Option<RangeOrOperator>) -> bool {
|
||||
let value = $get_value(bindings::LookAndFeel_IntID::$int_id as i32);
|
||||
query_value.map_or(value, |v| v == value)
|
||||
}
|
||||
|
||||
feature!(
|
||||
$feature_name,
|
||||
AllowsRanges::No,
|
||||
Evaluator::BoolInteger(__eval),
|
||||
FeatureFlags::CHROME_AND_UA_ONLY,
|
||||
ParsingRequirements::CHROME_AND_UA_ONLY,
|
||||
)
|
||||
}};
|
||||
($feature_name:expr, $int_id:ident) => {{
|
||||
|
@ -565,18 +661,18 @@ macro_rules! lnf_int_feature {
|
|||
/// pref, with `rust: true`. The feature name needs to be defined in
|
||||
/// `StaticAtoms.py` just like the others. In order to support dynamic changes,
|
||||
/// you also need to add them to kMediaQueryPrefs in nsXPLookAndFeel.cpp
|
||||
#[allow(unused)]
|
||||
macro_rules! bool_pref_feature {
|
||||
($feature_name:expr, $pref:tt) => {{
|
||||
fn __eval(_: &Context) -> bool {
|
||||
static_prefs::pref!($pref)
|
||||
fn __eval(_: &Device, query_value: Option<bool>, _: Option<RangeOrOperator>) -> bool {
|
||||
let value = static_prefs::pref!($pref);
|
||||
query_value.map_or(value, |v| v == value)
|
||||
}
|
||||
|
||||
feature!(
|
||||
$feature_name,
|
||||
AllowsRanges::No,
|
||||
Evaluator::BoolInteger(__eval),
|
||||
FeatureFlags::CHROME_AND_UA_ONLY,
|
||||
ParsingRequirements::CHROME_AND_UA_ONLY,
|
||||
)
|
||||
}};
|
||||
}
|
||||
|
@ -586,54 +682,54 @@ macro_rules! bool_pref_feature {
|
|||
/// to support new types in these entries and (2) ensuring that either
|
||||
/// nsPresContext::MediaFeatureValuesChanged is called when the value that
|
||||
/// would be returned by the evaluator function could change.
|
||||
pub static MEDIA_FEATURES: [QueryFeatureDescription; 59] = [
|
||||
pub static MEDIA_FEATURES: [MediaFeatureDescription; 58] = [
|
||||
feature!(
|
||||
atom!("width"),
|
||||
AllowsRanges::Yes,
|
||||
Evaluator::Length(eval_width),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("height"),
|
||||
AllowsRanges::Yes,
|
||||
Evaluator::Length(eval_height),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("aspect-ratio"),
|
||||
AllowsRanges::Yes,
|
||||
Evaluator::NumberRatio(eval_aspect_ratio),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("orientation"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_orientation, Orientation),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("device-width"),
|
||||
AllowsRanges::Yes,
|
||||
Evaluator::Length(eval_device_width),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("device-height"),
|
||||
AllowsRanges::Yes,
|
||||
Evaluator::Length(eval_device_height),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("device-aspect-ratio"),
|
||||
AllowsRanges::Yes,
|
||||
Evaluator::NumberRatio(eval_device_aspect_ratio),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("-moz-device-orientation"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_device_orientation, Orientation),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
// Webkit extensions that we support for de-facto web compatibility.
|
||||
// -webkit-{min|max}-device-pixel-ratio (controlled with its own pref):
|
||||
|
@ -641,68 +737,68 @@ pub static MEDIA_FEATURES: [QueryFeatureDescription; 59] = [
|
|||
atom!("device-pixel-ratio"),
|
||||
AllowsRanges::Yes,
|
||||
Evaluator::Float(eval_device_pixel_ratio),
|
||||
FeatureFlags::WEBKIT_PREFIX,
|
||||
ParsingRequirements::WEBKIT_PREFIX,
|
||||
),
|
||||
// -webkit-transform-3d.
|
||||
feature!(
|
||||
atom!("transform-3d"),
|
||||
AllowsRanges::No,
|
||||
Evaluator::BoolInteger(eval_transform_3d),
|
||||
FeatureFlags::WEBKIT_PREFIX,
|
||||
ParsingRequirements::WEBKIT_PREFIX,
|
||||
),
|
||||
feature!(
|
||||
atom!("-moz-device-pixel-ratio"),
|
||||
AllowsRanges::Yes,
|
||||
Evaluator::Float(eval_device_pixel_ratio),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("resolution"),
|
||||
AllowsRanges::Yes,
|
||||
Evaluator::Resolution(eval_resolution),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("display-mode"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_display_mode, DisplayMode),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("grid"),
|
||||
AllowsRanges::No,
|
||||
Evaluator::BoolInteger(eval_grid),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("scan"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_scan, Scan),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("color"),
|
||||
AllowsRanges::Yes,
|
||||
Evaluator::Integer(eval_color),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("color-index"),
|
||||
AllowsRanges::Yes,
|
||||
Evaluator::Integer(eval_color_index),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("monochrome"),
|
||||
AllowsRanges::Yes,
|
||||
Evaluator::Integer(eval_monochrome),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("prefers-reduced-motion"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_prefers_reduced_motion, PrefersReducedMotion),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("prefers-contrast"),
|
||||
|
@ -713,49 +809,31 @@ pub static MEDIA_FEATURES: [QueryFeatureDescription; 59] = [
|
|||
// layout.css.prefers-contrast.enabled preference. See
|
||||
// disabed_by_pref in media_feature_expression.rs for how that
|
||||
// is done.
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("forced-colors"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_forced_colors, ForcedColors),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("overflow-block"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_overflow_block, OverflowBlock),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("overflow-inline"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_overflow_inline, OverflowInline),
|
||||
FeatureFlags::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("update"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_update, Update),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("prefers-color-scheme"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_prefers_color_scheme, PrefersColorScheme),
|
||||
FeatureFlags::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("dynamic-range"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_dynamic_range, DynamicRange),
|
||||
FeatureFlags::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("video-dynamic-range"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_video_dynamic_range, DynamicRange),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
// Evaluates to the preferred color scheme for content. Only useful in
|
||||
// chrome context, where the chrome color-scheme and the content
|
||||
|
@ -764,31 +842,31 @@ pub static MEDIA_FEATURES: [QueryFeatureDescription; 59] = [
|
|||
atom!("-moz-content-prefers-color-scheme"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_content_prefers_color_scheme, PrefersColorScheme),
|
||||
FeatureFlags::CHROME_AND_UA_ONLY,
|
||||
ParsingRequirements::CHROME_AND_UA_ONLY,
|
||||
),
|
||||
feature!(
|
||||
atom!("pointer"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_pointer, Pointer),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("any-pointer"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_any_pointer, Pointer),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("hover"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_hover, Hover),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("any-hover"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_any_hover, Hover),
|
||||
FeatureFlags::empty(),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
// Internal -moz-is-glyph media feature: applies only inside SVG glyphs.
|
||||
// Internal because it is really only useful in the user agent anyway
|
||||
|
@ -797,43 +875,43 @@ pub static MEDIA_FEATURES: [QueryFeatureDescription; 59] = [
|
|||
atom!("-moz-is-glyph"),
|
||||
AllowsRanges::No,
|
||||
Evaluator::BoolInteger(eval_moz_is_glyph),
|
||||
FeatureFlags::CHROME_AND_UA_ONLY,
|
||||
ParsingRequirements::CHROME_AND_UA_ONLY,
|
||||
),
|
||||
feature!(
|
||||
atom!("-moz-is-resource-document"),
|
||||
AllowsRanges::No,
|
||||
Evaluator::BoolInteger(eval_moz_is_resource_document),
|
||||
FeatureFlags::CHROME_AND_UA_ONLY,
|
||||
ParsingRequirements::CHROME_AND_UA_ONLY,
|
||||
),
|
||||
feature!(
|
||||
atom!("-moz-platform"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_moz_platform, Platform),
|
||||
FeatureFlags::CHROME_AND_UA_ONLY,
|
||||
ParsingRequirements::CHROME_AND_UA_ONLY,
|
||||
),
|
||||
feature!(
|
||||
atom!("-moz-print-preview"),
|
||||
AllowsRanges::No,
|
||||
Evaluator::BoolInteger(eval_moz_print_preview),
|
||||
FeatureFlags::CHROME_AND_UA_ONLY,
|
||||
ParsingRequirements::CHROME_AND_UA_ONLY,
|
||||
),
|
||||
feature!(
|
||||
atom!("-moz-non-native-content-theme"),
|
||||
AllowsRanges::No,
|
||||
Evaluator::BoolInteger(eval_moz_non_native_content_theme),
|
||||
FeatureFlags::CHROME_AND_UA_ONLY,
|
||||
ParsingRequirements::CHROME_AND_UA_ONLY,
|
||||
),
|
||||
feature!(
|
||||
atom!("-moz-windows-non-native-menus"),
|
||||
AllowsRanges::No,
|
||||
Evaluator::BoolInteger(eval_moz_windows_non_native_menus),
|
||||
FeatureFlags::CHROME_AND_UA_ONLY,
|
||||
ParsingRequirements::CHROME_AND_UA_ONLY,
|
||||
),
|
||||
feature!(
|
||||
atom!("-moz-overlay-scrollbars"),
|
||||
AllowsRanges::No,
|
||||
Evaluator::BoolInteger(eval_moz_overlay_scrollbars),
|
||||
FeatureFlags::CHROME_AND_UA_ONLY,
|
||||
ParsingRequirements::CHROME_AND_UA_ONLY,
|
||||
),
|
||||
lnf_int_feature!(
|
||||
atom!("-moz-scrollbar-start-backward"),
|
||||
|
@ -855,6 +933,10 @@ pub static MEDIA_FEATURES: [QueryFeatureDescription; 59] = [
|
|||
ScrollArrowStyle,
|
||||
get_scrollbar_end_forward
|
||||
),
|
||||
lnf_int_feature!(
|
||||
atom!("-moz-scrollbar-thumb-proportional"),
|
||||
ScrollSliderStyle
|
||||
),
|
||||
lnf_int_feature!(atom!("-moz-menubar-drag"), MenuBarDrag),
|
||||
lnf_int_feature!(atom!("-moz-windows-default-theme"), WindowsDefaultTheme),
|
||||
lnf_int_feature!(atom!("-moz-mac-graphite-theme"), MacGraphiteTheme),
|
||||
|
@ -877,4 +959,8 @@ pub static MEDIA_FEATURES: [QueryFeatureDescription; 59] = [
|
|||
GTKCSDReversedPlacement
|
||||
),
|
||||
lnf_int_feature!(atom!("-moz-system-dark-theme"), SystemUsesDarkTheme),
|
||||
bool_pref_feature!(
|
||||
atom!("-moz-proton-places-tooltip"),
|
||||
"browser.proton.places-tooltip.enabled"
|
||||
),
|
||||
];
|
||||
|
|
|
@ -17,7 +17,6 @@ use crate::values::computed::font::GenericFontFamily;
|
|||
use crate::values::computed::{ColorScheme, Length};
|
||||
use crate::values::specified::color::SystemColor;
|
||||
use crate::values::specified::font::FONT_MEDIUM_PX;
|
||||
use crate::values::specified::ViewportVariant;
|
||||
use crate::values::{CustomIdent, KeyframesName};
|
||||
use app_units::{Au, AU_PER_PX};
|
||||
use cssparser::RGBA;
|
||||
|
@ -59,9 +58,6 @@ pub struct Device {
|
|||
/// Whether any styles computed in the document relied on the viewport size
|
||||
/// by using vw/vh/vmin/vmax units.
|
||||
used_viewport_size: AtomicBool,
|
||||
/// Whether any styles computed in the document relied on the viewport size
|
||||
/// by using dvw/dvh/dvmin/dvmax units.
|
||||
used_dynamic_viewport_size: AtomicBool,
|
||||
/// The CssEnvironment object responsible of getting CSS environment
|
||||
/// variables.
|
||||
environment: CssEnvironment,
|
||||
|
@ -104,7 +100,6 @@ impl Device {
|
|||
used_root_font_size: AtomicBool::new(false),
|
||||
used_font_metrics: AtomicBool::new(false),
|
||||
used_viewport_size: AtomicBool::new(false),
|
||||
used_dynamic_viewport_size: AtomicBool::new(false),
|
||||
environment: CssEnvironment,
|
||||
}
|
||||
}
|
||||
|
@ -272,8 +267,6 @@ impl Device {
|
|||
self.used_root_font_size.store(false, Ordering::Relaxed);
|
||||
self.used_font_metrics.store(false, Ordering::Relaxed);
|
||||
self.used_viewport_size.store(false, Ordering::Relaxed);
|
||||
self.used_dynamic_viewport_size
|
||||
.store(false, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// Returns whether we ever looked up the root font size of the Device.
|
||||
|
@ -344,10 +337,7 @@ impl Device {
|
|||
|
||||
/// Returns the current viewport size in app units, recording that it's been
|
||||
/// used for viewport unit resolution.
|
||||
pub fn au_viewport_size_for_viewport_unit_resolution(
|
||||
&self,
|
||||
variant: ViewportVariant,
|
||||
) -> Size2D<Au> {
|
||||
pub fn au_viewport_size_for_viewport_unit_resolution(&self) -> Size2D<Au> {
|
||||
self.used_viewport_size.store(true, Ordering::Relaxed);
|
||||
let pc = match self.pres_context() {
|
||||
Some(pc) => pc,
|
||||
|
@ -358,42 +348,8 @@ impl Device {
|
|||
return self.page_size_minus_default_margin(pc);
|
||||
}
|
||||
|
||||
match variant {
|
||||
ViewportVariant::UADefault => {
|
||||
let size = &pc.mSizeForViewportUnits;
|
||||
Size2D::new(Au(size.width), Au(size.height))
|
||||
},
|
||||
ViewportVariant::Small => {
|
||||
let size = &pc.mVisibleArea;
|
||||
Size2D::new(Au(size.width), Au(size.height))
|
||||
},
|
||||
ViewportVariant::Large => {
|
||||
let size = &pc.mVisibleArea;
|
||||
// Looks like IntCoordTyped is treated as if it's u32 in Rust.
|
||||
debug_assert!(
|
||||
/* pc.mDynamicToolbarMaxHeight >=0 && */
|
||||
pc.mDynamicToolbarMaxHeight < i32::MAX as u32
|
||||
);
|
||||
Size2D::new(
|
||||
Au(size.width),
|
||||
Au(size.height
|
||||
+ pc.mDynamicToolbarMaxHeight as i32 * pc.mCurAppUnitsPerDevPixel),
|
||||
)
|
||||
},
|
||||
ViewportVariant::Dynamic => {
|
||||
self.used_dynamic_viewport_size.store(true, Ordering::Relaxed);
|
||||
let size = &pc.mVisibleArea;
|
||||
// Looks like IntCoordTyped is treated as if it's u32 in Rust.
|
||||
debug_assert!(
|
||||
/* pc.mDynamicToolbarHeight >=0 && */
|
||||
pc.mDynamicToolbarHeight < i32::MAX as u32
|
||||
);
|
||||
Size2D::new(
|
||||
Au(size.width),
|
||||
Au(size.height + pc.mDynamicToolbarHeight as i32 * pc.mCurAppUnitsPerDevPixel),
|
||||
)
|
||||
},
|
||||
}
|
||||
let size = &pc.mSizeForViewportUnits;
|
||||
Size2D::new(Au(size.width), Au(size.height))
|
||||
}
|
||||
|
||||
/// Returns whether we ever looked up the viewport size of the Device.
|
||||
|
@ -401,21 +357,11 @@ impl Device {
|
|||
self.used_viewport_size.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Returns whether we ever looked up the dynamic viewport size of the Device.
|
||||
pub fn used_dynamic_viewport_size(&self) -> bool {
|
||||
self.used_dynamic_viewport_size.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Returns whether font metrics have been queried.
|
||||
pub fn used_font_metrics(&self) -> bool {
|
||||
self.used_font_metrics.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Returns whether visited styles are enabled.
|
||||
pub fn visited_styles_enabled(&self) -> bool {
|
||||
unsafe { bindings::Gecko_VisitedStylesEnabled(self.document()) }
|
||||
}
|
||||
|
||||
/// Returns the device pixel ratio.
|
||||
pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
|
||||
let pc = match self.pres_context() {
|
||||
|
|
|
@ -54,7 +54,7 @@ macro_rules! apply_non_ts_list {
|
|||
("-moz-styleeditor-transitioning", MozStyleeditorTransitioning, IN_STYLEEDITOR_TRANSITIONING_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
|
||||
("fullscreen", Fullscreen, IN_FULLSCREEN_STATE, _),
|
||||
("-moz-modal-dialog", MozModalDialog, IN_MODAL_DIALOG_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
|
||||
("-moz-topmost-modal", MozTopmostModal, IN_TOPMOST_MODAL_TOP_LAYER_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
|
||||
("-moz-topmost-modal-dialog", MozTopmostModalDialog, IN_TOPMOST_MODAL_DIALOG_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
|
||||
("-moz-broken", MozBroken, IN_BROKEN_STATE, _),
|
||||
("-moz-loading", MozLoading, IN_LOADING_STATE, _),
|
||||
("-moz-has-dir-attr", MozHasDirAttr, IN_HAS_DIR_ATTR_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
|
||||
|
@ -92,6 +92,8 @@ macro_rules! apply_non_ts_list {
|
|||
("-moz-is-html", MozIsHTML, _, _),
|
||||
("-moz-placeholder", MozPlaceholder, _, _),
|
||||
("-moz-lwtheme", MozLWTheme, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME),
|
||||
("-moz-lwtheme-brighttext", MozLWThemeBrightText, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME),
|
||||
("-moz-lwtheme-darktext", MozLWThemeDarkText, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME),
|
||||
("-moz-window-inactive", MozWindowInactive, _, _),
|
||||
]
|
||||
}
|
||||
|
|
|
@ -139,6 +139,15 @@ impl NonTSPseudoClass {
|
|||
/// Returns whether the pseudo-class is enabled in content sheets.
|
||||
#[inline]
|
||||
fn is_enabled_in_content(&self) -> bool {
|
||||
if matches!(
|
||||
*self,
|
||||
Self::MozLWTheme | Self::MozLWThemeBrightText | Self::MozLWThemeDarkText
|
||||
) {
|
||||
return static_prefs::pref!("layout.css.moz-lwtheme.content.enabled");
|
||||
}
|
||||
if let NonTSPseudoClass::MozLocaleDir(..) = *self {
|
||||
return static_prefs::pref!("layout.css.moz-locale-dir.content.enabled");
|
||||
}
|
||||
!self.has_any_flag(NonTSPseudoClassFlag::PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME)
|
||||
}
|
||||
|
||||
|
@ -175,6 +184,8 @@ impl NonTSPseudoClass {
|
|||
},
|
||||
NonTSPseudoClass::MozWindowInactive => DocumentState::WINDOW_INACTIVE,
|
||||
NonTSPseudoClass::MozLWTheme => DocumentState::LWTHEME,
|
||||
NonTSPseudoClass::MozLWThemeBrightText => DocumentState::LWTHEME_BRIGHTTEXT,
|
||||
NonTSPseudoClass::MozLWThemeDarkText => DocumentState::LWTHEME_DARKTEXT,
|
||||
_ => DocumentState::empty(),
|
||||
}
|
||||
}
|
||||
|
@ -197,13 +208,15 @@ impl NonTSPseudoClass {
|
|||
NonTSPseudoClass::MozNativeAnonymous |
|
||||
// :-moz-placeholder is parsed but never matches.
|
||||
NonTSPseudoClass::MozPlaceholder |
|
||||
// :-moz-lwtheme, :-moz-locale-dir and
|
||||
// :-moz-window-inactive depend only on the state of the
|
||||
// document, which is invariant across all the elements
|
||||
// involved in a given style cache.
|
||||
NonTSPseudoClass::MozLWTheme |
|
||||
// :-moz-locale-dir and :-moz-window-inactive depend only on
|
||||
// the state of the document, which is invariant across all
|
||||
// the elements involved in a given style cache.
|
||||
NonTSPseudoClass::MozLocaleDir(_) |
|
||||
NonTSPseudoClass::MozWindowInactive
|
||||
NonTSPseudoClass::MozWindowInactive |
|
||||
// Similar for the document themes.
|
||||
NonTSPseudoClass::MozLWTheme |
|
||||
NonTSPseudoClass::MozLWThemeBrightText |
|
||||
NonTSPseudoClass::MozLWThemeDarkText
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -445,9 +458,3 @@ unsafe impl HasFFI for SelectorList<SelectorImpl> {
|
|||
}
|
||||
unsafe impl HasSimpleFFI for SelectorList<SelectorImpl> {}
|
||||
unsafe impl HasBoxFFI for SelectorList<SelectorImpl> {}
|
||||
|
||||
// Selector and component sizes are important for matching performance.
|
||||
size_of_test!(selectors::parser::Selector<SelectorImpl>, 8);
|
||||
size_of_test!(selectors::parser::Component<SelectorImpl>, 24);
|
||||
size_of_test!(PseudoElement, 16);
|
||||
size_of_test!(NonTSPseudoClass, 16);
|
||||
|
|
|
@ -44,14 +44,14 @@ unsafe fn get_class_or_part_from_attr(attr: &structs::nsAttrValue) -> Class {
|
|||
structs::nsAttrValue_ValueType_eAtomArray
|
||||
);
|
||||
// NOTE: Bindgen doesn't deal with AutoTArray, so cast it below.
|
||||
let attr_array: *mut _ = *(*container)
|
||||
let array: *mut u8 = *(*container)
|
||||
.__bindgen_anon_1
|
||||
.mValue
|
||||
.as_ref()
|
||||
.__bindgen_anon_1
|
||||
.mAtomArray
|
||||
.as_ref();
|
||||
let array = (*attr_array).mArray.as_ptr() as *const structs::nsTArray<structs::RefPtr<nsAtom>>;
|
||||
let array = array as *const structs::nsTArray<structs::RefPtr<nsAtom>>;
|
||||
return Class::More(&**array);
|
||||
}
|
||||
debug_assert_eq!(base_type, structs::nsAttrValue_ValueBaseType_eStringBase);
|
||||
|
|
|
@ -66,8 +66,6 @@ use crate::stylist::CascadeData;
|
|||
use crate::values::{AtomIdent, AtomString};
|
||||
use crate::CaseSensitivityExt;
|
||||
use crate::LocalName;
|
||||
use app_units::Au;
|
||||
use euclid::default::Size2D;
|
||||
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
||||
use fxhash::FxHashMap;
|
||||
use selectors::attr::{AttrSelectorOperation, AttrSelectorOperator};
|
||||
|
@ -323,11 +321,6 @@ impl<'ln> GeckoNode<'ln> {
|
|||
self.flags() & (NODE_IS_IN_SHADOW_TREE as u32) != 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_connected(&self) -> bool {
|
||||
self.get_bool_flag(nsINode_BooleanFlag::IsConnected)
|
||||
}
|
||||
|
||||
/// WARNING: This logic is duplicated in Gecko's FlattenedTreeParentIsParent.
|
||||
/// Make sure to mirror any modifications in both places.
|
||||
#[inline]
|
||||
|
@ -1037,21 +1030,6 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn primary_box_size(&self) -> Size2D<Au> {
|
||||
if !self.as_node().is_connected() {
|
||||
return Size2D::zero();
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let frame = self.0._base._base._base.__bindgen_anon_1.mPrimaryFrame.as_ref();
|
||||
if frame.is_null() {
|
||||
return Size2D::zero();
|
||||
}
|
||||
Size2D::new(Au((**frame).mRect.width), Au((**frame).mRect.height))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the list of slotted nodes of this node.
|
||||
#[inline]
|
||||
fn slotted_nodes(&self) -> &[Self::ConcreteNode] {
|
||||
|
@ -1415,6 +1393,16 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
self.is_root_of_native_anonymous_subtree()
|
||||
}
|
||||
|
||||
unsafe fn set_selector_flags(&self, flags: ElementSelectorFlags) {
|
||||
debug_assert!(!flags.is_empty());
|
||||
self.set_flags(selector_flags_to_node_flags(flags));
|
||||
}
|
||||
|
||||
fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool {
|
||||
let node_flags = selector_flags_to_node_flags(flags);
|
||||
(self.flags() & node_flags) == node_flags
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn may_have_animations(&self) -> bool {
|
||||
if let Some(pseudo) = self.implemented_pseudo_element() {
|
||||
|
@ -1513,7 +1501,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
) -> bool {
|
||||
use crate::properties::LonghandIdSet;
|
||||
|
||||
let after_change_ui_style = after_change_style.get_ui();
|
||||
let after_change_box_style = after_change_style.get_box();
|
||||
let existing_transitions = self.css_transitions_info();
|
||||
let mut transitions_to_keep = LonghandIdSet::new();
|
||||
for transition_property in after_change_style.transition_properties() {
|
||||
|
@ -1523,7 +1511,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
transitions_to_keep.insert(physical_longhand);
|
||||
if self.needs_transitions_update_per_property(
|
||||
physical_longhand,
|
||||
after_change_ui_style.transition_combined_duration_at(transition_property.index),
|
||||
after_change_box_style.transition_combined_duration_at(transition_property.index),
|
||||
before_change_style,
|
||||
after_change_style,
|
||||
&existing_transitions,
|
||||
|
@ -1605,9 +1593,23 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
use crate::properties::longhands::_x_lang::SpecifiedValue as SpecifiedLang;
|
||||
use crate::properties::longhands::_x_text_zoom::SpecifiedValue as SpecifiedZoom;
|
||||
use crate::properties::longhands::color::SpecifiedValue as SpecifiedColor;
|
||||
use crate::properties::longhands::text_align::SpecifiedValue as SpecifiedTextAlign;
|
||||
use crate::stylesheets::layer_rule::LayerOrder;
|
||||
use crate::values::specified::color::Color;
|
||||
lazy_static! {
|
||||
static ref TH_RULE: ApplicableDeclarationBlock = {
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let pdb = PropertyDeclarationBlock::with_one(
|
||||
PropertyDeclaration::TextAlign(SpecifiedTextAlign::MozCenterOrInherit),
|
||||
Importance::Normal,
|
||||
);
|
||||
let arc = Arc::new_leaked(global_style_data.shared_lock.wrap(pdb));
|
||||
ApplicableDeclarationBlock::from_declarations(
|
||||
arc,
|
||||
ServoCascadeLevel::PresHints,
|
||||
LayerOrder::root(),
|
||||
)
|
||||
};
|
||||
static ref TABLE_COLOR_RULE: ApplicableDeclarationBlock = {
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let pdb = PropertyDeclarationBlock::with_one(
|
||||
|
@ -1652,7 +1654,9 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
let ns = self.namespace_id();
|
||||
// <th> elements get a default MozCenterOrInherit which may get overridden
|
||||
if ns == structs::kNameSpaceID_XHTML as i32 {
|
||||
if self.local_name().as_ptr() == atom!("table").as_ptr() &&
|
||||
if self.local_name().as_ptr() == atom!("th").as_ptr() {
|
||||
hints.push(TH_RULE.clone());
|
||||
} else if self.local_name().as_ptr() == atom!("table").as_ptr() &&
|
||||
self.as_node().owner_doc().quirks_mode() == QuirksMode::Quirks
|
||||
{
|
||||
hints.push(TABLE_COLOR_RULE.clone());
|
||||
|
@ -1844,11 +1848,6 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
None
|
||||
}
|
||||
|
||||
fn set_selector_flags(&self, flags: ElementSelectorFlags) {
|
||||
debug_assert!(!flags.is_empty());
|
||||
self.set_flags(selector_flags_to_node_flags(flags));
|
||||
}
|
||||
|
||||
fn attr_matches(
|
||||
&self,
|
||||
ns: &NamespaceConstraint<&Namespace>,
|
||||
|
@ -1961,11 +1960,15 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
self.local_name() == other.local_name() && self.namespace() == other.namespace()
|
||||
}
|
||||
|
||||
fn match_non_ts_pseudo_class(
|
||||
fn match_non_ts_pseudo_class<F>(
|
||||
&self,
|
||||
pseudo_class: &NonTSPseudoClass,
|
||||
context: &mut MatchingContext<Self::Impl>,
|
||||
) -> bool {
|
||||
flags_setter: &mut F,
|
||||
) -> bool
|
||||
where
|
||||
F: FnMut(&Self, ElementSelectorFlags),
|
||||
{
|
||||
use selectors::matching::*;
|
||||
match *pseudo_class {
|
||||
NonTSPseudoClass::Autofill |
|
||||
|
@ -2006,7 +2009,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
NonTSPseudoClass::MozDirAttrRTL |
|
||||
NonTSPseudoClass::MozDirAttrLikeAuto |
|
||||
NonTSPseudoClass::MozModalDialog |
|
||||
NonTSPseudoClass::MozTopmostModal |
|
||||
NonTSPseudoClass::MozTopmostModalDialog |
|
||||
NonTSPseudoClass::Active |
|
||||
NonTSPseudoClass::Hover |
|
||||
NonTSPseudoClass::MozAutofillPreview |
|
||||
|
@ -2021,9 +2024,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
self.is_link() && context.visited_handling().matches_visited()
|
||||
},
|
||||
NonTSPseudoClass::MozFirstNode => {
|
||||
if context.needs_selector_flags() {
|
||||
self.apply_selector_flags(ElementSelectorFlags::HAS_EDGE_CHILD_SELECTOR);
|
||||
}
|
||||
flags_setter(self, ElementSelectorFlags::HAS_EDGE_CHILD_SELECTOR);
|
||||
let mut elem = self.as_node();
|
||||
while let Some(prev) = elem.prev_sibling() {
|
||||
if prev.contains_non_whitespace_content() {
|
||||
|
@ -2034,9 +2035,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
true
|
||||
},
|
||||
NonTSPseudoClass::MozLastNode => {
|
||||
if context.needs_selector_flags() {
|
||||
self.apply_selector_flags(ElementSelectorFlags::HAS_EDGE_CHILD_SELECTOR);
|
||||
}
|
||||
flags_setter(self, ElementSelectorFlags::HAS_EDGE_CHILD_SELECTOR);
|
||||
let mut elem = self.as_node();
|
||||
while let Some(next) = elem.next_sibling() {
|
||||
if next.contains_non_whitespace_content() {
|
||||
|
@ -2047,9 +2046,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
true
|
||||
},
|
||||
NonTSPseudoClass::MozOnlyWhitespace => {
|
||||
if context.needs_selector_flags() {
|
||||
self.apply_selector_flags(ElementSelectorFlags::HAS_EMPTY_SELECTOR);
|
||||
}
|
||||
flags_setter(self, ElementSelectorFlags::HAS_EMPTY_SELECTOR);
|
||||
if self
|
||||
.as_node()
|
||||
.dom_children()
|
||||
|
@ -2071,6 +2068,8 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
NonTSPseudoClass::MozIsHTML => self.is_html_element_in_html_document(),
|
||||
|
||||
NonTSPseudoClass::MozLWTheme |
|
||||
NonTSPseudoClass::MozLWThemeBrightText |
|
||||
NonTSPseudoClass::MozLWThemeDarkText |
|
||||
NonTSPseudoClass::MozLocaleDir(..) |
|
||||
NonTSPseudoClass::MozWindowInactive => {
|
||||
let state_bit = pseudo_class.document_state_flag();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue