From 62a1b827563be3e1f4887a68ce8dc183b81c8194 Mon Sep 17 00:00:00 2001
From: Philipp Jungkamp
Date: Wed, 27 Nov 2024 15:15:34 +0100
Subject: [PATCH 1/2] glib: Change signal accumulator function signature
Use `std::ops::ControlFlow` instead of `bool` as return type to make
the control of signal emission more clear.
---
glib/src/subclass/signal.rs | 42 ++++++++++++++++++++++++++++++-------
1 file changed, 35 insertions(+), 7 deletions(-)
diff --git a/glib/src/subclass/signal.rs b/glib/src/subclass/signal.rs
index bcaa18f4ff3d..0af9e04fa090 100644
--- a/glib/src/subclass/signal.rs
+++ b/glib/src/subclass/signal.rs
@@ -1,6 +1,6 @@
// Take a look at the license at the top of the repository in the LICENSE file.
-use std::{fmt, num::NonZeroU32, ptr, sync::Mutex};
+use std::{fmt, num::NonZeroU32, ops::ControlFlow, ptr, sync::Mutex};
use crate::{
ffi, gobject_ffi, prelude::*, translate::*, utils::is_canonical_pspec_name, Closure,
@@ -18,7 +18,12 @@ pub struct SignalBuilder {
return_type: SignalType,
class_handler: Option Option + Send + Sync + 'static>>,
accumulator: Option<
- Box bool + Send + Sync + 'static>,
+ Box<
+ dyn Fn(&SignalInvocationHint, Value, &Value) -> ControlFlow
+ + Send
+ + Sync
+ + 'static,
+ >,
>,
}
@@ -352,7 +357,12 @@ enum SignalRegistration {
Unregistered {
class_handler: Option Option + Send + Sync + 'static>>,
accumulator: Option<
- Box bool + Send + Sync + 'static>,
+ Box<
+ dyn Fn(&SignalInvocationHint, Value, &Value) -> ControlFlow
+ + Send
+ + Sync
+ + 'static,
+ >,
>,
},
Registered {
@@ -480,7 +490,10 @@ impl SignalBuilder {
/// This is called if multiple signal handlers are connected to the signal for accumulating the
/// return values into a single value.
pub fn accumulator<
- F: Fn(&SignalInvocationHint, &mut Value, &Value) -> bool + Send + Sync + 'static,
+ F: Fn(&SignalInvocationHint, Value, &Value) -> ControlFlow
+ + Send
+ + Sync
+ + 'static,
>(
mut self,
func: F,
@@ -633,7 +646,7 @@ impl Signal {
let accumulator = &*(data as *const (
SignalType,
Box<
- dyn Fn(&SignalInvocationHint, &mut Value, &Value) -> bool
+ dyn Fn(&SignalInvocationHint, Value, &Value) -> ControlFlow
+ Send
+ Sync
+ 'static,
@@ -651,8 +664,23 @@ impl Signal {
handler_return.type_()
);
- let res = (accumulator.1)(&SignalInvocationHint(*ihint), return_accu, handler_return)
- .into_glib();
+ let control_flow = (accumulator.1)(
+ &SignalInvocationHint(*ihint),
+ std::mem::replace(return_accu, Value::uninitialized()),
+ handler_return,
+ );
+
+ let res = match control_flow {
+ ControlFlow::Continue(val) => {
+ *return_accu = val;
+ true.into_glib()
+ }
+
+ ControlFlow::Break(val) => {
+ *return_accu = val;
+ false.into_glib()
+ }
+ };
assert!(
return_accu.type_().is_a(return_type.into()),
From 8ffa149d538786bff6e88e1bc233eed92d60a8c0 Mon Sep 17 00:00:00 2001
From: Philipp Jungkamp
Date: Wed, 27 Nov 2024 15:32:55 +0100
Subject: [PATCH 2/2] glib: Add signal accumulator to object test
---
glib/src/subclass/object.rs | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/glib/src/subclass/object.rs b/glib/src/subclass/object.rs
index f3a81c5e4fd0..b6e548c6cd7e 100644
--- a/glib/src/subclass/object.rs
+++ b/glib/src/subclass/object.rs
@@ -422,6 +422,19 @@ mod test {
.build(),
super::Signal::builder("create-string")
.return_type::()
+ .accumulator(|_hint, acc, val| {
+ // join all strings from signal handlers by newline
+ let mut acc = acc
+ .get_owned::