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