Rewild Your Web
at main 157 lines 7.5 kB view raw
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