1
/* * * Copyright (C) 2009 Ali <aliov@xfce.org>
3
* Licensed under the GNU General Public License Version 2
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program 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
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30
#include <dbus/dbus.h>
31
#include <dbus/dbus-glib-lowlevel.h>
32
#include <dbus/dbus-glib.h>
34
#include <libxfce4util/libxfce4util.h>
36
#include "xfpm-dbus.h"
38
#include "xfpm-dbus-monitor.h"
39
#include "xfpm-dbus-marshal.h"
41
static void xfpm_dbus_monitor_finalize (GObject *object);
43
#define XFPM_DBUS_MONITOR_GET_PRIVATE(o) \
44
(G_TYPE_INSTANCE_GET_PRIVATE ((o), XFPM_TYPE_DBUS_MONITOR, XfpmDBusMonitorPrivate))
46
struct XfpmDBusMonitorPrivate
48
DBusGConnection *system_bus;
49
DBusGConnection *session_bus;
51
DBusGProxy *system_proxy;
52
DBusGProxy *session_proxy;
54
GPtrArray *names_array;
55
GPtrArray *services_array;
68
SERVICE_CONNECTION_CHANGED,
69
SYSTEM_BUS_CONNECTION_CHANGED,
73
static guint signals [LAST_SIGNAL] = { 0 };
75
G_DEFINE_TYPE (XfpmDBusMonitor, xfpm_dbus_monitor, G_TYPE_OBJECT)
78
xfpm_dbus_monitor_free_watch_data (XfpmWatchData *data)
84
static XfpmWatchData *
85
xfpm_dbus_monitor_get_watch_data (GPtrArray *array, const gchar *name, DBusBusType bus_type)
90
for ( i = 0; i < array->len; i++)
92
data = g_ptr_array_index (array, i);
93
if ( !g_strcmp0 (data->name, name) && data->bus_type == bus_type )
100
xfpm_dbus_monitor_unique_connection_name_lost (XfpmDBusMonitor *monitor, DBusBusType bus_type, const gchar *name)
102
XfpmWatchData *watch;
105
for ( i = 0; i < monitor->priv->names_array->len; i++ )
107
watch = g_ptr_array_index (monitor->priv->names_array, i);
109
if ( !g_strcmp0 (watch->name, name) && bus_type == watch->bus_type )
111
g_signal_emit (G_OBJECT(monitor), signals [UNIQUE_NAME_LOST], 0,
112
watch->name, bus_type == DBUS_BUS_SESSION ? TRUE : FALSE);
113
g_ptr_array_remove (monitor->priv->names_array, watch);
114
xfpm_dbus_monitor_free_watch_data (watch);
120
xfpm_dbus_monitor_service_connection_changed (XfpmDBusMonitor *monitor, DBusBusType bus_type,
121
const gchar *name, gboolean connected)
123
XfpmWatchData *watch;
126
for ( i = 0; i < monitor->priv->services_array->len; i++)
128
watch = g_ptr_array_index (monitor->priv->services_array, i);
130
if ( !g_strcmp0 (watch->name, name) && watch->bus_type == bus_type)
132
g_signal_emit (G_OBJECT (monitor), signals [SERVICE_CONNECTION_CHANGED], 0,
133
name, connected, bus_type == DBUS_BUS_SESSION ? TRUE : FALSE);
139
xfpm_dbus_monitor_name_owner_changed (XfpmDBusMonitor *monitor, const gchar *name,
140
const gchar *prev, const gchar *new, DBusBusType bus_type)
142
if ( strlen (prev) != 0 )
144
xfpm_dbus_monitor_unique_connection_name_lost (monitor, bus_type, prev);
146
/* Connection has name */
147
if ( strlen (name) != 0 )
148
xfpm_dbus_monitor_service_connection_changed (monitor, bus_type, name, FALSE);
150
else if ( strlen (name) != 0 && strlen (new) != 0)
152
xfpm_dbus_monitor_service_connection_changed (monitor, bus_type, name, TRUE);
157
xfpm_dbus_monitor_session_name_owner_changed_cb (DBusGProxy *proxy, const gchar *name,
158
const gchar *prev, const gchar *new,
159
XfpmDBusMonitor *monitor)
161
xfpm_dbus_monitor_name_owner_changed (monitor, name, prev, new, DBUS_BUS_SESSION);
165
xfpm_dbus_monitor_system_name_owner_changed_cb (DBusGProxy *proxy, const gchar *name,
166
const gchar *prev, const gchar *new,
167
XfpmDBusMonitor *monitor)
169
xfpm_dbus_monitor_name_owner_changed (monitor, name, prev, new, DBUS_BUS_SYSTEM);
173
xfpm_dbus_monitor_query_system_bus_idle (gpointer data)
175
XfpmDBusMonitor *monitor;
176
DBusGConnection *bus;
177
GError *error = NULL;
179
bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
183
TRACE ("System bus is not connected %s:", error->message);
184
g_error_free (error);
188
monitor = XFPM_DBUS_MONITOR (data);
189
g_signal_emit (G_OBJECT (monitor), signals [SYSTEM_BUS_CONNECTION_CHANGED], 0, TRUE);
195
xfpm_dbus_monitor_setup_system_watch (XfpmDBusMonitor *monitor)
197
g_timeout_add_seconds (2, (GSourceFunc) xfpm_dbus_monitor_query_system_bus_idle, monitor);
200
static DBusHandlerResult
201
xfpm_dbus_monitor_system_bus_filter (DBusConnection *bus, DBusMessage *message, void *data)
203
XfpmDBusMonitor *monitor;
205
if ( dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") )
207
TRACE ("System bus is disconnected");
208
monitor = XFPM_DBUS_MONITOR (data);
209
g_signal_emit (G_OBJECT (monitor), signals [SYSTEM_BUS_CONNECTION_CHANGED], 0, FALSE);
211
xfpm_dbus_monitor_setup_system_watch (monitor);
213
return DBUS_HANDLER_RESULT_HANDLED;
216
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
220
xfpm_dbus_monitor_session (XfpmDBusMonitor *monitor)
222
monitor->priv->session_proxy = dbus_g_proxy_new_for_name_owner (monitor->priv->session_bus,
223
"org.freedesktop.DBus",
224
"/org/freedesktop/DBus",
225
"org.freedesktop.DBus",
227
if ( !monitor->priv->session_proxy )
229
g_critical ("Unable to create proxy on /org/freedesktop/DBus");
233
dbus_g_proxy_add_signal (monitor->priv->session_proxy, "NameOwnerChanged",
234
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
236
dbus_g_proxy_connect_signal (monitor->priv->session_proxy, "NameOwnerChanged",
237
G_CALLBACK (xfpm_dbus_monitor_session_name_owner_changed_cb), monitor, NULL);
241
xfpm_dbus_monitor_system (XfpmDBusMonitor *monitor)
243
monitor->priv->system_proxy = dbus_g_proxy_new_for_name_owner (monitor->priv->system_bus,
244
"org.freedesktop.DBus",
245
"/org/freedesktop/DBus",
246
"org.freedesktop.DBus",
248
if ( !monitor->priv->system_proxy )
250
g_critical ("Unable to create proxy on /org/freedesktop/DBus");
254
dbus_g_proxy_add_signal (monitor->priv->system_proxy, "NameOwnerChanged",
255
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
257
dbus_g_proxy_connect_signal (monitor->priv->system_proxy, "NameOwnerChanged",
258
G_CALLBACK (xfpm_dbus_monitor_system_name_owner_changed_cb), monitor, NULL);
262
xfpm_dbus_monitor_class_init (XfpmDBusMonitorClass *klass)
264
GObjectClass *object_class = G_OBJECT_CLASS (klass);
266
signals [UNIQUE_NAME_LOST] =
267
g_signal_new ("unique-name-lost",
268
XFPM_TYPE_DBUS_MONITOR,
270
G_STRUCT_OFFSET (XfpmDBusMonitorClass, unique_name_lost),
272
_xfpm_dbus_marshal_VOID__STRING_BOOLEAN,
274
G_TYPE_STRING, G_TYPE_BOOLEAN);
276
signals [SERVICE_CONNECTION_CHANGED] =
277
g_signal_new ("service-connection-changed",
278
XFPM_TYPE_DBUS_MONITOR,
280
G_STRUCT_OFFSET (XfpmDBusMonitorClass, service_connection_changed),
282
_xfpm_dbus_marshal_VOID__STRING_BOOLEAN_BOOLEAN,
283
G_TYPE_NONE, 3, G_TYPE_STRING,
284
G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);
286
signals [SYSTEM_BUS_CONNECTION_CHANGED] =
287
g_signal_new ("system-bus-connection-changed",
288
XFPM_TYPE_DBUS_MONITOR,
290
G_STRUCT_OFFSET (XfpmDBusMonitorClass, system_bus_connection_changed),
292
g_cclosure_marshal_VOID__BOOLEAN,
293
G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
295
object_class->finalize = xfpm_dbus_monitor_finalize;
297
g_type_class_add_private (klass, sizeof (XfpmDBusMonitorPrivate));
301
xfpm_dbus_monitor_init (XfpmDBusMonitor *monitor)
303
monitor->priv = XFPM_DBUS_MONITOR_GET_PRIVATE (monitor);
305
monitor->priv->session_proxy = NULL;
306
monitor->priv->system_proxy = NULL;
308
monitor->priv->names_array = g_ptr_array_new ();
309
monitor->priv->services_array = g_ptr_array_new ();
311
monitor->priv->session_bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
312
monitor->priv->system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
314
xfpm_dbus_monitor_session (monitor);
315
xfpm_dbus_monitor_system (monitor);
317
dbus_connection_set_exit_on_disconnect (dbus_g_connection_get_connection (monitor->priv->system_bus),
320
dbus_connection_add_filter (dbus_g_connection_get_connection (monitor->priv->system_bus),
321
xfpm_dbus_monitor_system_bus_filter,
327
xfpm_dbus_monitor_finalize (GObject *object)
329
XfpmDBusMonitor *monitor;
331
monitor = XFPM_DBUS_MONITOR (object);
333
if ( monitor->priv->session_proxy )
335
dbus_g_proxy_disconnect_signal (monitor->priv->session_proxy, "NameOwnerChanged",
336
G_CALLBACK (xfpm_dbus_monitor_session_name_owner_changed_cb), monitor);
337
g_object_unref (monitor->priv->session_proxy);
340
if ( monitor->priv->system_proxy )
342
dbus_g_proxy_disconnect_signal (monitor->priv->system_proxy, "NameOwnerChanged",
343
G_CALLBACK (xfpm_dbus_monitor_system_name_owner_changed_cb), monitor);
344
g_object_unref (monitor->priv->system_proxy);
347
dbus_connection_remove_filter (dbus_g_connection_get_connection (monitor->priv->system_bus),
348
xfpm_dbus_monitor_system_bus_filter,
351
dbus_g_connection_unref (monitor->priv->system_bus);
352
dbus_g_connection_unref (monitor->priv->session_bus);
354
g_ptr_array_foreach (monitor->priv->names_array, (GFunc) xfpm_dbus_monitor_free_watch_data, NULL);
355
g_ptr_array_foreach (monitor->priv->services_array, (GFunc) xfpm_dbus_monitor_free_watch_data, NULL);
357
g_ptr_array_free (monitor->priv->names_array, TRUE);
358
g_ptr_array_free (monitor->priv->services_array, TRUE);
360
G_OBJECT_CLASS (xfpm_dbus_monitor_parent_class)->finalize (object);
364
xfpm_dbus_monitor_new (void)
366
static gpointer xfpm_dbus_monitor_object = NULL;
368
if ( G_LIKELY (xfpm_dbus_monitor_object != NULL) )
370
g_object_ref (xfpm_dbus_monitor_object);
374
xfpm_dbus_monitor_object = g_object_new (XFPM_TYPE_DBUS_MONITOR, NULL);
375
g_object_add_weak_pointer (xfpm_dbus_monitor_object, &xfpm_dbus_monitor_object);
378
return XFPM_DBUS_MONITOR (xfpm_dbus_monitor_object);
381
gboolean xfpm_dbus_monitor_add_unique_name (XfpmDBusMonitor *monitor, DBusBusType bus_type, const gchar *unique_name)
383
XfpmWatchData *watch;
385
g_return_val_if_fail (XFPM_IS_DBUS_MONITOR (monitor), FALSE);
386
g_return_val_if_fail (unique_name != NULL, FALSE);
388
/* We have it already */
389
if ( xfpm_dbus_monitor_get_watch_data (monitor->priv->names_array, unique_name, bus_type) )
392
watch = g_new0 (XfpmWatchData , 1);
393
watch->name = g_strdup (unique_name);
394
watch->bus_type = bus_type;
396
g_ptr_array_add (monitor->priv->names_array, watch);
400
void xfpm_dbus_monitor_remove_unique_name (XfpmDBusMonitor *monitor, DBusBusType bus_type, const gchar *unique_name)
402
XfpmWatchData *watch;
404
g_return_if_fail (XFPM_IS_DBUS_MONITOR (monitor));
406
watch = xfpm_dbus_monitor_get_watch_data (monitor->priv->names_array, unique_name, bus_type);
410
g_ptr_array_remove (monitor->priv->names_array, watch);
411
xfpm_dbus_monitor_free_watch_data (watch);
415
gboolean xfpm_dbus_monitor_add_service (XfpmDBusMonitor *monitor, DBusBusType bus_type, const gchar *service_name)
417
XfpmWatchData *watch;
419
g_return_val_if_fail (XFPM_IS_DBUS_MONITOR (monitor), FALSE);
421
if ( xfpm_dbus_monitor_get_watch_data (monitor->priv->services_array, service_name, bus_type ) )
424
watch = g_new0 (XfpmWatchData , 1);
425
watch->name = g_strdup (service_name);
426
watch->bus_type = bus_type;
428
g_ptr_array_add (monitor->priv->services_array, watch);
433
void xfpm_dbus_monitor_remove_service (XfpmDBusMonitor *monitor, DBusBusType bus_type, const gchar *service_name)
435
XfpmWatchData *watch;
437
g_return_if_fail (XFPM_IS_DBUS_MONITOR (monitor));
439
watch = xfpm_dbus_monitor_get_watch_data (monitor->priv->services_array, service_name, bus_type);
443
g_ptr_array_remove (monitor->priv->services_array, watch);
444
xfpm_dbus_monitor_free_watch_data (watch);