mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
script: Manage <iframe>
sizes in Window
(#34643)
Manage `<iframe>` size updates in `Window`. In addition to removing duplicated code, this will allow setting `<iframe>` sizes synchronously on child `Pipeline`s of the same origin in the script process in a followup change. The goal is remove flakiness from `<iframe>` sizing. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
eb82161a8a
commit
3e052676ef
18 changed files with 165 additions and 200 deletions
|
@ -11,7 +11,7 @@ use net_traits::image_cache::{
|
|||
ImageCache, ImageCacheResult, ImageOrMetadataAvailable, UsePlaceholder,
|
||||
};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use script_layout_interface::{PendingImage, PendingImageState};
|
||||
use script_layout_interface::{IFrameSizes, PendingImage, PendingImageState};
|
||||
use servo_url::{ImmutableOrigin, ServoUrl};
|
||||
use style::context::SharedStyleContext;
|
||||
use style::dom::OpaqueNode;
|
||||
|
@ -35,6 +35,9 @@ pub struct LayoutContext<'a> {
|
|||
/// A list of in-progress image loads to be shared with the script thread.
|
||||
pub pending_images: Mutex<Vec<PendingImage>>,
|
||||
|
||||
/// A collection of `<iframe>` sizes to send back to script.
|
||||
pub iframe_sizes: Mutex<IFrameSizes>,
|
||||
|
||||
pub webrender_image_cache:
|
||||
Arc<RwLock<FnvHashMap<(ServoUrl, UsePlaceholder), WebRenderImageInfo>>>,
|
||||
}
|
||||
|
|
|
@ -6,11 +6,9 @@ use std::cell::{OnceCell, RefCell};
|
|||
use std::sync::Arc;
|
||||
|
||||
use app_units::Au;
|
||||
use base::id::BrowsingContextId;
|
||||
use base::WebRenderEpochToU16;
|
||||
use embedder_traits::Cursor;
|
||||
use euclid::{Point2D, SideOffsets2D, Size2D, UnknownUnit};
|
||||
use fnv::FnvHashMap;
|
||||
use fonts::GlyphStore;
|
||||
use gradient::WebRenderGradient;
|
||||
use net_traits::image_cache::UsePlaceholder;
|
||||
|
@ -32,7 +30,6 @@ use style::values::generics::NonNegative;
|
|||
use style::values::specified::text::TextDecorationLine;
|
||||
use style::values::specified::ui::CursorKind;
|
||||
use style::Zero;
|
||||
use style_traits::CSSPixel;
|
||||
use webrender_api::units::{DevicePixel, LayoutPixel, LayoutRect, LayoutSize};
|
||||
use webrender_api::{
|
||||
self as wr, units, BorderDetails, BoxShadowClipMode, ClipChainId, CommonItemProperties,
|
||||
|
@ -162,12 +159,6 @@ pub(crate) struct DisplayListBuilder<'a> {
|
|||
/// The [DisplayList] used to collect display list items and metadata.
|
||||
pub display_list: &'a mut DisplayList,
|
||||
|
||||
/// A recording of the sizes of iframes encountered when building this
|
||||
/// display list. This information is forwarded to layout for the
|
||||
/// iframe so that its layout knows how large the initial containing block /
|
||||
/// viewport is.
|
||||
iframe_sizes: FnvHashMap<BrowsingContextId, Size2D<f32, CSSPixel>>,
|
||||
|
||||
/// Contentful paint i.e. whether the display list contains items of type
|
||||
/// text, image, non-white canvas or SVG). Used by metrics.
|
||||
/// See <https://w3c.github.io/paint-timing/#first-contentful-paint>.
|
||||
|
@ -175,12 +166,13 @@ pub(crate) struct DisplayListBuilder<'a> {
|
|||
}
|
||||
|
||||
impl DisplayList {
|
||||
/// Build the display list, returning true if it was contentful.
|
||||
pub fn build(
|
||||
&mut self,
|
||||
context: &LayoutContext,
|
||||
fragment_tree: &FragmentTree,
|
||||
root_stacking_context: &StackingContext,
|
||||
) -> (FnvHashMap<BrowsingContextId, Size2D<f32, CSSPixel>>, bool) {
|
||||
) -> bool {
|
||||
#[cfg(feature = "tracing")]
|
||||
let _span = tracing::trace_span!("display_list::build", servo_profiling = true).entered();
|
||||
let mut builder = DisplayListBuilder {
|
||||
|
@ -191,10 +183,9 @@ impl DisplayList {
|
|||
is_contentful: false,
|
||||
context,
|
||||
display_list: self,
|
||||
iframe_sizes: FnvHashMap::default(),
|
||||
};
|
||||
fragment_tree.build_display_list(&mut builder, root_stacking_context);
|
||||
(builder.iframe_sizes, builder.is_contentful)
|
||||
builder.is_contentful
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,11 +309,6 @@ impl Fragment {
|
|||
builder.is_contentful = true;
|
||||
let rect = iframe.rect.translate(containing_block.origin.to_vector());
|
||||
|
||||
builder.iframe_sizes.insert(
|
||||
iframe.browsing_context_id,
|
||||
Size2D::new(rect.size.width.to_f32_px(), rect.size.height.to_f32_px()),
|
||||
);
|
||||
|
||||
let common = builder.common_properties(rect.to_webrender(), &iframe.style);
|
||||
builder.wr().push_iframe(
|
||||
rect.to_webrender(),
|
||||
|
|
|
@ -1987,8 +1987,11 @@ impl FlexItem<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
let fragments = replaced
|
||||
.make_fragments(item_style, size.to_physical_size(container_writing_mode));
|
||||
let fragments = replaced.make_fragments(
|
||||
flex_context.layout_context,
|
||||
item_style,
|
||||
size.to_physical_size(container_writing_mode),
|
||||
);
|
||||
|
||||
Some(FlexItemLayoutResult {
|
||||
hypothetical_cross_size,
|
||||
|
|
|
@ -1399,6 +1399,7 @@ impl ReplacedContents {
|
|||
fn layout_in_flow_block_level(
|
||||
&self,
|
||||
base: &LayoutBoxBase,
|
||||
layout_context: &LayoutContext,
|
||||
containing_block: &ContainingBlock,
|
||||
mut sequential_layout_state: Option<&mut SequentialLayoutState>,
|
||||
) -> BoxFragment {
|
||||
|
@ -1420,7 +1421,7 @@ impl ReplacedContents {
|
|||
|
||||
let containing_block_writing_mode = containing_block.style.writing_mode;
|
||||
let physical_content_size = content_size.to_physical_size(containing_block_writing_mode);
|
||||
let fragments = self.make_fragments(&base.style, physical_content_size);
|
||||
let fragments = self.make_fragments(layout_context, &base.style, physical_content_size);
|
||||
|
||||
let clearance;
|
||||
if let Some(ref mut sequential_layout_state) = sequential_layout_state {
|
||||
|
@ -2071,7 +2072,12 @@ impl IndependentFormattingContext {
|
|||
sequential_layout_state,
|
||||
),
|
||||
IndependentFormattingContextContents::Replaced(contents) => contents
|
||||
.layout_in_flow_block_level(&self.base, containing_block, sequential_layout_state),
|
||||
.layout_in_flow_block_level(
|
||||
&self.base,
|
||||
layout_context,
|
||||
containing_block,
|
||||
sequential_layout_state,
|
||||
),
|
||||
}
|
||||
}
|
||||
pub(crate) fn layout_float_or_atomic_inline(
|
||||
|
@ -2099,7 +2105,7 @@ impl IndependentFormattingContext {
|
|||
&content_box_sizes_and_pbm,
|
||||
)
|
||||
.to_physical_size(container_writing_mode);
|
||||
let fragments = replaced.make_fragments(style, content_size);
|
||||
let fragments = replaced.make_fragments(layout_context, style, content_size);
|
||||
|
||||
let content_rect = PhysicalRect::new(PhysicalPoint::zero(), content_size);
|
||||
(fragments, content_rect, None)
|
||||
|
|
|
@ -572,6 +572,7 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
block: block_axis.size.to_definite().unwrap(),
|
||||
};
|
||||
fragments = replaced.make_fragments(
|
||||
layout_context,
|
||||
&style,
|
||||
content_size.to_physical_size(containing_block_writing_mode),
|
||||
);
|
||||
|
|
|
@ -10,9 +10,11 @@ use app_units::Au;
|
|||
use base::id::{BrowsingContextId, PipelineId};
|
||||
use canvas_traits::canvas::{CanvasId, CanvasMsg, FromLayoutMsg};
|
||||
use data_url::DataUrl;
|
||||
use euclid::Size2D;
|
||||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use net_traits::image_cache::{ImageOrMetadataAvailable, UsePlaceholder};
|
||||
use pixels::Image;
|
||||
use script_layout_interface::IFrameSize;
|
||||
use serde::Serialize;
|
||||
use servo_arc::Arc as ServoArc;
|
||||
use style::computed_values::object_fit::T as ObjectFit;
|
||||
|
@ -280,6 +282,7 @@ impl ReplacedContents {
|
|||
|
||||
pub fn make_fragments(
|
||||
&self,
|
||||
layout_context: &LayoutContext,
|
||||
style: &ServoArc<ComputedValues>,
|
||||
size: PhysicalSize<Au>,
|
||||
) -> Vec<Fragment> {
|
||||
|
@ -349,6 +352,15 @@ impl ReplacedContents {
|
|||
image_key: video.as_ref().map(|video| video.image_key),
|
||||
})],
|
||||
ReplacedContentKind::IFrame(iframe) => {
|
||||
let size = Size2D::new(rect.size.width.to_f32_px(), rect.size.height.to_f32_px());
|
||||
layout_context.iframe_sizes.lock().insert(
|
||||
iframe.browsing_context_id,
|
||||
IFrameSize {
|
||||
browsing_context_id: iframe.browsing_context_id,
|
||||
pipeline_id: iframe.pipeline_id,
|
||||
size,
|
||||
},
|
||||
);
|
||||
vec![Fragment::IFrame(IFrameFragment {
|
||||
base: self.base_fragment_info.into(),
|
||||
style: style.clone(),
|
||||
|
|
|
@ -174,8 +174,11 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> {
|
|||
// Create fragments if the RunMode if PerformLayout
|
||||
// If the RunMode is ComputeSize then only the returned size will be used
|
||||
if inputs.run_mode == RunMode::PerformLayout {
|
||||
child.child_fragments =
|
||||
replaced.make_fragments(style, content_box_size);
|
||||
child.child_fragments = replaced.make_fragments(
|
||||
self.layout_context,
|
||||
style,
|
||||
content_box_size,
|
||||
);
|
||||
}
|
||||
|
||||
let computed_size = taffy::Size {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue