Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit ec2ff2c

Browse files
committed
servo: Merge #19881 - Add layout RPC query for getting an element's style (from jonleighton:issue-19811); r=emilio
This enables us to implement Element::has_css_layout_box() in a more direct way, and also enables us to remove some of the existing more specific queries. Fixes #19811. r? @emilio Source-Repo: https://github.com/servo/servo Source-Revision: 2a46067587d63aec176621ab3b6112ef5200a248 --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 715f36d9bedb88b8bba29eff16913cb31a426305
1 parent 311adb3 commit ec2ff2c

10 files changed

Lines changed: 88 additions & 136 deletions

File tree

servo/components/layout/query.rs

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ use ipc_channel::ipc::IpcSender;
1616
use msg::constellation_msg::PipelineId;
1717
use opaque_node::OpaqueNodeMethods;
1818
use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse, LayoutRPC};
19-
use script_layout_interface::rpc::{MarginStyleResponse, NodeGeometryResponse};
20-
use script_layout_interface::rpc::{NodeOverflowResponse, NodeScrollRootIdResponse};
21-
use script_layout_interface::rpc::{OffsetParentResponse, ResolvedStyleResponse, TextIndexResponse};
19+
use script_layout_interface::rpc::{NodeGeometryResponse, NodeScrollRootIdResponse};
20+
use script_layout_interface::rpc::{OffsetParentResponse, ResolvedStyleResponse, StyleResponse};
21+
use script_layout_interface::rpc::TextIndexResponse;
2222
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
2323
use script_traits::LayoutMsg as ConstellationMsg;
2424
use script_traits::UntrustedNodeAddress;
@@ -59,9 +59,6 @@ pub struct LayoutThreadData {
5959
/// A queued response for the scroll root id for a given node.
6060
pub scroll_root_id_response: Option<ClipId>,
6161

62-
/// A pair of overflow property in x and y
63-
pub overflow_response: NodeOverflowResponse,
64-
6562
/// A queued response for the scroll {top, left, width, height} of a node in pixels.
6663
pub scroll_area_response: Rect<i32>,
6764

@@ -71,8 +68,8 @@ pub struct LayoutThreadData {
7168
/// A queued response for the offset parent/rect of a node.
7269
pub offset_parent_response: OffsetParentResponse,
7370

74-
/// A queued response for the offset parent/rect of a node.
75-
pub margin_style_response: MarginStyleResponse,
71+
/// A queued response for the style of a node.
72+
pub style_response: StyleResponse,
7673

7774
/// Scroll offsets of scrolling regions.
7875
pub scroll_offsets: ScrollOffsetMap,
@@ -128,10 +125,6 @@ impl LayoutRPC for LayoutRPCImpl {
128125
}
129126
}
130127

131-
fn node_overflow(&self) -> NodeOverflowResponse {
132-
NodeOverflowResponse(self.0.lock().unwrap().overflow_response.0)
133-
}
134-
135128
fn node_scroll_area(&self) -> NodeGeometryResponse {
136129
NodeGeometryResponse {
137130
client_rect: self.0.lock().unwrap().scroll_area_response
@@ -157,10 +150,10 @@ impl LayoutRPC for LayoutRPCImpl {
157150
rw_data.offset_parent_response.clone()
158151
}
159152

160-
fn margin_style(&self) -> MarginStyleResponse {
153+
fn style(&self) -> StyleResponse {
161154
let &LayoutRPCImpl(ref rw_data) = self;
162155
let rw_data = rw_data.lock().unwrap();
163-
rw_data.margin_style_response.clone()
156+
rw_data.style_response.clone()
164157
}
165158

166159
fn text_index(&self) -> TextIndexResponse {
@@ -863,24 +856,10 @@ pub fn process_offset_parent_query<N: LayoutNode>(requested_node: N, layout_root
863856
}
864857
}
865858

866-
pub fn process_node_overflow_request<N: LayoutNode>(requested_node: N) -> NodeOverflowResponse {
867-
let layout_node = requested_node.to_threadsafe();
868-
let style = &*layout_node.as_element().unwrap().resolved_style();
869-
let style_box = style.get_box();
870-
871-
NodeOverflowResponse(Some(Point2D::new(style_box.overflow_x, style_box.overflow_y)))
872-
}
873-
874-
pub fn process_margin_style_query<N: LayoutNode>(requested_node: N)
875-
-> MarginStyleResponse {
876-
let layout_node = requested_node.to_threadsafe();
877-
let style = &*layout_node.as_element().unwrap().resolved_style();
878-
let margin = style.get_margin();
859+
pub fn process_style_query<N: LayoutNode>(requested_node: N)
860+
-> StyleResponse {
861+
let element = requested_node.as_element().unwrap();
862+
let data = element.borrow_data();
879863

880-
MarginStyleResponse {
881-
top: margin.margin_top,
882-
right: margin.margin_right,
883-
bottom: margin.margin_bottom,
884-
left: margin.margin_left,
885-
}
864+
StyleResponse(data.map(|d| d.styles.primary().clone()))
886865
}

servo/components/layout_thread/lib.rs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ use layout::incremental::{LayoutDamageComputation, RelayoutMode, SpecialRestyleD
7575
use layout::layout_debug;
7676
use layout::parallel;
7777
use layout::query::{LayoutRPCImpl, LayoutThreadData, process_content_box_request, process_content_boxes_request};
78-
use layout::query::{process_margin_style_query, process_node_overflow_request, process_resolved_style_request};
7978
use layout::query::{process_node_geometry_request, process_node_scroll_area_request};
80-
use layout::query::{process_node_scroll_root_id_request, process_offset_parent_query};
79+
use layout::query::{process_node_scroll_root_id_request, process_offset_parent_query, process_resolved_style_request};
80+
use layout::query::process_style_query;
8181
use layout::sequential;
8282
use layout::traversal::{ComputeStackingRelativePositions, PreorderFlowTraversal, RecalcStyleAndConstructFlows};
8383
use layout::wrapper::LayoutNodeLayoutData;
@@ -94,7 +94,7 @@ use profile_traits::time::{self, TimerMetadata, profile};
9494
use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType};
9595
use script_layout_interface::message::{Msg, NewLayoutThreadInfo, NodesFromPointQueryType, Reflow};
9696
use script_layout_interface::message::{ReflowComplete, ReflowGoal, ScriptReflow};
97-
use script_layout_interface::rpc::{LayoutRPC, MarginStyleResponse, NodeOverflowResponse, OffsetParentResponse};
97+
use script_layout_interface::rpc::{LayoutRPC, StyleResponse, OffsetParentResponse};
9898
use script_layout_interface::rpc::TextIndexResponse;
9999
use script_layout_interface::wrapper_traits::LayoutNode;
100100
use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg};
@@ -519,10 +519,9 @@ impl LayoutThread {
519519
client_rect_response: Rect::zero(),
520520
scroll_root_id_response: None,
521521
scroll_area_response: Rect::zero(),
522-
overflow_response: NodeOverflowResponse(None),
523522
resolved_style_response: String::new(),
524523
offset_parent_response: OffsetParentResponse::empty(),
525-
margin_style_response: MarginStyleResponse::empty(),
524+
style_response: StyleResponse(None),
526525
scroll_offsets: HashMap::new(),
527526
text_index_response: TextIndexResponse(None),
528527
nodes_from_point_response: vec![],
@@ -1092,9 +1091,6 @@ impl LayoutThread {
10921091
ReflowGoal::NodeScrollGeometryQuery(_) => {
10931092
rw_data.scroll_area_response = Rect::zero();
10941093
},
1095-
ReflowGoal::NodeOverflowQuery(_) => {
1096-
rw_data.overflow_response = NodeOverflowResponse(None);
1097-
},
10981094
ReflowGoal::NodeScrollRootIdQuery(_) => {
10991095
rw_data.scroll_root_id_response = None;
11001096
},
@@ -1104,8 +1100,8 @@ impl LayoutThread {
11041100
ReflowGoal::OffsetParentQuery(_) => {
11051101
rw_data.offset_parent_response = OffsetParentResponse::empty();
11061102
},
1107-
ReflowGoal::MarginStyleQuery(_) => {
1108-
rw_data.margin_style_response = MarginStyleResponse::empty();
1103+
ReflowGoal::StyleQuery(_) => {
1104+
rw_data.style_response = StyleResponse(None);
11091105
},
11101106
ReflowGoal::TextIndexQuery(..) => {
11111107
rw_data.text_index_response = TextIndexResponse(None);
@@ -1379,10 +1375,6 @@ impl LayoutThread {
13791375
let node = unsafe { ServoLayoutNode::new(&node) };
13801376
rw_data.scroll_area_response = process_node_scroll_area_request(node, root_flow);
13811377
},
1382-
ReflowGoal::NodeOverflowQuery(node) => {
1383-
let node = unsafe { ServoLayoutNode::new(&node) };
1384-
rw_data.overflow_response = process_node_overflow_request(node);
1385-
},
13861378
ReflowGoal::NodeScrollRootIdQuery(node) => {
13871379
let node = unsafe { ServoLayoutNode::new(&node) };
13881380
rw_data.scroll_root_id_response = Some(process_node_scroll_root_id_request(self.id,
@@ -1401,9 +1393,9 @@ impl LayoutThread {
14011393
let node = unsafe { ServoLayoutNode::new(&node) };
14021394
rw_data.offset_parent_response = process_offset_parent_query(node, root_flow);
14031395
},
1404-
ReflowGoal::MarginStyleQuery(node) => {
1396+
ReflowGoal::StyleQuery(node) => {
14051397
let node = unsafe { ServoLayoutNode::new(&node) };
1406-
rw_data.margin_style_response = process_margin_style_query(node);
1398+
rw_data.style_response = process_style_query(node);
14071399
},
14081400
ReflowGoal::NodesFromPointQuery(client_point, ref reflow_goal) => {
14091401
let mut flags = match reflow_goal {

servo/components/script/devtools.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,13 @@ pub fn handle_get_layout(documents: &Documents,
154154
}
155155

156156
fn determine_auto_margins(window: &Window, node: &Node) -> AutoMargins {
157-
let margin = window.margin_style_query(node.to_trusted_node_address());
157+
let style = window.style_query(node.to_trusted_node_address()).unwrap();
158+
let margin = style.get_margin();
158159
AutoMargins {
159-
top: margin.top == margin_top::computed_value::T::Auto,
160-
right: margin.right == margin_right::computed_value::T::Auto,
161-
bottom: margin.bottom == margin_bottom::computed_value::T::Auto,
162-
left: margin.left == margin_left::computed_value::T::Auto,
160+
top: margin.margin_top == margin_top::computed_value::T::Auto,
161+
right: margin.margin_right == margin_right::computed_value::T::Auto,
162+
bottom: margin.margin_bottom == margin_bottom::computed_value::T::Auto,
163+
left: margin.margin_left == margin_left::computed_value::T::Auto,
163164
}
164165
}
165166

servo/components/script/dom/element.rs

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -348,60 +348,58 @@ impl Element {
348348
}
349349

350350
// https://drafts.csswg.org/cssom-view/#css-layout-box
351-
//
352-
// We'll have no content box if there's no fragment for the node, and we use
353-
// bounding_content_box, for simplicity, to detect this (rather than making a more specific
354-
// query to the layout thread).
355351
fn has_css_layout_box(&self) -> bool {
356-
self.upcast::<Node>().bounding_content_box().is_some()
352+
let style = self.upcast::<Node>().style();
353+
354+
// style will be None for elements in a display: none subtree. otherwise, the element has a
355+
// layout box iff it doesn't have display: none.
356+
style.map_or(false, |s| !s.get_box().clone_display().is_none())
357357
}
358358

359359
// https://drafts.csswg.org/cssom-view/#potentially-scrollable
360360
fn potentially_scrollable(&self) -> bool {
361-
self.has_css_layout_box() &&
362-
!self.overflow_x_is_visible() &&
363-
!self.overflow_y_is_visible()
361+
self.has_css_layout_box() && !self.has_any_visible_overflow()
364362
}
365363

366364
// https://drafts.csswg.org/cssom-view/#scrolling-box
367365
fn has_scrolling_box(&self) -> bool {
368366
// TODO: scrolling mechanism, such as scrollbar (We don't have scrollbar yet)
369367
// self.has_scrolling_mechanism()
370-
self.overflow_x_is_hidden() ||
371-
self.overflow_y_is_hidden()
368+
self.has_any_hidden_overflow()
372369
}
373370

374371
fn has_overflow(&self) -> bool {
375372
self.ScrollHeight() > self.ClientHeight() ||
376373
self.ScrollWidth() > self.ClientWidth()
377374
}
378375

379-
// used value of overflow-x is "visible"
380-
fn overflow_x_is_visible(&self) -> bool {
381-
let window = window_from_node(self);
382-
let overflow_pair = window.overflow_query(self.upcast::<Node>().to_trusted_node_address());
383-
overflow_pair.x == overflow_x::computed_value::T::Visible
384-
}
376+
// TODO: Once #19183 is closed (overflow-x/y types moved out of mako), then we could implement
377+
// a more generic `fn has_some_overflow(&self, overflow: Overflow)` rather than have
378+
// these two `has_any_{visible,hidden}_overflow` methods which are very structurally
379+
// similar.
385380

386-
// used value of overflow-y is "visible"
387-
fn overflow_y_is_visible(&self) -> bool {
388-
let window = window_from_node(self);
389-
let overflow_pair = window.overflow_query(self.upcast::<Node>().to_trusted_node_address());
390-
overflow_pair.y == overflow_y::computed_value::T::Visible
391-
}
381+
/// Computed value of overflow-x or overflow-y is "visible"
382+
fn has_any_visible_overflow(&self) -> bool {
383+
let style = self.upcast::<Node>().style();
392384

393-
// used value of overflow-x is "hidden"
394-
fn overflow_x_is_hidden(&self) -> bool {
395-
let window = window_from_node(self);
396-
let overflow_pair = window.overflow_query(self.upcast::<Node>().to_trusted_node_address());
397-
overflow_pair.x == overflow_x::computed_value::T::Hidden
385+
style.map_or(false, |s| {
386+
let box_ = s.get_box();
387+
388+
box_.clone_overflow_x() == overflow_x::computed_value::T::Visible ||
389+
box_.clone_overflow_y() == overflow_y::computed_value::T::Visible
390+
})
398391
}
399392

400-
// used value of overflow-y is "hidden"
401-
fn overflow_y_is_hidden(&self) -> bool {
402-
let window = window_from_node(self);
403-
let overflow_pair = window.overflow_query(self.upcast::<Node>().to_trusted_node_address());
404-
overflow_pair.y == overflow_y::computed_value::T::Hidden
393+
/// Computed value of overflow-x or overflow-y is "hidden"
394+
fn has_any_hidden_overflow(&self) -> bool {
395+
let style = self.upcast::<Node>().style();
396+
397+
style.map_or(false, |s| {
398+
let box_ = s.get_box();
399+
400+
box_.clone_overflow_x() == overflow_x::computed_value::T::Hidden ||
401+
box_.clone_overflow_y() == overflow_y::computed_value::T::Hidden
402+
})
405403
}
406404
}
407405

servo/components/script/dom/node.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ use std::mem;
8282
use std::ops::Range;
8383
use style::context::QuirksMode;
8484
use style::dom::OpaqueNode;
85+
use style::properties::ComputedValues;
8586
use style::selector_parser::{SelectorImpl, SelectorParser};
8687
use style::stylesheets::Stylesheet;
8788
use style::thread_state;
@@ -619,6 +620,10 @@ impl Node {
619620
window_from_node(self).client_rect_query(self.to_trusted_node_address())
620621
}
621622

623+
pub fn style(&self) -> Option<Arc<ComputedValues>> {
624+
window_from_node(self).style_query(self.to_trusted_node_address())
625+
}
626+
622627
// https://drafts.csswg.org/cssom-view/#dom-element-scrollwidth
623628
// https://drafts.csswg.org/cssom-view/#dom-element-scrollheight
624629
// https://drafts.csswg.org/cssom-view/#dom-element-scrolltop

servo/components/script/dom/window.rs

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ use script_layout_interface::{TrustedNodeAddress, PendingImageState};
7272
use script_layout_interface::message::{Msg, Reflow, ReflowGoal, ScriptReflow};
7373
use script_layout_interface::reporter::CSSErrorReporter;
7474
use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse, LayoutRPC};
75-
use script_layout_interface::rpc::{MarginStyleResponse, NodeScrollRootIdResponse};
76-
use script_layout_interface::rpc::{ResolvedStyleResponse, TextIndexResponse};
75+
use script_layout_interface::rpc::{NodeScrollRootIdResponse, ResolvedStyleResponse, TextIndexResponse};
7776
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, ScriptThreadEventCategory, Runtime};
7877
use script_thread::{ImageCacheMsg, MainThreadScriptChan, MainThreadScriptMsg};
7978
use script_thread::{ScriptThread, SendableMainThreadScriptChan};
@@ -82,6 +81,7 @@ use script_traits::{ScriptToConstellationChan, ScriptMsg, ScrollState, TimerEven
8281
use script_traits::{TimerSchedulerMsg, UntrustedNodeAddress, WindowSizeData, WindowSizeType};
8382
use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
8483
use selectors::attr::CaseSensitivity;
84+
use servo_arc;
8585
use servo_config::opts;
8686
use servo_config::prefs::PREFS;
8787
use servo_geometry::{f32_rect_to_au_rect, MaxRect};
@@ -102,8 +102,7 @@ use std::sync::mpsc::{Sender, channel};
102102
use std::sync::mpsc::TryRecvError::{Disconnected, Empty};
103103
use style::media_queries;
104104
use style::parser::ParserContext as CssParserContext;
105-
use style::properties::PropertyId;
106-
use style::properties::longhands::overflow_x;
105+
use style::properties::{ComputedValues, PropertyId};
107106
use style::selector_parser::PseudoElement;
108107
use style::str::HTML_SPACE_CHARACTERS;
109108
use style::stylesheets::CssRuleType;
@@ -1403,16 +1402,6 @@ impl Window {
14031402
self.layout_rpc.node_scroll_area().client_rect
14041403
}
14051404

1406-
pub fn overflow_query(&self,
1407-
node: TrustedNodeAddress) -> Point2D<overflow_x::computed_value::T> {
1408-
// NB: This is only called if the document is fully active, and the only
1409-
// reason to bail out from a query is if there's no viewport, so this
1410-
// *must* issue a reflow.
1411-
assert!(self.reflow(ReflowGoal::NodeOverflowQuery(node), ReflowReason::Query));
1412-
1413-
self.layout_rpc.node_overflow().0.unwrap()
1414-
}
1415-
14161405
pub fn scroll_offset_query(&self, node: &Node) -> Vector2D<f32> {
14171406
if let Some(scroll_offset) = self.scroll_offsets
14181407
.borrow()
@@ -1477,11 +1466,11 @@ impl Window {
14771466
(element, response.rect)
14781467
}
14791468

1480-
pub fn margin_style_query(&self, node: TrustedNodeAddress) -> MarginStyleResponse {
1481-
if !self.reflow(ReflowGoal::MarginStyleQuery(node), ReflowReason::Query) {
1482-
return MarginStyleResponse::empty();
1469+
pub fn style_query(&self, node: TrustedNodeAddress) -> Option<servo_arc::Arc<ComputedValues>> {
1470+
if !self.reflow(ReflowGoal::StyleQuery(node), ReflowReason::Query) {
1471+
return None
14831472
}
1484-
self.layout_rpc.margin_style()
1473+
self.layout_rpc.style().0
14851474
}
14861475

14871476
pub fn text_index_query(
@@ -1898,12 +1887,11 @@ fn debug_reflow_events(id: PipelineId, reflow_goal: &ReflowGoal, reason: &Reflow
18981887
ReflowGoal::ContentBoxesQuery(_n) => "\tContentBoxesQuery",
18991888
ReflowGoal::NodesFromPointQuery(..) => "\tNodesFromPointQuery",
19001889
ReflowGoal::NodeGeometryQuery(_n) => "\tNodeGeometryQuery",
1901-
ReflowGoal::NodeOverflowQuery(_n) => "\tNodeOverFlowQuery",
19021890
ReflowGoal::NodeScrollGeometryQuery(_n) => "\tNodeScrollGeometryQuery",
19031891
ReflowGoal::NodeScrollRootIdQuery(_n) => "\tNodeScrollRootIdQuery",
19041892
ReflowGoal::ResolvedStyleQuery(_, _, _) => "\tResolvedStyleQuery",
19051893
ReflowGoal::OffsetParentQuery(_n) => "\tOffsetParentQuery",
1906-
ReflowGoal::MarginStyleQuery(_n) => "\tMarginStyleQuery",
1894+
ReflowGoal::StyleQuery(_n) => "\tStyleQuery",
19071895
ReflowGoal::TextIndexQuery(..) => "\tTextIndexQuery",
19081896
ReflowGoal::TickAnimations => "\tTickAnimations",
19091897
});

0 commit comments

Comments
 (0)