C++: Make the platform support work without the "std" feature

Add a experimental-platform feature that doesn't include skia
This commit is contained in:
Olivier Goffart 2023-07-07 13:28:43 +02:00 committed by Olivier Goffart
parent 03bca95bef
commit 4a505c6788
3 changed files with 152 additions and 143 deletions

View file

@ -38,7 +38,8 @@ renderer-winit-software = ["i-slint-backend-selector/renderer-winit-software"]
gettext = ["i-slint-core/gettext-rs"] gettext = ["i-slint-core/gettext-rs"]
accessibility = ["i-slint-backend-selector/accessibility"] accessibility = ["i-slint-backend-selector/accessibility"]
experimental = ["i-slint-renderer-skia", "raw-window-handle", "std"] experimental = ["i-slint-renderer-skia", "raw-window-handle", "experimental-platform"]
experimental-platform = []
std = ["image", "i-slint-core/default", "i-slint-backend-selector"] std = ["image", "i-slint-core/default", "i-slint-backend-selector"]

View file

@ -10,7 +10,7 @@ use alloc::rc::Rc;
use core::ffi::c_void; use core::ffi::c_void;
use i_slint_core::window::{ffi::WindowAdapterRcOpaque, WindowAdapter}; use i_slint_core::window::{ffi::WindowAdapterRcOpaque, WindowAdapter};
#[cfg(feature = "experimental")] #[cfg(feature = "experimental-platform")]
pub mod platform; pub mod platform;
#[cfg(feature = "i-slint-backend-selector")] #[cfg(feature = "i-slint-backend-selector")]

View file

