use crate::object::ObjectType;
use crate::translate::{from_glib, FromGlib, IntoGlib, ToGlibPtr};
use ffi::{gboolean, gpointer};
use gobject_ffi::{self, GCallback};
use libc::{c_char, c_ulong, c_void};
use std::mem;
use std::num::NonZeroU64;
#[derive(Debug, Eq, PartialEq)]
pub struct SignalHandlerId(NonZeroU64);
impl SignalHandlerId {
pub unsafe fn as_raw(&self) -> libc::c_ulong {
self.0.get() as libc::c_ulong
}
}
impl FromGlib<c_ulong> for SignalHandlerId {
#[inline]
unsafe fn from_glib(val: c_ulong) -> Self {
assert_ne!(val, 0);
Self(NonZeroU64::new_unchecked(val as _))
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct Inhibit(pub bool);
#[doc(hidden)]
impl IntoGlib for Inhibit {
type GlibType = gboolean;
#[inline]
fn into_glib(self) -> gboolean {
self.0.into_glib()
}
}
impl crate::ToValue for Inhibit {
fn to_value(&self) -> crate::Value {
self.0.to_value()
}
fn value_type(&self) -> crate::Type {
<bool as crate::StaticType>::static_type()
}
}
pub unsafe fn connect_raw<F>(
receiver: *mut gobject_ffi::GObject,
signal_name: *const c_char,
trampoline: GCallback,
closure: *mut F,
) -> SignalHandlerId {
unsafe extern "C" fn destroy_closure<F>(ptr: *mut c_void, _: *mut gobject_ffi::GClosure) {
let _ = Box::<F>::from_raw(ptr as *mut _);
}
assert_eq!(mem::size_of::<*mut F>(), mem::size_of::<gpointer>());
assert!(trampoline.is_some());
let handle = gobject_ffi::g_signal_connect_data(
receiver,
signal_name,
trampoline,
closure as *mut _,
Some(destroy_closure::<F>),
0,
);
assert!(handle > 0);
from_glib(handle)
}
#[doc(alias = "g_signal_handler_block")]
pub fn signal_handler_block<T: ObjectType>(instance: &T, handler_id: &SignalHandlerId) {
unsafe {
gobject_ffi::g_signal_handler_block(
instance.as_object_ref().to_glib_none().0,
handler_id.as_raw(),
);
}
}
#[doc(alias = "g_signal_handler_unblock")]
pub fn signal_handler_unblock<T: ObjectType>(instance: &T, handler_id: &SignalHandlerId) {
unsafe {
gobject_ffi::g_signal_handler_unblock(
instance.as_object_ref().to_glib_none().0,
handler_id.as_raw(),
);
}
}
#[allow(clippy::needless_pass_by_value)]
#[doc(alias = "g_signal_handler_disconnect")]
pub fn signal_handler_disconnect<T: ObjectType>(instance: &T, handler_id: SignalHandlerId) {
unsafe {
gobject_ffi::g_signal_handler_disconnect(
instance.as_object_ref().to_glib_none().0,
handler_id.as_raw(),
);
}
}
#[doc(alias = "g_signal_stop_emission_by_name")]
pub fn signal_stop_emission_by_name<T: ObjectType>(instance: &T, signal_name: &str) {
unsafe {
gobject_ffi::g_signal_stop_emission_by_name(
instance.as_object_ref().to_glib_none().0,
signal_name.to_glib_none().0,
);
}
}
#[doc(alias = "g_signal_has_handler_pending")]
pub fn signal_has_handler_pending<T: ObjectType>(
instance: &T,
signal_id: crate::subclass::SignalId,
detail: Option<crate::Quark>,
may_be_blocked: bool,
) -> bool {
unsafe {
from_glib(gobject_ffi::g_signal_has_handler_pending(
instance.as_object_ref().to_glib_none().0,
signal_id.into_glib(),
detail.map_or(0, |d| d.into_glib()),
may_be_blocked.into_glib(),
))
}
}