1 /* signalproxy_connectionnode.cc
2  *
3  * Copyright (C) 2002 The gtkmm Development Team
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include <glibmm/signalproxy_connectionnode.h>
20 #include <glibmm/object.h>
21 #include <utility> // std::move()
22 
23 namespace Glib
24 {
25 
SignalProxyConnectionNode(const sigc::slot_base & slot,GObject * gobject)26 SignalProxyConnectionNode::SignalProxyConnectionNode(const sigc::slot_base& slot, GObject* gobject)
27 : connection_id_(0), slot_(slot), object_(gobject)
28 {
29   // The cleanup callback will be called when the connection is disconnected.
30   slot_.set_parent(this, &SignalProxyConnectionNode::notify /* cleanup callback */);
31 }
32 
SignalProxyConnectionNode(sigc::slot_base && slot,GObject * gobject)33 SignalProxyConnectionNode::SignalProxyConnectionNode(sigc::slot_base&& slot, GObject* gobject)
34 : connection_id_(0), slot_(std::move(slot)), object_(gobject)
35 {
36   // The cleanup callback will be called when the connection is disconnected.
37   slot_.set_parent(this, &SignalProxyConnectionNode::notify /* cleanup callback */);
38 }
39 
40 // notify is a message coming up from the slot to be passed back to Gtk+
41 // disconnect is a message coming up from the Gtk+ to be passed down to SigC++
42 // static
43 void*
notify(void * data)44 SignalProxyConnectionNode::notify(void* data)
45 {
46   // notification from libsigc++.
47   SignalProxyConnectionNode* conn = static_cast<SignalProxyConnectionNode*>(data);
48 
49   // If there is no object, this call was triggered from destroy_notify_handler(),
50   // because we set conn->object to 0 there:
51   if (conn && conn->object_)
52   {
53     GObject* o = conn->object_;
54     conn->object_ = nullptr;
55 
56     // We check first, because during destruction, GTK+ sometimes seems to
57     // disconnect them for us, before we expect it to. See bug #87912
58     if (g_signal_handler_is_connected(o, conn->connection_id_))
59     {
60       // Disconnecting triggers execution of destroy_notify_handler(), eiter immediately or later:
61       //   When the signal handler is currently running. (for instance, if the callback disconnects
62       //   its own connection)
63       //   In that case, destroy_notify_handler() will be called after this whole function has
64       //   returned.
65       // Anyway. destroy_notify_handler() will always be called, so we leave that to do the
66       // deletion.
67 
68       // Forget the connection:
69       gulong connection_id = conn->connection_id_;
70       conn->connection_id_ = 0;
71 
72       g_signal_handler_disconnect(o, connection_id);
73     }
74   }
75 
76   return nullptr; // apparently unused in libsigc++
77 }
78 
79 // static
80 void
destroy_notify_handler(gpointer data,GClosure *)81 SignalProxyConnectionNode::destroy_notify_handler(gpointer data, GClosure*)
82 {
83   // glib calls this when it has finished with a glib signal connection,
84   // either when the emitting object dies, or when the connection has been disconnected.
85 
86   // notification from gtk+.
87   SignalProxyConnectionNode* conn = static_cast<SignalProxyConnectionNode*>(data);
88 
89   if (conn)
90   {
91     // the object has already lost track of this object.
92     conn->object_ = nullptr;
93 
94     // If there are connection objects referring to slot_ they are notified during
95     // destruction of slot_.
96     delete conn;
97   }
98 }
99 
100 } /* namespace Glib */
101