chore: remove WindowMethods::rendering_context (#34780)

* Create Servo without initial webview ID

Signed-off-by: Wu Yuwei <yuweiwu@pm.me>

* Add rendering context in App struct

Signed-off-by: Wu Yuwei <yuweiwu@pm.me>

* Make webview manager optional

Signed-off-by: Wu Yuwei <yuweiwu@pm.me>

* Move window creation to init

Signed-off-by: Wu Yuwei <yuweiwu@pm.me>

* Create window from external rendering context

Signed-off-by: Wu Yuwei <yuweiwu@pm.me>

* Resize surface in compositor

Signed-off-by: Wu Yuwei <yuweiwu@pm.me>

* Obey clippy

Signed-off-by: Wu Yuwei <yuweiwu@pm.me>

* Update Android and OHOS

Signed-off-by: Wu Yuwei <yuweiwu@pm.me>

* Add missing arguent on OHOS

Signed-off-by: Wu Yuwei <yuweiwu@pm.me>

* Show webview after focused on Android and OH

Signed-off-by: Wu Yuwei <yuweiwu@pm.me>

* Remove rendering_context in ServoWindowCallbacks

Signed-off-by: Wu Yuwei <yuweiwu@pm.me>

* Create surface before swapchain in headless mode

Signed-off-by: Wu Yuwei <yuweiwu@pm.me>

---------

Signed-off-by: Wu Yuwei <yuweiwu@pm.me>
This commit is contained in:
Ngo Iok Ui (Wu Yu Wei) 2025-01-01 17:26:23 +09:00 committed by GitHub
parent 59c7ac680e
commit d581acab3b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 200 additions and 253 deletions

View file

@ -363,33 +363,13 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
composite_target: CompositeTarget, composite_target: CompositeTarget,
exit_after_load: bool, exit_after_load: bool,
convert_mouse_to_touch: bool, convert_mouse_to_touch: bool,
top_level_browsing_context_id: TopLevelBrowsingContextId,
version_string: String, version_string: String,
) -> Self { ) -> Self {
let embedder_coordinates = window.get_coordinates();
let mut webviews = WebViewManager::default();
webviews
.add(
top_level_browsing_context_id,
WebView {
pipeline_id: None,
rect: embedder_coordinates.get_viewport().to_f32(),
},
)
.expect("Infallible with a new WebViewManager");
let msg = ConstellationMsg::WebViewOpened(top_level_browsing_context_id);
if let Err(e) = state.constellation_chan.send(msg) {
warn!("Sending event to constellation failed ({:?}).", e);
}
webviews
.show(top_level_browsing_context_id)
.expect("Infallible due to add");
let compositor = IOCompositor { let compositor = IOCompositor {
embedder_coordinates: window.get_coordinates(), embedder_coordinates: window.get_coordinates(),
window, window,
port: state.receiver, port: state.receiver,
webviews, webviews: WebViewManager::default(),
pipeline_details: HashMap::new(), pipeline_details: HashMap::new(),
composition_request: CompositionRequest::NoCompositingNecessary, composition_request: CompositionRequest::NoCompositingNecessary,
touch_handler: TouchHandler::new(), touch_handler: TouchHandler::new(),
@ -1360,7 +1340,11 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
if self.embedder_coordinates.viewport != old_coords.viewport { if self.embedder_coordinates.viewport != old_coords.viewport {
let mut transaction = Transaction::new(); let mut transaction = Transaction::new();
transaction.set_document_view(self.embedder_coordinates.get_viewport()); let size = self.embedder_coordinates.get_viewport();
transaction.set_document_view(size);
if let Err(e) = self.rendering_context.resize(size.size().to_untyped()) {
warn!("Failed to resize surface: {e:?}");
}
self.webrender_api self.webrender_api
.send_transaction(self.webrender_document, transaction); .send_transaction(self.webrender_document, transaction);
} }

View file

@ -23,7 +23,6 @@ use webrender_api::units::{
DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixel, DevicePoint, DeviceRect, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixel, DevicePoint, DeviceRect,
}; };
use webrender_api::ScrollLocation; use webrender_api::ScrollLocation;
use webrender_traits::RenderingContext;
#[derive(Clone)] #[derive(Clone)]
pub enum MouseWindowEvent { pub enum MouseWindowEvent {
@ -218,8 +217,6 @@ pub trait WindowMethods {
/// will want to avoid blocking on UI events, and just /// will want to avoid blocking on UI events, and just
/// run the event loop at the vsync interval. /// run the event loop at the vsync interval.
fn set_animation_state(&self, _state: AnimationState); fn set_animation_state(&self, _state: AnimationState);
/// Get the [`RenderingContext`] of this Window.
fn rendering_context(&self) -> RenderingContext;
} }
pub trait EmbedderMethods { pub trait EmbedderMethods {

View file

@ -219,11 +219,6 @@ impl webrender_api::RenderNotifier for RenderNotifier {
} }
} }
pub struct InitializedServo<Window: WindowMethods + 'static + ?Sized> {
pub servo: Servo<Window>,
pub browser_id: TopLevelBrowsingContextId,
}
impl<Window> Servo<Window> impl<Window> Servo<Window>
where where
Window: WindowMethods + 'static + ?Sized, Window: WindowMethods + 'static + ?Sized,
@ -238,11 +233,12 @@ where
)] )]
#[allow(clippy::new_ret_no_self)] #[allow(clippy::new_ret_no_self)]
pub fn new( pub fn new(
rendering_context: RenderingContext,
mut embedder: Box<dyn EmbedderMethods>, mut embedder: Box<dyn EmbedderMethods>,
window: Rc<Window>, window: Rc<Window>,
user_agent: Option<String>, user_agent: Option<String>,
composite_target: CompositeTarget, composite_target: CompositeTarget,
) -> InitializedServo<Window> { ) -> Servo<Window> {
// Global configuration options, parsed from the command line. // Global configuration options, parsed from the command line.
let opts = opts::get(); let opts = opts::get();
@ -277,9 +273,6 @@ where
.unwrap_or(default_user_agent_string_for(DEFAULT_USER_AGENT).into()), .unwrap_or(default_user_agent_string_for(DEFAULT_USER_AGENT).into()),
}; };
// Initialize surfman
let rendering_context = window.rendering_context();
// Get GL bindings // Get GL bindings
let webrender_gl = match rendering_context.connection().gl_api() { let webrender_gl = match rendering_context.connection().gl_api() {
GLApi::GL => unsafe { gl::GlFns::load_with(|s| rendering_context.get_proc_address(s)) }, GLApi::GL => unsafe { gl::GlFns::load_with(|s| rendering_context.get_proc_address(s)) },
@ -302,7 +295,6 @@ where
// Reserving a namespace to create TopLevelBrowsingContextId. // Reserving a namespace to create TopLevelBrowsingContextId.
PipelineNamespace::install(PipelineNamespaceId(0)); PipelineNamespace::install(PipelineNamespaceId(0));
let top_level_browsing_context_id = TopLevelBrowsingContextId::new();
// Get both endpoints of a special channel for communication between // Get both endpoints of a special channel for communication between
// the client window and the compositor. This channel is unique because // the client window and the compositor. This channel is unique because
@ -525,21 +517,16 @@ where
composite_target, composite_target,
opts.exit_after_load, opts.exit_after_load,
opts.debug.convert_mouse_to_touch, opts.debug.convert_mouse_to_touch,
top_level_browsing_context_id,
embedder.get_version_string().unwrap_or_default(), embedder.get_version_string().unwrap_or_default(),
); );
let servo = Servo { Servo {
compositor, compositor,
constellation_chan, constellation_chan,
embedder_receiver, embedder_receiver,
messages_for_embedder: Vec::new(), messages_for_embedder: Vec::new(),
profiler_enabled: false, profiler_enabled: false,
_js_engine_setup: js_engine_setup, _js_engine_setup: js_engine_setup,
};
InitializedServo {
servo,
browser_id: top_level_browsing_context_id,
} }
} }

