Skip to main content

ohos_window_manager_binding/
window.rs

1use ohos_native_window_manager_sys::{
2    Input_KeyEvent, OH_NativeWindowManager_KeyEventFilter,
3    OH_NativeWindowManager_RegisterKeyEventFilter, OH_NativeWindowManager_UnregisterKeyEventFilter,
4};
5
6#[cfg(feature = "api-15")]
7use std::ffi::CString;
8#[cfg(feature = "api-15")]
9use std::mem::MaybeUninit;
10#[cfg(feature = "api-20")]
11use std::ptr::NonNull;
12
13#[cfg(feature = "api-15")]
14use ohos_image_native_binding::PixelMapNativeHandle;
15#[cfg(feature = "api-20")]
16use ohos_native_window_manager_sys::OH_WindowManager_InjectTouchEvent;
17#[cfg(feature = "api-15")]
18use ohos_native_window_manager_sys::{
19    Input_MouseEvent, Input_TouchEvent, OH_NativeWindowManager_MouseEventFilter,
20    OH_NativeWindowManager_RegisterMouseEventFilter,
21    OH_NativeWindowManager_RegisterTouchEventFilter, OH_NativeWindowManager_TouchEventFilter,
22    OH_NativeWindowManager_UnregisterMouseEventFilter,
23    OH_NativeWindowManager_UnregisterTouchEventFilter, OH_WindowManager_GetWindowAvoidArea,
24    OH_WindowManager_GetWindowProperties, OH_WindowManager_IsWindowShown,
25    OH_WindowManager_SetWindowBackgroundColor, OH_WindowManager_SetWindowBrightness,
26    OH_WindowManager_SetWindowFocusable, OH_WindowManager_SetWindowKeepScreenOn,
27    OH_WindowManager_SetWindowNavigationBarEnabled, OH_WindowManager_SetWindowPrivacyMode,
28    OH_WindowManager_SetWindowStatusBarColor, OH_WindowManager_SetWindowStatusBarEnabled,
29    OH_WindowManager_SetWindowTouchable, OH_WindowManager_ShowWindow, OH_WindowManager_Snapshot,
30    WindowManager_AvoidArea, WindowManager_WindowProperties,
31};
32#[cfg(feature = "api-26")]
33use ohos_native_window_manager_sys::{
34    OH_NativeWindowManager_GetKeyEventFilter, OH_NativeWindowManager_GetMouseEventFilter,
35    OH_NativeWindowManager_GetTouchEventFilter,
36    OH_WindowManager_RegisterFrameMetricsMeasuredCallback,
37    OH_WindowManager_UnregisterFrameMetricsMeasuredCallback,
38};
39#[cfg(feature = "api-22")]
40use ohos_native_window_manager_sys::{OH_WindowManager_LockCursor, OH_WindowManager_UnlockCursor};
41
42#[cfg(feature = "api-15")]
43use crate::error::{check, Error};
44use crate::error::{check_status, Result};
45#[cfg(feature = "api-15")]
46use crate::types::{AvoidArea, AvoidAreaType, WindowProperties};
47#[cfg(feature = "api-26")]
48use crate::FrameMetricsMeasuredCallback;
49
50pub type KeyEventFilter = unsafe extern "C" fn(*mut Input_KeyEvent) -> bool;
51#[cfg(feature = "api-15")]
52pub type MouseEventFilter = unsafe extern "C" fn(*mut Input_MouseEvent) -> bool;
53#[cfg(feature = "api-15")]
54pub type TouchEventFilter = unsafe extern "C" fn(*mut Input_TouchEvent) -> bool;
55
56/// A borrowed handle to a window managed by OpenHarmony.
57///
58/// This type does not own or destroy the native window. Its ID must come from
59/// the ArkTS window properties or another trusted platform API.
60#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
61pub struct Window {
62    id: i32,
63}
64
65impl Window {
66    pub const fn from_id(id: i32) -> Self {
67        Self { id }
68    }
69
70    pub const fn id(self) -> i32 {
71        self.id
72    }
73
74    pub fn register_key_event_filter(self, filter: KeyEventFilter) -> Result<()> {
75        let status = unsafe {
76            OH_NativeWindowManager_RegisterKeyEventFilter(
77                self.id,
78                Some(filter) as OH_NativeWindowManager_KeyEventFilter,
79            )
80        };
81        check_status(status)
82    }
83
84    pub fn unregister_key_event_filter(self) -> Result<()> {
85        check_status(unsafe { OH_NativeWindowManager_UnregisterKeyEventFilter(self.id) })
86    }
87
88    #[cfg(feature = "api-15")]
89    pub fn set_status_bar_enabled(self, enabled: bool, animate: bool) -> Result<()> {
90        check(unsafe { OH_WindowManager_SetWindowStatusBarEnabled(self.id, enabled, animate) })
91    }
92
93    #[cfg(feature = "api-15")]
94    pub fn set_status_bar_color(self, argb: u32) -> Result<()> {
95        check(unsafe { OH_WindowManager_SetWindowStatusBarColor(self.id, argb as i32) })
96    }
97
98    #[cfg(feature = "api-15")]
99    pub fn set_navigation_bar_enabled(self, enabled: bool, animate: bool) -> Result<()> {
100        check(unsafe { OH_WindowManager_SetWindowNavigationBarEnabled(self.id, enabled, animate) })
101    }
102
103    #[cfg(feature = "api-15")]
104    pub fn avoid_area(self, area_type: AvoidAreaType) -> Result<AvoidArea> {
105        let mut raw = MaybeUninit::<WindowManager_AvoidArea>::uninit();
106        check(unsafe {
107            OH_WindowManager_GetWindowAvoidArea(self.id, area_type.into(), raw.as_mut_ptr())
108        })?;
109        Ok(unsafe { raw.assume_init() }.into())
110    }
111
112    #[cfg(feature = "api-15")]
113    pub fn is_shown(self) -> Result<bool> {
114        let mut shown = false;
115        check(unsafe { OH_WindowManager_IsWindowShown(self.id, &mut shown) })?;
116        Ok(shown)
117    }
118
119    #[cfg(feature = "api-15")]
120    pub fn show(self) -> Result<()> {
121        check(unsafe { OH_WindowManager_ShowWindow(self.id) })
122    }
123
124    #[cfg(feature = "api-15")]
125    pub fn set_touchable(self, touchable: bool) -> Result<()> {
126        check(unsafe { OH_WindowManager_SetWindowTouchable(self.id, touchable) })
127    }
128
129    #[cfg(feature = "api-15")]
130    pub fn set_focusable(self, focusable: bool) -> Result<()> {
131        check(unsafe { OH_WindowManager_SetWindowFocusable(self.id, focusable) })
132    }
133
134    #[cfg(feature = "api-15")]
135    pub fn set_background_color(self, color: &str) -> Result<()> {
136        let color = c_string(color)?;
137        check(unsafe { OH_WindowManager_SetWindowBackgroundColor(self.id, color.as_ptr()) })
138    }
139
140    #[cfg(feature = "api-15")]
141    pub fn set_brightness(self, brightness: f32) -> Result<()> {
142        check(unsafe { OH_WindowManager_SetWindowBrightness(self.id, brightness) })
143    }
144
145    #[cfg(feature = "api-15")]
146    pub fn set_keep_screen_on(self, keep_screen_on: bool) -> Result<()> {
147        check(unsafe { OH_WindowManager_SetWindowKeepScreenOn(self.id, keep_screen_on) })
148    }
149
150    #[cfg(feature = "api-15")]
151    pub fn set_privacy_mode(self, privacy: bool) -> Result<()> {
152        check(unsafe { OH_WindowManager_SetWindowPrivacyMode(self.id, privacy) })
153    }
154
155    #[cfg(feature = "api-15")]
156    pub fn properties(self) -> Result<WindowProperties> {
157        let mut raw = MaybeUninit::<WindowManager_WindowProperties>::uninit();
158        check(unsafe { OH_WindowManager_GetWindowProperties(self.id, raw.as_mut_ptr()) })?;
159        Ok(unsafe { raw.assume_init() }.into())
160    }
161
162    #[cfg(feature = "api-15")]
163    pub fn snapshot(self, pixel_map: PixelMapNativeHandle) -> Result<()> {
164        check(unsafe { OH_WindowManager_Snapshot(self.id, pixel_map.as_raw().cast()) })
165    }
166
167    #[cfg(feature = "api-15")]
168    pub fn register_mouse_event_filter(self, filter: MouseEventFilter) -> Result<()> {
169        let status = unsafe {
170            OH_NativeWindowManager_RegisterMouseEventFilter(
171                self.id,
172                Some(filter) as OH_NativeWindowManager_MouseEventFilter,
173            )
174        };
175        check_status(status)
176    }
177
178    #[cfg(feature = "api-15")]
179    pub fn unregister_mouse_event_filter(self) -> Result<()> {
180        check_status(unsafe { OH_NativeWindowManager_UnregisterMouseEventFilter(self.id) })
181    }
182
183    #[cfg(feature = "api-15")]
184    pub fn register_touch_event_filter(self, filter: TouchEventFilter) -> Result<()> {
185        let status = unsafe {
186            OH_NativeWindowManager_RegisterTouchEventFilter(
187                self.id,
188                Some(filter) as OH_NativeWindowManager_TouchEventFilter,
189            )
190        };
191        check_status(status)
192    }
193
194    #[cfg(feature = "api-15")]
195    pub fn unregister_touch_event_filter(self) -> Result<()> {
196        check_status(unsafe { OH_NativeWindowManager_UnregisterTouchEventFilter(self.id) })
197    }
198
199    /// Injects a native touch event into this window.
200    ///
201    /// # Safety
202    ///
203    /// `event` must point to a live `Input_TouchEvent` created by the
204    /// multimodal input API and must remain valid for the duration of the call.
205    #[cfg(feature = "api-20")]
206    pub unsafe fn inject_touch_event(
207        self,
208        event: NonNull<Input_TouchEvent>,
209        window_x: i32,
210        window_y: i32,
211    ) -> Result<()> {
212        check(unsafe {
213            OH_WindowManager_InjectTouchEvent(self.id, event.as_ptr(), window_x, window_y)
214        })
215    }
216
217    #[cfg(feature = "api-22")]
218    pub fn lock_cursor(self, follow_movement: bool) -> Result<()> {
219        check(unsafe { OH_WindowManager_LockCursor(self.id, follow_movement) })
220    }
221
222    #[cfg(feature = "api-22")]
223    pub fn unlock_cursor(self) -> Result<()> {
224        check(unsafe { OH_WindowManager_UnlockCursor(self.id) })
225    }
226
227    #[cfg(feature = "api-26")]
228    pub fn key_event_filter(self) -> Result<Option<KeyEventFilter>> {
229        let mut filter: OH_NativeWindowManager_KeyEventFilter = None;
230        check_status(unsafe { OH_NativeWindowManager_GetKeyEventFilter(self.id, &mut filter) })?;
231        Ok(filter)
232    }
233
234    #[cfg(feature = "api-26")]
235    pub fn mouse_event_filter(self) -> Result<Option<MouseEventFilter>> {
236        let mut filter: OH_NativeWindowManager_MouseEventFilter = None;
237        check_status(unsafe { OH_NativeWindowManager_GetMouseEventFilter(self.id, &mut filter) })?;
238        Ok(filter)
239    }
240
241    #[cfg(feature = "api-26")]
242    pub fn touch_event_filter(self) -> Result<Option<TouchEventFilter>> {
243        let mut filter: OH_NativeWindowManager_TouchEventFilter = None;
244        check_status(unsafe { OH_NativeWindowManager_GetTouchEventFilter(self.id, &mut filter) })?;
245        Ok(filter)
246    }
247
248    #[cfg(feature = "api-26")]
249    pub fn register_frame_metrics_measured_callback(
250        self,
251        callback: FrameMetricsMeasuredCallback,
252    ) -> Result<()> {
253        check(unsafe {
254            OH_WindowManager_RegisterFrameMetricsMeasuredCallback(self.id, Some(callback))
255        })
256    }
257
258    #[cfg(feature = "api-26")]
259    pub fn unregister_frame_metrics_measured_callback(
260        self,
261        callback: FrameMetricsMeasuredCallback,
262    ) -> Result<()> {
263        check(unsafe {
264            OH_WindowManager_UnregisterFrameMetricsMeasuredCallback(self.id, Some(callback))
265        })
266    }
267}
268
269#[cfg(feature = "api-15")]
270fn c_string(value: &str) -> Result<CString> {
271    CString::new(value).map_err(|_| Error::InteriorNul)
272}
273
274#[cfg(test)]
275mod tests {
276    use super::*;
277
278    #[test]
279    fn preserves_window_id() {
280        let window = Window::from_id(42);
281        assert_eq!(window.id(), 42);
282    }
283
284    #[cfg(feature = "api-15")]
285    #[test]
286    fn validates_strings_before_ffi() {
287        assert_eq!(c_string("#ff00ff").unwrap().to_bytes(), b"#ff00ff");
288        assert_eq!(c_string("#ff\0ff"), Err(Error::InteriorNul));
289    }
290}