Add support for integrating Servo into Slint applications #8735 #8842
Replies: 3 comments 3 replies
-
I think this is a little tricky. For the display and window handle,
It's a bit hard to fit that into a comment, but in a nutshell for your scenario Slint uses the winit and the winit event loop, and it needs to drive it. It will default to the FemtoVG renderer, which uses OpenGL. The OpenGL surface and context must be owned by Slint (GL isn't really great a sharing these things as state easily gets mixed up). My suggestion as a general direction is to keep servo's rendering separate from Slint as much as possible and limit the exchange to textures bridged across servo's OpenGL stack and whatever stack you select for Slint. In an ideal world, the GL textures servo exports could be bridged to a GL independent but OS dependent primitive (dma-buf, iosurface) and then imported into say a wgpu::Texture, and that one we can integrate into Slint's rendering. |
Beta Was this translation helpful? Give feedback.
-
I am able to get blank window and servo run behind but getting #![allow(unsafe_op_in_unsafe_fn)]
use std::cell::RefCell;
use std::rc::Rc;
use url::Url;
use winit::dpi;
use slint::RenderingState;
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use servo::{
RenderingContext, Servo, ServoBuilder, WebView, WebViewBuilder, WindowRenderingContext,
};
slint::slint! {
export component MyApp inherits Window {
width: 1024px;
height: 768px;
in property <image> web_content <=> image.source;
image := Image {
width: 100%;
height: 100%;
}
}
}
struct AppDelegate {
app: MyApp,
}
impl servo::WebViewDelegate for AppDelegate {
fn notify_new_frame_ready(&self, _webview: WebView) {
self.app.window().request_redraw();
}
}
fn main() {
let app = MyApp::new().unwrap();
let app_weak = app.as_weak();
let window = app.window();
let servo: Rc<RefCell<Option<Servo>>> = Rc::new(RefCell::new(None));
let servo_clone = servo.clone();
let webview: Rc<RefCell<Option<WebView>>> = Rc::new(RefCell::new(None));
let webview_clone = webview.clone();
window
.set_rendering_notifier(move |state, _graphics_api| match state {
RenderingState::RenderingSetup => {
let app = app_weak.upgrade().unwrap();
let window = app.window();
let slint_window_handle = window.window_handle();
let window_handle = slint_window_handle.window_handle().unwrap();
let display_handle = slint_window_handle.display_handle().unwrap();
let slint_size = window.size();
let size = dpi::PhysicalSize::new(slint_size.width, slint_size.height);
let rendering_context =
WindowRenderingContext::new(display_handle, window_handle, size).unwrap();
let rendering_context_rc = Rc::new(rendering_context);
let offscreen_context = rendering_context_rc.offscreen_context(size);
let offscreen_context_rc = Rc::new(offscreen_context);
let _ = offscreen_context_rc.make_current();
let servo_instance = ServoBuilder::new(rendering_context_rc).build();
servo_instance.setup_logging();
let delegate = Rc::new(AppDelegate { app: app });
let url = Url::parse("https://example.com/").unwrap();
let webview_instance = WebViewBuilder::new(&servo_instance)
.url(url)
.delegate(delegate.clone())
.build();
*webview_clone.borrow_mut() = Some(webview_instance);
*servo_clone.borrow_mut() = Some(servo_instance);
}
RenderingState::RenderingTeardown => {
*webview_clone.borrow_mut() = None;
if let Some(servo_instance) = servo_clone.borrow_mut().take() {
servo_instance.deinit();
}
}
_ => {}
})
.unwrap();
app.run().unwrap();
} |
Beta Was this translation helpful? Give feedback.
-
I try to follow how verso integrate servo and it also need event loop for that i find backed builder api which accept event loop builder but the main hardle that why slint not allow to pass already built event loop so it can be shared with servo and slint i also tried to get proxy event loop but having type mismatched issues with that. #![allow(unsafe_op_in_unsafe_fn)]
use i_slint_backend_selector::with_platform;
use i_slint_backend_winit::{Backend, CustomApplicationHandler, WinitWindowEventResult};
use issue_8735::Verso;
use slint::platform::set_platform;
use slint::winit_030::SlintEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop, EventLoopProxy};
slint::slint! {
export component MyApp inherits Window {
width: 1024px;
height: 768px;
in property <image> web_content <=> image.source;
image := Image {
width: 100%;
height: 100%;
}
}
}
struct AppState {
proxy: Option<EventLoopProxy<SlintEvent>>,
}
impl CustomApplicationHandler for AppState {
fn resumed(
&mut self,
_event_loop: &ActiveEventLoop,
) -> WinitWindowEventResult {
let proxy = self.proxy.clone().unwrap();
Verso::new(_event_loop, proxy);
WinitWindowEventResult::Propagate
}
}
fn main() {
let mut event_loop_builder = EventLoop::<SlintEvent>::with_user_event();
let mut app_state = AppState { proxy: None };
let backend = Backend::builder()
.with_custom_application_handler(app_state)
.with_event_loop_builder(event_loop_builder)
.build()
.unwrap();
set_platform(Box::new(backend)).unwrap();
MyApp::new().unwrap().show();
with_platform(|b| {
let proxy = b.new_event_loop_proxy().unwrap();
app_state.proxy = Some(*proxy); /* mismatched types expected struct `winit::event_loop::EventLoopProxy<SlintEvent>` found trait object `dyn slint::platform::EventLoopProxy */
b.run_event_loop()
})
.unwrap();
}
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I am trying to work on this issue and using
ServoBuilder
which needrenderingcontext
for which needDisplayHandle
,WindowHandle
, andPhysicalSize<u32>
i have try to usedapp.window().set_rendering_notifier
but don't understand how to get these from this because its only exposestate
andgraphics_api
api and i have checked that servo is usingraw_window_handle
and slint also use this but cant understand how to use that.Can you point out to some info about how slint rendering pipeline work or files so i can understand my self
Beta Was this translation helpful? Give feedback.
All reactions