1use std::{mem, num::NonZeroU64};
7
8use crate::{ffi, gobject_ffi};
9use libc::{c_char, c_ulong, c_void};
10
11use crate::{prelude::*, translate::*};
12
13#[derive(Debug, Eq, PartialEq)]
49pub struct SignalHandlerId(NonZeroU64);
50
51impl SignalHandlerId {
52 pub unsafe fn as_raw(&self) -> libc::c_ulong {
55 self.0.get() as libc::c_ulong
56 }
57}
58
59impl FromGlib<c_ulong> for SignalHandlerId {
60 #[inline]
61 unsafe fn from_glib(val: c_ulong) -> Self {
62 unsafe {
63 debug_assert_ne!(val, 0);
64 Self(NonZeroU64::new_unchecked(val as _))
65 }
66 }
67}
68
69pub unsafe fn connect_raw<F>(
70 receiver: *mut gobject_ffi::GObject,
71 signal_name: *const c_char,
72 trampoline: gobject_ffi::GCallback,
73 closure: *mut F,
74) -> SignalHandlerId {
75 unsafe {
76 unsafe extern "C" fn destroy_closure<F>(ptr: *mut c_void, _: *mut gobject_ffi::GClosure) {
77 unsafe {
78 let _ = Box::<F>::from_raw(ptr as *mut _);
80 }
81 }
82 debug_assert_eq!(mem::size_of::<*mut F>(), mem::size_of::<ffi::gpointer>());
83 debug_assert!(trampoline.is_some());
84 let handle = gobject_ffi::g_signal_connect_data(
85 receiver,
86 signal_name,
87 trampoline,
88 closure as *mut _,
89 Some(destroy_closure::<F>),
90 0,
91 );
92 debug_assert!(handle > 0);
93 from_glib(handle)
94 }
95}
96
97#[doc(alias = "g_signal_handler_block")]
98pub fn signal_handler_block<T: ObjectType>(instance: &T, handler_id: &SignalHandlerId) {
99 unsafe {
100 gobject_ffi::g_signal_handler_block(
101 instance.as_object_ref().to_glib_none().0,
102 handler_id.as_raw(),
103 );
104 }
105}
106
107#[doc(alias = "g_signal_handler_unblock")]
108pub fn signal_handler_unblock<T: ObjectType>(instance: &T, handler_id: &SignalHandlerId) {
109 unsafe {
110 gobject_ffi::g_signal_handler_unblock(
111 instance.as_object_ref().to_glib_none().0,
112 handler_id.as_raw(),
113 );
114 }
115}
116
117#[allow(clippy::needless_pass_by_value)]
118#[doc(alias = "g_signal_handler_disconnect")]
119pub fn signal_handler_disconnect<T: ObjectType>(instance: &T, handler_id: SignalHandlerId) {
120 unsafe {
121 gobject_ffi::g_signal_handler_disconnect(
122 instance.as_object_ref().to_glib_none().0,
123 handler_id.as_raw(),
124 );
125 }
126}
127
128#[doc(alias = "g_signal_stop_emission_by_name")]
129pub fn signal_stop_emission_by_name<T: ObjectType>(instance: &T, signal_name: &str) {
130 unsafe {
131 gobject_ffi::g_signal_stop_emission_by_name(
132 instance.as_object_ref().to_glib_none().0,
133 signal_name.to_glib_none().0,
134 );
135 }
136}
137
138#[doc(alias = "g_signal_has_handler_pending")]
139pub fn signal_has_handler_pending<T: ObjectType>(
140 instance: &T,
141 signal_id: crate::subclass::SignalId,
142 detail: Option<crate::Quark>,
143 may_be_blocked: bool,
144) -> bool {
145 unsafe {
146 from_glib(gobject_ffi::g_signal_has_handler_pending(
147 instance.as_object_ref().to_glib_none().0,
148 signal_id.into_glib(),
149 detail.map_or(0, |d| d.into_glib()),
150 may_be_blocked.into_glib(),
151 ))
152 }
153}
154
155#[derive(Copy, Clone, Debug, PartialEq, Eq)]
161pub enum Propagation {
162 #[doc(alias = "GDK_EVENT_STOP")]
164 Stop,
165 #[doc(alias = "GDK_EVENT_PROPAGATE")]
167 Proceed,
168}
169
170impl Propagation {
171 pub fn is_stop(&self) -> bool {
174 matches!(self, Self::Stop)
175 }
176
177 pub fn is_proceed(&self) -> bool {
180 matches!(self, Self::Proceed)
181 }
182}
183
184impl From<bool> for Propagation {
185 fn from(value: bool) -> Self {
186 if value { Self::Stop } else { Self::Proceed }
187 }
188}
189
190impl From<Propagation> for bool {
191 fn from(c: Propagation) -> Self {
192 match c {
193 Propagation::Stop => true,
194 Propagation::Proceed => false,
195 }
196 }
197}
198
199#[doc(hidden)]
200impl IntoGlib for Propagation {
201 type GlibType = ffi::gboolean;
202
203 #[inline]
204 fn into_glib(self) -> ffi::gboolean {
205 bool::from(self).into_glib()
206 }
207}
208
209#[doc(hidden)]
210impl FromGlib<ffi::gboolean> for Propagation {
211 #[inline]
212 unsafe fn from_glib(value: ffi::gboolean) -> Self {
213 unsafe { bool::from_glib(value).into() }
214 }
215}
216
217impl crate::value::ToValue for Propagation {
218 fn to_value(&self) -> crate::Value {
219 bool::from(*self).to_value()
220 }
221
222 fn value_type(&self) -> crate::Type {
223 <bool as StaticType>::static_type()
224 }
225}
226
227impl From<Propagation> for crate::Value {
228 #[inline]
229 fn from(v: Propagation) -> Self {
230 bool::from(v).into()
231 }
232}