diff options
author | Emilio Cobos Álvarez <ecoal95@gmail.com> | 2016-08-30 16:37:37 -0700 |
---|---|---|
committer | Emilio Cobos Álvarez <ecoal95@gmail.com> | 2016-08-30 17:01:03 -0700 |
commit | fd9cd2f1036a580eba85dc65c11125a0bc85fb17 (patch) | |
tree | 2cf745b208f82a696e87006746a36881044a7853 /components/script/dom | |
parent | 1fcc447941b23fb54963f9590219387695e73cb6 (diff) | |
download | servo-fd9cd2f1036a580eba85dc65c11125a0bc85fb17.tar.gz servo-fd9cd2f1036a580eba85dc65c11125a0bc85fb17.zip |
layout: Keep track of whether we've deferred the painting of the document due to
a script query.
This will, rather unfortunately, mean that we might repaint two times if we've
deferred a paint, then get an out-of-band reflow. Still seemed better than not
suppressing paints at all.
Fixes #13131
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/document.rs | 23 | ||||
-rw-r--r-- | components/script/dom/window.rs | 6 |
2 files changed, 26 insertions, 3 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index cbd4b2ac253..58995645c27 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -221,6 +221,9 @@ pub struct Document { /// For each element that has had a state or attribute change since the last restyle, /// track the original condition of the element. modified_elements: DOMRefCell<HashMap<JS<Element>, ElementSnapshot>>, + /// This flag will be true if layout suppressed a reflow attempt that was + /// needed in order for the page to be painted. + needs_paint: Cell<bool>, /// http://w3c.github.io/touch-events/#dfn-active-touch-point active_touch_points: DOMRefCell<Vec<JS<Touch>>>, /// Navigation Timing properties: @@ -376,6 +379,10 @@ impl Document { } } + pub fn needs_paint(&self) -> bool { + self.needs_paint.get() + } + pub fn needs_reflow(&self) -> bool { // FIXME: This should check the dirty bit on the document, // not the document element. Needs some layout changes to make @@ -384,7 +391,8 @@ impl Document { Some(root) => { root.upcast::<Node>().is_dirty() || root.upcast::<Node>().has_dirty_descendants() || - !self.modified_elements.borrow().is_empty() + !self.modified_elements.borrow().is_empty() || + self.needs_paint() } None => false, } @@ -1602,6 +1610,8 @@ pub enum DocumentSource { pub trait LayoutDocumentHelpers { unsafe fn is_html_document_for_layout(&self) -> bool; unsafe fn drain_modified_elements(&self) -> Vec<(LayoutJS<Element>, ElementSnapshot)>; + unsafe fn needs_paint_from_layout(&self); + unsafe fn will_paint(&self); } #[allow(unsafe_code)] @@ -1618,6 +1628,16 @@ impl LayoutDocumentHelpers for LayoutJS<Document> { let result = elements.drain().map(|(k, v)| (k.to_layout(), v)).collect(); result } + + #[inline] + unsafe fn needs_paint_from_layout(&self) { + (*self.unsafe_get()).needs_paint.set(true) + } + + #[inline] + unsafe fn will_paint(&self) { + (*self.unsafe_get()).needs_paint.set(false) + } } /// https://url.spec.whatwg.org/#network-scheme @@ -1723,6 +1743,7 @@ impl Document { base_element: Default::default(), appropriate_template_contents_owner_document: Default::default(), modified_elements: DOMRefCell::new(HashMap::new()), + needs_paint: Cell::new(false), active_touch_points: DOMRefCell::new(Vec::new()), dom_loading: Cell::new(Default::default()), dom_interactive: Cell::new(Default::default()), diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index cd00390a305..b6bf6a35643 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -1200,9 +1200,11 @@ impl Window { if !for_display || self.Document().needs_reflow() { issued_reflow = self.force_reflow(goal, query_type, reason); - // If window_size is `None`, we don't reflow, so the document stays dirty. - // Otherwise, we shouldn't need a reflow immediately after a reflow. + // If window_size is `None`, we don't reflow, so the document stays + // dirty. Otherwise, we shouldn't need a reflow immediately after a + // reflow, except if we're waiting for a deferred paint. assert!(!self.Document().needs_reflow() || + (!for_display && self.Document().needs_paint()) || self.window_size.get().is_none() || self.suppress_reflow.get()); } else { |