1#[doc(hidden)]
2#[macro_export]
3macro_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 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;