fltk/macros/
window.rs

1#[doc(hidden)]
2#[macro_export]
3/// Implements WindowExt
4macro_rules! impl_window_ext {
5    ($name: ident, $flname: ident) => {
6        #[cfg(feature = "rwh06")]
7        impl HasWindowHandle for $name {
8            fn window_handle(&self) ->  Result<WindowHandle<'_>, HandleError> {
9                #[cfg(target_os = "windows")]
10                {
11                    let mut handle = Win32WindowHandle::new(std::num::NonZeroIsize::new(self.raw_handle() as isize).unwrap());
12                    handle.hinstance = std::num::NonZeroIsize::new($crate::app::display() as isize);
13                    return Ok(unsafe { WindowHandle::borrow_raw(RawWindowHandle::Win32(handle)) });
14                }
15
16                #[cfg(target_os = "macos")]
17                {
18                    let raw = self.raw_handle();
19                    unsafe extern "C" {
20                        pub fn cfltk_getContentView(xid: *mut raw::c_void) -> *mut raw::c_void;
21                    }
22                    let cv = unsafe { cfltk_getContentView(raw) };
23                    let handle = AppKitWindowHandle::new(std::ptr::NonNull::new(cv).unwrap());
24                    return Ok(unsafe { WindowHandle::borrow_raw(RawWindowHandle::AppKit(handle)) });
25                }
26
27                #[cfg(target_os = "android")]
28                {
29                    let handle = AndroidNdkWindowHandle::new(std::ptr::NonNull::new(self.raw_handle()).unwrap());
30                    return Ok(unsafe { WindowHandle::borrow_raw(RawWindowHandle::AndroidNdk(handle)) });
31                }
32
33                #[cfg(target_os = "emscripten")]
34                {
35                    let handle = WebCanvasWindowHandle::new(std::ptr::NonNull::new(unsafe { resolve_raw_handle(self.raw_handle() as *mut raw::c_void) }).unwrap());
36                    return Ok(unsafe { WindowHandle::borrow_raw(RawWindowHandle::WebCanvas(handle)) });
37                }
38
39                #[cfg(any(
40                    target_os = "linux",
41                    target_os = "dragonfly",
42                    target_os = "freebsd",
43                    target_os = "netbsd",
44                    target_os = "openbsd",
45                ))]
46                {
47                    if !$crate::app::using_wayland() {
48                        let handle = XlibWindowHandle::new(self.raw_handle() as RawXlibHandle);
49                        return Ok(unsafe { WindowHandle::borrow_raw(RawWindowHandle::Xlib(handle)) });
50                    } else {
51                        let handle = WaylandWindowHandle::new(std::ptr::NonNull::new(unsafe { resolve_raw_handle(self.raw_handle() as *mut raw::c_void) }).unwrap());
52                        return Ok(unsafe { WindowHandle::borrow_raw(RawWindowHandle::Wayland(handle)) });
53                    }
54                }
55            }
56        }
57
58        #[cfg(feature = "rwh06")]
59        impl HasDisplayHandle for $name {
60            fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
61                #[cfg(target_os = "windows")]
62                {
63                    let handle = WindowsDisplayHandle::new();
64                    return Ok(unsafe { DisplayHandle::borrow_raw(RawDisplayHandle::Windows(handle)) });
65                }
66
67                #[cfg(target_os = "macos")]
68                {
69                    let handle = AppKitDisplayHandle::new();
70                    return Ok(unsafe { DisplayHandle::borrow_raw(RawDisplayHandle::AppKit(handle)) });
71                }
72
73                #[cfg(target_os = "android")]
74                {
75                    let handle = AndroidDisplayHandle::new();
76                    return Ok(unsafe { DisplayHandle::borrow_raw(RawDisplayHandle::Android(handle)) });
77                }
78
79                #[cfg(target_os = "emscripten")]
80                {
81                    let handle = WebDisplayHandle::new();
82                    return Ok(unsafe { DisplayHandle::borrow_raw(RawDisplayHandle::Web(handle)) });
83                }
84
85                #[cfg(any(
86                    target_os = "linux",
87                    target_os = "dragonfly",
88                    target_os = "freebsd",
89                    target_os = "netbsd",
90                    target_os = "openbsd",
91                ))]
92                {
93                    if !$crate::app::using_wayland() {
94                        let display = std::ptr::NonNull::new($crate::app::display());
95                        let screen = self.screen_num();
96                        let handle = XlibDisplayHandle::new(display, screen);
97                        return Ok(unsafe { DisplayHandle::borrow_raw(RawDisplayHandle::Xlib(handle)) });
98                    } else {
99                        let handle = WaylandDisplayHandle::new(std::ptr::NonNull::new($crate::app::display()).unwrap());
100                        return Ok(unsafe { DisplayHandle::borrow_raw(RawDisplayHandle::Wayland(handle)) });
101                    }
102                }
103            }
104        }
105
106        paste::paste! {
107            unsafe impl WindowExt for $name {
108                fn set_center_screen(&mut self) {
109                    debug_assert!(
110                        self.w() != 0 && self.h() != 0,
111                        "center_screen requires the size of the widget to be known!"
112                    );
113                    let (mut x, mut y) = screen_size();
114                    x -= self.w();
115                    y -= self.h();
116                    self.resize(
117                        x / 2,
118                        y / 2,
119                        self.w(),
120                        self.h(),
121                    );
122                }
123
124                fn make_modal(&mut self, val: bool) {
125                    unsafe { [<$flname _make_modal>](self.inner.widget() as _, val as u32) }
126                }
127
128                fn fullscreen(&mut self, val: bool) {
129                    unsafe { [<$flname _fullscreen>](self.inner.widget() as _, val as u32) }
130                }
131
132                fn make_current(&mut self) {
133                    unsafe { [<$flname _make_current>](self.inner.widget() as _) }
134                }
135
136                fn icon(&self) -> Option<Box<dyn ImageExt>> {
137                    unsafe {
138                        let image_ptr = [<$flname _icon>](self.inner.widget() as _);
139                        if image_ptr.is_null() {
140                            None
141                        } else {
142                            let img =
143                                $crate::image::Image::from_image_ptr(image_ptr as *mut fltk_sys::image::Fl_Image);
144                            Some(Box::new(img))
145                        }
146                    }
147                }
148
149                fn set_icon(&mut self, image: Option<$crate::image::RgbImage>) {
150                    if let Some(image) = image {
151                        assert!(!image.was_deleted());
152                        // Shouldn't fail after the previous asserts!
153                        unsafe {
154                            [<$flname _set_icon>](
155                                self.inner.widget() as _,
156                                image.as_rgb_image().unwrap().as_image_ptr() as *mut _,
157                            )
158                        }
159                    } else {
160                    unsafe {
161                            [<$flname _set_icon>](
162                                self.inner.widget() as _,
163                                std::ptr::null_mut() as *mut raw::c_void,
164                            )
165                        }
166                    }
167                }
168
169                fn set_cursor(&mut self, cursor: Cursor) {
170                    unsafe { [<$flname _set_cursor>](self.inner.widget() as _, cursor as i32) }
171                }
172
173                fn shown(&self) -> bool {
174                    unsafe { [<$flname _shown>](self.inner.widget() as _) != 0 }
175                }
176
177                fn set_border(&mut self, flag: bool) {
178                    assert!($crate::app::is_ui_thread());
179                    unsafe { [<$flname _set_border>](self.inner.widget() as _, i32::from(flag)) }
180                }
181
182                fn border(&self) -> bool {
183                    unsafe { [<$flname _border>](self.inner.widget() as _) != 0 }
184                }
185
186                fn free_position(&mut self) {
187                    unsafe { [<$flname _free_position>](self.inner.widget() as _) }
188                }
189
190                fn raw_handle(&self) -> RawHandle {
191                    unsafe {
192                        let ptr = [<$flname _raw_handle>](self.inner.widget() as _);
193                        assert!(!ptr.is_null());
194                        return ptr as RawHandle;
195                    }
196                }
197
198                fn region(&self) -> $crate::draw::Region {
199                    unsafe {
200                        let ptr = [<$flname _region>](self.inner.widget() as _);
201                        assert!(!ptr.is_null());
202                        $crate::draw::Region(ptr)
203                    }
204                }
205
206                unsafe fn set_region(&mut self, region: $crate::draw::Region) { unsafe {
207                    assert!(!region.0.is_null());
208                    [<$flname _set_region>](self.inner.widget() as _, region.0)
209                }}
210
211                fn iconize(&mut self) {
212                    unsafe { [<$flname _iconize>](self.inner.widget() as _) }
213                }
214
215                fn fullscreen_active(&self) -> bool {
216                    unsafe { [<$flname _fullscreen_active>](self.inner.widget() as _) != 0 }
217                }
218
219                fn decorated_w(&self) -> i32 {
220                    unsafe { [<$flname _decorated_w>](self.inner.widget() as _) }
221                }
222
223                fn decorated_h(&self) -> i32 {
224                    unsafe { [<$flname _decorated_h>](self.inner.widget() as _) }
225                }
226
227                fn size_range(&mut self, min_w: i32, min_h: i32, max_w: i32, max_h: i32) {
228                    let max_w = if max_w > i32::from(u16::MAX) {
229                        0
230                    } else {
231                        max_w
232                    };
233                    let max_h = if max_h > i32::from(u16::MAX) {
234                        0
235                    } else {
236                        max_h
237                    };
238                    unsafe {
239                        [<$flname _size_range>](self.inner.widget() as _, min_w, min_h, max_w, max_h);
240                    }
241                }
242
243                fn hotspot<W: WidgetExt>(&mut self, w: &W) {
244                    unsafe { [<$flname _hotspot>](self.inner.widget() as _, w.as_widget_ptr() as _) }
245                }
246
247                fn set_shape(&mut self, image: Option<$crate::image::RgbImage>) {
248                    assert!(self.w() != 0);
249                    assert!(self.h() != 0);
250                    unsafe {
251                        if let Some(image) = image {
252                            assert!(!image.was_deleted());
253                            assert!(image.w() == image.data_w() as i32);
254                            assert!(image.h() == image.data_h() as i32);
255                            [<$flname _set_shape>](self.inner.widget() as _, image.as_image_ptr() as _)
256                        };
257                    }
258                }
259
260                fn shape(&self) -> Option<Box<dyn ImageExt>> {
261                    unsafe {
262                        let image_ptr = [<$flname _shape>](self.inner.widget() as _);
263                        if image_ptr.is_null() {
264                            None
265                        } else {
266                            let img =
267                            $crate::image::Image::from_image_ptr(image_ptr as *mut fltk_sys::image::Fl_Image);
268                            Some(Box::new(img))
269                        }
270                    }
271                }
272
273                fn x_root(&self) -> i32 {
274                    unsafe { [<$flname _x_root>](self.inner.widget() as _) }
275                }
276
277                fn y_root(&self) -> i32 {
278                    unsafe { [<$flname _y_root>](self.inner.widget() as _) }
279                }
280
281                fn set_cursor_image(
282                    &mut self,
283                    mut image: $crate::image::RgbImage,
284                    hot_x: i32,
285                    hot_y: i32,
286                ) {
287                    if image.data_w() != image.w() || image.data_h() == image.h() {
288                        image.scale(image.data_w(), image.data_h(), false, true);
289                    }
290                    unsafe {
291                        assert!(!image.was_deleted());
292                        [<$flname _set_cursor_image>](
293                            self.inner.widget() as _,
294                            image.as_image_ptr() as _,
295                            hot_x,
296                            hot_y,
297                        )
298                    }
299                }
300
301                fn default_cursor(&mut self, cursor: Cursor) {
302                    unsafe { [<$flname _default_cursor>](self.inner.widget() as _, cursor as i32) }
303                }
304
305                fn screen_num(&self) -> i32 {
306                    unsafe { [<$flname _screen_num>](self.inner.widget() as _) }
307                }
308
309                fn set_screen_num(&mut self, n: i32) {
310                    unsafe { [<$flname _set_screen_num>](self.inner.widget() as _, n) }
311                }
312
313                fn wait_for_expose(&self) {
314                    unsafe { [<$flname _wait_for_expose>](self.inner.widget() as _) }
315                }
316
317                fn opacity(&self) -> f64 {
318                    assert!(self.is_derived);
319                    unsafe { [<$flname _alpha>](self.inner.widget() as _) as f64 / 255.0 }
320                }
321
322                fn set_opacity(&mut self, val: f64) {
323                    assert!(self.is_derived);
324                    if self.shown() {
325                        self.wait_for_expose();
326                        let val: u8 = if val > 1.0 {
327                            255
328                        } else if val < 0.0 {
329                            0
330                        } else {
331                            (val * 255.0).round() as u8
332                        };
333                        unsafe { [<$flname _set_alpha>](self.inner.widget() as _, val) }
334                    }
335                }
336
337                fn xclass(&self) -> Option<String> {
338                    unsafe {
339                        let ptr = [<$flname _xclass>](self.inner.widget() as _);
340                        if ptr.is_null() {
341                            None
342                        } else {
343                            Some(CStr::from_ptr(ptr).to_string_lossy().to_string())
344                        }
345                    }
346                }
347
348                fn set_xclass(&mut self, s: &str) {
349                    let s = CString::safe_new(s);
350                    unsafe { [<$flname _set_xclass>](self.inner.widget() as _, s.as_ptr()) }
351                }
352
353                fn clear_modal_states(&mut self) {
354                    unsafe { [<$flname _clear_modal_states>](self.inner.widget() as _) }
355                }
356
357                fn force_position(&mut self, flag: bool) {
358                    assert!(self.is_derived);
359                    unsafe { [<$flname _force_position>](self.inner.widget() as _, flag as _) }
360                }
361
362                fn set_override(&mut self) {
363                    unsafe { [<$flname _set_override>](self.inner.widget() as _) }
364                }
365
366                fn is_override(&self) -> bool {
367                    unsafe { [<$flname _override>](self.inner.widget() as _) != 0 }
368                }
369
370                fn set_icon_label(&mut self, label: &str) {
371                    let label = CString::safe_new(label);
372                    unsafe { [<$flname _set_icon_label>](self.inner.widget() as _, label.as_ptr()) }
373                }
374
375                fn icon_label(&self) -> Option<String> {
376                    unsafe {
377                        let label_ptr = [<$flname _icon_label>](self.inner.widget() as _);
378                        if label_ptr.is_null() {
379                            None
380                        } else {
381                            Some(CStr::from_ptr(label_ptr as *mut std::os::raw::c_char)
382                            .to_string_lossy()
383                            .to_string())
384                        }
385                    }
386                }
387            }
388        }
389    };
390}
391
392pub use impl_window_ext;