diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index fa8f6966bb4..0d4ae0afc05 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -912,18 +912,6 @@ impl IOCompositor { .collect(); let _ = result_sender.send((font_keys, font_instance_keys)); }, - CompositorMsg::GetClientWindowRect(webview_id, response_sender) => { - let client_window_rect = self - .webview_renderers - .get(webview_id) - .map(|webview_renderer| { - webview_renderer.client_window_rect(self.rendering_context.size2d()) - }) - .unwrap_or_default(); - if let Err(error) = response_sender.send(client_window_rect) { - warn!("Sending response to get client window failed ({error:?})."); - } - }, CompositorMsg::GetScreenSize(webview_id, response_sender) => { let screen_size = self .webview_renderers @@ -993,11 +981,6 @@ impl IOCompositor { .collect(); let _ = result_sender.send((font_keys, font_instance_keys)); }, - CompositorMsg::GetClientWindowRect(_, response_sender) => { - if let Err(error) = response_sender.send(Default::default()) { - warn!("Sending response to get client window failed ({error:?})."); - } - }, CompositorMsg::GetScreenSize(_, response_sender) => { if let Err(error) = response_sender.send(Default::default()) { warn!("Sending response to get client window failed ({error:?})."); diff --git a/components/compositing/tracing.rs b/components/compositing/tracing.rs index c4cf76c1e2b..904148e0b24 100644 --- a/components/compositing/tracing.rs +++ b/components/compositing/tracing.rs @@ -51,7 +51,6 @@ mod from_constellation { Self::AddSystemFont(..) => target!("AddSystemFont"), Self::AddFontInstance(..) => target!("AddFontInstance"), Self::RemoveFonts(..) => target!("RemoveFonts"), - Self::GetClientWindowRect(..) => target!("GetClientWindowRect"), Self::GetScreenSize(..) => target!("GetScreenSize"), Self::GetAvailableScreenSize(..) => target!("GetAvailableScreenSize"), Self::CollectMemoryReport(..) => target!("CollectMemoryReport"), diff --git a/components/compositing/webview_renderer.rs b/components/compositing/webview_renderer.rs index 8a55634cbd4..7648c727732 100644 --- a/components/compositing/webview_renderer.rs +++ b/components/compositing/webview_renderer.rs @@ -19,14 +19,12 @@ use embedder_traits::{ MouseButtonEvent, MouseMoveEvent, ScrollEvent as EmbedderScrollEvent, ShutdownState, TouchEvent, TouchEventResult, TouchEventType, TouchId, ViewportDetails, }; -use euclid::{Box2D, Point2D, Scale, Size2D, Vector2D}; +use euclid::{Point2D, Scale, Size2D, Vector2D}; use fnv::FnvHashSet; use log::{debug, warn}; use servo_geometry::DeviceIndependentPixel; use style_traits::{CSSPixel, PinchZoomFactor}; -use webrender_api::units::{ - DeviceIntPoint, DeviceIntRect, DevicePixel, DevicePoint, DeviceRect, LayoutVector2D, -}; +use webrender_api::units::{DeviceIntPoint, DevicePixel, DevicePoint, DeviceRect, LayoutVector2D}; use webrender_api::{ExternalScrollId, HitTestFlags, ScrollLocation}; use crate::compositor::{HitTestError, PipelineDetails, ServoRenderer}; @@ -1041,20 +1039,6 @@ impl WebViewRenderer { old_rect != self.rect } - pub(crate) fn client_window_rect( - &self, - rendering_context_size: Size2D, - ) -> Box2D { - let screen_geometry = self.webview.screen_geometry().unwrap_or_default(); - let rect = DeviceIntRect::from_origin_and_size( - screen_geometry.offset, - rendering_context_size.to_i32(), - ) - .to_f32() / - self.hidpi_scale_factor; - rect.to_i32() - } - pub(crate) fn screen_size(&self) -> Size2D { let screen_geometry = self.webview.screen_geometry().unwrap_or_default(); (screen_geometry.size.to_f32() / self.hidpi_scale_factor).to_i32() diff --git a/components/constellation/tracing.rs b/components/constellation/tracing.rs index e4b68a6a1c4..37186126e2a 100644 --- a/components/constellation/tracing.rs +++ b/components/constellation/tracing.rs @@ -214,6 +214,7 @@ mod from_script { Self::SetCursor(..) => target_variant!("SetCursor"), Self::NewFavicon(..) => target_variant!("NewFavicon"), Self::HistoryChanged(..) => target_variant!("HistoryChanged"), + Self::GetWindowRect(..) => target_variant!("GetWindowRect"), Self::NotifyFullscreenStateChanged(..) => { target_variant!("NotifyFullscreenStateChanged") }, diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 29bb91a0d80..a88e7be215d 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -1686,12 +1686,9 @@ impl WindowMethods for Window { // https://drafts.csswg.org/cssom-view/#dom-window-resizeby fn ResizeBy(&self, x: i32, y: i32) { - let (size, _) = self.client_window(); + let size = self.client_window().size(); // Step 1 - self.ResizeTo( - x + size.width.to_i32().unwrap_or(1), - y + size.height.to_i32().unwrap_or(1), - ) + self.ResizeTo(x + size.width, y + size.height) } // https://drafts.csswg.org/cssom-view/#dom-window-moveto @@ -1706,33 +1703,29 @@ impl WindowMethods for Window { // https://drafts.csswg.org/cssom-view/#dom-window-moveby fn MoveBy(&self, x: i32, y: i32) { - let (_, origin) = self.client_window(); + let origin = self.client_window().min; // Step 1 self.MoveTo(x + origin.x, y + origin.y) } // https://drafts.csswg.org/cssom-view/#dom-window-screenx fn ScreenX(&self) -> i32 { - let (_, origin) = self.client_window(); - origin.x + self.client_window().min.x } // https://drafts.csswg.org/cssom-view/#dom-window-screeny fn ScreenY(&self) -> i32 { - let (_, origin) = self.client_window(); - origin.y + self.client_window().min.y } // https://drafts.csswg.org/cssom-view/#dom-window-outerheight fn OuterHeight(&self) -> i32 { - let (size, _) = self.client_window(); - size.height.to_i32().unwrap_or(1) + self.client_window().height() } // https://drafts.csswg.org/cssom-view/#dom-window-outerwidth fn OuterWidth(&self) -> i32 { - let (size, _) = self.client_window(); - size.width.to_i32().unwrap_or(1) + self.client_window().width() } // https://drafts.csswg.org/cssom-view/#dom-window-devicepixelratio @@ -2151,18 +2144,12 @@ impl Window { self.viewport_details.get().hidpi_scale_factor } - fn client_window(&self) -> (Size2D, Point2D) { - let timer_profile_chan = self.global().time_profiler_chan().clone(); - let (sender, receiver) = - ProfiledIpc::channel::(timer_profile_chan).unwrap(); - let _ = self.compositor_api.sender().send( - compositing_traits::CompositorMsg::GetClientWindowRect(self.webview_id(), sender), - ); - let rect = receiver.recv().unwrap_or_default(); - ( - Size2D::new(rect.size().width as u32, rect.size().height as u32), - Point2D::new(rect.min.x, rect.min.y), - ) + fn client_window(&self) -> DeviceIndependentIntRect { + let (sender, receiver) = ipc::channel().expect("Failed to create IPC channel!"); + + self.send_to_embedder(EmbedderMsg::GetWindowRect(self.webview_id(), sender)); + + receiver.recv().unwrap_or_default() } /// Prepares to tick animations and then does a reflow which also advances the diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 584d5902540..128d7b1a024 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -100,6 +100,7 @@ use servo_config::opts::Opts; use servo_config::prefs::Preferences; use servo_config::{opts, pref, prefs}; use servo_delegate::DefaultServoDelegate; +use servo_geometry::DeviceIndependentIntRect; use servo_media::ServoMedia; use servo_media::player::context::GlContext; use servo_url::ServoUrl; @@ -998,6 +999,25 @@ impl Servo { webview.delegate().show_form_control(webview, form_control); } }, + EmbedderMsg::GetWindowRect(webview_id, response_sender) => { + let window_rect = || { + let Some(webview) = self.get_webview_handle(webview_id) else { + return DeviceIndependentIntRect::default(); + }; + let hidpi_scale_factor = webview.hidpi_scale_factor(); + let Some(screen_geometry) = webview.delegate().screen_geometry(webview) else { + return DeviceIndependentIntRect::default(); + }; + + (screen_geometry.window_rect.to_f32() / hidpi_scale_factor) + .round() + .to_i32() + }; + + if let Err(error) = response_sender.send(window_rect()) { + warn!("Failed to respond to GetWindowRect: {error}"); + } + }, } } diff --git a/components/shared/compositing/lib.rs b/components/shared/compositing/lib.rs index 12507c74ea0..d1863b1bf4c 100644 --- a/components/shared/compositing/lib.rs +++ b/components/shared/compositing/lib.rs @@ -33,7 +33,7 @@ use euclid::default::Size2D as UntypedSize2D; use ipc_channel::ipc::{self, IpcSharedMemory}; use profile_traits::mem::{OpaqueSender, ReportsChan}; use serde::{Deserialize, Serialize}; -use servo_geometry::{DeviceIndependentIntRect, DeviceIndependentIntSize}; +use servo_geometry::DeviceIndependentIntSize; use webrender_api::units::{DevicePoint, LayoutVector2D, TexelRect}; use webrender_api::{ BuiltDisplayList, BuiltDisplayListDescriptor, ExternalImage, ExternalImageData, @@ -152,9 +152,6 @@ pub enum CompositorMsg { AddFontInstance(FontInstanceKey, FontKey, f32, FontInstanceFlags), /// Remove the given font resources from our WebRender instance. RemoveFonts(Vec, Vec), - - /// Get the client window size and position. - GetClientWindowRect(WebViewId, IpcSender), /// Get the size of the screen that the client window inhabits. GetScreenSize(WebViewId, IpcSender), /// Get the available screen size, without system interface elements such as menus, docks, and diff --git a/components/shared/embedder/lib.rs b/components/shared/embedder/lib.rs index da9b2369c45..036aaa87b10 100644 --- a/components/shared/embedder/lib.rs +++ b/components/shared/embedder/lib.rs @@ -31,6 +31,7 @@ use malloc_size_of_derive::MallocSizeOf; use num_derive::FromPrimitive; use pixels::RasterImage; use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use servo_geometry::DeviceIndependentIntRect; use servo_url::ServoUrl; use strum_macros::IntoStaticStr; use style::queries::values::PrefersColorScheme; @@ -363,6 +364,8 @@ pub enum EmbedderMsg { NewFavicon(WebViewId, ServoUrl), /// The history state has changed. HistoryChanged(WebViewId, Vec, usize), + /// Get the device independent window rectangle. + GetWindowRect(WebViewId, IpcSender), /// Entered or exited fullscreen. NotifyFullscreenStateChanged(WebViewId, bool), /// The [`LoadStatus`] of the Given `WebView` has changed. @@ -754,22 +757,25 @@ pub struct NotificationAction { } /// Information about a `WebView`'s screen geometry and offset. This is used -/// for the [Screen](https://drafts.csswg.org/cssom-view/#the-screen-interface) -/// CSSOM APIs and `window.screenLeft` / `window.screenTop`. +/// for the [Screen](https://drafts.csswg.org/cssom-view/#the-screen-interface) CSSOM APIs +/// and `window.screenLeft` / `window.screenX` / `window.screenTop` / `window.screenY` / +/// `window.moveBy`/ `window.resizeBy` / `window.outerWidth` / `window.outerHeight` / +/// `window.screen.availHeight` / `window.screen.availWidth`. #[derive(Clone, Copy, Debug, Default)] pub struct ScreenGeometry { /// The size of the screen in device pixels. This will be converted to /// CSS pixels based on the pixel scaling of the `WebView`. pub size: DeviceIntSize, - /// The available size of the screen in device pixels. This size is the size + /// The available size of the screen in device pixels for the purposes of + /// the `window.screen.availHeight` / `window.screen.availWidth`. This is the size /// available for web content on the screen, and should be `size` minus any system /// toolbars, docks, and interface elements. This will be converted to /// CSS pixels based on the pixel scaling of the `WebView`. pub available_size: DeviceIntSize, - /// The offset of the `WebView` in device pixels for the purposes of the `window.screenLeft` - /// and `window.screenTop` APIs. This will be converted to CSS pixels based on the pixel scaling - /// of the `WebView`. - pub offset: DeviceIntPoint, + /// The rectangle the `WebView`'s containing window in device pixels for the purposes of the + /// `window.screenLeft` and similar APIs. This will be converted to CSS pixels based + /// on the pixel scaling of the `WebView`. + pub window_rect: DeviceIntRect, } impl From for SelectElementOptionOrOptgroup { diff --git a/ports/servoshell/desktop/headed_window.rs b/ports/servoshell/desktop/headed_window.rs index f245a93ec93..01835d40e1d 100644 --- a/ports/servoshell/desktop/headed_window.rs +++ b/ports/servoshell/desktop/headed_window.rs @@ -17,7 +17,7 @@ use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawWindowHandle}; use servo::servo_config::pref; use servo::servo_geometry::{DeviceIndependentIntRect, DeviceIndependentPixel}; use servo::webrender_api::ScrollLocation; -use servo::webrender_api::units::{DeviceIntPoint, DeviceIntSize, DevicePixel}; +use servo::webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixel}; use servo::{ Cursor, ImeEvent, InputEvent, Key, KeyState, KeyboardEvent, MouseButton as ServoMouseButton, MouseButtonAction, MouseButtonEvent, MouseLeaveEvent, MouseMoveEvent, @@ -429,22 +429,22 @@ impl WindowPortsMethods for Window { 0.0, (self.toolbar_height.get() * self.hidpi_scale_factor()).0, ); - let screen_size = self.screen_size.to_f32() * hidpi_factor; + // FIXME: In reality, this should subtract screen space used by the system interface // elements, but it is difficult to get this value with `winit` currently. See: // See https://github.com/rust-windowing/winit/issues/2494 let available_screen_size = screen_size - toolbar_size; - // Offset the WebView origin by the toolbar so that it reflects the actual viewport and - // not the window origin. - let window_origin = self.winit_window.outer_position().unwrap_or_default(); - let offset = winit_position_to_euclid_point(window_origin); + let window_rect = DeviceIntRect::from_origin_and_size( + winit_position_to_euclid_point(self.winit_window.outer_position().unwrap_or_default()), + winit_size_to_euclid_size(self.winit_window.outer_size()).to_i32(), + ); ScreenGeometry { size: screen_size.to_i32(), available_size: available_screen_size.to_i32(), - offset, + window_rect, } } diff --git a/ports/servoshell/desktop/headless_window.rs b/ports/servoshell/desktop/headless_window.rs index 604644383a1..45952e5a4ad 100644 --- a/ports/servoshell/desktop/headless_window.rs +++ b/ports/servoshell/desktop/headless_window.rs @@ -68,7 +68,7 @@ impl WindowPortsMethods for Window { ScreenGeometry { size: self.screen_size, available_size: self.screen_size, - offset: Default::default(), + window_rect: self.inner_size.get().into(), } } diff --git a/ports/servoshell/egl/app_state.rs b/ports/servoshell/egl/app_state.rs index 11ba656d7fc..9a33bb375cc 100644 --- a/ports/servoshell/egl/app_state.rs +++ b/ports/servoshell/egl/app_state.rs @@ -124,13 +124,12 @@ impl ServoDelegate for ServoShellServoDelegate { impl WebViewDelegate for RunningAppState { fn screen_geometry(&self, _webview: WebView) -> Option { let coord = self.callbacks.coordinates.borrow(); - let offset = coord.origin(); let available_size = coord.size(); let screen_size = coord.size(); Some(ScreenGeometry { size: screen_size, available_size, - offset, + window_rect: DeviceIntRect::from_origin_and_size(coord.origin(), coord.size()), }) } diff --git a/tests/wpt/meta/webdriver/tests/classic/close_window/close.py.ini b/tests/wpt/meta/webdriver/tests/classic/close_window/close.py.ini index 4f37a70a8c2..b8f9016cdf5 100644 --- a/tests/wpt/meta/webdriver/tests/classic/close_window/close.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/close_window/close.py.ini @@ -1,9 +1,3 @@ [close.py] - [test_close_browsing_context_with_accepted_beforeunload_prompt[tab\]] - expected: FAIL - - [test_close_browsing_context_with_accepted_beforeunload_prompt[window\]] - expected: FAIL - [test_element_usage_after_closing_browsing_context] expected: ERROR diff --git a/tests/wpt/meta/webdriver/tests/classic/element_clear/clear.py.ini b/tests/wpt/meta/webdriver/tests/classic/element_clear/clear.py.ini index a58528c6440..fd6422a8806 100644 --- a/tests/wpt/meta/webdriver/tests/classic/element_clear/clear.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/element_clear/clear.py.ini @@ -211,9 +211,3 @@ [test_resettable_element_does_not_satisfy_validation_constraints[range-foo\]] expected: FAIL - - [test_resettable_element_does_not_satisfy_validation_constraints[color-foo\]] - expected: FAIL - - [test_resettable_element_does_not_satisfy_validation_constraints[datetime-foo\]] - expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/get_window_rect/get.py.ini b/tests/wpt/meta/webdriver/tests/classic/get_window_rect/get.py.ini deleted file mode 100644 index da692701464..00000000000 --- a/tests/wpt/meta/webdriver/tests/classic/get_window_rect/get.py.ini +++ /dev/null @@ -1,3 +0,0 @@ -[get.py] - [test_payload] - expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/switch_to_window/alerts.py.ini b/tests/wpt/meta/webdriver/tests/classic/switch_to_window/alerts.py.ini deleted file mode 100644 index 3e6ad0c8af9..00000000000 --- a/tests/wpt/meta/webdriver/tests/classic/switch_to_window/alerts.py.ini +++ /dev/null @@ -1,3 +0,0 @@ -[alerts.py] - [test_retain_tab_modal_status] - expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/switch_to_window/switch.py.ini b/tests/wpt/meta/webdriver/tests/classic/switch_to_window/switch.py.ini index 008e3931e35..ba3819d135b 100644 --- a/tests/wpt/meta/webdriver/tests/classic/switch_to_window/switch.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/switch_to_window/switch.py.ini @@ -1,7 +1,4 @@ [switch.py] - [test_finds_exising_user_prompt_after_tab_switch[alert\]] - expected: FAIL - [test_finds_exising_user_prompt_after_tab_switch[confirm\]] expected: ERROR