diff --git a/components/compositing/webview.rs b/components/compositing/webview.rs index 1263f877012..41e95f38689 100644 --- a/components/compositing/webview.rs +++ b/components/compositing/webview.rs @@ -20,7 +20,7 @@ pub struct WebViewManager { webviews: HashMap, /// The order to paint them in, topmost last. - painting_order: Vec, + pub(crate) painting_order: Vec, } #[derive(Clone, Copy, Debug, PartialEq)] diff --git a/ports/servoshell/Cargo.toml b/ports/servoshell/Cargo.toml index 1de0d8cdc4a..b845d61bf64 100644 --- a/ports/servoshell/Cargo.toml +++ b/ports/servoshell/Cargo.toml @@ -85,6 +85,7 @@ backtrace = { workspace = true } [target.'cfg(target_env = "ohos")'.dependencies] env_filter = "0.1.3" +euclid = { workspace = true } # force inprocess, until libc-rs 0.2.156 is released containing # https://github.com/rust-lang/libc/commit/9e248e212c5602cb4e98676e4c21ea0382663a12 ipc-channel = { workspace = true, features = ["force-inprocess"] } diff --git a/ports/servoshell/egl/ohos.rs b/ports/servoshell/egl/ohos.rs index 66e568972b0..908a4c75240 100644 --- a/ports/servoshell/egl/ohos.rs +++ b/ports/servoshell/egl/ohos.rs @@ -26,14 +26,14 @@ use simpleservo::EventLoopWaker; use xcomponent_sys::{ OH_NativeXComponent, OH_NativeXComponent_Callback, OH_NativeXComponent_GetKeyEvent, OH_NativeXComponent_GetKeyEventAction, OH_NativeXComponent_GetKeyEventCode, - OH_NativeXComponent_GetTouchEvent, OH_NativeXComponent_KeyAction, OH_NativeXComponent_KeyCode, - OH_NativeXComponent_KeyEvent, OH_NativeXComponent_RegisterCallback, - OH_NativeXComponent_RegisterKeyEventCallback, OH_NativeXComponent_TouchEvent, - OH_NativeXComponent_TouchEventType, + OH_NativeXComponent_GetTouchEvent, OH_NativeXComponent_GetXComponentSize, + OH_NativeXComponent_KeyAction, OH_NativeXComponent_KeyCode, OH_NativeXComponent_KeyEvent, + OH_NativeXComponent_RegisterCallback, OH_NativeXComponent_RegisterKeyEventCallback, + OH_NativeXComponent_TouchEvent, OH_NativeXComponent_TouchEventType, }; use super::host_trait::HostTrait; -use super::servo_glue::ServoGlue; +use super::servo_glue::{Coordinates, ServoGlue}; mod resources; mod simpleservo; @@ -104,6 +104,10 @@ pub(super) enum ServoAction { ImeSendEnter, Initialize(Box), Vsync, + Resize { + width: i32, + height: i32, + }, } /// Queue length for the thread-safe function to submit URL updates to ArkTS @@ -180,6 +184,9 @@ impl ServoAction { servo.notify_vsync(); servo.present_if_needed(); }, + Resize { width, height } => { + servo.resize(Coordinates::new(0, 0, *width, *height, *width, *height)) + }, }; } } @@ -263,9 +270,52 @@ extern "C" fn on_surface_created_cb(xcomponent: *mut OH_NativeXComponent, window info!("Returning from on_surface_created_cb"); } -// Todo: Probably we need to block here, until the main thread has processed the change. -extern "C" fn on_surface_changed_cb(_component: *mut OH_NativeXComponent, _window: *mut c_void) { - error!("on_surface_changed_cb is currently not implemented!"); +/// Returns the size of the surface +/// +/// # Safety +/// +/// `xcomponent` and `native_window` must be valid, non-null and aligned pointers to a +/// live xcomponent and associated native window surface. +unsafe fn get_xcomponent_size( + xcomponent: *mut OH_NativeXComponent, + native_window: *mut c_void, +) -> Result, i32> { + let mut width: u64 = 0; + let mut height: u64 = 0; + let result = unsafe { + OH_NativeXComponent_GetXComponentSize( + xcomponent, + native_window, + &raw mut width, + &raw mut height, + ) + }; + if result != 0 { + debug!("OH_NativeXComponent_GetXComponentSize failed with {result}"); + return Err(result); + } + + let width: i32 = width.try_into().expect("Width too large"); + let height: i32 = height.try_into().expect("Height too large"); + Ok(euclid::Size2D::new(width, height)) +} + +extern "C" fn on_surface_changed_cb( + xcomponent: *mut OH_NativeXComponent, + native_window: *mut c_void, +) { + debug!("on_surface_changed_cb: xc: {xcomponent:?}, window: {native_window:?}"); + // SAFETY: We just obtained these pointers from the callback, so we can assume them to be valid. + if let Ok(size) = unsafe { get_xcomponent_size(xcomponent, native_window) } { + info!("on_surface_changed_cb: Resizing to {size:?}"); + call(ServoAction::Resize { + width: size.width, + height: size.height, + }) + .unwrap(); + } else { + error!("on_surface_changed_cb: Surface changed, but failed to obtain new size") + } } extern "C" fn on_surface_destroyed_cb(_component: *mut OH_NativeXComponent, _window: *mut c_void) { diff --git a/ports/servoshell/egl/ohos/simpleservo.rs b/ports/servoshell/egl/ohos/simpleservo.rs index 3498531a949..ff0a37c6105 100644 --- a/ports/servoshell/egl/ohos/simpleservo.rs +++ b/ports/servoshell/egl/ohos/simpleservo.rs @@ -9,7 +9,6 @@ use std::rc::Rc; use log::{debug, info}; use servo::compositing::CompositeTarget; -use servo::euclid::Size2D; use servo::webrender_traits::SurfmanRenderingContext; /// The EventLoopWaker::wake function will be called from any thread. /// It will be called to notify embedder that some events are available, @@ -17,7 +16,7 @@ use servo::webrender_traits::SurfmanRenderingContext; pub use servo::EventLoopWaker; use servo::{self, resources, Servo}; use surfman::{Connection, SurfaceType}; -use xcomponent_sys::{OH_NativeXComponent, OH_NativeXComponent_GetXComponentSize}; +use xcomponent_sys::OH_NativeXComponent; use crate::egl::host_trait::HostTrait; use crate::egl::ohos::resources::ResourceReaderInstance; @@ -68,24 +67,13 @@ pub fn init( .create_adapter() .or(Err("Failed to create adapter"))?; - let mut width: u64 = 0; - let mut height: u64 = 0; - let res = unsafe { - OH_NativeXComponent_GetXComponentSize( - xcomponent, - native_window, - &mut width as *mut _, - &mut height as *mut _, - ) + let Ok(window_size) = (unsafe { super::get_xcomponent_size(xcomponent, native_window) }) else { + return Err("Failed to get xcomponent size"); }; - assert_eq!(res, 0, "OH_NativeXComponent_GetXComponentSize failed"); - let width: i32 = width.try_into().expect("Width too large"); - let height: i32 = height.try_into().expect("Height too large"); - debug!("Creating surfman widget with width {width} and height {height}"); - let native_widget = unsafe { - connection.create_native_widget_from_ptr(native_window, Size2D::new(width, height)) - }; + debug!("Creating surfman widget with {window_size:?}"); + let native_widget = + unsafe { connection.create_native_widget_from_ptr(native_window, window_size) }; let surface_type = SurfaceType::Widget { native_widget }; info!("Creating rendering context"); @@ -102,7 +90,14 @@ pub fn init( let window_callbacks = Rc::new(ServoWindowCallbacks::new( callbacks, - RefCell::new(Coordinates::new(0, 0, width, height, width, height)), + RefCell::new(Coordinates::new( + 0, + 0, + window_size.width, + window_size.height, + window_size.width, + window_size.height, + )), options.display_density as f32, )); diff --git a/ports/servoshell/egl/servo_glue.rs b/ports/servoshell/egl/servo_glue.rs index 0a12bd9c713..f485ed56b9c 100644 --- a/ports/servoshell/egl/servo_glue.rs +++ b/ports/servoshell/egl/servo_glue.rs @@ -15,7 +15,7 @@ use servo::compositing::windowing::{ }; use servo::euclid::{Box2D, Point2D, Rect, Scale, Size2D, Vector2D}; use servo::servo_geometry::DeviceIndependentPixel; -use servo::webrender_api::units::DevicePixel; +use servo::webrender_api::units::{DevicePixel, DeviceRect}; use servo::webrender_api::ScrollLocation; use servo::webrender_traits::SurfmanRenderingContext; use servo::{ @@ -222,8 +222,16 @@ impl ServoGlue { /// Let Servo know that the window has been resized. pub fn resize(&mut self, coordinates: Coordinates) { - info!("resize"); + info!("resize to {:?}", coordinates); + let size = coordinates.viewport.size; + let _ = self + .rendering_context + .resize(Size2D::new(size.width, size.height)) + .inspect_err(|e| error!("Failed to resize rendering context: {e:?}")); + *self.callbacks.coordinates.borrow_mut() = coordinates; self.active_webview().notify_rendering_context_resized(); + self.active_webview() + .move_resize(DeviceRect::from_size(size.to_f32())); self.maybe_perform_updates() } @@ -638,10 +646,12 @@ impl ServoGlue { EmbedderMsg::Keyboard(..) => { error!("Received unexpected keyboard event"); }, + EmbedderMsg::ResizeTo(size) => { + error!("Received resize event (to {size:?}). Currently only the user can resize windows"); + }, EmbedderMsg::Status(..) | EmbedderMsg::SelectFiles(..) | EmbedderMsg::MoveTo(..) | - EmbedderMsg::ResizeTo(..) | EmbedderMsg::SetCursor(..) | EmbedderMsg::NewFavicon(..) | EmbedderMsg::HeadParsed |