Skip to content
This repository was archived by the owner on Jun 8, 2021. It is now read-only.

Commit 697f46c

Browse files
authored
Merge pull request #444 from sdroege/signal-class-handler
Various signal subclass improvements
2 parents 63a757f + e4206b6 commit 697f46c

File tree

8 files changed

+330
-42
lines changed

8 files changed

+330
-42
lines changed

Gir_GObject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ deprecate_by_min_version = true
1212
generate = [
1313
"GObject.BindingFlags",
1414
"GObject.ParamFlags",
15+
"GObject.SignalFlags",
1516
]
1617

1718
ignore = [

src/gobject/auto/flags.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,33 @@ impl FromGlib<ffi::GParamFlags> for ParamFlags {
9494
}
9595
}
9696

97+
bitflags! {
98+
pub struct SignalFlags: u32 {
99+
const RUN_FIRST = 1;
100+
const RUN_LAST = 2;
101+
const RUN_CLEANUP = 4;
102+
const NO_RECURSE = 8;
103+
const DETAILED = 16;
104+
const ACTION = 32;
105+
const NO_HOOKS = 64;
106+
const MUST_COLLECT = 128;
107+
const DEPRECATED = 256;
108+
}
109+
}
110+
111+
#[doc(hidden)]
112+
impl ToGlib for SignalFlags {
113+
type GlibType = ffi::GSignalFlags;
114+
115+
fn to_glib(&self) -> ffi::GSignalFlags {
116+
self.bits()
117+
}
118+
}
119+
120+
#[doc(hidden)]
121+
impl FromGlib<ffi::GSignalFlags> for SignalFlags {
122+
fn from_glib(value: ffi::GSignalFlags) -> SignalFlags {
123+
SignalFlags::from_bits_truncate(value)
124+
}
125+
}
126+

src/gobject/auto/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub use self::binding::{Binding, BindingClass};
88
mod flags;
99
pub use self::flags::BindingFlags;
1010
pub use self::flags::ParamFlags;
11+
pub use self::flags::SignalFlags;
1112

