diff --git a/components/layout/query.rs b/components/layout/query.rs index 4225c170b42..d8dd633e8c3 100644 --- a/components/layout/query.rs +++ b/components/layout/query.rs @@ -6,22 +6,14 @@ use std::cmp::{max, min}; use std::ops::Deref; -use std::sync::{Arc, Mutex}; use app_units::Au; use euclid::default::{Box2D, Point2D, Rect, Size2D, Vector2D}; -use euclid::Size2D as TypedSize2D; -use ipc_channel::ipc::IpcSender; use msg::constellation_msg::PipelineId; -use script_layout_interface::rpc::{ - ContentBoxResponse, ContentBoxesResponse, LayoutRPC, NodeGeometryResponse, - NodeScrollIdResponse, OffsetParentResponse, ResolvedStyleResponse, TextIndexResponse, -}; use script_layout_interface::wrapper_traits::{ LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode, }; -use script_layout_interface::{LayoutElementType, LayoutNodeType}; -use script_traits::{LayoutMsg as ConstellationMsg, UntrustedNodeAddress}; +use script_layout_interface::{LayoutElementType, LayoutNodeType, OffsetParentResponse}; use servo_arc::Arc as ServoArc; use servo_url::ServoUrl; use style::computed_values::display::T as Display; @@ -33,17 +25,16 @@ use style::logical_geometry::{BlockFlowDirection, InlineBaseDirection, WritingMo use style::properties::style_structs::{self, Font}; use style::properties::{ parse_one_declaration_into, ComputedValues, Importance, LonghandId, PropertyDeclarationBlock, - PropertyDeclarationId, PropertyId, SourcePropertyDeclaration, + PropertyDeclarationId, PropertyId, ShorthandId, SourcePropertyDeclaration, }; use style::selector_parser::PseudoElement; use style::shared_lock::SharedRwLock; use style::stylesheets::{CssRuleType, Origin, UrlExtraData}; -use style_traits::{CSSPixel, ParsingMode, ToCss}; +use style_traits::{ParsingMode, ToCss}; use webrender_api::ExternalScrollId; use crate::construct::ConstructionResult; -use crate::context::LayoutContext; -use crate::display_list::items::{DisplayList, OpaqueNode, ScrollOffsetMap}; +use crate::display_list::items::OpaqueNode; use crate::display_list::IndexableText; use crate::flow::{Flow, GetBaseFlow}; use crate::fragment::{Fragment, FragmentBorderBoxIterator, FragmentFlags, SpecificFragmentInfo}; @@ -51,60 +42,6 @@ use crate::inline::InlineFragmentNodeFlags; use crate::sequential; use crate::wrapper::LayoutNodeLayoutData; -/// Mutable data belonging to the LayoutThread. -/// -/// This needs to be protected by a mutex so we can do fast RPCs. -pub struct LayoutThreadData { - /// The channel on which messages can be sent to the constellation. - pub constellation_chan: IpcSender, - - /// The root stacking context. - pub display_list: Option, - - pub indexable_text: IndexableText, - - /// A queued response for the union of the content boxes of a node. - pub content_box_response: Option>, - - /// A queued response for the content boxes of a node. - pub content_boxes_response: Vec>, - - /// A queued response for the client {top, left, width, height} of a node in pixels. - pub client_rect_response: Rect, - - /// A queued response for the scroll id for a given node. - pub scroll_id_response: Option, - - /// A queued response for the scroll {top, left, width, height} of a node in pixels. - pub scrolling_area_response: Rect, - - /// A queued response for the resolved style property of an element. - pub resolved_style_response: String, - - /// A queued response for the resolved font style for canvas. - pub resolved_font_style_response: Option>, - - /// A queued response for the offset parent/rect of a node. - pub offset_parent_response: OffsetParentResponse, - - /// Scroll offsets of scrolling regions. - pub scroll_offsets: ScrollOffsetMap, - - /// Index in a text fragment. We need this do determine the insertion point. - pub text_index_response: TextIndexResponse, - - /// A queued response for the list of nodes at a given point. - pub nodes_from_point_response: Vec, - - /// A queued response for the inner text of a given element. - pub element_inner_text_response: String, - - /// A queued response for the viewport dimensions for a given browsing context. - pub inner_window_dimensions_response: Option>, -} - -pub struct LayoutRPCImpl(pub Arc>); - // https://drafts.csswg.org/cssom-view/#overflow-directions fn overflow_direction(writing_mode: &WritingMode) -> OverflowDirection { match ( @@ -128,90 +65,6 @@ fn overflow_direction(writing_mode: &WritingMode) -> OverflowDirection { } } -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) -> ContentBoxResponse { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - ContentBoxResponse(rw_data.content_box_response) - } - - /// Requests the dimensions of all the content boxes, as in the `getClientRects()` call. - fn content_boxes(&self) -> ContentBoxesResponse { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - ContentBoxesResponse(rw_data.content_boxes_response.clone()) - } - - fn nodes_from_point_response(&self) -> Vec { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - rw_data.nodes_from_point_response.clone() - } - - fn node_geometry(&self) -> NodeGeometryResponse { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - NodeGeometryResponse { - client_rect: rw_data.client_rect_response, - } - } - - fn scrolling_area(&self) -> NodeGeometryResponse { - NodeGeometryResponse { - client_rect: self.0.lock().unwrap().scrolling_area_response, - } - } - - fn node_scroll_id(&self) -> NodeScrollIdResponse { - NodeScrollIdResponse( - self.0 - .lock() - .unwrap() - .scroll_id_response - .expect("scroll id is not correctly fetched"), - ) - } - - /// Retrieves the resolved value for a CSS style property. - fn resolved_style(&self) -> ResolvedStyleResponse { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - ResolvedStyleResponse(rw_data.resolved_style_response.clone()) - } - - fn resolved_font_style(&self) -> Option> { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - rw_data.resolved_font_style_response.clone() - } - - fn offset_parent(&self) -> OffsetParentResponse { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - rw_data.offset_parent_response.clone() - } - - fn text_index(&self) -> TextIndexResponse { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - rw_data.text_index_response.clone() - } - - fn element_inner_text(&self) -> String { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - rw_data.element_inner_text_response.clone() - } - - fn inner_window_dimensions(&self) -> Option> { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - rw_data.inner_window_dimensions_response - } -} - struct UnioningFragmentBorderBoxIterator { node_address: OpaqueNode, rect: Option>, @@ -788,14 +641,13 @@ pub fn process_scrolling_area_request( fn create_font_declaration( value: &str, - property: &PropertyId, url_data: &ServoUrl, quirks_mode: QuirksMode, ) -> Option { let mut declarations = SourcePropertyDeclaration::default(); let result = parse_one_declaration_into( &mut declarations, - property.clone(), + PropertyId::Shorthand(ShorthandId::Font), value, Origin::Author, &UrlExtraData(url_data.get_arc()), @@ -839,10 +691,9 @@ where } pub fn process_resolved_font_style_request<'dom, E>( - context: &LayoutContext, + context: &SharedStyleContext, node: E, value: &str, - property: &PropertyId, url_data: ServoUrl, shared_lock: &SharedRwLock, ) -> Option> @@ -853,8 +704,8 @@ where use style::traversal::resolve_style; // 1. Parse the given font property value - let quirks_mode = context.style_context.quirks_mode(); - let declarations = create_font_declaration(value, property, &url_data, quirks_mode)?; + let quirks_mode = context.quirks_mode(); + let declarations = create_font_declaration(value, &url_data, quirks_mode)?; // TODO: Reject 'inherit' and 'initial' values for the font property. @@ -866,7 +717,7 @@ where } else { let mut tlc = ThreadLocalStyleContext::new(); let mut context = StyleContext { - shared: &context.style_context, + shared: context, thread_local: &mut tlc, }; let styles = resolve_style(&mut context, element, RuleInclusion::All, None, None); @@ -874,22 +725,13 @@ where } } else { let default_declarations = - create_font_declaration("10px sans-serif", property, &url_data, quirks_mode).unwrap(); - resolve_for_declarations::( - &context.style_context, - None, - default_declarations, - shared_lock, - ) + create_font_declaration("10px sans-serif", &url_data, quirks_mode).unwrap(); + resolve_for_declarations::(context, None, default_declarations, shared_lock) }; // 3. Resolve the parsed value with resolved styles of the parent element - let computed_values = resolve_for_declarations::( - &context.style_context, - Some(&*parent_style), - declarations, - shared_lock, - ); + let computed_values = + resolve_for_declarations::(context, Some(&*parent_style), declarations, shared_lock); Some(computed_values.clone_font()) } @@ -897,7 +739,7 @@ where /// Return the resolved value of property for a given (pseudo)element. /// pub fn process_resolved_style_request<'dom>( - context: &LayoutContext, + context: &SharedStyleContext, node: impl LayoutNode<'dom>, pseudo: &Option, property: &PropertyId, @@ -921,7 +763,7 @@ pub fn process_resolved_style_request<'dom>( let mut tlc = ThreadLocalStyleContext::new(); let mut context = StyleContext { - shared: &context.style_context, + shared: context, thread_local: &mut tlc, }; @@ -1112,7 +954,7 @@ pub fn process_offset_parent_query( rect: Rect::new(origin, size), } }, - _ => OffsetParentResponse::empty(), + _ => OffsetParentResponse::default(), } } diff --git a/components/layout_2020/query.rs b/components/layout_2020/query.rs index 9dfd573493b..2702fe52117 100644 --- a/components/layout_2020/query.rs +++ b/components/layout_2020/query.rs @@ -3,22 +3,17 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ //! Utilities for querying the layout, as needed by layout. -use std::collections::HashMap; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use app_units::Au; use euclid::default::{Point2D, Rect}; use euclid::{SideOffsets2D, Size2D, Vector2D}; use log::warn; use msg::constellation_msg::PipelineId; -use script_layout_interface::rpc::{ - ContentBoxResponse, ContentBoxesResponse, LayoutRPC, NodeGeometryResponse, - NodeScrollIdResponse, OffsetParentResponse, ResolvedStyleResponse, TextIndexResponse, -}; use script_layout_interface::wrapper_traits::{ LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode, }; -use script_traits::UntrustedNodeAddress; +use script_layout_interface::OffsetParentResponse; use servo_arc::Arc as ServoArc; use servo_url::ServoUrl; use style::computed_values::position::T as Position; @@ -27,7 +22,7 @@ use style::dom::{OpaqueNode, TElement}; use style::properties::style_structs::Font; use style::properties::{ parse_one_declaration_into, ComputedValues, Importance, LonghandId, PropertyDeclarationBlock, - PropertyDeclarationId, PropertyId, SourcePropertyDeclaration, + PropertyDeclarationId, PropertyId, ShorthandId, SourcePropertyDeclaration, }; use style::selector_parser::PseudoElement; use style::shared_lock::SharedRwLock; @@ -35,146 +30,11 @@ use style::stylesheets::{CssRuleType, Origin, UrlExtraData}; use style::stylist::RuleInclusion; use style::traversal::resolve_style; use style::values::generics::text::LineHeight; -use style_traits::{CSSPixel, ParsingMode, ToCss}; -use webrender_api::units::LayoutPixel; -use webrender_api::{DisplayListBuilder, ExternalScrollId}; +use style_traits::{ParsingMode, ToCss}; +use webrender_api::ExternalScrollId; -use crate::context::LayoutContext; use crate::fragment_tree::{Fragment, FragmentFlags, FragmentTree, Tag}; -/// Mutable data belonging to the LayoutThread. -/// -/// This needs to be protected by a mutex so we can do fast RPCs. -pub struct LayoutThreadData { - /// The root stacking context. - pub display_list: Option, - - /// A queued response for the union of the content boxes of a node. - pub content_box_response: Option>, - - /// A queued response for the content boxes of a node. - pub content_boxes_response: Vec>, - - /// A queued response for the client {top, left, width, height} of a node in pixels. - pub client_rect_response: Rect, - - /// A queued response for the scroll id for a given node. - pub scroll_id_response: Option, - - /// A queued response for the scroll {top, left, width, height} of a node in pixels. - pub scrolling_area_response: Rect, - - /// A queued response for the resolved style property of an element. - pub resolved_style_response: String, - - /// A queued response for the resolved font style for canvas. - pub resolved_font_style_response: Option>, - - /// A queued response for the offset parent/rect of a node. - pub offset_parent_response: OffsetParentResponse, - - /// Scroll offsets of scrolling regions. - pub scroll_offsets: HashMap>, - - /// Index in a text fragment. We need this do determine the insertion point. - pub text_index_response: TextIndexResponse, - - /// A queued response for the list of nodes at a given point. - pub nodes_from_point_response: Vec, - - /// A queued response for the inner text of a given element. - pub element_inner_text_response: String, - - /// A queued response for the viewport dimensions for a given browsing context. - pub inner_window_dimensions_response: Option>, -} - -pub struct LayoutRPCImpl(pub Arc>); - -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) -> ContentBoxResponse { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - ContentBoxResponse(rw_data.content_box_response) - } - - /// Requests the dimensions of all the content boxes, as in the `getClientRects()` call. - fn content_boxes(&self) -> ContentBoxesResponse { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - ContentBoxesResponse(rw_data.content_boxes_response.clone()) - } - - fn nodes_from_point_response(&self) -> Vec { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - rw_data.nodes_from_point_response.clone() - } - - fn node_geometry(&self) -> NodeGeometryResponse { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - NodeGeometryResponse { - client_rect: rw_data.client_rect_response, - } - } - - fn scrolling_area(&self) -> NodeGeometryResponse { - NodeGeometryResponse { - client_rect: self.0.lock().unwrap().scrolling_area_response, - } - } - - fn node_scroll_id(&self) -> NodeScrollIdResponse { - NodeScrollIdResponse( - self.0 - .lock() - .unwrap() - .scroll_id_response - .expect("scroll id is not correctly fetched"), - ) - } - - /// Retrieves the resolved value for a CSS style property. - fn resolved_style(&self) -> ResolvedStyleResponse { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - ResolvedStyleResponse(rw_data.resolved_style_response.clone()) - } - - fn resolved_font_style(&self) -> Option> { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - rw_data.resolved_font_style_response.clone() - } - - fn offset_parent(&self) -> OffsetParentResponse { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - rw_data.offset_parent_response.clone() - } - - fn text_index(&self) -> TextIndexResponse { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - rw_data.text_index_response.clone() - } - - fn element_inner_text(&self) -> String { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - rw_data.element_inner_text_response.clone() - } - - fn inner_window_dimensions(&self) -> Option> { - let LayoutRPCImpl(rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - rw_data.inner_window_dimensions_response - } -} - pub fn process_content_box_request( requested_node: OpaqueNode, fragment_tree: Option>, @@ -242,7 +102,7 @@ pub fn process_node_scroll_area_request( /// Return the resolved value of property for a given (pseudo)element. /// pub fn process_resolved_style_request<'dom>( - context: &LayoutContext, + context: &SharedStyleContext, node: impl LayoutNode<'dom>, pseudo: &Option, property: &PropertyId, @@ -386,7 +246,7 @@ pub fn process_resolved_style_request<'dom>( } pub fn process_resolved_style_request_for_unstyled_node<'dom>( - context: &LayoutContext, + context: &SharedStyleContext, node: impl LayoutNode<'dom>, pseudo: &Option, property: &PropertyId, @@ -398,7 +258,7 @@ pub fn process_resolved_style_request_for_unstyled_node<'dom>( let mut tlc = ThreadLocalStyleContext::new(); let mut context = StyleContext { - shared: &context.style_context, + shared: context, thread_local: &mut tlc, }; @@ -449,8 +309,7 @@ pub fn process_offset_parent_query( node: OpaqueNode, fragment_tree: Option>, ) -> OffsetParentResponse { - process_offset_parent_query_inner(node, fragment_tree) - .unwrap_or_else(OffsetParentResponse::empty) + process_offset_parent_query_inner(node, fragment_tree).unwrap_or_default() } #[inline] @@ -656,14 +515,13 @@ pub fn process_element_inner_text_query<'dom>(_node: impl LayoutNode<'dom>) -> S "".to_owned() } -pub fn process_text_index_request(_node: OpaqueNode, _point: Point2D) -> TextIndexResponse { - TextIndexResponse(None) +pub fn process_text_index_request(_node: OpaqueNode, _point: Point2D) -> Option { + None } pub fn process_resolved_font_style_query<'dom, E>( - context: &LayoutContext, + context: &SharedStyleContext, node: E, - property: &PropertyId, value: &str, url_data: ServoUrl, shared_lock: &SharedRwLock, @@ -673,14 +531,13 @@ where { fn create_font_declaration( value: &str, - property: &PropertyId, url_data: &ServoUrl, quirks_mode: QuirksMode, ) -> Option { let mut declarations = SourcePropertyDeclaration::default(); let result = parse_one_declaration_into( &mut declarations, - property.clone(), + PropertyId::Shorthand(ShorthandId::Font), value, Origin::Author, &UrlExtraData(url_data.get_arc()), @@ -724,8 +581,8 @@ where // https://html.spec.whatwg.org/multipage/#dom-context-2d-font // 1. Parse the given font property value - let quirks_mode = context.style_context.quirks_mode(); - let declarations = create_font_declaration(value, property, &url_data, quirks_mode)?; + let quirks_mode = context.quirks_mode(); + let declarations = create_font_declaration(value, &url_data, quirks_mode)?; // TODO: Reject 'inherit' and 'initial' values for the font property. @@ -737,7 +594,7 @@ where } else { let mut tlc = ThreadLocalStyleContext::new(); let mut context = StyleContext { - shared: &context.style_context, + shared: context, thread_local: &mut tlc, }; let styles = resolve_style(&mut context, element, RuleInclusion::All, None, None); @@ -745,22 +602,13 @@ where } } else { let default_declarations = - create_font_declaration("10px sans-serif", property, &url_data, quirks_mode).unwrap(); - resolve_for_declarations::( - &context.style_context, - None, - default_declarations, - shared_lock, - ) + create_font_declaration("10px sans-serif", &url_data, quirks_mode).unwrap(); + resolve_for_declarations::(context, None, default_declarations, shared_lock) }; // 3. Resolve the parsed value with resolved styles of the parent element - let computed_values = resolve_for_declarations::( - &context.style_context, - Some(&*parent_style), - declarations, - shared_lock, - ); + let computed_values = + resolve_for_declarations::(context, Some(&*parent_style), declarations, shared_lock); Some(computed_values.clone_font()) } diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index c54d65700b0..beeb30ae9cf 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -14,11 +14,11 @@ use std::collections::HashMap; use std::ops::{Deref, DerefMut}; use std::process; use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::{Arc, Mutex, MutexGuard}; +use std::sync::{Arc, Mutex}; use app_units::Au; use embedder_traits::resources::{self, Resource}; -use euclid::default::Size2D as UntypedSize2D; +use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect, Size2D as UntypedSize2D}; use euclid::{Point2D, Rect, Scale, Size2D}; use fnv::FnvHashMap; use fxhash::{FxHashMap, FxHashSet}; @@ -32,7 +32,7 @@ use layout::construct::ConstructionResult; use layout::context::{ malloc_size_of_persistent_local_context, LayoutContext, RegisteredPainter, RegisteredPainters, }; -use layout::display_list::items::WebRenderImageInfo; +use layout::display_list::items::{DisplayList, ScrollOffsetMap, WebRenderImageInfo}; use layout::display_list::{IndexableText, ToLayout}; use layout::flow::{Flow, FlowFlags, GetBaseFlow, ImmutableFlowUtils, MutableOwnedFlowUtils}; use layout::flow_ref::FlowRef; @@ -41,7 +41,7 @@ use layout::query::{ process_client_rect_query, process_content_box_request, process_content_boxes_request, process_element_inner_text_query, process_node_scroll_id_request, process_offset_parent_query, process_resolved_font_style_request, process_resolved_style_request, - process_scrolling_area_request, LayoutRPCImpl, LayoutThreadData, + process_scrolling_area_request, }; use layout::traversal::{ construct_flows_at_ancestors, ComputeStackingRelativePositions, PreorderFlowTraversal, @@ -63,11 +63,12 @@ use profile_traits::time::{ }; use script::layout_dom::{ServoLayoutDocument, ServoLayoutElement, ServoLayoutNode}; use script_layout_interface::message::{ - Msg, NodesFromPointQueryType, QueryMsg, Reflow, ReflowComplete, ReflowGoal, ScriptReflow, + Msg, NodesFromPointQueryType, Reflow, ReflowComplete, ReflowGoal, ScriptReflow, }; -use script_layout_interface::rpc::{LayoutRPC, OffsetParentResponse, TextIndexResponse}; use script_layout_interface::wrapper_traits::LayoutNode; -use script_layout_interface::{Layout, LayoutConfig, LayoutFactory}; +use script_layout_interface::{ + Layout, LayoutConfig, LayoutFactory, OffsetParentResponse, TrustedNodeAddress, +}; use script_traits::{ ConstellationControlMsg, DrawAPaintImageResult, IFrameSizeMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg, PaintWorkletError, Painter, ScrollState, UntrustedNodeAddress, @@ -81,13 +82,14 @@ use style::animation::{AnimationSetKey, DocumentAnimationSet, ElementAnimationSe use style::context::{ QuirksMode, RegisteredSpeculativePainter, RegisteredSpeculativePainters, SharedStyleContext, }; -use style::dom::{ShowSubtree, ShowSubtreeDataAndPrimaryValues, TElement, TNode}; +use style::dom::{OpaqueNode, ShowSubtree, ShowSubtreeDataAndPrimaryValues, TElement, TNode}; use style::driver; use style::error_reporting::RustLogReporter; use style::global_style_data::{GLOBAL_STYLE_DATA, STYLE_THREAD_POOL}; use style::invalidation::element::restyle_hints::RestyleHint; use style::logical_geometry::LogicalPoint; use style::media_queries::{Device, MediaList, MediaType}; +use style::properties::style_structs::Font; use style::properties::PropertyId; use style::selector_parser::{PseudoElement, SnapshotMap}; use style::servo::restyle_damage::ServoRestyleDamage; @@ -158,11 +160,14 @@ pub struct LayoutThread { /// constraints. viewport_size: UntypedSize2D, - /// A mutex to allow for fast, read-only RPC of layout's internal data - /// structures, while still letting the LayoutThread modify them. - /// - /// All the other elements of this struct are read-only. - rw_data: Arc>, + /// The root stacking context. + display_list: RefCell>, + + /// A map that stores all of the indexable text in this layout. + indexable_text: RefCell, + + /// Scroll offsets of scrolling regions. + scroll_offsets: RefCell, webrender_image_cache: Arc>>, @@ -245,56 +250,6 @@ impl Drop for ScriptReflowResult { } } -/// The `LayoutThread` `rw_data` lock must remain locked until the first reflow, -/// as RPC calls don't make sense until then. Use this in combination with -/// `LayoutThread::lock_rw_data` and `LayoutThread::return_rw_data`. -pub enum RWGuard<'a> { - /// If the lock was previously held, from when the thread started. - Held(MutexGuard<'a, LayoutThreadData>), - /// If the lock was just used, and has been returned since there has been - /// a reflow already. - Used(MutexGuard<'a, LayoutThreadData>), -} - -impl<'a> Deref for RWGuard<'a> { - type Target = LayoutThreadData; - fn deref(&self) -> &LayoutThreadData { - match *self { - RWGuard::Held(ref x) => &**x, - RWGuard::Used(ref x) => &**x, - } - } -} - -impl<'a> DerefMut for RWGuard<'a> { - fn deref_mut(&mut self) -> &mut LayoutThreadData { - match *self { - RWGuard::Held(ref mut x) => &mut **x, - RWGuard::Used(ref mut x) => &mut **x, - } - } -} - -struct RwData<'a, 'b: 'a> { - rw_data: &'b Arc>, - possibly_locked_rw_data: &'a mut Option>, -} - -impl<'a, 'b: 'a> RwData<'a, 'b> { - /// If no reflow has happened yet, this will just return the lock in - /// `possibly_locked_rw_data`. Otherwise, it will acquire the `rw_data` lock. - /// - /// If you do not wish RPCs to remain blocked, just drop the `RWGuard` - /// returned from this function. If you _do_ wish for them to remain blocked, - /// use `block`. - fn lock(&mut self) -> RWGuard<'b> { - match self.possibly_locked_rw_data.take() { - None => RWGuard::Used(self.rw_data.lock().unwrap()), - Some(x) => RWGuard::Held(x), - } - } -} - impl Layout for LayoutThread { fn process(&mut self, msg: script_layout_interface::message::Msg) { self.handle_request(Request::FromScript(msg)); @@ -308,10 +263,6 @@ impl Layout for LayoutThread { self.handle_request(Request::FromFontCache); } - fn rpc(&self) -> Box { - Box::new(LayoutRPCImpl(self.rw_data.clone())) as Box - } - fn waiting_for_web_fonts_to_load(&self) -> bool { self.outstanding_web_fonts.load(Ordering::SeqCst) != 0 } @@ -350,6 +301,178 @@ impl Layout for LayoutThread { self.stylist .remove_stylesheet(DocumentStyleSheet(stylesheet.clone()), &guard); } + + fn query_content_box(&self, node: OpaqueNode) -> Option> { + let Some(mut root_flow) = self.root_flow_for_query() else { + return None; + }; + + let root_flow_ref = FlowRef::deref_mut(&mut root_flow); + process_content_box_request(node, root_flow_ref) + } + + fn query_content_boxes(&self, node: OpaqueNode) -> Vec> { + let Some(mut root_flow) = self.root_flow_for_query() else { + return vec![]; + }; + let root_flow_ref = FlowRef::deref_mut(&mut root_flow); + process_content_boxes_request(node, root_flow_ref) + } + + fn query_client_rect(&self, node: OpaqueNode) -> UntypedRect { + let Some(mut root_flow) = self.root_flow_for_query() else { + return UntypedRect::zero(); + }; + let root_flow_ref = FlowRef::deref_mut(&mut root_flow); + process_client_rect_query(node, root_flow_ref) + } + + fn query_element_inner_text( + &self, + node: script_layout_interface::TrustedNodeAddress, + ) -> String { + let node: ServoLayoutNode = unsafe { ServoLayoutNode::new(&node) }; + process_element_inner_text_query(node, &self.indexable_text.borrow()) + } + + fn query_inner_window_dimension( + &self, + browsing_context_id: BrowsingContextId, + ) -> Option> { + self.last_iframe_sizes + .borrow() + .get(&browsing_context_id) + .cloned() + } + + fn query_nodes_from_point( + &self, + point: UntypedPoint2D, + query_type: NodesFromPointQueryType, + ) -> Vec { + let mut flags = match query_type { + NodesFromPointQueryType::Topmost => HitTestFlags::empty(), + NodesFromPointQueryType::All => HitTestFlags::FIND_ALL, + }; + + // The point we get is not relative to the entire WebRender scene, but to this + // particular pipeline, so we need to tell WebRender about that. + flags.insert(HitTestFlags::POINT_RELATIVE_TO_PIPELINE_VIEWPORT); + + let client_point = units::DevicePoint::from_untyped(point); + let results = + self.webrender_api + .hit_test(Some(self.id.to_webrender()), client_point, flags); + + results.iter().map(|result| result.node).collect() + } + + fn query_offset_parent(&self, node: OpaqueNode) -> OffsetParentResponse { + let Some(mut root_flow) = self.root_flow_for_query() else { + return OffsetParentResponse::default(); + }; + let root_flow_ref = FlowRef::deref_mut(&mut root_flow); + process_offset_parent_query(node, root_flow_ref) + } + + fn query_resolved_style( + &self, + node: TrustedNodeAddress, + pseudo: Option, + property_id: PropertyId, + animations: DocumentAnimationSet, + animation_timeline_value: f64, + ) -> String { + let node: ServoLayoutNode = unsafe { ServoLayoutNode::new(&node) }; + let document = node.owner_doc(); + let document_shared_lock = document.style_shared_lock(); + let guards = StylesheetGuards { + author: &document_shared_lock.read(), + ua_or_user: &UA_STYLESHEETS.shared_lock.read(), + }; + let snapshot_map = SnapshotMap::new(); + + let shared_style_context = self.build_shared_style_context( + guards, + &snapshot_map, + animation_timeline_value, + &animations, + TraversalFlags::empty(), + ); + + let Some(mut root_flow) = self.root_flow_for_query() else { + return String::new(); + }; + let root_flow_ref = FlowRef::deref_mut(&mut root_flow); + + process_resolved_style_request( + &shared_style_context, + node, + &pseudo, + &property_id, + root_flow_ref, + ) + } + + fn query_resolved_font_style( + &self, + node: TrustedNodeAddress, + value: &str, + animations: DocumentAnimationSet, + animation_timeline_value: f64, + ) -> Option> { + let node: ServoLayoutNode = unsafe { ServoLayoutNode::new(&node) }; + let document = node.owner_doc(); + let document_shared_lock = document.style_shared_lock(); + let guards = StylesheetGuards { + author: &document_shared_lock.read(), + ua_or_user: &UA_STYLESHEETS.shared_lock.read(), + }; + let snapshot_map = SnapshotMap::new(); + let shared_style_context = self.build_shared_style_context( + guards, + &snapshot_map, + animation_timeline_value, + &animations, + TraversalFlags::empty(), + ); + + process_resolved_font_style_request( + &shared_style_context, + node, + value, + self.url.clone(), + document_shared_lock, + ) + } + + fn query_scroll_id( + &self, + node: script_layout_interface::TrustedNodeAddress, + ) -> webrender_api::ExternalScrollId { + let node: ServoLayoutNode = unsafe { ServoLayoutNode::new(&node) }; + process_node_scroll_id_request(self.id, node) + } + + fn query_scrolling_area(&self, node: Option) -> UntypedRect { + let Some(mut root_flow) = self.root_flow_for_query() else { + return UntypedRect::zero(); + }; + let root_flow_ref = FlowRef::deref_mut(&mut root_flow); + process_scrolling_area_request(node, root_flow_ref) + } + + fn query_text_indext( + &self, + node: OpaqueNode, + point_in_node: UntypedPoint2D, + ) -> Option { + let point_in_node = Point2D::new( + Au::from_f32_px(point_in_node.x), + Au::from_f32_px(point_in_node.y), + ); + self.indexable_text.borrow().text_index(node, point_in_node) + } } enum Request { FromPipeline(LayoutControlMsg), @@ -358,6 +481,10 @@ enum Request { } impl LayoutThread { + fn root_flow_for_query(&self) -> Option { + self.root_flow.borrow().clone() + } + fn new( id: PipelineId, url: ServoUrl, @@ -397,7 +524,7 @@ impl LayoutThread { url, is_iframe, script_chan, - constellation_chan: constellation_chan.clone(), + constellation_chan, time_profiler_chan, registered_painters: RegisteredPaintersImpl(Default::default()), image_cache, @@ -416,24 +543,9 @@ impl LayoutThread { ), webrender_api, stylist: Stylist::new(device, QuirksMode::NoQuirks), - rw_data: Arc::new(Mutex::new(LayoutThreadData { - constellation_chan, - display_list: None, - indexable_text: IndexableText::default(), - content_box_response: None, - content_boxes_response: Vec::new(), - client_rect_response: Rect::zero(), - scroll_id_response: None, - scrolling_area_response: Rect::zero(), - resolved_style_response: String::new(), - resolved_font_style_response: None, - offset_parent_response: OffsetParentResponse::empty(), - scroll_offsets: HashMap::new(), - text_index_response: TextIndexResponse(None), - nodes_from_point_response: vec![], - element_inner_text_response: String::new(), - inner_window_dimensions_response: None, - })), + display_list: Default::default(), + indexable_text: Default::default(), + scroll_offsets: Default::default(), webrender_image_cache: Arc::new(RwLock::new(FnvHashMap::default())), paint_time_metrics, layout_query_waiting_time: Histogram::new(), @@ -443,6 +555,27 @@ impl LayoutThread { } } + fn build_shared_style_context<'a>( + &'a self, + guards: StylesheetGuards<'a>, + snapshot_map: &'a SnapshotMap, + animation_timeline_value: f64, + animations: &DocumentAnimationSet, + traversal_flags: TraversalFlags, + ) -> SharedStyleContext<'a> { + SharedStyleContext { + stylist: &self.stylist, + options: GLOBAL_STYLE_DATA.options.clone(), + guards, + visited_styles_enabled: false, + animations: animations.clone(), + registered_speculative_painters: &self.registered_painters, + current_time_for_animations: animation_timeline_value, + traversal_flags, + snapshot_map, + } + } + // Create a layout context for use in building display lists, hit testing, &c. fn build_layout_context<'a>( &'a self, @@ -461,17 +594,13 @@ impl LayoutThread { LayoutContext { id: self.id, origin, - style_context: SharedStyleContext { - stylist: &self.stylist, - options: GLOBAL_STYLE_DATA.options.clone(), + style_context: self.build_shared_style_context( guards, - visited_styles_enabled: false, - animations: animations.clone(), - registered_speculative_painters: &self.registered_painters, - current_time_for_animations: animation_timeline_value, - traversal_flags, snapshot_map, - }, + animation_timeline_value, + animations, + traversal_flags, + ), image_cache: self.image_cache.clone(), font_cache_thread: Mutex::new(self.font_cache_thread.clone()), webrender_image_cache: self.webrender_image_cache.clone(), @@ -482,26 +611,18 @@ impl LayoutThread { /// Receives and dispatches messages from the script and constellation threads fn handle_request<'a, 'b>(&mut self, request: Request) { - let rw_data = self.rw_data.clone(); - let mut possibly_locked_rw_data = Some(rw_data.lock().unwrap()); - let mut rw_data = RwData { - rw_data: &rw_data, - possibly_locked_rw_data: &mut possibly_locked_rw_data, - }; - match request { Request::FromPipeline(LayoutControlMsg::SetScrollStates(new_scroll_states)) => { - self.handle_request_helper(Msg::SetScrollStates(new_scroll_states), &mut rw_data) + self.handle_request_helper(Msg::SetScrollStates(new_scroll_states)) }, Request::FromPipeline(LayoutControlMsg::ExitNow) => { - self.handle_request_helper(Msg::ExitNow, &mut rw_data); + self.handle_request_helper(Msg::ExitNow); }, Request::FromPipeline(LayoutControlMsg::PaintMetric(epoch, paint_time)) => { self.paint_time_metrics.maybe_set_metric(epoch, paint_time); }, - Request::FromScript(msg) => self.handle_request_helper(msg, &mut rw_data), + Request::FromScript(msg) => self.handle_request_helper(msg), Request::FromFontCache => { - let _rw_data = rw_data.lock(); self.outstanding_web_fonts.fetch_sub(1, Ordering::SeqCst); self.handle_web_font_loaded(); }, @@ -509,32 +630,23 @@ impl LayoutThread { } /// Receives and dispatches messages from other threads. - fn handle_request_helper( - &mut self, - request: Msg, - possibly_locked_rw_data: &mut RwData<'_, '_>, - ) { + fn handle_request_helper(&mut self, request: Msg) { match request { Msg::SetQuirksMode(mode) => self.handle_set_quirks_mode(mode), - Msg::GetRPC(response_chan) => { - response_chan - .send(Box::new(LayoutRPCImpl(self.rw_data.clone())) as Box) - .unwrap(); - }, Msg::Reflow(data) => { let mut data = ScriptReflowResult::new(data); profile( profile_time::ProfilerCategory::LayoutPerform, self.profiler_metadata(), self.time_profiler_chan.clone(), - || self.handle_reflow(&mut data, possibly_locked_rw_data), + || self.handle_reflow(&mut data), ); }, Msg::SetScrollStates(new_scroll_states) => { - self.set_scroll_states(new_scroll_states, possibly_locked_rw_data); + self.set_scroll_states(new_scroll_states); }, Msg::CollectReports(reports_chan) => { - self.collect_reports(reports_chan, possibly_locked_rw_data); + self.collect_reports(reports_chan); }, Msg::RegisterPaint(name, mut properties, painter) => { debug!("Registering the painter"); @@ -561,24 +673,20 @@ impl LayoutThread { } } - fn collect_reports( - &self, - reports_chan: ReportsChan, - possibly_locked_rw_data: &mut RwData<'_, '_>, - ) { + fn collect_reports(&self, reports_chan: ReportsChan) { let mut reports = vec![]; // Servo uses vanilla jemalloc, which doesn't have a // malloc_enclosing_size_of function. let mut ops = MallocSizeOfOps::new(servo_allocator::usable_size, None, None); // FIXME(njn): Just measuring the display tree for now. - let rw_data = possibly_locked_rw_data.lock(); - let display_list = rw_data.display_list.as_ref(); + let display_list = self.display_list.borrow(); + let display_list_ref = display_list.as_ref(); let formatted_url = &format!("url({})", self.url); reports.push(Report { path: path![formatted_url, "layout-thread", "display-list"], kind: ReportKind::ExplicitJemallocHeapSize, - size: display_list.map_or(0, |sc| sc.size_of(&mut ops)), + size: display_list_ref.map_or(0, |sc| sc.size_of(&mut ops)), }); reports.push(Report { @@ -768,7 +876,6 @@ impl LayoutThread { document: Option<&ServoLayoutDocument>, layout_root: &mut dyn Flow, layout_context: &mut LayoutContext, - rw_data: &mut LayoutThreadData, ) { let writing_mode = layout_root.base().writing_mode; let (metadata, sender) = (self.profiler_metadata(), self.time_profiler_chan.clone()); @@ -791,7 +898,7 @@ impl LayoutThread { .base() .restyle_damage .contains(ServoRestyleDamage::REPAINT) || - rw_data.display_list.is_none() + self.display_list.borrow().is_none() { if reflow_goal.needs_display_list() { let background_color = get_root_flow_background_color(layout_root); @@ -817,8 +924,9 @@ impl LayoutThread { let iframe_sizes = std::mem::take(&mut build_state.iframe_sizes); self.update_iframe_sizes(iframe_sizes); - rw_data.indexable_text = std::mem::take(&mut build_state.indexable_text); - rw_data.display_list = Some(build_state.to_display_list()); + *self.indexable_text.borrow_mut() = + std::mem::take(&mut build_state.indexable_text); + *self.display_list.borrow_mut() = Some(build_state.to_display_list()); } } @@ -836,8 +944,8 @@ impl LayoutThread { document.will_paint(); } - let display_list = rw_data.display_list.as_mut().unwrap(); - + let mut display_list = self.display_list.borrow_mut(); + let display_list = display_list.as_mut().unwrap(); if self.debug.dump_display_list { display_list.print(); } @@ -873,11 +981,7 @@ impl LayoutThread { } /// The high-level routine that performs layout. - fn handle_reflow( - &mut self, - data: &mut ScriptReflowResult, - possibly_locked_rw_data: &mut RwData<'_, '_>, - ) { + fn handle_reflow(&mut self, data: &mut ScriptReflowResult) { let document = unsafe { ServoLayoutNode::new(&data.document) }; let document = document.as_document().unwrap(); @@ -888,8 +992,6 @@ impl LayoutThread { debug!("Number of objects in DOM: {}", data.dom_count); debug!("layout: parallel? {}", self.parallel_flag); - let mut rw_data = possibly_locked_rw_data.lock(); - // Record the time that layout query has been waited. let now = time::precise_time_ns(); if let ReflowGoal::LayoutQuery(_, timestamp) = data.reflow_goal { @@ -898,57 +1000,9 @@ impl LayoutThread { .expect("layout: wrong layout query timestamp"); }; - let root_element = match document.root_element() { - None => { - // Since we cannot compute anything, give spec-required placeholders. - debug!("layout: No root node: bailing"); - match data.reflow_goal { - ReflowGoal::LayoutQuery(ref query_msg, _) => match query_msg { - &QueryMsg::ContentBoxQuery(_) => { - rw_data.content_box_response = None; - }, - &QueryMsg::ContentBoxesQuery(_) => { - rw_data.content_boxes_response = Vec::new(); - }, - &QueryMsg::NodesFromPointQuery(..) => { - rw_data.nodes_from_point_response = Vec::new(); - }, - &QueryMsg::ClientRectQuery(_) => { - rw_data.client_rect_response = Rect::zero(); - }, - &QueryMsg::ScrollingAreaQuery(_) => { - rw_data.scrolling_area_response = Rect::zero(); - }, - &QueryMsg::NodeScrollIdQuery(_) => { - rw_data.scroll_id_response = None; - }, - &QueryMsg::ResolvedStyleQuery(_, _, _) => { - rw_data.resolved_style_response = String::new(); - }, - &QueryMsg::OffsetParentQuery(_) => { - rw_data.offset_parent_response = OffsetParentResponse::empty(); - }, - &QueryMsg::StyleQuery => {}, - &QueryMsg::TextIndexQuery(..) => { - rw_data.text_index_response = TextIndexResponse(None); - }, - &QueryMsg::ElementInnerTextQuery(_) => { - rw_data.element_inner_text_response = String::new(); - }, - &QueryMsg::ResolvedFontStyleQuery(..) => { - rw_data.resolved_font_style_response = None; - }, - &QueryMsg::InnerWindowDimensionsQuery(_) => { - rw_data.inner_window_dimensions_response = None; - }, - }, - ReflowGoal::Full | - ReflowGoal::TickAnimations | - ReflowGoal::UpdateScrollNode(_) => {}, - } - return; - }, - Some(x) => x, + let Some(root_element) = document.root_element() else { + debug!("layout: No root node: bailing"); + return; }; debug!( @@ -1156,129 +1210,24 @@ impl LayoutThread { &data.reflow_info, &data.reflow_goal, Some(&document), - &mut rw_data, &mut layout_context, thread_pool, ); } self.first_reflow.set(false); - self.respond_to_query_if_necessary( - &data.reflow_goal, - &mut *rw_data, - &mut layout_context, - data.result.borrow_mut().as_mut().unwrap(), - document_shared_lock, - ); - } - fn respond_to_query_if_necessary( - &self, - reflow_goal: &ReflowGoal, - rw_data: &mut LayoutThreadData, - context: &mut LayoutContext, - reflow_result: &mut ReflowComplete, - shared_lock: &SharedRwLock, - ) { - reflow_result.pending_images = std::mem::take(&mut *context.pending_images.lock().unwrap()); + data.result.borrow_mut().as_mut().unwrap().pending_images = + std::mem::take(&mut *layout_context.pending_images.lock().unwrap()); - let mut root_flow = match self.root_flow.borrow().clone() { - Some(root_flow) => root_flow, - None => return, - }; - let root_flow = FlowRef::deref_mut(&mut root_flow); - match *reflow_goal { - ReflowGoal::LayoutQuery(ref querymsg, _) => match querymsg { - &QueryMsg::ContentBoxQuery(node) => { - rw_data.content_box_response = process_content_box_request(node, root_flow); - }, - &QueryMsg::ContentBoxesQuery(node) => { - rw_data.content_boxes_response = process_content_boxes_request(node, root_flow); - }, - &QueryMsg::TextIndexQuery(node, point_in_node) => { - let point_in_node = Point2D::new( - Au::from_f32_px(point_in_node.x), - Au::from_f32_px(point_in_node.y), - ); - rw_data.text_index_response = - TextIndexResponse(rw_data.indexable_text.text_index(node, point_in_node)); - }, - &QueryMsg::ClientRectQuery(node) => { - rw_data.client_rect_response = process_client_rect_query(node, root_flow); - }, - &QueryMsg::ScrollingAreaQuery(node) => { - rw_data.scrolling_area_response = - process_scrolling_area_request(node, root_flow); - }, - &QueryMsg::NodeScrollIdQuery(node) => { - let node: ServoLayoutNode = unsafe { ServoLayoutNode::new(&node) }; - rw_data.scroll_id_response = - Some(process_node_scroll_id_request(self.id, node)); - }, - &QueryMsg::ResolvedStyleQuery(node, ref pseudo, ref property) => { - let node: ServoLayoutNode = unsafe { ServoLayoutNode::new(&node) }; - rw_data.resolved_style_response = - process_resolved_style_request(context, node, pseudo, property, root_flow); - }, - &QueryMsg::ResolvedFontStyleQuery(node, ref property, ref value) => { - let node: ServoLayoutNode = unsafe { ServoLayoutNode::new(&node) }; - let url = self.url.clone(); - rw_data.resolved_font_style_response = process_resolved_font_style_request( - context, - node, - value, - property, - url, - shared_lock, - ); - }, - &QueryMsg::OffsetParentQuery(node) => { - rw_data.offset_parent_response = process_offset_parent_query(node, root_flow); - }, - &QueryMsg::StyleQuery => {}, - &QueryMsg::NodesFromPointQuery(client_point, ref reflow_goal) => { - let mut flags = match reflow_goal { - &NodesFromPointQueryType::Topmost => HitTestFlags::empty(), - &NodesFromPointQueryType::All => HitTestFlags::FIND_ALL, - }; - - // The point we get is not relative to the entire WebRender scene, but to this - // particular pipeline, so we need to tell WebRender about that. - flags.insert(HitTestFlags::POINT_RELATIVE_TO_PIPELINE_VIEWPORT); - - let client_point = units::DevicePoint::from_untyped(client_point); - let results = self.webrender_api.hit_test( - Some(self.id.to_webrender()), - client_point, - flags, - ); - - rw_data.nodes_from_point_response = - results.iter().map(|result| result.node).collect() - }, - &QueryMsg::ElementInnerTextQuery(node) => { - let node: ServoLayoutNode = unsafe { ServoLayoutNode::new(&node) }; - rw_data.element_inner_text_response = - process_element_inner_text_query(node, &rw_data.indexable_text); - }, - &QueryMsg::InnerWindowDimensionsQuery(browsing_context_id) => { - rw_data.inner_window_dimensions_response = self - .last_iframe_sizes - .borrow() - .get(&browsing_context_id) - .cloned(); - }, - }, - ReflowGoal::UpdateScrollNode(scroll_state) => { - self.update_scroll_node_state(&scroll_state, rw_data); - }, - ReflowGoal::Full | ReflowGoal::TickAnimations => {}, + if let ReflowGoal::UpdateScrollNode(scroll_state) = data.reflow_goal { + self.update_scroll_node_state(&scroll_state); } } - fn update_scroll_node_state(&self, state: &ScrollState, rw_data: &mut LayoutThreadData) { - rw_data - .scroll_offsets + fn update_scroll_node_state(&self, state: &ScrollState) { + self.scroll_offsets + .borrow_mut() .insert(state.scroll_id, state.scroll_offset); let point = Point2D::new(-state.scroll_offset.x, -state.scroll_offset.y); @@ -1289,12 +1238,7 @@ impl LayoutThread { ); } - fn set_scroll_states( - &mut self, - new_scroll_states: Vec, - possibly_locked_rw_data: &mut RwData<'_, '_>, - ) { - let mut rw_data = possibly_locked_rw_data.lock(); + fn set_scroll_states(&mut self, new_scroll_states: Vec) { let mut script_scroll_states = vec![]; let mut layout_scroll_states = HashMap::new(); for new_state in &new_scroll_states { @@ -1313,7 +1257,7 @@ impl LayoutThread { self.id, script_scroll_states, )); - rw_data.scroll_offsets = layout_scroll_states + *self.scroll_offsets.borrow_mut() = layout_scroll_states } /// Cancel animations for any nodes which have been removed from flow tree. @@ -1363,7 +1307,6 @@ impl LayoutThread { data: &Reflow, reflow_goal: &ReflowGoal, document: Option<&ServoLayoutDocument>, - rw_data: &mut LayoutThreadData, context: &mut LayoutContext, thread_pool: Option<&rayon::ThreadPool>, ) { @@ -1449,14 +1392,7 @@ impl LayoutThread { }, ); - self.perform_post_main_layout_passes( - data, - root_flow, - reflow_goal, - document, - rw_data, - context, - ); + self.perform_post_main_layout_passes(data, root_flow, reflow_goal, document, context); } fn perform_post_main_layout_passes( @@ -1465,7 +1401,6 @@ impl LayoutThread { mut root_flow: &mut FlowRef, reflow_goal: &ReflowGoal, document: Option<&ServoLayoutDocument>, - rw_data: &mut LayoutThreadData, layout_context: &mut LayoutContext, ) { // Build the display list if necessary, and send it to the painter. @@ -1475,7 +1410,6 @@ impl LayoutThread { document, FlowRef::deref_mut(&mut root_flow), &mut *layout_context, - rw_data, ); if self.debug.trace_layout { diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs index 760bdc85240..b5d9c97b171 100644 --- a/components/layout_thread_2020/lib.rs +++ b/components/layout_thread_2020/lib.rs @@ -13,12 +13,12 @@ use std::collections::HashMap; use std::ops::{Deref, DerefMut}; use std::process; use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::{Arc, Mutex, MutexGuard}; +use std::sync::{Arc, Mutex}; use app_units::Au; use embedder_traits::resources::{self, Resource}; -use euclid::default::Size2D as UntypedSize2D; -use euclid::{Point2D, Rect, Scale, Size2D}; +use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect, Size2D as UntypedSize2D}; +use euclid::{Point2D, Scale, Size2D, Vector2D}; use fnv::FnvHashMap; use fxhash::FxHashMap; use gfx::font_cache_thread::FontCacheThread; @@ -33,7 +33,7 @@ use layout::query::{ process_content_box_request, process_content_boxes_request, process_element_inner_text_query, process_node_geometry_request, process_node_scroll_area_request, process_node_scroll_id_request, process_offset_parent_query, process_resolved_font_style_query, - process_resolved_style_request, process_text_index_request, LayoutRPCImpl, LayoutThreadData, + process_resolved_style_request, process_text_index_request, }; use layout::traversal::RecalcStyle; use layout::{layout_debug, BoxTree, FragmentTree}; @@ -51,10 +51,11 @@ use profile_traits::time::{ }; use script::layout_dom::{ServoLayoutDocument, ServoLayoutElement, ServoLayoutNode}; use script_layout_interface::message::{ - Msg, NodesFromPointQueryType, QueryMsg, ReflowComplete, ReflowGoal, ScriptReflow, + Msg, NodesFromPointQueryType, ReflowComplete, ReflowGoal, ScriptReflow, +}; +use script_layout_interface::{ + Layout, LayoutConfig, LayoutFactory, OffsetParentResponse, TrustedNodeAddress, }; -use script_layout_interface::rpc::{LayoutRPC, OffsetParentResponse, TextIndexResponse}; -use script_layout_interface::{Layout, LayoutConfig, LayoutFactory}; use script_traits::{ ConstellationControlMsg, DrawAPaintImageResult, IFrameSizeMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg, PaintWorkletError, Painter, ScrollState, UntrustedNodeAddress, @@ -68,14 +69,15 @@ use style::animation::DocumentAnimationSet; use style::context::{ QuirksMode, RegisteredSpeculativePainter, RegisteredSpeculativePainters, SharedStyleContext, }; -use style::dom::{TElement, TNode}; +use style::dom::{OpaqueNode, TElement, TNode}; use style::driver; use style::error_reporting::RustLogReporter; use style::global_style_data::{GLOBAL_STYLE_DATA, STYLE_THREAD_POOL}; use style::invalidation::element::restyle_hints::RestyleHint; use style::media_queries::{Device, MediaList, MediaType}; +use style::properties::style_structs::Font; use style::properties::PropertyId; -use style::selector_parser::SnapshotMap; +use style::selector_parser::{PseudoElement, SnapshotMap}; use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards}; use style::stylesheets::{ DocumentStyleSheet, Origin, Stylesheet, StylesheetInDocument, UrlExtraData, @@ -86,7 +88,8 @@ use style::traversal::DomTraversal; use style::traversal_flags::TraversalFlags; use style_traits::{CSSPixel, DevicePixel, SpeculativePainter}; use url::Url; -use webrender_api::{units, HitTestFlags}; +use webrender_api::units::LayoutPixel; +use webrender_api::{units, ExternalScrollId, HitTestFlags}; /// Information needed by layout. pub struct LayoutThread { @@ -143,11 +146,8 @@ pub struct LayoutThread { /// constraints. viewport_size: UntypedSize2D, - /// A mutex to allow for fast, read-only RPC of layout's internal data - /// structures, while still letting the LayoutThread modify them. - /// - /// All the other elements of this struct are read-only. - rw_data: Arc>, + /// Scroll offsets of nodes that scroll. + scroll_offsets: RefCell>>, webrender_image_cache: Arc>>, @@ -224,56 +224,6 @@ impl Drop for ScriptReflowResult { } } -/// The `LayoutThread` `rw_data` lock must remain locked until the first reflow, -/// as RPC calls don't make sense until then. Use this in combination with -/// `LayoutThread::lock_rw_data` and `LayoutThread::return_rw_data`. -pub enum RWGuard<'a> { - /// If the lock was previously held, from when the thread started. - Held(MutexGuard<'a, LayoutThreadData>), - /// If the lock was just used, and has been returned since there has been - /// a reflow already. - Used(MutexGuard<'a, LayoutThreadData>), -} - -impl<'a> Deref for RWGuard<'a> { - type Target = LayoutThreadData; - fn deref(&self) -> &LayoutThreadData { - match *self { - RWGuard::Held(ref x) => &**x, - RWGuard::Used(ref x) => &**x, - } - } -} - -impl<'a> DerefMut for RWGuard<'a> { - fn deref_mut(&mut self) -> &mut LayoutThreadData { - match *self { - RWGuard::Held(ref mut x) => &mut **x, - RWGuard::Used(ref mut x) => &mut **x, - } - } -} - -struct RwData<'a, 'b: 'a> { - rw_data: &'b Arc>, - possibly_locked_rw_data: &'a mut Option>, -} - -impl<'a, 'b: 'a> RwData<'a, 'b> { - /// If no reflow has happened yet, this will just return the lock in - /// `possibly_locked_rw_data`. Otherwise, it will acquire the `rw_data` lock. - /// - /// If you do not wish RPCs to remain blocked, just drop the `RWGuard` - /// returned from this function. If you _do_ wish for them to remain blocked, - /// use `block`. - fn lock(&mut self) -> RWGuard<'b> { - match self.possibly_locked_rw_data.take() { - None => RWGuard::Used(self.rw_data.lock().unwrap()), - Some(x) => RWGuard::Held(x), - } - } -} - impl Layout for LayoutThread { fn process(&mut self, msg: script_layout_interface::message::Msg) { self.handle_request(Request::FromScript(msg)); @@ -287,10 +237,6 @@ impl Layout for LayoutThread { self.handle_request(Request::FromFontCache); } - fn rpc(&self) -> Box { - Box::new(LayoutRPCImpl(self.rw_data.clone())) as Box - } - fn waiting_for_web_fonts_to_load(&self) -> bool { self.outstanding_web_fonts.load(Ordering::SeqCst) != 0 } @@ -330,6 +276,152 @@ impl Layout for LayoutThread { self.stylist .remove_stylesheet(DocumentStyleSheet(stylesheet.clone()), &guard); } + + fn query_content_box(&self, node: OpaqueNode) -> Option> { + process_content_box_request(node, self.fragment_tree.borrow().clone()) + } + + fn query_content_boxes(&self, node: OpaqueNode) -> Vec> { + process_content_boxes_request(node, self.fragment_tree.borrow().clone()) + } + + fn query_client_rect(&self, node: OpaqueNode) -> UntypedRect { + process_node_geometry_request(node, self.fragment_tree.borrow().clone()) + } + + fn query_element_inner_text( + &self, + node: script_layout_interface::TrustedNodeAddress, + ) -> String { + let node = unsafe { ServoLayoutNode::::new(&node) }; + process_element_inner_text_query(node) + } + + fn query_inner_window_dimension( + &self, + _context: BrowsingContextId, + ) -> Option> { + // TODO(jdm): port the iframe sizing code from layout2013's display + // builder in order to support query iframe sizing. + None + } + + fn query_nodes_from_point( + &self, + point: UntypedPoint2D, + query_type: NodesFromPointQueryType, + ) -> Vec { + let mut flags = match query_type { + NodesFromPointQueryType::Topmost => HitTestFlags::empty(), + NodesFromPointQueryType::All => HitTestFlags::FIND_ALL, + }; + + // The point we get is not relative to the entire WebRender scene, but to this + // particular pipeline, so we need to tell WebRender about that. + flags.insert(HitTestFlags::POINT_RELATIVE_TO_PIPELINE_VIEWPORT); + + let client_point = units::DevicePoint::from_untyped(point); + let results = + self.webrender_api + .hit_test(Some(self.id.to_webrender()), client_point, flags); + + results.iter().map(|result| result.node).collect() + } + + fn query_offset_parent(&self, node: OpaqueNode) -> OffsetParentResponse { + process_offset_parent_query(node, self.fragment_tree.borrow().clone()) + } + + fn query_resolved_style( + &self, + node: TrustedNodeAddress, + pseudo: Option, + property_id: PropertyId, + animations: DocumentAnimationSet, + animation_timeline_value: f64, + ) -> String { + let node: ServoLayoutNode = unsafe { ServoLayoutNode::new(&node) }; + let document = node.owner_doc(); + let document_shared_lock = document.style_shared_lock(); + let guards = StylesheetGuards { + author: &document_shared_lock.read(), + ua_or_user: &UA_STYLESHEETS.shared_lock.read(), + }; + let snapshot_map = SnapshotMap::new(); + + let shared_style_context = self.build_shared_style_context( + guards, + &snapshot_map, + animation_timeline_value, + &animations, + TraversalFlags::empty(), + ); + + let fragment_tree = self.fragment_tree.borrow().clone(); + process_resolved_style_request( + &shared_style_context, + node, + &pseudo, + &property_id, + fragment_tree, + ) + } + + fn query_resolved_font_style( + &self, + node: TrustedNodeAddress, + value: &str, + animations: DocumentAnimationSet, + animation_timeline_value: f64, + ) -> Option> { + let node: ServoLayoutNode = unsafe { ServoLayoutNode::new(&node) }; + let document = node.owner_doc(); + let document_shared_lock = document.style_shared_lock(); + let guards = StylesheetGuards { + author: &document_shared_lock.read(), + ua_or_user: &UA_STYLESHEETS.shared_lock.read(), + }; + let snapshot_map = SnapshotMap::new(); + let shared_style_context = self.build_shared_style_context( + guards, + &snapshot_map, + animation_timeline_value, + &animations, + TraversalFlags::empty(), + ); + + process_resolved_font_style_query( + &shared_style_context, + node, + value, + self.url.clone(), + document_shared_lock, + ) + } + + fn query_scroll_id( + &self, + node: script_layout_interface::TrustedNodeAddress, + ) -> ExternalScrollId { + let node = unsafe { ServoLayoutNode::::new(&node) }; + process_node_scroll_id_request(self.id, node) + } + + fn query_scrolling_area(&self, node: Option) -> UntypedRect { + process_node_scroll_area_request(node, self.fragment_tree.borrow().clone()) + } + + fn query_text_indext( + &self, + node: OpaqueNode, + point_in_node: UntypedPoint2D, + ) -> Option { + let point_in_node = Point2D::new( + Au::from_f32_px(point_in_node.x), + Au::from_f32_px(point_in_node.y), + ); + process_text_index_request(node, point_in_node) + } } enum Request { @@ -398,23 +490,8 @@ impl LayoutThread { Au::from_f32_px(window_size.initial_viewport.height), ), webrender_api: webrender_api_sender, + scroll_offsets: Default::default(), stylist: Stylist::new(device, QuirksMode::NoQuirks), - rw_data: Arc::new(Mutex::new(LayoutThreadData { - display_list: None, - content_box_response: None, - content_boxes_response: Vec::new(), - client_rect_response: Rect::zero(), - scroll_id_response: None, - scrolling_area_response: Rect::zero(), - resolved_style_response: String::new(), - resolved_font_style_response: None, - offset_parent_response: OffsetParentResponse::empty(), - scroll_offsets: HashMap::new(), - text_index_response: TextIndexResponse(None), - nodes_from_point_response: vec![], - element_inner_text_response: String::new(), - inner_window_dimensions_response: None, - })), webrender_image_cache: Default::default(), paint_time_metrics, last_iframe_sizes: Default::default(), @@ -422,6 +499,27 @@ impl LayoutThread { } } + fn build_shared_style_context<'a>( + &'a self, + guards: StylesheetGuards<'a>, + snapshot_map: &'a SnapshotMap, + animation_timeline_value: f64, + animations: &DocumentAnimationSet, + traversal_flags: TraversalFlags, + ) -> SharedStyleContext<'a> { + SharedStyleContext { + stylist: &self.stylist, + options: GLOBAL_STYLE_DATA.options.clone(), + guards, + visited_styles_enabled: false, + animations: animations.clone(), + registered_speculative_painters: &self.registered_painters, + current_time_for_animations: animation_timeline_value, + traversal_flags, + snapshot_map, + } + } + // Create a layout context for use in building display lists, hit testing, &c. fn build_layout_context<'a>( &'a self, @@ -441,17 +539,13 @@ impl LayoutThread { LayoutContext { id: self.id, origin, - style_context: SharedStyleContext { - stylist: &self.stylist, - options: GLOBAL_STYLE_DATA.options.clone(), + style_context: self.build_shared_style_context( guards, - visited_styles_enabled: false, - animations: animations.clone(), - registered_speculative_painters: &self.registered_painters, - current_time_for_animations: animation_timeline_value, - traversal_flags, snapshot_map, - }, + animation_timeline_value, + animations, + traversal_flags, + ), image_cache: self.image_cache.clone(), font_cache_thread: Mutex::new(self.font_cache_thread.clone()), webrender_image_cache: self.webrender_image_cache.clone(), @@ -462,26 +556,18 @@ impl LayoutThread { /// Receives and dispatches messages from the script and constellation threads fn handle_request<'a, 'b>(&mut self, request: Request) { - let rw_data = self.rw_data.clone(); - let mut possibly_locked_rw_data = Some(rw_data.lock().unwrap()); - let mut rw_data = RwData { - rw_data: &rw_data, - possibly_locked_rw_data: &mut possibly_locked_rw_data, - }; - match request { Request::FromPipeline(LayoutControlMsg::SetScrollStates(new_scroll_states)) => { - self.handle_request_helper(Msg::SetScrollStates(new_scroll_states), &mut rw_data) + self.handle_request_helper(Msg::SetScrollStates(new_scroll_states)) }, Request::FromPipeline(LayoutControlMsg::ExitNow) => { - self.handle_request_helper(Msg::ExitNow, &mut rw_data); + self.handle_request_helper(Msg::ExitNow); }, Request::FromPipeline(LayoutControlMsg::PaintMetric(epoch, paint_time)) => { self.paint_time_metrics.maybe_set_metric(epoch, paint_time); }, - Request::FromScript(msg) => self.handle_request_helper(msg, &mut rw_data), + Request::FromScript(msg) => self.handle_request_helper(msg), Request::FromFontCache => { - let _rw_data = rw_data.lock(); self.outstanding_web_fonts.fetch_sub(1, Ordering::SeqCst); self.handle_web_font_loaded(); }, @@ -489,32 +575,23 @@ impl LayoutThread { } /// Receives and dispatches messages from other threads. - fn handle_request_helper( - &mut self, - request: Msg, - possibly_locked_rw_data: &mut RwData<'_, '_>, - ) { + fn handle_request_helper(&mut self, request: Msg) { match request { Msg::SetQuirksMode(mode) => self.handle_set_quirks_mode(mode), - Msg::GetRPC(response_chan) => { - response_chan - .send(Box::new(LayoutRPCImpl(self.rw_data.clone())) as Box) - .unwrap(); - }, Msg::Reflow(data) => { let mut data = ScriptReflowResult::new(data); profile( profile_time::ProfilerCategory::LayoutPerform, self.profiler_metadata(), self.time_profiler_chan.clone(), - || self.handle_reflow(&mut data, possibly_locked_rw_data), + || self.handle_reflow(&mut data), ); }, Msg::SetScrollStates(new_scroll_states) => { - self.set_scroll_states(new_scroll_states, possibly_locked_rw_data); + self.set_scroll_states(new_scroll_states); }, Msg::CollectReports(reports_chan) => { - self.collect_reports(reports_chan, possibly_locked_rw_data); + self.collect_reports(reports_chan); }, Msg::RegisterPaint(_name, _properties, _painter) => {}, // Receiving the Exit message at this stage only happens when layout is undergoing a "force exit". @@ -522,24 +599,18 @@ impl LayoutThread { } } - fn collect_reports( - &self, - reports_chan: ReportsChan, - possibly_locked_rw_data: &mut RwData<'_, '_>, - ) { + fn collect_reports(&self, reports_chan: ReportsChan) { let mut reports = vec![]; // Servo uses vanilla jemalloc, which doesn't have a // malloc_enclosing_size_of function. let mut ops = MallocSizeOfOps::new(servo_allocator::usable_size, None, None); // FIXME(njn): Just measuring the display tree for now. - let rw_data = possibly_locked_rw_data.lock(); - let display_list = rw_data.display_list.as_ref(); let formatted_url = &format!("url({})", self.url); reports.push(Report { path: path![formatted_url, "layout-thread", "display-list"], kind: ReportKind::ExplicitJemallocHeapSize, - size: display_list.map_or(0, |sc| sc.size_of(&mut ops)), + size: 0, }); reports.push(Report { @@ -590,71 +661,12 @@ impl LayoutThread { } /// The high-level routine that performs layout. - fn handle_reflow( - &mut self, - data: &mut ScriptReflowResult, - possibly_locked_rw_data: &mut RwData<'_, '_>, - ) { + fn handle_reflow(&mut self, data: &mut ScriptReflowResult) { let document = unsafe { ServoLayoutNode::::new(&data.document) }; let document = document.as_document().unwrap(); - - let mut rw_data = possibly_locked_rw_data.lock(); - - let root_element = match document.root_element() { - None => { - // Since we cannot compute anything, give spec-required placeholders. - debug!("layout: No root node: bailing"); - match data.reflow_goal { - ReflowGoal::LayoutQuery(ref query_msg, _) => match query_msg { - &QueryMsg::ContentBoxQuery(_) => { - rw_data.content_box_response = None; - }, - &QueryMsg::ContentBoxesQuery(_) => { - rw_data.content_boxes_response = Vec::new(); - }, - &QueryMsg::NodesFromPointQuery(..) => { - rw_data.nodes_from_point_response = Vec::new(); - }, - &QueryMsg::ClientRectQuery(_) => { - rw_data.client_rect_response = Rect::zero(); - }, - &QueryMsg::ScrollingAreaQuery(_) => { - rw_data.scrolling_area_response = Rect::zero(); - }, - &QueryMsg::NodeScrollIdQuery(_) => { - rw_data.scroll_id_response = None; - }, - &QueryMsg::ResolvedStyleQuery(_, _, _) => { - rw_data.resolved_style_response = String::new(); - }, - &QueryMsg::ResolvedFontStyleQuery(_, _, _) => { - rw_data.resolved_font_style_response = None; - }, - &QueryMsg::OffsetParentQuery(_) => { - rw_data.offset_parent_response = OffsetParentResponse::empty(); - }, - &QueryMsg::StyleQuery => {}, - &QueryMsg::TextIndexQuery(..) => { - rw_data.text_index_response = TextIndexResponse(None); - }, - &QueryMsg::ElementInnerTextQuery(_) => { - rw_data.element_inner_text_response = String::new(); - }, - &QueryMsg::InnerWindowDimensionsQuery(browsing_context_id) => { - rw_data.inner_window_dimensions_response = self - .last_iframe_sizes - .borrow() - .get(&browsing_context_id) - .cloned(); - }, - }, - ReflowGoal::Full | - ReflowGoal::TickAnimations | - ReflowGoal::UpdateScrollNode(_) => {}, - } - return; - }, - Some(x) => x, + let Some(root_element) = document.root_element() else { + debug!("layout: No root node: bailing"); + return; }; // Calculate the actual viewport as per DEVICE-ADAPT ยง 6 @@ -850,124 +862,18 @@ impl LayoutThread { } self.first_reflow.set(false); - self.respond_to_query_if_necessary( - &data.reflow_goal, - &mut *rw_data, - &mut layout_context, - data.result.borrow_mut().as_mut().unwrap(), - document_shared_lock, - ); - } - fn respond_to_query_if_necessary( - &self, - reflow_goal: &ReflowGoal, - rw_data: &mut LayoutThreadData, - context: &mut LayoutContext, - reflow_result: &mut ReflowComplete, - shared_lock: &SharedRwLock, - ) { - reflow_result.pending_images = std::mem::take(&mut *context.pending_images.lock().unwrap()); - - match *reflow_goal { - ReflowGoal::LayoutQuery(ref querymsg, _) => match querymsg { - &QueryMsg::ContentBoxQuery(node) => { - rw_data.content_box_response = - process_content_box_request(node, self.fragment_tree.borrow().clone()); - }, - &QueryMsg::ContentBoxesQuery(node) => { - rw_data.content_boxes_response = - process_content_boxes_request(node, self.fragment_tree.borrow().clone()); - }, - &QueryMsg::TextIndexQuery(node, point_in_node) => { - let point_in_node = Point2D::new( - Au::from_f32_px(point_in_node.x), - Au::from_f32_px(point_in_node.y), - ); - rw_data.text_index_response = process_text_index_request(node, point_in_node); - }, - &QueryMsg::ClientRectQuery(node) => { - rw_data.client_rect_response = - process_node_geometry_request(node, self.fragment_tree.borrow().clone()); - }, - &QueryMsg::ScrollingAreaQuery(node) => { - rw_data.scrolling_area_response = - process_node_scroll_area_request(node, self.fragment_tree.borrow().clone()); - }, - &QueryMsg::NodeScrollIdQuery(node) => { - let node = unsafe { ServoLayoutNode::::new(&node) }; - rw_data.scroll_id_response = - Some(process_node_scroll_id_request(self.id, node)); - }, - &QueryMsg::ResolvedStyleQuery(node, ref pseudo, ref property) => { - let node = unsafe { ServoLayoutNode::::new(&node) }; - let fragment_tree = self.fragment_tree.borrow().clone(); - rw_data.resolved_style_response = process_resolved_style_request( - context, - node, - pseudo, - property, - fragment_tree, - ); - }, - &QueryMsg::ResolvedFontStyleQuery(node, ref property, ref value) => { - let node = unsafe { ServoLayoutNode::::new(&node) }; - rw_data.resolved_font_style_response = process_resolved_font_style_query( - context, - node, - property, - value, - self.url.clone(), - shared_lock, - ); - }, - &QueryMsg::OffsetParentQuery(node) => { - rw_data.offset_parent_response = - process_offset_parent_query(node, self.fragment_tree.borrow().clone()); - }, - &QueryMsg::StyleQuery => {}, - &QueryMsg::NodesFromPointQuery(client_point, ref reflow_goal) => { - let mut flags = match reflow_goal { - &NodesFromPointQueryType::Topmost => HitTestFlags::empty(), - &NodesFromPointQueryType::All => HitTestFlags::FIND_ALL, - }; - - // The point we get is not relative to the entire WebRender scene, but to this - // particular pipeline, so we need to tell WebRender about that. - flags.insert(HitTestFlags::POINT_RELATIVE_TO_PIPELINE_VIEWPORT); - - let client_point = units::DevicePoint::from_untyped(client_point); - let results = self.webrender_api.hit_test( - Some(self.id.to_webrender()), - client_point, - flags, - ); - - rw_data.nodes_from_point_response = - results.iter().map(|result| result.node).collect() - }, - &QueryMsg::ElementInnerTextQuery(node) => { - let node = unsafe { ServoLayoutNode::::new(&node) }; - rw_data.element_inner_text_response = process_element_inner_text_query(node); - }, - &QueryMsg::InnerWindowDimensionsQuery(_browsing_context_id) => { - // TODO(jdm): port the iframe sizing code from layout2013's display - // builder in order to support query iframe sizing. - rw_data.inner_window_dimensions_response = None; - }, - }, - ReflowGoal::UpdateScrollNode(scroll_state) => { - self.update_scroll_node_state(&scroll_state, rw_data); - }, - ReflowGoal::Full | ReflowGoal::TickAnimations => {}, + data.result.borrow_mut().as_mut().unwrap().pending_images = + std::mem::take(&mut *layout_context.pending_images.lock().unwrap()); + if let ReflowGoal::UpdateScrollNode(scroll_state) = data.reflow_goal { + self.update_scroll_node_state(&scroll_state); } } - fn update_scroll_node_state(&self, state: &ScrollState, rw_data: &mut LayoutThreadData) { - rw_data - .scroll_offsets + fn update_scroll_node_state(&self, state: &ScrollState) { + self.scroll_offsets + .borrow_mut() .insert(state.scroll_id, state.scroll_offset); - let point = Point2D::new(-state.scroll_offset.x, -state.scroll_offset.y); self.webrender_api.send_scroll_node( self.id.to_webrender(), @@ -976,12 +882,7 @@ impl LayoutThread { ); } - fn set_scroll_states( - &mut self, - new_scroll_states: Vec, - possibly_locked_rw_data: &mut RwData<'_, '_>, - ) { - let mut rw_data = possibly_locked_rw_data.lock(); + fn set_scroll_states(&mut self, new_scroll_states: Vec) { let mut script_scroll_states = vec![]; let mut layout_scroll_states = HashMap::new(); for new_state in &new_scroll_states { @@ -1000,7 +901,7 @@ impl LayoutThread { self.id, script_scroll_states, )); - rw_data.scroll_offsets = layout_scroll_states + self.scroll_offsets = RefCell::new(layout_scroll_states); } fn perform_post_style_recalc_layout_passes( diff --git a/components/script/dom/documentorshadowroot.rs b/components/script/dom/documentorshadowroot.rs index fec2b6372db..59e84acf13c 100644 --- a/components/script/dom/documentorshadowroot.rs +++ b/components/script/dom/documentorshadowroot.rs @@ -84,16 +84,15 @@ impl DocumentOrShadowRoot { pub fn nodes_from_point( &self, client_point: &Point2D, - reflow_goal: NodesFromPointQueryType, + query_type: NodesFromPointQueryType, ) -> Vec { - if !self - .window - .layout_reflow(QueryMsg::NodesFromPointQuery(*client_point, reflow_goal)) - { + if !self.window.layout_reflow(QueryMsg::NodesFromPointQuery) { return vec![]; }; - self.window.layout_rpc().nodes_from_point_response() + self.window + .with_layout(|layout| layout.query_nodes_from_point(*client_point, query_type)) + .unwrap_or_default() } #[allow(unsafe_code)] diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs index f40c5439de7..1eca57e2b60 100644 --- a/components/script/dom/htmlelement.rs +++ b/components/script/dom/htmlelement.rs @@ -454,10 +454,11 @@ impl HTMLElementMethods for HTMLElement { return node.GetTextContent().unwrap(); } - window.layout_reflow(QueryMsg::ElementInnerTextQuery( - node.to_trusted_node_address(), - )); - DOMString::from(window.layout_rpc().element_inner_text()) + window.layout_reflow(QueryMsg::ElementInnerTextQuery); + let text = window + .with_layout(|layout| layout.query_element_inner_text(node.to_trusted_node_address())) + .unwrap_or_default(); + DOMString::from(text) } // https://html.spec.whatwg.org/multipage/#the-innertext-idl-attribute diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 644ba3b50fc..069c31ad806 100755 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -26,7 +26,6 @@ use net_traits::blob_url_store::get_blob_origin; use net_traits::filemanager_thread::FileManagerThreadMsg; use net_traits::{CoreResourceMsg, IpcSend}; use profile_traits::ipc; -use script_layout_interface::rpc::TextIndexResponse; use script_traits::ScriptToConstellationChan; use servo_atoms::Atom; use style::attr::AttrValue; @@ -2537,8 +2536,7 @@ impl VirtualMethods for HTMLInputElement { // now. if let Some(point_in_target) = mouse_event.point_in_target() { let window = window_from_node(self); - let TextIndexResponse(index) = - window.text_index_query(self.upcast::(), point_in_target); + let index = window.text_index_query(self.upcast::(), point_in_target); if let Some(i) = index { self.textinput.borrow_mut().set_edit_point_index(i); // trigger redraw diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index c03903e9199..14b45c5615d 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -49,10 +49,6 @@ use profile_traits::ipc as ProfiledIpc; use profile_traits::mem::ProfilerChan as MemProfilerChan; use profile_traits::time::ProfilerChan as TimeProfilerChan; use script_layout_interface::message::{Msg, QueryMsg, Reflow, ReflowGoal, ScriptReflow}; -use script_layout_interface::rpc::{ - ContentBoxResponse, ContentBoxesResponse, LayoutRPC, NodeScrollIdResponse, - ResolvedStyleResponse, TextIndexResponse, -}; use script_layout_interface::{Layout, PendingImageState, TrustedNodeAddress}; use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult}; use script_traits::{ @@ -70,7 +66,7 @@ use style::error_reporting::{ContextualParseError, ParseErrorReporter}; use style::media_queries; use style::parser::ParserContext as CssParserContext; use style::properties::style_structs::Font; -use style::properties::{PropertyId, ShorthandId}; +use style::properties::PropertyId; use style::selector_parser::PseudoElement; use style::str::HTML_SPACE_CHARACTERS; use style::stylesheets::{CssRuleType, Origin, UrlExtraData}; @@ -2049,52 +2045,55 @@ impl Window { } pub fn resolved_font_style_query(&self, node: &Node, value: String) -> Option> { - let id = PropertyId::Shorthand(ShorthandId::Font); - if !self.layout_reflow(QueryMsg::ResolvedFontStyleQuery( - node.to_trusted_node_address(), - id, - value, - )) { + if !self.layout_reflow(QueryMsg::ResolvedFontStyleQuery) { return None; } - self.layout_rpc().resolved_font_style() - } - pub fn layout_rpc(&self) -> Box { - self.with_layout(|layout| layout.rpc()).unwrap() + let document = self.Document(); + self.with_layout(|layout| { + layout.query_resolved_font_style( + node.to_trusted_node_address(), + &value, + document.animations().sets.clone(), + document.current_animation_timeline_value(), + ) + }) + .unwrap() } pub fn content_box_query(&self, node: &Node) -> Option> { - if !self.layout_reflow(QueryMsg::ContentBoxQuery(node.to_opaque())) { + if !self.layout_reflow(QueryMsg::ContentBox) { return None; } - let ContentBoxResponse(rect) = self.layout_rpc().content_box(); - rect + self.with_layout(|layout| layout.query_content_box(node.to_opaque())) + .unwrap_or(None) } pub fn content_boxes_query(&self, node: &Node) -> Vec> { - if !self.layout_reflow(QueryMsg::ContentBoxesQuery(node.to_opaque())) { + if !self.layout_reflow(QueryMsg::ContentBoxes) { return vec![]; } - let ContentBoxesResponse(rects) = self.layout_rpc().content_boxes(); - rects + self.with_layout(|layout| layout.query_content_boxes(node.to_opaque())) + .unwrap_or_default() } pub fn client_rect_query(&self, node: &Node) -> UntypedRect { - if !self.layout_reflow(QueryMsg::ClientRectQuery(node.to_opaque())) { + if !self.layout_reflow(QueryMsg::ClientRectQuery) { return Rect::zero(); } - self.layout_rpc().node_geometry().client_rect + self.with_layout(|layout| layout.query_client_rect(node.to_opaque())) + .unwrap_or_default() } /// Find the scroll area of the given node, if it is not None. If the node /// is None, find the scroll area of the viewport. pub fn scrolling_area_query(&self, node: Option<&Node>) -> UntypedRect { let opaque = node.map(|node| node.to_opaque()); - if !self.layout_reflow(QueryMsg::ScrollingAreaQuery(opaque)) { + if !self.layout_reflow(QueryMsg::ScrollingAreaQuery) { return Rect::zero(); } - self.layout_rpc().scrolling_area().client_rect + self.with_layout(|layout| layout.query_scrolling_area(opaque)) + .unwrap_or_default() } pub fn scroll_offset_query(&self, node: &Node) -> Vector2D { @@ -2106,7 +2105,7 @@ impl Window { // https://drafts.csswg.org/cssom-view/#element-scrolling-members pub fn scroll_node(&self, node: &Node, x_: f64, y_: f64, behavior: ScrollBehavior) { - if !self.layout_reflow(QueryMsg::NodeScrollIdQuery(node.to_trusted_node_address())) { + if !self.layout_reflow(QueryMsg::NodeScrollIdQuery) { return; } @@ -2117,7 +2116,9 @@ impl Window { .borrow_mut() .insert(node.to_opaque(), Vector2D::new(x_ as f32, y_ as f32)); - let NodeScrollIdResponse(scroll_id) = self.layout_rpc().node_scroll_id(); + let scroll_id = self + .with_layout(|layout| layout.query_scroll_id(node.to_trusted_node_address())) + .unwrap(); // Step 12 self.perform_a_scroll( @@ -2135,32 +2136,45 @@ impl Window { pseudo: Option, property: PropertyId, ) -> DOMString { - if !self.layout_reflow(QueryMsg::ResolvedStyleQuery(element, pseudo, property)) { + if !self.layout_reflow(QueryMsg::ResolvedStyleQuery) { return DOMString::new(); } - let ResolvedStyleResponse(resolved) = self.layout_rpc().resolved_style(); - DOMString::from(resolved) + + let document = self.Document(); + DOMString::from( + self.with_layout(|layout| { + layout.query_resolved_style( + element, + pseudo, + property, + document.animations().sets.clone(), + document.current_animation_timeline_value(), + ) + }) + .unwrap(), + ) } pub fn inner_window_dimensions_query( &self, browsing_context: BrowsingContextId, ) -> Option> { - if !self.layout_reflow(QueryMsg::InnerWindowDimensionsQuery(browsing_context)) { + if !self.layout_reflow(QueryMsg::InnerWindowDimensionsQuery) { return None; } - self.layout_rpc().inner_window_dimensions() + self.with_layout(|layout| layout.query_inner_window_dimension(browsing_context)) + .unwrap() } #[allow(unsafe_code)] pub fn offset_parent_query(&self, node: &Node) -> (Option>, UntypedRect) { - if !self.layout_reflow(QueryMsg::OffsetParentQuery(node.to_opaque())) { + if !self.layout_reflow(QueryMsg::OffsetParentQuery) { return (None, Rect::zero()); } - // FIXME(nox): Layout can reply with a garbage value which doesn't - // actually correspond to an element, that's unsound. - let response = self.layout_rpc().offset_parent(); + let response = self + .with_layout(|layout| layout.query_offset_parent(node.to_opaque())) + .unwrap(); let element = response.node_address.and_then(|parent_node_address| { let node = unsafe { from_untrusted_node_address(parent_node_address) }; DomRoot::downcast(node) @@ -2172,11 +2186,12 @@ impl Window { &self, node: &Node, point_in_node: UntypedPoint2D, - ) -> TextIndexResponse { - if !self.layout_reflow(QueryMsg::TextIndexQuery(node.to_opaque(), point_in_node)) { - return TextIndexResponse(None); + ) -> Option { + if !self.layout_reflow(QueryMsg::TextIndexQuery) { + return None; } - self.layout_rpc().text_index() + self.with_layout(|layout| layout.query_text_indext(node.to_opaque(), point_in_node)) + .unwrap() } #[allow(unsafe_code)] @@ -2705,19 +2720,19 @@ fn debug_reflow_events(id: PipelineId, reflow_goal: &ReflowGoal, reason: &Reflow ReflowGoal::TickAnimations => "\tTickAnimations", ReflowGoal::UpdateScrollNode(_) => "\tUpdateScrollNode", ReflowGoal::LayoutQuery(ref query_msg, _) => match *query_msg { - QueryMsg::ContentBoxQuery(_n) => "\tContentBoxQuery", - QueryMsg::ContentBoxesQuery(_n) => "\tContentBoxesQuery", - QueryMsg::NodesFromPointQuery(..) => "\tNodesFromPointQuery", - QueryMsg::ClientRectQuery(_n) => "\tClientRectQuery", - QueryMsg::ScrollingAreaQuery(_n) => "\tNodeScrollGeometryQuery", - QueryMsg::NodeScrollIdQuery(_n) => "\tNodeScrollIdQuery", - QueryMsg::ResolvedStyleQuery(_, _, _) => "\tResolvedStyleQuery", - QueryMsg::ResolvedFontStyleQuery(..) => "\nResolvedFontStyleQuery", - QueryMsg::OffsetParentQuery(_n) => "\tOffsetParentQuery", + QueryMsg::ContentBox => "\tContentBoxQuery", + QueryMsg::ContentBoxes => "\tContentBoxesQuery", + QueryMsg::NodesFromPointQuery => "\tNodesFromPointQuery", + QueryMsg::ClientRectQuery => "\tClientRectQuery", + QueryMsg::ScrollingAreaQuery => "\tNodeScrollGeometryQuery", + QueryMsg::NodeScrollIdQuery => "\tNodeScrollIdQuery", + QueryMsg::ResolvedStyleQuery => "\tResolvedStyleQuery", + QueryMsg::ResolvedFontStyleQuery => "\nResolvedFontStyleQuery", + QueryMsg::OffsetParentQuery => "\tOffsetParentQuery", QueryMsg::StyleQuery => "\tStyleQuery", - QueryMsg::TextIndexQuery(..) => "\tTextIndexQuery", - QueryMsg::ElementInnerTextQuery(_) => "\tElementInnerTextQuery", - QueryMsg::InnerWindowDimensionsQuery(_) => "\tInnerWindowDimensionsQuery", + QueryMsg::TextIndexQuery => "\tTextIndexQuery", + QueryMsg::ElementInnerTextQuery => "\tElementInnerTextQuery", + QueryMsg::InnerWindowDimensionsQuery => "\tInnerWindowDimensionsQuery", }, }; diff --git a/components/shared/msg/constellation_msg.rs b/components/shared/msg/constellation_msg.rs index 44f3eb6b12e..24fda786c9d 100644 --- a/components/shared/msg/constellation_msg.rs +++ b/components/shared/msg/constellation_msg.rs @@ -462,7 +462,6 @@ pub enum LayoutHangAnnotation { RemoveStylesheet, SetQuirksMode, Reflow, - GetRPC, CollectReports, ExitNow, GetCurrentEpoch, diff --git a/components/shared/script_layout/lib.rs b/components/shared/script_layout/lib.rs index 121788d7b16..aca819980d7 100644 --- a/components/shared/script_layout/lib.rs +++ b/components/shared/script_layout/lib.rs @@ -9,7 +9,6 @@ #![deny(unsafe_code)] pub mod message; -pub mod rpc; pub mod wrapper_traits; use std::any::Any; @@ -17,15 +16,19 @@ use std::borrow::Cow; use std::sync::atomic::AtomicIsize; use std::sync::Arc; +use app_units::Au; use atomic_refcell::AtomicRefCell; use canvas_traits::canvas::{CanvasId, CanvasMsg}; +use euclid::default::{Point2D, Rect}; +use euclid::Size2D; use gfx::font_cache_thread::FontCacheThread; use gfx_traits::Epoch; use ipc_channel::ipc::IpcSender; use libc::c_void; use malloc_size_of_derive::MallocSizeOf; +use message::NodesFromPointQueryType; use metrics::PaintTimeMetrics; -use msg::constellation_msg::PipelineId; +use msg::constellation_msg::{BrowsingContextId, PipelineId}; use net_traits::image_cache::{ImageCache, PendingImageId}; use profile_traits::time; use script_traits::{ @@ -34,9 +37,15 @@ use script_traits::{ }; use servo_arc::Arc as ServoArc; use servo_url::{ImmutableOrigin, ServoUrl}; +use style::animation::DocumentAnimationSet; use style::data::ElementData; +use style::dom::OpaqueNode; +use style::properties::style_structs::Font; +use style::properties::PropertyId; +use style::selector_parser::PseudoElement; use style::stylesheets::Stylesheet; -use webrender_api::ImageKey; +use style_traits::CSSPixel; +use webrender_api::{ExternalScrollId, ImageKey}; #[derive(MallocSizeOf)] pub struct StyleData { @@ -195,11 +204,6 @@ pub trait Layout { /// Handle a a single mesasge from the FontCacheThread. fn handle_font_cache_msg(&mut self); - /// Return the interface used for scipt queries. - /// TODO: Make this part of the the Layout interface itself now that the - /// layout thread has been removed. - fn rpc(&self) -> Box; - /// Whether or not this layout is waiting for fonts from loaded stylesheets to finish loading. fn waiting_for_web_fonts_to_load(&self) -> bool; @@ -221,6 +225,39 @@ pub trait Layout { /// Removes a stylesheet from the Layout. fn remove_stylesheet(&mut self, stylesheet: ServoArc); + + fn query_content_box(&self, node: OpaqueNode) -> Option>; + fn query_content_boxes(&self, node: OpaqueNode) -> Vec>; + fn query_client_rect(&self, node: OpaqueNode) -> Rect; + fn query_element_inner_text(&self, node: TrustedNodeAddress) -> String; + fn query_inner_window_dimension( + &self, + context: BrowsingContextId, + ) -> Option>; + fn query_nodes_from_point( + &self, + point: Point2D, + query_type: NodesFromPointQueryType, + ) -> Vec; + fn query_offset_parent(&self, node: OpaqueNode) -> OffsetParentResponse; + fn query_resolved_style( + &self, + node: TrustedNodeAddress, + pseudo: Option, + property_id: PropertyId, + animations: DocumentAnimationSet, + animation_timeline_value: f64, + ) -> String; + fn query_resolved_font_style( + &self, + node: TrustedNodeAddress, + value: &str, + animations: DocumentAnimationSet, + animation_timeline_value: f64, + ) -> Option>; + fn query_scroll_id(&self, node: TrustedNodeAddress) -> ExternalScrollId; + fn query_scrolling_area(&self, node: Option) -> Rect; + fn query_text_indext(&self, node: OpaqueNode, point: Point2D) -> Option; } /// This trait is part of `script_layout_interface` because it depends on both `script_traits` @@ -236,3 +273,8 @@ pub trait ScriptThreadFactory { user_agent: Cow<'static, str>, ); } +#[derive(Clone, Default)] +pub struct OffsetParentResponse { + pub node_address: Option, + pub rect: Rect, +} diff --git a/components/shared/script_layout/message.rs b/components/shared/script_layout/message.rs index e902bac4f7a..34de65cd227 100644 --- a/components/shared/script_layout/message.rs +++ b/components/shared/script_layout/message.rs @@ -4,21 +4,17 @@ use app_units::Au; use crossbeam_channel::Sender; -use euclid::default::{Point2D, Rect}; +use euclid::default::Rect; use malloc_size_of_derive::MallocSizeOf; -use msg::constellation_msg::BrowsingContextId; use profile_traits::mem::ReportsChan; use script_traits::{Painter, ScrollState, WindowSizeData}; use servo_atoms::Atom; use servo_url::ImmutableOrigin; use style::animation::DocumentAnimationSet; use style::context::QuirksMode; -use style::dom::OpaqueNode; use style::invalidation::element::restyle_hints::RestyleHint; -use style::properties::PropertyId; -use style::selector_parser::{PseudoElement, RestyleDamage, Snapshot}; +use style::selector_parser::{RestyleDamage, Snapshot}; -use crate::rpc::LayoutRPC; use crate::{PendingImage, TrustedNodeAddress}; /// Asynchronous messages that script can send to layout. @@ -29,9 +25,6 @@ pub enum Msg { /// Requests a reflow. Reflow(ScriptReflow), - /// Get an RPC interface. - GetRPC(Sender>), - /// Requests that layout measure its memory usage. The resulting reports are sent back /// via the supplied channel. CollectReports(ReportsChan), @@ -55,23 +48,19 @@ pub enum NodesFromPointQueryType { #[derive(Debug, PartialEq)] pub enum QueryMsg { - ContentBoxQuery(OpaqueNode), - ContentBoxesQuery(OpaqueNode), - ClientRectQuery(OpaqueNode), - ScrollingAreaQuery(Option), - OffsetParentQuery(OpaqueNode), - TextIndexQuery(OpaqueNode, Point2D), - NodesFromPointQuery(Point2D, NodesFromPointQueryType), - - // FIXME(nox): The following queries use the TrustedNodeAddress to - // access actual DOM nodes, but those values can be constructed from - // garbage values such as `0xdeadbeef as *const _`, this is unsound. - NodeScrollIdQuery(TrustedNodeAddress), - ResolvedStyleQuery(TrustedNodeAddress, Option, PropertyId), + ContentBox, + ContentBoxes, + ClientRectQuery, + ScrollingAreaQuery, + OffsetParentQuery, + TextIndexQuery, + NodesFromPointQuery, + NodeScrollIdQuery, + ResolvedStyleQuery, StyleQuery, - ElementInnerTextQuery(TrustedNodeAddress), - ResolvedFontStyleQuery(TrustedNodeAddress, PropertyId, String), - InnerWindowDimensionsQuery(BrowsingContextId), + ElementInnerTextQuery, + ResolvedFontStyleQuery, + InnerWindowDimensionsQuery, } /// Any query to perform with this reflow. @@ -93,18 +82,18 @@ impl ReflowGoal { match *self { ReflowGoal::Full | ReflowGoal::TickAnimations | ReflowGoal::UpdateScrollNode(_) => true, ReflowGoal::LayoutQuery(ref querymsg, _) => match *querymsg { - QueryMsg::ElementInnerTextQuery(_) | - QueryMsg::InnerWindowDimensionsQuery(_) | - QueryMsg::NodesFromPointQuery(..) | - QueryMsg::ResolvedStyleQuery(..) | - QueryMsg::TextIndexQuery(..) => true, - QueryMsg::ClientRectQuery(_) | - QueryMsg::ContentBoxQuery(_) | - QueryMsg::ContentBoxesQuery(_) | - QueryMsg::NodeScrollIdQuery(_) | - QueryMsg::OffsetParentQuery(_) | - QueryMsg::ResolvedFontStyleQuery(..) | - QueryMsg::ScrollingAreaQuery(_) | + QueryMsg::ElementInnerTextQuery | + QueryMsg::InnerWindowDimensionsQuery | + QueryMsg::NodesFromPointQuery | + QueryMsg::ResolvedStyleQuery | + QueryMsg::TextIndexQuery => true, + QueryMsg::ClientRectQuery | + QueryMsg::ContentBox | + QueryMsg::ContentBoxes | + QueryMsg::NodeScrollIdQuery | + QueryMsg::OffsetParentQuery | + QueryMsg::ResolvedFontStyleQuery | + QueryMsg::ScrollingAreaQuery | QueryMsg::StyleQuery => false, }, } @@ -116,18 +105,18 @@ impl ReflowGoal { match *self { ReflowGoal::Full | ReflowGoal::TickAnimations | ReflowGoal::UpdateScrollNode(_) => true, ReflowGoal::LayoutQuery(ref querymsg, _) => match *querymsg { - QueryMsg::NodesFromPointQuery(..) | - QueryMsg::TextIndexQuery(..) | - QueryMsg::ElementInnerTextQuery(_) => true, - QueryMsg::ContentBoxQuery(_) | - QueryMsg::ContentBoxesQuery(_) | - QueryMsg::ClientRectQuery(_) | - QueryMsg::ScrollingAreaQuery(_) | - QueryMsg::NodeScrollIdQuery(_) | - QueryMsg::ResolvedStyleQuery(..) | - QueryMsg::ResolvedFontStyleQuery(..) | - QueryMsg::OffsetParentQuery(_) | - QueryMsg::InnerWindowDimensionsQuery(_) | + QueryMsg::NodesFromPointQuery | + QueryMsg::TextIndexQuery | + QueryMsg::ElementInnerTextQuery => true, + QueryMsg::ContentBox | + QueryMsg::ContentBoxes | + QueryMsg::ClientRectQuery | + QueryMsg::ScrollingAreaQuery | + QueryMsg::NodeScrollIdQuery | + QueryMsg::ResolvedStyleQuery | + QueryMsg::ResolvedFontStyleQuery | + QueryMsg::OffsetParentQuery | + QueryMsg::InnerWindowDimensionsQuery | QueryMsg::StyleQuery => false, }, } diff --git a/components/shared/script_layout/rpc.rs b/components/shared/script_layout/rpc.rs deleted file mode 100644 index 3778d8f975a..00000000000 --- a/components/shared/script_layout/rpc.rs +++ /dev/null @@ -1,75 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - -use app_units::Au; -use euclid::default::Rect; -use euclid::Size2D; -use script_traits::UntrustedNodeAddress; -use servo_arc::Arc; -use style::properties::style_structs::Font; -use style_traits::CSSPixel; -use webrender_api::ExternalScrollId; - -/// Synchronous messages that script can send to layout. -/// -/// In general, you should use messages to talk to Layout. Use the RPC interface -/// if and only if the work is -/// -/// 1) read-only with respect to LayoutThreadData, -/// 2) small, -/// 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) -> ContentBoxResponse; - /// Requests the dimensions of all the content boxes, as in the `getClientRects()` call. - fn content_boxes(&self) -> ContentBoxesResponse; - /// Requests the geometry of this node. Used by APIs such as `clientTop`. - fn node_geometry(&self) -> NodeGeometryResponse; - /// Requests the scroll geometry of this node. Used by APIs such as `scrollTop`. - fn scrolling_area(&self) -> NodeGeometryResponse; - /// Requests the scroll id of this node. Used by APIs such as `scrollTop` - fn node_scroll_id(&self) -> NodeScrollIdResponse; - /// Query layout for the resolved value of a given CSS property - fn resolved_style(&self) -> ResolvedStyleResponse; - /// Query layout to get the resolved font style for canvas. - fn resolved_font_style(&self) -> Option>; - fn offset_parent(&self) -> OffsetParentResponse; - fn text_index(&self) -> TextIndexResponse; - /// Requests the list of nodes from the given point. - fn nodes_from_point_response(&self) -> Vec; - /// Query layout to get the inner text for a given element. - fn element_inner_text(&self) -> String; - /// Get the dimensions of an iframe's inner window. - fn inner_window_dimensions(&self) -> Option>; -} - -pub struct ContentBoxResponse(pub Option>); - -pub struct ContentBoxesResponse(pub Vec>); - -pub struct NodeGeometryResponse { - pub client_rect: Rect, -} - -pub struct NodeScrollIdResponse(pub ExternalScrollId); - -pub struct ResolvedStyleResponse(pub String); - -#[derive(Clone)] -pub struct OffsetParentResponse { - pub node_address: Option, - pub rect: Rect, -} - -impl OffsetParentResponse { - pub fn empty() -> OffsetParentResponse { - OffsetParentResponse { - node_address: None, - rect: Rect::zero(), - } - } -} - -#[derive(Clone)] -pub struct TextIndexResponse(pub Option);