libservo: Expose a ServoBuilder (#36549)

Expose a `ServoBuilder` for easily creating Servo instances using
default values. This change enables removing `EmbedderTraits`.

Testing: This is covered by `Servo` unit tests.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson 2025-04-16 18:58:52 +02:00 committed by GitHub
parent 7a8e75266f
commit d8a7abda69
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 252 additions and 271 deletions

View file

@ -20,11 +20,10 @@ use raw_window_handle::{
AndroidDisplayHandle, AndroidNdkWindowHandle, RawDisplayHandle, RawWindowHandle,
};
use servo::{
AlertResponse, LoadStatus, MediaSessionActionType, PermissionRequest, SimpleDialog, WebView,
};
use simpleservo::{
APP, DeviceIntRect, EventLoopWaker, InitOptions, InputMethodType, MediaSessionPlaybackState,
AlertResponse, EventLoopWaker, LoadStatus, MediaSessionActionType, PermissionRequest,
SimpleDialog, WebView,
};
use simpleservo::{APP, DeviceIntRect, InitOptions, InputMethodType, MediaSessionPlaybackState};
use super::app_state::{Coordinates, RunningAppState};
use super::host_trait::HostTrait;

View file

@ -8,18 +8,14 @@ use std::rc::Rc;
use dpi::PhysicalSize;
use raw_window_handle::{DisplayHandle, RawDisplayHandle, RawWindowHandle, WindowHandle};
/// The EventLoopWaker::wake function will be called from any thread.
/// It will be called to notify embedder that some events are available,
/// and that perform_updates need to be called
pub use servo::EventLoopWaker;
pub use servo::webrender_api::units::DeviceIntRect;
use servo::{self, Servo, resources};
use servo::{self, EventLoopWaker, ServoBuilder, resources};
pub use servo::{InputMethodType, MediaSessionPlaybackState, WindowRenderingContext};
use crate::egl::android::resources::ResourceReaderInstance;
use crate::egl::app_state::{
Coordinates, RunningAppState, ServoEmbedderCallbacks, ServoWindowCallbacks,
};
#[cfg(feature = "webxr")]
use crate::egl::app_state::XrDiscoveryWebXrRegistry;
use crate::egl::app_state::{Coordinates, RunningAppState, ServoWindowCallbacks};
use crate::egl::host_trait::HostTrait;
use crate::prefs::{ArgumentParsingResult, parse_command_line_arguments};
@ -85,26 +81,22 @@ pub fn init(
RefCell::new(init_opts.coordinates),
));
let embedder_callbacks = Box::new(ServoEmbedderCallbacks::new(
waker,
#[cfg(feature = "webxr")]
init_opts.xr_discovery,
));
let servo_builder = ServoBuilder::new(rendering_context.clone())
.opts(opts)
.preferences(preferences)
.event_loop_waker(waker);
let servo = Servo::new(
opts,
preferences,
rendering_context.clone(),
embedder_callbacks,
Default::default(),
);
#[cfg(feature = "webxr")]
let servo_builder = servo_builder.webxr_registry(Box::new(XrDiscoveryWebXrRegistry::new(
init_opts.xr_discovery,
)));
APP.with(|app| {
let app_state = RunningAppState::new(
init_opts.url,
init_opts.density,
rendering_context,
servo,
servo_builder.build(),
window_callbacks,
servoshell_preferences,
);

View file

@ -11,18 +11,16 @@ use keyboard_types::{CompositionEvent, CompositionState};
use log::{debug, error, info, warn};
use raw_window_handle::{RawWindowHandle, WindowHandle};
use servo::base::id::WebViewId;
use servo::compositing::windowing::EmbedderMethods;
use servo::euclid::{Point2D, Rect, Scale, Size2D, Vector2D};
use servo::servo_geometry::DeviceIndependentPixel;
use servo::webrender_api::ScrollLocation;
use servo::webrender_api::units::{DeviceIntRect, DeviceIntSize, DevicePixel};
use servo::{
AllowOrDenyRequest, ContextMenuResult, EmbedderProxy, EventLoopWaker, ImeEvent, InputEvent,
InputMethodType, Key, KeyState, KeyboardEvent, LoadStatus, MediaSessionActionType,
MediaSessionEvent, MouseButton, MouseButtonAction, MouseButtonEvent, MouseMoveEvent,
NavigationRequest, PermissionRequest, RenderingContext, ScreenGeometry, Servo, ServoDelegate,
ServoError, SimpleDialog, TouchEvent, TouchEventType, TouchId, WebView, WebViewBuilder,
WebViewDelegate, WindowRenderingContext,
AllowOrDenyRequest, ContextMenuResult, ImeEvent, InputEvent, InputMethodType, Key, KeyState,
KeyboardEvent, LoadStatus, MediaSessionActionType, MediaSessionEvent, MouseButton,
MouseButtonAction, MouseButtonEvent, MouseMoveEvent, NavigationRequest, PermissionRequest,
RenderingContext, ScreenGeometry, Servo, ServoDelegate, ServoError, SimpleDialog, TouchEvent,
TouchEventType, TouchId, WebView, WebViewBuilder, WebViewDelegate, WindowRenderingContext,
};
use url::Url;
@ -682,38 +680,24 @@ impl RunningAppState {
}
}
pub(super) struct ServoEmbedderCallbacks {
waker: Box<dyn EventLoopWaker>,
#[cfg(feature = "webxr")]
xr_discovery: Option<servo::webxr::Discovery>,
#[cfg(feature = "webxr")]
pub(crate) struct XrDiscoveryWebXrRegistry {
xr_discovery: RefCell<Option<servo::webxr::Discovery>>,
}
impl ServoEmbedderCallbacks {
pub(super) fn new(
waker: Box<dyn EventLoopWaker>,
#[cfg(feature = "webxr")] xr_discovery: Option<servo::webxr::Discovery>,
) -> Self {
#[cfg(feature = "webxr")]
impl XrDiscoveryWebXrRegistry {
pub(crate) fn new(xr_discovery: Option<servo::webxr::Discovery>) -> Self {
Self {
waker,
#[cfg(feature = "webxr")]
xr_discovery,
xr_discovery: RefCell::new(xr_discovery),
}
}
}
impl EmbedderMethods for ServoEmbedderCallbacks {
fn create_event_loop_waker(&mut self) -> Box<dyn EventLoopWaker> {
debug!("EmbedderMethods::create_event_loop_waker");
self.waker.clone()
}
#[cfg(feature = "webxr")]
fn register_webxr(
&mut self,
registry: &mut servo::webxr::MainThreadRegistry,
_embedder_proxy: EmbedderProxy,
) {
debug!("EmbedderMethods::register_xr");
#[cfg(feature = "webxr")]
impl servo::webxr::WebXrRegistry for XrDiscoveryWebXrRegistry {
fn register(&self, registry: &mut servo::webxr::MainThreadRegistry) {
debug!("XrDiscoveryWebXrRegistry::register");
if let Some(discovery) = self.xr_discovery.take() {
registry.register(discovery);
}

View file

@ -22,10 +22,9 @@ use ohos_ime::{AttachOptions, Ime, ImeProxy, RawTextEditorProxy};
use ohos_ime_sys::types::InputMethod_EnterKeyType;
use servo::style::Zero;
use servo::{
AlertResponse, InputMethodType, LoadStatus, MediaSessionPlaybackState, PermissionRequest,
SimpleDialog, WebView,
AlertResponse, EventLoopWaker, InputMethodType, LoadStatus, MediaSessionPlaybackState,
PermissionRequest, SimpleDialog, WebView,
};
use simpleservo::EventLoopWaker;
use xcomponent_sys::{
OH_NativeXComponent, OH_NativeXComponent_Callback, OH_NativeXComponent_GetKeyEvent,
OH_NativeXComponent_GetKeyEventAction, OH_NativeXComponent_GetKeyEventCode,

View file

@ -14,16 +14,10 @@ use raw_window_handle::{
DisplayHandle, OhosDisplayHandle, OhosNdkWindowHandle, RawDisplayHandle, RawWindowHandle,
WindowHandle,
};
/// The EventLoopWaker::wake function will be called from any thread.
/// It will be called to notify embedder that some events are available,
/// and that perform_updates need to be called
pub use servo::EventLoopWaker;
use servo::{self, Servo, WindowRenderingContext, resources};
use servo::{self, EventLoopWaker, ServoBuilder, WindowRenderingContext, resources};
use xcomponent_sys::OH_NativeXComponent;
use crate::egl::app_state::{
Coordinates, RunningAppState, ServoEmbedderCallbacks, ServoWindowCallbacks,
};
use crate::egl::app_state::{Coordinates, RunningAppState, ServoWindowCallbacks};
use crate::egl::host_trait::HostTrait;
use crate::egl::ohos::InitOpts;
use crate::egl::ohos::resources::ResourceReaderInstance;
@ -128,19 +122,11 @@ pub fn init(
RefCell::new(coordinates),
));
let embedder_callbacks = Box::new(ServoEmbedderCallbacks::new(
waker,
#[cfg(feature = "webxr")]
None,
));
let servo = Servo::new(
opts,
preferences,
rendering_context.clone(),
embedder_callbacks,
Default::default(),
);
let servo = ServoBuilder::new(rendering_context.clone())
.opts(opts)
.preferences(preferences)
.event_loop_waker(waker)
.build();
let app_state = RunningAppState::new(
Some(options.url),