1#![allow(unused_imports)]
2
3use crate::app::screen_size;
14use crate::enums::{Align, Color, Cursor, Damage, Event, Font, FrameType, LabelType, Mode, When};
15use crate::image::Image;
16use crate::prelude::*;
17use crate::utils::FlString;
18use crate::widget::Widget;
19use fltk_sys::window::*;
20#[cfg(feature = "rwh06")]
21use rwh06::*;
22use std::{
23 ffi::{CStr, CString},
24 mem,
25 ops::{Deref, DerefMut},
26 os::raw,
27};
28
29#[cfg(all(
31 not(any(
32 target_os = "windows",
33 target_os = "macos",
34 target_os = "ios",
35 target_os = "android",
36 target_os = "emscripten",
37 )),
38 any(
39 target_arch = "arm",
40 target_arch = "mips",
41 target_arch = "powerpc",
42 target_arch = "sparc",
43 target_arch = "wasm32",
44 target_arch = "x86",
45 )
46))]
47type RawXlibHandle = u32;
48
49#[cfg(all(
52 not(any(
53 target_os = "windows",
54 target_os = "macos",
55 target_os = "ios",
56 target_os = "android",
57 target_os = "emscripten"
58 )),
59 any(
60 target_arch = "aarch64",
61 target_arch = "loongarch64",
62 target_arch = "mips64",
63 target_arch = "powerpc64",
64 target_arch = "s390x",
65 target_arch = "sparc64",
66 target_arch = "x86_64",
67 )
68))]
69type RawXlibHandle = u64;
70
71#[cfg(any(
74 target_os = "windows",
75 target_os = "macos",
76 target_os = "ios",
77 target_os = "android",
78 target_os = "emscripten",
79))]
80pub type RawHandle = *mut raw::c_void;
81
82#[cfg(all(
85 not(any(
86 target_os = "windows",
87 target_os = "macos",
88 target_os = "ios",
89 target_os = "android",
90 target_os = "emscripten"
91 )),
92 feature = "no-wayland"
93))]
94pub type RawHandle = RawXlibHandle;
95
96#[cfg(all(
99 not(any(
100 target_os = "windows",
101 target_os = "macos",
102 target_os = "ios",
103 target_os = "android",
104 target_os = "emscripten"
105 )),
106 not(feature = "no-wayland")
107))]
108pub type RawHandle = *mut std::os::raw::c_void;
109
110pub type Window = DoubleWindow;
112
113#[repr(i32)]
115#[derive(Debug, Copy, Clone, PartialEq, Eq)]
116pub enum WindowType {
117 Single = 240,
119 Double = 241,
121}
122
123crate::macros::widget::impl_widget_type!(WindowType);
124
125macro_rules! impl_ppu {
126 ($name:ident) => {
127 impl $name {
128 pub fn pixels_per_unit(&self) -> f32 {
130 #[allow(unused_mut)]
131 let mut factor = 1.0;
132 #[cfg(target_os = "macos")]
133 {
134 unsafe extern "C" {
135 pub fn cfltk_getScalingFactor(handle: *mut raw::c_void) -> f64;
136 }
137 let mac_version = unsafe { fltk_sys::fl::Fl_mac_os_version() };
138 if mac_version >= 100700 {
139 factor = unsafe { cfltk_getScalingFactor(self.raw_handle()) };
140 }
141 }
142 let s = crate::app::screen_scale(self.screen_num());
143 s * factor as f32
144 }
145
146 pub fn pixel_w(&self) -> i32 {
148 (self.pixels_per_unit() as f64 * self.w() as f64) as i32
149 }
150
151 pub fn pixel_h(&self) -> i32 {
153 (self.pixels_per_unit() as f64 * self.h() as f64) as i32
154 }
155 }
156 };
157}
158
159macro_rules! impl_top_win {
160 ($name:ident) => {
161 impl $name {
162 pub unsafe fn find_by_handle(handle: RawHandle) -> Option<impl WindowExt> {
167 unsafe {
168 let ptr = Fl_Window_find_by_handle(handle as *const raw::c_void as *mut _);
169 if ptr.is_null() {
170 None
171 } else {
172 Some(Window::from_widget_ptr(
173 ptr as *mut fltk_sys::widget::Fl_Widget,
174 ))
175 }
176 }
177 }
178
179 pub fn show_with_env_args(&mut self) {
198 unsafe {
199 let args: Vec<String> = std::env::args().collect();
200 let len = args.len() as i32;
201 let mut v: Vec<*mut raw::c_char> = vec![];
202 for arg in args {
203 let c = CString::safe_new(arg.as_str());
204 v.push(c.into_raw() as *mut raw::c_char);
205 }
206 let mut v = mem::ManuallyDrop::new(v);
207 Fl_Window_show_with_args(
208 self.inner.widget() as *mut Fl_Window,
209 len,
210 v.as_mut_ptr(),
211 )
212 }
213 }
214
215 pub fn show_with_args(&mut self, args: &[&str]) {
234 unsafe {
235 let mut temp = vec![""];
236 temp.extend(args);
237 let len = temp.len() as i32;
238 let mut v: Vec<*mut raw::c_char> = vec![];
239 for arg in temp {
240 let c = CString::safe_new(arg);
241 v.push(c.into_raw() as *mut raw::c_char);
242 }
243 let mut v = mem::ManuallyDrop::new(v);
244 Fl_Window_show_with_args(
245 self.inner.widget() as *mut Fl_Window,
246 len,
247 v.as_mut_ptr(),
248 )
249 }
250 }
251
252 pub fn set_on_top(&mut self) {
255 assert!(self.raw_handle() as isize != 0);
256 #[cfg(target_os = "macos")]
257 {
258 unsafe extern "C" {
259 pub fn cfltk_setOnTop(handle: *mut raw::c_void);
260 }
261 unsafe {
262 cfltk_setOnTop(self.raw_handle());
263 }
264 }
265 #[cfg(target_os = "windows")]
266 {
267 unsafe extern "system" {
268 fn SetWindowPos(
269 hwnd: *mut raw::c_void,
270 insert_after: isize,
271 x: i32,
272 y: i32,
273 cx: i32,
274 cy: i32,
275 flags: u32,
276 ) -> bool;
277 }
278 const TOP_MOST: isize = -1;
279 const SWP_NOSIZE: u32 = 1;
280 const SWP_NOMOVE: u32 = 2;
281 unsafe {
282 SetWindowPos(
283 self.raw_handle(),
284 TOP_MOST,
285 0,
286 0,
287 0,
288 0,
289 SWP_NOSIZE | SWP_NOMOVE,
290 );
291 }
292 }
293 #[cfg(not(any(
294 target_os = "macos",
295 target_os = "android",
296 target_os = "windows",
297 target_os = "emscripten"
298 )))]
299 {
300 unsafe extern "C" {
301 pub fn cfltk_setOnTop(handle: RawXlibHandle);
302 }
303 if !crate::app::using_wayland() {
304 unsafe {
305 cfltk_setOnTop(self.raw_handle() as RawXlibHandle);
306 }
307 }
308 }
309 }
310
311 pub fn maximize(&mut self) {
313 unsafe { Fl_Window_maximize(self.inner.widget() as _) }
314 }
315
316 pub fn un_maximize(&mut self) {
318 unsafe { Fl_Window_un_maximize(self.inner.widget() as _) }
319 }
320
321 pub fn maximize_active(&self) -> bool {
323 unsafe { Fl_Window_maximize_active(self.inner.widget() as _) != 0 }
324 }
325
326 pub fn default_xclass() -> Option<String> {
328 unsafe {
329 let ptr = Fl_Single_Window_default_xclass();
330 if ptr.is_null() {
331 None
332 } else {
333 Some(CStr::from_ptr(ptr).to_string_lossy().to_string())
334 }
335 }
336 }
337
338 pub fn set_default_xclass(s: &str) {
341 let s = CString::safe_new(s);
342 unsafe { Fl_Single_Window_set_default_xclass(s.as_ptr()) }
343 }
344 }
345 };
346}
347
348#[derive(Debug)]
350pub struct SingleWindow {
351 inner: crate::widget::WidgetTracker,
352 is_derived: bool,
353}
354
355crate::macros::widget::impl_widget_ext!(SingleWindow, Fl_Single_Window);
356crate::macros::widget::impl_widget_base!(SingleWindow, Fl_Single_Window);
357crate::macros::group::impl_group_ext!(SingleWindow, Fl_Single_Window);
358crate::macros::window::impl_window_ext!(SingleWindow, Fl_Single_Window);
359
360impl SingleWindow {
361 pub fn new<'a, T: Into<Option<&'a str>>>(x: i32, y: i32, w: i32, h: i32, title: T) -> Self {
363 let temp = if let Some(title) = title.into() {
364 CString::safe_new(title).into_raw()
365 } else {
366 std::ptr::null_mut()
367 };
368 unsafe {
369 let widget_ptr = Fl_Single_Window_new(x, y, w, h, temp);
370 assert!(!widget_ptr.is_null());
371 assert!(crate::app::is_ui_thread());
372 let tracker = crate::widget::WidgetTracker::new(widget_ptr as _);
373 unsafe extern "C" fn shim(wid: *mut Fl_Widget, _data: *mut std::os::raw::c_void) {
374 unsafe {
375 let user_data = Fl_Single_Window_user_data(wid as _);
376 let draw_data = Fl_Single_Window_draw_data(wid as _);
377 let handle_data = Fl_Single_Window_handle_data(wid as _);
378 crate::app::add_timeout(0., move |h| {
379 if !user_data.is_null() {
380 let _x = Box::from_raw(user_data as *mut Box<dyn FnMut()>);
381 }
382 if !draw_data.is_null() {
383 let _x = Box::from_raw(draw_data as *mut Box<dyn FnMut()>);
384 }
385 if !handle_data.is_null() {
386 let _x = Box::from_raw(handle_data as *mut Box<dyn FnMut()>);
387 }
388 crate::app::remove_timeout(h);
389 });
390 }
391 }
392 Fl_Single_Window_set_deletion_callback(widget_ptr, Some(shim), std::ptr::null_mut());
393 Self {
394 inner: tracker,
395 is_derived: true,
396 }
397 }
398 }
399}
400
401impl Default for SingleWindow {
402 fn default() -> Self {
403 assert!(crate::app::is_ui_thread());
404 let mut win = SingleWindow::new(0, 0, 0, 0, None);
405 win.free_position();
406 win
407 }
408}
409
410impl_top_win!(SingleWindow);
411impl_ppu!(SingleWindow);
412
413#[derive(Debug)]
415pub struct DoubleWindow {
416 inner: crate::widget::WidgetTracker,
417 is_derived: bool,
418}
419
420crate::macros::widget::impl_widget_ext!(DoubleWindow, Fl_Double_Window);
421crate::macros::widget::impl_widget_base!(DoubleWindow, Fl_Double_Window);
422crate::macros::group::impl_group_ext!(DoubleWindow, Fl_Double_Window);
423crate::macros::window::impl_window_ext!(DoubleWindow, Fl_Double_Window);
424
425impl Default for DoubleWindow {
426 fn default() -> Self {
427 assert!(crate::app::is_ui_thread());
428 let mut win = DoubleWindow::new(0, 0, 0, 0, None);
429 win.free_position();
430 win
431 }
432}
433
434impl_top_win!(DoubleWindow);
435impl_ppu!(DoubleWindow);
436
437impl DoubleWindow {
438 pub fn new<'a, T: Into<Option<&'a str>>>(x: i32, y: i32, w: i32, h: i32, title: T) -> Self {
440 let temp = if let Some(title) = title.into() {
441 CString::safe_new(title).into_raw()
442 } else {
443 std::ptr::null_mut()
444 };
445 unsafe {
446 let widget_ptr = Fl_Double_Window_new(x, y, w, h, temp);
447 assert!(!widget_ptr.is_null());
448 assert!(crate::app::is_ui_thread());
449 let tracker = crate::widget::WidgetTracker::new(widget_ptr as _);
450 unsafe extern "C" fn shim(wid: *mut Fl_Widget, _data: *mut std::os::raw::c_void) {
451 unsafe {
452 let user_data = Fl_Double_Window_user_data(wid as _);
453 let draw_data = Fl_Double_Window_draw_data(wid as _);
454 let handle_data = Fl_Double_Window_handle_data(wid as _);
455 crate::app::add_timeout(0., move |h| {
456 if !user_data.is_null() {
457 let _x = Box::from_raw(user_data as *mut Box<dyn FnMut()>);
458 }
459 if !draw_data.is_null() {
460 let _x = Box::from_raw(draw_data as *mut Box<dyn FnMut()>);
461 }
462 if !handle_data.is_null() {
463 let _x = Box::from_raw(handle_data as *mut Box<dyn FnMut()>);
464 }
465 crate::app::remove_timeout(h);
466 });
467 }
468 }
469 Fl_Double_Window_set_deletion_callback(widget_ptr, Some(shim), std::ptr::null_mut());
470 Self {
471 inner: tracker,
472 is_derived: true,
473 }
474 }
475 }
476 pub fn flush(&mut self) {
478 unsafe { Fl_Double_Window_flush(self.inner.widget() as _) }
479 }
480
481 pub fn platform_show(&self) {
483 #[allow(unused_unsafe)]
484 unsafe {
485 #[cfg(target_os = "windows")]
486 {
487 unsafe extern "system" {
488 fn ShowWindow(hwnd: *mut raw::c_void, nCmdShow: raw::c_int) -> raw::c_int;
489 }
490 ShowWindow(self.raw_handle(), 9);
491 }
492 #[cfg(target_os = "macos")]
493 {
494 unsafe extern "C" {
495 fn cfltk_winShow(xid: *mut raw::c_void);
496 }
497 cfltk_winShow(self.raw_handle());
498 }
499 #[cfg(not(any(
500 target_os = "macos",
501 target_os = "android",
502 target_os = "windows",
503 target_os = "emscripten"
504 )))]
505 {
506 if crate::app::using_wayland() {
507 Fl_Double_Window_show(self.inner.widget() as _);
508 } else {
509 unsafe extern "C" {
510 fn cfltk_platform_show(proxy: *mut raw::c_void);
511 }
512 cfltk_platform_show(self.raw_handle() as *mut raw::c_void);
513 }
514 }
515 }
516 }
517
518 pub fn platform_hide(&self) {
520 #[allow(unused_unsafe)]
521 unsafe {
522 #[cfg(target_os = "windows")]
523 {
524 unsafe extern "system" {
525 fn ShowWindow(hwnd: *mut raw::c_void, nCmdShow: raw::c_int) -> raw::c_int;
526 }
527 ShowWindow(self.raw_handle(), 0);
528 }
529 #[cfg(target_os = "macos")]
530 {
531 unsafe extern "C" {
532 fn cfltk_winHide(xid: *mut raw::c_void);
533 }
534 cfltk_winHide(self.raw_handle());
535 }
536 #[cfg(not(any(
537 target_os = "macos",
538 target_os = "android",
539 target_os = "windows",
540 target_os = "emscripten"
541 )))]
542 {
543 if crate::app::using_wayland() {
544 Fl_Double_Window_hide(self.inner.widget() as _);
545 } else {
546 unsafe extern "C" {
547 fn cfltk_platform_hide(proxy: *mut raw::c_void);
548 }
549 cfltk_platform_hide(self.raw_handle() as *mut raw::c_void);
550 }
551 }
552 }
553 }
554}
555
556#[derive(Debug)]
558pub struct MenuWindow {
559 inner: crate::widget::WidgetTracker,
560 is_derived: bool,
561}
562
563crate::macros::widget::impl_widget_ext!(MenuWindow, Fl_Menu_Window);
564crate::macros::widget::impl_widget_base!(MenuWindow, Fl_Menu_Window);
565crate::macros::group::impl_group_ext!(MenuWindow, Fl_Menu_Window);
566crate::macros::window::impl_window_ext!(MenuWindow, Fl_Menu_Window);
567
568impl Default for MenuWindow {
569 fn default() -> Self {
570 assert!(crate::app::is_ui_thread());
571 let mut win = MenuWindow::new(0, 0, 0, 0, None);
572 win.free_position();
573 win
574 }
575}
576
577impl MenuWindow {
578 pub fn new<'a, T: Into<Option<&'a str>>>(x: i32, y: i32, w: i32, h: i32, title: T) -> Self {
580 let temp = if let Some(title) = title.into() {
581 CString::safe_new(title).into_raw()
582 } else {
583 std::ptr::null_mut()
584 };
585 unsafe {
586 let widget_ptr = Fl_Menu_Window_new(x, y, w, h, temp);
587 assert!(!widget_ptr.is_null());
588 assert!(crate::app::is_ui_thread());
589 let tracker = crate::widget::WidgetTracker::new(widget_ptr as _);
590 unsafe extern "C" fn shim(wid: *mut Fl_Widget, _data: *mut std::os::raw::c_void) {
591 unsafe {
592 let user_data = Fl_Menu_Window_user_data(wid as _);
593 let draw_data = Fl_Menu_Window_draw_data(wid as _);
594 let handle_data = Fl_Menu_Window_handle_data(wid as _);
595 crate::app::add_timeout(0., move |h| {
596 if !user_data.is_null() {
597 let _x = Box::from_raw(user_data as *mut Box<dyn FnMut()>);
598 }
599 if !draw_data.is_null() {
600 let _x = Box::from_raw(draw_data as *mut Box<dyn FnMut()>);
601 }
602 if !handle_data.is_null() {
603 let _x = Box::from_raw(handle_data as *mut Box<dyn FnMut()>);
604 }
605 crate::app::remove_timeout(h);
606 });
607 }
608 }
609 Fl_Menu_Window_set_deletion_callback(widget_ptr, Some(shim), std::ptr::null_mut());
610 Self {
611 inner: tracker,
612 is_derived: true,
613 }
614 }
615 }
616}
617
618#[derive(Debug)]
620pub struct OverlayWindow {
621 inner: crate::widget::WidgetTracker,
622 is_derived: bool,
623}
624
625crate::macros::widget::impl_widget_ext!(OverlayWindow, Fl_Overlay_Window);
626crate::macros::widget::impl_widget_base!(OverlayWindow, Fl_Overlay_Window);
627crate::macros::group::impl_group_ext!(OverlayWindow, Fl_Overlay_Window);
628crate::macros::window::impl_window_ext!(OverlayWindow, Fl_Overlay_Window);
629
630impl Default for OverlayWindow {
631 fn default() -> Self {
632 assert!(crate::app::is_ui_thread());
633 OverlayWindow::new(0, 0, 0, 0, None)
634 }
635}
636
637impl_top_win!(OverlayWindow);
638impl_ppu!(OverlayWindow);
639
640impl OverlayWindow {
641 pub fn new<'a, T: Into<Option<&'a str>>>(x: i32, y: i32, w: i32, h: i32, title: T) -> Self {
643 let temp = if let Some(title) = title.into() {
644 CString::safe_new(title).into_raw()
645 } else {
646 std::ptr::null_mut()
647 };
648 unsafe {
649 let widget_ptr = Fl_Overlay_Window_new(x, y, w, h, temp);
650 assert!(!widget_ptr.is_null());
651 assert!(crate::app::is_ui_thread());
652 let tracker = crate::widget::WidgetTracker::new(widget_ptr as _);
653 unsafe extern "C" fn shim(wid: *mut Fl_Widget, _data: *mut std::os::raw::c_void) {
654 unsafe {
655 let user_data = Fl_Overlay_Window_user_data(wid as _);
656 let draw_data = Fl_Overlay_Window_draw_data(wid as _);
657 let handle_data = Fl_Overlay_Window_handle_data(wid as _);
658 crate::app::add_timeout(0., move |h| {
659 if !user_data.is_null() {
660 let _x = Box::from_raw(user_data as *mut Box<dyn FnMut()>);
661 }
662 if !draw_data.is_null() {
663 let _x = Box::from_raw(draw_data as *mut Box<dyn FnMut()>);
664 }
665 if !handle_data.is_null() {
666 let _x = Box::from_raw(handle_data as *mut Box<dyn FnMut()>);
667 }
668 crate::app::remove_timeout(h);
669 });
670 }
671 }
672 Fl_Overlay_Window_set_deletion_callback(widget_ptr, Some(shim), std::ptr::null_mut());
673 Self {
674 inner: tracker,
675 is_derived: true,
676 }
677 }
678 }
679 pub fn flush(&mut self) {
681 unsafe { Fl_Double_Window_flush(self.inner.widget() as _) }
682 }
683
684 pub fn draw_overlay<F: FnMut(&mut Self) + 'static>(&mut self, cb: F) {
686 assert!(self.is_derived);
687 unsafe {
688 unsafe extern "C" fn shim(wid: *mut Fl_Widget, data: *mut raw::c_void) {
689 unsafe {
690 let mut wid = OverlayWindow::from_widget_ptr(wid as *mut _);
691 wid.assume_derived();
692 let a: *mut Box<dyn FnMut(&mut OverlayWindow)> =
693 data as *mut Box<dyn FnMut(&mut OverlayWindow)>;
694 let f: &mut (dyn FnMut(&mut OverlayWindow)) = &mut **a;
695 let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(&mut wid)));
696 }
697 }
698 let mut _old_data = None;
699 if self.is_derived {
700 _old_data = self.draw_data();
701 }
702 let a: *mut Box<dyn FnMut(&mut Self)> = Box::into_raw(Box::new(Box::new(cb)));
703 let data: *mut raw::c_void = a as *mut raw::c_void;
704 let callback: custom_draw_callback = Some(shim);
705 Fl_Overlay_Window_draw_overlay(self.inner.widget() as _, callback, data);
706 }
707 }
708
709 pub fn redraw_overlay(&self) {
711 unsafe { Fl_Overlay_Window_redraw_overlay(self.inner.widget() as _) }
712 }
713
714 pub fn can_do_overlay(&self) -> bool {
716 unsafe { Fl_Overlay_Window_can_do_overlay(self.inner.widget() as _) != 0 }
717 }
718}
719
720#[cfg(feature = "enable-glwindow")]
721pub struct GlContext(*mut raw::c_void);
723
724#[cfg(feature = "enable-glwindow")]
726#[derive(Debug)]
727pub struct GlutWindow {
728 inner: crate::widget::WidgetTracker,
729 is_derived: bool,
730}
731
732#[cfg(feature = "enable-glwindow")]
733crate::macros::widget::impl_widget_ext!(GlutWindow, Fl_Glut_Window);
734#[cfg(feature = "enable-glwindow")]
735crate::macros::widget::impl_widget_base!(GlutWindow, Fl_Glut_Window);
736#[cfg(feature = "enable-glwindow")]
737crate::macros::group::impl_group_ext!(GlutWindow, Fl_Glut_Window);
738#[cfg(feature = "enable-glwindow")]
739crate::macros::window::impl_window_ext!(GlutWindow, Fl_Glut_Window);
740
741#[cfg(feature = "enable-glwindow")]
742impl_top_win!(GlutWindow);
743
744#[cfg(feature = "enable-glwindow")]
745impl Default for GlutWindow {
746 fn default() -> GlutWindow {
747 assert!(crate::app::is_ui_thread());
748 let mut win = GlutWindow::new(0, 0, 0, 0, None);
749 win.free_position();
750 win
751 }
752}
753
754#[cfg(feature = "enable-glwindow")]
755impl GlutWindow {
756 pub fn new<'a, T: Into<Option<&'a str>>>(x: i32, y: i32, w: i32, h: i32, title: T) -> Self {
758 let temp = if let Some(title) = title.into() {
759 CString::safe_new(title).into_raw()
760 } else {
761 std::ptr::null_mut()
762 };
763 unsafe {
764 let widget_ptr = Fl_Glut_Window_new(x, y, w, h, temp);
765 assert!(!widget_ptr.is_null());
766 assert!(crate::app::is_ui_thread());
767 let tracker = crate::widget::WidgetTracker::new(widget_ptr as _);
768 unsafe extern "C" fn shim(wid: *mut Fl_Widget, _data: *mut std::os::raw::c_void) {
769 unsafe {
770 let user_data = Fl_Glut_Window_user_data(wid as _);
771 let draw_data = Fl_Glut_Window_draw_data(wid as _);
772 let handle_data = Fl_Glut_Window_handle_data(wid as _);
773 crate::app::add_timeout(0., move |h| {
774 if !user_data.is_null() {
775 let _x = Box::from_raw(user_data as *mut Box<dyn FnMut()>);
776 }
777 if !draw_data.is_null() {
778 let _x = Box::from_raw(draw_data as *mut Box<dyn FnMut()>);
779 }
780 if !handle_data.is_null() {
781 let _x = Box::from_raw(handle_data as *mut Box<dyn FnMut()>);
782 }
783 crate::app::remove_timeout(h);
784 });
785 }
786 }
787 Fl_Glut_Window_set_deletion_callback(widget_ptr, Some(shim), std::ptr::null_mut());
788 Self {
789 inner: tracker,
790 is_derived: true,
791 }
792 }
793 }
794
795 pub fn get_proc_address(&self, s: &str) -> *const raw::c_void {
797 unsafe extern "C" {
798 pub fn get_proc(name: *const raw::c_char) -> *mut raw::c_void;
799 }
800 let s = CString::safe_new(s);
801 let ret = unsafe { get_proc(s.as_ptr() as _) };
802 if !ret.is_null() {
803 ret as *const _
804 } else {
805 unsafe {
806 Fl_Glut_Window_get_proc_address(self.inner.widget() as _, s.as_ptr()) as *const _
807 }
808 }
809 }
810
811 pub fn flush(&mut self) {
813 unsafe { Fl_Glut_Window_flush(self.inner.widget() as _) }
814 }
815
816 pub fn valid(&self) -> bool {
818 unsafe { Fl_Glut_Window_valid(self.inner.widget() as _) != 0 }
819 }
820
821 pub fn set_valid(&mut self, v: bool) {
823 unsafe { Fl_Glut_Window_set_valid(self.inner.widget() as _, v as raw::c_char) }
824 }
825
826 pub fn context_valid(&self) -> bool {
828 unsafe { Fl_Glut_Window_context_valid(self.inner.widget() as _) != 0 }
829 }
830
831 pub fn set_context_valid(&mut self, v: bool) {
833 unsafe { Fl_Glut_Window_set_context_valid(self.inner.widget() as _, v as raw::c_char) }
834 }
835
836 pub fn context(&self) -> Option<GlContext> {
838 unsafe {
839 let ctx = Fl_Glut_Window_context(self.inner.widget() as _);
840 if ctx.is_null() {
841 None
842 } else {
843 Some(GlContext(ctx))
844 }
845 }
846 }
847
848 pub fn set_context(&mut self, ctx: GlContext, destroy_flag: bool) {
850 assert!(!ctx.0.is_null());
851 unsafe {
852 Fl_Glut_Window_set_context(self.inner.widget() as _, ctx.0, i32::from(destroy_flag))
853 }
854 }
855
856 pub fn swap_buffers(&mut self) {
858 unsafe { Fl_Glut_Window_swap_buffers(self.inner.widget() as _) }
859 }
860
861 pub fn swap_interval(&self) -> i32 {
863 unsafe { Fl_Glut_Window_swap_interval(self.inner.widget() as _) }
864 }
865
866 pub fn set_swap_interval(&mut self, frames: i32) {
868 unsafe { Fl_Glut_Window_set_swap_interval(self.inner.widget() as _, frames) }
869 }
870
871 pub fn ortho(&mut self) {
874 unsafe { Fl_Glut_Window_ortho(self.inner.widget() as _) }
875 }
876
877 pub fn can_do_overlay(&self) -> bool {
879 unsafe { Fl_Glut_Window_can_do_overlay(self.inner.widget() as _) != 0 }
880 }
881
882 pub fn redraw_overlay(&mut self) {
884 unsafe { Fl_Glut_Window_redraw_overlay(self.inner.widget() as _) }
885 }
886
887 pub fn hide_overlay(&mut self) {
889 unsafe { Fl_Glut_Window_hide_overlay(self.inner.widget() as _) }
890 }
891
892 pub fn make_overlay_current(&mut self) {
894 unsafe { Fl_Glut_Window_make_overlay_current(self.inner.widget() as _) }
895 }
896
897 pub fn pixels_per_unit(&self) -> f32 {
899 unsafe { Fl_Glut_Window_pixels_per_unit(self.inner.widget() as _) }
900 }
901
902 pub fn pixel_w(&self) -> i32 {
904 unsafe { Fl_Glut_Window_pixel_w(self.inner.widget() as _) }
905 }
906
907 pub fn pixel_h(&self) -> i32 {
909 unsafe { Fl_Glut_Window_pixel_h(self.inner.widget() as _) }
910 }
911
912 pub fn mode(&self) -> Mode {
914 unsafe { mem::transmute(Fl_Glut_Window_mode(self.inner.widget() as _)) }
915 }
916
917 pub fn set_mode(&mut self, mode: Mode) {
919 unsafe {
920 Fl_Glut_Window_set_mode(self.inner.widget() as _, mode.bits());
921 }
922 }
923}
924
925#[cfg(feature = "enable-glwindow")]
926pub type GlWindow = GlutWindow;
928
929#[cfg(feature = "enable-glwindow")]
931#[derive(Debug)]
932pub struct GlWidgetWindow {
933 inner: crate::widget::WidgetTracker,
934 is_derived: bool,
935}
936
937#[cfg(feature = "enable-glwindow")]
938crate::macros::widget::impl_widget_ext!(GlWidgetWindow, Fl_Gl_Window);
939#[cfg(feature = "enable-glwindow")]
940crate::macros::widget::impl_widget_base!(GlWidgetWindow, Fl_Gl_Window);
941#[cfg(feature = "enable-glwindow")]
942crate::macros::group::impl_group_ext!(GlWidgetWindow, Fl_Gl_Window);
943#[cfg(feature = "enable-glwindow")]
944crate::macros::window::impl_window_ext!(GlWidgetWindow, Fl_Gl_Window);
945
946#[cfg(feature = "enable-glwindow")]
947impl_top_win!(GlWidgetWindow);
948
949#[cfg(feature = "enable-glwindow")]
950impl Default for GlWidgetWindow {
951 fn default() -> GlWidgetWindow {
952 assert!(crate::app::is_ui_thread());
953 let mut win = GlWidgetWindow::new(0, 0, 0, 0, None);
954 win.free_position();
955 win.set_frame(FrameType::FlatBox);
956 win.begin();
957 win
958 }
959}
960
961#[cfg(feature = "enable-glwindow")]
962impl GlWidgetWindow {
963 pub fn new<'a, T: Into<Option<&'a str>>>(x: i32, y: i32, w: i32, h: i32, title: T) -> Self {
965 let temp = if let Some(title) = title.into() {
966 CString::safe_new(title).into_raw()
967 } else {
968 std::ptr::null_mut()
969 };
970 unsafe {
971 let widget_ptr = Fl_Gl_Window_new(x, y, w, h, temp);
972 assert!(!widget_ptr.is_null());
973 assert!(crate::app::is_ui_thread());
974 let tracker = crate::widget::WidgetTracker::new(widget_ptr as _);
975 unsafe extern "C" fn shim(wid: *mut Fl_Widget, _data: *mut std::os::raw::c_void) {
976 unsafe {
977 let user_data = Fl_Gl_Window_user_data(wid as _);
978 let draw_data = Fl_Gl_Window_draw_data(wid as _);
979 let handle_data = Fl_Gl_Window_handle_data(wid as _);
980 crate::app::add_timeout(0., move |h| {
981 if !user_data.is_null() {
982 let _x = Box::from_raw(user_data as *mut Box<dyn FnMut()>);
983 }
984 if !draw_data.is_null() {
985 let _x = Box::from_raw(draw_data as *mut Box<dyn FnMut()>);
986 }
987 if !handle_data.is_null() {
988 let _x = Box::from_raw(handle_data as *mut Box<dyn FnMut()>);
989 }
990 crate::app::remove_timeout(h);
991 });
992 }
993 }
994 Fl_Gl_Window_set_deletion_callback(widget_ptr, Some(shim), std::ptr::null_mut());
995 Self {
996 inner: tracker,
997 is_derived: true,
998 }
999 }
1000 }
1001
1002 pub fn get_proc_address(&self, s: &str) -> *const raw::c_void {
1004 unsafe extern "C" {
1005 pub fn get_proc(name: *const raw::c_char) -> *mut raw::c_void;
1006 }
1007 let s = CString::safe_new(s);
1008 let ret = unsafe { get_proc(s.as_ptr() as _) };
1009 if !ret.is_null() {
1010 ret as *const _
1011 } else {
1012 unsafe {
1013 Fl_Gl_Window_get_proc_address(self.inner.widget() as _, s.as_ptr()) as *const _
1014 }
1015 }
1016 }
1017
1018 pub fn flush(&mut self) {
1020 unsafe { Fl_Gl_Window_flush(self.inner.widget() as _) }
1021 }
1022
1023 pub fn valid(&self) -> bool {
1025 unsafe { Fl_Gl_Window_valid(self.inner.widget() as _) != 0 }
1026 }
1027
1028 pub fn set_valid(&mut self, v: bool) {
1030 unsafe { Fl_Gl_Window_set_valid(self.inner.widget() as _, v as raw::c_char) }
1031 }
1032
1033 pub fn context_valid(&self) -> bool {
1035 unsafe { Fl_Gl_Window_context_valid(self.inner.widget() as _) != 0 }
1036 }
1037
1038 pub fn set_context_valid(&mut self, v: bool) {
1040 unsafe { Fl_Gl_Window_set_context_valid(self.inner.widget() as _, v as raw::c_char) }
1041 }
1042
1043 pub fn context(&self) -> Option<GlContext> {
1045 unsafe {
1046 let ctx = Fl_Gl_Window_context(self.inner.widget() as _);
1047 if ctx.is_null() {
1048 None
1049 } else {
1050 Some(GlContext(ctx))
1051 }
1052 }
1053 }
1054
1055 pub fn set_context(&mut self, ctx: GlContext, destroy_flag: bool) {
1057 assert!(!ctx.0.is_null());
1058 unsafe {
1059 Fl_Gl_Window_set_context(self.inner.widget() as _, ctx.0, i32::from(destroy_flag))
1060 }
1061 }
1062
1063 pub fn swap_buffers(&mut self) {
1065 unsafe { Fl_Gl_Window_swap_buffers(self.inner.widget() as _) }
1066 }
1067
1068 pub fn swap_interval(&self) -> i32 {
1070 unsafe { Fl_Gl_Window_swap_interval(self.inner.widget() as _) }
1071 }
1072
1073 pub fn set_swap_interval(&mut self, frames: i32) {
1075 unsafe { Fl_Gl_Window_set_swap_interval(self.inner.widget() as _, frames) }
1076 }
1077
1078 pub fn ortho(&mut self) {
1081 unsafe { Fl_Gl_Window_ortho(self.inner.widget() as _) }
1082 }
1083
1084 pub fn can_do_overlay(&self) -> bool {
1086 unsafe { Fl_Gl_Window_can_do_overlay(self.inner.widget() as _) != 0 }
1087 }
1088
1089 pub fn redraw_overlay(&mut self) {
1091 unsafe { Fl_Gl_Window_redraw_overlay(self.inner.widget() as _) }
1092 }
1093
1094 pub fn hide_overlay(&mut self) {
1096 unsafe { Fl_Gl_Window_hide_overlay(self.inner.widget() as _) }
1097 }
1098
1099 pub fn make_overlay_current(&mut self) {
1101 unsafe { Fl_Gl_Window_make_overlay_current(self.inner.widget() as _) }
1102 }
1103
1104 pub fn pixels_per_unit(&self) -> f32 {
1106 unsafe { Fl_Gl_Window_pixels_per_unit(self.inner.widget() as _) }
1107 }
1108
1109 pub fn pixel_w(&self) -> i32 {
1111 unsafe { Fl_Gl_Window_pixel_w(self.inner.widget() as _) }
1112 }
1113
1114 pub fn pixel_h(&self) -> i32 {
1116 unsafe { Fl_Gl_Window_pixel_h(self.inner.widget() as _) }
1117 }
1118
1119 pub fn mode(&self) -> Mode {
1121 unsafe { mem::transmute(Fl_Gl_Window_mode(self.inner.widget() as _)) }
1122 }
1123
1124 pub fn set_mode(&mut self, mode: Mode) {
1126 unsafe {
1127 Fl_Gl_Window_set_mode(self.inner.widget() as _, mode.bits());
1128 }
1129 }
1130}