@@ -6,7 +6,7 @@ use crate::{
66 ffi, ActionGroup , DBusConnection , DBusInterfaceInfo , DBusMessage , DBusMethodInvocation ,
77 DBusSignalFlags , MenuModel ,
88} ;
9- use glib:: { prelude:: * , translate:: * } ;
9+ use glib:: { prelude:: * , translate:: * , WeakRef } ;
1010
1111pub trait DBusMethodCall : Sized {
1212 fn parse_call (
@@ -117,9 +117,76 @@ pub struct ActionGroupExportId(NonZeroU32);
117117pub struct MenuModelExportId ( NonZeroU32 ) ;
118118#[ derive( Debug , Eq , PartialEq ) ]
119119pub struct FilterId ( NonZeroU32 ) ;
120+
120121#[ derive( Debug , Eq , PartialEq ) ]
121122pub struct SignalSubscriptionId ( NonZeroU32 ) ;
122123
124+ // rustdoc-stripper-ignore-next
125+ /// A strong subscription to a D-Bus signal.
126+ ///
127+ /// Keep a reference to a D-Bus connection to maintain a subscription on a
128+ /// D-Bus signal even if the connection has no other strong reference.
129+ ///
130+ /// When dropped, unsubscribes from signal on the connection, and then drop the
131+ /// reference on the connection. If no other strong reference on the connection
132+ /// exists the connection is closed and destroyed.
133+ #[ derive( Debug ) ]
134+ pub struct SignalSubscription ( DBusConnection , Option < SignalSubscriptionId > ) ;
135+
136+ impl SignalSubscription {
137+ // rustdoc-stripper-ignore-next
138+ /// Downgrade this signal subscription to a weak one.
139+ #[ must_use]
140+ pub fn downgrade ( mut self ) -> WeakSignalSubscription {
141+ WeakSignalSubscription ( self . 0 . downgrade ( ) , self . 1 . take ( ) )
142+ }
143+ }
144+
145+ impl Drop for SignalSubscription {
146+ fn drop ( & mut self ) {
147+ if let Some ( id) = self . 1 . take ( ) {
148+ #[ allow( deprecated) ]
149+ self . 0 . signal_unsubscribe ( id) ;
150+ }
151+ }
152+ }
153+
154+ // rustdoc-stripper-ignore-next
155+ /// A weak subscription to a D-Bus signal.
156+ ///
157+ /// Like [`SignalSubscription`] but hold only a weak reference to the D-Bus
158+ /// connection the siganl is subscribed on, i.e. maintain the subscription on
159+ /// the D-Bus signal only as long as some strong reference exists on the
160+ /// corresponding D-Bus connection.
161+ ///
162+ /// When dropped, unsubscribes from signal on the connection if it still exists,
163+ /// and then drop the reference on the connection. If no other strong reference
164+ /// on the connection exists the connection is closed and destroyed.
165+ #[ derive( Debug ) ]
166+ pub struct WeakSignalSubscription ( WeakRef < DBusConnection > , Option < SignalSubscriptionId > ) ;
167+
168+ impl WeakSignalSubscription {
169+ // rustdoc-stripper-ignore-next
170+ /// Upgrade this signal subscription to a strong one.
171+ #[ must_use]
172+ pub fn upgrade ( mut self ) -> Option < SignalSubscription > {
173+ self . 0
174+ . upgrade ( )
175+ . map ( |c| SignalSubscription ( c, self . 1 . take ( ) ) )
176+ }
177+ }
178+
179+ impl Drop for WeakSignalSubscription {
180+ fn drop ( & mut self ) {
181+ if let Some ( id) = self . 1 . take ( ) {
182+ if let Some ( connection) = self . 0 . upgrade ( ) {
183+ #[ allow( deprecated) ]
184+ connection. signal_unsubscribe ( id) ;
185+ }
186+ }
187+ }
188+ }
189+
123190// rustdoc-stripper-ignore-next
124191/// Build a registered DBus object, by handling different parts of DBus.
125192#[ must_use = "The builder must be built to be used" ]
@@ -437,8 +504,45 @@ impl DBusConnection {
437504 }
438505 }
439506
507+ // rustdoc-stripper-ignore-next
508+ /// Subscribe to a D-Bus signal.
509+ ///
510+ /// See [`Self::signal_subscribe`] for arguments.
511+ ///
512+ /// Return a signal subscription which keeps a reference to this D-Bus
513+ /// connection and unsubscribes from the signal when dropped.
514+ ///
515+ /// To avoid reference cycles you may wish to downgrade the returned
516+ /// subscription to a weak one with [`SignalSubscription::downgrade`].
517+ #[ must_use]
518+ pub fn subscribe_to_signal <
519+ P : Fn ( & DBusConnection , & str , & str , & str , & str , & glib:: Variant ) + ' static ,
520+ > (
521+ & self ,
522+ sender : Option < & str > ,
523+ interface_name : Option < & str > ,
524+ member : Option < & str > ,
525+ object_path : Option < & str > ,
526+ arg0 : Option < & str > ,
527+ flags : DBusSignalFlags ,
528+ callback : P ,
529+ ) -> SignalSubscription {
530+ #[ allow( deprecated) ]
531+ let id = self . signal_subscribe (
532+ sender,
533+ interface_name,
534+ member,
535+ object_path,
536+ arg0,
537+ flags,
538+ callback,
539+ ) ;
540+ SignalSubscription ( self . clone ( ) , Some ( id) )
541+ }
542+
440543 #[ doc( alias = "g_dbus_connection_signal_subscribe" ) ]
441544 #[ allow( clippy:: too_many_arguments) ]
545+ #[ deprecated( note = "Prefer subscribe_to_signal" ) ]
442546 pub fn signal_subscribe <
443547 P : Fn ( & DBusConnection , & str , & str , & str , & str , & glib:: Variant ) + ' static ,
444548 > (
@@ -507,6 +611,7 @@ impl DBusConnection {
507611 }
508612
509613 #[ doc( alias = "g_dbus_connection_signal_unsubscribe" ) ]
614+ #[ deprecated( note = "Prefer subscribe_to_signal" ) ]
510615 pub fn signal_unsubscribe ( & self , subscription_id : SignalSubscriptionId ) {
511616 unsafe {
512617 ffi:: g_dbus_connection_signal_unsubscribe (
0 commit comments