1use crate::app::{init::init_all, init::is_initialized, widget::windows};
2use crate::prelude::*;
3use fltk_sys::fl;
4use std::{mem, os::raw, panic, thread, time};
5
6pub fn run() -> Result<(), FltkError> {
10 unsafe {
11 if !is_initialized() {
12 init_all();
13 }
14 if !crate::app::is_ui_thread() {
15 return Err(FltkError::Internal(FltkErrorKind::FailedToRun));
16 }
17 match fl::Fl_run() {
18 0 => Ok(()),
19 _ => Err(FltkError::Internal(FltkErrorKind::FailedToRun)),
20 }
21 }
22}
23
24pub fn enable_locks() -> Result<(), FltkError> {
26 lock()?;
27 Ok(())
28}
29
30pub fn lock() -> Result<(), FltkError> {
34 unsafe {
35 match fl::Fl_lock() {
36 0 => Ok(()),
37 _ => Err(FltkError::Internal(FltkErrorKind::FailedToLock)),
38 }
39 }
40}
41
42pub fn unlock() {
44 unsafe {
45 fl::Fl_unlock();
46 }
47}
48
49pub fn awake() {
51 unsafe { fl::Fl_awake() }
52}
53
54pub fn awake_callback<F: FnMut() + 'static>(cb: F) {
56 unsafe {
57 unsafe extern "C" fn shim(data: *mut raw::c_void) {
58 unsafe {
59 let mut a: Box<Box<dyn FnMut()>> = Box::from_raw(data as *mut Box<dyn FnMut()>);
60 let f: &mut (dyn FnMut()) = &mut **a;
61 let _ = panic::catch_unwind(panic::AssertUnwindSafe(f));
62 }
63 }
64 let a: *mut Box<dyn FnMut()> = Box::into_raw(Box::new(Box::new(cb)));
65 let data: *mut raw::c_void = a as *mut raw::c_void;
66 let callback: fl::Fl_Awake_Handler = Some(shim);
67 fl::Fl_awake_callback(callback, data);
68 }
69}
70
71pub fn wait() -> bool {
74 unsafe {
75 if !is_initialized() {
76 init_all();
77 }
78 assert!(crate::app::is_ui_thread());
79 fl::Fl_wait() != 0
80 }
81}
82
83pub fn sleep(dur: f64) {
85 let dur = dur * 1000.;
86 thread::sleep(time::Duration::from_millis(dur as u64));
87}
88
89pub fn wait_for(dur: f64) -> Result<bool, FltkError> {
95 unsafe {
96 if !is_initialized() {
97 init_all();
98 }
99 if !crate::app::is_ui_thread() {
100 return Err(FltkError::Internal(FltkErrorKind::FailedToRun));
101 }
102 match fl::Fl_wait_for(dur) as i32 {
103 0 => Ok(false),
104 1 => Ok(true),
105 _ => Err(FltkError::Unknown(String::from(
106 "The event loop was probably interrupted by an OS signal!",
107 ))),
108 }
109 }
110}
111
112pub fn should_program_quit() -> bool {
114 unsafe { fl::Fl_should_program_quit() != 0 }
115}
116
117pub fn program_should_quit(flag: bool) {
119 unsafe { fl::Fl_program_should_quit(i32::from(flag)) }
120}
121
122pub fn check() -> bool {
124 unsafe {
125 if !is_initialized() {
126 init_all();
127 }
128 assert!(crate::app::is_ui_thread());
129 fl::Fl_check() != 0
130 }
131}
132
133pub fn ready() -> bool {
136 unsafe {
137 if !is_initialized() {
138 init_all();
139 }
140 assert!(crate::app::is_ui_thread());
141 fl::Fl_ready() != 0
142 }
143}
144
145pub fn quit() {
147 if let Some(wins) = windows() {
148 for mut i in wins {
149 if i.shown() {
150 i.hide();
151 }
152 }
153 }
154}
155
156pub type IdleHandle = *mut ();
158
159unsafe extern "C" fn idle_shim(data: *mut raw::c_void) {
160 unsafe {
161 let a: *mut Box<dyn FnMut(IdleHandle)> = data as *mut Box<dyn FnMut(IdleHandle)>;
162 let f: &mut (dyn FnMut(IdleHandle)) = &mut **a;
163 let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| (*f)(data as _)));
164 }
165}
166
167pub fn add_idle<F: FnMut(IdleHandle) + 'static>(cb: F) -> IdleHandle {
171 unsafe {
172 let a: *mut Box<dyn FnMut(IdleHandle)> = Box::into_raw(Box::new(Box::new(cb)));
173 let data: *mut raw::c_void = a as *mut raw::c_void;
174 let callback: Option<unsafe extern "C" fn(arg1: *mut raw::c_void)> = Some(idle_shim);
175 fl::Fl_add_idle(callback, data);
176
177 data as _
178 }
179}
180
181pub fn remove_idle(handle: IdleHandle) {
183 unsafe {
184 let data: *mut raw::c_void = handle as *mut raw::c_void;
185 let callback: Option<unsafe extern "C" fn(arg1: *mut raw::c_void)> = Some(idle_shim);
186 fl::Fl_remove_idle(callback, data);
187 }
188}
189
190pub fn has_idle(handle: IdleHandle) -> bool {
192 unsafe {
193 let data: *mut raw::c_void = handle as *mut raw::c_void;
194 let callback: Option<unsafe extern "C" fn(arg1: *mut raw::c_void)> = Some(idle_shim);
195 fl::Fl_has_idle(callback, data) != 0
196 }
197}
198
199pub type CheckHandle = *mut ();
201
202pub fn add_check<F: FnMut(CheckHandle) + 'static>(cb: F) -> CheckHandle {
205 unsafe {
206 let a: *mut Box<dyn FnMut(CheckHandle)> = Box::into_raw(Box::new(Box::new(cb)));
207 let data: *mut raw::c_void = a as *mut raw::c_void;
208 let callback: Option<unsafe extern "C" fn(arg1: *mut raw::c_void)> = Some(idle_shim);
209 fl::Fl_add_check(callback, data);
210
211 data as _
212 }
213}
214
215pub fn remove_check(handle: CheckHandle) {
217 unsafe {
218 let data: *mut raw::c_void = handle as *mut raw::c_void;
219 let callback: Option<unsafe extern "C" fn(arg1: *mut raw::c_void)> = Some(idle_shim);
220 fl::Fl_remove_check(callback, data);
221 }
222}
223
224pub fn has_check(handle: CheckHandle) -> bool {
226 unsafe {
227 let data: *mut raw::c_void = handle as *mut raw::c_void;
228 let callback: Option<unsafe extern "C" fn(arg1: *mut raw::c_void)> = Some(idle_shim);
229 fl::Fl_has_check(callback, data) != 0
230 }
231}
232
233unsafe extern "C" fn clipboard_notify_shim(source: i32, data: *mut raw::c_void) {
234 unsafe {
235 let a: *mut Box<dyn FnMut(i32)> = data as *mut Box<dyn FnMut(i32)>;
236 let f: &mut (dyn FnMut(i32)) = &mut **a;
237 let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| (*f)(source)));
238 }
239}
240
241pub fn add_clipboard_notify<F: FnMut(i32) + 'static>(cb: F) {
245 unsafe {
246 let a: *mut Box<dyn FnMut(i32)> = Box::into_raw(Box::new(Box::new(cb)));
247 let data: *mut raw::c_void = a as *mut raw::c_void;
248 let callback: Option<unsafe extern "C" fn(source: i32, arg1: *mut raw::c_void)> =
249 Some(clipboard_notify_shim);
250 fl::Fl_add_clipboard_notify(callback, data);
251 }
252}
253
254pub fn remove_clipboard_notify() {
258 unsafe {
259 let callback: Option<unsafe extern "C" fn(source: i32, arg1: *mut raw::c_void)> =
260 Some(clipboard_notify_shim);
261 fl::Fl_remove_clipboard_notify(callback);
262 }
263}
264
265pub type TimeoutHandle = *mut ();
267
268unsafe extern "C" fn timeout_shim(data: *mut raw::c_void) {
269 unsafe {
270 let a: *mut Box<dyn FnMut(TimeoutHandle)> = data as *mut Box<dyn FnMut(TimeoutHandle)>;
271 let f: &mut (dyn FnMut(TimeoutHandle)) = &mut **a;
272 let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| (*f)(data as _)));
273 }
274}
275
276pub fn add_timeout<F: FnMut(TimeoutHandle) + 'static>(tm: f64, cb: F) -> TimeoutHandle {
296 assert!(crate::app::is_ui_thread());
297 unsafe {
298 let a: *mut Box<dyn FnMut(TimeoutHandle)> = Box::into_raw(Box::new(Box::new(cb)));
299 let data: *mut raw::c_void = a as *mut raw::c_void;
300 let callback: Option<unsafe extern "C" fn(arg1: *mut raw::c_void)> = Some(timeout_shim);
301 fl::Fl_add_timeout(tm, callback, data);
302
303 data as _
304 }
305}
306
307pub fn repeat_timeout(tm: f64, handle: TimeoutHandle) {
329 assert!(crate::app::is_ui_thread());
330 unsafe {
331 let data: *mut raw::c_void = handle as *mut raw::c_void;
332 let callback: Option<unsafe extern "C" fn(arg1: *mut raw::c_void)> = Some(timeout_shim);
333 fl::Fl_repeat_timeout(tm, callback, data);
334 }
335}
336
337pub fn remove_timeout(handle: TimeoutHandle) {
356 assert!(crate::app::is_ui_thread());
357 unsafe {
358 let data: *mut raw::c_void = handle as *mut raw::c_void;
359 let callback: Option<unsafe extern "C" fn(arg1: *mut raw::c_void)> = Some(timeout_shim);
360 fl::Fl_remove_timeout(callback, data);
361 }
362}
363
364pub fn has_timeout(handle: TimeoutHandle) -> bool {
366 assert!(crate::app::is_ui_thread());
367 unsafe {
368 let data: *mut raw::c_void = handle as *mut raw::c_void;
369 let callback: Option<unsafe extern "C" fn(arg1: *mut raw::c_void)> = Some(timeout_shim);
370 fl::Fl_has_timeout(callback, data) != 0
371 }
372}
373
374#[doc(hidden)]
375pub fn add_raw_timeout<T>(tm: f64, cb: fn(*mut T), data: *mut T) {
376 unsafe {
377 let callback: Option<unsafe extern "C" fn(arg1: *mut raw::c_void)> =
378 Some(mem::transmute(cb));
379 let data: *mut raw::c_void = data as *mut raw::c_void;
380 fl::Fl_add_timeout(tm, callback, data);
381 }
382}
383
384#[doc(hidden)]
385pub fn repeat_raw_timeout<T>(tm: f64, cb: fn(*mut T), data: *mut T) {
386 unsafe {
387 let callback: Option<unsafe extern "C" fn(arg1: *mut raw::c_void)> =
388 Some(mem::transmute(cb));
389 let data: *mut raw::c_void = data as *mut raw::c_void;
390 fl::Fl_repeat_timeout(tm, callback, data);
391 }
392}
393
394#[doc(hidden)]
395pub fn remove_raw_timeout<T>(cb: fn(*mut T), data: *mut T) {
396 unsafe {
397 let callback: Option<unsafe extern "C" fn(arg1: *mut raw::c_void)> =
398 Some(mem::transmute(cb));
399 let data: *mut raw::c_void = data as *mut raw::c_void;
400 fl::Fl_remove_timeout(callback, data);
401 }
402}
403
404#[doc(hidden)]
405pub fn has_raw_timeout<T>(cb: fn(*mut T), data: *mut T) -> bool {
406 unsafe {
407 let callback: Option<unsafe extern "C" fn(arg1: *mut raw::c_void)> =
408 Some(mem::transmute(cb));
409 let data: *mut raw::c_void = data as *mut raw::c_void;
410 fl::Fl_has_timeout(callback, data) != 0
411 }
412}
413
414pub unsafe fn add_system_handler(
418 cb: Option<unsafe extern "C" fn(*mut raw::c_void, *mut raw::c_void) -> i32>,
419 data: *mut raw::c_void,
420) {
421 unsafe {
422 assert!(crate::app::is_ui_thread());
423 fl::Fl_add_system_handler(cb, data);
424 }
425}
426
427pub unsafe fn remove_system_handler(
431 cb: Option<unsafe extern "C" fn(*mut raw::c_void, *mut raw::c_void) -> i32>,
432) {
433 unsafe {
434 assert!(crate::app::is_ui_thread());
435 fl::Fl_remove_system_handler(cb);
436 }
437}