mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Have ContentBox(es)Queries consult the flow tree
Instead of looking at the display tree, have ContentBox(es)Query consult the flow tree. This allow optimizing away parts of the display tree later. To do this we need to be more careful about how we send reflow requests, only querying the flow tree when possible. Fixes #3790.
This commit is contained in:
parent
1a3ff8739c
commit
2d72f00ccf
19 changed files with 374 additions and 213 deletions
|
@ -35,7 +35,8 @@ use floats::{ClearBoth, ClearLeft, ClearRight, FloatKind, FloatLeft, Floats, Pla
|
|||
use flow::{BaseFlow, BlockFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
||||
use flow::{MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal, mut_base};
|
||||
use flow;
|
||||
use fragment::{Fragment, ImageFragment, InlineBlockFragment, ScannedTextFragment};
|
||||
use fragment::{Fragment, ImageFragment, InlineBlockFragment, FragmentBoundsIterator};
|
||||
use fragment::ScannedTextFragment;
|
||||
use incremental::{Reflow, ReflowOutOfFlow};
|
||||
use layout_debug;
|
||||
use model::{Auto, IntrinsicISizes, MarginCollapseInfo, MarginsCollapse, MarginsCollapseThrough};
|
||||
|
@ -1816,6 +1817,14 @@ impl Flow for BlockFlow {
|
|||
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
|
||||
self.fragment.repair_style(new_style)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
if iterator.should_process(&self.fragment) {
|
||||
let fragment_origin = self.base.child_fragment_absolute_position(&self.fragment);
|
||||
iterator.process(&self.fragment,
|
||||
self.fragment.abs_bounds_from_origin(&fragment_origin));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Show for BlockFlow {
|
||||
|
|
|
@ -322,7 +322,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
Rect(physical_rect.origin + flow_origin, physical_rect.size)
|
||||
};
|
||||
// Fragment position wrt to the owning flow.
|
||||
let absolute_fragment_bounds = rect_to_absolute(self.style.writing_mode, self.border_box);
|
||||
let absolute_fragment_bounds = self.abs_bounds_from_origin(&flow_origin);
|
||||
debug!("Fragment::build_display_list at rel={}, abs={}: {}",
|
||||
self.border_box,
|
||||
absolute_fragment_bounds,
|
||||
|
@ -615,18 +615,12 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
fn build_display_list_for_block(&mut self,
|
||||
layout_context: &LayoutContext,
|
||||
background_border_level: BackgroundAndBorderLevel) {
|
||||
let relative_offset =
|
||||
self.fragment.relative_position(&self.base
|
||||
.absolute_position_info
|
||||
.relative_containing_block_size);
|
||||
|
||||
// Add the box that starts the block context.
|
||||
self.base.display_list = DisplayList::new();
|
||||
let absolute_position =
|
||||
self.base.abs_position.add_size(&relative_offset.to_physical(self.base.writing_mode));
|
||||
let absolute_fragment_origin = self.base.child_fragment_absolute_position(&self.fragment);
|
||||
self.fragment.build_display_list(&mut self.base.display_list,
|
||||
layout_context,
|
||||
absolute_position,
|
||||
absolute_fragment_origin,
|
||||
background_border_level,
|
||||
&self.base.clip_rect);
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ use context::LayoutContext;
|
|||
use floats::Floats;
|
||||
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
|
||||
use flow_ref::FlowRef;
|
||||
use fragment::{Fragment, TableRowFragment, TableCellFragment};
|
||||
use fragment::{Fragment, FragmentBoundsIterator, TableRowFragment, TableCellFragment};
|
||||
use incremental::{ReconstructFlow, Reflow, ReflowOutOfFlow, RestyleDamage};
|
||||
use inline::InlineFlow;
|
||||
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
|
||||
|
@ -214,6 +214,9 @@ pub trait Flow: fmt::Show + ToString + Sync {
|
|||
/// Phase 5 of reflow: builds display lists.
|
||||
fn build_display_list(&mut self, layout_context: &LayoutContext);
|
||||
|
||||
/// Perform an iteration of fragment bounds on this flow.
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator);
|
||||
|
||||
fn compute_collapsible_block_start_margin(&mut self,
|
||||
_layout_context: &mut LayoutContext,
|
||||
_margin_collapse_info: &mut MarginCollapseInfo) {
|
||||
|
@ -943,6 +946,14 @@ impl BaseFlow {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn child_fragment_absolute_position(&self, fragment: &Fragment) -> Point2D<Au> {
|
||||
let relative_offset =
|
||||
fragment.relative_position(&self
|
||||
.absolute_position_info
|
||||
.relative_containing_block_size);
|
||||
self.abs_position.add_size(&relative_offset.to_physical(self.writing_mode))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ImmutableFlowUtils for &'a Flow + 'a {
|
||||
|
|
|
@ -22,7 +22,7 @@ use text;
|
|||
use util::OpaqueNodeMethods;
|
||||
use wrapper::{TLayoutNode, ThreadSafeLayoutNode};
|
||||
|
||||
use geom::Size2D;
|
||||
use geom::{Point2D, Rect, Size2D};
|
||||
use gfx::display_list::OpaqueNode;
|
||||
use gfx::text::glyph::CharIndex;
|
||||
use gfx::text::text_run::TextRun;
|
||||
|
@ -1482,6 +1482,13 @@ impl Fragment {
|
|||
pub fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
|
||||
self.style = (*new_style).clone()
|
||||
}
|
||||
|
||||
pub fn abs_bounds_from_origin(&self, fragment_origin: &Point2D<Au>) -> Rect<Au> {
|
||||
// FIXME(#2795): Get the real container size
|
||||
let container_size = Size2D::zero();
|
||||
self.border_box.to_physical(self.style.writing_mode, container_size)
|
||||
.translate(fragment_origin)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Show for Fragment {
|
||||
|
@ -1502,3 +1509,13 @@ bitflags! {
|
|||
static IntrinsicInlineSizeIncludesSpecified = 0x08,
|
||||
}
|
||||
}
|
||||
|
||||
/// A top-down fragment bounds iteration handler.
|
||||
pub trait FragmentBoundsIterator {
|
||||
/// The operation to perform.
|
||||
fn process(&mut self, fragment: &Fragment, bounds: Rect<Au>);
|
||||
|
||||
/// Returns true if this fragment must be processed in-order. If this returns false,
|
||||
/// we skip the operation for this fragment, but continue processing siblings.
|
||||
fn should_process(&mut self, fragment: &Fragment) -> bool;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ use floats::{FloatLeft, Floats, PlacementInfo};
|
|||
use flow::{BaseFlow, FlowClass, Flow, InlineFlowClass, MutableFlowUtils};
|
||||
use flow;
|
||||
use fragment::{Fragment, InlineAbsoluteHypotheticalFragment, InlineBlockFragment};
|
||||
use fragment::{ScannedTextFragment, ScannedTextFragmentInfo, SplitInfo};
|
||||
use fragment::{FragmentBoundsIterator, ScannedTextFragment, ScannedTextFragmentInfo};
|
||||
use fragment::SplitInfo;
|
||||
use incremental::{Reflow, ReflowOutOfFlow};
|
||||
use layout_debug;
|
||||
use model::IntrinsicISizesContribution;
|
||||
|
@ -1195,15 +1196,10 @@ impl Flow for InlineFlow {
|
|||
debug!("Flow: building display list for {:u} inline fragments", self.fragments.len());
|
||||
|
||||
for fragment in self.fragments.fragments.iter_mut() {
|
||||
let rel_offset = fragment.relative_position(&self.base
|
||||
.absolute_position_info
|
||||
.relative_containing_block_size);
|
||||
let fragment_position = self.base
|
||||
.abs_position
|
||||
.add_size(&rel_offset.to_physical(self.base.writing_mode));
|
||||
let fragment_origin = self.base.child_fragment_absolute_position(fragment);
|
||||
fragment.build_display_list(&mut self.base.display_list,
|
||||
layout_context,
|
||||
fragment_position,
|
||||
fragment_origin,
|
||||
ContentLevel,
|
||||
&self.base.clip_rect);
|
||||
match fragment.specific {
|
||||
|
@ -1223,6 +1219,15 @@ impl Flow for InlineFlow {
|
|||
}
|
||||
|
||||
fn repair_style(&mut self, _: &Arc<ComputedValues>) {}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
for fragment in self.fragments.fragments.iter() {
|
||||
if iterator.should_process(fragment) {
|
||||
let fragment_origin = self.base.child_fragment_absolute_position(fragment);
|
||||
iterator.process(fragment, fragment.abs_bounds_from_origin(&fragment_origin));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Show for InlineFlow {
|
||||
|
|
|
@ -10,6 +10,7 @@ use construct::FlowConstructionResult;
|
|||
use context::SharedLayoutContext;
|
||||
use flow::{mod, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
|
||||
use flow_ref::FlowRef;
|
||||
use fragment::{Fragment, FragmentBoundsIterator};
|
||||
use incremental::{LayoutDamageComputation, Reflow, ReflowEntireDocument, Repaint};
|
||||
use layout_debug;
|
||||
use parallel::UnsafeFlow;
|
||||
|
@ -24,7 +25,7 @@ use encoding::all::UTF_8;
|
|||
use geom::point::Point2D;
|
||||
use geom::rect::Rect;
|
||||
use geom::size::Size2D;
|
||||
use gfx::display_list::{ContentStackingLevel, DisplayItem, DisplayItemIterator, DisplayList};
|
||||
use gfx::display_list::{ContentStackingLevel, DisplayItem, DisplayList};
|
||||
use gfx::display_list::{OpaqueNode};
|
||||
use gfx::render_task::{RenderInitMsg, RenderChan, RenderLayer};
|
||||
use gfx::{render_task, color};
|
||||
|
@ -34,12 +35,12 @@ use log;
|
|||
use script::dom::bindings::js::JS;
|
||||
use script::dom::node::{ElementNodeTypeId, LayoutDataRef, Node};
|
||||
use script::dom::element::{HTMLBodyElementTypeId, HTMLHtmlElementTypeId};
|
||||
use script::layout_interface::{AddStylesheetMsg, LoadStylesheetMsg, ScriptLayoutChan};
|
||||
use script::layout_interface::{TrustedNodeAddress, ContentBoxesResponse, ExitNowMsg};
|
||||
use script::layout_interface::{ContentBoxResponse, HitTestResponse, MouseOverResponse};
|
||||
use script::layout_interface::{LayoutChan, Msg, PrepareToExitMsg};
|
||||
use script::layout_interface::{GetRPCMsg, LayoutRPC, ReapLayoutDataMsg, Reflow};
|
||||
use script::layout_interface::{ReflowForDisplay, ReflowMsg};
|
||||
use script::layout_interface::{
|
||||
AddStylesheetMsg, ContentBoxResponse, ContentBoxesResponse, ContentBoxesQuery,
|
||||
ContentBoxQuery, ExitNowMsg, GetRPCMsg, HitTestResponse, LayoutChan, LayoutRPC,
|
||||
LoadStylesheetMsg, MouseOverResponse, Msg, NoQuery, PrepareToExitMsg, ReapLayoutDataMsg,
|
||||
Reflow, ReflowForDisplay, ReflowMsg, ScriptLayoutChan, TrustedNodeAddress,
|
||||
};
|
||||
use script_traits::{SendEventMsg, ReflowEvent, ReflowCompleteMsg, OpaqueScriptLayoutChannel};
|
||||
use script_traits::{ScriptControlChan, UntrustedNodeAddress};
|
||||
use servo_msg::compositor_msg::Scrollable;
|
||||
|
@ -95,6 +96,12 @@ pub struct LayoutTaskData {
|
|||
/// True if a style sheet was added since the last reflow. Currently, this causes all nodes to
|
||||
/// be dirtied at the next reflow.
|
||||
pub stylesheet_dirty: bool,
|
||||
|
||||
/// A queued response for the union of the content boxes of a node.
|
||||
pub content_box_response: Rect<Au>,
|
||||
|
||||
/// A queued response for the content boxes of a node.
|
||||
pub content_boxes_response: Vec<Rect<Au>>,
|
||||
}
|
||||
|
||||
/// Information needed by the layout task.
|
||||
|
@ -284,6 +291,8 @@ impl LayoutTask {
|
|||
dirty: Rect::zero(),
|
||||
generation: 0,
|
||||
stylesheet_dirty: false,
|
||||
content_box_response: Rect::zero(),
|
||||
content_boxes_response: Vec::new(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
@ -587,6 +596,124 @@ impl LayoutTask {
|
|||
fn verify_flow_tree(&self, _: &mut FlowRef) {
|
||||
}
|
||||
|
||||
fn process_content_box_request<'a>(&'a self,
|
||||
requested_node: TrustedNodeAddress,
|
||||
layout_root: &mut FlowRef,
|
||||
rw_data: &mut RWGuard<'a>) {
|
||||
let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node);
|
||||
let mut iterator = UnioningFragmentBoundsIterator::new(requested_node);
|
||||
sequential::iterate_through_flow_tree_fragment_bounds(layout_root, &mut iterator);
|
||||
rw_data.content_box_response = iterator.rect;
|
||||
}
|
||||
|
||||
fn process_content_boxes_request<'a>(&'a self,
|
||||
requested_node: TrustedNodeAddress,
|
||||
layout_root: &mut FlowRef,
|
||||
rw_data: &mut RWGuard<'a>) {
|
||||
let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node);
|
||||
let mut iterator = CollectingFragmentBoundsIterator::new(requested_node);
|
||||
sequential::iterate_through_flow_tree_fragment_bounds(layout_root, &mut iterator);
|
||||
rw_data.content_boxes_response = iterator.rects;
|
||||
}
|
||||
|
||||
fn build_display_list_for_reflow<'a>(&'a self,
|
||||
data: &Reflow,
|
||||
node: &mut LayoutNode,
|
||||
layout_root: &mut FlowRef,
|
||||
shared_layout_ctx: &mut SharedLayoutContext,
|
||||
rw_data: &mut RWGuard<'a>) {
|
||||
let writing_mode = flow::base(layout_root.deref()).writing_mode;
|
||||
profile(time::LayoutDispListBuildCategory,
|
||||
Some((&data.url, data.iframe, self.first_reflow.get())),
|
||||
self.time_profiler_chan.clone(),
|
||||
|| {
|
||||
shared_layout_ctx.dirty =
|
||||
flow::base(layout_root.deref()).position.to_physical(writing_mode,
|
||||
rw_data.screen_size);
|
||||
flow::mut_base(layout_root.deref_mut()).abs_position =
|
||||
LogicalPoint::zero(writing_mode).to_physical(writing_mode,
|
||||
rw_data.screen_size);
|
||||
|
||||
let rw_data = rw_data.deref_mut();
|
||||
match rw_data.parallel_traversal {
|
||||
None => {
|
||||
sequential::build_display_list_for_subtree(layout_root, shared_layout_ctx);
|
||||
}
|
||||
Some(ref mut traversal) => {
|
||||
parallel::build_display_list_for_subtree(layout_root,
|
||||
&data.url,
|
||||
data.iframe,
|
||||
self.first_reflow.get(),
|
||||
self.time_profiler_chan.clone(),
|
||||
shared_layout_ctx,
|
||||
traversal);
|
||||
}
|
||||
}
|
||||
|
||||
debug!("Done building display list. Display List = {}",
|
||||
flow::base(layout_root.deref()).display_list);
|
||||
|
||||
flow::mut_base(layout_root.deref_mut()).display_list.flatten(ContentStackingLevel);
|
||||
let display_list =
|
||||
Arc::new(mem::replace(&mut flow::mut_base(layout_root.deref_mut()).display_list,
|
||||
DisplayList::new()));
|
||||
|
||||
// FIXME(pcwalton): This is really ugly and can't handle overflow: scroll. Refactor
|
||||
// it with extreme prejudice.
|
||||
let mut color = color::rgba(1.0, 1.0, 1.0, 1.0);
|
||||
for child in node.traverse_preorder() {
|
||||
if child.type_id() == Some(ElementNodeTypeId(HTMLHtmlElementTypeId)) ||
|
||||
child.type_id() == Some(ElementNodeTypeId(HTMLBodyElementTypeId)) {
|
||||
let element_bg_color = {
|
||||
let thread_safe_child = ThreadSafeLayoutNode::new(&child);
|
||||
thread_safe_child.style()
|
||||
.resolve_color(thread_safe_child.style()
|
||||
.get_background()
|
||||
.background_color)
|
||||
.to_gfx_color()
|
||||
};
|
||||
match element_bg_color {
|
||||
color::rgba(0., 0., 0., 0.) => {}
|
||||
_ => {
|
||||
color = element_bg_color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let root_size = {
|
||||
let root_flow = flow::base(layout_root.deref());
|
||||
root_flow.position.size.to_physical(root_flow.writing_mode)
|
||||
};
|
||||
let root_size = Size2D(root_size.width.to_nearest_px() as uint,
|
||||
root_size.height.to_nearest_px() as uint);
|
||||
let render_layer = RenderLayer {
|
||||
id: layout_root.layer_id(0),
|
||||
display_list: display_list.clone(),
|
||||
position: Rect(Point2D(0u, 0u), root_size),
|
||||
background_color: color,
|
||||
scroll_policy: Scrollable,
|
||||
};
|
||||
|
||||
rw_data.display_list = Some(display_list);
|
||||
|
||||
// TODO(pcwalton): Eventually, when we have incremental reflow, this will have to
|
||||
// be smarter in order to handle retained layer contents properly from reflow to
|
||||
// reflow.
|
||||
let mut layers = SmallVec1::new();
|
||||
layers.push(render_layer);
|
||||
for layer in mem::replace(&mut flow::mut_base(layout_root.deref_mut()).layers,
|
||||
DList::new()).into_iter() {
|
||||
layers.push(layer)
|
||||
}
|
||||
|
||||
debug!("Layout done!");
|
||||
|
||||
self.render_chan.send(RenderInitMsg(layers));
|
||||
});
|
||||
}
|
||||
|
||||
/// The high-level routine that performs layout tasks.
|
||||
fn handle_reflow<'a>(&'a self,
|
||||
data: &Reflow,
|
||||
|
@ -713,97 +840,19 @@ impl LayoutTask {
|
|||
|
||||
// Build the display list if necessary, and send it to the renderer.
|
||||
if data.goal == ReflowForDisplay {
|
||||
let writing_mode = flow::base(layout_root.deref()).writing_mode;
|
||||
profile(time::LayoutDispListBuildCategory,
|
||||
Some((&data.url, data.iframe, self.first_reflow.get())),
|
||||
self.time_profiler_chan.clone(),
|
||||
|| {
|
||||
shared_layout_ctx.dirty =
|
||||
flow::base(layout_root.deref()).position.to_physical(writing_mode,
|
||||
rw_data.screen_size);
|
||||
flow::mut_base(layout_root.deref_mut()).abs_position =
|
||||
LogicalPoint::zero(writing_mode).to_physical(writing_mode,
|
||||
rw_data.screen_size);
|
||||
|
||||
let rw_data = rw_data.deref_mut();
|
||||
match rw_data.parallel_traversal {
|
||||
None => {
|
||||
sequential::build_display_list_for_subtree(&mut layout_root,
|
||||
&shared_layout_ctx);
|
||||
}
|
||||
Some(ref mut traversal) => {
|
||||
parallel::build_display_list_for_subtree(&mut layout_root,
|
||||
&data.url,
|
||||
data.iframe,
|
||||
self.first_reflow.get(),
|
||||
self.time_profiler_chan.clone(),
|
||||
&shared_layout_ctx,
|
||||
traversal);
|
||||
}
|
||||
self.build_display_list_for_reflow(data,
|
||||
node,
|
||||
&mut layout_root,
|
||||
&mut shared_layout_ctx,
|
||||
&mut rw_data);
|
||||
}
|
||||
|
||||
debug!("Done building display list. Display List = {}",
|
||||
flow::base(layout_root.deref()).display_list);
|
||||
|
||||
flow::mut_base(&mut *layout_root).display_list.flatten(ContentStackingLevel);
|
||||
let display_list =
|
||||
Arc::new(mem::replace(&mut flow::mut_base(&mut *layout_root).display_list,
|
||||
DisplayList::new()));
|
||||
|
||||
// FIXME(pcwalton): This is really ugly and can't handle overflow: scroll. Refactor
|
||||
// it with extreme prejudice.
|
||||
let mut color = color::rgba(1.0, 1.0, 1.0, 1.0);
|
||||
for child in node.traverse_preorder() {
|
||||
if child.type_id() == Some(ElementNodeTypeId(HTMLHtmlElementTypeId)) ||
|
||||
child.type_id() == Some(ElementNodeTypeId(HTMLBodyElementTypeId)) {
|
||||
let element_bg_color = {
|
||||
let thread_safe_child = ThreadSafeLayoutNode::new(&child);
|
||||
thread_safe_child.style()
|
||||
.resolve_color(thread_safe_child.style()
|
||||
.get_background()
|
||||
.background_color)
|
||||
.to_gfx_color()
|
||||
};
|
||||
match element_bg_color {
|
||||
color::rgba(0., 0., 0., 0.) => {}
|
||||
_ => {
|
||||
color = element_bg_color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let root_size = {
|
||||
let root_flow = flow::base(layout_root.deref());
|
||||
root_flow.position.size.to_physical(root_flow.writing_mode)
|
||||
};
|
||||
let root_size = Size2D(root_size.width.to_nearest_px() as uint,
|
||||
root_size.height.to_nearest_px() as uint);
|
||||
let render_layer = RenderLayer {
|
||||
id: layout_root.layer_id(0),
|
||||
display_list: display_list.clone(),
|
||||
position: Rect(Point2D(0u, 0u), root_size),
|
||||
background_color: color,
|
||||
scroll_policy: Scrollable,
|
||||
};
|
||||
|
||||
rw_data.display_list = Some(display_list);
|
||||
|
||||
// TODO(pcwalton): Eventually, when we have incremental reflow, this will have to
|
||||
// be smarter in order to handle retained layer contents properly from reflow to
|
||||
// reflow.
|
||||
let mut layers = SmallVec1::new();
|
||||
layers.push(render_layer);
|
||||
for layer in mem::replace(&mut flow::mut_base(layout_root.deref_mut()).layers,
|
||||
DList::new()).into_iter() {
|
||||
layers.push(layer)
|
||||
}
|
||||
|
||||
debug!("Layout done!");
|
||||
|
||||
self.render_chan.send(RenderInitMsg(layers));
|
||||
});
|
||||
match data.query_type {
|
||||
ContentBoxQuery(node) =>
|
||||
self.process_content_box_request(node, &mut layout_root, &mut rw_data),
|
||||
ContentBoxesQuery(node) =>
|
||||
self.process_content_boxes_request(node, &mut layout_root, &mut rw_data),
|
||||
NoQuery => {},
|
||||
}
|
||||
|
||||
self.first_reflow.set(false);
|
||||
|
@ -876,61 +925,17 @@ struct LayoutRPCImpl(Arc<Mutex<LayoutTaskData>>);
|
|||
impl LayoutRPC for LayoutRPCImpl {
|
||||
// The neat thing here is that in order to answer the following two queries we only
|
||||
// need to compare nodes for equality. Thus we can safely work only with `OpaqueNode`.
|
||||
fn content_box(&self, node: TrustedNodeAddress) -> ContentBoxResponse {
|
||||
let node: OpaqueNode = OpaqueNodeMethods::from_script_node(node);
|
||||
fn union_boxes_for_node(accumulator: &mut Option<Rect<Au>>,
|
||||
mut iter: DisplayItemIterator,
|
||||
node: OpaqueNode) {
|
||||
for item in iter {
|
||||
if item.base().node == node {
|
||||
match *accumulator {
|
||||
None => *accumulator = Some(item.base().bounds),
|
||||
Some(ref mut acc) => *acc = acc.union(&item.base().bounds),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut rect = None;
|
||||
{
|
||||
fn content_box(&self) -> ContentBoxResponse {
|
||||
let &LayoutRPCImpl(ref rw_data) = self;
|
||||
let rw_data = rw_data.lock();
|
||||
match rw_data.display_list {
|
||||
None => fail!("no display list!"),
|
||||
Some(ref display_list) => {
|
||||
union_boxes_for_node(&mut rect, display_list.iter(), node)
|
||||
}
|
||||
}
|
||||
}
|
||||
ContentBoxResponse(rect.unwrap_or(Rect::zero()))
|
||||
ContentBoxResponse(rw_data.content_box_response)
|
||||
}
|
||||
|
||||
/// Requests the dimensions of all the content boxes, as in the `getClientRects()` call.
|
||||
fn content_boxes(&self, node: TrustedNodeAddress) -> ContentBoxesResponse {
|
||||
let node: OpaqueNode = OpaqueNodeMethods::from_script_node(node);
|
||||
|
||||
fn add_boxes_for_node(accumulator: &mut Vec<Rect<Au>>,
|
||||
mut iter: DisplayItemIterator,
|
||||
node: OpaqueNode) {
|
||||
for item in iter {
|
||||
if item.base().node == node {
|
||||
accumulator.push(item.base().bounds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut boxes = vec!();
|
||||
{
|
||||
fn content_boxes(&self) -> ContentBoxesResponse {
|
||||
let &LayoutRPCImpl(ref rw_data) = self;
|
||||
let rw_data = rw_data.lock();
|
||||
match rw_data.display_list {
|
||||
None => fail!("no display list!"),
|
||||
Some(ref display_list) => {
|
||||
add_boxes_for_node(&mut boxes, display_list.iter(), node)
|
||||
}
|
||||
}
|
||||
}
|
||||
ContentBoxesResponse(boxes)
|
||||
let mut rw_data = rw_data.lock();
|
||||
ContentBoxesResponse(rw_data.content_boxes_response.clone())
|
||||
}
|
||||
|
||||
/// Requests the node containing the point of interest
|
||||
|
@ -997,3 +1002,55 @@ impl LayoutRPC for LayoutRPCImpl {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct UnioningFragmentBoundsIterator {
|
||||
node_address: OpaqueNode,
|
||||
rect: Rect<Au>,
|
||||
}
|
||||
|
||||
impl UnioningFragmentBoundsIterator {
|
||||
fn new(node_address: OpaqueNode) -> UnioningFragmentBoundsIterator {
|
||||
UnioningFragmentBoundsIterator {
|
||||
node_address: node_address,
|
||||
rect: Rect::zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FragmentBoundsIterator for UnioningFragmentBoundsIterator {
|
||||
fn process(&mut self, _: &Fragment, bounds: Rect<Au>) {
|
||||
if self.rect.is_empty() {
|
||||
self.rect = bounds;
|
||||
} else {
|
||||
self.rect = self.rect.union(&bounds);
|
||||
}
|
||||
}
|
||||
|
||||
fn should_process(&mut self, fragment: &Fragment) -> bool {
|
||||
self.node_address == fragment.node
|
||||
}
|
||||
}
|
||||
|
||||
struct CollectingFragmentBoundsIterator {
|
||||
node_address: OpaqueNode,
|
||||
rects: Vec<Rect<Au>>,
|
||||
}
|
||||
|
||||
impl CollectingFragmentBoundsIterator {
|
||||
fn new(node_address: OpaqueNode) -> CollectingFragmentBoundsIterator {
|
||||
CollectingFragmentBoundsIterator {
|
||||
node_address: node_address,
|
||||
rects: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FragmentBoundsIterator for CollectingFragmentBoundsIterator {
|
||||
fn process(&mut self, _: &Fragment, bounds: Rect<Au>) {
|
||||
self.rects.push(bounds);
|
||||
}
|
||||
|
||||
fn should_process(&mut self, fragment: &Fragment) -> bool {
|
||||
self.node_address == fragment.node
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use context::{LayoutContext, SharedLayoutContext};
|
|||
use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal};
|
||||
use flow;
|
||||
use flow_ref::FlowRef;
|
||||
use fragment::FragmentBoundsIterator;
|
||||
use servo_util::opts;
|
||||
use traversal::{BubbleISizes, RecalcStyleForNode, ConstructFlows};
|
||||
use traversal::{AssignBSizesAndStoreOverflow, AssignISizes};
|
||||
|
@ -92,3 +93,16 @@ pub fn build_display_list_for_subtree(root: &mut FlowRef,
|
|||
|
||||
doit(root.deref_mut(), compute_absolute_positions, build_display_list);
|
||||
}
|
||||
|
||||
pub fn iterate_through_flow_tree_fragment_bounds(root: &mut FlowRef,
|
||||
iterator: &mut FragmentBoundsIterator) {
|
||||
fn doit(flow: &mut Flow, iterator: &mut FragmentBoundsIterator) {
|
||||
flow.iterate_through_fragment_bounds(iterator);
|
||||
|
||||
for kid in flow::mut_base(flow).child_iter() {
|
||||
doit(kid, iterator);
|
||||
}
|
||||
}
|
||||
|
||||
doit(root.deref_mut(), iterator);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ use construct::FlowConstructor;
|
|||
use context::LayoutContext;
|
||||
use floats::FloatKind;
|
||||
use flow::{TableFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
||||
use fragment::Fragment;
|
||||
use fragment::{Fragment, FragmentBoundsIterator};
|
||||
use layout_debug;
|
||||
use model::{IntrinsicISizes, IntrinsicISizesContribution};
|
||||
use table_wrapper::{TableLayout, FixedLayout, AutoLayout};
|
||||
|
@ -327,6 +327,10 @@ impl Flow for TableFlow {
|
|||
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
|
||||
self.block_flow.repair_style(new_style)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
self.block_flow.iterate_through_fragment_bounds(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Show for TableFlow {
|
||||
|
|
|
@ -10,6 +10,7 @@ use block::BlockFlow;
|
|||
use construct::FlowConstructor;
|
||||
use context::LayoutContext;
|
||||
use flow::{TableCaptionFlowClass, FlowClass, Flow};
|
||||
use fragment::FragmentBoundsIterator;
|
||||
use wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
use servo_util::geometry::Au;
|
||||
|
@ -79,6 +80,10 @@ impl Flow for TableCaptionFlow {
|
|||
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
|
||||
self.block_flow.repair_style(new_style)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
self.iterate_through_fragment_bounds(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Show for TableCaptionFlow {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
use block::{BlockFlow, MarginsMayNotCollapse, ISizeAndMarginsComputer};
|
||||
use context::LayoutContext;
|
||||
use flow::{TableCellFlowClass, FlowClass, Flow};
|
||||
use fragment::Fragment;
|
||||
use fragment::{Fragment, FragmentBoundsIterator};
|
||||
use model::{MaybeAuto};
|
||||
use layout_debug;
|
||||
use table::InternalTable;
|
||||
|
@ -148,6 +148,10 @@ impl Flow for TableCellFlow {
|
|||
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
|
||||
self.block_flow.repair_style(new_style)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
self.block_flow.iterate_through_fragment_bounds(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Show for TableCellFlow {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
use context::LayoutContext;
|
||||
use css::node_style::StyledNode;
|
||||
use flow::{BaseFlow, TableColGroupFlowClass, FlowClass, Flow};
|
||||
use fragment::{Fragment, TableColumnFragment};
|
||||
use fragment::{Fragment, FragmentBoundsIterator, TableColumnFragment};
|
||||
use layout_debug;
|
||||
use wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
|
@ -95,6 +95,9 @@ impl Flow for TableColGroupFlow {
|
|||
fn build_display_list(&mut self, _: &LayoutContext) {}
|
||||
|
||||
fn repair_style(&mut self, _: &Arc<ComputedValues>) {}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, _: &mut FragmentBoundsIterator) {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Show for TableColGroupFlow {
|
||||
|
|
|
@ -12,7 +12,7 @@ use construct::FlowConstructor;
|
|||
use context::LayoutContext;
|
||||
use flow::{TableRowFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
||||
use flow;
|
||||
use fragment::Fragment;
|
||||
use fragment::{Fragment, FragmentBoundsIterator};
|
||||
use layout_debug;
|
||||
use table::{ColumnInlineSize, InternalTable};
|
||||
use model::{MaybeAuto, Specified, Auto};
|
||||
|
@ -251,6 +251,10 @@ impl Flow for TableRowFlow {
|
|||
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
|
||||
self.block_flow.repair_style(new_style)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
self.block_flow.iterate_through_fragment_bounds(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Show for TableRowFlow {
|
||||
|
|
|
@ -12,7 +12,7 @@ use construct::FlowConstructor;
|
|||
use context::LayoutContext;
|
||||
use flow::{TableRowGroupFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
||||
use flow;
|
||||
use fragment::Fragment;
|
||||
use fragment::{Fragment, FragmentBoundsIterator};
|
||||
use layout_debug;
|
||||
use model::IntrinsicISizesContribution;
|
||||
use table::{ColumnInlineSize, InternalTable, TableFlow};
|
||||
|
@ -211,6 +211,10 @@ impl Flow for TableRowGroupFlow {
|
|||
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
|
||||
self.block_flow.repair_style(new_style)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
self.block_flow.iterate_through_fragment_bounds(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Show for TableRowGroupFlow {
|
||||
|
|
|
@ -19,7 +19,7 @@ use construct::FlowConstructor;
|
|||
use context::LayoutContext;
|
||||
use floats::FloatKind;
|
||||
use flow::{TableWrapperFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
||||
use fragment::Fragment;
|
||||
use fragment::{Fragment, FragmentBoundsIterator};
|
||||
use table::ColumnInlineSize;
|
||||
use wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
|
@ -334,6 +334,10 @@ impl Flow for TableWrapperFlow {
|
|||
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
|
||||
self.block_flow.repair_style(new_style)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
self.block_flow.iterate_through_fragment_bounds(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Show for TableWrapperFlow {
|
||||
|
|
|
@ -45,8 +45,7 @@ use dom::text::Text;
|
|||
use dom::virtualmethods::{VirtualMethods, vtable_for};
|
||||
use dom::window::Window;
|
||||
use geom::rect::Rect;
|
||||
use layout_interface::{ContentBoxResponse, ContentBoxesResponse, LayoutRPC,
|
||||
LayoutChan, ReapLayoutDataMsg};
|
||||
use layout_interface::{LayoutChan, ReapLayoutDataMsg};
|
||||
use devtools_traits::NodeInfo;
|
||||
use script_traits::UntrustedNodeAddress;
|
||||
use servo_util::geometry::Au;
|
||||
|
@ -689,20 +688,11 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
|
|||
}
|
||||
|
||||
fn get_bounding_content_box(self) -> Rect<Au> {
|
||||
let window = window_from_node(self).root();
|
||||
let page = window.page();
|
||||
let addr = self.to_trusted_node_address();
|
||||
|
||||
let ContentBoxResponse(rect) = page.layout().content_box(addr);
|
||||
rect
|
||||
window_from_node(self).root().page().content_box_query(self.to_trusted_node_address())
|
||||
}
|
||||
|
||||
fn get_content_boxes(self) -> Vec<Rect<Au>> {
|
||||
let window = window_from_node(self).root();
|
||||
let page = window.page();
|
||||
let addr = self.to_trusted_node_address();
|
||||
let ContentBoxesResponse(rects) = page.layout().content_boxes(addr);
|
||||
rects
|
||||
window_from_node(self).root().page().content_boxes_query(self.to_trusted_node_address())
|
||||
}
|
||||
|
||||
// http://dom.spec.whatwg.org/#dom-parentnode-queryselector
|
||||
|
|
|
@ -19,7 +19,7 @@ use dom::location::Location;
|
|||
use dom::navigator::Navigator;
|
||||
use dom::performance::Performance;
|
||||
use dom::screen::Screen;
|
||||
use layout_interface::ReflowGoal;
|
||||
use layout_interface::NoQuery;
|
||||
use page::Page;
|
||||
use script_task::{ExitWindowMsg, ScriptChan, TriggerLoadMsg, TriggerFragmentMsg};
|
||||
use script_task::FromWindow;
|
||||
|
@ -312,7 +312,7 @@ impl Reflectable for Window {
|
|||
|
||||
pub trait WindowHelpers {
|
||||
fn reflow(self);
|
||||
fn flush_layout(self, goal: ReflowGoal);
|
||||
fn flush_layout(self);
|
||||
fn wait_until_safe_to_modify_dom(self);
|
||||
fn init_browser_context(self, doc: JSRef<Document>);
|
||||
fn load_url(self, href: DOMString);
|
||||
|
@ -350,8 +350,8 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
|
|||
self.page().damage();
|
||||
}
|
||||
|
||||
fn flush_layout(self, goal: ReflowGoal) {
|
||||
self.page().flush_layout(goal);
|
||||
fn flush_layout(self) {
|
||||
self.page().flush_layout(NoQuery);
|
||||
}
|
||||
|
||||
fn wait_until_safe_to_modify_dom(self) {
|
||||
|
|
|
@ -60,9 +60,9 @@ pub enum Msg {
|
|||
// 3) and really needs to be fast.
|
||||
pub trait LayoutRPC {
|
||||
/// Requests the dimensions of the content box, as in the `getBoundingClientRect()` call.
|
||||
fn content_box(&self, node: TrustedNodeAddress) -> ContentBoxResponse;
|
||||
fn content_box(&self) -> ContentBoxResponse;
|
||||
/// Requests the dimensions of all the content boxes, as in the `getClientRects()` call.
|
||||
fn content_boxes(&self, node: TrustedNodeAddress) -> ContentBoxesResponse;
|
||||
fn content_boxes(&self) -> ContentBoxesResponse;
|
||||
/// Requests the node containing the point of interest
|
||||
fn hit_test(&self, node: TrustedNodeAddress, point: Point2D<f32>) -> Result<HitTestResponse, ()>;
|
||||
fn mouse_over(&self, node: TrustedNodeAddress, point: Point2D<f32>) -> Result<MouseOverResponse, ()>;
|
||||
|
@ -82,6 +82,13 @@ pub enum ReflowGoal {
|
|||
ReflowForScriptQuery,
|
||||
}
|
||||
|
||||
/// Any query to perform with this reflow.
|
||||
pub enum ReflowQueryType {
|
||||
NoQuery,
|
||||
ContentBoxQuery(TrustedNodeAddress),
|
||||
ContentBoxesQuery(TrustedNodeAddress),
|
||||
}
|
||||
|
||||
/// Information needed for a reflow.
|
||||
pub struct Reflow {
|
||||
/// The document node.
|
||||
|
@ -99,7 +106,9 @@ pub struct Reflow {
|
|||
/// The channel that we send a notification to.
|
||||
pub script_join_chan: Sender<()>,
|
||||
/// Unique identifier
|
||||
pub id: uint
|
||||
pub id: uint,
|
||||
/// The type of query if any to perform during this reflow.
|
||||
pub query_type: ReflowQueryType,
|
||||
}
|
||||
|
||||
/// Encapsulates a channel to the layout task.
|
||||
|
|
|
@ -11,19 +11,22 @@ use dom::document::{Document, DocumentHelpers};
|
|||
use dom::element::Element;
|
||||
use dom::node::{Node, NodeHelpers};
|
||||
use dom::window::Window;
|
||||
use layout_interface::{ReflowForDisplay};
|
||||
use layout_interface::{HitTestResponse, MouseOverResponse};
|
||||
use layout_interface::{GetRPCMsg, LayoutChan, LayoutRPC};
|
||||
use layout_interface::{Reflow, ReflowGoal, ReflowMsg};
|
||||
use layout_interface::{
|
||||
ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery, ContentBoxesResponse,
|
||||
GetRPCMsg, HitTestResponse, LayoutChan, LayoutRPC, MouseOverResponse, NoQuery,
|
||||
Reflow, ReflowForDisplay, ReflowForScriptQuery, ReflowGoal, ReflowMsg,
|
||||
ReflowQueryType, TrustedNodeAddress
|
||||
};
|
||||
use script_traits::{UntrustedNodeAddress, ScriptControlChan};
|
||||
|
||||
use geom::point::Point2D;
|
||||
use geom::{Point2D, Rect};
|
||||
use js::rust::Cx;
|
||||
use servo_msg::compositor_msg::PerformingLayout;
|
||||
use servo_msg::compositor_msg::ScriptListener;
|
||||
use servo_msg::constellation_msg::{ConstellationChan, WindowSizeData};
|
||||
use servo_msg::constellation_msg::{PipelineId, SubpageId};
|
||||
use servo_net::resource_task::ResourceTask;
|
||||
use servo_util::geometry::Au;
|
||||
use servo_util::str::DOMString;
|
||||
use servo_util::smallvec::{SmallVec1, SmallVec};
|
||||
use std::cell::Cell;
|
||||
|
@ -164,26 +167,48 @@ impl Page {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn flush_layout(&self, goal: ReflowGoal) {
|
||||
if self.damaged.get() {
|
||||
pub fn flush_layout(&self, query: ReflowQueryType) {
|
||||
// If we are damaged, we need to force a full reflow, so that queries interact with
|
||||
// an accurate flow tree.
|
||||
let (reflow_goal, force_reflow) = if self.damaged.get() {
|
||||
(ReflowForDisplay, true)
|
||||
} else {
|
||||
match query {
|
||||
ContentBoxQuery(_) | ContentBoxesQuery(_) => (ReflowForScriptQuery, true),
|
||||
NoQuery => (ReflowForDisplay, false),
|
||||
}
|
||||
};
|
||||
|
||||
if force_reflow {
|
||||
let frame = self.frame();
|
||||
let window = frame.as_ref().unwrap().window.root();
|
||||
self.reflow(goal, window.control_chan().clone(), window.compositor());
|
||||
self.reflow(reflow_goal, window.control_chan().clone(), window.compositor(), query);
|
||||
} else {
|
||||
self.avoided_reflows.set(self.avoided_reflows.get() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn layout(&self) -> &LayoutRPC {
|
||||
// FIXME This should probably be ReflowForQuery, not Display. All queries currently
|
||||
// currently rely on the display list, which means we can't destroy it by
|
||||
// doing a query reflow.
|
||||
self.flush_layout(ReflowForDisplay);
|
||||
self.flush_layout(NoQuery);
|
||||
self.join_layout(); //FIXME: is this necessary, or is layout_rpc's mutex good enough?
|
||||
let layout_rpc: &LayoutRPC = &*self.layout_rpc;
|
||||
layout_rpc
|
||||
}
|
||||
|
||||
pub fn content_box_query(&self, content_box_request: TrustedNodeAddress) -> Rect<Au> {
|
||||
self.flush_layout(ContentBoxQuery(content_box_request));
|
||||
self.join_layout(); //FIXME: is this necessary, or is layout_rpc's mutex good enough?
|
||||
let ContentBoxResponse(rect) = self.layout_rpc.content_box();
|
||||
rect
|
||||
}
|
||||
|
||||
pub fn content_boxes_query(&self, content_boxes_request: TrustedNodeAddress) -> Vec<Rect<Au>> {
|
||||
self.flush_layout(ContentBoxesQuery(content_boxes_request));
|
||||
self.join_layout(); //FIXME: is this necessary, or is layout_rpc's mutex good enough?
|
||||
let ContentBoxesResponse(rects) = self.layout_rpc.content_boxes();
|
||||
rects
|
||||
}
|
||||
|
||||
// must handle root case separately
|
||||
pub fn remove(&self, id: PipelineId) -> Option<Rc<Page>> {
|
||||
let remove_idx = {
|
||||
|
@ -303,7 +328,8 @@ impl Page {
|
|||
pub fn reflow(&self,
|
||||
goal: ReflowGoal,
|
||||
script_chan: ScriptControlChan,
|
||||
compositor: &ScriptListener) {
|
||||
compositor: &ScriptListener,
|
||||
query_type: ReflowQueryType) {
|
||||
|
||||
let root = match *self.frame() {
|
||||
None => return,
|
||||
|
@ -349,6 +375,7 @@ impl Page {
|
|||
script_chan: script_chan,
|
||||
script_join_chan: join_chan,
|
||||
id: last_reflow_id.get(),
|
||||
query_type: query_type,
|
||||
};
|
||||
|
||||
let LayoutChan(ref chan) = self.layout_chan;
|
||||
|
|
|
@ -29,7 +29,7 @@ use dom::window::{Window, WindowHelpers};
|
|||
use dom::worker::{Worker, TrustedWorkerAddress};
|
||||
use dom::xmlhttprequest::{TrustedXHRAddress, XMLHttpRequest, XHRProgress};
|
||||
use parse::html::{InputString, InputUrl, parse_html};
|
||||
use layout_interface::{ScriptLayoutChan, LayoutChan, ReflowForDisplay};
|
||||
use layout_interface::{ScriptLayoutChan, LayoutChan, NoQuery, ReflowForDisplay};
|
||||
use layout_interface;
|
||||
use page::{Page, IterablePage, Frame};
|
||||
use timers::TimerId;
|
||||
|
@ -815,7 +815,7 @@ impl ScriptTask {
|
|||
let document_as_node = NodeCast::from_ref(document_js_ref);
|
||||
document.content_changed(document_as_node);
|
||||
}
|
||||
window.flush_layout(ReflowForDisplay);
|
||||
window.flush_layout();
|
||||
|
||||
{
|
||||
// No more reflow required
|
||||
|
@ -870,7 +870,7 @@ impl ScriptTask {
|
|||
}
|
||||
|
||||
page.damage();
|
||||
page.reflow(ReflowForDisplay, self.control_chan.clone(), &*self.compositor);
|
||||
page.reflow(ReflowForDisplay, self.control_chan.clone(), &*self.compositor, NoQuery);
|
||||
}
|
||||
|
||||
/// This is the main entry point for receiving and dispatching DOM events.
|
||||
|
@ -969,7 +969,7 @@ impl ScriptTask {
|
|||
let eventtarget: JSRef<EventTarget> = EventTargetCast::from_ref(node);
|
||||
let _ = eventtarget.dispatch_event_with_target(None, *event);
|
||||
|
||||
window.flush_layout(ReflowForDisplay);
|
||||
window.flush_layout();
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue