1 /* signalproxy.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 <glib-object.h>
20 #include <glibmm/exceptionhandler.h>
21 #include <glibmm/object.h>
22 #include <glibmm/signalproxy.h>
23
24 namespace Glib
25 {
26
27 // SignalProxyBase implementation:
28
SignalProxyBase(Glib::ObjectBase * obj)29 SignalProxyBase::SignalProxyBase(Glib::ObjectBase* obj) : obj_(obj)
30 {
31 }
32
33 // SignalProxyNormal implementation:
34
SignalProxyNormal(Glib::ObjectBase * obj,const SignalProxyInfo * info)35 SignalProxyNormal::SignalProxyNormal(Glib::ObjectBase* obj, const SignalProxyInfo* info)
36 : SignalProxyBase(obj), info_(info)
37 {
38 }
39
~SignalProxyNormal()40 SignalProxyNormal::~SignalProxyNormal() noexcept
41 {
42 }
43
44 sigc::slot_base&
connect_(const sigc::slot_base & slot,bool after)45 SignalProxyNormal::connect_(const sigc::slot_base& slot, bool after)
46 {
47 return connect_impl_(info_->callback, slot, after);
48 }
49
50 sigc::slot_base&
connect_notify_(const sigc::slot_base & slot,bool after)51 SignalProxyNormal::connect_notify_(const sigc::slot_base& slot, bool after)
52 {
53 return connect_impl_(info_->notify_callback, slot, after);
54 }
55
56 sigc::slot_base&
connect_impl_(GCallback callback,const sigc::slot_base & slot,bool after)57 SignalProxyNormal::connect_impl_(GCallback callback, const sigc::slot_base& slot, bool after)
58 {
59 // create a proxy to hold our connection info
60 auto pConnectionNode = new SignalProxyConnectionNode(slot, obj_->gobj());
61
62 // connect it to glib
63 // pConnectionNode will be passed in the data argument to the callback.
64 pConnectionNode->connection_id_ = g_signal_connect_data(obj_->gobj(), info_->signal_name,
65 callback, pConnectionNode, &SignalProxyConnectionNode::destroy_notify_handler,
66 static_cast<GConnectFlags>((after) ? G_CONNECT_AFTER : 0));
67
68 return pConnectionNode->slot_;
69 }
70
71 sigc::slot_base&
connect_impl_(bool notify,sigc::slot_base && slot,bool after)72 SignalProxyNormal::connect_impl_(bool notify, sigc::slot_base&& slot, bool after)
73 {
74 // create a proxy to hold our connection info
75 auto pConnectionNode = new SignalProxyConnectionNode(std::move(slot), obj_->gobj());
76
77 // connect it to glib
78 // pConnectionNode will be passed in the data argument to the callback.
79 pConnectionNode->connection_id_ = g_signal_connect_data(obj_->gobj(), info_->signal_name,
80 notify ? info_->notify_callback : info_->callback, pConnectionNode,
81 &SignalProxyConnectionNode::destroy_notify_handler,
82 static_cast<GConnectFlags>(after ? G_CONNECT_AFTER : 0));
83
84 return pConnectionNode->slot_;
85 }
86
87 void
emission_stop()88 SignalProxyNormal::emission_stop()
89 {
90 g_signal_stop_emission_by_name(obj_->gobj(), info_->signal_name);
91 }
92
93 // static
94 void
slot0_void_callback(GObject * self,void * data)95 SignalProxyNormal::slot0_void_callback(GObject* self, void* data)
96 {
97 // Do not try to call a signal on a disassociated wrapper.
98 if (Glib::ObjectBase::_get_current_wrapper(self))
99 {
100 try
101 {
102 if (sigc::slot_base* const slot = data_to_slot(data))
103 (*static_cast<sigc::slot<void>*>(slot))();
104 }
105 catch (...)
106 {
107 Glib::exception_handlers_invoke();
108 }
109 }
110 }
111
112 // SignalProxyDetailed implementation:
113
SignalProxyDetailed(Glib::ObjectBase * obj,const SignalProxyInfo * info,const Glib::ustring & detail_name)114 SignalProxyDetailed::SignalProxyDetailed(
115 Glib::ObjectBase* obj, const SignalProxyInfo* info, const Glib::ustring& detail_name)
116 : SignalProxyBase(obj),
117 info_(info),
118 detailed_name_(Glib::ustring(info->signal_name) +
119 (detail_name.empty() ? Glib::ustring() : ("::" + detail_name)))
120 {
121 }
122
~SignalProxyDetailed()123 SignalProxyDetailed::~SignalProxyDetailed() noexcept
124 {
125 }
126
127 sigc::slot_base&
connect_impl_(bool notify,const sigc::slot_base & slot,bool after)128 SignalProxyDetailed::connect_impl_(bool notify, const sigc::slot_base& slot, bool after)
129 {
130 // create a proxy to hold our connection info
131 auto pConnectionNode = new SignalProxyConnectionNode(slot, obj_->gobj());
132
133 // connect it to glib
134 // pConnectionNode will be passed in the data argument to the callback.
135 pConnectionNode->connection_id_ = g_signal_connect_data(obj_->gobj(), detailed_name_.c_str(),
136 notify ? info_->notify_callback : info_->callback, pConnectionNode,
137 &SignalProxyConnectionNode::destroy_notify_handler,
138 static_cast<GConnectFlags>(after ? G_CONNECT_AFTER : 0));
139
140 return pConnectionNode->slot_;
141 }
142
143 sigc::slot_base&
connect_impl_(bool notify,sigc::slot_base && slot,bool after)144 SignalProxyDetailed::connect_impl_(bool notify, sigc::slot_base&& slot, bool after)
145 {
146 // create a proxy to hold our connection info
147 auto pConnectionNode = new SignalProxyConnectionNode(std::move(slot), obj_->gobj());
148
149 // connect it to glib
150 // pConnectionNode will be passed in the data argument to the callback.
151 pConnectionNode->connection_id_ = g_signal_connect_data(obj_->gobj(), detailed_name_.c_str(),
152 notify ? info_->notify_callback : info_->callback, pConnectionNode,
153 &SignalProxyConnectionNode::destroy_notify_handler,
154 static_cast<GConnectFlags>(after ? G_CONNECT_AFTER : 0));
155
156 return pConnectionNode->slot_;
157 }
158
159 void
emission_stop()160 SignalProxyDetailed::emission_stop()
161 {
162 g_signal_stop_emission_by_name(obj_->gobj(), detailed_name_.c_str());
163 }
164
165 } // namespace Glib
166