mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
webdriver: Implement maximize window for both headless&headed window (#38271)
- Implement [Maximize Window](https://w3c.github.io/webdriver/#maximize-window) - Previously, headless window screen size is same as inner size if not specified in preference. We make it double as required by the test to not have max window initially. - Some other random cleanup. Testing: webdriver Stress test for maximize window (headed + headless). --------- Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
This commit is contained in:
parent
9ef4d0c9d7
commit
a3de3ffa75
11 changed files with 76 additions and 91 deletions
|
@ -4422,6 +4422,7 @@ where
|
||||||
WebDriverCommandMsg::GetWindowRect(..) |
|
WebDriverCommandMsg::GetWindowRect(..) |
|
||||||
WebDriverCommandMsg::GetViewportSize(..) |
|
WebDriverCommandMsg::GetViewportSize(..) |
|
||||||
WebDriverCommandMsg::SetWindowRect(..) |
|
WebDriverCommandMsg::SetWindowRect(..) |
|
||||||
|
WebDriverCommandMsg::MaximizeWebView(..) |
|
||||||
WebDriverCommandMsg::LoadUrl(..) |
|
WebDriverCommandMsg::LoadUrl(..) |
|
||||||
WebDriverCommandMsg::Refresh(..) |
|
WebDriverCommandMsg::Refresh(..) |
|
||||||
WebDriverCommandMsg::SendKeys(..) |
|
WebDriverCommandMsg::SendKeys(..) |
|
||||||
|
|
|
@ -138,6 +138,8 @@ pub enum WebDriverCommandMsg {
|
||||||
DeviceIndependentIntRect,
|
DeviceIndependentIntRect,
|
||||||
IpcSender<DeviceIndependentIntRect>,
|
IpcSender<DeviceIndependentIntRect>,
|
||||||
),
|
),
|
||||||
|
/// Maximize the window. Send back result window rectangle.
|
||||||
|
MaximizeWebView(WebViewId, IpcSender<DeviceIndependentIntRect>),
|
||||||
/// Take a screenshot of the viewport.
|
/// Take a screenshot of the viewport.
|
||||||
TakeScreenshot(
|
TakeScreenshot(
|
||||||
WebViewId,
|
WebViewId,
|
||||||
|
|
|
@ -911,7 +911,6 @@ impl Handler {
|
||||||
|
|
||||||
// (TODO) Step 14. Fully exit fullscreen.
|
// (TODO) Step 14. Fully exit fullscreen.
|
||||||
// (TODO) Step 15. Restore the window.
|
// (TODO) Step 15. Restore the window.
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
|
||||||
|
|
||||||
let current = LazyCell::new(|| {
|
let current = LazyCell::new(|| {
|
||||||
let WebDriverResponse::WindowRect(current) = self
|
let WebDriverResponse::WindowRect(current) = self
|
||||||
|
@ -929,7 +928,7 @@ impl Handler {
|
||||||
params.width.unwrap_or_else(|| current.width),
|
params.width.unwrap_or_else(|| current.width),
|
||||||
params.height.unwrap_or_else(|| current.height),
|
params.height.unwrap_or_else(|| current.height),
|
||||||
);
|
);
|
||||||
|
let (sender, receiver) = ipc::channel().unwrap();
|
||||||
// Step 16 - 17. Set the width/height in CSS pixels.
|
// Step 16 - 17. Set the width/height in CSS pixels.
|
||||||
// This should be done as long as one of width/height is not null.
|
// This should be done as long as one of width/height is not null.
|
||||||
|
|
||||||
|
@ -941,7 +940,7 @@ impl Handler {
|
||||||
Point2D::new(x, y),
|
Point2D::new(x, y),
|
||||||
Size2D::new(width, height),
|
Size2D::new(width, height),
|
||||||
),
|
),
|
||||||
sender.clone(),
|
sender,
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
let window_rect = wait_for_script_response(receiver)?;
|
let window_rect = wait_for_script_response(receiver)?;
|
||||||
|
@ -955,6 +954,38 @@ impl Handler {
|
||||||
Ok(WebDriverResponse::WindowRect(window_size_response))
|
Ok(WebDriverResponse::WindowRect(window_size_response))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webdriver/#maximize-window>
|
||||||
|
fn handle_maximize_window(&mut self) -> WebDriverResult<WebDriverResponse> {
|
||||||
|
// Step 1. If the remote end does not support the Maximize Window command for session's
|
||||||
|
// current top-level browsing context for any reason,
|
||||||
|
// return error with error code unsupported operation.
|
||||||
|
let webview_id = self.session()?.webview_id;
|
||||||
|
// Step 2. If session's current top-level browsing context is no longer open,
|
||||||
|
// return error with error code no such window.
|
||||||
|
self.verify_top_level_browsing_context_is_open(webview_id)?;
|
||||||
|
|
||||||
|
// Step 3. Try to handle any user prompts with session.
|
||||||
|
self.handle_any_user_prompts(self.session()?.webview_id)?;
|
||||||
|
|
||||||
|
// Step 4. (TODO) Fully exit fullscreen.
|
||||||
|
|
||||||
|
// Step 5. (TODO) Restore the window.
|
||||||
|
|
||||||
|
// Step 6. Maximize the window of session's current top-level browsing context.
|
||||||
|
let (sender, receiver) = ipc::channel().unwrap();
|
||||||
|
self.send_message_to_embedder(WebDriverCommandMsg::MaximizeWebView(webview_id, sender))?;
|
||||||
|
|
||||||
|
let window_rect = wait_for_script_response(receiver)?;
|
||||||
|
debug!("Result window_rect: {window_rect:?}");
|
||||||
|
let window_size_response = WindowRectResponse {
|
||||||
|
x: window_rect.min.x,
|
||||||
|
y: window_rect.min.y,
|
||||||
|
width: window_rect.width(),
|
||||||
|
height: window_rect.height(),
|
||||||
|
};
|
||||||
|
Ok(WebDriverResponse::WindowRect(window_size_response))
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_is_enabled(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
|
fn handle_is_enabled(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
let (sender, receiver) = ipc::channel().unwrap();
|
||||||
|
|
||||||
|
@ -2483,6 +2514,7 @@ impl WebDriverHandler<ServoExtensionRoute> for Handler {
|
||||||
WebDriverCommand::GetWindowHandles => self.handle_window_handles(),
|
WebDriverCommand::GetWindowHandles => self.handle_window_handles(),
|
||||||
WebDriverCommand::NewWindow(ref parameters) => self.handle_new_window(parameters),
|
WebDriverCommand::NewWindow(ref parameters) => self.handle_new_window(parameters),
|
||||||
WebDriverCommand::CloseWindow => self.handle_close_window(),
|
WebDriverCommand::CloseWindow => self.handle_close_window(),
|
||||||
|
WebDriverCommand::MaximizeWindow => self.handle_maximize_window(),
|
||||||
WebDriverCommand::SwitchToFrame(ref parameters) => {
|
WebDriverCommand::SwitchToFrame(ref parameters) => {
|
||||||
self.handle_switch_to_frame(parameters)
|
self.handle_switch_to_frame(parameters)
|
||||||
},
|
},
|
||||||
|
|
|
@ -392,6 +392,22 @@ impl App {
|
||||||
warn!("Failed to send response of GetWindowSize: {error}");
|
warn!("Failed to send response of GetWindowSize: {error}");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
WebDriverCommandMsg::MaximizeWebView(webview_id, response_sender) => {
|
||||||
|
let window = self
|
||||||
|
.windows
|
||||||
|
.values()
|
||||||
|
.next()
|
||||||
|
.expect("Should have at least one window in servoshell");
|
||||||
|
window.maximize(
|
||||||
|
&running_state
|
||||||
|
.webview_by_id(webview_id)
|
||||||
|
.expect("Webview must exists as we just verified"),
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Err(error) = response_sender.send(window.window_rect()) {
|
||||||
|
warn!("Failed to send response of GetWindowSize: {error}");
|
||||||
|
}
|
||||||
|
},
|
||||||
WebDriverCommandMsg::SetWindowRect(webview_id, requested_rect, size_sender) => {
|
WebDriverCommandMsg::SetWindowRect(webview_id, requested_rect, size_sender) => {
|
||||||
let Some(webview) = running_state.webview_by_id(webview_id) else {
|
let Some(webview) = running_state.webview_by_id(webview_id) else {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -767,10 +767,7 @@ impl WindowPortsMethods for Window {
|
||||||
// this prevents a crash in the compositor due to invalid surface size
|
// this prevents a crash in the compositor due to invalid surface size
|
||||||
self.winit_window.set_min_inner_size(Some(PhysicalSize::new(
|
self.winit_window.set_min_inner_size(Some(PhysicalSize::new(
|
||||||
MIN_INNER_WIDTH,
|
MIN_INNER_WIDTH,
|
||||||
i32::max(
|
MIN_INNER_HEIGHT.max((self.toolbar_height() * self.hidpi_scale_factor()).0 as i32),
|
||||||
MIN_INNER_HEIGHT,
|
|
||||||
(self.toolbar_height() * self.hidpi_scale_factor()).0 as i32,
|
|
||||||
),
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -808,6 +805,10 @@ impl WindowPortsMethods for Window {
|
||||||
Some(winit::window::Theme::Light) | None => servo::Theme::Light,
|
Some(winit::window::Theme::Light) | None => servo::Theme::Light,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn maximize(&self, _webview: &WebView) {
|
||||||
|
self.winit_window.set_maximized(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn winit_phase_to_touch_event_type(phase: TouchPhase) -> TouchEventType {
|
fn winit_phase_to_touch_event_type(phase: TouchPhase) -> TouchEventType {
|
||||||
|
|
|
@ -13,7 +13,7 @@ use servo::servo_geometry::{
|
||||||
DeviceIndependentIntRect, DeviceIndependentPixel, convert_rect_to_css_pixel,
|
DeviceIndependentIntRect, DeviceIndependentPixel, convert_rect_to_css_pixel,
|
||||||
};
|
};
|
||||||
use servo::webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixel};
|
use servo::webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixel};
|
||||||
use servo::{RenderingContext, ScreenGeometry, SoftwareRenderingContext};
|
use servo::{RenderingContext, ScreenGeometry, SoftwareRenderingContext, WebView};
|
||||||
use winit::dpi::PhysicalSize;
|
use winit::dpi::PhysicalSize;
|
||||||
|
|
||||||
use super::app_state::RunningAppState;
|
use super::app_state::RunningAppState;
|
||||||
|
@ -47,7 +47,7 @@ impl Window {
|
||||||
|
|
||||||
let screen_size = servoshell_preferences
|
let screen_size = servoshell_preferences
|
||||||
.screen_size_override
|
.screen_size_override
|
||||||
.map_or(inner_size, |screen_size_override| {
|
.map_or(inner_size * 2, |screen_size_override| {
|
||||||
(screen_size_override.to_f32() * hidpi_factor).to_i32()
|
(screen_size_override.to_f32() * hidpi_factor).to_i32()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ impl WindowPortsMethods for Window {
|
||||||
|
|
||||||
fn request_resize(
|
fn request_resize(
|
||||||
&self,
|
&self,
|
||||||
webview: &::servo::WebView,
|
webview: &WebView,
|
||||||
outer_size: DeviceIntSize,
|
outer_size: DeviceIntSize,
|
||||||
) -> Option<DeviceIntSize> {
|
) -> Option<DeviceIntSize> {
|
||||||
let new_size = DeviceIntSize::new(
|
let new_size = DeviceIntSize::new(
|
||||||
|
@ -167,4 +167,17 @@ impl WindowPortsMethods for Window {
|
||||||
fn rendering_context(&self) -> Rc<dyn RenderingContext> {
|
fn rendering_context(&self) -> Rc<dyn RenderingContext> {
|
||||||
self.rendering_context.clone()
|
self.rendering_context.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn maximize(&self, webview: &WebView) {
|
||||||
|
self.window_position.set(Point2D::zero());
|
||||||
|
self.inner_size.set(self.screen_size);
|
||||||
|
// Because we are managing the rendering surface ourselves, there will be no other
|
||||||
|
// notification (such as from the display manager) that it has changed size, so we
|
||||||
|
// must notify the compositor here.
|
||||||
|
webview.move_resize(self.screen_size.to_f32().into());
|
||||||
|
webview.resize(PhysicalSize::new(
|
||||||
|
self.screen_size.width as u32,
|
||||||
|
self.screen_size.height as u32,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,4 +65,5 @@ pub trait WindowPortsMethods {
|
||||||
servo::Theme::Light
|
servo::Theme::Light
|
||||||
}
|
}
|
||||||
fn window_rect(&self) -> DeviceIndependentIntRect;
|
fn window_rect(&self) -> DeviceIndependentIntRect;
|
||||||
|
fn maximize(&self, webview: &WebView);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,4 @@
|
||||||
[maximize.py]
|
[maximize.py]
|
||||||
[test_no_top_browsing_context]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_no_browsing_context]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_response_payload]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_fully_exit_fullscreen]
|
[test_fully_exit_fullscreen]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
[stress.py]
|
|
||||||
[test_stress[0\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_stress[1\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_stress[2\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_stress[3\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_stress[4\]]
|
|
||||||
expected: FAIL
|
|
|
@ -1,54 +0,0 @@
|
||||||
[user_prompts.py]
|
|
||||||
[test_accept[alert-None\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_accept[confirm-True\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_accept[prompt-\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_accept_and_notify[alert-None\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_accept_and_notify[confirm-True\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_accept_and_notify[prompt-\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_dismiss[alert-None\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_dismiss[confirm-False\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_dismiss[prompt-None\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_dismiss_and_notify[alert-None\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_dismiss_and_notify[confirm-False\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_dismiss_and_notify[prompt-None\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_ignore[alert\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_ignore[confirm\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_ignore[prompt\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_default[alert-None\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_default[confirm-False\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_default[prompt-None\]]
|
|
||||||
expected: FAIL
|
|
|
@ -2,8 +2,5 @@
|
||||||
[test_restore_from_fullscreen]
|
[test_restore_from_fullscreen]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[test_restore_from_maximized]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_set_to_available_size]
|
[test_set_to_available_size]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue