1use crate::prelude::*;
2use crate::window::Window;
3use fltk_sys::fl;
4use std::{mem, os::raw, panic, ptr};
5
6pub type WidgetPtr = *mut fltk_sys::widget::Fl_Widget;
8
9pub fn grab() -> Option<impl WindowExt> {
11 unsafe {
12 let ptr = fl::Fl_grab();
13 if ptr.is_null() {
14 None
15 } else {
16 Some(crate::window::Window::from_widget_ptr(ptr as *mut _))
17 }
18 }
19}
20
21pub fn set_grab<W: WindowExt>(win: Option<W>) {
23 unsafe {
24 win.map_or_else(
25 || fl::Fl_set_grab(ptr::null_mut()),
26 |w| fl::Fl_set_grab(w.as_widget_ptr() as *mut _),
27 );
28 }
29}
30
31pub fn set_callback<F, W>(widget: &mut W, cb: F)
33where
34 F: FnMut(&mut dyn WidgetExt),
35 W: WidgetExt,
36{
37 unsafe {
38 unsafe extern "C" fn shim(wid: *mut fltk_sys::widget::Fl_Widget, data: *mut raw::c_void) {
39 unsafe {
40 #[allow(clippy::type_complexity)]
41 let a: *mut Box<dyn FnMut(&mut dyn WidgetExt)> =
42 data as *mut Box<dyn FnMut(&mut dyn WidgetExt)>;
43 let f: &mut (dyn FnMut(&mut dyn WidgetExt)) = &mut **a;
44 let mut wid = crate::widget::Widget::from_widget_ptr(wid);
45 let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| f(&mut wid)));
46 }
47 }
48 let mut _old_data = None;
49 if widget.is_derived() {
50 _old_data = widget.user_data();
51 }
52 #[allow(clippy::type_complexity)]
53 let a: *mut Box<dyn FnMut(&mut dyn WidgetExt)> = Box::into_raw(Box::new(Box::new(cb)));
54 let data: *mut raw::c_void = a as *mut raw::c_void;
55 let callback: fltk_sys::widget::Fl_Callback = Some(shim);
56 fltk_sys::widget::Fl_Widget_set_callback(widget.as_widget_ptr(), callback, data);
57 }
58}
59
60pub unsafe fn set_raw_callback<W>(
87 widget: &mut W,
88 data: *mut raw::c_void,
89 cb: Option<fn(WidgetPtr, *mut raw::c_void)>,
90) where
91 W: WidgetExt,
92{
93 unsafe {
94 let cb: Option<unsafe extern "C" fn(WidgetPtr, *mut raw::c_void)> = mem::transmute(cb);
95 fltk_sys::widget::Fl_Widget_set_callback(widget.as_widget_ptr(), cb, data);
96 }
97}
98
99pub fn first_window() -> Option<impl WindowExt> {
101 unsafe {
102 let x = fl::Fl_first_window();
103 if x.is_null() {
104 None
105 } else {
106 let x = Window::from_widget_ptr(x as *mut fltk_sys::widget::Fl_Widget);
107 Some(x)
108 }
109 }
110}
111
112pub fn next_window<W: WindowExt>(w: &W) -> Option<impl WindowExt> {
114 unsafe {
115 let x = fl::Fl_next_window(w.as_widget_ptr() as *const raw::c_void);
116 if x.is_null() {
117 None
118 } else {
119 let x = Window::from_widget_ptr(x as *mut fltk_sys::widget::Fl_Widget);
120 Some(x)
121 }
122 }
123}
124
125pub fn modal() -> Option<impl WindowExt> {
127 unsafe {
128 let x = fl::Fl_modal();
129 if x.is_null() {
130 None
131 } else {
132 let x = Window::from_widget_ptr(x as *mut fltk_sys::widget::Fl_Widget);
133 Some(x)
134 }
135 }
136}
137
138pub fn delete_widget<Wid: WidgetBase>(wid: Wid) {
140 WidgetBase::delete(wid);
141}
142
143pub fn set_damage(flag: bool) {
145 let flag = if flag { 0x80 } else { 0 };
146 unsafe { fl::Fl_set_damage(flag) }
147}
148
149pub fn damage() -> bool {
151 unsafe { fl::Fl_damage() != 0 }
152}
153
154pub fn pushed() -> Option<impl WidgetExt> {
156 unsafe {
157 let ptr = fl::Fl_pushed();
158 if ptr.is_null() {
159 None
160 } else {
161 Some(crate::widget::Widget::from_widget_ptr(ptr as *mut _))
162 }
163 }
164}
165
166pub fn focus() -> Option<impl WidgetExt> {
168 unsafe {
169 let ptr = fl::Fl_focus();
170 if ptr.is_null() {
171 None
172 } else {
173 Some(crate::widget::Widget::from_widget_ptr(
174 ptr as *mut fltk_sys::widget::Fl_Widget,
175 ))
176 }
177 }
178}
179
180pub fn set_focus<W: WidgetExt>(wid: &W) {
182 unsafe { fl::Fl_set_focus(wid.as_widget_ptr() as *mut raw::c_void) }
183}
184
185pub fn windows() -> Option<Vec<impl WindowExt>> {
187 let mut v: Vec<Window> = vec![];
188 if let Some(first) = first_window() {
189 let first: Window = unsafe { first.as_widget() };
190 v.push(first.clone());
191 let mut win = first;
192 while let Some(wind) = next_window(&win.clone()) {
193 let w = unsafe { wind.as_widget::<Window>() };
194 v.push(w.clone());
195 win = w;
196 }
197 Some(v)
198 } else {
199 None
200 }
201}