Skip to main content

ohos_window_manager_binding/
manager.rs

1#[cfg(feature = "api-21")]
2use std::ffi::CStr;
3#[cfg(feature = "api-17")]
4use std::ptr;
5
6#[cfg(feature = "api-21")]
7use ohos_native_window_manager_sys::{
8    OH_PixelmapNative, OH_WindowManager_GetAllMainWindowInfo,
9    OH_WindowManager_GetMainWindowSnapshot, OH_WindowManager_ReleaseAllMainWindowInfo,
10    OH_WindowManager_ReleaseMainWindowSnapshot, WindowManager_MainWindowInfo,
11    WindowManager_WindowSnapshotConfig,
12};
13#[cfg(feature = "api-17")]
14use ohos_native_window_manager_sys::{
15    OH_WindowManager_GetAllWindowLayoutInfoList, OH_WindowManager_ReleaseAllWindowLayoutInfoList,
16};
17
18#[cfg(feature = "api-17")]
19use crate::error::{check, Error, Result};
20#[cfg(feature = "api-21")]
21use crate::types::MainWindowInfo;
22#[cfg(feature = "api-17")]
23use crate::types::Rect;
24
25#[cfg(feature = "api-21")]
26pub type RawPixelMap = OH_PixelmapNative;
27#[cfg(feature = "api-21")]
28pub type MainWindowSnapshotCallback =
29    unsafe extern "C" fn(snapshot_list: *mut *const RawPixelMap, snapshot_count: usize);
30
31#[cfg(feature = "api-21")]
32#[derive(Clone, Copy, Debug, PartialEq, Eq)]
33pub struct WindowSnapshotConfig {
34    pub use_cache: bool,
35}
36
37#[cfg(feature = "api-21")]
38impl Default for WindowSnapshotConfig {
39    fn default() -> Self {
40        Self { use_cache: true }
41    }
42}
43
44#[cfg(feature = "api-21")]
45impl From<WindowSnapshotConfig> for WindowManager_WindowSnapshotConfig {
46    fn from(value: WindowSnapshotConfig) -> Self {
47        Self {
48            useCache: value.use_cache,
49        }
50    }
51}
52
53#[derive(Clone, Copy, Debug, Default)]
54pub struct WindowManager;
55
56impl WindowManager {
57    #[cfg(feature = "api-17")]
58    pub fn visible_window_layouts(display_id: i64) -> Result<Vec<Rect>> {
59        let mut raw = ptr::null_mut();
60        let mut len = 0;
61        check(unsafe {
62            OH_WindowManager_GetAllWindowLayoutInfoList(display_id, &mut raw, &mut len)
63        })?;
64
65        if len > 0 && raw.is_null() {
66            return Err(Error::UnexpectedNull);
67        }
68
69        let layouts = if len == 0 {
70            Vec::new()
71        } else {
72            unsafe { std::slice::from_raw_parts(raw, len) }
73                .iter()
74                .copied()
75                .map(Rect::from)
76                .collect()
77        };
78        if !raw.is_null() {
79            unsafe { OH_WindowManager_ReleaseAllWindowLayoutInfoList(raw) };
80        }
81        Ok(layouts)
82    }
83
84    #[cfg(feature = "api-21")]
85    pub fn main_windows() -> Result<Vec<MainWindowInfo>> {
86        let mut raw = ptr::null_mut();
87        let mut len = 0;
88        check(unsafe { OH_WindowManager_GetAllMainWindowInfo(&mut raw, &mut len) })?;
89
90        if len > 0 && raw.is_null() {
91            return Err(Error::UnexpectedNull);
92        }
93
94        let windows = if len == 0 {
95            Vec::new()
96        } else {
97            unsafe { std::slice::from_raw_parts(raw, len) }
98                .iter()
99                .map(main_window_info_from_raw)
100                .collect()
101        };
102        if !raw.is_null() {
103            unsafe { OH_WindowManager_ReleaseAllMainWindowInfo(raw) };
104        }
105        Ok(windows)
106    }
107
108    /// Requests snapshots for the supplied main-window IDs.
109    ///
110    /// The native API invokes `callback` asynchronously. The callback must
111    /// release the returned native list according to the platform contract.
112    #[cfg(feature = "api-21")]
113    pub fn request_main_window_snapshots(
114        window_ids: &mut [i32],
115        config: WindowSnapshotConfig,
116        callback: MainWindowSnapshotCallback,
117    ) -> Result<()> {
118        check(unsafe {
119            OH_WindowManager_GetMainWindowSnapshot(
120                window_ids.as_mut_ptr(),
121                window_ids.len(),
122                config.into(),
123                Some(callback),
124            )
125        })
126    }
127
128    /// Releases a snapshot list returned to a native snapshot callback.
129    ///
130    /// # Safety
131    ///
132    /// `snapshot_list` must be the exact pointer returned by
133    /// `OH_WindowManager_GetMainWindowSnapshot`, and it must not have been
134    /// released previously.
135    #[cfg(feature = "api-21")]
136    pub unsafe fn release_main_window_snapshots(snapshot_list: *const RawPixelMap) {
137        unsafe { OH_WindowManager_ReleaseMainWindowSnapshot(snapshot_list) };
138    }
139}
140
141#[cfg(feature = "api-21")]
142fn main_window_info_from_raw(raw: &WindowManager_MainWindowInfo) -> MainWindowInfo {
143    let label = if raw.label.is_null() {
144        None
145    } else {
146        Some(
147            unsafe { CStr::from_ptr(raw.label) }
148                .to_string_lossy()
149                .into_owned(),
150        )
151    };
152    MainWindowInfo {
153        display_id: raw.displayId,
154        window_id: raw.windowId,
155        showing: raw.showing,
156        label,
157    }
158}
159
160#[cfg(all(test, feature = "api-21"))]
161mod tests {
162    use std::ffi::CString;
163
164    use super::*;
165
166    #[test]
167    fn copies_main_window_label() {
168        let label = CString::new("main window").unwrap();
169        let raw = WindowManager_MainWindowInfo {
170            displayId: 7,
171            windowId: 8,
172            showing: true,
173            label: label.as_ptr(),
174        };
175
176        assert_eq!(
177            main_window_info_from_raw(&raw),
178            MainWindowInfo {
179                display_id: 7,
180                window_id: 8,
181                showing: true,
182                label: Some("main window".to_string()),
183            }
184        );
185    }
186
187    #[test]
188    fn accepts_missing_main_window_label() {
189        let raw = WindowManager_MainWindowInfo {
190            displayId: 1,
191            windowId: 2,
192            showing: false,
193            label: ptr::null(),
194        };
195
196        assert_eq!(main_window_info_from_raw(&raw).label, None);
197    }
198
199    #[test]
200    fn snapshot_config_defaults_to_using_cache() {
201        assert!(WindowSnapshotConfig::default().use_cache);
202    }
203}