From f57561964cde6f3ff77c26ffec54b92116f49921 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Thu, 18 Jul 2024 14:06:37 +0200 Subject: [PATCH] chore(deps): Upgrade to `ndk 0.9` and fix thread-safety interactions (#956) Most changes were copied over from my `wry` PR at https://github.com/tauri-apps/wry/pull/1296. Most notably a `&ThreadLooper` is now passed to `wry::android_setup()` because we have one, and it gives important safety guarantees when it comes to registering callbacks on this looper, without (unnecessarily!) requiring `Send`. A thread-local requirement already exists for the `JNIEnv` that is passed around anyway. Also note that certain workarounds and illogical inverted passes around `key_code()` handling are no longer needed, as the `ndk` crate now passes an `enum` with the raw `i32` around so that the `.into()` conversion for `i32` (the correct type) now becomes lossless. --- .changes/ndk-0.9.md | 7 +++++++ Cargo.toml | 4 ++-- examples/transparent.rs | 1 + src/keyboard.rs | 2 +- src/platform_impl/android/mod.rs | 19 ++++++----------- src/platform_impl/android/ndk_glue.rs | 30 ++++++++++++++++----------- 6 files changed, 35 insertions(+), 28 deletions(-) create mode 100644 .changes/ndk-0.9.md diff --git a/.changes/ndk-0.9.md b/.changes/ndk-0.9.md new file mode 100644 index 000000000..ad6ce8079 --- /dev/null +++ b/.changes/ndk-0.9.md @@ -0,0 +1,7 @@ +--- +"tao": minor +--- + +**Breaking change**: Upgrade `ndk` crate to `0.9` and `ndk-sys` crate to `0.6`. Types from the `ndk` crate are used in public API surface. +**Breaking change**: Change `NativeKeyCode::Android(u32)` type to use `i32`, which is the native type used by all Android API. +**Breaking change**: The `setup` function passed to `android_binding!()` must now take a `&ThreadLooper` instead of `&ForeignLooper`, matching the `wry` change in https://github.com/tauri-apps/wry/pull/1296. diff --git a/Cargo.toml b/Cargo.toml index 9843710a5..a88c564d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -97,8 +97,8 @@ once_cell = "1" [target."cfg(target_os = \"android\")".dependencies] jni = "0.21" -ndk = "0.7" -ndk-sys = "0.4" +ndk = "0.9" +ndk-sys = "0.6" ndk-context = "0.1" tao-macros = { version = "0.1.0", path = "./tao-macros" } diff --git a/examples/transparent.rs b/examples/transparent.rs index 6439748a4..6e6b571c7 100644 --- a/examples/transparent.rs +++ b/examples/transparent.rs @@ -2,6 +2,7 @@ // Copyright 2021-2023 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 +#[cfg(windows)] use std::{num::NonZeroU32, rc::Rc}; use tao::{ diff --git a/src/keyboard.rs b/src/keyboard.rs index 29b193774..115d2410c 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -192,7 +192,7 @@ pub enum NativeKeyCode { /// This is the android "key code" of the event as returned by /// `KeyEvent.getKeyCode()` - Android(u32), + Android(i32), } /// Represents the code of a physical key. diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index 72ae99053..896f064d5 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -17,10 +17,8 @@ use ndk::{ event::{InputEvent, KeyAction, MotionAction}, looper::{ForeignLooper, Poll, ThreadLooper}, }; -use ndk_sys::AKeyEvent_getKeyCode; use std::{ collections::VecDeque, - convert::TryInto, sync::RwLock, time::{Duration, Instant}, }; @@ -190,7 +188,7 @@ impl EventLoop { }, Some(EventSource::InputQueue) => { if let Some(input_queue) = ndk_glue::input_queue().as_ref() { - while let Ok(Some(event)) = input_queue.get_event() { + while let Ok(Some(event)) = input_queue.event() { if let Some(event) = input_queue.pre_dispatch(event) { let mut handled = true; let window_id = window::WindowId(WindowId); @@ -253,16 +251,9 @@ impl EventLoop { _ => event::ElementState::Released, }; - // We use the unsafe function directly because - // we want to forward the keycode value even if it doesn't have a variant - // defined in the ndk crate. - let keycode_u32 = unsafe { AKeyEvent_getKeyCode(key.ptr().as_ptr()) as u32 }; - let keycode = keycode_u32 - .try_into() - .unwrap_or(ndk::event::Keycode::Unknown); - let physical_key = - KeyCode::Unidentified(NativeKeyCode::Android(keycode.into())); - let native = NativeKeyCode::Android(keycode_u32); + let keycode = key.key_code(); + let native = NativeKeyCode::Android(keycode.into()); + let physical_key = KeyCode::Unidentified(native); let logical_key = keycode_to_logical(keycode, native); // TODO: maybe use getUnicodeChar to get the logical key @@ -284,6 +275,7 @@ impl EventLoop { }; call_event_handler!(event_handler, self.window_target(), control_flow, event); } + _ => {} }; input_queue.finish_event(event, handled); } @@ -1202,6 +1194,7 @@ fn keycode_to_logical(keycode: ndk::event::Keycode, native: NativeKeyCode) -> Ke ThumbsUp => Key::Unidentified(native), ThumbsDown => Key::Unidentified(native), ProfileSwitch => Key::Unidentified(native), + _ => Key::Unidentified(native), } } diff --git a/src/platform_impl/android/ndk_glue.rs b/src/platform_impl/android/ndk_glue.rs index cb7678339..5b0de40fb 100644 --- a/src/platform_impl/android/ndk_glue.rs +++ b/src/platform_impl/android/ndk_glue.rs @@ -120,17 +120,19 @@ pub fn content_rect() -> Rect { CONTENT_RECT.read().unwrap().clone() } -static PIPE: Lazy<[RawFd; 2]> = Lazy::new(|| { +pub static PIPE: Lazy<[OwnedFd; 2]> = Lazy::new(|| { let mut pipe: [RawFd; 2] = Default::default(); unsafe { libc::pipe(pipe.as_mut_ptr()) }; - pipe + pipe.map(|fd| unsafe { OwnedFd::from_raw_fd(fd) }) }); pub fn poll_events() -> Option { unsafe { let size = std::mem::size_of::(); let mut event = Event::Start; - if libc::read(PIPE[0], &mut event as *mut _ as *mut _, size) == size as libc::ssize_t { + if libc::read(PIPE[0].as_raw_fd(), &mut event as *mut _ as *mut _, size) + == size as libc::ssize_t + { Some(event) } else { None @@ -141,7 +143,7 @@ pub fn poll_events() -> Option { unsafe fn wake(event: Event) { log::trace!("{:?}", event); let size = std::mem::size_of::(); - let res = libc::write(PIPE[1], &event as *const _ as *const _, size); + let res = libc::write(PIPE[1].as_raw_fd(), &event as *const _ as *const _, size); assert_eq!(res, size as libc::ssize_t); } @@ -179,7 +181,7 @@ pub unsafe fn create( mut env: JNIEnv, _jclass: JClass, jobject: JObject, - setup: unsafe fn(&str, JNIEnv, &ForeignLooper, GlobalRef), + setup: unsafe fn(&str, JNIEnv, &ThreadLooper, GlobalRef), main: fn(), ) { //-> jobjectArray { @@ -204,16 +206,20 @@ pub unsafe fn create( activity.as_obj().as_raw() as *mut _, ); - let looper = ThreadLooper::for_thread().unwrap().into_foreign(); + let looper = ThreadLooper::for_thread().unwrap(); setup(PACKAGE.get().unwrap(), env, &looper, activity); - let mut logpipe: [RawFd; 2] = Default::default(); - libc::pipe(logpipe.as_mut_ptr()); - libc::dup2(logpipe[1], libc::STDOUT_FILENO); - libc::dup2(logpipe[1], libc::STDERR_FILENO); + let logpipe = { + let mut logpipe: [RawFd; 2] = Default::default(); + libc::pipe(logpipe.as_mut_ptr()); + libc::dup2(logpipe[1], libc::STDOUT_FILENO); + libc::dup2(logpipe[1], libc::STDERR_FILENO); + + logpipe.map(|fd| unsafe { OwnedFd::from_raw_fd(fd) }) + }; thread::spawn(move || { let tag = CStr::from_bytes_with_nul(b"RustStdoutStderr\0").unwrap(); - let file = File::from_raw_fd(logpipe[0]); + let file = File::from_raw_fd(logpipe[0].as_raw_fd()); let mut reader = BufReader::new(file); let mut buffer = String::new(); loop { @@ -236,7 +242,7 @@ pub unsafe fn create( let foreign = looper.into_foreign(); foreign .add_fd( - PIPE[0], + PIPE[0].as_fd(), NDK_GLUE_LOOPER_EVENT_PIPE_IDENT, FdEvent::INPUT, std::ptr::null_mut(),