From 3801345fb879e6b68a2fc5067c86cc75a653936d Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 5 Apr 2023 16:34:20 +0200 Subject: [PATCH] WIP: attempt to run a slint example on Android I just wanted to know if it worked out of the box, but it doesn't. We get a panic: Cannot get the native window, it's null and will always be null before Event::Resumed and after Event::Suspended. Make sure you only call this function between those events. --- api/rs/slint/lib.rs | 3 +++ examples/printerdemo/rust/Cargo.toml | 9 ++++++++- examples/printerdemo/rust/main.rs | 7 +++++++ internal/backends/selector/lib.rs | 3 +++ internal/backends/winit/Cargo.toml | 2 +- internal/backends/winit/event_loop.rs | 18 ++++++++++++++++-- internal/backends/winit/lib.rs | 7 +++++++ internal/renderers/femtovg/lib.rs | 4 ++++ 8 files changed, 49 insertions(+), 4 deletions(-) diff --git a/api/rs/slint/lib.rs b/api/rs/slint/lib.rs index 86eb2f37b31..4dd31d5b2f5 100644 --- a/api/rs/slint/lib.rs +++ b/api/rs/slint/lib.rs @@ -253,6 +253,9 @@ pub use i_slint_core::sharedvector::SharedVector; pub use i_slint_core::timers::{Timer, TimerMode}; pub use i_slint_core::{format, string::SharedString}; +#[cfg(target_os = "android")] +pub use i_slint_backend_selector::android_init; + pub mod private_unstable_api; /// Enters the main event loop. This is necessary in order to receive diff --git a/examples/printerdemo/rust/Cargo.toml b/examples/printerdemo/rust/Cargo.toml index b2cbb7ffe20..9071d3fadcd 100644 --- a/examples/printerdemo/rust/Cargo.toml +++ b/examples/printerdemo/rust/Cargo.toml @@ -15,7 +15,7 @@ path = "main.rs" name = "printerdemo" [dependencies] -slint = { path = "../../../api/rs/slint" } +slint = { path = "../../../api/rs/slint", default-features=false, features=["std", "backend-winit", "renderer-winit-femtovg", "compat-1-0"] } chrono = { version = "0.4", default-features = false, features = ["clock", "std"]} @@ -34,3 +34,10 @@ slint-build = { path = "../../../api/rs/build" } #wasm# wasm-bindgen = { version = "0.2" } #wasm# web-sys = { version = "0.3", features=["console"] } #wasm# console_error_panic_hook = "0.1.5" + + + [lib] + path = "main.rs" + crate-type = ["cdylib"] +[target.'cfg(target_os = "android")'.dependencies] +android-activity = "0.4" diff --git a/examples/printerdemo/rust/main.rs b/examples/printerdemo/rust/main.rs index 3d22450d96a..5937ec062b8 100644 --- a/examples/printerdemo/rust/main.rs +++ b/examples/printerdemo/rust/main.rs @@ -101,3 +101,10 @@ pub fn main() { main_window.run().unwrap(); } + +#[cfg(target_os = "android")] +#[no_mangle] +fn android_main(app: android_activity::AndroidApp) { + slint::android_init(app).unwrap(); + main(); +} diff --git a/internal/backends/selector/lib.rs b/internal/backends/selector/lib.rs index 03da1df69c2..459e648e528 100644 --- a/internal/backends/selector/lib.rs +++ b/internal/backends/selector/lib.rs @@ -92,3 +92,6 @@ pub fn use_modules() { #[cfg(feature = "i-slint-backend-winit")] i_slint_backend_winit::use_modules(); } + +#[cfg(all(feature = "i-slint-backend-winit", target_os = "android"))] +pub use i_slint_backend_winit::android_init; diff --git a/internal/backends/winit/Cargo.toml b/internal/backends/winit/Cargo.toml index 4ea049d60f6..35b68ad2aa6 100644 --- a/internal/backends/winit/Cargo.toml +++ b/internal/backends/winit/Cargo.toml @@ -44,7 +44,7 @@ once_cell = "1.5" pin-weak = "1" scoped-tls-hkt = "0.1" # Pinned due to https://github.com/slint-ui/slint/issues/2424 -winit = { version = "=0.28.3", default-features = false } +winit = { version = "=0.28.3", default-features = false, features = ["android-native-activity"] } instant = "0.1" raw-window-handle = { version = "0.5", features = ["alloc"] } scopeguard = { version = "1.1.0", default-features = false } diff --git a/internal/backends/winit/event_loop.rs b/internal/backends/winit/event_loop.rs index 811e9304eaa..5bb82309f72 100644 --- a/internal/backends/winit/event_loop.rs +++ b/internal/backends/winit/event_loop.rs @@ -64,9 +64,23 @@ struct NotRunningEventLoop { event_loop_proxy: winit::event_loop::EventLoopProxy, } +#[cfg(target_os = "android")] +pub(crate) static ANDROID_APP: once_cell::sync::OnceCell< + winit::platform::android::activity::AndroidApp, +> = once_cell::sync::OnceCell::new(); + impl NotRunningEventLoop { fn new() -> Self { - let instance = winit::event_loop::EventLoopBuilder::with_user_event().build(); + #[allow(unused_mut)] + let mut builder = winit::event_loop::EventLoopBuilder::with_user_event(); + #[cfg(target_os = "android")] + { + use winit::platform::android::EventLoopBuilderExtAndroid; + builder.with_android_app( + ANDROID_APP.get().expect("android must be initialized with android_init").clone(), + ); + } + let instance = builder.build(); let event_loop_proxy = instance.create_proxy(); let clipboard = RefCell::new(create_clipboard(&instance)); Self { clipboard, instance, event_loop_proxy } @@ -468,7 +482,7 @@ pub fn run() -> Result<(), corelib::platform::PlatformError> { use winit::event_loop::{ControlFlow, EventLoopWindowTarget}; let not_running_loop_instance = MAYBE_LOOP_INSTANCE.with(|loop_instance| { - loop_instance.borrow_mut().take().unwrap_or_else(NotRunningEventLoop::new) + loop_instance.borrow_mut().take().unwrap_or_else(|| NotRunningEventLoop::new()) }); let event_loop_proxy = not_running_loop_instance.event_loop_proxy; diff --git a/internal/backends/winit/lib.rs b/internal/backends/winit/lib.rs index bf974086271..aaf62b72207 100644 --- a/internal/backends/winit/lib.rs +++ b/internal/backends/winit/lib.rs @@ -200,3 +200,10 @@ impl i_slint_core::platform::Platform for Backend { }) } } + +#[cfg(target_os = "android")] +pub fn android_init( + android_app: winit::platform::android::activity::AndroidApp, +) -> Result<(), String> { + event_loop::ANDROID_APP.set(android_app).map_err(|_| "android_init called twice".into()) +} diff --git a/internal/renderers/femtovg/lib.rs b/internal/renderers/femtovg/lib.rs index a35cf7a28ea..a4217c0cd60 100644 --- a/internal/renderers/femtovg/lib.rs +++ b/internal/renderers/femtovg/lib.rs @@ -373,6 +373,10 @@ impl Renderer for FemtoVGRenderer { &self, data: &'static [u8], ) -> Result<(), Box> { + // FIXME: this panics + #[cfg(target_os = "android")] + return Ok(()); + fonts::register_font_from_memory(data) }