diff options
author | bors-servo <metajack+bors@gmail.com> | 2014-12-18 00:24:49 -0700 |
---|---|---|
committer | bors-servo <metajack+bors@gmail.com> | 2014-12-18 00:24:49 -0700 |
commit | e2267e0a0749e27046ee8a26ba514cc6865e0345 (patch) | |
tree | 7b7b34c971ab6127c7f0748fc3fde10f6d3ca722 /components/layout/layout_task.rs | |
parent | 6eb9ae1eff2d26c52ad2ac59eec703bd7e8ae867 (diff) | |
parent | 7371e0b8e38753ffbc977529359d8befb4f87481 (diff) | |
download | servo-e2267e0a0749e27046ee8a26ba514cc6865e0345.tar.gz servo-e2267e0a0749e27046ee8a26ba514cc6865e0345.zip |
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.
Diffstat (limited to 'components/layout/layout_task.rs')
-rw-r--r-- | components/layout/layout_task.rs | 156 |
1 files changed, 90 insertions, 66 deletions
diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 4d8885cf8ed..48941a0d336 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -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)) } } } |