1213
#[doc(hidden)]
1314
pub mod traits {

src/source.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use std::cell::RefCell;
66
use std::mem::transmute;
7-
#[cfg(any(unix, feature = "dox"))]
7+
#[cfg(unix)]
88
use std::os::unix::io::RawFd;
99
#[cfg(all(not(unix), feature = "dox"))]
1010
use libc::c_int as RawFd;

src/subclass/interface.rs

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::ptr;
1111

1212
use super::{InitializingType, Property};
1313
use translate::*;
14-
use {IsA, Object, ObjectExt, StaticType, Type, Value};
14+
use {IsA, Object, ObjectExt, SignalFlags, StaticType, Type, Value};
1515

1616
impl<T: ObjectInterface> InitializingType<T> {
1717
/// Adds an interface prerequisite for `I` to the type.
@@ -139,17 +139,46 @@ pub trait ObjectInterfaceExt: ObjectInterface {
139139
///
140140
/// This can be emitted later by `glib::Object::emit` and external code
141141
/// can connect to the signal to get notified about emissions.
142-
fn add_signal(&mut self, name: &str, arg_types: &[Type], ret_type: Type) {
142+
fn add_signal(&mut self, name: &str, flags: SignalFlags, arg_types: &[Type], ret_type: Type) {
143143
unsafe {
144144
super::types::add_signal(
145145
*(self as *mut _ as *mut ffi::GType),
146146
name,
147+
flags,
147148
arg_types,
148149
ret_type,
149150
);
150151
}
151152
}
152153

154+
/// Add a new signal with class handler to the interface.
155+
///
156+
/// This can be emitted later by `glib::Object::emit` and external code
157+
/// can connect to the signal to get notified about emissions.
158+
///
159+
/// The class handler will be called during the signal emission at the corresponding stage.
160+
fn add_signal_with_class_handler<F>(
161+
&mut self,
162+
name: &str,
163+
flags: SignalFlags,
164+
arg_types: &[Type],
165+
ret_type: Type,
166+
class_handler: F,
167+
) where
168+
F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
169+
{
170+
unsafe {
171+
super::types::add_signal_with_class_handler(
172+
*(self as *mut _ as *mut ffi::GType),
173+
name,
174+
flags,
175+
arg_types,
176+
ret_type,
177+
class_handler,
178+
);
179+
}
180+
}
181+
153182
/// Add a new signal with accumulator to the interface.
154183
///
155184
/// This can be emitted later by `glib::Object::emit` and external code
@@ -162,40 +191,57 @@ pub trait ObjectInterfaceExt: ObjectInterface {
162191
fn add_signal_with_accumulator<F>(
163192
&mut self,
164193
name: &str,
194+
flags: SignalFlags,
165195
arg_types: &[Type],
166196
ret_type: Type,
167197
accumulator: F,
168198
) where
169-
F: Fn(&mut Value, &Value) -> bool + Send + Sync + 'static,
199+
F: Fn(&super::SignalInvocationHint, &mut Value, &Value) -> bool + Send + Sync + 'static,
170200
{
171201
unsafe {
172202
super::types::add_signal_with_accumulator(
173203
*(self as *mut _ as *mut ffi::GType),
174204
name,
205+
flags,
175206
arg_types,
176207
ret_type,
177208
accumulator,
178209
);
179210
}
180211
}
181212

182-
/// Add a new action signal with accumulator to the interface.
213+
/// Add a new signal with accumulator and class handler to the interface.
214+
///
215+
/// This can be emitted later by `glib::Object::emit` and external code
216+
/// can connect to the signal to get notified about emissions.
183217
///
184-
/// Different to normal signals, action signals are supposed to be emitted
185-
/// by external code and will cause the provided handler to be called.
218+
/// The accumulator function is used for accumulating the return values of
219+
/// multiple signal handlers. The new value is passed as second argument and
220+
/// should be combined with the old value in the first argument. If no further
221+
/// signal handlers should be called, `false` should be returned.
186222
///
187-
/// It can be thought of as a dynamic function call.
188-
fn add_action_signal<F>(&mut self, name: &str, arg_types: &[Type], ret_type: Type, handler: F)
189-
where
190-
F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
223+
/// The class handler will be called during the signal emission at the corresponding stage.
224+
fn add_signal_with_class_handler_and_accumulator<F, G>(
225+
&mut self,
226+
name: &str,
227+
flags: SignalFlags,
228+
arg_types: &[Type],
229+
ret_type: Type,
230+
class_handler: F,
231+
accumulator: G,
232+
) where
233+
F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
234+
G: Fn(&super::SignalInvocationHint, &mut Value, &Value) -> bool + Send + Sync + 'static,
191235
{
192236
unsafe {
193-
super::types::add_action_signal(
237+
super::types::add_signal_with_class_handler_and_accumulator(
194238
*(self as *mut _ as *mut ffi::GType),
195239
name,
240+
flags,
196241
arg_types,
197242
ret_type,
198-
handler,
243+
class_handler,
244+
accumulator,
199245
);
200246
}
201247
}

src/subclass/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,4 +195,6 @@ pub mod prelude {
195195
pub use self::boxed::register_boxed_type;
196196
pub use self::interface::register_interface;
197197
pub use self::object::Property;
198-
pub use self::types::{register_type, InitializingType, TypeData};
198+
pub use self::types::{
199+
register_type, InitializingType, SignalClassHandlerToken, SignalInvocationHint, TypeData,
200+
};

src/subclass/object.rs

Lines changed: 98 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::mem;
1212
use std::ptr;
1313

1414
use translate::*;
15-
use {Object, ObjectClass, Type, Value};
15+
use {Object, ObjectClass, ObjectType, SignalFlags, Type, Value};
1616

1717
use super::prelude::*;
1818
use super::types;
@@ -176,17 +176,46 @@ pub unsafe trait ObjectClassSubclassExt: Sized + 'static {
176176
///
177177
/// This can be emitted later by `glib::Object::emit` and external code
178178
/// can connect to the signal to get notified about emissions.
179-
fn add_signal(&mut self, name: &str, arg_types: &[Type], ret_type: Type) {
179+
fn add_signal(&mut self, name: &str, flags: SignalFlags, arg_types: &[Type], ret_type: Type) {
180180
unsafe {
181181
super::types::add_signal(
182182
*(self as *mut _ as *mut ffi::GType),
183183
name,
184+
flags,
184185
arg_types,
185186
ret_type,
186187
);
187188
}
188189
}
189190

191+
/// Add a new signal with class handler to the subclass.
192+
///
193+
/// This can be emitted later by `glib::Object::emit` and external code
194+
/// can connect to the signal to get notified about emissions.
195+
///
196+
/// The class handler will be called during the signal emission at the corresponding stage.
197+
fn add_signal_with_class_handler<F>(
198+
&mut self,
199+
name: &str,
200+
flags: SignalFlags,
201+
arg_types: &[Type],
202+
ret_type: Type,
203+
class_handler: F,
204+
) where
205+
F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
206+
{
207+
unsafe {
208+
super::types::add_signal_with_class_handler(
209+
*(self as *mut _ as *mut ffi::GType),
210+
name,
211+
flags,
212+
arg_types,
213+
ret_type,
214+
class_handler,
215+
);
216+
}
217+
}
218+
190219
/// Add a new signal with accumulator to the subclass.
191220
///
192221
/// This can be emitted later by `glib::Object::emit` and external code
@@ -199,40 +228,70 @@ pub unsafe trait ObjectClassSubclassExt: Sized + 'static {
199228
fn add_signal_with_accumulator<F>(
200229
&mut self,
201230
name: &str,
231+
flags: SignalFlags,
202232
arg_types: &[Type],
203233
ret_type: Type,
204234
accumulator: F,
205235
) where
206-
F: Fn(&mut Value, &Value) -> bool + Send + Sync + 'static,
236+
F: Fn(&super::SignalInvocationHint, &mut Value, &Value) -> bool + Send + Sync + 'static,
207237
{
208238
unsafe {
209239
super::types::add_signal_with_accumulator(
210240
*(self as *mut _ as *mut ffi::GType),
211241
name,
242+
flags,
212243
arg_types,
213244
ret_type,
214245
accumulator,
215246
);
216247
}
217248
}
218249

219-
/// Add a new action signal with accumulator to the subclass.
250+
/// Add a new signal with accumulator and class handler to the subclass.
220251
///
221-
/// Different to normal signals, action signals are supposed to be emitted
222-
/// by external code and will cause the provided handler to be called.
252+
/// This can be emitted later by `glib::Object::emit` and external code
253+
/// can connect to the signal to get notified about emissions.
223254
///
224-
/// It can be thought of as a dynamic function call.
225-
fn add_action_signal<F>(&mut self, name: &str, arg_types: &[Type], ret_type: Type, handler: F)
226-
where
227-
F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
255+
/// The accumulator function is used for accumulating the return values of
256+
/// multiple signal handlers. The new value is passed as second argument and
257+
/// should be combined with the old value in the first argument. If no further
258+
/// signal handlers should be called, `false` should be returned.
259+
///
260+
/// The class handler will be called during the signal emission at the corresponding stage.
261+
fn add_signal_with_class_handler_and_accumulator<F, G>(
262+
&mut self,
263+
name: &str,
264+
flags: SignalFlags,
265+
arg_types: &[Type],
266+
ret_type: Type,
267+
class_handler: F,
268+
accumulator: G,
269+
) where
270+
F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
271+
G: Fn(&super::SignalInvocationHint, &mut Value, &Value) -> bool + Send + Sync + 'static,
228272
{
229273
unsafe {
230-
super::types::add_action_signal(
274+
super::types::add_signal_with_class_handler_and_accumulator(
231275
*(self as *mut _ as *mut ffi::GType),
232276
name,
277+
flags,
233278
arg_types,
234279
ret_type,
235-
handler,
280+
class_handler,
281+
accumulator,
282+
);
283+
}
284+
}
285+
286+
fn override_signal_class_handler<F>(&mut self, name: &str, class_handler: F)
287+
where
288+
F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
289+
{
290+
unsafe {
291+
super::types::signal_override_class_handler(
292+
name,
293+
*(self as *mut _ as *mut ffi::GType),
294+
class_handler,
236295
);
237296
}
238297
}
@@ -251,6 +310,24 @@ unsafe impl<T: ObjectSubclass> IsSubclassable<T> for ObjectClass {
251310
}
252311
}
253312

313+
pub trait ObjectImplExt: ObjectImpl + ObjectSubclass {
314+
fn signal_chain_from_overridden(
315+
&self,
316+
token: &super::SignalClassHandlerToken,
317+
values: &[Value],
318+
) -> Option<Value> {
319+
unsafe {
320+
super::types::signal_chain_from_overridden(
321+
self.get_instance().as_ptr() as *mut _,
322+
token,
323+
values,
324+
)
325+
}
326+
}
327+
}
328+
329+
impl<T: ObjectImpl + ObjectSubclass> ObjectImplExt for T {}
330+
254331
#[cfg(test)]
255332
mod test {
256333
use super::super::super::object::ObjectExt;
@@ -302,13 +379,19 @@ mod test {
302379
fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
303380
klass.install_properties(&PROPERTIES);
304381

305-
klass.add_signal("name-changed", &[String::static_type()], ::Type::Unit);
382+
klass.add_signal(
383+
"name-changed",
384+
SignalFlags::RUN_LAST,
385+
&[String::static_type()],
386+
::Type::Unit,
387+
);
306388

307-
klass.add_action_signal(
389+
klass.add_signal_with_class_handler(
308390
"change-name",
391+
SignalFlags::RUN_LAST | SignalFlags::ACTION,
309392
&[String::static_type()],
310393
String::static_type(),
311-
|args| {
394+
|_, args| {
312395
let obj = args[0].get::<Object>().unwrap();
313396
let new_name = args[1].get::<String>().unwrap();
314397
let imp = Self::from_instance(&obj);

0 commit comments

Comments
 (0)