mirror of
https://github.com/servo/servo.git
synced 2025-07-13 18:33:40 +01:00
Propagate dirty bits after invalidation if needed.
This commit is contained in:
parent
c98b362e65
commit
22ace048cb
3 changed files with 73 additions and 20 deletions
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
use context::{SharedStyleContext, StackLimitChecker};
|
use context::{SharedStyleContext, StackLimitChecker};
|
||||||
use dom::TElement;
|
use dom::TElement;
|
||||||
|
use invalidation::element::invalidator::InvalidationResult;
|
||||||
use invalidation::element::restyle_hints::RestyleHint;
|
use invalidation::element::restyle_hints::RestyleHint;
|
||||||
use properties::ComputedValues;
|
use properties::ComputedValues;
|
||||||
use properties::longhands::display::computed_value as display;
|
use properties::longhands::display::computed_value as display;
|
||||||
|
@ -329,10 +330,10 @@ impl ElementData {
|
||||||
element: E,
|
element: E,
|
||||||
shared_context: &SharedStyleContext,
|
shared_context: &SharedStyleContext,
|
||||||
stack_limit_checker: Option<&StackLimitChecker>,
|
stack_limit_checker: Option<&StackLimitChecker>,
|
||||||
) {
|
) -> InvalidationResult {
|
||||||
// In animation-only restyle we shouldn't touch snapshot at all.
|
// In animation-only restyle we shouldn't touch snapshot at all.
|
||||||
if shared_context.traversal_flags.for_animation_only() {
|
if shared_context.traversal_flags.for_animation_only() {
|
||||||
return;
|
return InvalidationResult::empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
use invalidation::element::invalidator::TreeStyleInvalidator;
|
use invalidation::element::invalidator::TreeStyleInvalidator;
|
||||||
|
@ -345,17 +346,20 @@ impl ElementData {
|
||||||
element.handled_snapshot(),
|
element.handled_snapshot(),
|
||||||
element.implemented_pseudo_element());
|
element.implemented_pseudo_element());
|
||||||
|
|
||||||
if element.has_snapshot() && !element.handled_snapshot() {
|
if !element.has_snapshot() || element.handled_snapshot() {
|
||||||
let invalidator = TreeStyleInvalidator::new(
|
return InvalidationResult::empty();
|
||||||
element,
|
|
||||||
Some(self),
|
|
||||||
shared_context,
|
|
||||||
stack_limit_checker,
|
|
||||||
);
|
|
||||||
invalidator.invalidate();
|
|
||||||
unsafe { element.set_handled_snapshot() }
|
|
||||||
debug_assert!(element.handled_snapshot());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let invalidator = TreeStyleInvalidator::new(
|
||||||
|
element,
|
||||||
|
Some(self),
|
||||||
|
shared_context,
|
||||||
|
stack_limit_checker,
|
||||||
|
);
|
||||||
|
let result = invalidator.invalidate();
|
||||||
|
unsafe { element.set_handled_snapshot() }
|
||||||
|
debug_assert!(element.handled_snapshot());
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this element has styles.
|
/// Returns true if this element has styles.
|
||||||
|
|
|
@ -115,7 +115,7 @@ impl fmt::Debug for Invalidation {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The result of processing a single invalidation for a given element.
|
/// The result of processing a single invalidation for a given element.
|
||||||
struct InvalidationResult {
|
struct SingleInvalidationResult {
|
||||||
/// Whether the element itself was invalidated.
|
/// Whether the element itself was invalidated.
|
||||||
invalidated_self: bool,
|
invalidated_self: bool,
|
||||||
/// Whether the invalidation matched, either invalidating the element or
|
/// Whether the invalidation matched, either invalidating the element or
|
||||||
|
@ -123,6 +123,42 @@ struct InvalidationResult {
|
||||||
matched: bool,
|
matched: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The result of a whole invalidation process for a given element.
|
||||||
|
pub struct InvalidationResult {
|
||||||
|
/// Whether the element itself was invalidated.
|
||||||
|
invalidated_self: bool,
|
||||||
|
/// Whether the element's descendants were invalidated.
|
||||||
|
invalidated_descendants: bool,
|
||||||
|
/// Whether the element's siblings were invalidated.
|
||||||
|
invalidated_siblings: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InvalidationResult {
|
||||||
|
/// Create an emtpy result.
|
||||||
|
pub fn empty() -> Self {
|
||||||
|
Self {
|
||||||
|
invalidated_self: false,
|
||||||
|
invalidated_descendants: false,
|
||||||
|
invalidated_siblings: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether the invalidation has invalidate the element itself.
|
||||||
|
pub fn has_invalidated_self(&self) -> bool {
|
||||||
|
self.invalidated_self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether the invalidation has invalidate desendants.
|
||||||
|
pub fn has_invalidated_descendants(&self) -> bool {
|
||||||
|
self.invalidated_descendants
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether the invalidation has invalidate siblings.
|
||||||
|
pub fn has_invalidated_siblings(&self) -> bool {
|
||||||
|
self.invalidated_siblings
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
|
impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
|
||||||
where E: TElement,
|
where E: TElement,
|
||||||
{
|
{
|
||||||
|
@ -142,7 +178,7 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform the invalidation pass.
|
/// Perform the invalidation pass.
|
||||||
pub fn invalidate(mut self) {
|
pub fn invalidate(mut self) -> InvalidationResult {
|
||||||
debug!("StyleTreeInvalidator::invalidate({:?})", self.element);
|
debug!("StyleTreeInvalidator::invalidate({:?})", self.element);
|
||||||
debug_assert!(self.element.has_snapshot(), "Why bothering?");
|
debug_assert!(self.element.has_snapshot(), "Why bothering?");
|
||||||
debug_assert!(self.data.is_some(), "How exactly?");
|
debug_assert!(self.data.is_some(), "How exactly?");
|
||||||
|
@ -155,7 +191,7 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
|
||||||
let snapshot = wrapper.snapshot().expect("has_snapshot lied");
|
let snapshot = wrapper.snapshot().expect("has_snapshot lied");
|
||||||
|
|
||||||
if !snapshot.has_attrs() && state_changes.is_empty() {
|
if !snapshot.has_attrs() && state_changes.is_empty() {
|
||||||
return;
|
return InvalidationResult::empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are sensitive to visitedness and the visited state changed, we
|
// If we are sensitive to visitedness and the visited state changed, we
|
||||||
|
@ -252,8 +288,10 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
|
||||||
debug!("Collected invalidations (self: {}): ", invalidated_self);
|
debug!("Collected invalidations (self: {}): ", invalidated_self);
|
||||||
debug!(" > descendants: {:?}", descendant_invalidations);
|
debug!(" > descendants: {:?}", descendant_invalidations);
|
||||||
debug!(" > siblings: {:?}", sibling_invalidations);
|
debug!(" > siblings: {:?}", sibling_invalidations);
|
||||||
self.invalidate_descendants(&descendant_invalidations);
|
let invalidated_descendants = self.invalidate_descendants(&descendant_invalidations);
|
||||||
self.invalidate_siblings(&mut sibling_invalidations);
|
let invalidated_siblings = self.invalidate_siblings(&mut sibling_invalidations);
|
||||||
|
|
||||||
|
InvalidationResult { invalidated_self, invalidated_descendants, invalidated_siblings }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Go through later DOM siblings, invalidating style as needed using the
|
/// Go through later DOM siblings, invalidating style as needed using the
|
||||||
|
@ -585,7 +623,7 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
|
||||||
descendant_invalidations: &mut InvalidationVector,
|
descendant_invalidations: &mut InvalidationVector,
|
||||||
sibling_invalidations: &mut InvalidationVector,
|
sibling_invalidations: &mut InvalidationVector,
|
||||||
invalidation_kind: InvalidationKind,
|
invalidation_kind: InvalidationKind,
|
||||||
) -> InvalidationResult {
|
) -> SingleInvalidationResult {
|
||||||
debug!("TreeStyleInvalidator::process_invalidation({:?}, {:?}, {:?})",
|
debug!("TreeStyleInvalidator::process_invalidation({:?}, {:?}, {:?})",
|
||||||
self.element, invalidation, invalidation_kind);
|
self.element, invalidation, invalidation_kind);
|
||||||
|
|
||||||
|
@ -759,7 +797,7 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InvalidationResult { invalidated_self, matched, }
|
SingleInvalidationResult { invalidated_self, matched, }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3719,6 +3719,17 @@ pub extern "C" fn Servo_ProcessInvalidations(set: RawServoStyleSetBorrowed,
|
||||||
let mut data = data.as_mut().map(|d| &mut **d);
|
let mut data = data.as_mut().map(|d| &mut **d);
|
||||||
|
|
||||||
if let Some(ref mut data) = data {
|
if let Some(ref mut data) = data {
|
||||||
data.invalidate_style_if_needed(element, &shared_style_context, None);
|
let result = data.invalidate_style_if_needed(element, &shared_style_context, None);
|
||||||
|
if result.has_invalidated_siblings() {
|
||||||
|
let parent = element.traversal_parent().expect("How could we invalidate siblings without a common parent?");
|
||||||
|
unsafe {
|
||||||
|
parent.set_dirty_descendants();
|
||||||
|
bindings::Gecko_NoteDirtySubtreeForInvalidation(parent.0);
|
||||||
|
}
|
||||||
|
} else if result.has_invalidated_descendants() {
|
||||||
|
unsafe { bindings::Gecko_NoteDirtySubtreeForInvalidation(element.0) };
|
||||||
|
} else if result.has_invalidated_self() {
|
||||||
|
unsafe { bindings::Gecko_NoteDirtyElement(element.0) };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue