use crate::log::error;
use core::{ffi::c_void, marker::PhantomData, mem::MaybeUninit, ptr::NonNull};
use ohos_sys::ace::xcomponent::native_interface_xcomponent::OH_NativeXComponent_GetXComponentSize;
use ohos_sys::{
ace::xcomponent::native_interface_xcomponent::{
OH_NativeXComponent, OH_NativeXComponent_GetTouchEvent, OH_NativeXComponent_TouchEvent,
},
native_window::OHNativeWindow,
};
mod log;
pub struct Size {
pub width: u64,
pub height: u64,
_opaque: [u64; 0],
}
pub struct XComponent<'a> {
xcomponent: NonNull<OH_NativeXComponent>,
window: NonNull<OHNativeWindow>,
phantom: PhantomData<&'a mut OH_NativeXComponent>,
}
impl<'a> XComponent<'a> {
pub fn new(
xcomponent: *mut OH_NativeXComponent,
window: *mut c_void,
) -> Option<XComponent<'a>> {
Some(XComponent {
xcomponent: NonNull::new(xcomponent)?,
window: NonNull::new(window.cast())?,
phantom: PhantomData,
})
}
pub fn get_touch_event(&self) -> Result<OH_NativeXComponent_TouchEvent, i32> {
let touch_event = unsafe {
let mut touch_event: MaybeUninit<OH_NativeXComponent_TouchEvent> =
MaybeUninit::uninit();
let res = OH_NativeXComponent_GetTouchEvent(
self.xcomponent.as_ptr(),
self.window.as_ptr().cast(),
touch_event.as_mut_ptr(),
);
if res != 0 {
error!("OH_NativeXComponent_GetTouchEvent failed with {res}");
return Err(res);
}
touch_event.assume_init()
};
Ok(touch_event)
}
pub fn size(&self) -> Size {
let mut width: u64 = 0;
let mut height: u64 = 0;
let res = unsafe {
OH_NativeXComponent_GetXComponentSize(
self.xcomponent.as_ptr(),
self.window.as_ptr() as *const c_void,
&mut width as *mut _,
&mut height as *mut _,
)
};
assert_eq!(res, 0, "OH_NativeXComponent_GetXComponentSize failed");
Size {
width,
height,
_opaque: [],
}
}
}
#[cfg(feature = "register")]
#[cfg_attr(docsrs, doc(cfg(feature = "register")))]
#[derive(Debug)]
pub enum RegisterCallbackError {
XcomponentPropertyMissing(String),
UnwrapXComponentFailed(i32),
RegisterCallbackFailed(i32),
}
#[cfg(feature = "register")]
#[cfg_attr(docsrs, doc(cfg(feature = "register")))]
impl Into<String> for RegisterCallbackError {
fn into(self) -> String {
format!("{:?}", self)
}
}
#[cfg(feature = "register")]
#[cfg_attr(docsrs, doc(cfg(feature = "register")))]
pub fn register_xcomponent_callbacks(
exports: &napi_ohos::JsObject,
env: &napi_ohos::Env,
callbacks: &'static ohos_sys::ace::xcomponent::native_interface_xcomponent::OH_NativeXComponent_Callback,
) -> Result<(), RegisterCallbackError> {
use napi_ohos::NapiRaw;
use ohos_sys::ace::xcomponent::native_interface_xcomponent::OH_NativeXComponent_RegisterCallback;
let xcomponent_js_object = exports
.get_named_property::<napi_ohos::JsObject>("__NATIVE_XCOMPONENT_OBJ__")
.map_err(|e| RegisterCallbackError::XcomponentPropertyMissing(e.to_string()))?;
let raw = unsafe { xcomponent_js_object.raw() };
let raw_env = env.raw();
let mut native_xcomponent: *mut OH_NativeXComponent = core::ptr::null_mut();
let res = unsafe {
napi_ohos::sys::napi_unwrap(
raw_env,
raw,
&mut native_xcomponent as *mut *mut OH_NativeXComponent as *mut *mut c_void,
)
};
if res != 0 {
return Err(RegisterCallbackError::UnwrapXComponentFailed(res));
}
let res =
unsafe { OH_NativeXComponent_RegisterCallback(native_xcomponent, callbacks as *const _ as *mut _) };
if res != 0 {
return Err(RegisterCallbackError::RegisterCallbackFailed(res));
}
Ok(())
}