Skip to main content

ohos_xcomponent_binding/
xcomponent.rs

1#![allow(clippy::missing_safety_doc)]
2
3use napi_ohos::{
4    bindgen_prelude::{check_status, JsObjectValue, Object},
5    Env, JsValue, Result,
6};
7use napi_sys_ohos as sys;
8use ohos_xcomponent_sys::{
9    OH_NativeXComponent, OH_NativeXComponent_Callback, OH_NATIVE_XCOMPONENT_OBJ,
10};
11use std::{os::raw::c_void, ptr};
12
13use crate::{
14    native_xcomponent::NativeXComponent, tool::resolve_id, TouchEventData, WindowRaw,
15    XComponentOffset, XComponentRaw, XComponentSize,
16};
17
18/// Accept XComponent with env and exports
19/// ### Example
20/// ```no_run
21/// #[module_exports]
22/// pub fn init(exports: Object, env: Env) -> Result<()> {
23///     let xcomponent = XComponent::init(env, exports)?;
24///
25///     Ok(())
26/// }
27/// ```
28#[repr(transparent)]
29pub struct XComponent(NativeXComponent);
30
31impl XComponent {
32    pub fn init(env: Env, exports: Object<'_>) -> Result<Self> {
33        // Safety: static char * we can use it directly.
34        // c char has \0, we should remove it.
35        let xcomponent_obj_name: &str = unsafe {
36            std::str::from_utf8_unchecked(
37                &OH_NATIVE_XCOMPONENT_OBJ[..OH_NATIVE_XCOMPONENT_OBJ.len() - 1],
38            )
39        };
40
41        let export_instance: Object<'_> = exports.get_named_property(xcomponent_obj_name)?;
42        // env.unwrap will check type, so we just use ffi directly.
43        let mut instance = ptr::null_mut();
44        check_status!(
45            unsafe {
46                sys::napi_unwrap(
47                    env.raw(),
48                    export_instance.raw(),
49                    &mut instance as *mut *mut OH_NativeXComponent as *mut *mut c_void,
50                )
51            },
52            "Get OH_NativeXComponent failed."
53        )?;
54
55        let id = resolve_id(instance);
56
57        Ok(XComponent(NativeXComponent {
58            raw: XComponentRaw(instance),
59            id,
60        }))
61    }
62
63    /// Get current xcomponent instance's id
64    pub fn id(&self) -> Result<String> {
65        self.0.id()
66    }
67
68    /// get raw point
69    pub fn raw(&self) -> *mut OH_NativeXComponent {
70        self.0.raw()
71    }
72
73    pub fn set_frame_rate(&self, min: i32, max: i32, expected: i32) -> Result<()> {
74        self.0.set_frame_rate(min, max, expected)
75    }
76
77    /// Register callbacks   
78    /// For multi-mode, it will use hashmap to store all of your callbacks closure.   
79    /// This may cause xcomponent being slower, if you want to avoid this.    
80    /// You can disable feature with `callbacks` and use `register_native_callback`   
81    #[cfg(feature = "callbacks")]
82    pub fn register_callback(&self) -> Result<()> {
83        self.0.register_callback()
84    }
85
86    /// Use ffi to register callbacks directly.
87    pub unsafe fn register_native_callback(
88        &self,
89        callbacks: Box<OH_NativeXComponent_Callback>,
90    ) -> Result<()> {
91        self.0.register_native_callback(callbacks)
92    }
93
94    /// Get current XComponent's size info include width and height.
95    pub fn size(&self, window: WindowRaw) -> Result<XComponentSize> {
96        self.0.size(window)
97    }
98
99    /// Get the offset of the surface held by the current XComponent.
100    pub fn offset(&self, window: WindowRaw) -> Result<XComponentOffset> {
101        self.0.offset(window)
102    }
103
104    pub fn on_frame_callback(&self, cb: fn(XComponentRaw, u64, u64) -> Result<()>) -> Result<()> {
105        self.0.on_frame_callback(cb)
106    }
107
108    pub fn on_surface_changed(&self, cb: fn(XComponentRaw, WindowRaw) -> Result<()>) {
109        self.0.on_surface_changed(cb)
110    }
111
112    pub fn on_surface_created(&self, cb: fn(XComponentRaw, WindowRaw) -> Result<()>) {
113        self.0.on_surface_created(cb)
114    }
115
116    pub fn on_surface_destroyed(&self, cb: fn(XComponentRaw, WindowRaw) -> Result<()>) {
117        self.0.on_surface_destroyed(cb)
118    }
119
120    pub fn on_touch_event(&self, cb: fn(XComponentRaw, WindowRaw, TouchEventData) -> Result<()>) {
121        self.0.on_touch_event(cb)
122    }
123}