diff --git a/crates/ely_servo_host/src/host.rs b/crates/ely_servo_host/src/host.rs index 01eb10e..11e0077 100644 --- a/crates/ely_servo_host/src/host.rs +++ b/crates/ely_servo_host/src/host.rs @@ -220,6 +220,13 @@ pub struct ScrollRequest { pub delta_y: i32, } +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ResizeRequest { + pub webview_id: WebViewId, + pub width: u32, + pub height: u32, +} + #[derive(Clone, Debug, Eq, PartialEq)] pub struct MouseClickRequest { pub webview_id: WebViewId, @@ -275,6 +282,8 @@ pub trait ServoHost { fn scroll(&mut self, request: ScrollRequest) -> Result<(), ServoHostError>; + fn resize(&mut self, request: ResizeRequest) -> Result<(), ServoHostError>; + fn click(&mut self, request: MouseClickRequest) -> Result<(), ServoHostError>; fn drag(&mut self, request: MouseDragRequest) -> Result<(), ServoHostError>; diff --git a/crates/ely_servo_host/src/lib.rs b/crates/ely_servo_host/src/lib.rs index 9223112..59efa5c 100644 --- a/crates/ely_servo_host/src/lib.rs +++ b/crates/ely_servo_host/src/lib.rs @@ -10,8 +10,8 @@ mod runtime_input; pub use error::ServoHostError; pub use host::{ KeyboardTextRequest, MouseClickRequest, MouseDragRequest, NavigationRequest, - PermissionDecision, PermissionRequest, RenderedFrame, RenderedFrameSummary, ScrollRequest, - ServoHost, TouchTapRequest, WebViewSnapshot, WebViewState, + PermissionDecision, PermissionRequest, RenderedFrame, RenderedFrameSummary, ResizeRequest, + ScrollRequest, ServoHost, TouchTapRequest, WebViewSnapshot, WebViewState, }; #[cfg(feature = "servo-engine")] pub use runtime::{ServoSurfaceSize, SoftwareServoHost}; diff --git a/crates/ely_servo_host/src/runtime.rs b/crates/ely_servo_host/src/runtime.rs index 9c15256..c4320fd 100644 --- a/crates/ely_servo_host/src/runtime.rs +++ b/crates/ely_servo_host/src/runtime.rs @@ -19,8 +19,8 @@ use url::Url; use crate::{ KeyboardTextRequest, MouseClickRequest, MouseDragRequest, NavigationRequest, - PermissionDecision, PermissionRequest, RenderedFrame, ScrollRequest, ServoHost, ServoHostError, - TouchTapRequest, WebViewSnapshot, WebViewState, + PermissionDecision, PermissionRequest, RenderedFrame, ResizeRequest, ScrollRequest, ServoHost, + ServoHostError, TouchTapRequest, WebViewSnapshot, WebViewState, runtime_input::{send_keyboard_text, send_mouse_click, send_mouse_drag, send_touch_tap}, }; @@ -165,6 +165,16 @@ impl ServoHost for SoftwareServoHost { Ok(()) } + fn resize(&mut self, request: ResizeRequest) -> Result<(), ServoHostError> { + let webview = self + .webviews + .get(&request.webview_id) + .ok_or_else(|| ServoHostError::WebViewNotFound { id: request.webview_id.clone() })?; + + webview.webview.resize(PhysicalSize::new(request.width, request.height)); + Ok(()) + } + fn click(&mut self, request: MouseClickRequest) -> Result<(), ServoHostError> { let webview = self .webviews diff --git a/crates/ely_servo_host/tests/software_host.rs b/crates/ely_servo_host/tests/software_host.rs index 48164e2..7295fff 100644 --- a/crates/ely_servo_host/tests/software_host.rs +++ b/crates/ely_servo_host/tests/software_host.rs @@ -4,11 +4,16 @@ use std::{error::Error, thread, time::Duration}; use ely_domain::{ProfileId, TabId, UrlText}; use ely_servo_host::{ - KeyboardTextRequest, MouseClickRequest, MouseDragRequest, NavigationRequest, ScrollRequest, - ServoHost, ServoHostError, ServoSurfaceSize, SoftwareServoHost, TouchTapRequest, WebViewState, + KeyboardTextRequest, MouseClickRequest, MouseDragRequest, NavigationRequest, ResizeRequest, + ScrollRequest, ServoHost, ServoHostError, ServoSurfaceSize, SoftwareServoHost, TouchTapRequest, + WebViewState, }; const MINIMUM_CONTENT_PIXELS: u64 = 1_000; +const INITIAL_WIDTH: u32 = 640; +const INITIAL_HEIGHT: u32 = 480; +const RESIZED_WIDTH: u32 = 934; +const RESIZED_HEIGHT: u32 = 657; const PRD_SITE_COMPATIBILITY_CASES: &[PrdSiteCompatibilityCase] = &[ PrdSiteCompatibilityCase { url: "https://example.com", title_fragment: "Example Domain" }, PrdSiteCompatibilityCase { url: "https://servo.org", title_fragment: "Servo" }, @@ -26,7 +31,7 @@ struct PrdSiteCompatibilityCase { #[test] fn manages_real_servo_webview_lifecycle() -> Result<(), Box> { - let mut host = SoftwareServoHost::new(ServoSurfaceSize::new(640, 480))?; + let mut host = SoftwareServoHost::new(ServoSurfaceSize::new(INITIAL_WIDTH, INITIAL_HEIGHT))?; let tab_id = TabId::new(); let profile_id = ProfileId::new(); @@ -139,8 +144,25 @@ fn manages_real_servo_webview_lifecycle() -> Result<(), Box> { assert_rendered_frame_has_content(&host, "https://servo.org scrolled", MINIMUM_CONTENT_PIXELS)?; assert_ne!(host.last_rendered_frame()?.sample_hash(), previous_frame_hash); + let previous_frame_hash = host.last_rendered_frame()?.sample_hash(); + host.resize(ResizeRequest { + webview_id: webview_id.clone(), + width: RESIZED_WIDTH, + height: RESIZED_HEIGHT, + })?; + let snapshot = wait_for_rendered_webview(&mut host, &webview_id, Some(previous_frame_hash))?; + assert_eq!(snapshot.state(), &WebViewState::Complete, "snapshot: {snapshot:?}"); + assert_rendered_frame_has_dimensions_and_content( + &host, + "https://servo.org resized", + RESIZED_WIDTH, + RESIZED_HEIGHT, + MINIMUM_CONTENT_PIXELS, + )?; + assert_ne!(host.last_rendered_frame()?.sample_hash(), previous_frame_hash); + assert!(matches!( - SoftwareServoHost::new(ServoSurfaceSize::new(640, 480)), + SoftwareServoHost::new(ServoSurfaceSize::new(INITIAL_WIDTH, INITIAL_HEIGHT)), Err(ServoHostError::RuntimeAlreadyStarted) )); Ok(()) @@ -182,11 +204,27 @@ fn assert_rendered_frame_has_content( host: &SoftwareServoHost, label: &str, minimum_content_pixels: u64, +) -> Result<(), Box> { + assert_rendered_frame_has_dimensions_and_content( + host, + label, + INITIAL_WIDTH, + INITIAL_HEIGHT, + minimum_content_pixels, + ) +} + +fn assert_rendered_frame_has_dimensions_and_content( + host: &SoftwareServoHost, + label: &str, + expected_width: u32, + expected_height: u32, + minimum_content_pixels: u64, ) -> Result<(), Box> { let frame = host.last_rendered_frame()?; - assert_eq!(frame.width(), 640, "{label}: {frame:?}"); - assert_eq!(frame.height(), 480, "{label}: {frame:?}"); + assert_eq!(frame.width(), expected_width, "{label}: {frame:?}"); + assert_eq!(frame.height(), expected_height, "{label}: {frame:?}"); assert!(frame.opaque_pixel_count() > 0, "{label}: {frame:?}"); assert!(frame.non_white_pixel_count() > 0, "{label}: {frame:?}"); assert!(frame.content_pixel_count() >= minimum_content_pixels, "{label}: {frame:?}");