Rewild Your Web
web browser dweb
at main 158 lines 7.5 kB view raw
1--- original 2+++ modified 3@@ -37,13 +37,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@@ -123,6 +124,10 @@ 23 24 /// The collector for calculating Largest Contentful Paint 25 lcp_candidate_collector: Option<&'a mut LargestContentfulPaintCandidateCollector>, 26+ 27+ /// For embedded webviews with page zoom, this is the SpatialId of the zoom reference frame. 28+ /// When present, this is used as the root spatial ID instead of root_reference_frame. 29+ zoom_reference_frame_spatial_id: Option<SpatialId>, 30 } 31 32 struct InspectorHighlight { 33@@ -188,6 +193,36 @@ 34 webrender_display_list_builder.dump_serialized_display_list(); 35 } 36 37+ // For embedded webviews, apply page zoom as a root reference frame transform. 38+ // This is done here (inside the display list) rather than externally (in the painter) 39+ // because embedded webviews are rendered via push_iframe from their parent's display list. 40+ let page_zoom_for_rendering = paint_info.viewport_details.page_zoom_for_rendering; 41+ let zoom_reference_frame_spatial_id = if let Some(zoom) = page_zoom_for_rendering { 42+ log::warn!( 43+ "DisplayListBuilder: applying page_zoom_for_rendering={} for pipeline {:?}", 44+ zoom, 45+ pipeline_id 46+ ); 47+ let transform = LayoutTransform::scale(zoom, zoom, 1.0); 48+ let root_ref_frame = SpatialId::root_reference_frame(pipeline_id); 49+ let zoom_spatial_id = webrender_display_list_builder.push_reference_frame( 50+ LayoutPoint::zero(), 51+ root_ref_frame, 52+ TransformStyle::Flat, 53+ PropertyBinding::Value(transform), 54+ ReferenceFrameKind::Transform { 55+ is_2d_scale_translation: true, 56+ should_snap: true, 57+ paired_with_perspective: false, 58+ }, 59+ // Use a unique key for this zoom reference frame 60+ SpatialTreeItemKey::new(0, u64::MAX), 61+ ); 62+ Some(zoom_spatial_id) 63+ } else { 64+ None 65+ }; 66+ 67 let _span = profile_traits::trace_span!("DisplayListBuilder::build").entered(); 68 let mut builder = DisplayListBuilder { 69 current_scroll_node_id: paint_info.root_reference_frame_id, 70@@ -201,6 +236,7 @@ 71 image_resolver, 72 device_pixel_ratio, 73 lcp_candidate_collector, 74+ zoom_reference_frame_spatial_id, 75 }; 76 77 builder.add_all_spatial_nodes(); 78@@ -214,15 +250,20 @@ 79 let pipeline_id = builder.paint_info.pipeline_id; 80 let viewport_size = builder.paint_info.viewport_details.size; 81 let viewport_rect = LayoutRect::from_size(viewport_size.cast_unit()); 82+ // Use the zoom reference frame if present, otherwise use the built-in root reference frame. 83+ // This ensures the viewport hit test is in the same coordinate space as content. 84+ let viewport_spatial_id = builder 85+ .zoom_reference_frame_spatial_id 86+ .unwrap_or_else(|| SpatialId::root_reference_frame(pipeline_id)); 87 builder.wr().push_hit_test( 88 viewport_rect, 89 ClipChainId::INVALID, 90- SpatialId::root_reference_frame(pipeline_id), 91+ viewport_spatial_id, 92 PrimitiveFlags::default(), 93 (0, 0), /* tag */ 94 ); 95 96- // Paint the canvas’ background (if any) before/under everything else 97+ // Paint the canvas' background (if any) before/under everything else 98 stacking_context_tree 99 .root_stacking_context 100 .build_canvas_background_display_list(&mut builder, fragment_tree); 101@@ -231,6 +272,11 @@ 102 .build_display_list(&mut builder); 103 builder.paint_dom_inspector_highlight(); 104 105+ // Pop the zoom reference frame if we pushed one 106+ if page_zoom_for_rendering.is_some() { 107+ webrender_display_list_builder.pop_reference_frame(); 108+ } 109+ 110 webrender_display_list_builder.end().1 111 } 112 113@@ -268,12 +314,42 @@ 114 let mut scroll_tree = std::mem::take(&mut self.paint_info.scroll_tree); 115 let mut mapping = Vec::with_capacity(scroll_tree.nodes.len()); 116 117- mapping.push(SpatialId::root_reference_frame(self.pipeline_id())); 118- mapping.push(SpatialId::root_scroll_node(self.pipeline_id())); 119- 120 let pipeline_id = self.pipeline_id(); 121 let pipeline_tag = ((pipeline_id.0 as u64) << 32) | pipeline_id.1 as u64; 122 123+ // If we have a zoom reference frame (for embedded webviews with page zoom), 124+ // use it as the root spatial ID and define our own scroll frame as its child. 125+ // Otherwise use the built-in root_reference_frame and root_scroll_node. 126+ // This ensures all content is rendered as a descendant of the zoom transform. 127+ if let Some(zoom_spatial_id) = self.zoom_reference_frame_spatial_id { 128+ mapping.push(zoom_spatial_id); 129+ 130+ // Define a scroll frame as a child of the zoom reference frame. 131+ // This replaces the built-in root_scroll_node which is not a child of our zoom frame. 132+ let viewport_size = self.paint_info.viewport_details.size; 133+ let clip_rect = LayoutRect::from_size(viewport_size.cast_unit()); 134+ // Use the same rect for content - actual scroll limits are managed by the scroll tree 135+ let content_rect = clip_rect; 136+ 137+ spatial_tree_count += 1; 138+ let spatial_tree_item_key = SpatialTreeItemKey::new(pipeline_tag, spatial_tree_count); 139+ 140+ let root_scroll_spatial_id = self.wr().define_scroll_frame( 141+ zoom_spatial_id, 142+ ExternalScrollId(0, pipeline_id.into()), 143+ content_rect, 144+ clip_rect, 145+ LayoutVector2D::zero(), /* external_scroll_offset */ 146+ 0, /* scroll_offset_generation */ 147+ wr::HasScrollLinkedEffect::No, 148+ spatial_tree_item_key, 149+ ); 150+ mapping.push(root_scroll_spatial_id); 151+ } else { 152+ mapping.push(SpatialId::root_reference_frame(pipeline_id)); 153+ mapping.push(SpatialId::root_scroll_node(pipeline_id)); 154+ } 155+ 156 for node in scroll_tree.nodes.iter().skip(2) { 157 let parent_scroll_node_id = node 158 .parent