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,
exit_after_load: bool,
convert_mouse_to_touch: bool,
top_level_browsing_context_id: TopLevelBrowsingContextId,
version_string: String,
) -> 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 {
embedder_coordinates: window.get_coordinates(),
window,
port: state.receiver,
webviews,
webviews: WebViewManager::default(),
pipeline_details: HashMap::new(),
composition_request: CompositionRequest::NoCompositingNecessary,
touch_handler: TouchHandler::new(),
@ -1360,7 +1340,11 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
if self.embedder_coordinates.viewport != old_coords.viewport {
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
.send_transaction(self.webrender_document, transaction);
}

View file

@ -23,7 +23,6 @@ use webrender_api::units::{
DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixel, DevicePoint, DeviceRect,
};
use webrender_api::ScrollLocation;
use webrender_traits::RenderingContext;
#[derive(Clone)]
pub enum MouseWindowEvent {
@ -218,8 +217,6 @@ pub trait WindowMethods {
/// will want to avoid blocking on UI events, and just
/// run the event loop at the vsync interval.
fn set_animation_state(&self, _state: AnimationState);
/// Get the [`RenderingContext`] of this Window.
fn rendering_context(&self) -> RenderingContext;
}
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>
where
Window: WindowMethods + 'static + ?Sized,
@ -238,11 +233,12 @@ where
)]
#[allow(clippy::new_ret_no_self)]
pub fn new(
rendering_context: RenderingContext,
mut embedder: Box<dyn EmbedderMethods>,
window: Rc<Window>,
user_agent: Option<String>,
composite_target: CompositeTarget,
) -> InitializedServo<Window> {
) -> Servo<Window> {
// Global configuration options, parsed from the command line.
let opts = opts::get();
@ -277,9 +273,6 @@ where
.unwrap_or(default_user_agent_string_for(DEFAULT_USER_AGENT).into()),
};
// Initialize surfman
let rendering_context = window.rendering_context();
// Get GL bindings
let webrender_gl = match rendering_context.connection().gl_api() {
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.
PipelineNamespace::install(PipelineNamespaceId(0));
let top_level_browsing_context_id = TopLevelBrowsingContextId::new();
// Get both endpoints of a special channel for communication between
// the client window and the compositor. This channel is unique because
@ -525,21 +517,16 @@ where
composite_target,
opts.exit_after_load,
opts.debug.convert_mouse_to_touch,
top_level_browsing_context_id,
embedder.get_version_string().unwrap_or_default(),
);
let servo = Servo {
Servo {
compositor,
constellation_chan,
embedder_receiver,
messages_for_embedder: Vec::new(),
profiler_enabled: false,
_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,
)]
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;
size_of_test!(TopLevelBrowsingContextId, 8);

View file

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

View file

