forked from
me.webbeef.org/browser.html
Rewild Your Web
1--- original
2+++ modified
3@@ -39,13 +39,14 @@
4 use style::values::specified::text::TextDecorationLine;
5 use style_traits::{CSSPixel as StyloCSSPixel, DevicePixel as StyloDevicePixel};
6 use webrender_api::units::{
7- DeviceIntSize, DevicePixel, LayoutPixel, LayoutPoint, LayoutRect, LayoutSideOffsets, LayoutSize,
8+ DeviceIntSize, DevicePixel, LayoutPixel, LayoutPoint, LayoutRect, LayoutSideOffsets,
9+ LayoutSize, LayoutTransform,
10 };
11 use webrender_api::{
12 self as wr, BorderDetails, BorderRadius, BorderSide, BoxShadowClipMode, BuiltDisplayList,
13- ClipChainId, ClipMode, ColorF, CommonItemProperties, ComplexClipRegion, GlyphInstance,
14- NinePatchBorder, NinePatchBorderSource, NormalBorder, PrimitiveFlags, PropertyBinding,
15- SpatialId, SpatialTreeItemKey, units,
16+ ClipChainId, ClipMode, ColorF, CommonItemProperties, ComplexClipRegion, ExternalScrollId,
17+ GlyphInstance, NinePatchBorder, NinePatchBorderSource, NormalBorder, PrimitiveFlags,
18+ PropertyBinding, ReferenceFrameKind, SpatialId, SpatialTreeItemKey, TransformStyle, units,
19 };
20 use wr::units::LayoutVector2D;
21
22@@ -128,6 +129,9 @@
23
24 /// Statistics collected about the reflow, in order to write tests for incremental layout.
25 reflow_statistics: &'a mut ReflowStatistics,
26+ /// For embedded webviews with page zoom, this is the SpatialId of the zoom reference frame.
27+ /// When present, this is used as the root spatial ID instead of root_reference_frame.
28+ zoom_reference_frame_spatial_id: Option<SpatialId>,
29 }
30
31 struct InspectorHighlight {
32@@ -195,6 +199,36 @@
33 webrender_display_list_builder.dump_serialized_display_list();
34 }
35
36+ // For embedded webviews, apply page zoom as a root reference frame transform.
37+ // This is done here (inside the display list) rather than externally (in the painter)
38+ // because embedded webviews are rendered via push_iframe from their parent's display list.
39+ let page_zoom_for_rendering = paint_info.viewport_details.page_zoom_for_rendering;
40+ let zoom_reference_frame_spatial_id = if let Some(zoom) = page_zoom_for_rendering {
41+ log::warn!(
42+ "DisplayListBuilder: applying page_zoom_for_rendering={} for pipeline {:?}",
43+ zoom,
44+ pipeline_id
45+ );
46+ let transform = LayoutTransform::scale(zoom, zoom, 1.0);
47+ let root_ref_frame = SpatialId::root_reference_frame(pipeline_id);
48+ let zoom_spatial_id = webrender_display_list_builder.push_reference_frame(
49+ LayoutPoint::zero(),
50+ root_ref_frame,
51+ TransformStyle::Flat,
52+ PropertyBinding::Value(transform),
53+ ReferenceFrameKind::Transform {
54+ is_2d_scale_translation: true,
55+ should_snap: true,
56+ paired_with_perspective: false,
57+ },
58+ // Use a unique key for this zoom reference frame
59+ SpatialTreeItemKey::new(0, u64::MAX),
60+ );
61+ Some(zoom_spatial_id)
62+ } else {
63+ None
64+ };
65+
66 let _span = profile_traits::trace_span!("DisplayListBuilder::build").entered();
67 let mut builder = DisplayListBuilder {
68 current_scroll_node_id: paint_info.root_reference_frame_id,
69@@ -209,6 +243,7 @@
70 device_pixel_ratio,
71 paint_timing_handler,
72 reflow_statistics,
73+ zoom_reference_frame_spatial_id,
74 };
75
76 builder.add_all_spatial_nodes();
77@@ -222,15 +257,20 @@
78 let pipeline_id = builder.paint_info.pipeline_id;
79 let viewport_size = builder.paint_info.viewport_details.size;
80 let viewport_rect = LayoutRect::from_size(viewport_size.cast_unit());
81+ // Use the zoom reference frame if present, otherwise use the built-in root reference frame.
82+ // This ensures the viewport hit test is in the same coordinate space as content.
83+ let viewport_spatial_id = builder
84+ .zoom_reference_frame_spatial_id
85+ .unwrap_or_else(|| SpatialId::root_reference_frame(pipeline_id));
86 builder.wr().push_hit_test(
87 viewport_rect,
88 ClipChainId::INVALID,
89- SpatialId::root_reference_frame(pipeline_id),
90+ viewport_spatial_id,
91 PrimitiveFlags::default(),
92 (0, 0), /* tag */
93 );
94
95- // Paint the canvas’ background (if any) before/under everything else
96+ // Paint the canvas' background (if any) before/under everything else
97 stacking_context_tree
98 .root_stacking_context
99 .build_canvas_background_display_list(&mut builder, fragment_tree);
100@@ -239,6 +279,11 @@
101 .build_display_list(&mut builder);
102 builder.paint_dom_inspector_highlight();
103
104+ // Pop the zoom reference frame if we pushed one
105+ if page_zoom_for_rendering.is_some() {
106+ webrender_display_list_builder.pop_reference_frame();
107+ }
108+
109 webrender_display_list_builder.end().1
110 }
111
112@@ -276,12 +321,42 @@
113 let mut scroll_tree = std::mem::take(&mut self.paint_info.scroll_tree);
114 let mut mapping = Vec::with_capacity(scroll_tree.nodes.len());
115
116- mapping.push(SpatialId::root_reference_frame(self.pipeline_id()));
117- mapping.push(SpatialId::root_scroll_node(self.pipeline_id()));
118-
119 let pipeline_id = self.pipeline_id();
120 let pipeline_tag = ((pipeline_id.0 as u64) << 32) | pipeline_id.1 as u64;
121
122+ // If we have a zoom reference frame (for embedded webviews with page zoom),
123+ // use it as the root spatial ID and define our own scroll frame as its child.
124+ // Otherwise use the built-in root_reference_frame and root_scroll_node.
125+ // This ensures all content is rendered as a descendant of the zoom transform.
126+ if let Some(zoom_spatial_id) = self.zoom_reference_frame_spatial_id {
127+ mapping.push(zoom_spatial_id);
128+
129+ // Define a scroll frame as a child of the zoom reference frame.
130+ // This replaces the built-in root_scroll_node which is not a child of our zoom frame.
131+ let viewport_size = self.paint_info.viewport_details.size;
132+ let clip_rect = LayoutRect::from_size(viewport_size.cast_unit());
133+ // Use the same rect for content - actual scroll limits are managed by the scroll tree
134+ let content_rect = clip_rect;
135+
136+ spatial_tree_count += 1;
137+ let spatial_tree_item_key = SpatialTreeItemKey::new(pipeline_tag, spatial_tree_count);
138+
139+ let root_scroll_spatial_id = self.wr().define_scroll_frame(
140+ zoom_spatial_id,
141+ ExternalScrollId(0, pipeline_id.into()),
142+ content_rect,
143+ clip_rect,
144+ LayoutVector2D::zero(), /* external_scroll_offset */
145+ 0, /* scroll_offset_generation */
146+ wr::HasScrollLinkedEffect::No,
147+ spatial_tree_item_key,
148+ );
149+ mapping.push(root_scroll_spatial_id);
150+ } else {
151+ mapping.push(SpatialId::root_reference_frame(pipeline_id));
152+ mapping.push(SpatialId::root_scroll_node(pipeline_id));
153+ }
154+
155 for node in scroll_tree.nodes.iter().skip(2) {
156 let parent_scroll_node_id = node
157 .parent