mirror of
https://github.com/servo/servo.git
synced 2025-07-29 10:10:34 +01:00
Add support for <iframe> elements for Layout 2020
This change adds support for the <iframe> element to Layout 2020. In addition, certain aspects of the implementation are made the same between both layout systems.
This commit is contained in:
parent
e09acf88f4
commit
9e0b41ebc4
38 changed files with 281 additions and 164 deletions
|
@ -3106,13 +3106,18 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_iframe_size_msg(&mut self, iframe_sizes: Vec<IFrameSizeMsg>) {
|
fn handle_iframe_size_msg(&mut self, iframe_sizes: Vec<IFrameSizeMsg>) {
|
||||||
for IFrameSizeMsg { data, type_ } in iframe_sizes {
|
for IFrameSizeMsg {
|
||||||
|
browsing_context_id,
|
||||||
|
size,
|
||||||
|
type_,
|
||||||
|
} in iframe_sizes
|
||||||
|
{
|
||||||
let window_size = WindowSizeData {
|
let window_size = WindowSizeData {
|
||||||
initial_viewport: data.size,
|
initial_viewport: size,
|
||||||
device_pixel_ratio: self.window_size.device_pixel_ratio,
|
device_pixel_ratio: self.window_size.device_pixel_ratio,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.resize_browsing_context(window_size, type_, data.id);
|
self.resize_browsing_context(window_size, type_, browsing_context_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,10 +43,9 @@ use gfx::text::glyph::ByteIndex;
|
||||||
use gfx::text::TextRun;
|
use gfx::text::TextRun;
|
||||||
use gfx_traits::{combine_id_with_fragment_type, FragmentType, StackingContextId};
|
use gfx_traits::{combine_id_with_fragment_type, FragmentType, StackingContextId};
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::{BrowsingContextId, PipelineId};
|
||||||
use net_traits::image_cache::UsePlaceholder;
|
use net_traits::image_cache::UsePlaceholder;
|
||||||
use range::Range;
|
use range::Range;
|
||||||
use script_traits::IFrameSize;
|
|
||||||
use servo_config::opts;
|
use servo_config::opts;
|
||||||
use servo_geometry::{self, MaxRect};
|
use servo_geometry::{self, MaxRect};
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
@ -68,7 +67,7 @@ use style::values::generics::background::BackgroundSize;
|
||||||
use style::values::generics::image::PaintWorklet;
|
use style::values::generics::image::PaintWorklet;
|
||||||
use style::values::specified::ui::CursorKind;
|
use style::values::specified::ui::CursorKind;
|
||||||
use style::values::RGBA;
|
use style::values::RGBA;
|
||||||
use style_traits::ToCss;
|
use style_traits::{CSSPixel, ToCss};
|
||||||
use webrender_api::units::{LayoutRect, LayoutTransform, LayoutVector2D};
|
use webrender_api::units::{LayoutRect, LayoutTransform, LayoutVector2D};
|
||||||
use webrender_api::{self, BorderDetails, BorderRadius, BorderSide, BoxShadowClipMode, ColorF};
|
use webrender_api::{self, BorderDetails, BorderRadius, BorderSide, BoxShadowClipMode, ColorF};
|
||||||
use webrender_api::{ColorU, ExternalScrollId, FilterOp, GlyphInstance, ImageRendering, LineStyle};
|
use webrender_api::{ColorU, ExternalScrollId, FilterOp, GlyphInstance, ImageRendering, LineStyle};
|
||||||
|
@ -328,7 +327,7 @@ pub struct DisplayListBuildState<'a> {
|
||||||
|
|
||||||
/// Vector containing iframe sizes, used to inform the constellation about
|
/// Vector containing iframe sizes, used to inform the constellation about
|
||||||
/// new iframe sizes
|
/// new iframe sizes
|
||||||
pub iframe_sizes: Vec<IFrameSize>,
|
pub iframe_sizes: FnvHashMap<BrowsingContextId, euclid::Size2D<f32, CSSPixel>>,
|
||||||
|
|
||||||
/// Stores text runs to answer text queries used to place a cursor inside text.
|
/// Stores text runs to answer text queries used to place a cursor inside text.
|
||||||
pub indexable_text: IndexableText,
|
pub indexable_text: IndexableText,
|
||||||
|
@ -350,7 +349,7 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
current_clipping_and_scrolling: ClippingAndScrolling::simple(
|
current_clipping_and_scrolling: ClippingAndScrolling::simple(
|
||||||
ClipScrollNodeIndex::root_scroll_node(),
|
ClipScrollNodeIndex::root_scroll_node(),
|
||||||
),
|
),
|
||||||
iframe_sizes: Vec::new(),
|
iframe_sizes: FnvHashMap::default(),
|
||||||
indexable_text: IndexableText::default(),
|
indexable_text: IndexableText::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1838,10 +1837,10 @@ impl Fragment {
|
||||||
|
|
||||||
// XXXjdm: This sleight-of-hand to convert LayoutRect -> Size2D<CSSPixel>
|
// XXXjdm: This sleight-of-hand to convert LayoutRect -> Size2D<CSSPixel>
|
||||||
// looks bogus.
|
// looks bogus.
|
||||||
state.iframe_sizes.push(IFrameSize {
|
state.iframe_sizes.insert(
|
||||||
id: browsing_context_id,
|
browsing_context_id,
|
||||||
size: euclid::Size2D::new(bounds.size.width, bounds.size.height),
|
euclid::Size2D::new(bounds.size.width, bounds.size.height),
|
||||||
});
|
);
|
||||||
|
|
||||||
let pipeline_id = match fragment_info.pipeline_id {
|
let pipeline_id = match fragment_info.pipeline_id {
|
||||||
Some(pipeline_id) => pipeline_id,
|
Some(pipeline_id) => pipeline_id,
|
||||||
|
|
|
@ -10,8 +10,10 @@ use crate::replaced::IntrinsicSizes;
|
||||||
use crate::style_ext::ComputedValuesExt;
|
use crate::style_ext::ComputedValuesExt;
|
||||||
use embedder_traits::Cursor;
|
use embedder_traits::Cursor;
|
||||||
use euclid::{Point2D, SideOffsets2D, Size2D};
|
use euclid::{Point2D, SideOffsets2D, Size2D};
|
||||||
|
use fnv::FnvHashMap;
|
||||||
use gfx::text::glyph::GlyphStore;
|
use gfx::text::glyph::GlyphStore;
|
||||||
use mitochondria::OnceCell;
|
use mitochondria::OnceCell;
|
||||||
|
use msg::constellation_msg::BrowsingContextId;
|
||||||
use net_traits::image_cache::UsePlaceholder;
|
use net_traits::image_cache::UsePlaceholder;
|
||||||
use script_traits::compositor::CompositorDisplayListInfo;
|
use script_traits::compositor::CompositorDisplayListInfo;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -22,6 +24,7 @@ use style::properties::ComputedValues;
|
||||||
use style::values::computed::{BorderStyle, Length, LengthPercentage};
|
use style::values::computed::{BorderStyle, Length, LengthPercentage};
|
||||||
use style::values::specified::text::TextDecorationLine;
|
use style::values::specified::text::TextDecorationLine;
|
||||||
use style::values::specified::ui::CursorKind;
|
use style::values::specified::ui::CursorKind;
|
||||||
|
use style_traits::CSSPixel;
|
||||||
use webrender_api::{self as wr, units};
|
use webrender_api::{self as wr, units};
|
||||||
|
|
||||||
mod background;
|
mod background;
|
||||||
|
@ -48,6 +51,7 @@ pub struct DisplayListBuilder<'a> {
|
||||||
pub context: &'a LayoutContext<'a>,
|
pub context: &'a LayoutContext<'a>,
|
||||||
pub wr: wr::DisplayListBuilder,
|
pub wr: wr::DisplayListBuilder,
|
||||||
pub compositor_info: CompositorDisplayListInfo,
|
pub compositor_info: CompositorDisplayListInfo,
|
||||||
|
pub iframe_sizes: FnvHashMap<BrowsingContextId, Size2D<f32, CSSPixel>>,
|
||||||
|
|
||||||
/// Contentful paint, for the purpose of
|
/// Contentful paint, for the purpose of
|
||||||
/// https://w3c.github.io/paint-timing/#first-contentful-paint
|
/// https://w3c.github.io/paint-timing/#first-contentful-paint
|
||||||
|
@ -69,6 +73,7 @@ impl<'a> DisplayListBuilder<'a> {
|
||||||
context,
|
context,
|
||||||
wr: wr::DisplayListBuilder::new(pipeline_id, fragment_tree.scrollable_overflow()),
|
wr: wr::DisplayListBuilder::new(pipeline_id, fragment_tree.scrollable_overflow()),
|
||||||
compositor_info: CompositorDisplayListInfo::default(),
|
compositor_info: CompositorDisplayListInfo::default(),
|
||||||
|
iframe_sizes: FnvHashMap::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +147,34 @@ impl Fragment {
|
||||||
Visibility::Hidden => (),
|
Visibility::Hidden => (),
|
||||||
Visibility::Collapse => (),
|
Visibility::Collapse => (),
|
||||||
},
|
},
|
||||||
|
Fragment::IFrame(iframe) => match iframe.style.get_inherited_box().visibility {
|
||||||
|
Visibility::Visible => {
|
||||||
|
builder.is_contentful = true;
|
||||||
|
let rect = iframe
|
||||||
|
.rect
|
||||||
|
.to_physical(iframe.style.writing_mode, containing_block)
|
||||||
|
.translate(containing_block.origin.to_vector());
|
||||||
|
|
||||||
|
builder.iframe_sizes.insert(
|
||||||
|
iframe.browsing_context_id,
|
||||||
|
Size2D::new(rect.size.width.px(), rect.size.height.px()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let common = builder.common_properties(rect.to_webrender(), &iframe.style);
|
||||||
|
builder.wr.push_iframe(
|
||||||
|
rect.to_webrender(),
|
||||||
|
common.clip_rect,
|
||||||
|
&wr::SpaceAndClipInfo {
|
||||||
|
spatial_id: common.spatial_id,
|
||||||
|
clip_id: common.clip_id,
|
||||||
|
},
|
||||||
|
iframe.pipeline_id.to_webrender(),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
Visibility::Hidden => (),
|
||||||
|
Visibility::Collapse => (),
|
||||||
|
},
|
||||||
Fragment::Text(t) => match t.parent_style.get_inherited_box().visibility {
|
Fragment::Text(t) => match t.parent_style.get_inherited_box().visibility {
|
||||||
Visibility::Visible => {
|
Visibility::Visible => {
|
||||||
self.build_display_list_for_text_fragment(t, builder, containing_block)
|
self.build_display_list_for_text_fragment(t, builder, containing_block)
|
||||||
|
|
|
@ -482,7 +482,7 @@ impl Fragment {
|
||||||
stacking_context,
|
stacking_context,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
Fragment::Text(_) | Fragment::Image(_) => {
|
Fragment::Text(_) | Fragment::Image(_) | Fragment::IFrame(_) => {
|
||||||
stacking_context.fragments.push(StackingContextFragment {
|
stacking_context.fragments.push(StackingContextFragment {
|
||||||
section: StackingContextSection::Content,
|
section: StackingContextSection::Content,
|
||||||
space_and_clip: builder.current_space_and_clip,
|
space_and_clip: builder.current_space_and_clip,
|
||||||
|
|
|
@ -11,6 +11,7 @@ use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside, DisplayOuts
|
||||||
use crate::wrapper::GetStyleAndLayoutData;
|
use crate::wrapper::GetStyleAndLayoutData;
|
||||||
use atomic_refcell::AtomicRefMut;
|
use atomic_refcell::AtomicRefMut;
|
||||||
use html5ever::LocalName;
|
use html5ever::LocalName;
|
||||||
|
use msg::constellation_msg::{BrowsingContextId, PipelineId};
|
||||||
use net_traits::image::base::Image as NetImage;
|
use net_traits::image::base::Image as NetImage;
|
||||||
use script_layout_interface::wrapper_traits::{
|
use script_layout_interface::wrapper_traits::{
|
||||||
LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
|
LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
|
||||||
|
@ -396,6 +397,7 @@ pub(crate) trait NodeExt<'dom>: 'dom + Copy + LayoutNode<'dom> + Send + Sync {
|
||||||
/// adjusted for `image_density`.
|
/// adjusted for `image_density`.
|
||||||
fn as_image(self) -> Option<(Option<Arc<NetImage>>, PhysicalSize<f64>)>;
|
fn as_image(self) -> Option<(Option<Arc<NetImage>>, PhysicalSize<f64>)>;
|
||||||
fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize<f64>)>;
|
fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize<f64>)>;
|
||||||
|
fn as_iframe(self) -> Option<(PipelineId, BrowsingContextId)>;
|
||||||
fn first_child(self) -> Option<Self>;
|
fn first_child(self) -> Option<Self>;
|
||||||
fn next_sibling(self) -> Option<Self>;
|
fn next_sibling(self) -> Option<Self>;
|
||||||
fn parent_node(self) -> Option<Self>;
|
fn parent_node(self) -> Option<Self>;
|
||||||
|
@ -462,6 +464,16 @@ where
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_iframe(self) -> Option<(PipelineId, BrowsingContextId)> {
|
||||||
|
let node = self.to_threadsafe();
|
||||||
|
match (node.iframe_pipeline_id(), node.iframe_browsing_context_id()) {
|
||||||
|
(Some(pipeline_id), Some(browsing_context_id)) => {
|
||||||
|
Some((pipeline_id, browsing_context_id))
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn first_child(self) -> Option<Self> {
|
fn first_child(self) -> Option<Self> {
|
||||||
TNode::first_child(&self)
|
TNode::first_child(&self)
|
||||||
}
|
}
|
||||||
|
|
|
@ -475,6 +475,7 @@ impl FragmentTree {
|
||||||
.to_physical(fragment.parent_style.writing_mode, &containing_block),
|
.to_physical(fragment.parent_style.writing_mode, &containing_block),
|
||||||
Fragment::AbsoluteOrFixedPositioned(_) |
|
Fragment::AbsoluteOrFixedPositioned(_) |
|
||||||
Fragment::Image(_) |
|
Fragment::Image(_) |
|
||||||
|
Fragment::IFrame(_) |
|
||||||
Fragment::Anonymous(_) => return None,
|
Fragment::Anonymous(_) => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -506,6 +507,7 @@ impl FragmentTree {
|
||||||
Fragment::Box(_) |
|
Fragment::Box(_) |
|
||||||
Fragment::Text(_) |
|
Fragment::Text(_) |
|
||||||
Fragment::Image(_) |
|
Fragment::Image(_) |
|
||||||
|
Fragment::IFrame(_) |
|
||||||
Fragment::Anonymous(_) => return None,
|
Fragment::Anonymous(_) => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ use gfx::font::FontMetrics as GfxFontMetrics;
|
||||||
use gfx::text::glyph::GlyphStore;
|
use gfx::text::glyph::GlyphStore;
|
||||||
use gfx_traits::print_tree::PrintTree;
|
use gfx_traits::print_tree::PrintTree;
|
||||||
use gfx_traits::{combine_id_with_fragment_type, FragmentType};
|
use gfx_traits::{combine_id_with_fragment_type, FragmentType};
|
||||||
|
use msg::constellation_msg::{BrowsingContextId, PipelineId};
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
use serde::ser::{Serialize, Serializer};
|
use serde::ser::{Serialize, Serializer};
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
|
@ -70,6 +71,7 @@ pub(crate) enum Fragment {
|
||||||
AbsoluteOrFixedPositioned(AbsoluteOrFixedPositionedFragment),
|
AbsoluteOrFixedPositioned(AbsoluteOrFixedPositionedFragment),
|
||||||
Text(TextFragment),
|
Text(TextFragment),
|
||||||
Image(ImageFragment),
|
Image(ImageFragment),
|
||||||
|
IFrame(IFrameFragment),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
@ -174,6 +176,16 @@ pub(crate) struct ImageFragment {
|
||||||
pub image_key: ImageKey,
|
pub image_key: ImageKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct IFrameFragment {
|
||||||
|
pub debug_id: DebugId,
|
||||||
|
pub pipeline_id: PipelineId,
|
||||||
|
pub browsing_context_id: BrowsingContextId,
|
||||||
|
pub rect: Rect<Length>,
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
pub style: ServoArc<ComputedValues>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Fragment {
|
impl Fragment {
|
||||||
pub fn offset_inline(&mut self, offset: &Length) {
|
pub fn offset_inline(&mut self, offset: &Length) {
|
||||||
let position = match self {
|
let position = match self {
|
||||||
|
@ -182,6 +194,7 @@ impl Fragment {
|
||||||
Fragment::Anonymous(f) => &mut f.rect.start_corner,
|
Fragment::Anonymous(f) => &mut f.rect.start_corner,
|
||||||
Fragment::Text(f) => &mut f.rect.start_corner,
|
Fragment::Text(f) => &mut f.rect.start_corner,
|
||||||
Fragment::Image(f) => &mut f.rect.start_corner,
|
Fragment::Image(f) => &mut f.rect.start_corner,
|
||||||
|
Fragment::IFrame(f) => &mut f.rect.start_corner,
|
||||||
};
|
};
|
||||||
|
|
||||||
position.inline += *offset;
|
position.inline += *offset;
|
||||||
|
@ -193,7 +206,8 @@ impl Fragment {
|
||||||
Fragment::Text(fragment) => Some(fragment.tag),
|
Fragment::Text(fragment) => Some(fragment.tag),
|
||||||
Fragment::AbsoluteOrFixedPositioned(_) |
|
Fragment::AbsoluteOrFixedPositioned(_) |
|
||||||
Fragment::Anonymous(_) |
|
Fragment::Anonymous(_) |
|
||||||
Fragment::Image(_) => None,
|
Fragment::Image(_) |
|
||||||
|
Fragment::IFrame(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,6 +218,7 @@ impl Fragment {
|
||||||
Fragment::Anonymous(fragment) => fragment.print(tree),
|
Fragment::Anonymous(fragment) => fragment.print(tree),
|
||||||
Fragment::Text(fragment) => fragment.print(tree),
|
Fragment::Text(fragment) => fragment.print(tree),
|
||||||
Fragment::Image(fragment) => fragment.print(tree),
|
Fragment::Image(fragment) => fragment.print(tree),
|
||||||
|
Fragment::IFrame(fragment) => fragment.print(tree),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,6 +236,9 @@ impl Fragment {
|
||||||
Fragment::Image(fragment) => fragment
|
Fragment::Image(fragment) => fragment
|
||||||
.rect
|
.rect
|
||||||
.to_physical(fragment.style.writing_mode, &containing_block),
|
.to_physical(fragment.style.writing_mode, &containing_block),
|
||||||
|
Fragment::IFrame(fragment) => fragment
|
||||||
|
.rect
|
||||||
|
.to_physical(fragment.style.writing_mode, &containing_block),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,6 +480,16 @@ impl ImageFragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IFrameFragment {
|
||||||
|
pub fn print(&self, tree: &mut PrintTree) {
|
||||||
|
tree.add_item(format!(
|
||||||
|
"IFrame\
|
||||||
|
\npipeline={:?} rect={:?}",
|
||||||
|
self.pipeline_id, self.rect
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CollapsedBlockMargins {
|
impl CollapsedBlockMargins {
|
||||||
pub fn from_margin(margin: &Sides<Length>) -> Self {
|
pub fn from_margin(margin: &Sides<Length>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -10,7 +10,6 @@ use app_units::Au;
|
||||||
use euclid::default::{Point2D, Rect};
|
use euclid::default::{Point2D, Rect};
|
||||||
use euclid::Size2D;
|
use euclid::Size2D;
|
||||||
use euclid::Vector2D;
|
use euclid::Vector2D;
|
||||||
use ipc_channel::ipc::IpcSender;
|
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::PipelineId;
|
||||||
use script_layout_interface::rpc::TextIndexResponse;
|
use script_layout_interface::rpc::TextIndexResponse;
|
||||||
use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse, LayoutRPC};
|
use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse, LayoutRPC};
|
||||||
|
@ -19,7 +18,6 @@ use script_layout_interface::rpc::{OffsetParentResponse, ResolvedStyleResponse};
|
||||||
use script_layout_interface::wrapper_traits::{
|
use script_layout_interface::wrapper_traits::{
|
||||||
LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
|
LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
|
||||||
};
|
};
|
||||||
use script_traits::LayoutMsg as ConstellationMsg;
|
|
||||||
use script_traits::UntrustedNodeAddress;
|
use script_traits::UntrustedNodeAddress;
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -43,9 +41,6 @@ use webrender_api::ExternalScrollId;
|
||||||
///
|
///
|
||||||
/// This needs to be protected by a mutex so we can do fast RPCs.
|
/// This needs to be protected by a mutex so we can do fast RPCs.
|
||||||
pub struct LayoutThreadData {
|
pub struct LayoutThreadData {
|
||||||
/// The channel on which messages can be sent to the constellation.
|
|
||||||
pub constellation_chan: IpcSender<ConstellationMsg>,
|
|
||||||
|
|
||||||
/// The root stacking context.
|
/// The root stacking context.
|
||||||
pub display_list: Option<webrender_api::DisplayListBuilder>,
|
pub display_list: Option<webrender_api::DisplayListBuilder>,
|
||||||
|
|
||||||
|
@ -427,6 +422,7 @@ fn process_offset_parent_query_inner(
|
||||||
.to_physical(fragment.parent_style.writing_mode, &containing_block),
|
.to_physical(fragment.parent_style.writing_mode, &containing_block),
|
||||||
Fragment::AbsoluteOrFixedPositioned(_) |
|
Fragment::AbsoluteOrFixedPositioned(_) |
|
||||||
Fragment::Image(_) |
|
Fragment::Image(_) |
|
||||||
|
Fragment::IFrame(_) |
|
||||||
Fragment::Anonymous(_) => unreachable!(),
|
Fragment::Anonymous(_) => unreachable!(),
|
||||||
};
|
};
|
||||||
let border_box = fragment_relative_rect.translate(containing_block.origin.to_vector());
|
let border_box = fragment_relative_rect.translate(containing_block.origin.to_vector());
|
||||||
|
@ -503,6 +499,7 @@ fn process_offset_parent_query_inner(
|
||||||
Fragment::AbsoluteOrFixedPositioned(_) |
|
Fragment::AbsoluteOrFixedPositioned(_) |
|
||||||
Fragment::Text(_) |
|
Fragment::Text(_) |
|
||||||
Fragment::Image(_) |
|
Fragment::Image(_) |
|
||||||
|
Fragment::IFrame(_) |
|
||||||
Fragment::Anonymous(_) => None,
|
Fragment::Anonymous(_) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -552,6 +549,7 @@ fn process_offset_parent_query_inner(
|
||||||
Fragment::Box(_) |
|
Fragment::Box(_) |
|
||||||
Fragment::Text(_) |
|
Fragment::Text(_) |
|
||||||
Fragment::Image(_) |
|
Fragment::Image(_) |
|
||||||
|
Fragment::IFrame(_) |
|
||||||
Fragment::Anonymous(_) => None,
|
Fragment::Anonymous(_) => None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom_traversal::NodeExt;
|
use crate::dom_traversal::NodeExt;
|
||||||
use crate::fragments::{DebugId, Fragment, ImageFragment};
|
use crate::fragments::{DebugId, Fragment, IFrameFragment, ImageFragment};
|
||||||
use crate::geom::flow_relative::{Rect, Vec2};
|
use crate::geom::flow_relative::{Rect, Vec2};
|
||||||
use crate::geom::PhysicalSize;
|
use crate::geom::PhysicalSize;
|
||||||
use crate::sizing::ContentSizes;
|
use crate::sizing::ContentSizes;
|
||||||
|
@ -12,6 +12,7 @@ use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin};
|
||||||
use crate::ContainingBlock;
|
use crate::ContainingBlock;
|
||||||
use canvas_traits::canvas::{CanvasId, CanvasMsg, FromLayoutMsg};
|
use canvas_traits::canvas::{CanvasId, CanvasMsg, FromLayoutMsg};
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
|
use msg::constellation_msg::{BrowsingContextId, PipelineId};
|
||||||
use net_traits::image::base::Image;
|
use net_traits::image::base::Image;
|
||||||
use net_traits::image_cache::{ImageOrMetadataAvailable, UsePlaceholder};
|
use net_traits::image_cache::{ImageOrMetadataAvailable, UsePlaceholder};
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
|
@ -41,6 +42,9 @@ pub(crate) struct ReplacedContent {
|
||||||
///
|
///
|
||||||
/// * For SVG, see https://svgwg.org/svg2-draft/coords.html#SizingSVGInCSS
|
/// * For SVG, see https://svgwg.org/svg2-draft/coords.html#SizingSVGInCSS
|
||||||
/// and again https://github.com/w3c/csswg-drafts/issues/4572.
|
/// and again https://github.com/w3c/csswg-drafts/issues/4572.
|
||||||
|
///
|
||||||
|
/// * IFrames do not have intrinsic width and height or intrinsic ratio according
|
||||||
|
/// to https://drafts.csswg.org/css-images/#intrinsic-dimensions.
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub(crate) struct IntrinsicSizes {
|
pub(crate) struct IntrinsicSizes {
|
||||||
pub width: Option<Length>,
|
pub width: Option<Length>,
|
||||||
|
@ -75,9 +79,16 @@ pub(crate) struct CanvasInfo {
|
||||||
pub canvas_id: CanvasId,
|
pub canvas_id: CanvasId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub(crate) struct IFrameInfo {
|
||||||
|
pub pipeline_id: PipelineId,
|
||||||
|
pub browsing_context_id: BrowsingContextId,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub(crate) enum ReplacedContentKind {
|
pub(crate) enum ReplacedContentKind {
|
||||||
Image(Option<Arc<Image>>),
|
Image(Option<Arc<Image>>),
|
||||||
|
IFrame(IFrameInfo),
|
||||||
Canvas(CanvasInfo),
|
Canvas(CanvasInfo),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,35 +96,51 @@ impl ReplacedContent {
|
||||||
pub fn for_element<'dom>(element: impl NodeExt<'dom>) -> Option<Self> {
|
pub fn for_element<'dom>(element: impl NodeExt<'dom>) -> Option<Self> {
|
||||||
let (kind, intrinsic_size_in_dots) = {
|
let (kind, intrinsic_size_in_dots) = {
|
||||||
if let Some((image, intrinsic_size_in_dots)) = element.as_image() {
|
if let Some((image, intrinsic_size_in_dots)) = element.as_image() {
|
||||||
(ReplacedContentKind::Image(image), intrinsic_size_in_dots)
|
(
|
||||||
|
ReplacedContentKind::Image(image),
|
||||||
|
Some(intrinsic_size_in_dots),
|
||||||
|
)
|
||||||
} else if let Some((canvas_info, intrinsic_size_in_dots)) = element.as_canvas() {
|
} else if let Some((canvas_info, intrinsic_size_in_dots)) = element.as_canvas() {
|
||||||
(
|
(
|
||||||
ReplacedContentKind::Canvas(canvas_info),
|
ReplacedContentKind::Canvas(canvas_info),
|
||||||
intrinsic_size_in_dots,
|
Some(intrinsic_size_in_dots),
|
||||||
|
)
|
||||||
|
} else if let Some((pipeline_id, browsing_context_id)) = element.as_iframe() {
|
||||||
|
(
|
||||||
|
ReplacedContentKind::IFrame(IFrameInfo {
|
||||||
|
pipeline_id,
|
||||||
|
browsing_context_id,
|
||||||
|
}),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: should 'image-resolution' (when implemented) be used *instead* of
|
let intrinsic = intrinsic_size_in_dots.map_or_else(
|
||||||
// `script::dom::htmlimageelement::ImageRequest::current_pixel_density`?
|
|| IntrinsicSizes {
|
||||||
|
width: None,
|
||||||
// https://drafts.csswg.org/css-images-4/#the-image-resolution
|
height: None,
|
||||||
let dppx = 1.0;
|
ratio: None,
|
||||||
|
|
||||||
let width = (intrinsic_size_in_dots.width as CSSFloat) / dppx;
|
|
||||||
let height = (intrinsic_size_in_dots.height as CSSFloat) / dppx;
|
|
||||||
|
|
||||||
return Some(Self {
|
|
||||||
kind,
|
|
||||||
intrinsic: IntrinsicSizes {
|
|
||||||
width: Some(Length::new(width)),
|
|
||||||
height: Some(Length::new(height)),
|
|
||||||
// FIXME https://github.com/w3c/csswg-drafts/issues/4572
|
|
||||||
ratio: Some(width / height),
|
|
||||||
},
|
},
|
||||||
});
|
|intrinsic_size_in_dots| {
|
||||||
|
// FIXME: should 'image-resolution' (when implemented) be used *instead* of
|
||||||
|
// `script::dom::htmlimageelement::ImageRequest::current_pixel_density`?
|
||||||
|
// https://drafts.csswg.org/css-images-4/#the-image-resolution
|
||||||
|
let dppx = 1.0;
|
||||||
|
let width = (intrinsic_size_in_dots.width as CSSFloat) / dppx;
|
||||||
|
let height = (intrinsic_size_in_dots.height as CSSFloat) / dppx;
|
||||||
|
IntrinsicSizes {
|
||||||
|
width: Some(Length::new(width)),
|
||||||
|
height: Some(Length::new(height)),
|
||||||
|
// FIXME https://github.com/w3c/csswg-drafts/issues/4572
|
||||||
|
ratio: Some(width / height),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return Some(Self { kind, intrinsic });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_image_url<'dom>(
|
pub fn from_image_url<'dom>(
|
||||||
|
@ -203,6 +230,18 @@ impl ReplacedContent {
|
||||||
})
|
})
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
|
ReplacedContentKind::IFrame(iframe) => {
|
||||||
|
vec![Fragment::IFrame(IFrameFragment {
|
||||||
|
debug_id: DebugId::new(),
|
||||||
|
style: style.clone(),
|
||||||
|
pipeline_id: iframe.pipeline_id,
|
||||||
|
browsing_context_id: iframe.browsing_context_id,
|
||||||
|
rect: Rect {
|
||||||
|
start_corner: Vec2::zero(),
|
||||||
|
size,
|
||||||
|
},
|
||||||
|
})]
|
||||||
|
},
|
||||||
ReplacedContentKind::Canvas(canvas_info) => {
|
ReplacedContentKind::Canvas(canvas_info) => {
|
||||||
if self.intrinsic.width == Some(Length::zero()) ||
|
if self.intrinsic.width == Some(Length::zero()) ||
|
||||||
self.intrinsic.height == Some(Length::zero())
|
self.intrinsic.height == Some(Length::zero())
|
||||||
|
@ -264,6 +303,7 @@ impl ReplacedContent {
|
||||||
|
|
||||||
let default_object_size = || {
|
let default_object_size = || {
|
||||||
// FIXME:
|
// FIXME:
|
||||||
|
// https://drafts.csswg.org/css-images/#default-object-size
|
||||||
// “If 300px is too wide to fit the device, UAs should use the width of
|
// “If 300px is too wide to fit the device, UAs should use the width of
|
||||||
// the largest rectangle that has a 2:1 ratio and fits the device instead.”
|
// the largest rectangle that has a 2:1 ratio and fits the device instead.”
|
||||||
// “height of the largest rectangle that has a 2:1 ratio, has a height not greater
|
// “height of the largest rectangle that has a 2:1 ratio, has a height not greater
|
||||||
|
|
|
@ -216,7 +216,7 @@ pub struct LayoutThread {
|
||||||
layout_query_waiting_time: Histogram,
|
layout_query_waiting_time: Histogram,
|
||||||
|
|
||||||
/// The sizes of all iframes encountered during the last layout operation.
|
/// The sizes of all iframes encountered during the last layout operation.
|
||||||
last_iframe_sizes: RefCell<HashMap<BrowsingContextId, Size2D<f32, CSSPixel>>>,
|
last_iframe_sizes: RefCell<FnvHashMap<BrowsingContextId, Size2D<f32, CSSPixel>>>,
|
||||||
|
|
||||||
/// Flag that indicates if LayoutThread is busy handling a request.
|
/// Flag that indicates if LayoutThread is busy handling a request.
|
||||||
busy: Arc<AtomicBool>,
|
busy: Arc<AtomicBool>,
|
||||||
|
@ -1008,6 +1008,49 @@ impl LayoutThread {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the recorded iframe sizes of the contents of this layout thread and
|
||||||
|
/// when these sizes changes, send a message to the constellation informing it
|
||||||
|
/// of the new sizes.
|
||||||
|
fn update_iframe_sizes(
|
||||||
|
&self,
|
||||||
|
new_iframe_sizes: FnvHashMap<BrowsingContextId, Size2D<f32, CSSPixel>>,
|
||||||
|
) {
|
||||||
|
let old_iframe_sizes =
|
||||||
|
std::mem::replace(&mut *self.last_iframe_sizes.borrow_mut(), new_iframe_sizes);
|
||||||
|
|
||||||
|
if self.last_iframe_sizes.borrow().is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let size_messages: Vec<_> = self
|
||||||
|
.last_iframe_sizes
|
||||||
|
.borrow()
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(browsing_context_id, size)| {
|
||||||
|
match old_iframe_sizes.get(&browsing_context_id) {
|
||||||
|
Some(old_size) if old_size != size => Some(IFrameSizeMsg {
|
||||||
|
browsing_context_id: *browsing_context_id,
|
||||||
|
size: *size,
|
||||||
|
type_: WindowSizeType::Resize,
|
||||||
|
}),
|
||||||
|
None => Some(IFrameSizeMsg {
|
||||||
|
browsing_context_id: *browsing_context_id,
|
||||||
|
size: *size,
|
||||||
|
type_: WindowSizeType::Initial,
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if !size_messages.is_empty() {
|
||||||
|
let msg = ConstellationMsg::IFrameSizes(size_messages);
|
||||||
|
if let Err(e) = self.constellation_chan.send(msg) {
|
||||||
|
warn!("Layout resize to constellation failed ({}).", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Computes the stacking-relative positions of all flows and, if the painting is dirty and the
|
/// Computes the stacking-relative positions of all flows and, if the painting is dirty and the
|
||||||
/// reflow type need it, builds the display list.
|
/// reflow type need it, builds the display list.
|
||||||
fn compute_abs_pos_and_build_display_list(
|
fn compute_abs_pos_and_build_display_list(
|
||||||
|
@ -1068,48 +1111,10 @@ impl LayoutThread {
|
||||||
build_state.root_stacking_context.bounds = origin;
|
build_state.root_stacking_context.bounds = origin;
|
||||||
build_state.root_stacking_context.overflow = origin;
|
build_state.root_stacking_context.overflow = origin;
|
||||||
|
|
||||||
if !build_state.iframe_sizes.is_empty() {
|
// We will not use build_state.iframe_sizes again, so it's safe to move it.
|
||||||
// build_state.iframe_sizes is only used here, so its okay to replace
|
let iframe_sizes =
|
||||||
// it with an empty vector
|
std::mem::replace(&mut build_state.iframe_sizes, FnvHashMap::default());
|
||||||
let iframe_sizes =
|
self.update_iframe_sizes(iframe_sizes);
|
||||||
std::mem::replace(&mut build_state.iframe_sizes, vec![]);
|
|
||||||
// Collect the last frame's iframe sizes to compute any differences.
|
|
||||||
// Every frame starts with a fresh collection so that any removed
|
|
||||||
// iframes do not linger.
|
|
||||||
let last_iframe_sizes = std::mem::replace(
|
|
||||||
&mut *self.last_iframe_sizes.borrow_mut(),
|
|
||||||
HashMap::default(),
|
|
||||||
);
|
|
||||||
let mut size_messages = vec![];
|
|
||||||
for new_size in iframe_sizes {
|
|
||||||
// Only notify the constellation about existing iframes
|
|
||||||
// that have a new size, or iframes that did not previously
|
|
||||||
// exist.
|
|
||||||
if let Some(old_size) = last_iframe_sizes.get(&new_size.id) {
|
|
||||||
if *old_size != new_size.size {
|
|
||||||
size_messages.push(IFrameSizeMsg {
|
|
||||||
data: new_size,
|
|
||||||
type_: WindowSizeType::Resize,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
size_messages.push(IFrameSizeMsg {
|
|
||||||
data: new_size,
|
|
||||||
type_: WindowSizeType::Initial,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
self.last_iframe_sizes
|
|
||||||
.borrow_mut()
|
|
||||||
.insert(new_size.id, new_size.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !size_messages.is_empty() {
|
|
||||||
let msg = ConstellationMsg::IFrameSizes(size_messages);
|
|
||||||
if let Err(e) = self.constellation_chan.send(msg) {
|
|
||||||
warn!("Layout resize to constellation failed ({}).", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rw_data.indexable_text = std::mem::replace(
|
rw_data.indexable_text = std::mem::replace(
|
||||||
&mut build_state.indexable_text,
|
&mut build_state.indexable_text,
|
||||||
|
|
|
@ -51,10 +51,10 @@ use layout_traits::LayoutThreadFactory;
|
||||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||||
use metrics::{PaintTimeMetrics, ProfilerMetadataFactory, ProgressiveWebMetric};
|
use metrics::{PaintTimeMetrics, ProfilerMetadataFactory, ProgressiveWebMetric};
|
||||||
use msg::constellation_msg::{
|
use msg::constellation_msg::{
|
||||||
BackgroundHangMonitor, BackgroundHangMonitorRegister, HangAnnotation,
|
BackgroundHangMonitor, BackgroundHangMonitorRegister, BrowsingContextId, HangAnnotation,
|
||||||
|
LayoutHangAnnotation, MonitoredComponentId, MonitoredComponentType, PipelineId,
|
||||||
|
TopLevelBrowsingContextId,
|
||||||
};
|
};
|
||||||
use msg::constellation_msg::{LayoutHangAnnotation, MonitoredComponentType, PipelineId};
|
|
||||||
use msg::constellation_msg::{MonitoredComponentId, TopLevelBrowsingContextId};
|
|
||||||
use net_traits::image_cache::{ImageCache, UsePlaceholder};
|
use net_traits::image_cache::{ImageCache, UsePlaceholder};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use profile_traits::mem::{self as profile_mem, Report, ReportKind, ReportsChan};
|
use profile_traits::mem::{self as profile_mem, Report, ReportKind, ReportsChan};
|
||||||
|
@ -64,10 +64,11 @@ use script_layout_interface::message::{LayoutThreadInit, Msg, NodesFromPointQuer
|
||||||
use script_layout_interface::message::{QueryMsg, ReflowComplete, ReflowGoal, ScriptReflow};
|
use script_layout_interface::message::{QueryMsg, ReflowComplete, ReflowGoal, ScriptReflow};
|
||||||
use script_layout_interface::rpc::TextIndexResponse;
|
use script_layout_interface::rpc::TextIndexResponse;
|
||||||
use script_layout_interface::rpc::{LayoutRPC, OffsetParentResponse};
|
use script_layout_interface::rpc::{LayoutRPC, OffsetParentResponse};
|
||||||
use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg};
|
use script_traits::{
|
||||||
use script_traits::{DrawAPaintImageResult, PaintWorkletError};
|
ConstellationControlMsg, DrawAPaintImageResult, IFrameSizeMsg, LayoutControlMsg,
|
||||||
use script_traits::{Painter, WebrenderIpcSender};
|
LayoutMsg as ConstellationMsg, PaintWorkletError, Painter, ScrollState, UntrustedNodeAddress,
|
||||||
use script_traits::{ScrollState, UntrustedNodeAddress, WindowSizeData};
|
WebrenderIpcSender, WindowSizeData, WindowSizeType,
|
||||||
|
};
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
use servo_atoms::Atom;
|
use servo_atoms::Atom;
|
||||||
use servo_config::opts;
|
use servo_config::opts;
|
||||||
|
@ -135,6 +136,9 @@ pub struct LayoutThread {
|
||||||
/// A means of communication with the background hang monitor.
|
/// A means of communication with the background hang monitor.
|
||||||
background_hang_monitor: Box<dyn BackgroundHangMonitor>,
|
background_hang_monitor: Box<dyn BackgroundHangMonitor>,
|
||||||
|
|
||||||
|
/// The channel on which messages can be sent to the constellation.
|
||||||
|
constellation_chan: IpcSender<ConstellationMsg>,
|
||||||
|
|
||||||
/// The channel on which messages can be sent to the script thread.
|
/// The channel on which messages can be sent to the script thread.
|
||||||
script_chan: IpcSender<ConstellationControlMsg>,
|
script_chan: IpcSender<ConstellationControlMsg>,
|
||||||
|
|
||||||
|
@ -190,6 +194,9 @@ pub struct LayoutThread {
|
||||||
/// Paint time metrics.
|
/// Paint time metrics.
|
||||||
paint_time_metrics: PaintTimeMetrics,
|
paint_time_metrics: PaintTimeMetrics,
|
||||||
|
|
||||||
|
/// The sizes of all iframes encountered during the last layout operation.
|
||||||
|
last_iframe_sizes: RefCell<FnvHashMap<BrowsingContextId, Size2D<f32, CSSPixel>>>,
|
||||||
|
|
||||||
/// Flag that indicates if LayoutThread is busy handling a request.
|
/// Flag that indicates if LayoutThread is busy handling a request.
|
||||||
busy: Arc<AtomicBool>,
|
busy: Arc<AtomicBool>,
|
||||||
|
|
||||||
|
@ -493,6 +500,7 @@ impl LayoutThread {
|
||||||
is_iframe: is_iframe,
|
is_iframe: is_iframe,
|
||||||
port: port,
|
port: port,
|
||||||
pipeline_port: pipeline_receiver,
|
pipeline_port: pipeline_receiver,
|
||||||
|
constellation_chan,
|
||||||
script_chan: script_chan.clone(),
|
script_chan: script_chan.clone(),
|
||||||
background_hang_monitor,
|
background_hang_monitor,
|
||||||
time_profiler_chan: time_profiler_chan,
|
time_profiler_chan: time_profiler_chan,
|
||||||
|
@ -513,7 +521,6 @@ impl LayoutThread {
|
||||||
webrender_api: webrender_api_sender,
|
webrender_api: webrender_api_sender,
|
||||||
stylist: Stylist::new(device, QuirksMode::NoQuirks),
|
stylist: Stylist::new(device, QuirksMode::NoQuirks),
|
||||||
rw_data: Arc::new(Mutex::new(LayoutThreadData {
|
rw_data: Arc::new(Mutex::new(LayoutThreadData {
|
||||||
constellation_chan: constellation_chan,
|
|
||||||
display_list: None,
|
display_list: None,
|
||||||
content_box_response: None,
|
content_box_response: None,
|
||||||
content_boxes_response: Vec::new(),
|
content_boxes_response: Vec::new(),
|
||||||
|
@ -531,6 +538,7 @@ impl LayoutThread {
|
||||||
})),
|
})),
|
||||||
webrender_image_cache: Default::default(),
|
webrender_image_cache: Default::default(),
|
||||||
paint_time_metrics: paint_time_metrics,
|
paint_time_metrics: paint_time_metrics,
|
||||||
|
last_iframe_sizes: Default::default(),
|
||||||
busy,
|
busy,
|
||||||
load_webfonts_synchronously,
|
load_webfonts_synchronously,
|
||||||
relayout_event,
|
relayout_event,
|
||||||
|
@ -919,8 +927,12 @@ impl LayoutThread {
|
||||||
&QueryMsg::ElementInnerTextQuery(_) => {
|
&QueryMsg::ElementInnerTextQuery(_) => {
|
||||||
rw_data.element_inner_text_response = String::new();
|
rw_data.element_inner_text_response = String::new();
|
||||||
},
|
},
|
||||||
&QueryMsg::InnerWindowDimensionsQuery(_) => {
|
&QueryMsg::InnerWindowDimensionsQuery(browsing_context_id) => {
|
||||||
rw_data.inner_window_dimensions_response = None;
|
rw_data.inner_window_dimensions_response = self
|
||||||
|
.last_iframe_sizes
|
||||||
|
.borrow()
|
||||||
|
.get(&browsing_context_id)
|
||||||
|
.cloned();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ReflowGoal::Full | ReflowGoal::TickAnimations => {},
|
ReflowGoal::Full | ReflowGoal::TickAnimations => {},
|
||||||
|
@ -976,8 +988,7 @@ impl LayoutThread {
|
||||||
if viewport_size_changed {
|
if viewport_size_changed {
|
||||||
if let Some(constraints) = self.stylist.viewport_constraints() {
|
if let Some(constraints) = self.stylist.viewport_constraints() {
|
||||||
// let the constellation know about the viewport constraints
|
// let the constellation know about the viewport constraints
|
||||||
rw_data
|
self.constellation_chan
|
||||||
.constellation_chan
|
|
||||||
.send(ConstellationMsg::ViewportConstrained(
|
.send(ConstellationMsg::ViewportConstrained(
|
||||||
self.id,
|
self.id,
|
||||||
constraints.clone(),
|
constraints.clone(),
|
||||||
|
@ -1348,6 +1359,8 @@ impl LayoutThread {
|
||||||
display_list.wr.finalize(),
|
display_list.wr.finalize(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.update_iframe_sizes(display_list.iframe_sizes);
|
||||||
|
|
||||||
if self.trace_layout {
|
if self.trace_layout {
|
||||||
layout_debug::end_trace(self.generation.get());
|
layout_debug::end_trace(self.generation.get());
|
||||||
}
|
}
|
||||||
|
@ -1391,6 +1404,49 @@ impl LayoutThread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the recorded iframe sizes of the contents of this layout thread and
|
||||||
|
/// when these sizes changes, send a message to the constellation informing it
|
||||||
|
/// of the new sizes.
|
||||||
|
fn update_iframe_sizes(
|
||||||
|
&self,
|
||||||
|
new_iframe_sizes: FnvHashMap<BrowsingContextId, Size2D<f32, CSSPixel>>,
|
||||||
|
) {
|
||||||
|
let old_iframe_sizes =
|
||||||
|
std::mem::replace(&mut *self.last_iframe_sizes.borrow_mut(), new_iframe_sizes);
|
||||||
|
|
||||||
|
if self.last_iframe_sizes.borrow().is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let size_messages: Vec<_> = self
|
||||||
|
.last_iframe_sizes
|
||||||
|
.borrow()
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(browsing_context_id, size)| {
|
||||||
|
match old_iframe_sizes.get(&browsing_context_id) {
|
||||||
|
Some(old_size) if old_size != size => Some(IFrameSizeMsg {
|
||||||
|
browsing_context_id: *browsing_context_id,
|
||||||
|
size: *size,
|
||||||
|
type_: WindowSizeType::Resize,
|
||||||
|
}),
|
||||||
|
None => Some(IFrameSizeMsg {
|
||||||
|
browsing_context_id: *browsing_context_id,
|
||||||
|
size: *size,
|
||||||
|
type_: WindowSizeType::Initial,
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if !size_messages.is_empty() {
|
||||||
|
let msg = ConstellationMsg::IFrameSizes(size_messages);
|
||||||
|
if let Err(e) = self.constellation_chan.send(msg) {
|
||||||
|
warn!("Layout resize to constellation failed ({}).", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProfilerMetadataFactory for LayoutThread {
|
impl ProfilerMetadataFactory for LayoutThread {
|
||||||
|
|
|
@ -1541,17 +1541,13 @@ impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iframe_browsing_context_id(self) -> Option<BrowsingContextId> {
|
fn iframe_browsing_context_id(self) -> Option<BrowsingContextId> {
|
||||||
let iframe_element = self
|
self.downcast::<HTMLIFrameElement>()
|
||||||
.downcast::<HTMLIFrameElement>()
|
.map_or(None, |iframe_element| iframe_element.browsing_context_id())
|
||||||
.expect("not an iframe element!");
|
|
||||||
iframe_element.browsing_context_id()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iframe_pipeline_id(self) -> Option<PipelineId> {
|
fn iframe_pipeline_id(self) -> Option<PipelineId> {
|
||||||
let iframe_element = self
|
self.downcast::<HTMLIFrameElement>()
|
||||||
.downcast::<HTMLIFrameElement>()
|
.map_or(None, |iframe_element| iframe_element.pipeline_id())
|
||||||
.expect("not an iframe element!");
|
|
||||||
iframe_element.pipeline_id()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
|
|
@ -82,9 +82,7 @@ pub use crate::script_msg::{
|
||||||
DOMMessage, HistoryEntryReplacement, Job, JobError, JobResult, JobResultValue, JobType,
|
DOMMessage, HistoryEntryReplacement, Job, JobError, JobResult, JobResultValue, JobType,
|
||||||
SWManagerMsg, SWManagerSenders, ScopeThings, ServiceWorkerMsg,
|
SWManagerMsg, SWManagerSenders, ScopeThings, ServiceWorkerMsg,
|
||||||
};
|
};
|
||||||
pub use crate::script_msg::{
|
pub use crate::script_msg::{EventResult, IFrameSizeMsg, LayoutMsg, LogEntry, ScriptMsg};
|
||||||
EventResult, IFrameSize, IFrameSizeMsg, LayoutMsg, LogEntry, ScriptMsg,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The address of a node. Layout sends these back. They must be validated via
|
/// The address of a node. Layout sends these back. They must be validated via
|
||||||
/// `from_untrusted_node_address` before they can be used, because we do not trust layout.
|
/// `from_untrusted_node_address` before they can be used, because we do not trust layout.
|
||||||
|
|
|
@ -41,20 +41,13 @@ use style_traits::CSSPixel;
|
||||||
use webgpu::{wgpu, WebGPU, WebGPUResponseResult};
|
use webgpu::{wgpu, WebGPU, WebGPUResponseResult};
|
||||||
use webrender_api::units::{DeviceIntPoint, DeviceIntSize};
|
use webrender_api::units::{DeviceIntPoint, DeviceIntSize};
|
||||||
|
|
||||||
/// A particular iframe's size, associated with a browsing context.
|
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
|
||||||
pub struct IFrameSize {
|
|
||||||
/// The child browsing context for this iframe.
|
|
||||||
pub id: BrowsingContextId,
|
|
||||||
/// The size of the iframe.
|
|
||||||
pub size: Size2D<f32, CSSPixel>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An iframe sizing operation.
|
/// An iframe sizing operation.
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||||
pub struct IFrameSizeMsg {
|
pub struct IFrameSizeMsg {
|
||||||
/// The iframe sizing data.
|
/// The child browsing context for this iframe.
|
||||||
pub data: IFrameSize,
|
pub browsing_context_id: BrowsingContextId,
|
||||||
|
/// The size of the iframe.
|
||||||
|
pub size: Size2D<f32, CSSPixel>,
|
||||||
/// The kind of sizing operation.
|
/// The kind of sizing operation.
|
||||||
pub type_: WindowSizeType,
|
pub type_: WindowSizeType,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
[float-replaced-height-004.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[float-replaced-height-005.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[float-replaced-height-007.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[block-replaced-height-004.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[block-replaced-height-005.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[block-replaced-height-007.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[cross-domain-iframe-paint-order.sub.html]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[inline-block-replaced-height-004.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[inline-block-replaced-height-005.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[inline-block-replaced-height-007.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[inline-replaced-height-004.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[inline-replaced-height-005.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[inline-replaced-height-007.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[resizable-iframe-paint-order.html]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[absolute-replaced-height-004.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[absolute-replaced-height-005.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[absolute-replaced-height-011.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[absolute-replaced-height-012.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[absolute-replaced-height-018.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[absolute-replaced-height-019.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[absolute-replaced-height-025.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[absolute-replaced-height-026.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[absolute-replaced-height-032.xht]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[absolute-replaced-height-033.xht]
|
|
||||||
expected: FAIL
|
|
Loading…
Add table
Add a link
Reference in a new issue