mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Combine ReflowGoal and ReflowQueryType
This simplifies the logic in the layout_thread and makes it clearer which types of reflows generate display lists and cause display updates.
This commit is contained in:
parent
75a4dcf293
commit
0380431157
9 changed files with 177 additions and 267 deletions
|
@ -94,7 +94,7 @@ use parking_lot::RwLock;
|
|||
use profile_traits::mem::{self, Report, ReportKind, ReportsChan};
|
||||
use profile_traits::time::{self, TimerMetadata, profile};
|
||||
use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType};
|
||||
use script_layout_interface::message::{Msg, NewLayoutThreadInfo, Reflow, ReflowQueryType};
|
||||
use script_layout_interface::message::{Msg, NewLayoutThreadInfo, Reflow, ReflowGoal};
|
||||
use script_layout_interface::message::{ScriptReflow, ReflowComplete};
|
||||
use script_layout_interface::rpc::{LayoutRPC, MarginStyleResponse, NodeOverflowResponse, OffsetParentResponse};
|
||||
use script_layout_interface::rpc::TextIndexResponse;
|
||||
|
@ -122,7 +122,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
|||
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||
use std::thread;
|
||||
use style::animation::Animation;
|
||||
use style::context::{QuirksMode, ReflowGoal, SharedStyleContext};
|
||||
use style::context::{QuirksMode, SharedStyleContext};
|
||||
use style::context::{StyleSystemOptions, ThreadLocalStyleContextCreationInfo};
|
||||
use style::context::RegisteredSpeculativePainter;
|
||||
use style::context::RegisteredSpeculativePainters;
|
||||
|
@ -943,10 +943,10 @@ impl LayoutThread {
|
|||
}
|
||||
|
||||
/// Computes the stacking-relative positions of all flows and, if the painting is dirty and the
|
||||
/// reflow goal and query type need it, builds the display list.
|
||||
/// reflow type need it, builds the display list.
|
||||
fn compute_abs_pos_and_build_display_list(&self,
|
||||
data: &Reflow,
|
||||
query_type: Option<&ReflowQueryType>,
|
||||
reflow_goal: &ReflowGoal,
|
||||
document: Option<&ServoLayoutDocument>,
|
||||
layout_root: &mut Flow,
|
||||
layout_context: &mut LayoutContext,
|
||||
|
@ -968,52 +968,45 @@ impl LayoutThread {
|
|||
|
||||
if flow::base(layout_root).restyle_damage.contains(REPAINT) ||
|
||||
rw_data.display_list.is_none() {
|
||||
let display_list_needed = query_type.map(reflow_query_type_needs_display_list)
|
||||
.unwrap_or(false);
|
||||
match (data.goal, display_list_needed) {
|
||||
(ReflowGoal::ForDisplay, _) | (ReflowGoal::ForScriptQuery, true) => {
|
||||
let mut build_state =
|
||||
sequential::build_display_list_for_subtree(layout_root,
|
||||
layout_context);
|
||||
if reflow_goal.needs_display_list() {
|
||||
let mut build_state =
|
||||
sequential::build_display_list_for_subtree(layout_root, layout_context);
|
||||
|
||||
debug!("Done building display list.");
|
||||
debug!("Done building display list.");
|
||||
|
||||
let root_size = {
|
||||
let root_flow = flow::base(layout_root);
|
||||
if self.stylist.viewport_constraints().is_some() {
|
||||
root_flow.position.size.to_physical(root_flow.writing_mode)
|
||||
} else {
|
||||
root_flow.overflow.scroll.size
|
||||
}
|
||||
};
|
||||
|
||||
let origin = Rect::new(Point2D::new(Au(0), Au(0)), root_size);
|
||||
build_state.root_stacking_context.bounds = origin;
|
||||
build_state.root_stacking_context.overflow = origin;
|
||||
|
||||
if !build_state.iframe_sizes.is_empty() {
|
||||
// build_state.iframe_sizes is only used here, so its okay to replace
|
||||
// it with an empty vector
|
||||
let iframe_sizes = std::mem::replace(&mut build_state.iframe_sizes, vec![]);
|
||||
let msg = ConstellationMsg::IFrameSizes(iframe_sizes);
|
||||
if let Err(e) = self.constellation_chan.send(msg) {
|
||||
warn!("Layout resize to constellation failed ({}).", e);
|
||||
}
|
||||
let root_size = {
|
||||
let root_flow = flow::base(layout_root);
|
||||
if self.stylist.viewport_constraints().is_some() {
|
||||
root_flow.position.size.to_physical(root_flow.writing_mode)
|
||||
} else {
|
||||
root_flow.overflow.scroll.size
|
||||
}
|
||||
};
|
||||
|
||||
rw_data.display_list = Some(Arc::new(build_state.to_display_list()));
|
||||
let origin = Rect::new(Point2D::new(Au(0), Au(0)), root_size);
|
||||
build_state.root_stacking_context.bounds = origin;
|
||||
build_state.root_stacking_context.overflow = origin;
|
||||
|
||||
if !build_state.iframe_sizes.is_empty() {
|
||||
// build_state.iframe_sizes is only used here, so its okay to replace
|
||||
// it with an empty vector
|
||||
let iframe_sizes = std::mem::replace(&mut build_state.iframe_sizes, vec![]);
|
||||
let msg = ConstellationMsg::IFrameSizes(iframe_sizes);
|
||||
if let Err(e) = self.constellation_chan.send(msg) {
|
||||
warn!("Layout resize to constellation failed ({}).", e);
|
||||
}
|
||||
}
|
||||
(ReflowGoal::ForScriptQuery, false) => {}
|
||||
|
||||
rw_data.display_list = Some(Arc::new(build_state.to_display_list()));
|
||||
}
|
||||
}
|
||||
|
||||
if data.goal != ReflowGoal::ForDisplay {
|
||||
if !reflow_goal.needs_display() {
|
||||
// Defer the paint step until the next ForDisplay.
|
||||
//
|
||||
// We need to tell the document about this so it doesn't
|
||||
// incorrectly suppress reflows. See #13131.
|
||||
document.expect("No document in a non-display reflow?")
|
||||
.needs_paint_from_layout();
|
||||
document.expect("No document in a non-display reflow?").needs_paint_from_layout();
|
||||
return;
|
||||
}
|
||||
if let Some(document) = document {
|
||||
|
@ -1066,12 +1059,6 @@ impl LayoutThread {
|
|||
let document = unsafe { ServoLayoutNode::new(&data.document) };
|
||||
let document = document.as_document().unwrap();
|
||||
|
||||
// FIXME(pcwalton): Combine `ReflowGoal` and `ReflowQueryType`. Then remove this assert.
|
||||
debug_assert!((data.reflow_info.goal == ReflowGoal::ForDisplay &&
|
||||
data.query_type == ReflowQueryType::NoQuery) ||
|
||||
(data.reflow_info.goal == ReflowGoal::ForScriptQuery &&
|
||||
data.query_type != ReflowQueryType::NoQuery));
|
||||
|
||||
// Parallelize if there's more than 750 objects based on rzambre's suggestion
|
||||
// https://github.com/servo/servo/issues/10110
|
||||
self.parallel_flag = self.layout_threads > 1 && data.dom_count > 750;
|
||||
|
@ -1085,44 +1072,44 @@ impl LayoutThread {
|
|||
None => {
|
||||
// Since we cannot compute anything, give spec-required placeholders.
|
||||
debug!("layout: No root node: bailing");
|
||||
match data.query_type {
|
||||
ReflowQueryType::ContentBoxQuery(_) => {
|
||||
match data.reflow_goal {
|
||||
ReflowGoal::ContentBoxQuery(_) => {
|
||||
rw_data.content_box_response = None;
|
||||
},
|
||||
ReflowQueryType::ContentBoxesQuery(_) => {
|
||||
ReflowGoal::ContentBoxesQuery(_) => {
|
||||
rw_data.content_boxes_response = Vec::new();
|
||||
},
|
||||
ReflowQueryType::HitTestQuery(..) => {
|
||||
ReflowGoal::HitTestQuery(..) => {
|
||||
rw_data.hit_test_response = (None, false);
|
||||
},
|
||||
ReflowQueryType::NodesFromPoint(..) => {
|
||||
ReflowGoal::NodesFromPoint(..) => {
|
||||
rw_data.nodes_from_point_response = Vec::new();
|
||||
},
|
||||
ReflowQueryType::NodeGeometryQuery(_) => {
|
||||
ReflowGoal::NodeGeometryQuery(_) => {
|
||||
rw_data.client_rect_response = Rect::zero();
|
||||
},
|
||||
ReflowQueryType::NodeScrollGeometryQuery(_) => {
|
||||
ReflowGoal::NodeScrollGeometryQuery(_) => {
|
||||
rw_data.scroll_area_response = Rect::zero();
|
||||
},
|
||||
ReflowQueryType::NodeOverflowQuery(_) => {
|
||||
ReflowGoal::NodeOverflowQuery(_) => {
|
||||
rw_data.overflow_response = NodeOverflowResponse(None);
|
||||
},
|
||||
ReflowQueryType::NodeScrollRootIdQuery(_) => {
|
||||
ReflowGoal::NodeScrollRootIdQuery(_) => {
|
||||
rw_data.scroll_root_id_response = None;
|
||||
},
|
||||
ReflowQueryType::ResolvedStyleQuery(_, _, _) => {
|
||||
ReflowGoal::ResolvedStyleQuery(_, _, _) => {
|
||||
rw_data.resolved_style_response = String::new();
|
||||
},
|
||||
ReflowQueryType::OffsetParentQuery(_) => {
|
||||
ReflowGoal::OffsetParentQuery(_) => {
|
||||
rw_data.offset_parent_response = OffsetParentResponse::empty();
|
||||
},
|
||||
ReflowQueryType::MarginStyleQuery(_) => {
|
||||
ReflowGoal::MarginStyleQuery(_) => {
|
||||
rw_data.margin_style_response = MarginStyleResponse::empty();
|
||||
},
|
||||
ReflowQueryType::TextIndexQuery(..) => {
|
||||
ReflowGoal::TextIndexQuery(..) => {
|
||||
rw_data.text_index_response = TextIndexResponse(None);
|
||||
}
|
||||
ReflowQueryType::NoQuery => {}
|
||||
ReflowGoal::Full | ReflowGoal:: TickAnimations => {}
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
@ -1130,7 +1117,7 @@ impl LayoutThread {
|
|||
};
|
||||
|
||||
debug!("layout: processing reflow request for: {:?} ({}) (query={:?})",
|
||||
element, self.url, data.query_type);
|
||||
element, self.url, data.reflow_goal);
|
||||
trace!("{:?}", ShowSubtree(element.as_node()));
|
||||
|
||||
let initial_viewport = data.window_size.initial_viewport;
|
||||
|
@ -1325,20 +1312,20 @@ impl LayoutThread {
|
|||
if let Some(mut root_flow) = self.root_flow.borrow().clone() {
|
||||
self.perform_post_style_recalc_layout_passes(&mut root_flow,
|
||||
&data.reflow_info,
|
||||
Some(&data.query_type),
|
||||
&data.reflow_goal,
|
||||
Some(&document),
|
||||
&mut rw_data,
|
||||
&mut layout_context);
|
||||
}
|
||||
|
||||
self.respond_to_query_if_necessary(&data.query_type,
|
||||
self.respond_to_query_if_necessary(&data.reflow_goal,
|
||||
&mut *rw_data,
|
||||
&mut layout_context,
|
||||
data.result.borrow_mut().as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn respond_to_query_if_necessary(&self,
|
||||
query_type: &ReflowQueryType,
|
||||
reflow_goal: &ReflowGoal,
|
||||
rw_data: &mut LayoutThreadData,
|
||||
context: &mut LayoutContext,
|
||||
reflow_result: &mut ReflowComplete) {
|
||||
|
@ -1359,16 +1346,16 @@ impl LayoutThread {
|
|||
None => return,
|
||||
};
|
||||
let root_flow = FlowRef::deref_mut(&mut root_flow);
|
||||
match *query_type {
|
||||
ReflowQueryType::ContentBoxQuery(node) => {
|
||||
match *reflow_goal {
|
||||
ReflowGoal::ContentBoxQuery(node) => {
|
||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||
rw_data.content_box_response = process_content_box_request(node, root_flow);
|
||||
},
|
||||
ReflowQueryType::ContentBoxesQuery(node) => {
|
||||
ReflowGoal::ContentBoxesQuery(node) => {
|
||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||
rw_data.content_boxes_response = process_content_boxes_request(node, root_flow);
|
||||
},
|
||||
ReflowQueryType::HitTestQuery(client_point, update_cursor) => {
|
||||
ReflowGoal::HitTestQuery(client_point, update_cursor) => {
|
||||
let point = Point2D::new(Au::from_f32_px(client_point.x),
|
||||
Au::from_f32_px(client_point.y));
|
||||
let result = rw_data.display_list
|
||||
|
@ -1377,7 +1364,7 @@ impl LayoutThread {
|
|||
.hit_test(&point, &rw_data.scroll_offsets);
|
||||
rw_data.hit_test_response = (result.last().cloned(), update_cursor);
|
||||
},
|
||||
ReflowQueryType::TextIndexQuery(node, mouse_x, mouse_y) => {
|
||||
ReflowGoal::TextIndexQuery(node, mouse_x, mouse_y) => {
|
||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||
let opaque_node = node.opaque();
|
||||
let client_point = Point2D::new(Au::from_px(mouse_x),
|
||||
|
@ -1390,24 +1377,24 @@ impl LayoutThread {
|
|||
&client_point,
|
||||
&rw_data.scroll_offsets));
|
||||
},
|
||||
ReflowQueryType::NodeGeometryQuery(node) => {
|
||||
ReflowGoal::NodeGeometryQuery(node) => {
|
||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||
rw_data.client_rect_response = process_node_geometry_request(node, root_flow);
|
||||
},
|
||||
ReflowQueryType::NodeScrollGeometryQuery(node) => {
|
||||
ReflowGoal::NodeScrollGeometryQuery(node) => {
|
||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||
rw_data.scroll_area_response = process_node_scroll_area_request(node, root_flow);
|
||||
},
|
||||
ReflowQueryType::NodeOverflowQuery(node) => {
|
||||
ReflowGoal::NodeOverflowQuery(node) => {
|
||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||
rw_data.overflow_response = process_node_overflow_request(node);
|
||||
},
|
||||
ReflowQueryType::NodeScrollRootIdQuery(node) => {
|
||||
ReflowGoal::NodeScrollRootIdQuery(node) => {
|
||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||
rw_data.scroll_root_id_response = Some(process_node_scroll_root_id_request(self.id,
|
||||
node));
|
||||
},
|
||||
ReflowQueryType::ResolvedStyleQuery(node, ref pseudo, ref property) => {
|
||||
ReflowGoal::ResolvedStyleQuery(node, ref pseudo, ref property) => {
|
||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||
rw_data.resolved_style_response =
|
||||
process_resolved_style_request(context,
|
||||
|
@ -1416,15 +1403,15 @@ impl LayoutThread {
|
|||
property,
|
||||
root_flow);
|
||||
},
|
||||
ReflowQueryType::OffsetParentQuery(node) => {
|
||||
ReflowGoal::OffsetParentQuery(node) => {
|
||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||
rw_data.offset_parent_response = process_offset_parent_query(node, root_flow);
|
||||
},
|
||||
ReflowQueryType::MarginStyleQuery(node) => {
|
||||
ReflowGoal::MarginStyleQuery(node) => {
|
||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||
rw_data.margin_style_response = process_margin_style_query(node);
|
||||
},
|
||||
ReflowQueryType::NodesFromPoint(client_point) => {
|
||||
ReflowGoal::NodesFromPoint(client_point) => {
|
||||
let client_point = Point2D::new(Au::from_f32_px(client_point.x),
|
||||
Au::from_f32_px(client_point.y));
|
||||
let nodes_from_point_list = {
|
||||
|
@ -1442,8 +1429,9 @@ impl LayoutThread {
|
|||
.rev()
|
||||
.map(|metadata| metadata.node.to_untrusted_node_address())
|
||||
.collect()
|
||||
},
|
||||
ReflowQueryType::NoQuery => {}
|
||||
}
|
||||
|
||||
ReflowGoal::Full | ReflowGoal::TickAnimations => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1482,7 +1470,6 @@ impl LayoutThread {
|
|||
|
||||
if let Some(mut root_flow) = self.root_flow.borrow().clone() {
|
||||
let reflow_info = Reflow {
|
||||
goal: ReflowGoal::ForDisplay,
|
||||
page_clip_rect: max_rect(),
|
||||
};
|
||||
|
||||
|
@ -1513,7 +1500,7 @@ impl LayoutThread {
|
|||
}
|
||||
self.perform_post_style_recalc_layout_passes(&mut root_flow,
|
||||
&reflow_info,
|
||||
None,
|
||||
&ReflowGoal::TickAnimations,
|
||||
None,
|
||||
&mut *rw_data,
|
||||
&mut layout_context);
|
||||
|
@ -1525,7 +1512,7 @@ impl LayoutThread {
|
|||
fn perform_post_style_recalc_layout_passes(&self,
|
||||
root_flow: &mut FlowRef,
|
||||
data: &Reflow,
|
||||
query_type: Option<&ReflowQueryType>,
|
||||
reflow_goal: &ReflowGoal,
|
||||
document: Option<&ServoLayoutDocument>,
|
||||
rw_data: &mut LayoutThreadData,
|
||||
context: &mut LayoutContext) {
|
||||
|
@ -1609,7 +1596,7 @@ impl LayoutThread {
|
|||
});
|
||||
|
||||
self.perform_post_main_layout_passes(data,
|
||||
query_type,
|
||||
reflow_goal,
|
||||
document,
|
||||
rw_data,
|
||||
context);
|
||||
|
@ -1617,14 +1604,14 @@ impl LayoutThread {
|
|||
|
||||
fn perform_post_main_layout_passes(&self,
|
||||
data: &Reflow,
|
||||
query_type: Option<&ReflowQueryType>,
|
||||
reflow_goal: &ReflowGoal,
|
||||
document: Option<&ServoLayoutDocument>,
|
||||
rw_data: &mut LayoutThreadData,
|
||||
layout_context: &mut LayoutContext) {
|
||||
// Build the display list if necessary, and send it to the painter.
|
||||
if let Some(mut root_flow) = self.root_flow.borrow().clone() {
|
||||
self.compute_abs_pos_and_build_display_list(data,
|
||||
query_type,
|
||||
reflow_goal,
|
||||
document,
|
||||
FlowRef::deref_mut(&mut root_flow),
|
||||
&mut *layout_context,
|
||||
|
@ -1762,20 +1749,6 @@ fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Returns true if the given reflow query type needs a full, up-to-date display list to be present
|
||||
/// or false if it only needs stacking-relative positions.
|
||||
fn reflow_query_type_needs_display_list(query_type: &ReflowQueryType) -> bool {
|
||||
match *query_type {
|
||||
ReflowQueryType::HitTestQuery(..) | ReflowQueryType::TextIndexQuery(..) |
|
||||
ReflowQueryType::NodesFromPoint(..) => true,
|
||||
ReflowQueryType::ContentBoxQuery(_) | ReflowQueryType::ContentBoxesQuery(_) |
|
||||
ReflowQueryType::NodeGeometryQuery(_) | ReflowQueryType::NodeScrollGeometryQuery(_) |
|
||||
ReflowQueryType::NodeOverflowQuery(_) | ReflowQueryType::NodeScrollRootIdQuery(_) |
|
||||
ReflowQueryType::ResolvedStyleQuery(..) | ReflowQueryType::OffsetParentQuery(_) |
|
||||
ReflowQueryType::MarginStyleQuery(_) | ReflowQueryType::NoQuery => false,
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref UA_STYLESHEETS: UserAgentStylesheets = {
|
||||
match get_ua_stylesheets() {
|
||||
|
|
|
@ -11,8 +11,7 @@ use dom::eventtarget::EventTarget;
|
|||
use dom::mouseevent::MouseEvent;
|
||||
use dom::node::window_from_node;
|
||||
use dom::window::ReflowReason;
|
||||
use script_layout_interface::message::ReflowQueryType;
|
||||
use style::context::ReflowGoal;
|
||||
use script_layout_interface::message::ReflowGoal;
|
||||
|
||||
/// Trait for elements with defined activation behavior
|
||||
pub trait Activatable {
|
||||
|
@ -38,18 +37,14 @@ pub trait Activatable {
|
|||
self.as_element().set_active_state(true);
|
||||
|
||||
let win = window_from_node(self.as_element());
|
||||
win.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::ElementStateChanged);
|
||||
win.reflow(ReflowGoal::Full, ReflowReason::ElementStateChanged);
|
||||
}
|
||||
|
||||
fn exit_formal_activation_state(&self) {
|
||||
self.as_element().set_active_state(false);
|
||||
|
||||
let win = window_from_node(self.as_element());
|
||||
win.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::ElementStateChanged);
|
||||
win.reflow(ReflowGoal::Full, ReflowReason::ElementStateChanged);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ use net_traits::pub_domains::is_pub_domain;
|
|||
use net_traits::request::RequestInit;
|
||||
use net_traits::response::HttpsState;
|
||||
use num_traits::ToPrimitive;
|
||||
use script_layout_interface::message::{Msg, ReflowQueryType};
|
||||
use script_layout_interface::message::{Msg, ReflowGoal};
|
||||
use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory};
|
||||
use script_thread::{MainThreadScriptMsg, ScriptThread};
|
||||
use script_traits::{AnimationState, CompositorEvent, DocumentActivity};
|
||||
|
@ -133,7 +133,7 @@ use std::mem;
|
|||
use std::rc::Rc;
|
||||
use std::time::{Duration, Instant};
|
||||
use style::attr::AttrValue;
|
||||
use style::context::{QuirksMode, ReflowGoal};
|
||||
use style::context::QuirksMode;
|
||||
use style::invalidation::element::restyle_hints::{RestyleHint, RESTYLE_SELF, RESTYLE_STYLE_ATTRIBUTE};
|
||||
use style::media_queries::{Device, MediaList, MediaType};
|
||||
use style::selector_parser::{RestyleDamage, Snapshot};
|
||||
|
@ -463,11 +463,7 @@ impl Document {
|
|||
if activity == DocumentActivity::FullyActive {
|
||||
self.title_changed();
|
||||
self.dirty_all_nodes();
|
||||
self.window().reflow(
|
||||
ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::CachedPageNeededReflow
|
||||
);
|
||||
self.window().reflow(ReflowGoal::Full, ReflowReason::CachedPageNeededReflow);
|
||||
self.window().resume();
|
||||
} else {
|
||||
self.window().suspend();
|
||||
|
@ -585,9 +581,7 @@ impl Document {
|
|||
}
|
||||
|
||||
self.reflow_timeout.set(None);
|
||||
self.window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::RefreshTick);
|
||||
self.window.reflow(ReflowGoal::Full, ReflowReason::RefreshTick);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -949,9 +943,7 @@ impl Document {
|
|||
self.maybe_fire_dblclick(client_point, node);
|
||||
}
|
||||
|
||||
self.window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::MouseEvent);
|
||||
self.window.reflow(ReflowGoal::Full, ReflowReason::MouseEvent);
|
||||
}
|
||||
|
||||
fn maybe_fire_dblclick(&self, click_pos: Point2D<f32>, target: &Node) {
|
||||
|
@ -1201,9 +1193,7 @@ impl Document {
|
|||
// Store the current mouse over target for next frame.
|
||||
prev_mouse_over_target.set(maybe_new_target.r());
|
||||
|
||||
self.window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::MouseEvent);
|
||||
self.window.reflow(ReflowGoal::Full, ReflowReason::MouseEvent);
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
|
@ -1324,9 +1314,7 @@ impl Document {
|
|||
let event = event.upcast::<Event>();
|
||||
let result = event.fire(&target);
|
||||
|
||||
window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::MouseEvent);
|
||||
window.reflow(ReflowGoal::Full, ReflowReason::MouseEvent);
|
||||
|
||||
match result {
|
||||
EventStatus::Canceled => TouchEventResult::Processed(false),
|
||||
|
@ -1447,9 +1435,7 @@ impl Document {
|
|||
}
|
||||
}
|
||||
|
||||
self.window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::KeyEvent);
|
||||
self.window.reflow(ReflowGoal::Full, ReflowReason::KeyEvent);
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#converting-nodes-into-a-node
|
||||
|
@ -1595,9 +1581,7 @@ impl Document {
|
|||
|
||||
self.running_animation_callbacks.set(false);
|
||||
|
||||
let spurious = !self.window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::RequestAnimationFrame);
|
||||
let spurious = !self.window.reflow(ReflowGoal::Full, ReflowReason::RequestAnimationFrame);
|
||||
|
||||
if spurious && !was_faking_animation_frames {
|
||||
// If the rAF callbacks did not mutate the DOM, then the
|
||||
|
@ -1610,9 +1594,7 @@ impl Document {
|
|||
// for the interim frames where we are deciding whether this rAF
|
||||
// is considered spurious, we need to ensure that the layout
|
||||
// and compositor *do* tick the animation.
|
||||
self.window.force_reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::RequestAnimationFrame);
|
||||
self.window.force_reflow(ReflowGoal::Full, ReflowReason::RequestAnimationFrame);
|
||||
}
|
||||
|
||||
// Only send the animation change state message after running any callbacks.
|
||||
|
@ -1670,9 +1652,7 @@ impl Document {
|
|||
// Disarm the reflow timer and trigger the initial reflow.
|
||||
self.reflow_timeout.set(None);
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
self.window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::FirstLoad);
|
||||
self.window.reflow(ReflowGoal::Full, ReflowReason::FirstLoad);
|
||||
}
|
||||
|
||||
// Deferred scripts have to wait for page to finish loading,
|
||||
|
@ -1749,11 +1729,7 @@ impl Document {
|
|||
// http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventEnd
|
||||
update_with_current_time_ms(&document.load_event_end);
|
||||
|
||||
window.reflow(
|
||||
ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::DocumentLoaded,
|
||||
);
|
||||
window.reflow(ReflowGoal::Full, ReflowReason::DocumentLoaded);
|
||||
|
||||
document.notify_constellation_load();
|
||||
|
||||
|
@ -1900,9 +1876,7 @@ impl Document {
|
|||
window.dom_manipulation_task_source().queue_event(self.upcast(), atom!("DOMContentLoaded"),
|
||||
EventBubbles::Bubbles, EventCancelable::NotCancelable, window);
|
||||
|
||||
window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::DOMContentLoaded);
|
||||
window.reflow(ReflowGoal::Full, ReflowReason::DOMContentLoaded);
|
||||
update_with_current_time_ms(&self.dom_content_loaded_event_end);
|
||||
|
||||
// Step 4.2.
|
||||
|
@ -2032,9 +2006,7 @@ impl Document {
|
|||
}
|
||||
|
||||
pub fn nodes_from_point(&self, client_point: &Point2D<f32>) -> Vec<UntrustedNodeAddress> {
|
||||
if !self.window.reflow(ReflowGoal::ForScriptQuery,
|
||||
ReflowQueryType::NodesFromPoint(*client_point),
|
||||
ReflowReason::Query) {
|
||||
if !self.window.reflow(ReflowGoal::NodesFromPoint(*client_point), ReflowReason::Query) {
|
||||
return vec!();
|
||||
};
|
||||
|
||||
|
@ -2591,9 +2563,7 @@ impl Document {
|
|||
element.set_target_state(true);
|
||||
}
|
||||
|
||||
self.window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::ElementStateChanged);
|
||||
self.window.reflow(ReflowGoal::Full, ReflowReason::ElementStateChanged);
|
||||
}
|
||||
|
||||
pub fn incr_ignore_destructive_writes_counter(&self) {
|
||||
|
|
|
@ -85,7 +85,7 @@ use js::jsapi::Heap;
|
|||
use js::jsval::JSVal;
|
||||
use net_traits::request::CorsSettings;
|
||||
use ref_filter_map::ref_filter_map;
|
||||
use script_layout_interface::message::ReflowQueryType;
|
||||
use script_layout_interface::message::ReflowGoal;
|
||||
use script_thread::ScriptThread;
|
||||
use selectors::attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivity};
|
||||
use selectors::matching::{ElementSelectorFlags, LocalMatchingContext, MatchingContext, MatchingMode};
|
||||
|
@ -105,7 +105,7 @@ use std::rc::Rc;
|
|||
use style::CaseSensitivityExt;
|
||||
use style::applicable_declarations::ApplicableDeclarationBlock;
|
||||
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
|
||||
use style::context::{QuirksMode, ReflowGoal};
|
||||
use style::context::QuirksMode;
|
||||
use style::element_state::*;
|
||||
use style::invalidation::element::restyle_hints::RESTYLE_SELF;
|
||||
use style::properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
|
||||
|
@ -3070,9 +3070,7 @@ impl TaskOnce for ElementPerformFullscreenEnter {
|
|||
// Step 7.5
|
||||
element.set_fullscreen_state(true);
|
||||
document.set_fullscreen_element(Some(&element));
|
||||
document.window().reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::ElementStateChanged);
|
||||
document.window().reflow(ReflowGoal::Full, ReflowReason::ElementStateChanged);
|
||||
|
||||
// Step 7.6
|
||||
document.upcast::<EventTarget>().fire_event(atom!("fullscreenchange"));
|
||||
|
@ -3105,9 +3103,7 @@ impl TaskOnce for ElementPerformFullscreenExit {
|
|||
// Step 9.6
|
||||
element.set_fullscreen_state(false);
|
||||
|
||||
document.window().reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::ElementStateChanged);
|
||||
document.window().reflow(ReflowGoal::Full, ReflowReason::ElementStateChanged);
|
||||
|
||||
document.set_fullscreen_element(None);
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ use js::jsapi::{JSAutoCompartment, JSContext, MutableHandleValue};
|
|||
use js::jsval::{NullValue, UndefinedValue};
|
||||
use msg::constellation_msg::{FrameType, BrowsingContextId, PipelineId, TopLevelBrowsingContextId, TraversalDirection};
|
||||
use net_traits::response::HttpsState;
|
||||
use script_layout_interface::message::ReflowQueryType;
|
||||
use script_layout_interface::message::ReflowGoal;
|
||||
use script_thread::ScriptThread;
|
||||
use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, JsEvalResult, LoadData, UpdatePipelineIdReason};
|
||||
use script_traits::{MozBrowserEvent, NewLayoutInfo, ScriptMsg};
|
||||
|
@ -53,7 +53,6 @@ use servo_config::servo_version;
|
|||
use servo_url::ServoUrl;
|
||||
use std::cell::Cell;
|
||||
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
|
||||
use style::context::ReflowGoal;
|
||||
use task_source::TaskSource;
|
||||
|
||||
bitflags! {
|
||||
|
@ -313,9 +312,7 @@ impl HTMLIFrameElement {
|
|||
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
let window = window_from_node(self);
|
||||
window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::FramedContentChanged);
|
||||
window.reflow(ReflowGoal::Full, ReflowReason::FramedContentChanged);
|
||||
}
|
||||
|
||||
fn new_inherited(local_name: LocalName,
|
||||
|
@ -396,9 +393,7 @@ impl HTMLIFrameElement {
|
|||
// TODO Step 5 - unset child document `mut iframe load` flag
|
||||
|
||||
let window = window_from_node(self);
|
||||
window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::IFrameLoadEvent);
|
||||
window.reflow(ReflowGoal::Full, ReflowReason::IFrameLoadEvent);
|
||||
}
|
||||
|
||||
/// Check whether the iframe has the mozprivatebrowsing attribute set
|
||||
|
|
|
@ -70,7 +70,7 @@ use open;
|
|||
use profile_traits::mem::ProfilerChan as MemProfilerChan;
|
||||
use profile_traits::time::ProfilerChan as TimeProfilerChan;
|
||||
use script_layout_interface::{TrustedNodeAddress, PendingImageState};
|
||||
use script_layout_interface::message::{Msg, Reflow, ReflowQueryType, ScriptReflow};
|
||||
use script_layout_interface::message::{Msg, Reflow, ReflowGoal, ScriptReflow};
|
||||
use script_layout_interface::reporter::CSSErrorReporter;
|
||||
use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse, LayoutRPC};
|
||||
use script_layout_interface::rpc::{MarginStyleResponse, NodeScrollRootIdResponse};
|
||||
|
@ -102,7 +102,6 @@ use std::sync::{Arc, Mutex};
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::{Sender, channel};
|
||||
use std::sync::mpsc::TryRecvError::{Disconnected, Empty};
|
||||
use style::context::ReflowGoal;
|
||||
use style::media_queries;
|
||||
use style::parser::ParserContext as CssParserContext;
|
||||
use style::properties::PropertyId;
|
||||
|
@ -1199,10 +1198,7 @@ impl Window {
|
|||
///
|
||||
/// Returns true if layout actually happened, false otherwise.
|
||||
#[allow(unsafe_code)]
|
||||
pub fn force_reflow(&self,
|
||||
goal: ReflowGoal,
|
||||
query_type: ReflowQueryType,
|
||||
reason: ReflowReason) -> bool {
|
||||
pub fn force_reflow(&self, reflow_goal: ReflowGoal, reason: ReflowReason) -> bool {
|
||||
// Check if we need to unsuppress reflow. Note that this needs to be
|
||||
// *before* any early bailouts, or reflow might never be unsuppresed!
|
||||
match reason {
|
||||
|
@ -1217,14 +1213,14 @@ impl Window {
|
|||
None => return false,
|
||||
};
|
||||
|
||||
let for_display = query_type == ReflowQueryType::NoQuery;
|
||||
let for_display = reflow_goal == ReflowGoal::Full;
|
||||
if for_display && self.suppress_reflow.get() {
|
||||
debug!("Suppressing reflow pipeline {} for goal {:?} reason {:?} before FirstLoad or RefreshTick",
|
||||
self.upcast::<GlobalScope>().pipeline_id(), goal, reason);
|
||||
debug!("Suppressing reflow pipeline {} for reason {:?} before FirstLoad or RefreshTick",
|
||||
self.upcast::<GlobalScope>().pipeline_id(), reason);
|
||||
return false;
|
||||
}
|
||||
|
||||
debug!("script: performing reflow for goal {:?} reason {:?}", goal, reason);
|
||||
debug!("script: performing reflow for reason {:?}", reason);
|
||||
|
||||
let marker = if self.need_emit_timeline_marker(TimelineMarkerType::Reflow) {
|
||||
Some(TimelineMarker::start("Reflow".to_owned()))
|
||||
|
@ -1237,7 +1233,7 @@ impl Window {
|
|||
|
||||
// On debug mode, print the reflow event information.
|
||||
if opts::get().relayout_event {
|
||||
debug_reflow_events(self.upcast::<GlobalScope>().pipeline_id(), &goal, &query_type, &reason);
|
||||
debug_reflow_events(self.upcast::<GlobalScope>().pipeline_id(), &reflow_goal, &reason);
|
||||
}
|
||||
|
||||
let document = self.Document();
|
||||
|
@ -1245,15 +1241,15 @@ impl Window {
|
|||
let stylesheets_changed = document.flush_stylesheets_for_reflow();
|
||||
|
||||
// Send new document and relevant styles to layout.
|
||||
let needs_display = reflow_goal.needs_display();
|
||||
let reflow = ScriptReflow {
|
||||
reflow_info: Reflow {
|
||||
goal: goal,
|
||||
page_clip_rect: self.page_clip_rect.get(),
|
||||
},
|
||||
document: self.Document().upcast::<Node>().to_trusted_node_address(),
|
||||
stylesheets_changed,
|
||||
window_size,
|
||||
query_type,
|
||||
reflow_goal,
|
||||
script_join_chan: join_chan,
|
||||
dom_count: self.Document().dom_count(),
|
||||
};
|
||||
|
@ -1277,7 +1273,7 @@ impl Window {
|
|||
|
||||
// Pending reflows require display, so only reset the pending reflow count if this reflow
|
||||
// was to be displayed.
|
||||
if goal == ReflowGoal::ForDisplay {
|
||||
if needs_display {
|
||||
self.pending_reflow_count.set(0);
|
||||
}
|
||||
|
||||
|
@ -1329,15 +1325,12 @@ impl Window {
|
|||
/// that layout might hold if the first layout hasn't happened yet (which
|
||||
/// may happen in the only case a query reflow may bail out, that is, if the
|
||||
/// viewport size is not present). See #11223 for an example of that.
|
||||
pub fn reflow(&self,
|
||||
goal: ReflowGoal,
|
||||
query_type: ReflowQueryType,
|
||||
reason: ReflowReason) -> bool {
|
||||
let for_display = query_type == ReflowQueryType::NoQuery;
|
||||
pub fn reflow(&self, reflow_goal: ReflowGoal, reason: ReflowReason) -> bool {
|
||||
let for_display = reflow_goal == ReflowGoal::Full;
|
||||
|
||||
let mut issued_reflow = false;
|
||||
if !for_display || self.Document().needs_reflow() {
|
||||
issued_reflow = self.force_reflow(goal, query_type, reason);
|
||||
issued_reflow = self.force_reflow(reflow_goal, 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
|
||||
|
@ -1387,9 +1380,7 @@ impl Window {
|
|||
}
|
||||
|
||||
pub fn content_box_query(&self, content_box_request: TrustedNodeAddress) -> Option<Rect<Au>> {
|
||||
if !self.reflow(ReflowGoal::ForScriptQuery,
|
||||
ReflowQueryType::ContentBoxQuery(content_box_request),
|
||||
ReflowReason::Query) {
|
||||
if !self.reflow(ReflowGoal::ContentBoxQuery(content_box_request), ReflowReason::Query) {
|
||||
return None;
|
||||
}
|
||||
let ContentBoxResponse(rect) = self.layout_rpc.content_box();
|
||||
|
@ -1397,9 +1388,7 @@ impl Window {
|
|||
}
|
||||
|
||||
pub fn content_boxes_query(&self, content_boxes_request: TrustedNodeAddress) -> Vec<Rect<Au>> {
|
||||
if !self.reflow(ReflowGoal::ForScriptQuery,
|
||||
ReflowQueryType::ContentBoxesQuery(content_boxes_request),
|
||||
ReflowReason::Query) {
|
||||
if !self.reflow(ReflowGoal::ContentBoxesQuery(content_boxes_request), ReflowReason::Query) {
|
||||
return vec![];
|
||||
}
|
||||
let ContentBoxesResponse(rects) = self.layout_rpc.content_boxes();
|
||||
|
@ -1407,9 +1396,7 @@ impl Window {
|
|||
}
|
||||
|
||||
pub fn client_rect_query(&self, node_geometry_request: TrustedNodeAddress) -> Rect<i32> {
|
||||
if !self.reflow(ReflowGoal::ForScriptQuery,
|
||||
ReflowQueryType::NodeGeometryQuery(node_geometry_request),
|
||||
ReflowReason::Query) {
|
||||
if !self.reflow(ReflowGoal::NodeGeometryQuery(node_geometry_request), ReflowReason::Query) {
|
||||
return Rect::zero();
|
||||
}
|
||||
self.layout_rpc.node_geometry().client_rect
|
||||
|
@ -1419,8 +1406,7 @@ impl Window {
|
|||
client_point: Point2D<f32>,
|
||||
update_cursor: bool)
|
||||
-> Option<UntrustedNodeAddress> {
|
||||
if !self.reflow(ReflowGoal::ForScriptQuery,
|
||||
ReflowQueryType::HitTestQuery(client_point, update_cursor),
|
||||
if !self.reflow(ReflowGoal::HitTestQuery(client_point, update_cursor),
|
||||
ReflowReason::Query) {
|
||||
return None
|
||||
}
|
||||
|
@ -1429,9 +1415,7 @@ impl Window {
|
|||
}
|
||||
|
||||
pub fn scroll_area_query(&self, node: TrustedNodeAddress) -> Rect<i32> {
|
||||
if !self.reflow(ReflowGoal::ForScriptQuery,
|
||||
ReflowQueryType::NodeScrollGeometryQuery(node),
|
||||
ReflowReason::Query) {
|
||||
if !self.reflow(ReflowGoal::NodeScrollGeometryQuery(node), ReflowReason::Query) {
|
||||
return Rect::zero();
|
||||
}
|
||||
self.layout_rpc.node_scroll_area().client_rect
|
||||
|
@ -1442,9 +1426,7 @@ impl Window {
|
|||
// NB: This is only called if the document is fully active, and the only
|
||||
// reason to bail out from a query is if there's no viewport, so this
|
||||
// *must* issue a reflow.
|
||||
assert!(self.reflow(ReflowGoal::ForScriptQuery,
|
||||
ReflowQueryType::NodeOverflowQuery(node),
|
||||
ReflowReason::Query));
|
||||
assert!(self.reflow(ReflowGoal::NodeOverflowQuery(node), ReflowReason::Query));
|
||||
|
||||
self.layout_rpc.node_overflow().0.unwrap()
|
||||
}
|
||||
|
@ -1464,8 +1446,7 @@ impl Window {
|
|||
x_: f64,
|
||||
y_: f64,
|
||||
behavior: ScrollBehavior) {
|
||||
if !self.reflow(ReflowGoal::ForScriptQuery,
|
||||
ReflowQueryType::NodeScrollRootIdQuery(node.to_trusted_node_address()),
|
||||
if !self.reflow(ReflowGoal::NodeScrollRootIdQuery(node.to_trusted_node_address()),
|
||||
ReflowReason::Query) {
|
||||
return;
|
||||
}
|
||||
|
@ -1490,8 +1471,7 @@ impl Window {
|
|||
element: TrustedNodeAddress,
|
||||
pseudo: Option<PseudoElement>,
|
||||
property: PropertyId) -> DOMString {
|
||||
if !self.reflow(ReflowGoal::ForScriptQuery,
|
||||
ReflowQueryType::ResolvedStyleQuery(element, pseudo, property),
|
||||
if !self.reflow(ReflowGoal::ResolvedStyleQuery(element, pseudo, property),
|
||||
ReflowReason::Query) {
|
||||
return DOMString::new();
|
||||
}
|
||||
|
@ -1501,9 +1481,7 @@ impl Window {
|
|||
|
||||
#[allow(unsafe_code)]
|
||||
pub fn offset_parent_query(&self, node: TrustedNodeAddress) -> (Option<DomRoot<Element>>, Rect<Au>) {
|
||||
if !self.reflow(ReflowGoal::ForScriptQuery,
|
||||
ReflowQueryType::OffsetParentQuery(node),
|
||||
ReflowReason::Query) {
|
||||
if !self.reflow(ReflowGoal::OffsetParentQuery(node), ReflowReason::Query) {
|
||||
return (None, Rect::zero());
|
||||
}
|
||||
|
||||
|
@ -1518,18 +1496,14 @@ impl Window {
|
|||
}
|
||||
|
||||
pub fn margin_style_query(&self, node: TrustedNodeAddress) -> MarginStyleResponse {
|
||||
if !self.reflow(ReflowGoal::ForScriptQuery,
|
||||
ReflowQueryType::MarginStyleQuery(node),
|
||||
ReflowReason::Query) {
|
||||
if !self.reflow(ReflowGoal::MarginStyleQuery(node), ReflowReason::Query) {
|
||||
return MarginStyleResponse::empty();
|
||||
}
|
||||
self.layout_rpc.margin_style()
|
||||
}
|
||||
|
||||
pub fn text_index_query(&self, node: TrustedNodeAddress, mouse_x: i32, mouse_y: i32) -> TextIndexResponse {
|
||||
if !self.reflow(ReflowGoal::ForScriptQuery,
|
||||
ReflowQueryType::TextIndexQuery(node, mouse_x, mouse_y),
|
||||
ReflowReason::Query) {
|
||||
if !self.reflow(ReflowGoal::TextIndexQuery(node, mouse_x, mouse_y), ReflowReason::Query) {
|
||||
return TextIndexResponse(None);
|
||||
}
|
||||
self.layout_rpc.text_index()
|
||||
|
@ -1590,9 +1564,7 @@ impl Window {
|
|||
|
||||
pub fn handle_fire_timer(&self, timer_id: TimerEventId) {
|
||||
self.upcast::<GlobalScope>().fire_timer(timer_id);
|
||||
self.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::Timer);
|
||||
self.reflow(ReflowGoal::Full, ReflowReason::Timer);
|
||||
}
|
||||
|
||||
pub fn set_window_size(&self, size: WindowSizeData) {
|
||||
|
@ -1922,27 +1894,23 @@ fn should_move_clip_rect(clip_rect: Rect<Au>, new_viewport: Rect<f32>) -> bool {
|
|||
(clip_rect.max_y() - new_viewport.max_y()).abs() <= viewport_scroll_margin.height
|
||||
}
|
||||
|
||||
fn debug_reflow_events(id: PipelineId, goal: &ReflowGoal, query_type: &ReflowQueryType, reason: &ReflowReason) {
|
||||
fn debug_reflow_events(id: PipelineId, reflow_goal: &ReflowGoal, reason: &ReflowReason) {
|
||||
let mut debug_msg = format!("**** pipeline={}", id);
|
||||
debug_msg.push_str(match *goal {
|
||||
ReflowGoal::ForDisplay => "\tForDisplay",
|
||||
ReflowGoal::ForScriptQuery => "\tForScriptQuery",
|
||||
});
|
||||
|
||||
debug_msg.push_str(match *query_type {
|
||||
ReflowQueryType::NoQuery => "\tNoQuery",
|
||||
ReflowQueryType::ContentBoxQuery(_n) => "\tContentBoxQuery",
|
||||
ReflowQueryType::ContentBoxesQuery(_n) => "\tContentBoxesQuery",
|
||||
ReflowQueryType::HitTestQuery(..) => "\tHitTestQuery",
|
||||
ReflowQueryType::NodesFromPoint(..) => "\tNodesFromPoint",
|
||||
ReflowQueryType::NodeGeometryQuery(_n) => "\tNodeGeometryQuery",
|
||||
ReflowQueryType::NodeOverflowQuery(_n) => "\tNodeOverFlowQuery",
|
||||
ReflowQueryType::NodeScrollGeometryQuery(_n) => "\tNodeScrollGeometryQuery",
|
||||
ReflowQueryType::NodeScrollRootIdQuery(_n) => "\tNodeScrollRootIdQuery",
|
||||
ReflowQueryType::ResolvedStyleQuery(_, _, _) => "\tResolvedStyleQuery",
|
||||
ReflowQueryType::OffsetParentQuery(_n) => "\tOffsetParentQuery",
|
||||
ReflowQueryType::MarginStyleQuery(_n) => "\tMarginStyleQuery",
|
||||
ReflowQueryType::TextIndexQuery(..) => "\tTextIndexQuery",
|
||||
debug_msg.push_str(match *reflow_goal {
|
||||
ReflowGoal::Full => "\tFull",
|
||||
ReflowGoal::ContentBoxQuery(_n) => "\tContentBoxQuery",
|
||||
ReflowGoal::ContentBoxesQuery(_n) => "\tContentBoxesQuery",
|
||||
ReflowGoal::HitTestQuery(..) => "\tHitTestQuery",
|
||||
ReflowGoal::NodesFromPoint(..) => "\tNodesFromPoint",
|
||||
ReflowGoal::NodeGeometryQuery(_n) => "\tNodeGeometryQuery",
|
||||
ReflowGoal::NodeOverflowQuery(_n) => "\tNodeOverFlowQuery",
|
||||
ReflowGoal::NodeScrollGeometryQuery(_n) => "\tNodeScrollGeometryQuery",
|
||||
ReflowGoal::NodeScrollRootIdQuery(_n) => "\tNodeScrollRootIdQuery",
|
||||
ReflowGoal::ResolvedStyleQuery(_, _, _) => "\tResolvedStyleQuery",
|
||||
ReflowGoal::OffsetParentQuery(_n) => "\tOffsetParentQuery",
|
||||
ReflowGoal::MarginStyleQuery(_n) => "\tMarginStyleQuery",
|
||||
ReflowGoal::TextIndexQuery(..) => "\tTextIndexQuery",
|
||||
ReflowGoal::TickAnimations => "\tTickAnimations",
|
||||
});
|
||||
|
||||
debug_msg.push_str(match *reason {
|
||||
|
|
|
@ -84,7 +84,7 @@ use net_traits::request::{CredentialsMode, Destination, RedirectMode, RequestIni
|
|||
use net_traits::storage_thread::StorageType;
|
||||
use profile_traits::mem::{self, OpaqueSender, Report, ReportKind, ReportsChan};
|
||||
use profile_traits::time::{self, ProfilerCategory, profile};
|
||||
use script_layout_interface::message::{self, Msg, NewLayoutThreadInfo, ReflowQueryType};
|
||||
use script_layout_interface::message::{self, Msg, NewLayoutThreadInfo, ReflowGoal};
|
||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
|
||||
use script_runtime::{ScriptPort, get_reports, new_rt_and_cx};
|
||||
use script_traits::{CompositorEvent, ConstellationControlMsg};
|
||||
|
@ -113,7 +113,6 @@ use std::result::Result;
|
|||
use std::sync::Arc;
|
||||
use std::sync::mpsc::{Receiver, Select, Sender, channel};
|
||||
use std::thread;
|
||||
use style::context::ReflowGoal;
|
||||
use style::thread_state;
|
||||
use task_source::dom_manipulation::DOMManipulationTaskSource;
|
||||
use task_source::file_reading::FileReadingTaskSource;
|
||||
|
@ -1091,17 +1090,13 @@ impl ScriptThread {
|
|||
let window = document.window();
|
||||
let pending_reflows = window.get_pending_reflow_count();
|
||||
if pending_reflows > 0 {
|
||||
window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::ImageLoaded);
|
||||
window.reflow(ReflowGoal::Full, ReflowReason::ImageLoaded);
|
||||
} else {
|
||||
// Reflow currently happens when explicitly invoked by code that
|
||||
// knows the document could have been modified. This should really
|
||||
// be driven by the compositor on an as-needed basis instead, to
|
||||
// minimize unnecessary work.
|
||||
window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::MissingExplicitReflow);
|
||||
window.reflow(ReflowGoal::Full, ReflowReason::MissingExplicitReflow);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2173,7 +2168,7 @@ impl ScriptThread {
|
|||
fn rebuild_and_force_reflow(&self, document: &Document, reason: ReflowReason) {
|
||||
let window = window_from_node(&*document);
|
||||
document.dirty_all_nodes();
|
||||
window.reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, reason);
|
||||
window.reflow(ReflowGoal::Full, reason);
|
||||
}
|
||||
|
||||
/// This is the main entry point for receiving and dispatching DOM events.
|
||||
|
@ -2382,9 +2377,7 @@ impl ScriptThread {
|
|||
|
||||
let window = document.window();
|
||||
window.set_window_size(new_size);
|
||||
window.force_reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::WindowResize);
|
||||
window.force_reflow(ReflowGoal::Full, ReflowReason::WindowResize);
|
||||
|
||||
// http://dev.w3.org/csswg/cssom-view/#resizing-viewports
|
||||
if size_type == WindowSizeType::Resize {
|
||||
|
|
|
@ -20,7 +20,7 @@ use servo_atoms::Atom;
|
|||
use servo_url::ServoUrl;
|
||||
use std::sync::Arc;
|
||||
use std::sync::mpsc::{Receiver, Sender};
|
||||
use style::context::{QuirksMode, ReflowGoal};
|
||||
use style::context::QuirksMode;
|
||||
use style::properties::PropertyId;
|
||||
use style::selector_parser::PseudoElement;
|
||||
use style::stylesheets::Stylesheet;
|
||||
|
@ -103,8 +103,9 @@ pub enum Msg {
|
|||
|
||||
/// Any query to perform with this reflow.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum ReflowQueryType {
|
||||
NoQuery,
|
||||
pub enum ReflowGoal {
|
||||
Full,
|
||||
TickAnimations,
|
||||
ContentBoxQuery(TrustedNodeAddress),
|
||||
ContentBoxesQuery(TrustedNodeAddress),
|
||||
NodeOverflowQuery(TrustedNodeAddress),
|
||||
|
@ -119,10 +120,38 @@ pub enum ReflowQueryType {
|
|||
NodesFromPoint(Point2D<f32>),
|
||||
}
|
||||
|
||||
impl ReflowGoal {
|
||||
/// Returns true if the given ReflowQuery needs a full, up-to-date display list to
|
||||
/// be present or false if it only needs stacking-relative positions.
|
||||
pub fn needs_display_list(&self) -> bool {
|
||||
match *self {
|
||||
ReflowGoal::NodesFromPoint(..) | ReflowGoal::HitTestQuery(..) |
|
||||
ReflowGoal::TextIndexQuery(..) | ReflowGoal::Full => true,
|
||||
ReflowGoal::ContentBoxQuery(_) | ReflowGoal::ContentBoxesQuery(_) |
|
||||
ReflowGoal::NodeGeometryQuery(_) | ReflowGoal::NodeScrollGeometryQuery(_) |
|
||||
ReflowGoal::NodeOverflowQuery(_) | ReflowGoal::NodeScrollRootIdQuery(_) |
|
||||
ReflowGoal::ResolvedStyleQuery(..) | ReflowGoal::OffsetParentQuery(_) |
|
||||
ReflowGoal::MarginStyleQuery(_) | ReflowGoal::TickAnimations => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the given ReflowQuery needs its display list send to WebRender or
|
||||
/// false if a layout_thread display list is sufficient.
|
||||
pub fn needs_display(&self) -> bool {
|
||||
match *self {
|
||||
ReflowGoal::MarginStyleQuery(_) | ReflowGoal::TextIndexQuery(..) |
|
||||
ReflowGoal::HitTestQuery(..) | ReflowGoal::ContentBoxQuery(_) |
|
||||
ReflowGoal::ContentBoxesQuery(_) | ReflowGoal::NodeGeometryQuery(_) |
|
||||
ReflowGoal::NodeScrollGeometryQuery(_) | ReflowGoal::NodeOverflowQuery(_) |
|
||||
ReflowGoal::NodeScrollRootIdQuery(_) | ReflowGoal::ResolvedStyleQuery(..) |
|
||||
ReflowGoal::OffsetParentQuery(_) | ReflowGoal::NodesFromPoint(..) => false,
|
||||
ReflowGoal::Full | ReflowGoal::TickAnimations => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Information needed for a reflow.
|
||||
pub struct Reflow {
|
||||
/// The goal of reflow: either to render to the screen or to flush layout info for script.
|
||||
pub goal: ReflowGoal,
|
||||
/// A clipping rectangle for the page, an enlarged rectangle containing the viewport.
|
||||
pub page_clip_rect: Rect<Au>,
|
||||
}
|
||||
|
@ -148,8 +177,8 @@ pub struct ScriptReflow {
|
|||
pub window_size: WindowSizeData,
|
||||
/// The channel that we send a notification to.
|
||||
pub script_join_chan: Sender<ReflowComplete>,
|
||||
/// The type of query if any to perform during this reflow.
|
||||
pub query_type: ReflowQueryType,
|
||||
/// The goal of this reflow.
|
||||
pub reflow_goal: ReflowGoal,
|
||||
/// The number of objects in the dom #10110
|
||||
pub dom_count: u32,
|
||||
}
|
||||
|
|
|
@ -819,15 +819,6 @@ pub struct StyleContext<'a, E: TElement + 'a> {
|
|||
pub thread_local: &'a mut ThreadLocalStyleContext<E>,
|
||||
}
|
||||
|
||||
/// Why we're doing reflow.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum ReflowGoal {
|
||||
/// We're reflowing in order to send a display list to the screen.
|
||||
ForDisplay,
|
||||
/// We're reflowing in order to satisfy a script query. No display list will be created.
|
||||
ForScriptQuery,
|
||||
}
|
||||
|
||||
/// A registered painter
|
||||
#[cfg(feature = "servo")]
|
||||
pub trait RegisteredSpeculativePainter: SpeculativePainter {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue