auto merge of #4358 : pcwalton/servo/cursor, r=mbrubeck

I'm not sure how we want to handle Linux cursors, and GLFW has no
ability to set cursors (short of disabling it and managing it yourself).

If you test this in the wild you will probably hit #4357 until that PR lands.
This commit is contained in:
bors-servo 2014-12-18 00:24:49 -07:00
commit e2267e0a07
23 changed files with 564 additions and 171 deletions

View file

@ -24,7 +24,7 @@ use geom::{Point2D, Rect, Size2D, SideOffsets2D};
use gfx::color;
use gfx::display_list::{BOX_SHADOW_INFLATION_FACTOR, BaseDisplayItem, BorderDisplayItem};
use gfx::display_list::{BorderDisplayItemClass, BorderRadii, BoxShadowDisplayItem};
use gfx::display_list::{BoxShadowDisplayItemClass, DisplayItem, DisplayList};
use gfx::display_list::{BoxShadowDisplayItemClass, DisplayItem, DisplayItemMetadata, DisplayList};
use gfx::display_list::{GradientDisplayItem, GradientDisplayItemClass};
use gfx::display_list::{GradientStop, ImageDisplayItem, ImageDisplayItemClass, LineDisplayItem};
use gfx::display_list::{LineDisplayItemClass, SidewaysLeft};
@ -34,6 +34,7 @@ use gfx::paint_task::PaintLayer;
use servo_msg::compositor_msg::{FixedPosition, Scrollable};
use servo_msg::constellation_msg::{ConstellationChan, FrameRectMsg};
use servo_net::image::holder::ImageHolder;
use servo_util::cursor::{DefaultCursor, TextCursor, VerticalTextCursor};
use servo_util::geometry::{mod, Au, ZERO_POINT, ZERO_RECT};
use servo_util::logical_geometry::{LogicalRect, WritingMode};
use servo_util::opts;
@ -132,6 +133,7 @@ pub trait FragmentDisplayListBuilding {
clip_rect: &Rect<Au>);
fn build_debug_borders_around_text_fragments(&self,
style: &ComputedValues,
display_list: &mut DisplayList,
flow_origin: Point2D<Au>,
text_fragment: &ScannedTextFragmentInfo,
@ -197,7 +199,11 @@ impl FragmentDisplayListBuilding for Fragment {
let background_color = style.resolve_color(style.get_background().background_color);
if !background_color.alpha.approx_eq(&0.0) {
display_list.push(SolidColorDisplayItemClass(box SolidColorDisplayItem {
base: BaseDisplayItem::new(*absolute_bounds, self.node, *clip_rect),
base: BaseDisplayItem::new(*absolute_bounds,
DisplayItemMetadata::new(self.node,
style,
DefaultCursor),
*clip_rect),
color: background_color.to_gfx_color(),
}), level);
}
@ -309,7 +315,9 @@ impl FragmentDisplayListBuilding for Fragment {
// Create the image display item.
display_list.push(ImageDisplayItemClass(box ImageDisplayItem {
base: BaseDisplayItem::new(bounds, self.node, clip_rect),
base: BaseDisplayItem::new(bounds,
DisplayItemMetadata::new(self.node, style, DefaultCursor),
clip_rect),
image: image.clone(),
stretch_size: Size2D(Au::from_px(image.width as int),
Au::from_px(image.height as int)),
@ -417,7 +425,9 @@ impl FragmentDisplayListBuilding for Fragment {
absolute_bounds.origin.y + absolute_bounds.size.height / 2);
let gradient_display_item = GradientDisplayItemClass(box GradientDisplayItem {
base: BaseDisplayItem::new(*absolute_bounds, self.node, clip_rect),
base: BaseDisplayItem::new(*absolute_bounds,
DisplayItemMetadata::new(self.node, style, DefaultCursor),
clip_rect),
start_point: center - delta,
end_point: center + delta,
stops: stops,
@ -441,7 +451,11 @@ impl FragmentDisplayListBuilding for Fragment {
absolute_bounds.translate(&Point2D(box_shadow.offset_x, box_shadow.offset_y))
.inflate(inflation, inflation);
list.push(BoxShadowDisplayItemClass(box BoxShadowDisplayItem {
base: BaseDisplayItem::new(bounds, self.node, *clip_rect),
base: BaseDisplayItem::new(bounds,
DisplayItemMetadata::new(self.node,
style,
DefaultCursor),
*clip_rect),
box_bounds: *absolute_bounds,
color: style.resolve_color(box_shadow.color).to_gfx_color(),
offset: Point2D(box_shadow.offset_x, box_shadow.offset_y),
@ -470,7 +484,9 @@ impl FragmentDisplayListBuilding for Fragment {
// Append the border to the display list.
display_list.push(BorderDisplayItemClass(box BorderDisplayItem {
base: BaseDisplayItem::new(*abs_bounds, self.node, *clip_rect),
base: BaseDisplayItem::new(*abs_bounds,
DisplayItemMetadata::new(self.node, style, DefaultCursor),
*clip_rect),
border_widths: border.to_physical(style.writing_mode),
color: SideOffsets2D::new(top_color.to_gfx_color(),
right_color.to_gfx_color(),
@ -510,7 +526,9 @@ impl FragmentDisplayListBuilding for Fragment {
// Append the outline to the display list.
let color = style.resolve_color(style.get_outline().outline_color).to_gfx_color();
display_list.outlines.push_back(BorderDisplayItemClass(box BorderDisplayItem {
base: BaseDisplayItem::new(bounds, self.node, *clip_rect),
base: BaseDisplayItem::new(bounds,
DisplayItemMetadata::new(self.node, style, DefaultCursor),
*clip_rect),
border_widths: SideOffsets2D::new_all_same(width),
color: SideOffsets2D::new_all_same(color),
style: SideOffsets2D::new_all_same(outline_style),
@ -519,6 +537,7 @@ impl FragmentDisplayListBuilding for Fragment {
}
fn build_debug_borders_around_text_fragments(&self,
style: &ComputedValues,
display_list: &mut DisplayList,
flow_origin: Point2D<Au>,
text_fragment: &ScannedTextFragmentInfo,
@ -533,7 +552,9 @@ impl FragmentDisplayListBuilding for Fragment {
// Compute the text fragment bounds and draw a border surrounding them.
display_list.content.push_back(BorderDisplayItemClass(box BorderDisplayItem {
base: BaseDisplayItem::new(absolute_fragment_bounds, self.node, *clip_rect),
base: BaseDisplayItem::new(absolute_fragment_bounds,
DisplayItemMetadata::new(self.node, style, DefaultCursor),
*clip_rect),
border_widths: SideOffsets2D::new_all_same(Au::from_px(1)),
color: SideOffsets2D::new_all_same(color::rgb(0, 0, 200)),
style: SideOffsets2D::new_all_same(border_style::solid),
@ -549,7 +570,9 @@ impl FragmentDisplayListBuilding for Fragment {
baseline.origin = baseline.origin + flow_origin;
let line_display_item = box LineDisplayItem {
base: BaseDisplayItem::new(baseline, self.node, *clip_rect),
base: BaseDisplayItem::new(baseline,
DisplayItemMetadata::new(self.node, style, DefaultCursor),
*clip_rect),
color: color::rgb(0, 200, 0),
style: border_style::dashed,
};
@ -570,7 +593,11 @@ impl FragmentDisplayListBuilding for Fragment {
// This prints a debug border around the border of this fragment.
display_list.content.push_back(BorderDisplayItemClass(box BorderDisplayItem {
base: BaseDisplayItem::new(absolute_fragment_bounds, self.node, *clip_rect),
base: BaseDisplayItem::new(absolute_fragment_bounds,
DisplayItemMetadata::new(self.node,
&*self.style,
DefaultCursor),
*clip_rect),
border_widths: SideOffsets2D::new_all_same(Au::from_px(1)),
color: SideOffsets2D::new_all_same(color::rgb(0, 0, 200)),
style: SideOffsets2D::new_all_same(border_style::solid),
@ -731,14 +758,14 @@ impl FragmentDisplayListBuilding for Fragment {
SpecificFragmentInfo::TableColumn(_) => panic!("Shouldn't see table column fragments here."),
SpecificFragmentInfo::ScannedText(ref text_fragment) => {
// Create the text display item.
let orientation = if self.style.writing_mode.is_vertical() {
let (orientation, cursor) = if self.style.writing_mode.is_vertical() {
if self.style.writing_mode.is_sideways_left() {
SidewaysLeft
(SidewaysLeft, VerticalTextCursor)
} else {
SidewaysRight
(SidewaysRight, VerticalTextCursor)
}
} else {
Upright
(Upright, TextCursor)
};
let metrics = &text_fragment.run.font_metrics;
@ -750,7 +777,11 @@ impl FragmentDisplayListBuilding for Fragment {
};
display_list.content.push_back(TextDisplayItemClass(box TextDisplayItem {
base: BaseDisplayItem::new(absolute_content_box, self.node, *clip_rect),
base: BaseDisplayItem::new(absolute_content_box,
DisplayItemMetadata::new(self.node,
self.style(),
cursor),
*clip_rect),
text_run: text_fragment.run.clone(),
range: text_fragment.range,
text_color: self.style().get_color().color.to_gfx_color(),
@ -760,14 +791,21 @@ impl FragmentDisplayListBuilding for Fragment {
// Create display items for text decoration
{
let line = |maybe_color: Option<RGBA>, rect: || -> LogicalRect<Au>| {
let line = |maybe_color: Option<RGBA>,
style: &ComputedValues,
rect: || -> LogicalRect<Au>| {
match maybe_color {
None => {}
Some(color) => {
let bounds = rect_to_absolute(self.style.writing_mode, rect());
display_list.content.push_back(SolidColorDisplayItemClass(
box SolidColorDisplayItem {
base: BaseDisplayItem::new(bounds, self.node, *clip_rect),
base: BaseDisplayItem::new(
bounds,
DisplayItemMetadata::new(self.node,
style,
DefaultCursor),
*clip_rect),
color: color.to_gfx_color(),
}))
}
@ -776,20 +814,20 @@ impl FragmentDisplayListBuilding for Fragment {
let text_decorations =
self.style().get_inheritedtext()._servo_text_decorations_in_effect;
line(text_decorations.underline, || {
line(text_decorations.underline, self.style(), || {
let mut rect = content_box.clone();
rect.start.b = rect.start.b + metrics.ascent - metrics.underline_offset;
rect.size.block = metrics.underline_size;
rect
});
line(text_decorations.overline, || {
line(text_decorations.overline, self.style(), || {
let mut rect = content_box.clone();
rect.size.block = metrics.underline_size;
rect
});
line(text_decorations.line_through, || {
line(text_decorations.line_through, self.style(), || {
let mut rect = content_box.clone();
rect.start.b = rect.start.b + metrics.ascent - metrics.strikeout_offset;
rect.size.block = metrics.strikeout_size;
@ -798,7 +836,8 @@ impl FragmentDisplayListBuilding for Fragment {
}
if opts::get().show_debug_fragment_borders {
self.build_debug_borders_around_text_fragments(display_list,
self.build_debug_borders_around_text_fragments(self.style(),
display_list,
flow_origin,
&**text_fragment,
clip_rect);
@ -822,7 +861,9 @@ impl FragmentDisplayListBuilding for Fragment {
// Place the image into the display list.
display_list.content.push_back(ImageDisplayItemClass(box ImageDisplayItem {
base: BaseDisplayItem::new(absolute_content_box,
self.node,
DisplayItemMetadata::new(self.node,
&*self.style,
DefaultCursor),
*clip_rect),
image: image.clone(),
stretch_size: absolute_content_box.size,

View file

@ -13,8 +13,7 @@ use flow_ref::FlowRef;
use fragment::{Fragment, FragmentBoundsIterator};
use incremental::{LayoutDamageComputation, REFLOW, REFLOW_ENTIRE_DOCUMENT, REPAINT};
use layout_debug;
use parallel::UnsafeFlow;
use parallel;
use parallel::{mod, UnsafeFlow};
use sequential;
use util::{LayoutDataAccess, LayoutDataWrapper, OpaqueNodeMethods, ToGfxColor};
use wrapper::{LayoutNode, TLayoutNode, ThreadSafeLayoutNode};
@ -26,7 +25,7 @@ use geom::rect::Rect;
use geom::size::Size2D;
use geom::scale_factor::ScaleFactor;
use gfx::color;
use gfx::display_list::{DisplayList, OpaqueNode, StackingContext};
use gfx::display_list::{DisplayItemMetadata, DisplayList, OpaqueNode, StackingContext};
use gfx::font_cache_task::FontCacheTask;
use gfx::paint_task::{mod, PaintInitMsg, PaintChan, PaintLayer};
use layout_traits;
@ -40,22 +39,25 @@ use script::layout_interface::{ContentBoxesQuery, ContentBoxQuery, ExitNowMsg, G
use script::layout_interface::{HitTestResponse, LayoutChan, LayoutRPC, LoadStylesheetMsg};
use script::layout_interface::{MouseOverResponse, Msg, NoQuery, PrepareToExitMsg};
use script::layout_interface::{ReapLayoutDataMsg, Reflow, ReflowForDisplay, ReflowMsg};
use script::layout_interface::{ScriptLayoutChan, SetQuirksModeMsg, TrustedNodeAddress};
use script::layout_interface::{ReflowForScriptQuery, ScriptLayoutChan, SetQuirksModeMsg};
use script::layout_interface::{TrustedNodeAddress};
use script_traits::{SendEventMsg, ReflowEvent, ReflowCompleteMsg, OpaqueScriptLayoutChannel};
use script_traits::{ScriptControlChan, UntrustedNodeAddress};
use servo_msg::compositor_msg::Scrollable;
use servo_msg::constellation_msg::{ConstellationChan, PipelineId, Failure, FailureMsg};
use servo_msg::constellation_msg::{SetCursorMsg};
use servo_net::image_cache_task::{ImageCacheTask, ImageResponseMsg};
use servo_net::local_image_cache::{ImageResponder, LocalImageCache};
use servo_net::resource_task::{ResourceTask, load_bytes_iter};
use servo_util::cursor::DefaultCursor;
use servo_util::geometry::Au;
use servo_util::logical_geometry::LogicalPoint;
use servo_util::opts;
use servo_util::smallvec::{SmallVec, SmallVec1, VecLike};
use servo_util::task::spawn_named_with_send_on_failure;
use servo_util::task_state;
use servo_util::time::{TimeProfilerChan, profile, TimerMetadataFrameType, TimerMetadataReflowType};
use servo_util::time;
use servo_util::time::{mod, ProfilerMetadata, TimeProfilerChan, TimerMetadataFrameType};
use servo_util::time::{TimerMetadataReflowType, profile};
use servo_util::workqueue::WorkQueue;
use std::cell::Cell;
use std::comm::{channel, Sender, Receiver, Select};
@ -73,6 +75,9 @@ pub struct LayoutTaskData {
/// The local image cache.
pub local_image_cache: Arc<Mutex<LocalImageCache<UntrustedNodeAddress>>>,
/// The channel on which messages can be sent to the constellation.
pub constellation_chan: ConstellationChan,
/// The size of the viewport.
pub screen_size: Size2D<Au>,
@ -112,9 +117,6 @@ pub struct LayoutTask {
//// The channel to send messages to ourself.
pub chan: LayoutChan,
/// The channel on which messages can be sent to the constellation.
pub constellation_chan: ConstellationChan,
/// The channel on which messages can be sent to the script task.
pub script_chan: ScriptControlChan,
@ -262,7 +264,6 @@ impl LayoutTask {
port: port,
pipeline_port: pipeline_port,
chan: chan,
constellation_chan: constellation_chan,
script_chan: script_chan,
paint_chan: paint_chan,
time_profiler_chan: time_profiler_chan,
@ -273,6 +274,7 @@ impl LayoutTask {
rw_data: Arc::new(Mutex::new(
LayoutTaskData {
local_image_cache: local_image_cache,
constellation_chan: constellation_chan,
screen_size: screen_size,
stacking_context: None,
stylist: box Stylist::new(device),
@ -302,7 +304,7 @@ impl LayoutTask {
SharedLayoutContext {
image_cache: rw_data.local_image_cache.clone(),
screen_size: rw_data.screen_size.clone(),
constellation_chan: self.constellation_chan.clone(),
constellation_chan: rw_data.constellation_chan.clone(),
layout_chan: self.chan.clone(),
font_cache_task: self.font_cache_task.clone(),
stylist: &*rw_data.stylist,
@ -397,9 +399,7 @@ impl LayoutTask {
},
ReflowMsg(data) => {
profile(time::LayoutPerformCategory,
Some((&data.url,
if data.iframe { TimerMetadataFrameType::IFrame } else { TimerMetadataFrameType::RootWindow },
if self.first_reflow.get() { TimerMetadataReflowType::FirstReflow } else { TimerMetadataReflowType::Incremental })),
self.profiler_metadata(&*data),
self.time_profiler_chan.clone(),
|| self.handle_reflow(&*data, possibly_locked_rw_data));
},
@ -573,9 +573,7 @@ impl LayoutTask {
// NOTE: this currently computes borders, so any pruning should separate that
// operation out.
parallel::traverse_flow_tree_preorder(layout_root,
&data.url,
if data.iframe { TimerMetadataFrameType::IFrame } else { TimerMetadataFrameType::RootWindow },
if self.first_reflow.get() { TimerMetadataReflowType::FirstReflow } else { TimerMetadataReflowType::Incremental },
self.profiler_metadata(data),
self.time_profiler_chan.clone(),
shared_layout_context,
traversal);
@ -624,16 +622,14 @@ impl LayoutTask {
data: &Reflow,
node: &mut LayoutNode,
layout_root: &mut FlowRef,
shared_layout_ctx: &mut SharedLayoutContext,
shared_layout_context: &mut SharedLayoutContext,
rw_data: &mut RWGuard<'a>) {
let writing_mode = flow::base(&**layout_root).writing_mode;
profile(time::LayoutDispListBuildCategory,
Some((&data.url,
if data.iframe { TimerMetadataFrameType::IFrame } else { TimerMetadataFrameType::RootWindow },
if self.first_reflow.get() { TimerMetadataReflowType::FirstReflow } else { TimerMetadataReflowType::Incremental })),
self.time_profiler_chan.clone(),
|| {
shared_layout_ctx.dirty =
self.profiler_metadata(data),
self.time_profiler_chan.clone(),
|| {
shared_layout_context.dirty =
flow::base(&**layout_root).position.to_physical(writing_mode,
rw_data.screen_size);
flow::mut_base(&mut **layout_root).stacking_relative_position =
@ -645,15 +641,13 @@ impl LayoutTask {
let rw_data = rw_data.deref_mut();
match rw_data.parallel_traversal {
None => {
sequential::build_display_list_for_subtree(layout_root, shared_layout_ctx);
sequential::build_display_list_for_subtree(layout_root, shared_layout_context);
}
Some(ref mut traversal) => {
parallel::build_display_list_for_subtree(layout_root,
&data.url,
if data.iframe { TimerMetadataFrameType::IFrame } else { TimerMetadataFrameType::RootWindow },
if self.first_reflow.get() { TimerMetadataReflowType::FirstReflow } else { TimerMetadataReflowType::Incremental },
self.profiler_metadata(data),
self.time_profiler_chan.clone(),
shared_layout_ctx,
shared_layout_context,
traversal);
}
}
@ -746,9 +740,9 @@ impl LayoutTask {
rw_data.screen_size = current_screen_size;
// Create a layout context for use throughout the following passes.
let mut shared_layout_ctx = self.build_shared_layout_context(rw_data.deref(),
node,
&data.url);
let mut shared_layout_context = self.build_shared_layout_context(rw_data.deref(),
node,
&data.url);
// Handle conditions where the entire flow tree is invalid.
let screen_size_changed = current_screen_size != old_screen_size;
@ -775,19 +769,17 @@ impl LayoutTask {
}
let mut layout_root = profile(time::LayoutStyleRecalcCategory,
Some((&data.url,
if data.iframe { TimerMetadataFrameType::IFrame } else { TimerMetadataFrameType::RootWindow },
if self.first_reflow.get() { TimerMetadataReflowType::FirstReflow } else { TimerMetadataReflowType::Incremental })),
self.profiler_metadata(data),
self.time_profiler_chan.clone(),
|| {
// Perform CSS selector matching and flow construction.
let rw_data = rw_data.deref_mut();
match rw_data.parallel_traversal {
None => {
sequential::traverse_dom_preorder(*node, &shared_layout_ctx);
sequential::traverse_dom_preorder(*node, &shared_layout_context);
}
Some(ref mut traversal) => {
parallel::traverse_dom_preorder(*node, &shared_layout_ctx, traversal)
parallel::traverse_dom_preorder(*node, &shared_layout_context, traversal)
}
}
@ -795,13 +787,12 @@ impl LayoutTask {
});
profile(time::LayoutRestyleDamagePropagation,
Some((&data.url,
if data.iframe { TimerMetadataFrameType::IFrame } else { TimerMetadataFrameType::RootWindow },
if self.first_reflow.get() { TimerMetadataReflowType::FirstReflow } else { TimerMetadataReflowType::Incremental })),
self.profiler_metadata(data),
self.time_profiler_chan.clone(),
|| {
if opts::get().nonincremental_layout ||
layout_root.deref_mut().compute_layout_damage().contains(REFLOW_ENTIRE_DOCUMENT) {
if opts::get().nonincremental_layout || layout_root.deref_mut()
.compute_layout_damage()
.contains(REFLOW_ENTIRE_DOCUMENT) {
layout_root.deref_mut().reflow_entire_document()
}
});
@ -818,42 +809,45 @@ impl LayoutTask {
// Perform the primary layout passes over the flow tree to compute the locations of all
// the boxes.
profile(time::LayoutMainCategory,
Some((&data.url,
if data.iframe { TimerMetadataFrameType::IFrame } else { TimerMetadataFrameType::RootWindow },
if self.first_reflow.get() { TimerMetadataReflowType::FirstReflow } else { TimerMetadataReflowType::Incremental })),
self.profiler_metadata(data),
self.time_profiler_chan.clone(),
|| {
let rw_data = rw_data.deref_mut();
match rw_data.parallel_traversal {
None => {
// Sequential mode.
self.solve_constraints(&mut layout_root, &shared_layout_ctx)
self.solve_constraints(&mut layout_root, &shared_layout_context)
}
Some(_) => {
// Parallel mode.
self.solve_constraints_parallel(data,
rw_data,
&mut layout_root,
&mut shared_layout_ctx);
&mut shared_layout_context);
}
}
});
// Build the display list if necessary, and send it to the painter.
if data.goal == ReflowForDisplay {
self.build_display_list_for_reflow(data,
node,
&mut layout_root,
&mut shared_layout_ctx,
&mut rw_data);
match data.goal {
ReflowForDisplay => {
self.build_display_list_for_reflow(data,
node,
&mut layout_root,
&mut shared_layout_context,
&mut rw_data);
}
ReflowForScriptQuery => {}
}
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 => {},
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);
@ -896,11 +890,13 @@ impl LayoutTask {
}
}
// When images can't be loaded in time to display they trigger
// this callback in some task somewhere. This will send a message
// to the script task, and ultimately cause the image to be
// re-requested. We probably don't need to go all the way back to
// the script task for this.
/// When images can't be loaded in time to display they trigger
/// this callback in some task somewhere. This will send a message
/// to the script task, and ultimately cause the image to be
/// re-requested. We probably don't need to go all the way back to
/// the script task for this.
///
/// FIXME(pcwalton): Rewrite all of this.
fn make_on_image_available_cb(&self) -> Box<ImageResponder<UntrustedNodeAddress>+Send> {
// This has a crazy signature because the image cache needs to
// make multiple copies of the callback, and the dom event
@ -919,6 +915,21 @@ impl LayoutTask {
let _: Option<LayoutDataWrapper> = mem::transmute(
mem::replace(&mut *layout_data_ref, None));
}
/// Returns profiling information which is passed to the time profiler.
fn profiler_metadata<'a>(&self, data: &'a Reflow) -> ProfilerMetadata<'a> {
Some((&data.url,
if data.iframe {
TimerMetadataFrameType::IFrame
} else {
TimerMetadataFrameType::RootWindow
},
if self.first_reflow.get() {
TimerMetadataReflowType::FirstReflow
} else {
TimerMetadataReflowType::Incremental
}))
}
}
struct LayoutRPCImpl(Arc<Mutex<LayoutTaskData>>);
@ -951,7 +962,7 @@ impl LayoutRPC for LayoutRPCImpl {
let mut result = Vec::new();
stacking_context.hit_test(point, &mut result, true);
if !result.is_empty() {
Some(HitTestResponse(result[0]))
Some(HitTestResponse(result[0].node.to_untrusted_node_address()))
} else {
None
}
@ -967,7 +978,7 @@ impl LayoutRPC for LayoutRPCImpl {
fn mouse_over(&self, _: TrustedNodeAddress, point: Point2D<f32>)
-> Result<MouseOverResponse, ()> {
let mut mouse_over_list: Vec<UntrustedNodeAddress> = vec!();
let mut mouse_over_list: Vec<DisplayItemMetadata> = vec!();
let point = Point2D(Au::from_frac_px(point.x as f64), Au::from_frac_px(point.y as f64));
{
let &LayoutRPCImpl(ref rw_data) = self;
@ -978,12 +989,25 @@ impl LayoutRPC for LayoutRPCImpl {
stacking_context.hit_test(point, &mut mouse_over_list, false);
}
}
// Compute the new cursor.
let cursor = if !mouse_over_list.is_empty() {
mouse_over_list[0].cursor
} else {
DefaultCursor
};
let ConstellationChan(ref constellation_chan) = rw_data.constellation_chan;
constellation_chan.send(SetCursorMsg(cursor));
}
if mouse_over_list.is_empty() {
Err(())
} else {
Ok(MouseOverResponse(mouse_over_list))
let response_list =
mouse_over_list.iter()
.map(|metadata| metadata.node.to_untrusted_node_address())
.collect();
Ok(MouseOverResponse(response_list))
}
}
}

View file

@ -13,15 +13,13 @@ use flow_ref::FlowRef;
use traversal::{RecalcStyleForNode, ConstructFlows};
use traversal::{BubbleISizes, AssignISizes, AssignBSizesAndStoreOverflow};
use traversal::{ComputeAbsolutePositions, BuildDisplayList};
use url::Url;
use util::{LayoutDataAccess, LayoutDataWrapper};
use wrapper::{layout_node_to_unsafe_layout_node, layout_node_from_unsafe_layout_node, LayoutNode};
use wrapper::{PostorderNodeMutTraversal, UnsafeLayoutNode};
use wrapper::{PreorderDomTraversal, PostorderDomTraversal};
use servo_util::opts;
use servo_util::time::{TimeProfilerChan, profile, TimerMetadataFrameType, TimerMetadataReflowType};
use servo_util::time;
use servo_util::time::{mod, ProfilerMetadata, TimeProfilerChan, profile};
use servo_util::workqueue::{WorkQueue, WorkUnit, WorkerProxy};
use std::mem;
use std::ptr;
@ -422,9 +420,7 @@ pub fn traverse_dom_preorder(root: LayoutNode,
}
pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
url: &Url,
iframe: TimerMetadataFrameType,
reflow_type: TimerMetadataReflowType,
profiler_metadata: ProfilerMetadata,
time_profiler_chan: TimeProfilerChan,
shared_layout_context: &SharedLayoutContext,
queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeFlow>) {
@ -436,7 +432,7 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
queue.data = shared_layout_context as *const _;
profile(time::LayoutParallelWarmupCategory, Some((url, iframe, reflow_type)), time_profiler_chan, || {
profile(time::LayoutParallelWarmupCategory, profiler_metadata, time_profiler_chan, || {
queue.push(WorkUnit {
fun: assign_inline_sizes,
data: mut_owned_flow_to_unsafe_flow(root),
@ -449,15 +445,13 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
}
pub fn build_display_list_for_subtree(root: &mut FlowRef,
url: &Url,
iframe: TimerMetadataFrameType,
reflow_type: TimerMetadataReflowType,
profiler_metadata: ProfilerMetadata,
time_profiler_chan: TimeProfilerChan,
shared_layout_context: &SharedLayoutContext,
queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeFlow>) {
queue.data = shared_layout_context as *const _;
profile(time::LayoutParallelWarmupCategory, Some((url, iframe, reflow_type)), time_profiler_chan, || {
profile(time::LayoutParallelWarmupCategory, profiler_metadata, time_profiler_chan, || {
queue.push(WorkUnit {
fun: compute_absolute_positions,
data: mut_owned_flow_to_unsafe_flow(root),