This post explains and shows a code snippet about how to disconnect a signal handler from inside itself, in rust.
All of the rust types used here that are not prefixed by modules names, are in the std
library.
In C, what you would do is pass a pointer to malloc-ed heap memory to the user_data
argument, that will contain (at some point) the signal handler id, in rust is pretty much the same idea, but it’s a little bit tricky.
You need to first declare a variable with type Rc<RefCell<Option<glib::SignalHandlerId>>>
, It’s a Rc
“smart pointer”, that points to heap memory allocated RefCell<...>
, this RefCell
is needed to help us to bypass the static borrow rules, since we can only pass shared references inside of the signal handler, and finally the Option<glib::SignalHandlerId>
is a nullable type, since glib::SignalHandlerId
doesn’t have a default/zero value, that’s why is needed.
We connect to the signal and pass a cloned Rc
, then inside of the signal handler we call disconnect from it when we need to do it.
In code, that would look like this:
let widget: gtk::Widget = ...;
let signal_id: Rc<RefCell<Option<glib::SignalHandlerId>>> = Default::default();
// The borrow_mut method comes from RefCell type
*signal_id.borrow_mut() = Some(
widget.connect_closure(
"foo",
false, // after flag
glib::closure!(
#[strong]
signal_id,
|widget: gtk::Widget| {
// Some work/condition..., then we disconnect the handler
if let Some(id) = signal_id.take() {
widget.disconnect(id);
}
}
)
)
);
I hope you find it useful.