1#[cfg(unix)]
4use std::os::unix::io::RawFd;
5use std::{cell::RefCell, mem::transmute, num::NonZeroU32, time::Duration};
6
7use crate::ffi::{self, gboolean, gpointer};
8#[cfg(all(not(unix), docsrs))]
9use libc::c_int as RawFd;
10
11#[cfg(unix)]
12use crate::IOCondition;
13use crate::{thread_guard::ThreadGuard, translate::*, ControlFlow, MainContext, Source};
14
15#[derive(Debug, Eq, PartialEq)]
21pub struct SourceId(NonZeroU32);
22
23impl SourceId {
24 pub fn as_raw(&self) -> u32 {
27 self.0.get()
28 }
29
30 #[doc(alias = "g_source_remove")]
35 pub fn remove(self) {
36 unsafe {
37 result_from_gboolean!(
38 ffi::g_source_remove(self.as_raw()),
39 "Failed to remove source"
40 )
41 .unwrap()
42 }
43 }
44}
45
46#[doc(hidden)]
47impl FromGlib<u32> for SourceId {
48 #[inline]
49 unsafe fn from_glib(val: u32) -> Self {
50 debug_assert_ne!(val, 0);
51 Self(NonZeroU32::new_unchecked(val))
52 }
53}
54
55#[derive(Copy, Clone, Debug, Eq, PartialEq)]
58#[doc(alias = "GPid")]
59pub struct Pid(pub ffi::GPid);
60
61unsafe impl Send for Pid {}
62unsafe impl Sync for Pid {}
63
64#[doc(hidden)]
65impl IntoGlib for Pid {
66 type GlibType = ffi::GPid;
67
68 #[inline]
69 fn into_glib(self) -> ffi::GPid {
70 self.0
71 }
72}
73
74#[doc(hidden)]
75impl FromGlib<ffi::GPid> for Pid {
76 #[inline]
77 unsafe fn from_glib(val: ffi::GPid) -> Self {
78 Self(val)
79 }
80}
81
82unsafe extern "C" fn trampoline<F: FnMut() -> ControlFlow + Send + 'static>(
83 func: gpointer,
84) -> gboolean {
85 let func: &RefCell<F> = &*(func as *const RefCell<F>);
86 (*func.borrow_mut())().into_glib()
87}
88
89unsafe extern "C" fn trampoline_local<F: FnMut() -> ControlFlow + 'static>(
90 func: gpointer,
91) -> gboolean {
92 let func: &ThreadGuard<RefCell<F>> = &*(func as *const ThreadGuard<RefCell<F>>);
93 (*func.get_ref().borrow_mut())().into_glib()
94}
95
96unsafe extern "C" fn destroy_closure<F: FnMut() -> ControlFlow + Send + 'static>(ptr: gpointer) {
97 let _ = Box::<RefCell<F>>::from_raw(ptr as *mut _);
98}
99
100unsafe extern "C" fn destroy_closure_local<F: FnMut() -> ControlFlow + 'static>(ptr: gpointer) {
101 let _ = Box::<ThreadGuard<RefCell<F>>>::from_raw(ptr as *mut _);
102}
103
104fn into_raw<F: FnMut() -> ControlFlow + Send + 'static>(func: F) -> gpointer {
105 let func: Box<RefCell<F>> = Box::new(RefCell::new(func));
106 Box::into_raw(func) as gpointer
107}
108
109fn into_raw_local<F: FnMut() -> ControlFlow + 'static>(func: F) -> gpointer {
110 let func: Box<ThreadGuard<RefCell<F>>> = Box::new(ThreadGuard::new(RefCell::new(func)));
111 Box::into_raw(func) as gpointer
112}
113
114unsafe extern "C" fn trampoline_child_watch<F: FnMut(Pid, i32) + Send + 'static>(
115 pid: ffi::GPid,
116 status: i32,
117 func: gpointer,
118) {
119 let func: &RefCell<F> = &*(func as *const RefCell<F>);
120 (*func.borrow_mut())(Pid(pid), status)
121}
122
123unsafe extern "C" fn trampoline_child_watch_local<F: FnMut(Pid, i32) + 'static>(
124 pid: ffi::GPid,
125 status: i32,
126 func: gpointer,
127) {
128 let func: &ThreadGuard<RefCell<F>> = &*(func as *const ThreadGuard<RefCell<F>>);
129 (*func.get_ref().borrow_mut())(Pid(pid), status)
130}
131
132unsafe extern "C" fn destroy_closure_child_watch<F: FnMut(Pid, i32) + Send + 'static>(
133 ptr: gpointer,
134) {
135 let _ = Box::<RefCell<F>>::from_raw(ptr as *mut _);
136}
137
138unsafe extern "C" fn destroy_closure_child_watch_local<F: FnMut(Pid, i32) + 'static>(
139 ptr: gpointer,
140) {
141 let _ = Box::<ThreadGuard<RefCell<F>>>::from_raw(ptr as *mut _);
142}
143
144fn into_raw_child_watch<F: FnMut(Pid, i32) + Send + 'static>(func: F) -> gpointer {
145 let func: Box<RefCell<F>> = Box::new(RefCell::new(func));
146 Box::into_raw(func) as gpointer
147}
148
149fn into_raw_child_watch_local<F: FnMut(Pid, i32) + 'static>(func: F) -> gpointer {
150 let func: Box<ThreadGuard<RefCell<F>>> = Box::new(ThreadGuard::new(RefCell::new(func)));
151 Box::into_raw(func) as gpointer
152}
153
154#[cfg(unix)]
155#[cfg_attr(docsrs, doc(cfg(unix)))]
156unsafe extern "C" fn trampoline_unix_fd<
157 F: FnMut(RawFd, IOCondition) -> ControlFlow + Send + 'static,
158>(
159 fd: i32,
160 condition: ffi::GIOCondition,
161 func: gpointer,
162) -> gboolean {
163 let func: &RefCell<F> = &*(func as *const RefCell<F>);
164 (*func.borrow_mut())(fd, from_glib(condition)).into_glib()
165}
166
167#[cfg(unix)]
168#[cfg_attr(docsrs, doc(cfg(unix)))]
169unsafe extern "C" fn trampoline_unix_fd_local<
170 F: FnMut(RawFd, IOCondition) -> ControlFlow + 'static,
171>(
172 fd: i32,
173 condition: ffi::GIOCondition,
174 func: gpointer,
175) -> gboolean {
176 let func: &ThreadGuard<RefCell<F>> = &*(func as *const ThreadGuard<RefCell<F>>);
177 (*func.get_ref().borrow_mut())(fd, from_glib(condition)).into_glib()
178}
179
180#[cfg(unix)]
181#[cfg_attr(docsrs, doc(cfg(unix)))]
182unsafe extern "C" fn destroy_closure_unix_fd<
183 F: FnMut(RawFd, IOCondition) -> ControlFlow + Send + 'static,
184>(
185 ptr: gpointer,
186) {
187 let _ = Box::<RefCell<F>>::from_raw(ptr as *mut _);
188}
189
190#[cfg(unix)]
191#[cfg_attr(docsrs, doc(cfg(unix)))]
192unsafe extern "C" fn destroy_closure_unix_fd_local<
193 F: FnMut(RawFd, IOCondition) -> ControlFlow + 'static,
194>(
195 ptr: gpointer,
196) {
197 let _ = Box::<ThreadGuard<RefCell<F>>>::from_raw(ptr as *mut _);
198}
199
200#[cfg(unix)]
201#[cfg_attr(docsrs, doc(cfg(unix)))]
202fn into_raw_unix_fd<F: FnMut(RawFd, IOCondition) -> ControlFlow + Send + 'static>(
203 func: F,
204) -> gpointer {
205 let func: Box<RefCell<F>> = Box::new(RefCell::new(func));
206 Box::into_raw(func) as gpointer
207}
208
209#[cfg(unix)]
210#[cfg_attr(docsrs, doc(cfg(unix)))]
211fn into_raw_unix_fd_local<F: FnMut(RawFd, IOCondition) -> ControlFlow + 'static>(
212 func: F,
213) -> gpointer {
214 let func: Box<ThreadGuard<RefCell<F>>> = Box::new(ThreadGuard::new(RefCell::new(func)));
215 Box::into_raw(func) as gpointer
216}
217
218#[inline(always)]
224fn fnmut_callback_wrapper(
225 func: impl FnOnce() + Send + 'static,
226) -> impl FnMut() -> ControlFlow + Send + 'static {
227 let mut func = Some(func);
228 move || {
229 let func = func
230 .take()
231 .expect("GSource closure called after returning ControlFlow::Break");
232 func();
233 ControlFlow::Break
234 }
235}
236
237#[inline(always)]
246fn fnmut_callback_wrapper_local(
247 func: impl FnOnce() + 'static,
248) -> impl FnMut() -> ControlFlow + 'static {
249 let mut func = Some(func);
250 move || {
251 let func = func
252 .take()
253 .expect("GSource closure called after returning glib::ControlFlow::Break");
254 func();
255 ControlFlow::Break
256 }
257}
258
259#[doc(alias = "g_idle_add_full")]
267pub fn idle_add<F>(func: F) -> SourceId
268where
269 F: FnMut() -> ControlFlow + Send + 'static,
270{
271 unsafe {
272 from_glib(ffi::g_idle_add_full(
273 ffi::G_PRIORITY_DEFAULT_IDLE,
274 Some(trampoline::<F>),
275 into_raw(func),
276 Some(destroy_closure::<F>),
277 ))
278 }
279}
280
281#[doc(alias = "g_idle_add_full")]
290pub fn idle_add_full<F>(priority: Priority, func: F) -> SourceId
291where
292 F: FnMut() -> ControlFlow + Send + 'static,
293{
294 unsafe {
295 from_glib(ffi::g_idle_add_full(
296 priority.into_glib(),
297 Some(trampoline::<F>),
298 into_raw(func),
299 Some(destroy_closure::<F>),
300 ))
301 }
302}
303
304#[doc(alias = "g_idle_add_full")]
315#[doc(alias = "g_idle_add_once")]
316pub fn idle_add_once<F>(func: F) -> SourceId
317where
318 F: FnOnce() + Send + 'static,
319{
320 idle_add(fnmut_callback_wrapper(func))
321}
322
323#[doc(alias = "g_idle_add_full")]
337pub fn idle_add_local<F>(func: F) -> SourceId
338where
339 F: FnMut() -> ControlFlow + 'static,
340{
341 unsafe {
342 let context = MainContext::default();
343 let _acquire = context
344 .acquire()
345 .expect("default main context already acquired by another thread");
346 from_glib(ffi::g_idle_add_full(
347 ffi::G_PRIORITY_DEFAULT_IDLE,
348 Some(trampoline_local::<F>),
349 into_raw_local(func),
350 Some(destroy_closure_local::<F>),
351 ))
352 }
353}
354
355#[doc(alias = "g_idle_add_full")]
370pub fn idle_add_local_full<F>(priority: Priority, func: F) -> SourceId
371where
372 F: FnMut() -> ControlFlow + 'static,
373{
374 unsafe {
375 let context = MainContext::default();
376 let _acquire = context
377 .acquire()
378 .expect("default main context already acquired by another thread");
379 from_glib(ffi::g_idle_add_full(
380 priority.into_glib(),
381 Some(trampoline_local::<F>),
382 into_raw_local(func),
383 Some(destroy_closure_local::<F>),
384 ))
385 }
386}
387
388#[doc(alias = "g_idle_add_full")]
405pub fn idle_add_local_once<F>(func: F) -> SourceId
406where
407 F: FnOnce() + 'static,
408{
409 idle_add_local(fnmut_callback_wrapper_local(func))
410}
411
412#[doc(alias = "g_timeout_add_full")]
424pub fn timeout_add<F>(interval: Duration, func: F) -> SourceId
425where
426 F: FnMut() -> ControlFlow + Send + 'static,
427{
428 unsafe {
429 from_glib(ffi::g_timeout_add_full(
430 ffi::G_PRIORITY_DEFAULT,
431 interval.as_millis() as _,
432 Some(trampoline::<F>),
433 into_raw(func),
434 Some(destroy_closure::<F>),
435 ))
436 }
437}
438
439#[doc(alias = "g_timeout_add_full")]
451pub fn timeout_add_full<F>(interval: Duration, priority: Priority, func: F) -> SourceId
452where
453 F: FnMut() -> ControlFlow + Send + 'static,
454{
455 unsafe {
456 from_glib(ffi::g_timeout_add_full(
457 priority.into_glib(),
458 interval.as_millis() as _,
459 Some(trampoline::<F>),
460 into_raw(func),
461 Some(destroy_closure::<F>),
462 ))
463 }
464}
465
466#[doc(alias = "g_timeout_add_full")]
481#[doc(alias = "g_timeout_add_once")]
482pub fn timeout_add_once<F>(interval: Duration, func: F) -> SourceId
483where
484 F: FnOnce() + Send + 'static,
485{
486 timeout_add(interval, fnmut_callback_wrapper(func))
487}
488
489#[doc(alias = "g_timeout_add_full")]
507pub fn timeout_add_local<F>(interval: Duration, func: F) -> SourceId
508where
509 F: FnMut() -> ControlFlow + 'static,
510{
511 unsafe {
512 let context = MainContext::default();
513 let _acquire = context
514 .acquire()
515 .expect("default main context already acquired by another thread");
516 from_glib(ffi::g_timeout_add_full(
517 ffi::G_PRIORITY_DEFAULT,
518 interval.as_millis() as _,
519 Some(trampoline_local::<F>),
520 into_raw_local(func),
521 Some(destroy_closure_local::<F>),
522 ))
523 }
524}
525
526#[doc(alias = "g_timeout_add_full")]
544pub fn timeout_add_local_full<F>(interval: Duration, priority: Priority, func: F) -> SourceId
545where
546 F: FnMut() -> ControlFlow + 'static,
547{
548 unsafe {
549 let context = MainContext::default();
550 let _acquire = context
551 .acquire()
552 .expect("default main context already acquired by another thread");
553 from_glib(ffi::g_timeout_add_full(
554 priority.into_glib(),
555 interval.as_millis() as _,
556 Some(trampoline_local::<F>),
557 into_raw_local(func),
558 Some(destroy_closure_local::<F>),
559 ))
560 }
561}
562
563#[doc(alias = "g_timeout_add_full")]
584pub fn timeout_add_local_once<F>(interval: Duration, func: F) -> SourceId
585where
586 F: FnOnce() + 'static,
587{
588 timeout_add_local(interval, fnmut_callback_wrapper_local(func))
589}
590
591#[doc(alias = "g_timeout_add_seconds_full")]
602pub fn timeout_add_seconds<F>(interval: u32, func: F) -> SourceId
603where
604 F: FnMut() -> ControlFlow + Send + 'static,
605{
606 unsafe {
607 from_glib(ffi::g_timeout_add_seconds_full(
608 ffi::G_PRIORITY_DEFAULT,
609 interval,
610 Some(trampoline::<F>),
611 into_raw(func),
612 Some(destroy_closure::<F>),
613 ))
614 }
615}
616
617#[doc(alias = "g_timeout_add_seconds_full")]
631pub fn timeout_add_seconds_once<F>(interval: u32, func: F) -> SourceId
632where
633 F: FnOnce() + Send + 'static,
634{
635 timeout_add_seconds(interval, fnmut_callback_wrapper(func))
636}
637
638#[doc(alias = "g_timeout_add_seconds_full")]
655pub fn timeout_add_seconds_local<F>(interval: u32, func: F) -> SourceId
656where
657 F: FnMut() -> ControlFlow + 'static,
658{
659 unsafe {
660 let context = MainContext::default();
661 let _acquire = context
662 .acquire()
663 .expect("default main context already acquired by another thread");
664 from_glib(ffi::g_timeout_add_seconds_full(
665 ffi::G_PRIORITY_DEFAULT,
666 interval,
667 Some(trampoline_local::<F>),
668 into_raw_local(func),
669 Some(destroy_closure_local::<F>),
670 ))
671 }
672}
673
674#[doc(alias = "g_timeout_add_seconds_full")]
694pub fn timeout_add_seconds_local_once<F>(interval: u32, func: F) -> SourceId
695where
696 F: FnOnce() + 'static,
697{
698 timeout_add_seconds_local(interval, fnmut_callback_wrapper_local(func))
699}
700
701#[doc(alias = "g_child_watch_add_full")]
707pub fn child_watch_add<F>(pid: Pid, func: F) -> SourceId
708where
709 F: FnMut(Pid, i32) + Send + 'static,
710{
711 unsafe {
712 from_glib(ffi::g_child_watch_add_full(
713 ffi::G_PRIORITY_DEFAULT,
714 pid.0,
715 Some(trampoline_child_watch::<F>),
716 into_raw_child_watch(func),
717 Some(destroy_closure_child_watch::<F>),
718 ))
719 }
720}
721
722#[doc(alias = "g_child_watch_add_full")]
734pub fn child_watch_add_local<F>(pid: Pid, func: F) -> SourceId
735where
736 F: FnMut(Pid, i32) + 'static,
737{
738 unsafe {
739 let context = MainContext::default();
740 let _acquire = context
741 .acquire()
742 .expect("default main context already acquired by another thread");
743 from_glib(ffi::g_child_watch_add_full(
744 ffi::G_PRIORITY_DEFAULT,
745 pid.0,
746 Some(trampoline_child_watch_local::<F>),
747 into_raw_child_watch_local(func),
748 Some(destroy_closure_child_watch_local::<F>),
749 ))
750 }
751}
752
753#[cfg(unix)]
754#[cfg_attr(docsrs, doc(cfg(unix)))]
755#[doc(alias = "g_unix_signal_add_full")]
764pub fn unix_signal_add<F>(signum: i32, func: F) -> SourceId
765where
766 F: FnMut() -> ControlFlow + Send + 'static,
767{
768 unsafe {
769 from_glib(ffi::g_unix_signal_add_full(
770 ffi::G_PRIORITY_DEFAULT,
771 signum,
772 Some(trampoline::<F>),
773 into_raw(func),
774 Some(destroy_closure::<F>),
775 ))
776 }
777}
778
779#[cfg(unix)]
780#[cfg_attr(docsrs, doc(cfg(unix)))]
781#[doc(alias = "g_unix_signal_add_full")]
793pub fn unix_signal_add_once<F>(signum: i32, func: F) -> SourceId
794where
795 F: FnOnce() + Send + 'static,
796{
797 unix_signal_add(signum, fnmut_callback_wrapper(func))
798}
799
800#[cfg(unix)]
801#[cfg_attr(docsrs, doc(cfg(unix)))]
802#[doc(alias = "g_unix_signal_add_full")]
817pub fn unix_signal_add_local<F>(signum: i32, func: F) -> SourceId
818where
819 F: FnMut() -> ControlFlow + 'static,
820{
821 unsafe {
822 let context = MainContext::default();
823 let _acquire = context
824 .acquire()
825 .expect("default main context already acquired by another thread");
826 from_glib(ffi::g_unix_signal_add_full(
827 ffi::G_PRIORITY_DEFAULT,
828 signum,
829 Some(trampoline_local::<F>),
830 into_raw_local(func),
831 Some(destroy_closure_local::<F>),
832 ))
833 }
834}
835
836#[cfg(unix)]
837#[cfg_attr(docsrs, doc(cfg(unix)))]
838#[doc(alias = "g_unix_signal_add_full")]
856pub fn unix_signal_add_local_once<F>(signum: i32, func: F) -> SourceId
857where
858 F: FnOnce() + 'static,
859{
860 unix_signal_add_local(signum, fnmut_callback_wrapper_local(func))
861}
862
863#[cfg(unix)]
864#[cfg_attr(docsrs, doc(cfg(unix)))]
865#[doc(alias = "g_unix_fd_add_full")]
875pub fn unix_fd_add<F>(fd: RawFd, condition: IOCondition, func: F) -> SourceId
876where
877 F: FnMut(RawFd, IOCondition) -> ControlFlow + Send + 'static,
878{
879 unsafe {
880 from_glib(ffi::g_unix_fd_add_full(
881 ffi::G_PRIORITY_DEFAULT,
882 fd,
883 condition.into_glib(),
884 Some(trampoline_unix_fd::<F>),
885 into_raw_unix_fd(func),
886 Some(destroy_closure_unix_fd::<F>),
887 ))
888 }
889}
890
891#[cfg(unix)]
892#[cfg_attr(docsrs, doc(cfg(unix)))]
893#[doc(alias = "g_unix_fd_add_full")]
903pub fn unix_fd_add_full<F>(
904 fd: RawFd,
905 priority: Priority,
906 condition: IOCondition,
907 func: F,
908) -> SourceId
909where
910 F: FnMut(RawFd, IOCondition) -> ControlFlow + Send + 'static,
911{
912 unsafe {
913 from_glib(ffi::g_unix_fd_add_full(
914 priority.into_glib(),
915 fd,
916 condition.into_glib(),
917 Some(trampoline_unix_fd::<F>),
918 into_raw_unix_fd(func),
919 Some(destroy_closure_unix_fd::<F>),
920 ))
921 }
922}
923
924#[cfg(unix)]
925#[cfg_attr(docsrs, doc(cfg(unix)))]
926#[doc(alias = "g_unix_fd_add_full")]
942pub fn unix_fd_add_local<F>(fd: RawFd, condition: IOCondition, func: F) -> SourceId
943where
944 F: FnMut(RawFd, IOCondition) -> ControlFlow + 'static,
945{
946 unsafe {
947 let context = MainContext::default();
948 let _acquire = context
949 .acquire()
950 .expect("default main context already acquired by another thread");
951 from_glib(ffi::g_unix_fd_add_full(
952 ffi::G_PRIORITY_DEFAULT,
953 fd,
954 condition.into_glib(),
955 Some(trampoline_unix_fd_local::<F>),
956 into_raw_unix_fd_local(func),
957 Some(destroy_closure_unix_fd_local::<F>),
958 ))
959 }
960}
961
962#[cfg(unix)]
963#[cfg_attr(docsrs, doc(cfg(unix)))]
964#[doc(alias = "g_unix_fd_add_full")]
980pub fn unix_fd_add_local_full<F>(
981 fd: RawFd,
982 priority: Priority,
983 condition: IOCondition,
984 func: F,
985) -> SourceId
986where
987 F: FnMut(RawFd, IOCondition) -> ControlFlow + 'static,
988{
989 unsafe {
990 let context = MainContext::default();
991 let _acquire = context
992 .acquire()
993 .expect("default main context already acquired by another thread");
994 from_glib(ffi::g_unix_fd_add_full(
995 priority.into_glib(),
996 fd,
997 condition.into_glib(),
998 Some(trampoline_unix_fd_local::<F>),
999 into_raw_unix_fd_local(func),
1000 Some(destroy_closure_unix_fd_local::<F>),
1001 ))
1002 }
1003}
1004
1005#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
1008pub struct Priority(i32);
1009
1010impl Priority {
1011 #[doc(alias = "G_PRIORITY_HIGH")]
1012 pub const HIGH: Self = Self(ffi::G_PRIORITY_HIGH);
1013 #[doc(alias = "G_PRIORITY_DEFAULT")]
1014 pub const DEFAULT: Self = Self(ffi::G_PRIORITY_DEFAULT);
1015 #[doc(alias = "G_PRIORITY_HIGH_IDLE")]
1016 pub const HIGH_IDLE: Self = Self(ffi::G_PRIORITY_HIGH_IDLE);
1017 #[doc(alias = "G_PRIORITY_DEFAULT_IDLE")]
1018 pub const DEFAULT_IDLE: Self = Self(ffi::G_PRIORITY_DEFAULT_IDLE);
1019 #[doc(alias = "G_PRIORITY_LOW")]
1020 pub const LOW: Self = Self(ffi::G_PRIORITY_LOW);
1021}
1022
1023impl Default for Priority {
1024 fn default() -> Self {
1025 Self::DEFAULT
1026 }
1027}
1028
1029#[doc(hidden)]
1030impl IntoGlib for Priority {
1031 type GlibType = i32;
1032
1033 #[inline]
1034 fn into_glib(self) -> i32 {
1035 self.0
1036 }
1037}
1038
1039#[doc(hidden)]
1040impl FromGlib<i32> for Priority {
1041 #[inline]
1042 unsafe fn from_glib(val: i32) -> Self {
1043 Self::from(val)
1044 }
1045}
1046
1047impl From<i32> for Priority {
1048 fn from(value: i32) -> Self {
1049 Self(value)
1050 }
1051}
1052
1053#[doc(alias = "g_idle_source_new")]
1058pub fn idle_source_new<F>(name: Option<&str>, priority: Priority, func: F) -> Source
1059where
1060 F: FnMut() -> ControlFlow + Send + 'static,
1061{
1062 unsafe {
1063 let source = ffi::g_idle_source_new();
1064 ffi::g_source_set_callback(
1065 source,
1066 Some(trampoline::<F>),
1067 into_raw(func),
1068 Some(destroy_closure::<F>),
1069 );
1070 ffi::g_source_set_priority(source, priority.into_glib());
1071
1072 if let Some(name) = name {
1073 ffi::g_source_set_name(source, name.to_glib_none().0);
1074 }
1075
1076 from_glib_full(source)
1077 }
1078}
1079
1080#[doc(alias = "g_timeout_source_new")]
1089pub fn timeout_source_new<F>(
1090 interval: Duration,
1091 name: Option<&str>,
1092 priority: Priority,
1093 func: F,
1094) -> Source
1095where
1096 F: FnMut() -> ControlFlow + Send + 'static,
1097{
1098 unsafe {
1099 let source = ffi::g_timeout_source_new(interval.as_millis() as _);
1100 ffi::g_source_set_callback(
1101 source,
1102 Some(trampoline::<F>),
1103 into_raw(func),
1104 Some(destroy_closure::<F>),
1105 );
1106 ffi::g_source_set_priority(source, priority.into_glib());
1107
1108 if let Some(name) = name {
1109 ffi::g_source_set_name(source, name.to_glib_none().0);
1110 }
1111
1112 from_glib_full(source)
1113 }
1114}
1115
1116#[doc(alias = "g_timeout_source_new_seconds")]
1124pub fn timeout_source_new_seconds<F>(
1125 interval: u32,
1126 name: Option<&str>,
1127 priority: Priority,
1128 func: F,
1129) -> Source
1130where
1131 F: FnMut() -> ControlFlow + Send + 'static,
1132{
1133 unsafe {
1134 let source = ffi::g_timeout_source_new_seconds(interval);
1135 ffi::g_source_set_callback(
1136 source,
1137 Some(trampoline::<F>),
1138 into_raw(func),
1139 Some(destroy_closure::<F>),
1140 );
1141 ffi::g_source_set_priority(source, priority.into_glib());
1142
1143 if let Some(name) = name {
1144 ffi::g_source_set_name(source, name.to_glib_none().0);
1145 }
1146
1147 from_glib_full(source)
1148 }
1149}
1150
1151#[doc(alias = "g_child_watch_source_new")]
1157pub fn child_watch_source_new<F>(
1158 pid: Pid,
1159 name: Option<&str>,
1160 priority: Priority,
1161 func: F,
1162) -> Source
1163where
1164 F: FnMut(Pid, i32) + Send + 'static,
1165{
1166 unsafe {
1167 let source = ffi::g_child_watch_source_new(pid.0);
1168 ffi::g_source_set_callback(
1169 source,
1170 Some(transmute::<
1171 *mut (),
1172 unsafe extern "C" fn(ffi::gpointer) -> ffi::gboolean,
1173 >(trampoline_child_watch::<F> as *mut ())),
1174 into_raw_child_watch(func),
1175 Some(destroy_closure_child_watch::<F>),
1176 );
1177 ffi::g_source_set_priority(source, priority.into_glib());
1178
1179 if let Some(name) = name {
1180 ffi::g_source_set_name(source, name.to_glib_none().0);
1181 }
1182
1183 from_glib_full(source)
1184 }
1185}
1186
1187#[cfg(unix)]
1188#[cfg_attr(docsrs, doc(cfg(unix)))]
1189#[doc(alias = "g_unix_signal_source_new")]
1196pub fn unix_signal_source_new<F>(
1197 signum: i32,
1198 name: Option<&str>,
1199 priority: Priority,
1200 func: F,
1201) -> Source
1202where
1203 F: FnMut() -> ControlFlow + Send + 'static,
1204{
1205 unsafe {
1206 let source = ffi::g_unix_signal_source_new(signum);
1207 ffi::g_source_set_callback(
1208 source,
1209 Some(trampoline::<F>),
1210 into_raw(func),
1211 Some(destroy_closure::<F>),
1212 );
1213 ffi::g_source_set_priority(source, priority.into_glib());
1214
1215 if let Some(name) = name {
1216 ffi::g_source_set_name(source, name.to_glib_none().0);
1217 }
1218
1219 from_glib_full(source)
1220 }
1221}
1222
1223#[cfg(unix)]
1224#[cfg_attr(docsrs, doc(cfg(unix)))]
1225#[doc(alias = "g_unix_fd_source_new")]
1232pub fn unix_fd_source_new<F>(
1233 fd: RawFd,
1234 condition: IOCondition,
1235 name: Option<&str>,
1236 priority: Priority,
1237 func: F,
1238) -> Source
1239where
1240 F: FnMut(RawFd, IOCondition) -> ControlFlow + Send + 'static,
1241{
1242 unsafe {
1243 let source = ffi::g_unix_fd_source_new(fd, condition.into_glib());
1244 ffi::g_source_set_callback(
1245 source,
1246 Some(transmute::<
1247 *const (),
1248 unsafe extern "C" fn(ffi::gpointer) -> ffi::gboolean,
1249 >(trampoline_unix_fd::<F> as *const ())),
1250 into_raw_unix_fd(func),
1251 Some(destroy_closure_unix_fd::<F>),
1252 );
1253 ffi::g_source_set_priority(source, priority.into_glib());
1254
1255 if let Some(name) = name {
1256 ffi::g_source_set_name(source, name.to_glib_none().0);
1257 }
1258
1259 from_glib_full(source)
1260 }
1261}
1262
1263impl Source {
1264 #[doc(alias = "g_source_attach")]
1265 pub fn attach(&self, context: Option<&MainContext>) -> SourceId {
1266 unsafe {
1267 from_glib(ffi::g_source_attach(
1268 self.to_glib_none().0,
1269 context.to_glib_none().0,
1270 ))
1271 }
1272 }
1273}