E596 Implement setting position through webdriver for headed window (#38209) · servo/servo@4ff6b1d · GitHub
[go: up one dir, main page]

Skip to content

Commit 4ff6b1d

Browse files
authored
Implement setting position through webdriver for headed window (#38209)
Previously, we pretend we are able to set position in response. Now we can really do it. Testing: Able to set position accurately when tested locally. Fixes: Task 5 of #37804. --------- Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
1 parent cff48d4 commit 4ff6b1d

File tree

7 files changed

+64
-36
lines changed

7 files changed

+64
-36
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/constellation/constellation.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4461,7 +4461,7 @@ where
44614461
WebDriverCommandMsg::IsWebViewOpen(..) |
44624462
WebDriverCommandMsg::GetWindowRect(..) |
44634463
WebDriverCommandMsg::GetViewportSize(..) |
4464-
WebDriverCommandMsg::SetWindowSize(..) |
4464+
WebDriverCommandMsg::SetWindowRect(..) |
44654465
WebDriverCommandMsg::LoadUrl(..) |
44664466
WebDriverCommandMsg::Refresh(..) |
44674467
WebDriverCommandMsg::SendKeys(..) |

components/shared/embedder/webdriver.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use keyboard_types::KeyboardEvent;
1616
use keyboard_types::webdriver::Event as WebDriverInputEvent;
1717
use pixels::RasterImage;
1818
use serde::{Deserialize, Serialize};
19-
use servo_geometry::{DeviceIndependentIntRect, DeviceIndependentIntSize, DeviceIndependentPixel};
19+
use servo_geometry::DeviceIndependentIntRect;
2020
use servo_url::ServoUrl;
2121
use style_traits::CSSPixel;
2222
use webdriver::common::{WebElement, WebFrame, WebWindow};
@@ -132,11 +132,11 @@ pub enum WebDriverCommandMsg {
132132
// expect one response from constellation for each tick actions.
133133
Option<WebDriverMessageId>,
134134
),
135-
/// Set the window size.
136-
SetWindowSize(
135+
/// Set the outer window rectangle.
136+
SetWindowRect(
137137
WebViewId,
138-
DeviceIndependentIntSize,
139-
IpcSender<Size2D<i32, DeviceIndependentPixel>>,
138+
DeviceIndependentIntRect,
139+
IpcSender<DeviceIndependentIntRect>,
140140
),
141141
/// Take a screenshot of the viewport.
142142
TakeScreenshot(

components/webdriver_server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pixels = { path = "../pixels" }
2828
serde = { workspace = true }
2929
serde_json = { workspace = true }
3030
servo_config = { path = "../config" }
31+
servo_geometry = { path = "../geometry" }
3132
servo_url = { path = "../url" }
3233
stylo_traits = { workspace = true }
3334
uuid = { workspace = true }

components/webdriver_server/lib.rs

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use embedder_traits::{
2828
WebDriverJSError, WebDriverJSResult, WebDriverJSValue, WebDriverLoadStatus, WebDriverMessageId,
2929
WebDriverScriptCommand,
3030
};
31-
use euclid::{Rect, Size2D};
31+
use euclid::{Point2D, Rect, Size2D};
3232
use http::method::Method;
3333
use image::{DynamicImage, ImageFormat, RgbaImage};
3434
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
@@ -41,6 +41,7 @@ use serde::ser::Serializer;
4141
use serde::{Deserialize, Serialize};
4242
use serde_json::{Value, json};
4343
use servo_config::prefs::{self, PrefValue, Preferences};
44+
use servo_geometry::DeviceIndependentIntRect;
4445
use servo_url::ServoUrl;
4546
use style_traits::CSSPixel;
4647
use uuid::Uuid;
@@ -889,7 +890,7 @@ impl Handler {
889890
}
890891

891892
/// <https://w3c.github.io/webdriver/#set-window-rect>
892-
fn handle_set_window_size(
893+
fn handle_set_window_rect(
893894
&self,
894895
params: &WindowRectParameters,
895896
) -> WebDriverResult<WebDriverResponse> {
@@ -908,18 +909,10 @@ impl Handler {
908909
// Step 13. Handle any user prompt.
909910
self.handle_any_user_prompts(webview_id)?;
910911

911-
// We don't current allow modifying the window x/y positions, so we can just
912-
// return the current window rectangle if not changing dimension.
913-
if params.width.is_none() && params.height.is_none() {
914-
return self.handle_window_rect(VerifyBrowsingContextIsOpen::No);
915-
}
916912
// (TODO) Step 14. Fully exit fullscreen.
917913
// (TODO) Step 15. Restore the window.
918914
let (sender, receiver) = ipc::channel().unwrap();
919915

920-
// Step 16 - 17. Set the width/height in CSS pixels.
921-
// This should be done as long as one of width/height is not null.
922-
923916
let current = LazyCell::new(|| {
924917
let WebDriverResponse::WindowRect(current) = self
925918
.handle_window_rect(VerifyBrowsingContextIsOpen::No)
@@ -930,24 +923,34 @@ impl Handler {
930923
current
931924
});
932925

933-
let (width, height) = (
926+
let (x, y, width, height) = (
927+
params.x.unwrap_or_else(|| current.x),
928+
params.y.unwrap_or_else(|| current.y),
934929
params.width.unwrap_or_else(|| current.width),
935930
params.height.unwrap_or_else(|| current.height),
936931
);
937932

938-
self.send_message_to_embedder(WebDriverCommandMsg::SetWindowSize(
933+
// Step 16 - 17. Set the width/height in CSS pixels.
934+
// This should be done as long as one of width/height is not null.
935+
936+
// Step 18 - 19. Set the screen x/y in CSS pixels.
937+
// This should be done as long as one of width/height is not null.
938+
self.send_message_to_embedder(WebDriverCommandMsg::SetWindowRect(
939939
webview_id,
940-
Size2D::new(width, height),
940+
DeviceIndependentIntRect::from_origin_and_size(
941+
Point2D::new(x, y),
942+
Size2D::new(width, height),
943+
),
941944
sender.clone(),
942945
))?;
943946

944-
let window_size = wait_for_script_response(receiver)?;
945-
debug!("window_size after resizing: {window_size:?}");
947+
let window_rect = wait_for_script_response(receiver)?;
948+
debug!("Result window_rect: {window_rect:?}");
946949
let window_size_response = WindowRectResponse {
947-
x: 0,
948-
y: 0,
949-
width: window_size.width,
950-
height: window_size.height,
950+
x: window_rect.min.x,
951+
y: window_rect.min.y,
952+
width: window_rect.width(),
953+
height: window_rect.height(),
951954
};
952955
Ok(WebDriverResponse::WindowRect(window_size_response))
953956
}
@@ -2449,7 +2452,7 @@ impl WebDriverHandler<ServoExtensionRoute> for Handler {
24492452
WebDriverCommand::GetWindowRect => {
24502453
self.handle_window_rect(VerifyBrowsingContextIsOpen::Yes)
24512454
},
2452-
WebDriverCommand::SetWindowRect(ref size) => self.handle_set_window_size(size),
2455+
WebDriverCommand::SetWindowRect(ref size) => self.handle_set_window_rect(size),
24532456
WebDriverCommand::IsEnabled(ref element) => self.handle_is_enabled(element),
24542457
WebDriverCommand::IsSelected(ref element) => self.handle_is_selected(element),
24552458
WebDriverCommand::GoBack => self.handle_go_back(),

ports/servoshell/desktop/app.rs

Lines changed: 27 additions & 10 deletions
3486
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ use log::{info, trace, warn};
2121
use net::protocols::ProtocolRegistry;
2222
use servo::config::opts::Opts;
2323
use servo::config::prefs::Preferences;
24-
use servo::servo_geometry::convert_size_to_css_pixel;
24+
use servo::servo_geometry::convert_rect_to_css_pixel;
2525
use servo::servo_url::ServoUrl;
2626
use servo::user_content_manager::{UserContentManager, UserScript};
2727
use servo::webrender_api::ScrollLocation;
28+
use servo::webrender_api::units::DeviceIntRect;
2829
use servo::{
2930
EventLoopWaker, ImeEvent, InputEvent, KeyboardEvent, MouseButtonEvent, MouseMoveEvent,
3031
WebDriverCommandMsg, WebDriverScriptCommand, WebDriverUserPromptAction, WheelDelta, WheelEvent,
@@ -38,6 +39,7 @@ use winit::window::WindowId;
3839

3940
use super::app_state::AppState;
4041
use super::events_loop::{AppEvent, EventLoopProxy, EventsLoop};
42+
use super::geometry::winit_position_to_euclid_point;
4143
use super::minibrowser::{Minibrowser, MinibrowserEvent};
4244
use super::{headed_window, headless_window};
4345
use crate::desktop::app_state::RunningAppState;
@@ -392,7 +394,7 @@ impl App {
392394
warn!("Failed to send response of GetWindowSize: {error}");
393395
}
394396
},
395-
WebDriverCommandMsg::SetWindowSize(webview_id, requested_size, size_sender) => {
397+
WebDriverCommandMsg::SetWindowRect(webview_id, requested_rect, size_sender) => {
396398
let Some(webview) = running_state.webview_by_id(webview_id) else {
397399
continue;
398400
};
@@ -404,20 +406,35 @@ impl App {
404406
.expect("Should have at least one window in servoshell");
405407
let scale = window.hidpi_scale_factor();
406408

407-
let requested_physical_size =
408-
(requested_size.to_f32() * scale).round().to_i32();
409+
let requested_physical_rect =
410+
(requested_rect.to_f32() * scale).round().to_i32();
409411

410412
// When None is returned, it means that the request went to the display system,
411413
// and the actual size will be delivered later with the WindowEvent::Resized.
412-
let returned_size = window.request_resize(&webview, requested_physical_size);
414+
// Step 17. Set Width/Height.
415+
let returned_size =
416+
window.request_resize(&webview, requested_physical_rect.size());
413417
// TODO: Handle None case. For now, we assume always succeed.
414418
// In reality, the request may exceed available screen size.
415419

416-
if let Err(error) = size_sender.send(
417-
returned_size
418-
.map(|size| convert_size_to_css_pixel(size, scale))
419-
.unwrap_or(requested_size),
420-
) {
420+
// Step 18. Set position of the window.
421+
window.set_position(requested_physical_rect.min);
422+
423+
let result_physical_position = window
424+
.winit_window()
425+
.and_then(|window| window.outer_position().ok())
426+
.map(winit_position_to_euclid_point)
427+
.unwrap_or(requested_physical_rect.min);
428+
429+
let reply_rect = convert_rect_to_css_pixel(
430+
DeviceIntRect::from_origin_and_size(
431+
result_physical_position,
432+
returned_size.unwrap_or(requested_physical_rect.size()),
433+
),
434+
scale,
435+
);
436+
437+
if let Err(error) = size_sender.send(reply_rect) {
421438
warn!("Failed to send window size: {error}");
422439
}
423440
},

ports/servoshell/desktop/headed_window.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,12 @@ impl WindowPortsMethods for Window {
480480

481481
fn request_resize(&self, _: &WebView, new_outer_size: DeviceIntSize) -> Option<DeviceIntSize> {
482482
let outer_size = self.winit_window.outer_size();
483+
if outer_size.width == new_outer_size.width as u32 &&
484+
outer_size.height == new_outer_size.height as u32
485+
{
486+
return Some(new_outer_size);
487+
}
488+
483489
let inner_size = self.winit_window.inner_size();
484490
let decoration_height = outer_size.height - inner_size.height;
485491
let decoration_width = outer_size.width - inner_size.width;

0 commit comments

Comments
 (0)
0