diff options
author | Martin Robinson <mrobinson@igalia.com> | 2024-03-29 17:25:47 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-29 16:25:47 +0000 |
commit | b7d089930ea075a580a20bede881c677a0ba0fb0 (patch) | |
tree | c85d7bf011d80d5f3c47a2a5b5df2948134ec1b8 /components/shared/script_layout | |
parent | 07391e346b0ff3e89485ddc7e8f3c448ef1de4f4 (diff) | |
download | servo-b7d089930ea075a580a20bede881c677a0ba0fb0.tar.gz servo-b7d089930ea075a580a20bede881c677a0ba0fb0.zip |
layout: Remove LayoutRPC and query layout via the `Layout` trait (#31937)
Instead of the tricky `LayoutRPC` interface, query layout using the
`Layout` trait. This means that now queries will requires calling layout
and then running the query. During layout an enum is used to indicate
what kind of layout is necessary.
This change also removes the mutex-locked `rw_data` from both layout
threads. It's no longer necessary since layout runs synchronously. The
one downside here is that for resolved style queries, we now have to
create two StyleContexts. One for layout and one for the query itself.
The creation of this context should not be very expensive though.
`LayoutRPC` used to be necessary because layout used to run
asynchronously from script, but that no longer happens. With this
change, it becomes possible to safely pass nodes to layout from script
-- a cleanup that can happen in a followup change.
Diffstat (limited to 'components/shared/script_layout')
-rw-r--r-- | components/shared/script_layout/lib.rs | 58 | ||||
-rw-r--r-- | components/shared/script_layout/message.rs | 87 | ||||
-rw-r--r-- | components/shared/script_layout/rpc.rs | 75 |
3 files changed, 88 insertions, 132 deletions
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<dyn rpc::LayoutRPC>; - /// 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<Stylesheet>); + + fn query_content_box(&self, node: OpaqueNode) -> Option<Rect<Au>>; + fn query_content_boxes(&self, node: OpaqueNode) -> Vec<Rect<Au>>; + fn query_client_rect(&self, node: OpaqueNode) -> Rect<i32>; + fn query_element_inner_text(&self, node: TrustedNodeAddress) -> String; + fn query_inner_window_dimension( + &self, + context: BrowsingContextId, + ) -> Option<Size2D<f32, CSSPixel>>; + fn query_nodes_from_point( + &self, + point: Point2D<f32>, + query_type: NodesFromPointQueryType, + ) -> Vec<UntrustedNodeAddress>; + fn query_offset_parent(&self, node: OpaqueNode) -> OffsetParentResponse; + fn query_resolved_style( + &self, + node: TrustedNodeAddress, + pseudo: Option<PseudoElement>, + 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<ServoArc<Font>>; + fn query_scroll_id(&self, node: TrustedNodeAddress) -> ExternalScrollId; + fn query_scrolling_area(&self, node: Option<OpaqueNode>) -> Rect<i32>; + fn query_text_indext(&self, node: OpaqueNode, point: Point2D<f32>) -> Option<usize>; } /// 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<UntrustedNodeAddress>, + pub rect: Rect<Au>, +} 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<Box<dyn LayoutRPC + Send>>), - /// 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<OpaqueNode>), - OffsetParentQuery(OpaqueNode), - TextIndexQuery(OpaqueNode, Point2D<f32>), - NodesFromPointQuery(Point2D<f32>, 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<PseudoElement>, 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<Arc<Font>>; - 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<UntrustedNodeAddress>; - /// 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<Size2D<f32, CSSPixel>>; -} - -pub struct ContentBoxResponse(pub Option<Rect<Au>>); - -pub struct ContentBoxesResponse(pub Vec<Rect<Au>>); - -pub struct NodeGeometryResponse { - pub client_rect: Rect<i32>, -} - -pub struct NodeScrollIdResponse(pub ExternalScrollId); - -pub struct ResolvedStyleResponse(pub String); - -#[derive(Clone)] -pub struct OffsetParentResponse { - pub node_address: Option<UntrustedNodeAddress>, - pub rect: Rect<Au>, -} - -impl OffsetParentResponse { - pub fn empty() -> OffsetParentResponse { - OffsetParentResponse { - node_address: None, - rect: Rect::zero(), - } - } -} - -#[derive(Clone)] -pub struct TextIndexResponse(pub Option<usize>); |