@ -4,22 +4,24 @@
//! Application entry point, runs the event loop.
use std::cell::{Cell, RefCell, RefMut};
use std::cell::Cell;
use std::collections::HashMap;
use std::rc::Rc;
use std::time::Instant;
use std::{env, fs};
use gleam::gl;
use log::{error, info, trace};
use log::{info, trace};
use raw_window_handle::HasDisplayHandle;
use servo::base::id::WebViewId;
use servo::compositing::windowing::EmbedderEvent;
use servo::compositing::CompositeTarget;
use servo::config::opts;
use servo::embedder_traits::EventLoopWaker;
use servo::servo_config::pref;
use servo::url::ServoUrl;
use servo::webrender_traits::RenderingContext;
use servo::Servo;
use surfman::GLApi;
use surfman::Connection;
use webxr::glwindow::GlWindowDiscovery;
#[cfg(target_os = "windows")]
use webxr::openxr::{AppInfo, OpenXrDiscovery};
@ -31,6 +33,7 @@ use winit::window::WindowId;
use super::events_loop::{EventLoopGuard, EventsLoop, WakerEvent};
use super::minibrowser::Minibrowser;
use super::webview::WebViewManager;
use super::{headed_window, headless_window};
use crate::desktop::embedder::{EmbedderCallbacks, XrDiscovery};
use crate::desktop::events_loop::with_current_event_loop;
use crate::desktop::tracing::trace_winit_event;
@ -39,16 +42,18 @@ use crate::parser::get_default_url;
pub struct App {
servo: Option<Servo<dyn WindowPortsMethods>>,
webviews: RefCell<WebViewManager<dyn WindowPortsMethods>>,
event_queue: RefCell<Vec<EmbedderEvent>>,
webviews: Option<WebViewManager<dyn WindowPortsMethods>>,
event_queue: Vec<EmbedderEvent>,
suspended: Cell<bool>,
windows: HashMap<WindowId, Rc<dyn WindowPortsMethods>>,
minibrowser: Option<RefCell<Minibrowser>>,
minibrowser: Option<Minibrowser>,
user_agent: Option<String>,
waker: Box<dyn EventLoopWaker>,
initial_url: ServoUrl,
t_start: Instant,
t: Instant,
do_not_use_native_titlebar: bool,
device_pixel_ratio_override: Option<f32>,
}
enum Present {
@ -70,19 +75,19 @@ enum PumpResult {
impl App {
pub fn new(
events_loop: &EventsLoop,
window: Rc<dyn WindowPortsMethods>,
user_agent: Option<String>,
url: Option<String>,
do_not_use_native_titlebar: bool,
device_pixel_ratio_override: Option<f32>,
) -> Self {
// Handle browser state.
let webviews = WebViewManager::new(window.clone());
let initial_url = get_default_url(url.as_deref(), env::current_dir().unwrap(), |path| {
fs::metadata(path).is_ok()
});
let t = Instant::now();
let mut app = App {
event_queue: RefCell::new(vec![]),
webviews: RefCell::new(webviews),
App {
event_queue: vec![],
webviews: None,
servo: None,
suspended: Cell::new(false),
windows: HashMap::new(),
@ -92,54 +97,80 @@ impl App {
initial_url: initial_url.clone(),
t_start: t,
t,
do_not_use_native_titlebar,
device_pixel_ratio_override,
}
}
/// 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")
};
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);
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,
))
};
app.minibrowser = Some(
Minibrowser::new(
&rendering_context,
events_loop.as_winit(),
initial_url.clone(),
)
.into(),
);
// 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(mut minibrowser) = app.minibrowser() {
if let Some(ref mut minibrowser) = self.minibrowser {
// Servo is not yet initialised, so there is no `servo_framebuffer_id`.
minibrowser.update(
window.winit_window().unwrap(),
&mut app.webviews.borrow_mut(),
self.webviews.as_mut().unwrap(),
None,
"init",
);
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.event_queue.borrow_mut().push(EmbedderEvent::Idle);
self.event_queue.push(EmbedderEvent::Idle);
let (_, window) = self.windows.iter().next().unwrap();
let surfman = window.rendering_context();
let openxr_discovery = if pref!(dom.webxr.openxr.enabled) && !opts::get().headless {
#[cfg(target_os = "windows")]
@ -162,9 +193,9 @@ impl App {
.expect("An event loop should always be active in headed mode")
});
Some(XrDiscovery::GlWindow(GlWindowDiscovery::new(
surfman.connection(),
surfman.adapter(),
surfman.context_attributes(),
rendering_context.connection(),
rendering_context.adapter(),
rendering_context.context_attributes(),
factory,
)))
} else {
@ -182,17 +213,17 @@ impl App {
} else {
CompositeTarget::Window
};
let servo_data = Servo::new(
let mut servo = Servo::new(
rendering_context,
embedder,
window.clone(),
self.user_agent.clone(),
composite_target,
);
let mut servo = servo_data.servo;
servo.handle_events(vec![EmbedderEvent::NewWebView(
self.initial_url.to_owned(),
servo_data.browser_id,
WebViewId::new(),
)]);
servo.setup_logging();
@ -203,8 +234,8 @@ impl App {
self.windows.iter().any(|(_, window)| window.is_animating())
}
fn get_events(&self) -> Vec<EmbedderEvent> {
std::mem::take(&mut *self.event_queue.borrow_mut())
fn get_events(&mut self) -> Vec<EmbedderEvent> {
std::mem::take(&mut self.event_queue)
}
/// 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
/// of the Servo interface so that the WebViewManager can handle them.
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.
let mut embedder_events = self.get_events();
for window in self.windows.values() {
embedder_events.extend(window.get_events());
}
@ -285,21 +316,15 @@ impl App {
match self.handle_events() {
PumpResult::Shutdown => {
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();
if let Some(mut minibrowser) = self.minibrowser() {
if let Some(ref mut minibrowser) = self.minibrowser {
minibrowser.context.destroy();
}
},
PumpResult::Continue { update, present } => {
if update {
if let Some(mut minibrowser) = self.minibrowser() {
let webviews = &mut self.webviews.borrow_mut();
if let Some(ref mut minibrowser) = self.minibrowser {
let webviews = self.webviews.as_mut().unwrap();
if minibrowser.update_webview_data(webviews) {
// Update the minibrowser immediately. While we could update by requesting a
// 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
// call Servo::repaint_synchronously. At the moment we dont, so there wont be
// 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(
window.winit_window().unwrap(),
&mut self.webviews.borrow_mut(),
self.webviews.as_mut().unwrap(),
self.servo.as_ref().unwrap().offscreen_framebuffer_id(),
"PumpResult::Present::Immediate",
);
@ -364,14 +389,14 @@ impl App {
if self.servo.is_none() {
return false;
}
self.event_queue.borrow_mut().push(EmbedderEvent::Idle);
self.event_queue.push(EmbedderEvent::Idle);
let mut exit = false;
match self.handle_events() {
PumpResult::Shutdown => {
exit = true;
self.servo.take().unwrap().deinit();
if let Some(mut minibrowser) = self.minibrowser() {
if let Some(ref mut minibrowser) = self.minibrowser {
minibrowser.context.destroy();
}
},
@ -394,16 +419,12 @@ impl App {
}
exit
}
fn minibrowser(&self) -> Option<RefMut<Minibrowser>> {
self.minibrowser.as_ref().map(|x| x.borrow_mut())
}
}
impl ApplicationHandler<WakerEvent> for App {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
let _guard = EventLoopGuard::new(event_loop);
self.init();
self.init(Some(event_loop));
}
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
// 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(
window.winit_window().unwrap(),
&mut self.webviews.borrow_mut(),
self.webviews.as_mut().unwrap(),
self.servo.as_ref().unwrap().offscreen_framebuffer_id(),
"RedrawRequested",
);
@ -452,7 +473,7 @@ impl ApplicationHandler<WakerEvent> for App {
// Handle the event
let mut consumed = false;
if let Some(mut minibrowser) = self.minibrowser() {
if let Some(ref mut minibrowser) = self.minibrowser {
match event {
WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
// 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 {
minibrowser.update(
window.winit_window().unwrap(),
&mut self.webviews.borrow_mut(),
self.webviews.as_mut().unwrap(),
self.servo.as_ref().unwrap().offscreen_framebuffer_id(),
"Sync WebView size with Window Resize event",
);
@ -501,7 +522,7 @@ impl ApplicationHandler<WakerEvent> for App {
}
if !consumed {
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);
@ -517,9 +538,9 @@ impl ApplicationHandler<WakerEvent> for App {
}
// Consume and handle any events from the Minibrowser.
if let Some(minibrowser) = self.minibrowser() {
let webviews = &mut self.webviews.borrow_mut();
let app_event_queue = &mut self.event_queue.borrow_mut();
if let Some(ref minibrowser) = self.minibrowser {
let webviews = &mut self.webviews.as_mut().unwrap();
let app_event_queue = &mut self.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() {
return;
}
self.event_queue.borrow_mut().push(EmbedderEvent::Idle);
self.event_queue.push(EmbedderEvent::Idle);
let Some(window) = self.windows.values().next() else {
return;
@ -558,9 +579,9 @@ impl ApplicationHandler<WakerEvent> for App {
}
// Consume and handle any events from the Minibrowser.
if let Some(minibrowser) = self.minibrowser() {
let webviews = &mut self.webviews.borrow_mut();
let app_event_queue = &mut self.event_queue.borrow_mut();
if let Some(ref minibrowser) = self.minibrowser {
let webviews = &mut self.webviews.as_mut().unwrap();
let app_event_queue = &mut self.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
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::rc::Rc;
use std::{env, panic, process};
use getopts::Options;
use log::{error, warn};
use log::error;
use servo::config::opts::{self, ArgumentParsingResult};
use servo::config::set_pref;
use servo::servo_config::pref;
use crate::desktop::app::App;
use crate::desktop::events_loop::EventsLoop;
use crate::desktop::{headed_window, headless_window};
use crate::panic_hook;
pub fn main() {
@ -106,29 +103,12 @@ pub fn main() {
let event_loop = EventsLoop::new(opts::get().headless, opts::get().output_file.is_some())
.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(
&event_loop,
window.clone(),
user_agent,
url_opt.map(|s| s.to_string()),
do_not_use_native_titlebar,
device_pixel_ratio_override,
);
event_loop.run_app(&mut app);

View file

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

View file

@ -9,6 +9,7 @@ use std::sync::{Arc, Condvar, Mutex};
use std::time;
use log::warn;
use servo::config::{pref, set_pref};
use servo::embedder_traits::EventLoopWaker;
use winit::error::EventLoopError;
use winit::event_loop::{ActiveEventLoop, EventLoop as WinitEventLoop};
@ -79,14 +80,7 @@ impl EventsLoop {
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) {
match self.0 {
EventLoop::Winit(events_loop) => {
@ -97,7 +91,12 @@ impl EventsLoop {
},
EventLoop::Headless(ref 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 {
self.sleep(flag, condvar);
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 log::{debug, info, trace};
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use raw_window_handle::HasWindowHandle;
use servo::compositing::windowing::{
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::ScrollLocation;
use servo::webrender_traits::RenderingContext;
use surfman::{Connection, Context, Device, SurfaceType};
use surfman::{Context, Device, SurfaceType};
use winit::dpi::{LogicalSize, PhysicalPosition, PhysicalSize};
use winit::event::{ElementState, KeyEvent, MouseButton, MouseScrollDelta, TouchPhase};
use winit::event_loop::ActiveEventLoop;
use winit::keyboard::{Key as LogicalKey, ModifiersState, NamedKey};
#[cfg(any(target_os = "linux", target_os = "windows"))]
use winit::window::Icon;
use super::events_loop::WakerEvent;
use super::geometry::{winit_position_to_euclid_point, winit_size_to_euclid_size};
use super::keyutils::keyboard_event_from_winit;
use super::window_trait::{WindowPortsMethods, LINE_HEIGHT};
pub struct Window {
winit_window: winit::window::Window,
rendering_context: RenderingContext,
screen_size: Size2D<u32, DeviceIndependentPixel>,
inner_size: Cell<PhysicalSize<u32>>,
toolbar_height: Cell<Length<f32, DeviceIndependentPixel>>,
@ -58,8 +57,9 @@ pub struct Window {
impl Window {
pub fn new(
rendering_context: &RenderingContext,
window_size: Size2D<u32, DeviceIndependentPixel>,
event_loop: &winit::event_loop::EventLoop<WakerEvent>,
event_loop: &ActiveEventLoop,
no_native_titlebar: bool,
device_pixel_ratio_override: Option<f32>,
) -> Window {
@ -103,20 +103,13 @@ impl Window {
let screen_size = (winit_size_to_euclid_size(screen_size).to_f64() / screen_scale).to_u32();
// 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
.window_handle()
.expect("could not get window handle from window");
let inner_size = winit_window.inner_size();
let native_widget = connection
let native_widget = rendering_context
.connection()
.create_native_widget_from_window_handle(
window_handle,
winit_size_to_euclid_size(inner_size).to_i32().to_untyped(),
@ -124,13 +117,18 @@ impl Window {
.expect("Failed to create native widget");
let surface_type = SurfaceType::Widget { native_widget };
let rendering_context = RenderingContext::create(&connection, &adapter, surface_type)
.expect("Failed to create WR surfman");
let surface = rendering_context
.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());
Window {
winit_window,
rendering_context,
event_queue: RefCell::new(vec![]),
mouse_down_button: Cell::new(None),
mouse_down_point: Cell::new(Point2D::zero()),
@ -478,9 +476,6 @@ impl WindowPortsMethods for Window {
},
winit::event::WindowEvent::Resized(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.event_queue
.borrow_mut()
@ -565,10 +560,6 @@ impl WindowMethods for Window {
fn set_animation_state(&self, state: AnimationState) {
self.animation_state.set(state);
}
fn rendering_context(&self) -> RenderingContext {
self.rendering_context.clone()
}
}
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::{Box2D, Length, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector3D};
use log::warn;
use servo::compositing::windowing::{
AnimationState, EmbedderCoordinates, EmbedderEvent, WindowMethods,
};
use servo::config::opts;
use servo::servo_geometry::DeviceIndependentPixel;
use servo::webrender_api::units::{DeviceIntSize, DevicePixel};
use servo::webrender_traits::RenderingContext;
use surfman::{Connection, Context, Device, SurfaceType};
use surfman::{Context, Device};
use crate::desktop::window_trait::WindowPortsMethods;
pub struct Window {
rendering_context: RenderingContext,
animation_state: Cell<AnimationState>,
fullscreen: Cell<bool>,
device_pixel_ratio_override: Option<Scale<f32, DeviceIndependentPixel, DevicePixel>>,
@ -39,17 +36,6 @@ impl Window {
size: Size2D<u32, DeviceIndependentPixel>,
device_pixel_ratio_override: Option<f32>,
) -> 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>> =
device_pixel_ratio_override.map(Scale::new);
let hidpi_factor = device_pixel_ratio_override.unwrap_or_else(Scale::identity);
@ -64,7 +50,6 @@ impl Window {
);
let window = Window {
rendering_context,
animation_state: Cell::new(AnimationState::Idle),
fullscreen: Cell::new(false),
device_pixel_ratio_override,
@ -97,19 +82,11 @@ impl WindowPortsMethods for Window {
return Some(new_size);
}
match self.rendering_context.resize(new_size.to_untyped()) {
Ok(()) => {
self.inner_size.set(new_size);
if let Ok(ref mut queue) = self.event_queue.write() {
queue.push(EmbedderEvent::WindowResize);
}
Some(new_size)
},
Err(error) => {
warn!("Could not resize window: {error:?}");
None
},
self.inner_size.set(new_size);
if let Ok(ref mut queue) = self.event_queue.write() {
queue.push(EmbedderEvent::WindowResize);
}
Some(new_size)
}
fn device_hidpi_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> {
@ -123,12 +100,7 @@ impl WindowPortsMethods for Window {
}
fn page_height(&self) -> f32 {
let height = self
.rendering_context
.context_surface_info()
.unwrap_or(None)
.map(|info| info.size.height)
.unwrap_or(0);
let height = self.inner_size.get().height;
let dpr = self.hidpi_factor();
height as f32 * dpr.get()
}
@ -185,10 +157,6 @@ impl WindowMethods for Window {
fn set_animation_state(&self, state: AnimationState) {
self.animation_state.set(state);
}
fn rendering_context(&self) -> RenderingContext {
self.rendering_context.clone()
}
}
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::TopLevelBrowsingContextId;
use winit::event::{ElementState, MouseButton, WindowEvent};
use winit::event_loop::EventLoop;
use winit::event_loop::ActiveEventLoop;
use winit::window::Window;
use super::egui_glue::EguiGlow;
use super::events_loop::WakerEvent;
use super::geometry::winit_position_to_euclid_point;
use super::webview::{LoadStatus, WebViewManager};
use super::window_trait::WindowPortsMethods;
@ -80,7 +79,7 @@ fn truncate_with_ellipsis(input: &str, max_length: usize) -> String {
impl Minibrowser {
pub fn new(
rendering_context: &RenderingContext,
event_loop: &EventLoop<WakerEvent>,
event_loop: &ActiveEventLoop,
initial_url: ServoUrl,
) -> Self {
let gl = unsafe {

View file

@ -9,6 +9,7 @@ use std::os::raw::c_void;
use std::rc::Rc;
use getopts::Options;
use servo::base::id::WebViewId;
use servo::compositing::windowing::EmbedderEvent;
use servo::compositing::CompositeTarget;
pub use servo::config::prefs::{add_user_prefs, PrefValue};
@ -93,14 +94,19 @@ pub fn init(
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"))?;
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(
callbacks,
RefCell::new(init_opts.coordinates),
init_opts.density,
rendering_context.clone(),
));
let embedder_callbacks = Box::new(ServoEmbedderCallbacks::new(
@ -110,6 +116,7 @@ pub fn init(
));
let servo = Servo::new(
rendering_context.clone(),
embedder_callbacks,
window_callbacks.clone(),
None,
@ -117,8 +124,8 @@ pub fn init(
);
SERVO.with(|s| {
let mut servo_glue = ServoGlue::new(rendering_context, servo.servo, window_callbacks, None);
let _ = servo_glue.process_event(EmbedderEvent::NewWebView(url, servo.browser_id));
let mut servo_glue = ServoGlue::new(rendering_context, servo, window_callbacks, None);
let _ = servo_glue.process_event(EmbedderEvent::NewWebView(url, WebViewId::new()));
*s.borrow_mut() = Some(servo_glue);
});

View file

@ -9,6 +9,7 @@ use std::rc::Rc;
use log::{debug, error, info};
use ohos_sys::xcomponent::{OH_NativeXComponent, OH_NativeXComponent_GetXComponentSize};
use servo::base::id::WebViewId;
use servo::compositing::windowing::EmbedderEvent;
use servo::compositing::CompositeTarget;
use servo::embedder_traits::resources;
@ -118,8 +119,14 @@ pub fn init(
let surface_type = SurfaceType::Widget { native_widget };
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"))?;
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...");
@ -127,7 +134,6 @@ pub fn init(
callbacks,
RefCell::new(Coordinates::new(0, 0, width, height, width, height)),
options.display_density as f32,
rendering_context.clone(),
));
let embedder_callbacks = Box::new(ServoEmbedderCallbacks::new(
@ -137,6 +143,7 @@ pub fn init(
));
let servo = Servo::new(
rendering_context.clone(),
embedder_callbacks,
window_callbacks.clone(),
// 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(
rendering_context,
servo.servo,
servo,
window_callbacks,
Some(options.resource_dir),
);
@ -156,7 +163,7 @@ pub fn init(
.ok()
.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)
}

View file

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