mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
style: Process all the MediumFeatureChanges at the same time.
This avoids resetting the computed values all the time, and paves the way to avoid using a StyleSet on XBL bindings / Shadow DOM, which we should really really do because it's super overkill. There are some XBL bits that are kind of hacky, in particular the mStylistDirty, but they'll go away soon, since I want to redo how we store styles in XBL. The alternative, which was returning an array of indices or something was even more hacky I think. Bug: 1435939 Reviewed-by: xidorn MozReview-Commit-ID: 6tEl5gebXVF
This commit is contained in:
parent
9324feb994
commit
0907c21600
2 changed files with 58 additions and 43 deletions
|
@ -1089,9 +1089,6 @@ impl Stylist {
|
||||||
///
|
///
|
||||||
/// Also, the device that arrives here may need to take the viewport rules
|
/// Also, the device that arrives here may need to take the viewport rules
|
||||||
/// into account.
|
/// into account.
|
||||||
///
|
|
||||||
/// For Gecko, this is called when XBL bindings are used by different
|
|
||||||
/// documents.
|
|
||||||
pub fn set_device(
|
pub fn set_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut device: Device,
|
mut device: Device,
|
||||||
|
@ -1119,14 +1116,22 @@ impl Stylist {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.device = device;
|
self.device = device;
|
||||||
self.media_features_change_changed_style(guards)
|
self.media_features_change_changed_style(guards, &self.device)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether, given a media feature change, any previously-applicable
|
/// Returns whether, given a media feature change, any previously-applicable
|
||||||
/// style has become non-applicable, or vice-versa for each origin.
|
/// style has become non-applicable, or vice-versa for each origin, using
|
||||||
|
/// `device`.
|
||||||
|
///
|
||||||
|
/// Passing `device` is needed because this is used for XBL in Gecko, which
|
||||||
|
/// can be stale in various ways, so we need to pass the device of the
|
||||||
|
/// document itself, which is what is kept up-to-date.
|
||||||
|
///
|
||||||
|
/// Arguably XBL should use something more lightweight than a Stylist.
|
||||||
pub fn media_features_change_changed_style(
|
pub fn media_features_change_changed_style(
|
||||||
&self,
|
&self,
|
||||||
guards: &StylesheetGuards,
|
guards: &StylesheetGuards,
|
||||||
|
device: &Device,
|
||||||
) -> OriginSet {
|
) -> OriginSet {
|
||||||
debug!("Stylist::media_features_change_changed_style");
|
debug!("Stylist::media_features_change_changed_style");
|
||||||
|
|
||||||
|
@ -1145,7 +1150,7 @@ impl Stylist {
|
||||||
let affected_changed = !origin_cascade_data.media_feature_affected_matches(
|
let affected_changed = !origin_cascade_data.media_feature_affected_matches(
|
||||||
stylesheet,
|
stylesheet,
|
||||||
guard,
|
guard,
|
||||||
&self.device,
|
device,
|
||||||
self.quirks_mode
|
self.quirks_mode
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ use style::gecko_bindings::sugar::ownership::{HasSimpleFFI, Strong};
|
||||||
use style::gecko_bindings::sugar::refptr::RefPtr;
|
use style::gecko_bindings::sugar::refptr::RefPtr;
|
||||||
use style::gecko_properties;
|
use style::gecko_properties;
|
||||||
use style::invalidation::element::restyle_hints;
|
use style::invalidation::element::restyle_hints;
|
||||||
use style::media_queries::{Device, MediaList, parse_media_query_list};
|
use style::media_queries::{MediaList, parse_media_query_list};
|
||||||
use style::parser::{Parse, ParserContext, self};
|
use style::parser::{Parse, ParserContext, self};
|
||||||
use style::properties::{ComputedValues, DeclarationSource, Importance};
|
use style::properties::{ComputedValues, DeclarationSource, Importance};
|
||||||
use style::properties::{LonghandId, LonghandIdSet, PropertyDeclaration, PropertyDeclarationBlock, PropertyId};
|
use style::properties::{LonghandId, LonghandIdSet, PropertyDeclaration, PropertyDeclarationBlock, PropertyId};
|
||||||
|
@ -1122,10 +1122,10 @@ pub extern "C" fn Servo_StyleSet_AppendStyleSheet(
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Servo_StyleSet_MediumFeaturesChanged(
|
pub unsafe extern "C" fn Servo_StyleSet_MediumFeaturesChanged(
|
||||||
raw_data: RawServoStyleSetBorrowed,
|
document_set: RawServoStyleSetBorrowed,
|
||||||
viewport_units_used: *mut bool,
|
non_document_sets: *const nsTArray<*mut structs::ServoStyleSet>,
|
||||||
may_affect_default_style: bool,
|
may_affect_default_style: bool,
|
||||||
) -> u8 {
|
) -> structs::MediumFeaturesChangedResult {
|
||||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
let guard = global_style_data.shared_lock.read();
|
let guard = global_style_data.shared_lock.read();
|
||||||
|
|
||||||
|
@ -1136,48 +1136,58 @@ pub unsafe extern "C" fn Servo_StyleSet_MediumFeaturesChanged(
|
||||||
//
|
//
|
||||||
// We need to ensure the default computed values are up to date though,
|
// We need to ensure the default computed values are up to date though,
|
||||||
// because those can influence the result of media query evaluation.
|
// because those can influence the result of media query evaluation.
|
||||||
//
|
let mut document_data =
|
||||||
// FIXME(emilio, bug 1369984): do the computation conditionally, to do it
|
PerDocumentStyleData::from_ffi(document_set).borrow_mut();
|
||||||
// less often.
|
|
||||||
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
|
||||||
|
|
||||||
*viewport_units_used = data.stylist.device().used_viewport_size();
|
|
||||||
if may_affect_default_style {
|
if may_affect_default_style {
|
||||||
// FIXME(emilio): It's a shame we do this too for XBL stuff, but we need
|
document_data.stylist.device_mut().reset_computed_values();
|
||||||
// to right now to evaluate relative units in media queries correctly.
|
|
||||||
//
|
|
||||||
// We should instead just pass the `Device` reference from the master
|
|
||||||
// stylist, but that looked kinda gross... Maybe it's not actually.
|
|
||||||
data.stylist.device_mut().reset_computed_values();
|
|
||||||
}
|
}
|
||||||
let guards = StylesheetGuards::same(&guard);
|
let guards = StylesheetGuards::same(&guard);
|
||||||
|
|
||||||
let origins_in_which_rules_changed =
|
let origins_in_which_rules_changed =
|
||||||
data.stylist.media_features_change_changed_style(&guards);
|
document_data.stylist.media_features_change_changed_style(
|
||||||
|
&guards,
|
||||||
|
document_data.stylist.device(),
|
||||||
|
);
|
||||||
|
|
||||||
// We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
|
let affects_document_rules = !origins_in_which_rules_changed.is_empty();
|
||||||
// work as return values with the Linux 32-bit ABI at the moment because
|
if affects_document_rules {
|
||||||
// they wrap the value in a struct, so for now just unwrap it.
|
document_data.stylist.force_stylesheet_origins_dirty(origins_in_which_rules_changed);
|
||||||
OriginFlags::from(origins_in_which_rules_changed).0
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
let mut affects_non_document_rules = false;
|
||||||
pub extern "C" fn Servo_StyleSet_SetDevice(
|
for non_document_style_set in &**non_document_sets {
|
||||||
raw_data: RawServoStyleSetBorrowed,
|
let non_document_data = &*(**non_document_style_set).mRawSet.mPtr;
|
||||||
pres_context: RawGeckoPresContextOwned
|
let non_document_data =
|
||||||
) -> u8 {
|
mem::transmute::<&structs::RawServoStyleSet, &bindings::RawServoStyleSet>(non_document_data);
|
||||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
let mut non_document_data =
|
||||||
let guard = global_style_data.shared_lock.read();
|
PerDocumentStyleData::from_ffi(non_document_data).borrow_mut();
|
||||||
|
|
||||||
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
let origins_changed =
|
||||||
let device = Device::new(pres_context);
|
non_document_data.stylist.media_features_change_changed_style(
|
||||||
let guards = StylesheetGuards::same(&guard);
|
&guards,
|
||||||
let origins_in_which_rules_changed =
|
document_data.stylist.device(),
|
||||||
data.stylist.set_device(device, &guards);
|
);
|
||||||
|
if !origins_changed.is_empty() {
|
||||||
|
affects_non_document_rules = true;
|
||||||
|
// XBL stylesets are rebuilt entirely, so we need to mark them
|
||||||
|
// dirty from here instead of going through the stylist
|
||||||
|
// force_origin_dirty stuff, which would be useless.
|
||||||
|
//
|
||||||
|
// FIXME(emilio, bug 1436059): This is super-hacky, make XBL /
|
||||||
|
// Shadow DOM not use a style set at all.
|
||||||
|
(**non_document_style_set).mStylistState = structs::StylistState_StyleSheetsDirty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
|
let uses_viewport_units =
|
||||||
// work as return values with the Linux 32-bit ABI at the moment because
|
document_data.stylist.device().used_viewport_size();
|
||||||
// they wrap the value in a struct, so for now just unwrap it.
|
|
||||||
OriginFlags::from(origins_in_which_rules_changed).0
|
structs::MediumFeaturesChangedResult {
|
||||||
|
mAffectsDocumentRules: affects_document_rules,
|
||||||
|
mAffectsNonDocumentRules: affects_non_document_rules,
|
||||||
|
mUsesViewportUnits: uses_viewport_units,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue