aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2015-11-04 06:28:46 +0530
committerbors-servo <lbergstrom+bors@mozilla.com>2015-11-04 06:28:46 +0530
commit36c5dd4c8c543ed6767fe9dd367281b292d68dba (patch)
treea0c21cec5f47107562be0546c9b98a8bd6610ed3
parente91169c0e2cfe37b1a2d0feb3aab50b72c816ffc (diff)
parent6633773a589d87e81d2cf539983004d6ba957c68 (diff)
downloadservo-36c5dd4c8c543ed6767fe9dd367281b292d68dba.tar.gz
servo-36c5dd4c8c543ed6767fe9dd367281b292d68dba.zip
Auto merge of #8299 - pcwalton:dont-reflow-on-hover, r=mbrubeck
Fix several bugs causing the page to reflow on every mouse move event After all these changes are applied, Hacker News and GitHub only repaint and reflow nodes that actually have hover styles applied when the mouse moves over them. r? @mbrubeck cc @bholley <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8299) <!-- Reviewable:end -->
-rw-r--r--components/layout/block.rs33
-rw-r--r--components/layout/context.rs4
-rw-r--r--components/layout/css/matching.rs4
-rw-r--r--components/layout/flow.rs5
-rw-r--r--components/layout/layout_task.rs50
5 files changed, 56 insertions, 40 deletions
diff --git a/components/layout/block.rs b/components/layout/block.rs
index 399b3e5a9f4..51d09e6cf28 100644
--- a/components/layout/block.rs
+++ b/components/layout/block.rs
@@ -989,9 +989,10 @@ impl BlockFlow {
let mut block_size = cur_b - block_start_offset;
let is_root = self.is_root();
if is_root {
- let screen_size = LogicalSize::from_physical(self.fragment.style.writing_mode,
- layout_context.shared.screen_size);
- block_size = max(screen_size.block, block_size)
+ let viewport_size =
+ LogicalSize::from_physical(self.fragment.style.writing_mode,
+ layout_context.shared.viewport_size);
+ block_size = max(viewport_size.block, block_size)
}
if is_root || self.formatting_context_type() != FormattingContextType::None ||
@@ -1156,9 +1157,9 @@ impl BlockFlow {
pub fn explicit_block_containing_size(&self, layout_context: &LayoutContext) -> Option<Au> {
if self.is_root() || self.is_fixed() {
- let screen_size = LogicalSize::from_physical(self.fragment.style.writing_mode,
- layout_context.shared.screen_size);
- Some(screen_size.block)
+ let viewport_size = LogicalSize::from_physical(self.fragment.style.writing_mode,
+ layout_context.shared.viewport_size);
+ Some(viewport_size.block)
} else if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) &&
self.base.block_container_explicit_block_size.is_none() {
self.base.absolute_cb.explicit_block_containing_size(layout_context)
@@ -1223,7 +1224,7 @@ impl BlockFlow {
fn calculate_absolute_block_size_and_margins(&mut self, layout_context: &LayoutContext) {
let opaque_self = OpaqueFlow::from_flow(self);
let containing_block_block_size =
- self.containing_block_size(&layout_context.shared.screen_size, opaque_self).block;
+ self.containing_block_size(&layout_context.shared.viewport_size, opaque_self).block;
// This is the stored content block-size value from assign-block-size
let content_block_size = self.fragment.border_box.size.block;
@@ -1381,7 +1382,7 @@ impl BlockFlow {
// Calculate containing block inline size.
let containing_block_size = if flags.contains(IS_ABSOLUTELY_POSITIONED) {
- self.containing_block_size(&layout_context.shared.screen_size, opaque_self).inline
+ self.containing_block_size(&layout_context.shared.viewport_size, opaque_self).inline
} else {
content_inline_size
};
@@ -1714,7 +1715,7 @@ impl Flow for BlockFlow {
debug!("Setting root position");
self.base.position.start = LogicalPoint::zero(self.base.writing_mode);
self.base.block_container_inline_size = LogicalSize::from_physical(
- self.base.writing_mode, layout_context.shared.screen_size).inline;
+ self.base.writing_mode, layout_context.shared.viewport_size).inline;
self.base.block_container_writing_mode = self.base.writing_mode;
// The root element is never impacted by floats.
@@ -1979,12 +1980,12 @@ impl Flow for BlockFlow {
let visible_rect =
match layout_context.shared.visible_rects.get(&self.layer_id()) {
Some(visible_rect) => *visible_rect,
- None => Rect::new(Point2D::zero(), layout_context.shared.screen_size),
+ None => Rect::new(Point2D::zero(), layout_context.shared.viewport_size),
};
- let screen_size = layout_context.shared.screen_size;
- visible_rect.inflate(screen_size.width * DISPLAY_PORT_SIZE_FACTOR,
- screen_size.height * DISPLAY_PORT_SIZE_FACTOR)
+ let viewport_size = layout_context.shared.viewport_size;
+ visible_rect.inflate(viewport_size.width * DISPLAY_PORT_SIZE_FACTOR,
+ viewport_size.height * DISPLAY_PORT_SIZE_FACTOR)
} else if is_stacking_context {
self.base
.stacking_relative_position_of_display_port
@@ -2705,7 +2706,7 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
layout_context: &LayoutContext)
-> Au {
let opaque_block = OpaqueFlow::from_flow(block);
- block.containing_block_size(&layout_context.shared.screen_size, opaque_block).inline
+ block.containing_block_size(&layout_context.shared.viewport_size, opaque_block).inline
}
fn set_inline_position_of_flow_if_necessary(&self,
@@ -2817,7 +2818,7 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
-> MaybeAuto {
let opaque_block = OpaqueFlow::from_flow(block);
let containing_block_inline_size =
- block.containing_block_size(&layout_context.shared.screen_size, opaque_block).inline;
+ block.containing_block_size(&layout_context.shared.viewport_size, opaque_block).inline;
let fragment = block.fragment();
fragment.assign_replaced_inline_size_if_necessary(containing_block_inline_size);
// For replaced absolute flow, the rest of the constraint solving will
@@ -2831,7 +2832,7 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
layout_context: &LayoutContext)
-> Au {
let opaque_block = OpaqueFlow::from_flow(block);
- block.containing_block_size(&layout_context.shared.screen_size, opaque_block).inline
+ block.containing_block_size(&layout_context.shared.viewport_size, opaque_block).inline
}
fn set_inline_position_of_flow_if_necessary(&self,
diff --git a/components/layout/context.rs b/components/layout/context.rs
index 4f2cf89de2e..f3db3d80a01 100644
--- a/components/layout/context.rs
+++ b/components/layout/context.rs
@@ -82,8 +82,8 @@ pub struct SharedLayoutContext {
/// A channel for the image cache to send responses to.
pub image_cache_sender: ImageCacheChan,
- /// The current screen size.
- pub screen_size: Size2D<Au>,
+ /// The current viewport size.
+ pub viewport_size: Size2D<Au>,
/// Screen sized changed?
pub screen_size_changed: bool,
diff --git a/components/layout/css/matching.rs b/components/layout/css/matching.rs
index 5773fc6630a..456f8cbe88f 100644
--- a/components/layout/css/matching.rs
+++ b/components/layout/css/matching.rs
@@ -463,7 +463,7 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
None => None,
Some(ref style) => Some(&**style),
};
- let (the_style, is_cacheable) = cascade(layout_context.screen_size,
+ let (the_style, is_cacheable) = cascade(layout_context.viewport_size,
applicable_declarations,
shareable,
Some(&***parent_style),
@@ -472,7 +472,7 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
this_style = the_style
}
None => {
- let (the_style, is_cacheable) = cascade(layout_context.screen_size,
+ let (the_style, is_cacheable) = cascade(layout_context.viewport_size,
applicable_declarations,
shareable,
None,
diff --git a/components/layout/flow.rs b/components/layout/flow.rs
index 5be4533dc6a..e316d5f3b76 100644
--- a/components/layout/flow.rs
+++ b/components/layout/flow.rs
@@ -940,11 +940,12 @@ pub struct BaseFlow {
impl fmt::Debug for BaseFlow {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
- "@ {:?}, CC {}, ADC {}, Ovr {:?}",
+ "@ {:?}, CC {}, ADC {}, Ovr {:?}, Dmg {:?}",
self.position,
self.parallel.children_count.load(Ordering::SeqCst),
self.abs_descendants.len(),
- self.overflow)
+ self.overflow,
+ self.restyle_damage)
}
}
diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs
index 06c56110386..42dcddb57a4 100644
--- a/components/layout/layout_task.rs
+++ b/components/layout/layout_task.rs
@@ -109,9 +109,13 @@ pub struct LayoutTaskData {
/// The channel on which messages can be sent to the constellation.
pub constellation_chan: ConstellationChan,
- /// The size of the viewport.
+ /// The size of the screen.
pub screen_size: Size2D<Au>,
+ /// The size of the viewport. This may be different from the size of the screen due to viewport
+ /// constraints.
+ pub viewport_size: Size2D<Au>,
+
/// The root stacking context.
pub stacking_context: Option<Arc<StackingContext>>,
@@ -408,6 +412,7 @@ impl LayoutTask {
image_cache_task: image_cache_task,
constellation_chan: constellation_chan,
screen_size: screen_size,
+ viewport_size: screen_size,
stacking_context: None,
stylist: stylist,
parallel_traversal: parallel_traversal,
@@ -445,7 +450,7 @@ impl LayoutTask {
SharedLayoutContext {
image_cache_task: rw_data.image_cache_task.clone(),
image_cache_sender: self.image_cache_sender.clone(),
- screen_size: rw_data.screen_size.clone(),
+ viewport_size: rw_data.viewport_size.clone(),
screen_size_changed: screen_size_changed,
constellation_chan: rw_data.constellation_chan.clone(),
layout_chan: self.chan.clone(),
@@ -1033,7 +1038,7 @@ impl LayoutTask {
|| {
flow::mut_base(flow_ref::deref_mut(layout_root)).stacking_relative_position =
LogicalPoint::zero(writing_mode).to_physical(writing_mode,
- rw_data.screen_size);
+ rw_data.viewport_size);
flow::mut_base(flow_ref::deref_mut(layout_root)).clip =
ClippingRegion::from_rect(&data.page_clip_rect);
@@ -1138,24 +1143,31 @@ impl LayoutTask {
let mut rw_data = self.lock_rw_data(possibly_locked_rw_data);
let initial_viewport = data.window_size.initial_viewport;
- let old_screen_size = rw_data.screen_size;
+ let old_viewport_size = rw_data.viewport_size;
let current_screen_size = Size2D::new(Au::from_f32_px(initial_viewport.width.get()),
Au::from_f32_px(initial_viewport.height.get()));
rw_data.screen_size = current_screen_size;
- // Handle conditions where the entire flow tree is invalid.
- let screen_size_changed = current_screen_size != old_screen_size;
- if screen_size_changed {
- // Calculate the actual viewport as per DEVICE-ADAPT § 6
- let device = Device::new(MediaType::Screen, initial_viewport);
- rw_data.stylist.set_device(device);
+ // Calculate the actual viewport as per DEVICE-ADAPT § 6
+ let device = Device::new(MediaType::Screen, initial_viewport);
+ rw_data.stylist.set_device(device);
- if let Some(constraints) = rw_data.stylist.constrain_viewport() {
+ let constraints = rw_data.stylist.constrain_viewport();
+ rw_data.viewport_size = match constraints {
+ Some(ref constraints) => {
debug!("Viewport constraints: {:?}", constraints);
// other rules are evaluated against the actual viewport
- rw_data.screen_size = Size2D::new(Au::from_f32_px(constraints.size.width.get()),
- Au::from_f32_px(constraints.size.height.get()));
+ Size2D::new(Au::from_f32_px(constraints.size.width.get()),
+ Au::from_f32_px(constraints.size.height.get()))
+ }
+ None => current_screen_size,
+ };
+
+ // Handle conditions where the entire flow tree is invalid.
+ let viewport_size_changed = rw_data.viewport_size != old_viewport_size;
+ if viewport_size_changed {
+ if let Some(constraints) = constraints {
let device = Device::new(MediaType::Screen, constraints.size);
rw_data.stylist.set_device(device);
@@ -1168,7 +1180,7 @@ impl LayoutTask {
// If the entire flow tree is invalid, then it will be reflowed anyhow.
let needs_dirtying = rw_data.stylist.update();
- let needs_reflow = screen_size_changed && !needs_dirtying;
+ let needs_reflow = viewport_size_changed && !needs_dirtying;
unsafe {
if needs_dirtying {
LayoutTask::dirty_all_nodes(node);
@@ -1184,14 +1196,16 @@ impl LayoutTask {
if !needs_dirtying {
for &(el, state_change) in state_changes.iter() {
debug_assert!(!state_change.is_empty());
- let hint = rw_data.stylist.restyle_hint_for_state_change(&el, el.get_state(), state_change);
+ let hint = rw_data.stylist.restyle_hint_for_state_change(&el,
+ el.get_state(),
+ state_change);
el.note_restyle_hint(hint);
}
}
// Create a layout context for use throughout the following passes.
let mut shared_layout_context = self.build_shared_layout_context(&*rw_data,
- screen_size_changed,
+ viewport_size_changed,
&self.url,
data.reflow_info.goal);
@@ -1262,8 +1276,8 @@ impl LayoutTask {
let mut must_regenerate_display_lists = false;
let mut old_visible_rects = HashMap::with_hash_state(Default::default());
let inflation_amount =
- Size2D::new(rw_data.screen_size.width * DISPLAY_PORT_THRESHOLD_SIZE_FACTOR,
- rw_data.screen_size.height * DISPLAY_PORT_THRESHOLD_SIZE_FACTOR);
+ Size2D::new(rw_data.viewport_size.width * DISPLAY_PORT_THRESHOLD_SIZE_FACTOR,
+ rw_data.viewport_size.height * DISPLAY_PORT_THRESHOLD_SIZE_FACTOR);
for &(ref layer_id, ref new_visible_rect) in &new_visible_rects {
match rw_data.visible_rects.get(layer_id) {
None => {