View file

@ -282,6 +282,8 @@ thread_local!(pub static TOP_LEVEL_BROWSING_CONTEXT_ID: Cell<Option<TopLevelBrow
Clone, Copy, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize, Clone, Copy, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize,
)] )]
pub struct TopLevelBrowsingContextId(pub BrowsingContextId); pub struct TopLevelBrowsingContextId(pub BrowsingContextId);
/// An alias to ID of top level browsing context. A web view is usually what people would treat as
/// a normal web page.
pub type WebViewId = TopLevelBrowsingContextId; pub type WebViewId = TopLevelBrowsingContextId;
size_of_test!(TopLevelBrowsingContextId, 8); size_of_test!(TopLevelBrowsingContextId, 8);

View file

@ -43,7 +43,7 @@ impl RenderingContext {
pub fn create( pub fn create(
connection: &Connection, connection: &Connection,
adapter: &Adapter, adapter: &Adapter,
surface_type: SurfaceType<NativeWidget>, headless: Option<Size2D<i32>>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let mut device = connection.create_device(adapter)?; let mut device = connection.create_device(adapter)?;
let flags = ContextAttributeFlags::ALPHA | let flags = ContextAttributeFlags::ALPHA |
@ -57,10 +57,8 @@ impl RenderingContext {
let context_descriptor = device.create_context_descriptor(&context_attributes)?; let context_descriptor = device.create_context_descriptor(&context_attributes)?;
let mut context = device.create_context(&context_descriptor, None)?; let mut context = device.create_context(&context_descriptor, None)?;
let surface_access = SurfaceAccess::GPUOnly; let surface_access = SurfaceAccess::GPUOnly;
let headless = match surface_type { let swap_chain = if let Some(size) = headless {
SurfaceType::Widget { .. } => false, let surface_type = SurfaceType::Generic { size };
SurfaceType::Generic { .. } => true,
};
let surface = device.create_surface(&context, surface_access, surface_type)?; let surface = device.create_surface(&context, surface_access, surface_type)?;
device device
.bind_surface_to_context(&mut context, surface) .bind_surface_to_context(&mut context, surface)
@ -68,10 +66,7 @@ impl RenderingContext {
let _ = device.destroy_surface(&mut context, &mut surface); let _ = device.destroy_surface(&mut context, &mut surface);
err err
})?; })?;
device.make_context_current(&context)?; device.make_context_current(&context)?;
let swap_chain = if headless {
Some(SwapChain::create_attached( Some(SwapChain::create_attached(
&mut device, &mut device,
&mut context, &mut context,
@ -100,6 +95,20 @@ impl RenderingContext {
device.create_surface(context, surface_access, surface_type) device.create_surface(context, surface_access, surface_type)
} }
pub fn bind_surface(&self, surface: Surface) -> Result<(), Error> {
let device = &self.0.device.borrow();
let context = &mut self.0.context.borrow_mut();
device
.bind_surface_to_context(context, surface)
.map_err(|(err, mut surface)| {
let _ = device.destroy_surface(context, &mut surface);
err
})?;
device.make_context_current(context)?;
Ok(())
}
pub fn destroy_surface(&self, mut surface: Surface) -> Result<(), Error> { pub fn destroy_surface(&self, mut surface: Surface) -> Result<(), Error> {
let device = &self.0.device.borrow(); let device = &self.0.device.borrow();
let context = &mut self.0.context.borrow_mut(); let context = &mut self.0.context.borrow_mut();

View file

@ -4,22 +4,24 @@
//! Application entry point, runs the event loop. //! Application entry point, runs the event loop.
use std::cell::{Cell, RefCell, RefMut}; use std::cell::Cell;
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
use std::time::Instant; use std::time::Instant;
use std::{env, fs}; use std::{env, fs};
use gleam::gl; use log::{info, trace};
use log::{error, info, trace}; use raw_window_handle::HasDisplayHandle;
use servo::base::id::WebViewId;
use servo::compositing::windowing::EmbedderEvent; use servo::compositing::windowing::EmbedderEvent;
use servo::compositing::CompositeTarget; use servo::compositing::CompositeTarget;
use servo::config::opts; use servo::config::opts;
use servo::embedder_traits::EventLoopWaker; use servo::embedder_traits::EventLoopWaker;
use servo::servo_config::pref; use servo::servo_config::pref;
use servo::url::ServoUrl; use servo::url::ServoUrl;
use servo::webrender_traits::RenderingContext;
use servo::Servo; use servo::Servo;
use surfman::GLApi; use surfman::Connection;
use webxr::glwindow::GlWindowDiscovery; use webxr::glwindow::GlWindowDiscovery;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use webxr::openxr::{AppInfo, OpenXrDiscovery}; use webxr::openxr::{AppInfo, OpenXrDiscovery};
@ -31,6 +33,7 @@ use winit::window::WindowId;
use super::events_loop::{EventLoopGuard, EventsLoop, WakerEvent}; use super::events_loop::{EventLoopGuard, EventsLoop, WakerEvent};
use super::minibrowser::Minibrowser; use super::minibrowser::Minibrowser;
use super::webview::WebViewManager; use super::webview::WebViewManager;
use super::{headed_window, headless_window};
use crate::desktop::embedder::{EmbedderCallbacks, XrDiscovery}; use crate::desktop::embedder::{EmbedderCallbacks, XrDiscovery};
use crate::desktop::events_loop::with_current_event_loop; use crate::desktop::events_loop::with_current_event_loop;
use crate::desktop::tracing::trace_winit_event; use crate::desktop::tracing::trace_winit_event;
@ -39,16 +42,18 @@ use crate::parser::get_default_url;
pub struct App { pub struct App {
servo: Option<Servo<dyn WindowPortsMethods>>, servo: Option<Servo<dyn WindowPortsMethods>>,
webviews: RefCell<WebViewManager<dyn WindowPortsMethods>>, webviews: Option<WebViewManager<dyn WindowPortsMethods>>,
event_queue: RefCell<Vec<EmbedderEvent>>, event_queue: Vec<EmbedderEvent>,
suspended: Cell<bool>, suspended: Cell<bool>,
windows: HashMap<WindowId, Rc<dyn WindowPortsMethods>>, windows: HashMap<WindowId, Rc<dyn WindowPortsMethods>>,
minibrowser: Option<RefCell<Minibrowser>>, minibrowser: Option<Minibrowser>,
user_agent: Option<String>, user_agent: Option<String>,
waker: Box<dyn EventLoopWaker>, waker: Box<dyn EventLoopWaker>,
initial_url: ServoUrl, initial_url: ServoUrl,
t_start: Instant, t_start: Instant,
t: Instant, t: Instant,
do_not_use_native_titlebar: bool,
device_pixel_ratio_override: Option<f32>,
} }
enum Present { enum Present {
@ -70,19 +75,19 @@ enum PumpResult {
impl App { impl App {
pub fn new( pub fn new(
events_loop: &EventsLoop, events_loop: &EventsLoop,
window: Rc<dyn WindowPortsMethods>,
user_agent: Option<String>, user_agent: Option<String>,
url: Option<String>, url: Option<String>,
do_not_use_native_titlebar: bool,
device_pixel_ratio_override: Option<f32>,
) -> Self { ) -> Self {
// Handle browser state. // Handle browser state.
let webviews = WebViewManager::new(window.clone());
let initial_url = get_default_url(url.as_deref(), env::current_dir().unwrap(), |path| { let initial_url = get_default_url(url.as_deref(), env::current_dir().unwrap(), |path| {
fs::metadata(path).is_ok() fs::metadata(path).is_ok()
}); });
let t = Instant::now(); let t = Instant::now();
let mut app = App { App {
event_queue: RefCell::new(vec![]), event_queue: vec![],
webviews: RefCell::new(webviews), webviews: None,
servo: None, servo: None,
suspended: Cell::new(false), suspended: Cell::new(false),
windows: HashMap::new(), windows: HashMap::new(),
@ -92,54 +97,80 @@ impl App {
initial_url: initial_url.clone(), initial_url: initial_url.clone(),
t_start: t, t_start: t,
t, t,
}; do_not_use_native_titlebar,
device_pixel_ratio_override,
if window.winit_window().is_some() { }
// Make sure the gl context is made current.
let rendering_context = window.rendering_context();
let webrender_gl = match rendering_context.connection().gl_api() {
GLApi::GL => unsafe {
gl::GlFns::load_with(|s| rendering_context.get_proc_address(s))
},
GLApi::GLES => unsafe {
gl::GlesFns::load_with(|s| rendering_context.get_proc_address(s))
},
};
rendering_context.make_gl_context_current().unwrap();
debug_assert_eq!(webrender_gl.get_error(), gleam::gl::NO_ERROR);
app.minibrowser = Some(
Minibrowser::new(
&rendering_context,
events_loop.as_winit(),
initial_url.clone(),
)
.into(),
);
} }
if let Some(mut minibrowser) = app.minibrowser() { /// Initialize Application once event loop start running.
pub fn init(&mut self, event_loop: Option<&ActiveEventLoop>) {
// Create rendering context
let rendering_context = if opts::get().headless {
let connection = Connection::new().expect("Failed to create connection");
let adapter = connection
.create_software_adapter()
.expect("Failed to create adapter");
RenderingContext::create(
&connection,
&adapter,
Some(opts::get().initial_window_size.to_untyped().to_i32()),
)
.expect("Failed to create WR surfman")
} else {
let display_handle = event_loop
.unwrap()
.display_handle()
.expect("could not get display handle from window");
let connection = Connection::from_display_handle(display_handle)
.expect("Failed to create connection");
let adapter = connection
.create_adapter()
.expect("Failed to create adapter");
RenderingContext::create(&connection, &adapter, None)
.expect("Failed to create WR surfman")
};
let window = if opts::get().headless {
headless_window::Window::new(
opts::get().initial_window_size,
self.device_pixel_ratio_override,
)
} else {
Rc::new(headed_window::Window::new(
&rendering_context,
opts::get().initial_window_size,
event_loop.unwrap(),
self.do_not_use_native_titlebar,
self.device_pixel_ratio_override,
))
};
// Create window's context
self.webviews = Some(WebViewManager::new(window.clone()));
if window.winit_window().is_some() {
self.minibrowser = Some(Minibrowser::new(
&rendering_context,
event_loop.unwrap(),
self.initial_url.clone(),
));
}
if let Some(ref mut minibrowser) = self.minibrowser {
// Servo is not yet initialised, so there is no `servo_framebuffer_id`. // Servo is not yet initialised, so there is no `servo_framebuffer_id`.
minibrowser.update( minibrowser.update(
window.winit_window().unwrap(), window.winit_window().unwrap(),
&mut app.webviews.borrow_mut(), self.webviews.as_mut().unwrap(),
None, None,
"init", "init",
); );
window.set_toolbar_height(minibrowser.toolbar_height); window.set_toolbar_height(minibrowser.toolbar_height);
} }
app.windows.insert(window.id(), window); self.windows.insert(window.id(), window);
app
}
/// Initialize Application once event loop start running.
pub fn init(&mut self) {
self.suspended.set(false); self.suspended.set(false);
self.event_queue.borrow_mut().push(EmbedderEvent::Idle); self.event_queue.push(EmbedderEvent::Idle);
let (_, window) = self.windows.iter().next().unwrap(); let (_, window) = self.windows.iter().next().unwrap();
let surfman = window.rendering_context();
let openxr_discovery = if pref!(dom.webxr.openxr.enabled) && !opts::get().headless { let openxr_discovery = if pref!(dom.webxr.openxr.enabled) && !opts::get().headless {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
@ -162,9 +193,9 @@ impl App {
.expect("An event loop should always be active in headed mode") .expect("An event loop should always be active in headed mode")
}); });
Some(XrDiscovery::GlWindow(GlWindowDiscovery::new( Some(XrDiscovery::GlWindow(GlWindowDiscovery::new(
surfman.connection(), rendering_context.connection(),
surfman.adapter(), rendering_context.adapter(),
surfman.context_attributes(), rendering_context.context_attributes(),
factory, factory,
))) )))
} else { } else {
@ -182,17 +213,17 @@ impl App {
} else { } else {
CompositeTarget::Window CompositeTarget::Window
}; };
let servo_data = Servo::new( let mut servo = Servo::new(
rendering_context,
embedder, embedder,
window.clone(), window.clone(),
self.user_agent.clone(), self.user_agent.clone(),
composite_target, composite_target,
); );
let mut servo = servo_data.servo;
servo.handle_events(vec![EmbedderEvent::NewWebView( servo.handle_events(vec![EmbedderEvent::NewWebView(
self.initial_url.to_owned(), self.initial_url.to_owned(),
servo_data.browser_id, WebViewId::new(),
)]); )]);
servo.setup_logging(); servo.setup_logging();
@ -203,8 +234,8 @@ impl App {
self.windows.iter().any(|(_, window)| window.is_animating()) self.windows.iter().any(|(_, window)| window.is_animating())
} }
fn get_events(&self) -> Vec<EmbedderEvent> { fn get_events(&mut self) -> Vec<EmbedderEvent> {
std::mem::take(&mut *self.event_queue.borrow_mut()) std::mem::take(&mut self.event_queue)
} }
/// Pumps events and messages between the embedder and Servo, where embedder events flow /// Pumps events and messages between the embedder and Servo, where embedder events flow
@ -215,10 +246,10 @@ impl App {
/// receive and collect embedder messages from the various Servo components, then take them out /// receive and collect embedder messages from the various Servo components, then take them out
/// of the Servo interface so that the WebViewManager can handle them. /// of the Servo interface so that the WebViewManager can handle them.
fn handle_events(&mut self) -> PumpResult { fn handle_events(&mut self) -> PumpResult {
let mut webviews = self.webviews.borrow_mut(); let mut embedder_events = self.get_events();
let webviews = self.webviews.as_mut().unwrap();
// Take any outstanding embedder events from the App and its Windows. // Take any outstanding embedder events from the App and its Windows.
let mut embedder_events = self.get_events();
for window in self.windows.values() { for window in self.windows.values() {
embedder_events.extend(window.get_events()); embedder_events.extend(window.get_events());
} }
@ -285,21 +316,15 @@ impl App {
match self.handle_events() { match self.handle_events() {
PumpResult::Shutdown => { PumpResult::Shutdown => {
event_loop.exit(); event_loop.exit();
if let Err(e) = window
.rendering_context()
.unbind_native_surface_from_context()
{
error!("Failed to unbind native surface: {e:?}");
}
self.servo.take().unwrap().deinit(); self.servo.take().unwrap().deinit();
if let Some(mut minibrowser) = self.minibrowser() { if let Some(ref mut minibrowser) = self.minibrowser {
minibrowser.context.destroy(); minibrowser.context.destroy();
} }
}, },
PumpResult::Continue { update, present } => { PumpResult::Continue { update, present } => {
if update { if update {
if let Some(mut minibrowser) = self.minibrowser() { if let Some(ref mut minibrowser) = self.minibrowser {
let webviews = &mut self.webviews.borrow_mut(); let webviews = self.webviews.as_mut().unwrap();
if minibrowser.update_webview_data(webviews) { if minibrowser.update_webview_data(webviews) {
// Update the minibrowser immediately. While we could update by requesting a // Update the minibrowser immediately. While we could update by requesting a
// redraw, doing so would delay the location update by two frames. // redraw, doing so would delay the location update by two frames.
@ -320,10 +345,10 @@ impl App {
// If we had resized any of the viewports in response to this, we would need to // If we had resized any of the viewports in response to this, we would need to
// call Servo::repaint_synchronously. At the moment we dont, so there wont be // call Servo::repaint_synchronously. At the moment we dont, so there wont be
// any paint scheduled, and calling it would hang the compositor forever. // any paint scheduled, and calling it would hang the compositor forever.
if let Some(mut minibrowser) = self.minibrowser() { if let Some(ref mut minibrowser) = self.minibrowser {
minibrowser.update( minibrowser.update(
window.winit_window().unwrap(), window.winit_window().unwrap(),
&mut self.webviews.borrow_mut(), self.webviews.as_mut().unwrap(),
self.servo.as_ref().unwrap().offscreen_framebuffer_id(), self.servo.as_ref().unwrap().offscreen_framebuffer_id(),
"PumpResult::Present::Immediate", "PumpResult::Present::Immediate",
); );
@ -364,14 +389,14 @@ impl App {
if self.servo.is_none() { if self.servo.is_none() {
return false; return false;
} }
self.event_queue.borrow_mut().push(EmbedderEvent::Idle); self.event_queue.push(EmbedderEvent::Idle);
let mut exit = false; let mut exit = false;
match self.handle_events() { match self.handle_events() {
PumpResult::Shutdown => { PumpResult::Shutdown => {
exit = true; exit = true;
self.servo.take().unwrap().deinit(); self.servo.take().unwrap().deinit();
if let Some(mut minibrowser) = self.minibrowser() { if let Some(ref mut minibrowser) = self.minibrowser {
minibrowser.context.destroy(); minibrowser.context.destroy();
} }
}, },
@ -394,16 +419,12 @@ impl App {
} }
exit exit
} }
fn minibrowser(&self) -> Option<RefMut<Minibrowser>> {
self.minibrowser.as_ref().map(|x| x.borrow_mut())
}
} }
impl ApplicationHandler<WakerEvent> for App { impl ApplicationHandler<WakerEvent> for App {
fn resumed(&mut self, event_loop: &ActiveEventLoop) { fn resumed(&mut self, event_loop: &ActiveEventLoop) {
let _guard = EventLoopGuard::new(event_loop); let _guard = EventLoopGuard::new(event_loop);
self.init(); self.init(Some(event_loop));
} }
fn window_event( fn window_event(
@ -437,10 +458,10 @@ impl ApplicationHandler<WakerEvent> for App {
// WARNING: do not defer painting or presenting to some later tick of the event // WARNING: do not defer painting or presenting to some later tick of the event
// loop or servoshell may become unresponsive! (servo#30312) // loop or servoshell may become unresponsive! (servo#30312)
if let Some(mut minibrowser) = self.minibrowser() { if let Some(ref mut minibrowser) = self.minibrowser {
minibrowser.update( minibrowser.update(
window.winit_window().unwrap(), window.winit_window().unwrap(),
&mut self.webviews.borrow_mut(), self.webviews.as_mut().unwrap(),
self.servo.as_ref().unwrap().offscreen_framebuffer_id(), self.servo.as_ref().unwrap().offscreen_framebuffer_id(),
"RedrawRequested", "RedrawRequested",
); );
@ -452,7 +473,7 @@ impl ApplicationHandler<WakerEvent> for App {
// Handle the event // Handle the event
let mut consumed = false; let mut consumed = false;
if let Some(mut minibrowser) = self.minibrowser() { if let Some(ref mut minibrowser) = self.minibrowser {
match event { match event {
WindowEvent::ScaleFactorChanged { scale_factor, .. } => { WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
// Intercept any ScaleFactorChanged events away from EguiGlow::on_window_event, so // Intercept any ScaleFactorChanged events away from EguiGlow::on_window_event, so
@ -482,7 +503,7 @@ impl ApplicationHandler<WakerEvent> for App {
if let WindowEvent::Resized(_) = event { if let WindowEvent::Resized(_) = event {
minibrowser.update( minibrowser.update(
window.winit_window().unwrap(), window.winit_window().unwrap(),
&mut self.webviews.borrow_mut(), self.webviews.as_mut().unwrap(),
self.servo.as_ref().unwrap().offscreen_framebuffer_id(), self.servo.as_ref().unwrap().offscreen_framebuffer_id(),
"Sync WebView size with Window Resize event", "Sync WebView size with Window Resize event",
); );
@ -501,7 +522,7 @@ impl ApplicationHandler<WakerEvent> for App {
} }
if !consumed { if !consumed {
if event == winit::event::WindowEvent::RedrawRequested { if event == winit::event::WindowEvent::RedrawRequested {
self.event_queue.borrow_mut().push(EmbedderEvent::Idle); self.event_queue.push(EmbedderEvent::Idle);
} }
window.queue_embedder_events_for_winit_event(event); window.queue_embedder_events_for_winit_event(event);
@ -517,9 +538,9 @@ impl ApplicationHandler<WakerEvent> for App {
} }
// Consume and handle any events from the Minibrowser. // Consume and handle any events from the Minibrowser.
if let Some(minibrowser) = self.minibrowser() { if let Some(ref minibrowser) = self.minibrowser {
let webviews = &mut self.webviews.borrow_mut(); let webviews = &mut self.webviews.as_mut().unwrap();
let app_event_queue = &mut self.event_queue.borrow_mut(); let app_event_queue = &mut self.event_queue;
minibrowser.queue_embedder_events_for_minibrowser_events(webviews, app_event_queue); minibrowser.queue_embedder_events_for_minibrowser_events(webviews, app_event_queue);
} }
@ -541,7 +562,7 @@ impl ApplicationHandler<WakerEvent> for App {
if self.servo.is_none() { if self.servo.is_none() {
return; return;
} }
self.event_queue.borrow_mut().push(EmbedderEvent::Idle); self.event_queue.push(EmbedderEvent::Idle);
let Some(window) = self.windows.values().next() else { let Some(window) = self.windows.values().next() else {
return; return;
@ -558,9 +579,9 @@ impl ApplicationHandler<WakerEvent> for App {
} }
// Consume and handle any events from the Minibrowser. // Consume and handle any events from the Minibrowser.
if let Some(minibrowser) = self.minibrowser() { if let Some(ref minibrowser) = self.minibrowser {
let webviews = &mut self.webviews.borrow_mut(); let webviews = &mut self.webviews.as_mut().unwrap();
let app_event_queue = &mut self.event_queue.borrow_mut(); let app_event_queue = &mut self.event_queue;
minibrowser.queue_embedder_events_for_minibrowser_events(webviews, app_event_queue); minibrowser.queue_embedder_events_for_minibrowser_events(webviews, app_event_queue);
} }

View file

@ -2,18 +2,15 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::rc::Rc;
use std::{env, panic, process}; use std::{env, panic, process};
use getopts::Options; use getopts::Options;
use log::{error, warn}; use log::error;
use servo::config::opts::{self, ArgumentParsingResult}; use servo::config::opts::{self, ArgumentParsingResult};
use servo::config::set_pref;
use servo::servo_config::pref; use servo::servo_config::pref;
use crate::desktop::app::App; use crate::desktop::app::App;
use crate::desktop::events_loop::EventsLoop; use crate::desktop::events_loop::EventsLoop;
use crate::desktop::{headed_window, headless_window};
use crate::panic_hook; use crate::panic_hook;
pub fn main() { pub fn main() {
@ -106,29 +103,12 @@ pub fn main() {
let event_loop = EventsLoop::new(opts::get().headless, opts::get().output_file.is_some()) let event_loop = EventsLoop::new(opts::get().headless, opts::get().output_file.is_some())
.expect("Failed to create events loop"); .expect("Failed to create events loop");
// Implements window methods, used by compositor.
// FIXME: We keep the window until application exits. Otherwise, it will cause
// simthay-clipboard thread segfault on Wayland.
let window = if opts::get().headless {
if pref!(media.glvideo.enabled) {
warn!("GL video rendering is not supported on headless windows.");
set_pref!(media.glvideo.enabled, false);
}
headless_window::Window::new(opts::get().initial_window_size, device_pixel_ratio_override)
} else {
Rc::new(headed_window::Window::new(
opts::get().initial_window_size,
event_loop.as_winit(),
do_not_use_native_titlebar,
device_pixel_ratio_override,
))
};
let mut app = App::new( let mut app = App::new(
&event_loop, &event_loop,
window.clone(),
user_agent, user_agent,
url_opt.map(|s| s.to_string()), url_opt.map(|s| s.to_string()),
do_not_use_native_titlebar,
device_pixel_ratio_override,
); );
event_loop.run_app(&mut app); event_loop.run_app(&mut app);

View file

@ -38,6 +38,7 @@ use egui_glow::ShaderVersion;
pub use egui_winit; pub use egui_winit;
use egui_winit::winit; use egui_winit::winit;
pub use egui_winit::EventResponse; pub use egui_winit::EventResponse;
use winit::event_loop::ActiveEventLoop;
/// Use [`egui`] from a [`glow`] app based on [`winit`]. /// Use [`egui`] from a [`glow`] app based on [`winit`].
pub struct EguiGlow { pub struct EguiGlow {
@ -52,7 +53,7 @@ pub struct EguiGlow {
impl EguiGlow { impl EguiGlow {
/// For automatic shader version detection set `shader_version` to `None`. /// For automatic shader version detection set `shader_version` to `None`.
pub fn new( pub fn new(
event_loop: &winit::event_loop::EventLoop<super::events_loop::WakerEvent>, event_loop: &ActiveEventLoop,
gl: std::sync::Arc<glow::Context>, gl: std::sync::Arc<glow::Context>,
shader_version: Option<ShaderVersion>, shader_version: Option<ShaderVersion>,
) -> Self { ) -> Self {

View file

@ -9,6 +9,7 @@ use std::sync::{Arc, Condvar, Mutex};
use std::time; use std::time;
use log::warn; use log::warn;
use servo::config::{pref, set_pref};
use servo::embedder_traits::EventLoopWaker; use servo::embedder_traits::EventLoopWaker;
use winit::error::EventLoopError; use winit::error::EventLoopError;
use winit::event_loop::{ActiveEventLoop, EventLoop as WinitEventLoop}; use winit::event_loop::{ActiveEventLoop, EventLoop as WinitEventLoop};
@ -79,14 +80,7 @@ impl EventsLoop {
EventLoop::Headless(ref data) => Box::new(HeadlessEventLoopWaker(data.clone())), EventLoop::Headless(ref data) => Box::new(HeadlessEventLoopWaker(data.clone())),
} }
} }
pub fn as_winit(&self) -> &WinitEventLoop<WakerEvent> {
match self.0 {
EventLoop::Winit(Some(ref event_loop)) => event_loop,
EventLoop::Winit(None) | EventLoop::Headless(..) => {
panic!("Can't access winit event loop while using the fake headless event loop")
},
}
}
pub fn run_app(self, app: &mut App) { pub fn run_app(self, app: &mut App) {
match self.0 { match self.0 {
EventLoop::Winit(events_loop) => { EventLoop::Winit(events_loop) => {
@ -97,7 +91,12 @@ impl EventsLoop {
}, },
EventLoop::Headless(ref data) => { EventLoop::Headless(ref data) => {
let (flag, condvar) = &**data; let (flag, condvar) = &**data;
app.init(); if pref!(media.glvideo.enabled) {
warn!("GL video rendering is not supported on headless windows.");
set_pref!(media.glvideo.enabled, false);
}
app.init(None);
loop { loop {
self.sleep(flag, condvar); self.sleep(flag, condvar);
if app.handle_events_with_headless() { if app.handle_events_with_headless() {

View file

@ -10,7 +10,7 @@ use std::rc::Rc;
use euclid::{Angle, Length, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector2D, Vector3D}; use euclid::{Angle, Length, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector2D, Vector3D};
use log::{debug, info, trace}; use log::{debug, info, trace};
use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use raw_window_handle::HasWindowHandle;
use servo::compositing::windowing::{ use servo::compositing::windowing::{
AnimationState, EmbedderCoordinates, EmbedderEvent, MouseWindowEvent, WindowMethods, AnimationState, EmbedderCoordinates, EmbedderEvent, MouseWindowEvent, WindowMethods,
}; };
@ -22,21 +22,20 @@ use servo::servo_geometry::DeviceIndependentPixel;
use servo::webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixel}; use servo::webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixel};
use servo::webrender_api::ScrollLocation; use servo::webrender_api::ScrollLocation;
use servo::webrender_traits::RenderingContext; use servo::webrender_traits::RenderingContext;
use surfman::{Connection, Context, Device, SurfaceType}; use surfman::{Context, Device, SurfaceType};
use winit::dpi::{LogicalSize, PhysicalPosition, PhysicalSize}; use winit::dpi::{LogicalSize, PhysicalPosition, PhysicalSize};
use winit::event::{ElementState, KeyEvent, MouseButton, MouseScrollDelta, TouchPhase}; use winit::event::{ElementState, KeyEvent, MouseButton, MouseScrollDelta, TouchPhase};
use winit::event_loop::ActiveEventLoop;
use winit::keyboard::{Key as LogicalKey, ModifiersState, NamedKey}; use winit::keyboard::{Key as LogicalKey, ModifiersState, NamedKey};
#[cfg(any(target_os = "linux", target_os = "windows"))] #[cfg(any(target_os = "linux", target_os = "windows"))]
use winit::window::Icon; use winit::window::Icon;
use super::events_loop::WakerEvent;
use super::geometry::{winit_position_to_euclid_point, winit_size_to_euclid_size}; use super::geometry::{winit_position_to_euclid_point, winit_size_to_euclid_size};
use super::keyutils::keyboard_event_from_winit; use super::keyutils::keyboard_event_from_winit;
use super::window_trait::{WindowPortsMethods, LINE_HEIGHT}; use super::window_trait::{WindowPortsMethods, LINE_HEIGHT};
pub struct Window { pub struct Window {
winit_window: winit::window::Window, winit_window: winit::window::Window,
rendering_context: RenderingContext,
screen_size: Size2D<u32, DeviceIndependentPixel>, screen_size: Size2D<u32, DeviceIndependentPixel>,
inner_size: Cell<PhysicalSize<u32>>, inner_size: Cell<PhysicalSize<u32>>,
toolbar_height: Cell<Length<f32, DeviceIndependentPixel>>, toolbar_height: Cell<Length<f32, DeviceIndependentPixel>>,
@ -58,8 +57,9 @@ pub struct Window {
impl Window { impl Window {
pub fn new( pub fn new(
rendering_context: &RenderingContext,
window_size: Size2D<u32, DeviceIndependentPixel>, window_size: Size2D<u32, DeviceIndependentPixel>,
event_loop: &winit::event_loop::EventLoop<WakerEvent>, event_loop: &ActiveEventLoop,
no_native_titlebar: bool, no_native_titlebar: bool,
device_pixel_ratio_override: Option<f32>, device_pixel_ratio_override: Option<f32>,
) -> Window { ) -> Window {
@ -103,20 +103,13 @@ impl Window {
let screen_size = (winit_size_to_euclid_size(screen_size).to_f64() / screen_scale).to_u32(); let screen_size = (winit_size_to_euclid_size(screen_size).to_f64() / screen_scale).to_u32();
// Initialize surfman // Initialize surfman
let display_handle = winit_window
.display_handle()
.expect("could not get display handle from window");
let connection =
Connection::from_display_handle(display_handle).expect("Failed to create connection");
let adapter = connection
.create_adapter()
.expect("Failed to create adapter");
let window_handle = winit_window let window_handle = winit_window
.window_handle() .window_handle()
.expect("could not get window handle from window"); .expect("could not get window handle from window");
let inner_size = winit_window.inner_size(); let inner_size = winit_window.inner_size();
let native_widget = connection let native_widget = rendering_context
.connection()
.create_native_widget_from_window_handle( .create_native_widget_from_window_handle(
window_handle, window_handle,
winit_size_to_euclid_size(inner_size).to_i32().to_untyped(), winit_size_to_euclid_size(inner_size).to_i32().to_untyped(),
@ -124,13 +117,18 @@ impl Window {
.expect("Failed to create native widget"); .expect("Failed to create native widget");
let surface_type = SurfaceType::Widget { native_widget }; let surface_type = SurfaceType::Widget { native_widget };
let rendering_context = RenderingContext::create(&connection, &adapter, surface_type) let surface = rendering_context
.expect("Failed to create WR surfman"); .create_surface(surface_type)
.expect("Failed to create surface");
rendering_context
.bind_surface(surface)
.expect("Failed to bind surface");
// Make sure the gl context is made current.
rendering_context.make_gl_context_current().unwrap();
debug!("Created window {:?}", winit_window.id()); debug!("Created window {:?}", winit_window.id());
Window { Window {
winit_window, winit_window,
rendering_context,
event_queue: RefCell::new(vec![]), event_queue: RefCell::new(vec![]),
mouse_down_button: Cell::new(None), mouse_down_button: Cell::new(None),
mouse_down_point: Cell::new(Point2D::zero()), mouse_down_point: Cell::new(Point2D::zero()),
@ -478,9 +476,6 @@ impl WindowPortsMethods for Window {
}, },
winit::event::WindowEvent::Resized(new_size) => { winit::event::WindowEvent::Resized(new_size) => {
if self.inner_size.get() != new_size { if self.inner_size.get() != new_size {
self.rendering_context
.resize(Size2D::new(new_size.width, new_size.height).to_i32())
.expect("Failed to resize");
self.inner_size.set(new_size); self.inner_size.set(new_size);
self.event_queue self.event_queue
.borrow_mut() .borrow_mut()
@ -565,10 +560,6 @@ impl WindowMethods for Window {
fn set_animation_state(&self, state: AnimationState) { fn set_animation_state(&self, state: AnimationState) {
self.animation_state.set(state); self.animation_state.set(state);
} }
fn rendering_context(&self) -> RenderingContext {
self.rendering_context.clone()
}
} }
fn winit_phase_to_touch_event_type(phase: TouchPhase) -> TouchEventType { fn winit_phase_to_touch_event_type(phase: TouchPhase) -> TouchEventType {

View file

@ -10,20 +10,17 @@ use std::sync::RwLock;
use euclid::num::Zero; use euclid::num::Zero;
use euclid::{Box2D, Length, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector3D}; use euclid::{Box2D, Length, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector3D};
use log::warn;
use servo::compositing::windowing::{ use servo::compositing::windowing::{
AnimationState, EmbedderCoordinates, EmbedderEvent, WindowMethods, AnimationState, EmbedderCoordinates, EmbedderEvent, WindowMethods,
}; };
use servo::config::opts; use servo::config::opts;
use servo::servo_geometry::DeviceIndependentPixel; use servo::servo_geometry::DeviceIndependentPixel;
use servo::webrender_api::units::{DeviceIntSize, DevicePixel}; use servo::webrender_api::units::{DeviceIntSize, DevicePixel};
use servo::webrender_traits::RenderingContext; use surfman::{Context, Device};
use surfman::{Connection, Context, Device, SurfaceType};
use crate::desktop::window_trait::WindowPortsMethods; use crate::desktop::window_trait::WindowPortsMethods;
pub struct Window { pub struct Window {
rendering_context: RenderingContext,
animation_state: Cell<AnimationState>, animation_state: Cell<AnimationState>,
fullscreen: Cell<bool>, fullscreen: Cell<bool>,
device_pixel_ratio_override: Option<Scale<f32, DeviceIndependentPixel, DevicePixel>>, device_pixel_ratio_override: Option<Scale<f32, DeviceIndependentPixel, DevicePixel>>,
@ -39,17 +36,6 @@ impl Window {
size: Size2D<u32, DeviceIndependentPixel>, size: Size2D<u32, DeviceIndependentPixel>,
device_pixel_ratio_override: Option<f32>, device_pixel_ratio_override: Option<f32>,
) -> Rc<dyn WindowPortsMethods> { ) -> Rc<dyn WindowPortsMethods> {
// Initialize surfman
let connection = Connection::new().expect("Failed to create connection");
let adapter = connection
.create_software_adapter()
.expect("Failed to create adapter");
let surface_type = SurfaceType::Generic {
size: size.to_untyped().to_i32(),
};
let rendering_context = RenderingContext::create(&connection, &adapter, surface_type)
.expect("Failed to create WR surfman");
let device_pixel_ratio_override: Option<Scale<f32, DeviceIndependentPixel, DevicePixel>> = let device_pixel_ratio_override: Option<Scale<f32, DeviceIndependentPixel, DevicePixel>> =
device_pixel_ratio_override.map(Scale::new); device_pixel_ratio_override.map(Scale::new);
let hidpi_factor = device_pixel_ratio_override.unwrap_or_else(Scale::identity); let hidpi_factor = device_pixel_ratio_override.unwrap_or_else(Scale::identity);
@ -64,7 +50,6 @@ impl Window {
); );
let window = Window { let window = Window {
rendering_context,
animation_state: Cell::new(AnimationState::Idle), animation_state: Cell::new(AnimationState::Idle),
fullscreen: Cell::new(false), fullscreen: Cell::new(false),
device_pixel_ratio_override, device_pixel_ratio_override,
@ -97,19 +82,11 @@ impl WindowPortsMethods for Window {
return Some(new_size); return Some(new_size);
} }
match self.rendering_context.resize(new_size.to_untyped()) {
Ok(()) => {
self.inner_size.set(new_size); self.inner_size.set(new_size);
if let Ok(ref mut queue) = self.event_queue.write() { if let Ok(ref mut queue) = self.event_queue.write() {
queue.push(EmbedderEvent::WindowResize); queue.push(EmbedderEvent::WindowResize);
} }
Some(new_size) Some(new_size)
},
Err(error) => {
warn!("Could not resize window: {error:?}");
None
},
}
} }
fn device_hidpi_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> { fn device_hidpi_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> {
@ -123,12 +100,7 @@ impl WindowPortsMethods for Window {
} }
fn page_height(&self) -> f32 { fn page_height(&self) -> f32 {
let height = self let height = self.inner_size.get().height;
.rendering_context
.context_surface_info()
.unwrap_or(None)
.map(|info| info.size.height)
.unwrap_or(0);
let dpr = self.hidpi_factor(); let dpr = self.hidpi_factor();
height as f32 * dpr.get() height as f32 * dpr.get()
} }
@ -185,10 +157,6 @@ impl WindowMethods for Window {
fn set_animation_state(&self, state: AnimationState) { fn set_animation_state(&self, state: AnimationState) {
self.animation_state.set(state); self.animation_state.set(state);
} }
fn rendering_context(&self) -> RenderingContext {
self.rendering_context.clone()
}
} }
impl webxr::glwindow::GlWindow for Window { impl webxr::glwindow::GlWindow for Window {

View file

@ -28,11 +28,10 @@ use servo::webrender_api::units::DevicePixel;
use servo::webrender_traits::RenderingContext; use servo::webrender_traits::RenderingContext;
use servo::TopLevelBrowsingContextId; use servo::TopLevelBrowsingContextId;
use winit::event::{ElementState, MouseButton, WindowEvent}; use winit::event::{ElementState, MouseButton, WindowEvent};
use winit::event_loop::EventLoop; use winit::event_loop::ActiveEventLoop;
use winit::window::Window; use winit::window::Window;
use super::egui_glue::EguiGlow; use super::egui_glue::EguiGlow;
use super::events_loop::WakerEvent;
use super::geometry::winit_position_to_euclid_point; use super::geometry::winit_position_to_euclid_point;
use super::webview::{LoadStatus, WebViewManager}; use super::webview::{LoadStatus, WebViewManager};
use super::window_trait::WindowPortsMethods; use super::window_trait::WindowPortsMethods;
@ -80,7 +79,7 @@ fn truncate_with_ellipsis(input: &str, max_length: usize) -> String {
impl Minibrowser { impl Minibrowser {
pub fn new( pub fn new(
rendering_context: &RenderingContext, rendering_context: &RenderingContext,
event_loop: &EventLoop<WakerEvent>, event_loop: &ActiveEventLoop,
initial_url: ServoUrl, initial_url: ServoUrl,
) -> Self { ) -> Self {
let gl = unsafe { let gl = unsafe {

View file

@ -9,6 +9,7 @@ use std::os::raw::c_void;
use std::rc::Rc; use std::rc::Rc;
use getopts::Options; use getopts::Options;
use servo::base::id::WebViewId;
use servo::compositing::windowing::EmbedderEvent; use servo::compositing::windowing::EmbedderEvent;
use servo::compositing::CompositeTarget; use servo::compositing::CompositeTarget;
pub use servo::config::prefs::{add_user_prefs, PrefValue}; pub use servo::config::prefs::{add_user_prefs, PrefValue};
@ -93,14 +94,19 @@ pub fn init(
SurfaceType::Widget { native_widget } SurfaceType::Widget { native_widget }
}, },
}; };
let rendering_context = RenderingContext::create(&connection, &adapter, surface_type) let rendering_context = RenderingContext::create(&connection, &adapter, None)
.or(Err("Failed to create surface manager"))?; .or(Err("Failed to create surface manager"))?;
let surface = rendering_context
.create_surface(surface_type)
.or(Err("Failed to create surface"))?;
rendering_context
.bind_surface(surface)
.or(Err("Failed to bind surface"))?;
let window_callbacks = Rc::new(ServoWindowCallbacks::new( let window_callbacks = Rc::new(ServoWindowCallbacks::new(
callbacks, callbacks,
RefCell::new(init_opts.coordinates), RefCell::new(init_opts.coordinates),
init_opts.density, init_opts.density,
rendering_context.clone(),
)); ));
let embedder_callbacks = Box::new(ServoEmbedderCallbacks::new( let embedder_callbacks = Box::new(ServoEmbedderCallbacks::new(
@ -110,6 +116,7 @@ pub fn init(
)); ));
let servo = Servo::new( let servo = Servo::new(
rendering_context.clone(),
embedder_callbacks, embedder_callbacks,
window_callbacks.clone(), window_callbacks.clone(),
None, None,
@ -117,8 +124,8 @@ pub fn init(
); );
SERVO.with(|s| { SERVO.with(|s| {
let mut servo_glue = ServoGlue::new(rendering_context, servo.servo, window_callbacks, None); let mut servo_glue = ServoGlue::new(rendering_context, servo, window_callbacks, None);
let _ = servo_glue.process_event(EmbedderEvent::NewWebView(url, servo.browser_id)); let _ = servo_glue.process_event(EmbedderEvent::NewWebView(url, WebViewId::new()));
*s.borrow_mut() = Some(servo_glue); *s.borrow_mut() = Some(servo_glue);
}); });

View file

@ -9,6 +9,7 @@ use std::rc::Rc;
use log::{debug, error, info}; use log::{debug, error, info};
use ohos_sys::xcomponent::{OH_NativeXComponent, OH_NativeXComponent_GetXComponentSize}; use ohos_sys::xcomponent::{OH_NativeXComponent, OH_NativeXComponent_GetXComponentSize};
use servo::base::id::WebViewId;
use servo::compositing::windowing::EmbedderEvent; use servo::compositing::windowing::EmbedderEvent;
use servo::compositing::CompositeTarget; use servo::compositing::CompositeTarget;
use servo::embedder_traits::resources; use servo::embedder_traits::resources;
@ -118,8 +119,14 @@ pub fn init(
let surface_type = SurfaceType::Widget { native_widget }; let surface_type = SurfaceType::Widget { native_widget };
info!("Creating rendering context"); info!("Creating rendering context");
let rendering_context = RenderingContext::create(&connection, &adapter, surface_type) let rendering_context = RenderingContext::create(&connection, &adapter, None)
.or(Err("Failed to create surface manager"))?; .or(Err("Failed to create surface manager"))?;
let surface = rendering_context
.create_surface(surface_type)
.or(Err("Failed to create surface"))?;
rendering_context
.bind_surface(surface)
.or(Err("Failed to bind surface"))?;
info!("before ServoWindowCallbacks..."); info!("before ServoWindowCallbacks...");
@ -127,7 +134,6 @@ pub fn init(
callbacks, callbacks,
RefCell::new(Coordinates::new(0, 0, width, height, width, height)), RefCell::new(Coordinates::new(0, 0, width, height, width, height)),
options.display_density as f32, options.display_density as f32,
rendering_context.clone(),
)); ));
let embedder_callbacks = Box::new(ServoEmbedderCallbacks::new( let embedder_callbacks = Box::new(ServoEmbedderCallbacks::new(
@ -137,6 +143,7 @@ pub fn init(
)); ));
let servo = Servo::new( let servo = Servo::new(
rendering_context.clone(),
embedder_callbacks, embedder_callbacks,
window_callbacks.clone(), window_callbacks.clone(),
// User agent: Mozilla/5.0 (<Phone|PC|Tablet>; HarmonyOS 5.0) bla bla // User agent: Mozilla/5.0 (<Phone|PC|Tablet>; HarmonyOS 5.0) bla bla
@ -146,7 +153,7 @@ pub fn init(
let mut servo_glue = ServoGlue::new( let mut servo_glue = ServoGlue::new(
rendering_context, rendering_context,
servo.servo, servo,
window_callbacks, window_callbacks,
Some(options.resource_dir), Some(options.resource_dir),
); );
@ -156,7 +163,7 @@ pub fn init(
.ok() .ok()
.unwrap_or_else(|| ServoUrl::parse("about:blank").expect("Infallible")); .unwrap_or_else(|| ServoUrl::parse("about:blank").expect("Infallible"));
let _ = servo_glue.process_event(EmbedderEvent::NewWebView(initial_url, servo.browser_id)); let _ = servo_glue.process_event(EmbedderEvent::NewWebView(initial_url, WebViewId::new()));
Ok(servo_glue) Ok(servo_glue)
} }

View file

@ -58,7 +58,6 @@ pub(super) struct ServoWindowCallbacks {
host_callbacks: Box<dyn HostTrait>, host_callbacks: Box<dyn HostTrait>,
coordinates: RefCell<Coordinates>, coordinates: RefCell<Coordinates>,
hidpi_factor: Scale<f32, DeviceIndependentPixel, DevicePixel>, hidpi_factor: Scale<f32, DeviceIndependentPixel, DevicePixel>,
rendering_context: RenderingContext,
} }
impl ServoWindowCallbacks { impl ServoWindowCallbacks {
@ -66,13 +65,11 @@ impl ServoWindowCallbacks {
host_callbacks: Box<dyn HostTrait>, host_callbacks: Box<dyn HostTrait>,
coordinates: RefCell<Coordinates>, coordinates: RefCell<Coordinates>,
hidpi_factor: f32, hidpi_factor: f32,
rendering_context: RenderingContext,
) -> Self { ) -> Self {
Self { Self {
host_callbacks, host_callbacks,
coordinates, coordinates,
hidpi_factor: Scale::new(hidpi_factor), hidpi_factor: Scale::new(hidpi_factor),
rendering_context,
} }
} }
} }
@ -549,6 +546,8 @@ impl ServoGlue {
}, },
EmbedderMsg::WebViewFocused(webview_id) => { EmbedderMsg::WebViewFocused(webview_id) => {
self.focused_webview_id = Some(webview_id); self.focused_webview_id = Some(webview_id);
self.events
.push(EmbedderEvent::ShowWebView(webview_id, true));
}, },
EmbedderMsg::WebViewBlurred => { EmbedderMsg::WebViewBlurred => {
self.focused_webview_id = None; self.focused_webview_id = None;
@ -717,8 +716,4 @@ impl WindowMethods for ServoWindowCallbacks {
self.host_callbacks self.host_callbacks
.on_animating_changed(state == AnimationState::Animating); .on_animating_changed(state == AnimationState::Animating);
} }
fn rendering_context(&self) -> RenderingContext {
self.rendering_context.clone()
}
} }