diff options
author | Adenilson Cavalcanti <cavalcantii@gmail.com> | 2015-03-04 15:45:34 -0800 |
---|---|---|
committer | Adenilson Cavalcanti <cavalcantii@gmail.com> | 2015-03-06 12:27:18 -0800 |
commit | 618f56410db1f18ce05744e45e8f9651152d9ae2 (patch) | |
tree | 897296f1f8ac0e05f89101be365cb67a4e262e4d | |
parent | 34289943e354b2ac0e54fd1fe2d65c944f6c8e9d (diff) | |
download | servo-618f56410db1f18ce05744e45e8f9651152d9ae2.tar.gz servo-618f56410db1f18ce05744e45e8f9651152d9ae2.zip |
Implements reflow events debugging.
Start servo with -Z relayout-event and you should have
reflow events printed to the terminal.
-rw-r--r-- | components/script/dom/document.rs | 6 | ||||
-rw-r--r-- | components/script/dom/window.rs | 58 | ||||
-rw-r--r-- | components/script/script_task.rs | 18 | ||||
-rw-r--r-- | components/util/opts.rs | 6 |
4 files changed, 70 insertions, 18 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 059f568f873..8bd32de323d 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -56,7 +56,7 @@ use dom::processinginstruction::ProcessingInstruction; use dom::range::Range; use dom::treewalker::TreeWalker; use dom::uievent::UIEvent; -use dom::window::{Window, WindowHelpers}; +use dom::window::{Window, WindowHelpers, ReflowReason}; use layout_interface::{HitTestResponse, MouseOverResponse}; use msg::compositor_msg::ScriptListener; @@ -523,7 +523,7 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { el.authentic_click_activation(event); self.commit_focus_transaction(); - window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery); + window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::MouseEvent); } /// Return need force reflow or not @@ -664,7 +664,7 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { _ => () } - window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery); + window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::KeyEvent); } fn set_current_script(self, script: Option<JSRef<HTMLScriptElement>>) { diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 29551114315..1babbfcb2cd 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -41,6 +41,7 @@ use net::image_cache_task::ImageCacheTask; use net::resource_task::ResourceTask; use net::storage_task::StorageTask; use util::geometry::{self, Au, MAX_RECT}; +use util::opts; use util::str::{DOMString,HTML_SPACE_CHARACTERS}; use geom::{Point2D, Rect, Size2D}; @@ -63,6 +64,19 @@ use std::sync::mpsc::{channel, Receiver}; use std::sync::mpsc::TryRecvError::{Empty, Disconnected}; use time; +/// Extra information concerning the reason for reflowing. +pub enum ReflowReason { + CachedPageNeededReflow, + FirstLoad, + KeyEvent, + MouseEvent, + Query, + ReceivedReflowEvent, + Timer, + Viewport, + WindowResize, +} + #[dom_struct] pub struct Window { eventtarget: EventTarget, @@ -397,7 +411,7 @@ pub trait WindowHelpers { fn init_browser_context(self, doc: JSRef<Document>, frame_element: Option<JSRef<Element>>); fn load_url(self, href: DOMString); fn handle_fire_timer(self, timer_id: TimerId); - fn reflow(self, goal: ReflowGoal, query_type: ReflowQueryType); + fn reflow(self, goal: ReflowGoal, query_type: ReflowQueryType, reason: ReflowReason); fn join_layout(self); fn layout(&self) -> &LayoutRPC; fn content_box_query(self, content_box_request: TrustedNodeAddress) -> Rect<Au>; @@ -480,7 +494,7 @@ impl<'a> WindowHelpers for JSRef<'a, Window> { /// yet, the page is presumed invisible and no reflow is performed. /// /// TODO(pcwalton): Only wait for style recalc, since we have off-main-thread layout. - fn reflow(self, goal: ReflowGoal, query_type: ReflowQueryType) { + fn reflow(self, goal: ReflowGoal, query_type: ReflowQueryType, reason: ReflowReason) { let document = self.Document().root(); let root = document.r().GetDocumentElement().root(); let root = match root.r() { @@ -511,6 +525,11 @@ impl<'a> WindowHelpers for JSRef<'a, Window> { let window_size = self.window_size.get(); + // On debug mode, print the reflow event information. + if opts::get().relayout_event { + debug_reflow_events(&goal, &query_type, &reason); + } + // Send new document and relevant styles to layout. let reflow = box Reflow { document_root: root.to_trusted_node_address(), @@ -562,14 +581,14 @@ impl<'a> WindowHelpers for JSRef<'a, Window> { } fn content_box_query(self, content_box_request: TrustedNodeAddress) -> Rect<Au> { - self.reflow(ReflowGoal::ForScriptQuery, ReflowQueryType::ContentBoxQuery(content_box_request)); + self.reflow(ReflowGoal::ForScriptQuery, ReflowQueryType::ContentBoxQuery(content_box_request), ReflowReason::Query); self.join_layout(); //FIXME: is this necessary, or is layout_rpc's mutex good enough? let ContentBoxResponse(rect) = self.layout_rpc.content_box(); rect } fn content_boxes_query(self, content_boxes_request: TrustedNodeAddress) -> Vec<Rect<Au>> { - self.reflow(ReflowGoal::ForScriptQuery, ReflowQueryType::ContentBoxesQuery(content_boxes_request)); + self.reflow(ReflowGoal::ForScriptQuery, ReflowQueryType::ContentBoxesQuery(content_boxes_request), ReflowReason::Query); self.join_layout(); //FIXME: is this necessary, or is layout_rpc's mutex good enough? let ContentBoxesResponse(rects) = self.layout_rpc.content_boxes(); rects @@ -609,7 +628,7 @@ impl<'a> WindowHelpers for JSRef<'a, Window> { fn handle_fire_timer(self, timer_id: TimerId) { self.timers.fire_timer(timer_id, self); - self.reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery); + self.reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::Timer); } fn set_fragment_name(self, fragment: Option<String>) { @@ -715,7 +734,6 @@ impl<'a> WindowHelpers for JSRef<'a, Window> { fn freeze(self) { self.timers.suspend(); } - } impl Window { @@ -798,3 +816,31 @@ fn should_move_clip_rect(clip_rect: Rect<Au>, new_viewport: Rect<f32>) -> bool{ (clip_rect.origin.y - new_viewport.origin.y).abs() <= viewport_scroll_margin.height || (clip_rect.max_y() - new_viewport.max_y()).abs() <= viewport_scroll_margin.height } + +fn debug_reflow_events(goal: &ReflowGoal, query_type: &ReflowQueryType, reason: &ReflowReason) { + let mut debug_msg = String::from_str("****"); + match *goal { + ReflowGoal::ForDisplay => debug_msg.push_str("\tForDisplay"), + ReflowGoal::ForScriptQuery => debug_msg.push_str("\tForScriptQuery"), + } + + match *query_type { + ReflowQueryType::NoQuery => debug_msg.push_str("\tNoQuery"), + ReflowQueryType::ContentBoxQuery(_n) => debug_msg.push_str("\tContentBoxQuery"), + ReflowQueryType::ContentBoxesQuery(_n) => debug_msg.push_str("\tContentBoxesQuery"), + } + + match *reason { + ReflowReason::CachedPageNeededReflow => debug_msg.push_str("\tCachedPageNeededReflow"), + ReflowReason::FirstLoad => debug_msg.push_str("\tFirstLoad"), + ReflowReason::KeyEvent => debug_msg.push_str("\tKeyEvent"), + ReflowReason::MouseEvent => debug_msg.push_str("\tMouseEvent"), + ReflowReason::Query => debug_msg.push_str("\tQuery"), + ReflowReason::ReceivedReflowEvent => debug_msg.push_str("\tReceivedReflowEvent"), + ReflowReason::Timer => debug_msg.push_str("\tTimer"), + ReflowReason::Viewport => debug_msg.push_str("\tViewport"), + ReflowReason::WindowResize => debug_msg.push_str("\tWindowResize"), + } + + println!("{}", debug_msg); +} diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 673dc3510ef..4fa240aa3c1 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -36,7 +36,7 @@ use dom::event::{Event, EventHelpers}; use dom::uievent::UIEvent; use dom::eventtarget::EventTarget; use dom::node::{self, Node, NodeHelpers, NodeDamage, window_from_node}; -use dom::window::{Window, WindowHelpers, ScriptHelpers}; +use dom::window::{Window, WindowHelpers, ScriptHelpers, ReflowReason}; use dom::worker::{Worker, TrustedWorkerAddress}; use parse::html::{HTMLInput, parse_html}; use layout_interface::{ScriptLayoutChan, LayoutChan, ReflowGoal, ReflowQueryType}; @@ -697,7 +697,7 @@ impl ScriptTask { let window = inner_page.window().root(); if window.r().set_page_clip_rect_with_new_viewport(rect) { let page = get_page(page, id); - self.force_reflow(&*page); + self.force_reflow(&*page, ReflowReason::Viewport); } return; } @@ -771,7 +771,7 @@ impl ScriptTask { let needed_reflow = page.set_reflow_status(false); if needed_reflow { - self.force_reflow(&*page); + self.force_reflow(&*page, ReflowReason::CachedPageNeededReflow); } } @@ -1007,7 +1007,7 @@ impl ScriptTask { debug!("kicking off initial reflow of {:?}", final_url); document.r().content_changed(NodeCast::from_ref(document.r()), NodeDamage::OtherNodeDamage); - window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery); + window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::FirstLoad); // No more reflow required page.set_reflow_status(false); @@ -1060,11 +1060,11 @@ impl ScriptTask { } /// Reflows non-incrementally. - fn force_reflow(&self, page: &Page) { + fn force_reflow(&self, page: &Page, reason: ReflowReason) { let document = page.document().root(); document.r().dirty_all_nodes(); let window = window_from_node(document.r()).root(); - window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery); + window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, reason); } /// This is the main entry point for receiving and dispatching DOM events. @@ -1113,7 +1113,7 @@ impl ScriptTask { let mouse_over_targets = &mut *self.mouse_over_targets.borrow_mut(); if document.r().handle_mouse_move_event(self.js_runtime.ptr, point, mouse_over_targets) { - self.force_reflow(&page) + self.force_reflow(&page, ReflowReason::MouseEvent) } } @@ -1151,7 +1151,7 @@ impl ScriptTask { let page = get_page(&self.root_page(), pipeline_id); let window = page.window().root(); window.r().set_window_size(new_size); - self.force_reflow(&*page); + self.force_reflow(&*page, ReflowReason::WindowResize); let document = page.document().root(); let fragment_node = window.r().steal_fragment_name() @@ -1177,7 +1177,7 @@ impl ScriptTask { fn handle_reflow_event(&self, pipeline_id: PipelineId) { debug!("script got reflow event"); let page = get_page(&self.root_page(), pipeline_id); - self.force_reflow(&*page); + self.force_reflow(&*page, ReflowReason::ReceivedReflowEvent); } /// Initiate a non-blocking fetch for a specified resource. Stores the InProgressLoad diff --git a/components/util/opts.rs b/components/util/opts.rs index 6bcbf694940..c27106d16a0 100644 --- a/components/util/opts.rs +++ b/components/util/opts.rs @@ -113,6 +113,9 @@ pub struct Opts { /// Dumps the flow tree after a layout. pub dump_display_list: bool, + /// Emits notifications when there is a relayout. + pub relayout_event: bool, + /// Whether to show an error when display list geometry escapes flow overflow regions. pub validate_display_list_geometry: bool, @@ -136,6 +139,7 @@ pub fn print_debug_usage(app: &str) { print_option("disable-text-aa", "Disable antialiasing of rendered text."); print_option("dump-flow-tree", "Print the flow tree after each layout."); print_option("dump-display-list", "Print the display list after each layout."); + print_option("relayout-event", "Print notifications when there is a relayout."); print_option("profile-tasks", "Instrument each task, writing the output to a file."); print_option("show-compositor-borders", "Paint borders along layer and tile boundaries."); print_option("show-fragment-borders", "Paint borders along fragment boundaries."); @@ -188,6 +192,7 @@ pub fn default_opts() -> Opts { user_agent: None, dump_flow_tree: false, dump_display_list: false, + relayout_event: false, validate_display_list_geometry: false, profile_tasks: false, resources_path: None, @@ -336,6 +341,7 @@ pub fn from_cmdline_args(args: &[String]) -> bool { enable_text_antialiasing: !debug_options.contains(&"disable-text-aa"), dump_flow_tree: debug_options.contains(&"dump-flow-tree"), dump_display_list: debug_options.contains(&"dump-display-list"), + relayout_event: debug_options.contains(&"relayout-event"), validate_display_list_geometry: debug_options.contains(&"validate-display-list-geometry"), resources_path: opt_match.opt_str("resources-path"), }; |