From 9d56d0fbadd35364f905884f619cdefed69b47c3 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Sat, 7 Oct 2023 18:12:58 +0200 Subject: [PATCH] ndk/native_window: Implement `HasWindowHandle` for 0.4 and 0.6 (and maintain 0.5) Following [the same strategy in winit], move `raw-window-handle 0.5` behind a `rwh_05` feature and add `raw-window-handle 0.4` and the newly released `raw-window-handle 0.6` behind a corresponding `rwh04`/`rwh_06` feature. The new **non-raw** trait and **lifetimed** type since `0.6` have been implemented instead, as `raw-window-handle` provides blanket implementations to coerce/convert back to `Raw*` types. [the same strategy in winit]: https://github.com/rust-windowing/winit/pull/3126 --- ndk/CHANGELOG.md | 1 + ndk/Cargo.toml | 7 ++++-- ndk/src/native_window.rs | 49 ++++++++++++++++++++++++++++++---------- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/ndk/CHANGELOG.md b/ndk/CHANGELOG.md index 816b55c5..3b00bfca 100644 --- a/ndk/CHANGELOG.md +++ b/ndk/CHANGELOG.md @@ -28,6 +28,7 @@ - native_window: Add `set_buffers_transform()`, `try_allocate_buffers()` and `set_frame_rate*()`. (#425) - hardware_buffer: Add `id()` to retrieve a system-wide unique identifier for a `HardwareBuffer`. (#428) - **Breaking:** bitmap: Strip `Android` prefix from structs and enums, and `Bitmap` from `Result`. (#430) +- **Breaking:** `raw-window-handle 0.5` support is now behind an _optional_ `rwh_05` crate feature and `raw-window-handle` `0.4` and `0.6` support is provided via the new `rwh_04` and (default-enabled) `rwh_06` crate features. (#434) # 0.7.0 (2022-07-24) diff --git a/ndk/Cargo.toml b/ndk/Cargo.toml index 86d3e96e..67b2a98d 100644 --- a/ndk/Cargo.toml +++ b/ndk/Cargo.toml @@ -13,7 +13,8 @@ repository = "https://github.com/rust-mobile/ndk" rust-version = "1.66" [features] -all = ["audio", "bitmap","media", "api-level-31"] +default = ["rwh_06"] +all = ["audio", "bitmap","media", "api-level-31", "rwh_04", "rwh_05", "rwh_06"] audio = ["ffi/audio", "api-level-26"] bitmap = ["ffi/bitmap"] @@ -36,7 +37,9 @@ bitflags = "2.0.0" jni-sys = "0.3.0" log = "0.4" num_enum = "0.7" -raw-window-handle = "0.5" +rwh_04 = { package = "raw-window-handle", version = "0.4", optional = true } +rwh_05 = { package = "raw-window-handle", version = "0.5", optional = true } +rwh_06 = { package = "raw-window-handle", version = "0.6", optional = true } thiserror = "1.0.23" [dependencies.jni] diff --git a/ndk/src/native_window.rs b/ndk/src/native_window.rs index cf421dc4..2734e9ec 100644 --- a/ndk/src/native_window.rs +++ b/ndk/src/native_window.rs @@ -6,8 +6,7 @@ use crate::utils::status_to_io_result; pub use super::hardware_buffer_format::HardwareBufferFormat; use jni_sys::{jobject, JNIEnv}; -use raw_window_handle::{AndroidNdkWindowHandle, HasRawWindowHandle, RawWindowHandle}; -use std::{ffi::c_void, io::Result, mem::MaybeUninit, ptr::NonNull}; +use std::{ffi::c_void, io, mem::MaybeUninit, ptr::NonNull}; pub type Rect = ffi::ARect; @@ -39,11 +38,34 @@ impl Clone for NativeWindow { } } -unsafe impl HasRawWindowHandle for NativeWindow { - fn raw_window_handle(&self) -> RawWindowHandle { - let mut handle = AndroidNdkWindowHandle::empty(); - handle.a_native_window = self.ptr.as_ptr() as *mut c_void; - RawWindowHandle::AndroidNdk(handle) +#[cfg(feature = "rwh_04")] +unsafe impl rwh_04::HasRawWindowHandle for NativeWindow { + fn raw_window_handle(&self) -> rwh_04::RawWindowHandle { + let mut handle = rwh_04::AndroidNdkHandle::empty(); + handle.a_native_window = self.ptr.as_ptr().cast(); + rwh_04::RawWindowHandle::AndroidNdk(handle) + } +} + +#[cfg(feature = "rwh_05")] +unsafe impl rwh_05::HasRawWindowHandle for NativeWindow { + fn raw_window_handle(&self) -> rwh_05::RawWindowHandle { + let mut handle = rwh_05::AndroidNdkWindowHandle::empty(); + handle.a_native_window = self.ptr.as_ptr().cast(); + rwh_05::RawWindowHandle::AndroidNdk(handle) + } +} + +#[cfg(feature = "rwh_06")] +impl rwh_06::HasWindowHandle for NativeWindow { + fn window_handle(&self) -> Result, rwh_06::HandleError> { + let handle = rwh_06::AndroidNdkWindowHandle::new(self.ptr.cast()); + let handle = rwh_06::RawWindowHandle::AndroidNdk(handle); + // SAFETY: All fields of the "raw" `AndroidNdkWindowHandle` struct are filled out. The + // returned pointer is also kept valid by `NativeWindow` (until `Drop`), which is lifetime- + // borrowed in the returned `WindowHandle<'_>` and cannot be outlived. Its value won't + // change throughout the lifetime of this `NativeWindow`. + Ok(unsafe { rwh_06::WindowHandle::borrow_raw(handle) }) } } @@ -98,7 +120,7 @@ impl NativeWindow { width: i32, height: i32, format: Option, - ) -> Result<()> { + ) -> io::Result<()> { let format = format.map_or(0, |f| { u32::from(f) .try_into() @@ -112,7 +134,7 @@ impl NativeWindow { /// Set a transform that will be applied to future buffers posted to the window. #[cfg(feature = "api-level-26")] - pub fn set_buffers_transform(&self, transform: NativeWindowTransform) -> Result<()> { + pub fn set_buffers_transform(&self, transform: NativeWindowTransform) -> io::Result<()> { let status = unsafe { ffi::ANativeWindow_setBuffersTransform(self.ptr.as_ptr(), transform.bits() as i32) }; @@ -133,7 +155,7 @@ impl NativeWindow { &self, frame_rate: f32, compatibility: FrameRateCompatibility, - ) -> Result<()> { + ) -> io::Result<()> { let compatibility = (compatibility as u32) .try_into() .expect("i8 overflow in FrameRateCompatibility"); @@ -180,7 +202,7 @@ impl NativeWindow { frame_rate: f32, compatibility: FrameRateCompatibility, change_frame_rate_strategy: ChangeFrameRateStrategy, - ) -> Result<()> { + ) -> io::Result<()> { let compatibility = (compatibility as u32) .try_into() .expect("i8 overflow in FrameRateCompatibility"); @@ -235,7 +257,10 @@ impl NativeWindow { /// /// Optionally pass the region you intend to draw into `dirty_bounds`. When this function /// returns it is updated (commonly enlarged) with the actual area the caller needs to redraw. - pub fn lock(&self, dirty_bounds: Option<&mut Rect>) -> Result> { + pub fn lock( + &self, + dirty_bounds: Option<&mut Rect>, + ) -> io::Result> { let dirty_bounds = match dirty_bounds { Some(dirty_bounds) => dirty_bounds, None => std::ptr::null_mut(),