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::{convert::TryFrom, ffi::c_void, io::Result, ptr::NonNull};
#[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct NativeWindow {
ptr: NonNull<ffi::ANativeWindow>,
}
unsafe impl Send for NativeWindow {}
unsafe impl Sync for NativeWindow {}
impl Drop for NativeWindow {
fn drop(&mut self) {
unsafe { ffi::ANativeWindow_release(self.ptr.as_ptr()) }
}
}
impl Clone for NativeWindow {
fn clone(&self) -> Self {
unsafe { ffi::ANativeWindow_acquire(self.ptr.as_ptr()) }
Self { ptr: self.ptr }
}
}
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)
}
}
impl NativeWindow {
pub unsafe fn from_ptr(ptr: NonNull<ffi::ANativeWindow>) -> Self {
Self { ptr }
}
pub unsafe fn clone_from_ptr(ptr: NonNull<ffi::ANativeWindow>) -> Self {
ffi::ANativeWindow_acquire(ptr.as_ptr());
Self::from_ptr(ptr)
}
pub fn ptr(&self) -> NonNull<ffi::ANativeWindow> {
self.ptr
}
pub fn height(&self) -> i32 {
unsafe { ffi::ANativeWindow_getHeight(self.ptr.as_ptr()) }
}
pub fn width(&self) -> i32 {
unsafe { ffi::ANativeWindow_getWidth(self.ptr.as_ptr()) }
}
pub fn format(&self) -> HardwareBufferFormat {
let value = unsafe { ffi::ANativeWindow_getFormat(self.ptr.as_ptr()) };
let value = u32::try_from(value).unwrap();
HardwareBufferFormat::try_from(value).unwrap()
}
pub fn set_buffers_geometry(
&self,
width: i32,
height: i32,
format: Option<HardwareBufferFormat>,
) -> Result<()> {
let format: u32 = format.map_or(0, |f| f.into());
let status = unsafe {
ffi::ANativeWindow_setBuffersGeometry(self.ptr.as_ptr(), width, height, format as i32)
};
status_to_io_result(status, ())
}
pub unsafe fn from_surface(env: *mut JNIEnv, surface: jobject) -> Option<Self> {
let ptr = ffi::ANativeWindow_fromSurface(env, surface);
Some(Self::from_ptr(NonNull::new(ptr)?))
}
#[cfg(feature = "api-level-26")]
pub unsafe fn to_surface(&self, env: *mut JNIEnv) -> jobject {
ffi::ANativeWindow_toSurface(env, self.ptr().as_ptr())
}
}