style: Ensure we generate a ReconstructFrame hint when -moz-binding changes on a display:none root.

This commit is contained in:
Cameron McCormack 2017-07-25 11:11:47 +08:00
parent bf16b146e8
commit e36b4340e1
3 changed files with 45 additions and 3 deletions

View file

@ -6,7 +6,7 @@
use gecko_bindings::bindings; use gecko_bindings::bindings;
use gecko_bindings::structs; use gecko_bindings::structs;
use gecko_bindings::structs::{nsChangeHint, nsStyleContext}; use gecko_bindings::structs::{nsChangeHint, nsStyleContext, nsStyleStructID};
use matching::{StyleChange, StyleDifference}; use matching::{StyleChange, StyleDifference};
use properties::ComputedValues; use properties::ComputedValues;
use servo_arc::Arc; use servo_arc::Arc;
@ -62,6 +62,34 @@ impl GeckoRestyleDamage {
StyleDifference::new(GeckoRestyleDamage(hint), change) StyleDifference::new(GeckoRestyleDamage(hint), change)
} }
/// Computes the `StyleDifference` between the two `ComputedValues` objects
/// for the case where the old and new style are both `display: none`.
///
/// In general we don't need to generate damage for such elements, but we
/// do need to generate a frame reconstruction for `-moz-binding` changes,
/// so that we can start loading the new binding.
pub fn compute_undisplayed_style_difference(
old_style: &ComputedValues,
new_style: &ComputedValues,
) -> StyleDifference {
let mut any_style_changed: bool = false;
// Just compute the Display struct's difference.
let display_struct_bit = 1 << (nsStyleStructID::eStyleStruct_Display as u32);
let hint = unsafe {
bindings::Gecko_CalcStyleDifference(old_style,
new_style,
display_struct_bit,
&mut any_style_changed)
};
// Only pay attention to a reconstruct change hint.
let damage = GeckoRestyleDamage(hint) & Self::reconstruct();
let change = if damage.is_empty() { StyleChange::Changed } else { StyleChange::Unchanged };
StyleDifference::new(damage, change)
}
/// Returns true if this restyle damage contains all the damage of |other|. /// Returns true if this restyle damage contains all the damage of |other|.
pub fn contains(self, other: Self) -> bool { pub fn contains(self, other: Self) -> bool {
self & other == other self & other == other

View file

@ -783,8 +783,11 @@ pub trait MatchMethods : TElement {
// This happens with display:none elements, and not-yet-existing // This happens with display:none elements, and not-yet-existing
// pseudo-elements. // pseudo-elements.
if new_style_is_display_none && old_style_is_display_none { if new_style_is_display_none && old_style_is_display_none {
// The style remains display:none. No need for damage. // The style remains display:none. The only case we need to care
return StyleDifference::new(RestyleDamage::empty(), StyleChange::Unchanged) // about is if -moz-binding changed, and to generate a reconstruct
// so that we can start the binding load. Otherwise, there is no
// need for damage.
return RestyleDamage::compute_undisplayed_style_difference(old_values, new_values);
} }
if pseudo.map_or(false, |p| p.is_before_or_after()) { if pseudo.map_or(false, |p| p.is_before_or_after()) {

View file

@ -69,6 +69,17 @@ impl ServoRestyleDamage {
StyleDifference::new(damage, change) StyleDifference::new(damage, change)
} }
/// Computes the `StyleDifference` between the two `ComputedValues` objects
/// for the case where the old and new style are both `display: none`.
///
/// For Servo we never need to generate any damage for such elements.
pub fn compute_undisplayed_style_difference(
_old_style: &ComputedValues,
_new_style: &ComputedValues,
) -> StyleDifference {
StyleDifference::new(Self::empty(), StyleChange::Unchanged)
}
/// Returns a bitmask that represents a flow that needs to be rebuilt and /// Returns a bitmask that represents a flow that needs to be rebuilt and
/// reflowed. /// reflowed.
/// ///