@ -11,7 +11,6 @@ use i_slint_core::renderer::Renderer;
use i_slint_core::software_renderer::{RepaintBufferType, SoftwareRenderer}; use i_slint_core::software_renderer::{RepaintBufferType, SoftwareRenderer};
use i_slint_core::window::ffi::WindowAdapterRcOpaque; use i_slint_core::window::ffi::WindowAdapterRcOpaque;
use i_slint_core::window::{WindowAdapter, WindowAdapterInternal}; use i_slint_core::window::{WindowAdapter, WindowAdapterInternal};
use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
type WindowAdapterUserData = *mut c_void; type WindowAdapterUserData = *mut c_void;
@ -214,146 +213,155 @@ pub unsafe extern "C" fn slint_software_renderer_handle(r: SoftwareRendererOpaqu
core::mem::transmute(r) core::mem::transmute(r)
} }
type SkiaRendererOpaque = *const c_void; #[cfg(all(feature = "i-slint-renderer-skia", feature = "raw-window-handle"))]
type SkiaRenderer = i_slint_renderer_skia::SkiaRenderer; pub mod skia {
use super::*;
use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
struct CppRawHandle(RawWindowHandle, RawDisplayHandle); struct CppRawHandle(RawWindowHandle, RawDisplayHandle);
// the raw handle type are #[non_exhaustive], so they can't be initialize with the convenient syntax. Work that around. // the raw handle type are #[non_exhaustive], so they can't be initialize with the convenient syntax. Work that around.
macro_rules! init_raw { macro_rules! init_raw {
($ty:ty { $($var:ident),* }) => { ($ty:ty { $($var:ident),* }) => {
{ {
let mut h = <$ty>::empty(); let mut h = <$ty>::empty();
$(h.$var = $var;)* $(h.$var = $var;)*
h h
} }
}; };
} }
type CppRawHandleOpaque = *const c_void; type CppRawHandleOpaque = *const c_void;
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn slint_new_raw_window_handle_win32( pub unsafe extern "C" fn slint_new_raw_window_handle_win32(
hwnd: *mut c_void, hwnd: *mut c_void,
hinstance: *mut c_void, hinstance: *mut c_void,
) -> CppRawHandleOpaque { ) -> CppRawHandleOpaque {
let handle = CppRawHandle( let handle = CppRawHandle(
RawWindowHandle::Win32(init_raw!(raw_window_handle::Win32WindowHandle { hwnd, hinstance })), RawWindowHandle::Win32(init_raw!(raw_window_handle::Win32WindowHandle {
RawDisplayHandle::Windows(raw_window_handle::WindowsDisplayHandle::empty()), hwnd,
); hinstance
Box::into_raw(Box::new(handle)) as CppRawHandleOpaque })),
} RawDisplayHandle::Windows(raw_window_handle::WindowsDisplayHandle::empty()),
);
#[no_mangle] Box::into_raw(Box::new(handle)) as CppRawHandleOpaque
pub unsafe extern "C" fn slint_new_raw_window_handle_x11( }
window: u32,
visual_id: u32, #[no_mangle]
connection: *mut c_void, pub unsafe extern "C" fn slint_new_raw_window_handle_x11(
screen: core::ffi::c_int, window: u32,
) -> CppRawHandleOpaque { visual_id: u32,
use raw_window_handle::{XcbDisplayHandle, XcbWindowHandle}; connection: *mut c_void,
let handle = CppRawHandle( screen: core::ffi::c_int,
RawWindowHandle::Xcb(init_raw!(XcbWindowHandle { window, visual_id })), ) -> CppRawHandleOpaque {
RawDisplayHandle::Xcb(init_raw!(XcbDisplayHandle { connection, screen })), use raw_window_handle::{XcbDisplayHandle, XcbWindowHandle};
); let handle = CppRawHandle(
Box::into_raw(Box::new(handle)) as CppRawHandleOpaque RawWindowHandle::Xcb(init_raw!(XcbWindowHandle { window, visual_id })),
} RawDisplayHandle::Xcb(init_raw!(XcbDisplayHandle { connection, screen })),
);
#[no_mangle] Box::into_raw(Box::new(handle)) as CppRawHandleOpaque
pub unsafe extern "C" fn slint_new_raw_window_handle_wayland( }
surface: *mut c_void,
display: *mut c_void, #[no_mangle]
) -> CppRawHandleOpaque { pub unsafe extern "C" fn slint_new_raw_window_handle_wayland(
use raw_window_handle::{WaylandDisplayHandle, WaylandWindowHandle}; surface: *mut c_void,
let handle = CppRawHandle( display: *mut c_void,
RawWindowHandle::Wayland(init_raw!(WaylandWindowHandle { surface })), ) -> CppRawHandleOpaque {
RawDisplayHandle::Wayland(init_raw!(WaylandDisplayHandle { display })), use raw_window_handle::{WaylandDisplayHandle, WaylandWindowHandle};
); let handle = CppRawHandle(
Box::into_raw(Box::new(handle)) as CppRawHandleOpaque RawWindowHandle::Wayland(init_raw!(WaylandWindowHandle { surface })),
} RawDisplayHandle::Wayland(init_raw!(WaylandDisplayHandle { display })),
);
#[no_mangle] Box::into_raw(Box::new(handle)) as CppRawHandleOpaque
pub unsafe extern "C" fn slint_new_raw_window_handle_appkit( }
ns_view: *mut c_void,
ns_window: *mut c_void, #[no_mangle]
) -> CppRawHandleOpaque { pub unsafe extern "C" fn slint_new_raw_window_handle_appkit(
use raw_window_handle::{AppKitDisplayHandle, AppKitWindowHandle}; ns_view: *mut c_void,
let handle = CppRawHandle( ns_window: *mut c_void,
RawWindowHandle::AppKit(init_raw!(AppKitWindowHandle { ns_view, ns_window })), ) -> CppRawHandleOpaque {
RawDisplayHandle::AppKit(AppKitDisplayHandle::empty()), use raw_window_handle::{AppKitDisplayHandle, AppKitWindowHandle};
); let handle = CppRawHandle(
Box::into_raw(Box::new(handle)) as CppRawHandleOpaque RawWindowHandle::AppKit(init_raw!(AppKitWindowHandle { ns_view, ns_window })),
} RawDisplayHandle::AppKit(AppKitDisplayHandle::empty()),
);
#[no_mangle] Box::into_raw(Box::new(handle)) as CppRawHandleOpaque
pub unsafe extern "C" fn slint_raw_window_handle_drop(handle: CppRawHandleOpaque) { }
drop(Box::from_raw(handle as *mut CppRawHandle))
} #[no_mangle]
pub unsafe extern "C" fn slint_raw_window_handle_drop(handle: CppRawHandleOpaque) {
#[no_mangle] drop(Box::from_raw(handle as *mut CppRawHandle))
pub unsafe extern "C" fn slint_skia_renderer_new( }
handle_opaque: CppRawHandleOpaque,
size: IntSize, type SkiaRendererOpaque = *const c_void;
) -> SkiaRendererOpaque { type SkiaRenderer = i_slint_renderer_skia::SkiaRenderer;
let handle = &*(handle_opaque as *const CppRawHandle);
#[no_mangle]
// Safety: This is safe because the handle remains valid; the next rwh release provides `new()` without unsafe. pub unsafe extern "C" fn slint_skia_renderer_new(
let active_handle = unsafe { raw_window_handle::ActiveHandle::new_unchecked() }; handle_opaque: CppRawHandleOpaque,
size: IntSize,
// Safety: the C++ code should ensure that the handle is valid ) -> SkiaRendererOpaque {
let (window_handle, display_handle) = unsafe { let handle = &*(handle_opaque as *const CppRawHandle);
(
raw_window_handle::WindowHandle::borrow_raw(handle.0, active_handle), // Safety: This is safe because the handle remains valid; the next rwh release provides `new()` without unsafe.
raw_window_handle::DisplayHandle::borrow_raw(handle.1), let active_handle = unsafe { raw_window_handle::ActiveHandle::new_unchecked() };
)
}; // Safety: the C++ code should ensure that the handle is valid
let (window_handle, display_handle) = unsafe {
let boxed_renderer: Box<SkiaRenderer> = Box::new( (
SkiaRenderer::new( raw_window_handle::WindowHandle::borrow_raw(handle.0, active_handle),
window_handle, raw_window_handle::DisplayHandle::borrow_raw(handle.1),
display_handle, )
PhysicalSize { width: size.width, height: size.height }, };
)
.unwrap(), let boxed_renderer: Box<SkiaRenderer> = Box::new(
); SkiaRenderer::new(
Box::into_raw(boxed_renderer) as SkiaRendererOpaque window_handle,
} display_handle,
PhysicalSize { width: size.width, height: size.height },
#[no_mangle] )
pub unsafe extern "C" fn slint_skia_renderer_drop(r: SkiaRendererOpaque) { .unwrap(),
drop(Box::from_raw(r as *mut SkiaRenderer)) );
} Box::into_raw(boxed_renderer) as SkiaRendererOpaque
}
#[no_mangle]
pub unsafe extern "C" fn slint_skia_renderer_show(r: SkiaRendererOpaque) { #[no_mangle]
let r = &*(r as *const SkiaRenderer); pub unsafe extern "C" fn slint_skia_renderer_drop(r: SkiaRendererOpaque) {
r.show().unwrap() drop(Box::from_raw(r as *mut SkiaRenderer))
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn slint_skia_renderer_hide(r: SkiaRendererOpaque) { pub unsafe extern "C" fn slint_skia_renderer_show(r: SkiaRendererOpaque) {
let r = &*(r as *const SkiaRenderer); let r = &*(r as *const SkiaRenderer);
r.hide().unwrap() r.show().unwrap()
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn slint_skia_renderer_resize(r: SkiaRendererOpaque, size: IntSize) { pub unsafe extern "C" fn slint_skia_renderer_hide(r: SkiaRendererOpaque) {
let r = &*(r as *const SkiaRenderer); let r = &*(r as *const SkiaRenderer);
r.resize_event(PhysicalSize { width: size.width, height: size.height }).unwrap(); r.hide().unwrap()
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn slint_skia_renderer_render( pub unsafe extern "C" fn slint_skia_renderer_resize(r: SkiaRendererOpaque, size: IntSize) {
r: SkiaRendererOpaque, let r = &*(r as *const SkiaRenderer);
window: *const WindowAdapterRcOpaque, r.resize_event(PhysicalSize { width: size.width, height: size.height }).unwrap();
) { }
let window_adapter = &*(window as *const Rc<dyn WindowAdapter>);
let r = &*(r as *const SkiaRenderer); #[no_mangle]
r.render(window_adapter.window()).unwrap(); pub unsafe extern "C" fn slint_skia_renderer_render(
} r: SkiaRendererOpaque,
window: *const WindowAdapterRcOpaque,
#[no_mangle] ) {
pub unsafe extern "C" fn slint_skia_renderer_handle(r: SkiaRendererOpaque) -> RendererPtr { let window_adapter = &*(window as *const Rc<dyn WindowAdapter>);
let r = (r as *const SkiaRenderer) as *const dyn Renderer; let r = &*(r as *const SkiaRenderer);
core::mem::transmute(r) r.render(window_adapter.window()).unwrap();
}
#[no_mangle]
pub unsafe extern "C" fn slint_skia_renderer_handle(r: SkiaRendererOpaque) -> RendererPtr {
let r = (r as *const SkiaRenderer) as *const dyn Renderer;
core::mem::transmute(r)
}
} }