diff --git a/Cargo.lock b/Cargo.lock index a099a839bd6..634151d2bc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6433,6 +6433,7 @@ dependencies = [ "base", "canvas_traits", "constellation_traits", + "embedder_traits", "euclid", "fnv", "fonts", diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 90a7bb24cd1..62c9225876a 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -21,13 +21,13 @@ use compositing_traits::{ }; use constellation_traits::{ AnimationTickType, CompositorHitTestResult, ConstellationMsg, PaintMetricEvent, - UntrustedNodeAddress, WindowSizeData, WindowSizeType, + UntrustedNodeAddress, WindowSizeType, }; use crossbeam_channel::Sender; use dpi::PhysicalSize; use embedder_traits::{ Cursor, InputEvent, MouseButtonEvent, MouseMoveEvent, ScreenGeometry, ShutdownState, - TouchEventType, + TouchEventType, ViewportDetails, }; use euclid::{Box2D, Point2D, Rect, Scale, Size2D, Transform3D}; use fnv::FnvHashMap; @@ -479,6 +479,17 @@ impl IOCompositor { } } + pub fn default_webview_viewport_details(&self) -> ViewportDetails { + // The division by 1 represents the page's default zoom of 100%, + // and gives us the appropriate CSSPixel type for the viewport. + let hidpi_scale_factor = self.window.hidpi_factor(); + let scaled_viewport_size = self.rendering_context.size2d().to_f32() / hidpi_scale_factor; + ViewportDetails { + size: scaled_viewport_size / Scale::new(1.0), + hidpi_scale_factor: Scale::new(hidpi_scale_factor.0), + } + } + fn set_needs_repaint(&self, reason: RepaintReason) { let mut needs_repaint = self.needs_repaint.get(); needs_repaint.insert(reason); @@ -1248,13 +1259,13 @@ impl IOCompositor { ) { // The device pixel ratio used by the style system should include the scale from page pixels // to device pixels, but not including any pinch zoom. - let device_pixel_ratio = self.device_pixels_per_page_pixel_not_including_page_zoom(); - let initial_viewport = rect.size().to_f32() / device_pixel_ratio; - let msg = ConstellationMsg::WindowSize( + let hidpi_scale_factor = self.device_pixels_per_page_pixel_not_including_page_zoom(); + let size = rect.size().to_f32() / hidpi_scale_factor; + let msg = ConstellationMsg::ChangeViewportDetails( webview_id, - WindowSizeData { - device_pixel_ratio, - initial_viewport, + ViewportDetails { + size, + hidpi_scale_factor, }, WindowSizeType::Resize, ); diff --git a/components/constellation/browsingcontext.rs b/components/constellation/browsingcontext.rs index 6f8b24dabcb..0a6974a1f2a 100644 --- a/components/constellation/browsingcontext.rs +++ b/components/constellation/browsingcontext.rs @@ -5,9 +5,8 @@ use std::collections::{HashMap, HashSet}; use base::id::{BrowsingContextGroupId, BrowsingContextId, PipelineId, WebViewId}; -use euclid::Size2D; +use embedder_traits::ViewportDetails; use log::warn; -use style_traits::CSSPixel; use crate::pipeline::Pipeline; @@ -50,8 +49,8 @@ pub struct BrowsingContext { /// The top-level browsing context ancestor pub top_level_id: WebViewId, - /// The size of the frame. - pub size: Size2D, + /// The [`ViewportDetails`] of the frame that this [`BrowsingContext`] represents. + pub viewport_details: ViewportDetails, /// Whether this browsing context is in private browsing mode. pub is_private: bool, @@ -85,7 +84,7 @@ impl BrowsingContext { top_level_id: WebViewId, pipeline_id: PipelineId, parent_pipeline_id: Option, - size: Size2D, + viewport_details: ViewportDetails, is_private: bool, inherited_secure_context: Option, throttled: bool, @@ -96,7 +95,7 @@ impl BrowsingContext { bc_group_id, id, top_level_id, - size, + viewport_details, is_private, inherited_secure_context, throttled, diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 8ef33132966..facfdff3885 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -111,7 +111,7 @@ use canvas_traits::webgl::WebGLThreads; use compositing_traits::{CompositorMsg, CompositorProxy, SendableFrameTree}; use constellation_traits::{ AnimationTickType, CompositorHitTestResult, ConstellationMsg as FromCompositorMsg, LogEntry, - PaintMetricEvent, ScrollState, TraversalDirection, WindowSizeData, WindowSizeType, + PaintMetricEvent, ScrollState, TraversalDirection, WindowSizeType, }; use crossbeam_channel::{Receiver, Sender, select, unbounded}; use devtools_traits::{ @@ -123,7 +123,7 @@ use embedder_traits::user_content_manager::UserContentManager; use embedder_traits::{ Cursor, EmbedderMsg, EmbedderProxy, ImeEvent, InputEvent, MediaSessionActionType, MediaSessionEvent, MediaSessionPlaybackState, MouseButton, MouseButtonAction, MouseButtonEvent, - Theme, WebDriverCommandMsg, WebDriverLoadStatus, + Theme, ViewportDetails, WebDriverCommandMsg, WebDriverLoadStatus, }; use euclid::Size2D; use euclid::default::Size2D as UntypedSize2D; @@ -415,9 +415,6 @@ pub struct Constellation { /// and the namespaces are allocated by the constellation. next_pipeline_namespace_id: PipelineNamespaceId, - /// The size of the top-level window. - window_size: WindowSizeData, - /// Bits of state used to interact with the webdriver implementation webdriver: WebDriverData, @@ -601,7 +598,6 @@ where pub fn start( state: InitialConstellationState, layout_factory: Arc, - initial_window_size: WindowSizeData, random_pipeline_closure_probability: Option, random_pipeline_closure_seed: Option, hard_fail: bool, @@ -713,7 +709,6 @@ where next_pipeline_namespace_id: PipelineNamespaceId(2), time_profiler_chan: state.time_profiler_chan, mem_profiler_chan: state.mem_profiler_chan, - window_size: initial_window_size, phantom: PhantomData, webdriver: WebDriverData::new(), document_states: HashMap::new(), @@ -877,7 +872,7 @@ where webview_id: WebViewId, parent_pipeline_id: Option, opener: Option, - initial_window_size: Size2D, + initial_viewport_details: ViewportDetails, // TODO: we have to provide ownership of the LoadData // here, because it will be send on an ipc channel, // and ipc channels take onership of their data. @@ -967,10 +962,7 @@ where resource_threads, time_profiler_chan: self.time_profiler_chan.clone(), mem_profiler_chan: self.mem_profiler_chan.clone(), - window_size: WindowSizeData { - initial_viewport: initial_window_size, - device_pixel_ratio: self.window_size.device_pixel_ratio, - }, + viewport_details: initial_viewport_details, event_loop, load_data, prev_throttled: throttled, @@ -1048,7 +1040,7 @@ where top_level_id: WebViewId, pipeline_id: PipelineId, parent_pipeline_id: Option, - size: Size2D, + viewport_details: ViewportDetails, is_private: bool, inherited_secure_context: Option, throttled: bool, @@ -1081,7 +1073,7 @@ where top_level_id, pipeline_id, parent_pipeline_id, - size, + viewport_details, is_private, inherited_secure_context, throttled, @@ -1320,8 +1312,8 @@ where }, // Create a new top level browsing context. Will use response_chan to return // the browsing context id. - FromCompositorMsg::NewWebView(url, webview_id) => { - self.handle_new_top_level_browsing_context(url, webview_id, None); + FromCompositorMsg::NewWebView(url, webview_id, viewport_details) => { + self.handle_new_top_level_browsing_context(url, webview_id, viewport_details, None); }, // Close a top level browsing context. FromCompositorMsg::CloseWebView(webview_id) => { @@ -1346,8 +1338,16 @@ where FromCompositorMsg::TraverseHistory(webview_id, direction) => { self.handle_traverse_history_msg(webview_id, direction); }, - FromCompositorMsg::WindowSize(webview_id, new_size, size_type) => { - self.handle_window_size_msg(webview_id, new_size, size_type); + FromCompositorMsg::ChangeViewportDetails( + webview_id, + new_viewport_details, + size_type, + ) => { + self.handle_change_viewport_details_msg( + webview_id, + new_viewport_details, + size_type, + ); }, FromCompositorMsg::ThemeChange(theme) => { self.handle_theme_change(theme); @@ -2714,7 +2714,7 @@ where Some(context) => context, None => return warn!("failed browsing context is missing"), }; - let window_size = browsing_context.size; + let viewport_details = browsing_context.viewport_details; let pipeline_id = browsing_context.pipeline_id; let throttled = browsing_context.throttled; @@ -2759,7 +2759,7 @@ where webview_id, None, opener, - window_size, + viewport_details, new_load_data, sandbox, is_private, @@ -2773,7 +2773,7 @@ where // to avoid closing again in handle_activate_document_msg (though it would be harmless) replace: Some(NeedsToReload::Yes(old_pipeline_id, old_load_data)), new_browsing_context_info: None, - window_size, + viewport_details, }); } @@ -2950,9 +2950,9 @@ where &mut self, url: ServoUrl, webview_id: WebViewId, + viewport_details: ViewportDetails, response_sender: Option>, ) { - let window_size = self.window_size.initial_viewport; let pipeline_id = PipelineId::new(); let browsing_context_id = BrowsingContextId::from(webview_id); let load_data = LoadData::new( @@ -2993,7 +2993,7 @@ where webview_id, None, None, - window_size, + viewport_details, load_data, sandbox, is_private, @@ -3010,7 +3010,7 @@ where inherited_secure_context: None, throttled, }), - window_size, + viewport_details, }); if let Some(response_sender) = response_sender { @@ -3067,12 +3067,7 @@ where type_, } in iframe_sizes { - let window_size = WindowSizeData { - initial_viewport: size, - device_pixel_ratio: self.window_size.device_pixel_ratio, - }; - - self.resize_browsing_context(window_size, type_, browsing_context_id); + self.resize_browsing_context(size, type_, browsing_context_id); } } @@ -3200,14 +3195,13 @@ where None }; - // https://github.com/rust-lang/rust/issues/59159 - let browsing_context_size = browsing_context.size; + let browsing_context_size = browsing_context.viewport_details; let browsing_context_throttled = browsing_context.throttled; // TODO(servo#30571) revert to debug_assert_eq!() once underlying bug is fixed #[cfg(debug_assertions)] - if !(browsing_context_size == load_info.window_size.initial_viewport) { + if !(browsing_context_size == load_info.viewport_details) { log::warn!( - "debug assertion failed! browsing_context_size == load_info.window_size.initial_viewport" + "debug assertion failed! browsing_context_size == load_info.viewport_details.initial_viewport" ); } @@ -3231,7 +3225,7 @@ where replace, // Browsing context for iframe already exists. new_browsing_context_info: None, - window_size: load_info.window_size.initial_viewport, + viewport_details: load_info.viewport_details, }); } @@ -3295,7 +3289,7 @@ where inherited_secure_context: is_parent_secure, throttled: is_parent_throttled, }), - window_size: load_info.window_size.initial_viewport, + viewport_details: load_info.viewport_details, }); } @@ -3323,8 +3317,8 @@ where opener_webview_id, webview_id_sender, )); - let new_webview_id = match webview_id_receiver.recv() { - Ok(Some(webview_id)) => webview_id, + let (new_webview_id, viewport_details) = match webview_id_receiver.recv() { + Ok(Some((webview_id, viewport_details))) => (webview_id, viewport_details), Ok(None) | Err(_) => { let _ = response_sender.send(None); return; @@ -3409,7 +3403,7 @@ where inherited_secure_context: is_opener_secure, throttled: is_opener_throttled, }), - window_size: self.window_size.initial_viewport, + viewport_details, }); } @@ -3528,10 +3522,10 @@ where return None; }, }; - let (window_size, pipeline_id, parent_pipeline_id, is_private, is_throttled) = + let (viewport_details, pipeline_id, parent_pipeline_id, is_private, is_throttled) = match self.browsing_contexts.get(&browsing_context_id) { Some(ctx) => ( - ctx.size, + ctx.viewport_details, ctx.pipeline_id, ctx.parent_pipeline_id, ctx.is_private, @@ -3608,7 +3602,7 @@ where webview_id, None, opener, - window_size, + viewport_details, load_data, sandbox, is_private, @@ -3621,7 +3615,7 @@ where replace, // `load_url` is always invoked on an existing browsing context. new_browsing_context_info: None, - window_size, + viewport_details, }); Some(new_pipeline_id) }, @@ -3901,7 +3895,7 @@ where top_level_id, old_pipeline_id, parent_pipeline_id, - window_size, + viewport_details, is_private, throttled, ) = match self.browsing_contexts.get(&browsing_context_id) { @@ -3909,7 +3903,7 @@ where ctx.top_level_id, ctx.pipeline_id, ctx.parent_pipeline_id, - ctx.size, + ctx.viewport_details, ctx.is_private, ctx.throttled, ), @@ -3926,7 +3920,7 @@ where top_level_id, parent_pipeline_id, opener, - window_size, + viewport_details, load_data.clone(), sandbox, is_private, @@ -3939,7 +3933,7 @@ where replace: Some(NeedsToReload::Yes(pipeline_id, load_data)), // Browsing context must exist at this point. new_browsing_context_info: None, - window_size, + viewport_details, }); return; }, @@ -4348,14 +4342,15 @@ where }; self.embedder_proxy .send(EmbedderMsg::AllowOpeningWebView(webview_id, chan)); - let webview_id = match port.recv() { - Ok(Some(webview_id)) => webview_id, + let (webview_id, viewport_details) = match port.recv() { + Ok(Some((webview_id, viewport_details))) => (webview_id, viewport_details), Ok(None) => return warn!("Embedder refused to allow opening webview"), Err(error) => return warn!("Failed to receive webview id: {error:?}"), }; self.handle_new_top_level_browsing_context( ServoUrl::parse_with_base(None, "about:blank").expect("Infallible parse"), webview_id, + viewport_details, Some(load_sender), ); let _ = sender.send(webview_id); @@ -4363,8 +4358,14 @@ where WebDriverCommandMsg::FocusWebView(webview_id) => { self.handle_focus_web_view(webview_id); }, - WebDriverCommandMsg::GetWindowSize(_, response_sender) => { - let _ = response_sender.send(self.window_size.initial_viewport); + WebDriverCommandMsg::GetWindowSize(webview_id, response_sender) => { + let browsing_context_id = BrowsingContextId::from(webview_id); + let size = self + .browsing_contexts + .get(&browsing_context_id) + .map(|browsing_context| browsing_context.viewport_details.size) + .unwrap_or_default(); + let _ = response_sender.send(size); }, WebDriverCommandMsg::SetWindowSize(webview_id, size, response_sender) => { self.webdriver.resize_channel = Some(response_sender); @@ -4726,7 +4727,7 @@ where change.webview_id, change.new_pipeline_id, new_context_info.parent_pipeline_id, - change.window_size, + change.viewport_details, new_context_info.is_private, new_context_info.inherited_secure_context, new_context_info.throttled, @@ -4969,25 +4970,23 @@ where feature = "tracing", tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace") )] - fn handle_window_size_msg( + fn handle_change_viewport_details_msg( &mut self, webview_id: WebViewId, - new_size: WindowSizeData, + new_viewport_details: ViewportDetails, size_type: WindowSizeType, ) { debug!( - "handle_window_size_msg: {:?}", - new_size.initial_viewport.to_untyped() + "handle_change_viewport_details_msg: {:?}", + new_viewport_details.size.to_untyped() ); let browsing_context_id = BrowsingContextId::from(webview_id); - self.resize_browsing_context(new_size, size_type, browsing_context_id); + self.resize_browsing_context(new_viewport_details, size_type, browsing_context_id); if let Some(response_sender) = self.webdriver.resize_channel.take() { - let _ = response_sender.send(new_size.initial_viewport); + let _ = response_sender.send(new_viewport_details.size); } - - self.window_size = new_size; } /// Called when the window exits from fullscreen mode @@ -5061,7 +5060,7 @@ where // If the rectangle for this pipeline is zero sized, it will // never be painted. In this case, don't query the layout // thread as it won't contribute to the final output image. - if browsing_context.size == Size2D::zero() { + if browsing_context.viewport_details.size == Size2D::zero() { continue; } @@ -5156,12 +5155,12 @@ where )] fn resize_browsing_context( &mut self, - new_size: WindowSizeData, + new_viewport_details: ViewportDetails, size_type: WindowSizeType, browsing_context_id: BrowsingContextId, ) { if let Some(browsing_context) = self.browsing_contexts.get_mut(&browsing_context_id) { - browsing_context.size = new_size.initial_viewport; + browsing_context.viewport_details = new_viewport_details; // Send Resize (or ResizeInactive) messages to each pipeline in the frame tree. let pipeline_id = browsing_context.pipeline_id; let pipeline = match self.pipelines.get(&pipeline_id) { @@ -5170,7 +5169,7 @@ where }; let _ = pipeline.event_loop.send(ScriptThreadMessage::Resize( pipeline.id, - new_size, + new_viewport_details, size_type, )); let pipeline_ids = browsing_context @@ -5181,7 +5180,10 @@ where if let Some(pipeline) = self.pipelines.get(id) { let _ = pipeline .event_loop - .send(ScriptThreadMessage::ResizeInactive(pipeline.id, new_size)); + .send(ScriptThreadMessage::ResizeInactive( + pipeline.id, + new_viewport_details, + )); } } } @@ -5199,7 +5201,7 @@ where if pipeline.browsing_context_id == browsing_context_id { let _ = pipeline.event_loop.send(ScriptThreadMessage::Resize( pipeline.id, - new_size, + new_viewport_details, size_type, )); } diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs index fb046d77c33..ffbc3a9b772 100644 --- a/components/constellation/pipeline.rs +++ b/components/constellation/pipeline.rs @@ -19,9 +19,9 @@ use base::id::{ use bluetooth_traits::BluetoothRequest; use canvas_traits::webgl::WebGLPipeline; use compositing_traits::{CompositionPipeline, CompositorMsg, CompositorProxy}; -use constellation_traits::WindowSizeData; use crossbeam_channel::{Sender, unbounded}; use devtools_traits::{DevtoolsControlMsg, ScriptToDevtoolsControlMsg}; +use embedder_traits::ViewportDetails; use embedder_traits::user_content_manager::UserContentManager; use fonts::{SystemFontServiceProxy, SystemFontServiceProxySender}; use ipc_channel::Error; @@ -161,8 +161,8 @@ pub struct InitialPipelineState { /// A channel to the memory profiler thread. pub mem_profiler_chan: profile_mem::ProfilerChan, - /// Information about the initial window size. - pub window_size: WindowSizeData, + /// The initial [`ViewportDetails`] to use when starting this new [`Pipeline`]. + pub viewport_details: ViewportDetails, /// The ID of the pipeline namespace for this script thread. pub pipeline_namespace_id: PipelineNamespaceId, @@ -219,7 +219,7 @@ impl Pipeline { webview_id: state.webview_id, opener: state.opener, load_data: state.load_data.clone(), - window_size: state.window_size, + viewport_details: state.viewport_details, }; if let Err(e) = script_chan.send(ScriptThreadMessage::AttachLayout(new_layout_info)) @@ -275,7 +275,7 @@ impl Pipeline { resource_threads: state.resource_threads, time_profiler_chan: state.time_profiler_chan, mem_profiler_chan: state.mem_profiler_chan, - window_size: state.window_size, + viewport_details: state.viewport_details, script_chan: script_chan.clone(), load_data: state.load_data.clone(), script_port, @@ -484,7 +484,7 @@ pub struct UnprivilegedPipelineContent { resource_threads: ResourceThreads, time_profiler_chan: time::ProfilerChan, mem_profiler_chan: profile_mem::ProfilerChan, - window_size: WindowSizeData, + viewport_details: ViewportDetails, script_chan: IpcSender, load_data: LoadData, script_port: IpcReceiver, @@ -534,7 +534,7 @@ impl UnprivilegedPipelineContent { time_profiler_sender: self.time_profiler_chan.clone(), memory_profiler_sender: self.mem_profiler_chan.clone(), devtools_server_sender: self.devtools_ipc_sender, - window_size: self.window_size, + viewport_details: self.viewport_details, pipeline_namespace_id: self.pipeline_namespace_id, content_process_shutdown_sender: content_process_shutdown_chan, webgl_chan: self.webgl_chan, diff --git a/components/constellation/session_history.rs b/components/constellation/session_history.rs index 9155ffcfca8..1da2ea4db65 100644 --- a/components/constellation/session_history.rs +++ b/components/constellation/session_history.rs @@ -6,11 +6,10 @@ use std::cmp::PartialEq; use std::fmt; use base::id::{BrowsingContextId, HistoryStateId, PipelineId, WebViewId}; -use euclid::Size2D; +use embedder_traits::ViewportDetails; use log::debug; use script_traits::LoadData; use servo_url::ServoUrl; -use style_traits::CSSPixel; use crate::browsingcontext::NewBrowsingContextInfo; @@ -127,8 +126,8 @@ pub struct SessionHistoryChange { /// easily available when they need to be constructed. pub new_browsing_context_info: Option, - /// The size of the viewport for the browsing context. - pub window_size: Size2D, + /// The size and hidpi scale factor of the viewport for the browsing context. + pub viewport_details: ViewportDetails, } /// Represents a pipeline or discarded pipeline in a history entry. diff --git a/components/constellation/tracing.rs b/components/constellation/tracing.rs index fd00d62067b..d7373ef4d93 100644 --- a/components/constellation/tracing.rs +++ b/components/constellation/tracing.rs @@ -58,7 +58,7 @@ mod from_compositor { Self::LoadUrl(..) => target!("LoadUrl"), Self::ClearCache => target!("ClearCache"), Self::TraverseHistory(..) => target!("TraverseHistory"), - Self::WindowSize(..) => target!("WindowSize"), + Self::ChangeViewportDetails(..) => target!("ChangeViewportDetails"), Self::ThemeChange(..) => target!("ThemeChange"), Self::TickAnimation(..) => target!("TickAnimation"), Self::WebDriverCommand(..) => target!("WebDriverCommand"), diff --git a/components/layout_2020/replaced.rs b/components/layout_2020/replaced.rs index 47bb932fa9e..58d09700e6e 100644 --- a/components/layout_2020/replaced.rs +++ b/components/layout_2020/replaced.rs @@ -9,7 +9,8 @@ use std::sync::Arc; use app_units::Au; use base::id::{BrowsingContextId, PipelineId}; use data_url::DataUrl; -use euclid::Size2D; +use embedder_traits::ViewportDetails; +use euclid::{Scale, Size2D}; use net_traits::image_cache::{ImageOrMetadataAvailable, UsePlaceholder}; use pixels::Image; use script_layout_interface::IFrameSize; @@ -358,12 +359,17 @@ impl ReplacedContents { }, ReplacedContentKind::IFrame(iframe) => { let size = Size2D::new(rect.size.width.to_f32_px(), rect.size.height.to_f32_px()); + let hidpi_scale_factor = layout_context.shared_context().device_pixel_ratio(); + layout_context.iframe_sizes.lock().insert( iframe.browsing_context_id, IFrameSize { browsing_context_id: iframe.browsing_context_id, pipeline_id: iframe.pipeline_id, - size, + viewport_details: ViewportDetails { + size, + hidpi_scale_factor: Scale::new(hidpi_scale_factor.0), + }, }, ); vec![Fragment::IFrame(ArcRefCell::new(IFrameFragment { diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs index 470ce1d7600..a34a7bf75a5 100644 --- a/components/layout_thread_2020/lib.rs +++ b/components/layout_thread_2020/lib.rs @@ -17,7 +17,8 @@ use std::sync::{Arc, LazyLock}; use app_units::Au; use base::Epoch; use base::id::{PipelineId, WebViewId}; -use constellation_traits::{ScrollState, UntrustedNodeAddress, WindowSizeData}; +use constellation_traits::{ScrollState, UntrustedNodeAddress}; +use embedder_traits::ViewportDetails; use embedder_traits::resources::{self, Resource}; use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect, Size2D as UntypedSize2D}; use euclid::{Point2D, Scale, Size2D, Vector2D}; @@ -473,8 +474,8 @@ impl LayoutThread { let device = Device::new( MediaType::screen(), QuirksMode::NoQuirks, - config.window_size.initial_viewport, - Scale::new(config.window_size.device_pixel_ratio.get()), + config.viewport_details.size, + Scale::new(config.viewport_details.hidpi_scale_factor.get()), Box::new(LayoutFontMetricsProvider(config.font_context.clone())), ComputedValues::initial_values_with_font_override(font), // TODO: obtain preferred color scheme from embedder @@ -497,8 +498,8 @@ impl LayoutThread { // Epoch starts at 1 because of the initial display list for epoch 0 that we send to WR epoch: Cell::new(Epoch(1)), viewport_size: Size2D::new( - Au::from_f32_px(config.window_size.initial_viewport.width), - Au::from_f32_px(config.window_size.initial_viewport.height), + Au::from_f32_px(config.viewport_details.size.width), + Au::from_f32_px(config.viewport_details.size.height), ), compositor_api: config.compositor_api, scroll_offsets: Default::default(), @@ -618,11 +619,15 @@ impl LayoutThread { }; let had_used_viewport_units = self.stylist.device().used_viewport_units(); - let viewport_size_changed = self.viewport_did_change(reflow_request.window_size); + let viewport_size_changed = self.viewport_did_change(reflow_request.viewport_details); let theme_changed = self.theme_did_change(reflow_request.theme); if viewport_size_changed || theme_changed { - self.update_device(reflow_request.window_size, reflow_request.theme, &guards); + self.update_device( + reflow_request.viewport_details, + reflow_request.theme, + &guards, + ); } if viewport_size_changed && had_used_viewport_units { @@ -951,11 +956,11 @@ impl LayoutThread { } } - fn viewport_did_change(&mut self, window_size_data: WindowSizeData) -> bool { - let new_pixel_ratio = window_size_data.device_pixel_ratio.get(); + fn viewport_did_change(&mut self, viewport_details: ViewportDetails) -> bool { + let new_pixel_ratio = viewport_details.hidpi_scale_factor.get(); let new_viewport_size = Size2D::new( - Au::from_f32_px(window_size_data.initial_viewport.width), - Au::from_f32_px(window_size_data.initial_viewport.height), + Au::from_f32_px(viewport_details.size.width), + Au::from_f32_px(viewport_details.size.height), ); // TODO: eliminate self.viewport_size in favour of using self.device.au_viewport_size() @@ -975,15 +980,15 @@ impl LayoutThread { /// Update layout given a new viewport. Returns true if the viewport changed or false if it didn't. fn update_device( &mut self, - window_size_data: WindowSizeData, + viewport_details: ViewportDetails, theme: PrefersColorScheme, guards: &StylesheetGuards, ) { let device = Device::new( MediaType::screen(), self.stylist.quirks_mode(), - window_size_data.initial_viewport, - Scale::new(window_size_data.device_pixel_ratio.get()), + viewport_details.size, + Scale::new(viewport_details.hidpi_scale_factor.get()), Box::new(LayoutFontMetricsProvider(self.font_context.clone())), self.stylist.device().default_computed_values().to_arc(), theme, diff --git a/components/script/dom/documentorshadowroot.rs b/components/script/dom/documentorshadowroot.rs index ac9140e65c4..6d59623c966 100644 --- a/components/script/dom/documentorshadowroot.rs +++ b/components/script/dom/documentorshadowroot.rs @@ -128,7 +128,7 @@ impl DocumentOrShadowRoot { let x = *x as f32; let y = *y as f32; let point = &Point2D::new(x, y); - let viewport = self.window.window_size().initial_viewport; + let viewport = self.window.viewport_details().size; if !has_browsing_context { return None; @@ -176,7 +176,7 @@ impl DocumentOrShadowRoot { let x = *x as f32; let y = *y as f32; let point = &Point2D::new(x, y); - let viewport = self.window.window_size().initial_viewport; + let viewport = self.window.viewport_details().size; if !has_browsing_context { return vec![]; diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index db0b4c63c5f..8193c99c896 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -4344,7 +4344,7 @@ impl Element { if (in_quirks_mode && doc.GetBody().as_deref() == self.downcast::()) || (!in_quirks_mode && *self.root_element() == *self) { - let viewport_dimensions = doc.window().window_size().initial_viewport.round().to_i32(); + let viewport_dimensions = doc.window().viewport_details().size.round().to_i32(); rect.size = Size2D::::new(viewport_dimensions.width, viewport_dimensions.height); } diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index dd4277d18cb..9a680353ad9 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -6,8 +6,8 @@ use std::cell::Cell; use base::id::{BrowsingContextId, PipelineId, WebViewId}; use bitflags::bitflags; -use constellation_traits::WindowSizeData; use dom_struct::dom_struct; +use embedder_traits::ViewportDetails; use html5ever::{LocalName, Prefix, local_name, namespace_url, ns}; use js::rust::HandleObject; use net_traits::ReferrerPolicy; @@ -196,12 +196,12 @@ impl HTMLIFrameElement { history_handling, }; - let window_size = WindowSizeData { - initial_viewport: window - .get_iframe_size_if_known(browsing_context_id, can_gc) - .unwrap_or_default(), - device_pixel_ratio: window.device_pixel_ratio(), - }; + let viewport_details = window + .get_iframe_viewport_details_if_known(browsing_context_id, can_gc) + .unwrap_or_else(|| ViewportDetails { + hidpi_scale_factor: window.device_pixel_ratio(), + ..Default::default() + }); match pipeline_type { PipelineType::InitialAboutBlank => { @@ -212,7 +212,7 @@ impl HTMLIFrameElement { load_data: load_data.clone(), old_pipeline_id, sandbox: sandboxed, - window_size, + viewport_details, }; window .as_global_scope() @@ -227,7 +227,7 @@ impl HTMLIFrameElement { webview_id, opener: None, load_data, - window_size, + viewport_details, }; self.pipeline_id.set(Some(new_pipeline_id)); @@ -239,7 +239,7 @@ impl HTMLIFrameElement { load_data, old_pipeline_id, sandbox: sandboxed, - window_size, + viewport_details, }; window .as_global_scope() diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index bec3b2018f7..ee23270a549 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -808,8 +808,8 @@ impl HTMLImageElement { let device_pixel_ratio = self .owner_document() .window() - .window_size() - .device_pixel_ratio + .viewport_details() + .hidpi_scale_factor .get() as f64; for (index, image_source) in img_sources.iter().enumerate() { let current_den = image_source.descriptor.density.unwrap(); diff --git a/components/script/dom/intersectionobserver.rs b/components/script/dom/intersectionobserver.rs index 81ac8a1337d..ec98116d3a4 100644 --- a/components/script/dom/intersectionobserver.rs +++ b/components/script/dom/intersectionobserver.rs @@ -444,7 +444,7 @@ impl IntersectionObserver { // > (note that this processing step can only be reached if the document is fully active). // TODO: viewport should consider native scrollbar if exist. Recheck Servo's scrollbar approach. document.map(|document| { - let viewport = document.window().window_size().initial_viewport; + let viewport = document.window().viewport_details().size; Rect::from_size(Size2D::new( Au::from_f32_px(viewport.width), Au::from_f32_px(viewport.height), diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 84f8deb16b1..57c90354dba 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -21,7 +21,7 @@ use base64::Engine; #[cfg(feature = "bluetooth")] use bluetooth_traits::BluetoothRequest; use canvas_traits::webgl::WebGLChan; -use constellation_traits::{ScrollState, WindowSizeData, WindowSizeType}; +use constellation_traits::{ScrollState, WindowSizeType}; use crossbeam_channel::{Sender, unbounded}; use cssparser::{Parser, ParserInput, SourceLocation}; use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType}; @@ -29,7 +29,7 @@ use dom_struct::dom_struct; use embedder_traits::user_content_manager::{UserContentManager, UserScript}; use embedder_traits::{ AlertResponse, ConfirmResponse, EmbedderMsg, PromptResponse, SimpleDialog, Theme, - WebDriverJSError, WebDriverJSResult, + ViewportDetails, WebDriverJSError, WebDriverJSResult, }; use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect}; use euclid::{Point2D, Rect, Scale, Size2D, Vector2D}; @@ -257,7 +257,7 @@ pub(crate) struct Window { /// Most recent unhandled resize event, if any. #[no_trace] - unhandled_resize_event: DomRefCell>, + unhandled_resize_event: DomRefCell>, /// Platform theme. #[no_trace] @@ -274,9 +274,9 @@ pub(crate) struct Window { #[ignore_malloc_size_of = "Rc is hard"] js_runtime: DomRefCell>>, - /// The current size of the window, in pixels. + /// The [`ViewportDetails`] of this [`Window`]'s frame. #[no_trace] - window_size: Cell, + viewport_details: Cell, /// A handle for communicating messages to the bluetooth thread. #[no_trace] @@ -1300,9 +1300,9 @@ impl WindowMethods for Window { // https://drafts.csswg.org/cssom-view/#dom-window-innerheight //TODO Include Scrollbar fn InnerHeight(&self) -> i32 { - self.window_size + self.viewport_details .get() - .initial_viewport + .size .height .to_i32() .unwrap_or(0) @@ -1311,12 +1311,7 @@ impl WindowMethods for Window { // https://drafts.csswg.org/cssom-view/#dom-window-innerwidth //TODO Include Scrollbar fn InnerWidth(&self) -> i32 { - self.window_size - .get() - .initial_viewport - .width - .to_i32() - .unwrap_or(0) + self.viewport_details.get().size.width.to_i32().unwrap_or(0) } // https://drafts.csswg.org/cssom-view/#dom-window-scrollx @@ -1822,7 +1817,7 @@ impl Window { // Step 5 & 6 // TODO: Remove scrollbar dimensions. - let viewport = self.window_size.get().initial_viewport; + let viewport = self.viewport_details.get().size; // Step 7 & 8 // TODO: Consider `block-end` and `inline-end` overflow direction. @@ -1885,7 +1880,7 @@ impl Window { } pub(crate) fn device_pixel_ratio(&self) -> Scale { - self.window_size.get().device_pixel_ratio + self.viewport_details.get().hidpi_scale_factor } fn client_window(&self) -> (Size2D, Point2D) { @@ -1994,7 +1989,7 @@ impl Window { document: document.upcast::().to_trusted_node_address(), dirty_root, stylesheets_changed, - window_size: self.window_size.get(), + viewport_details: self.viewport_details.get(), origin: self.origin().immutable().clone(), reflow_goal, dom_count: document.dom_count(), @@ -2050,7 +2045,7 @@ impl Window { let size_messages = self .Document() .iframes_mut() - .handle_new_iframe_sizes_after_layout(results.iframe_sizes, self.device_pixel_ratio()); + .handle_new_iframe_sizes_after_layout(results.iframe_sizes); if !size_messages.is_empty() { self.send_to_constellation(ScriptMsg::IFrameSizes(size_messages)); } @@ -2364,11 +2359,11 @@ impl Window { /// If the given |browsing_context_id| refers to an `