2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 3
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
22
#include <sys/types.h>
25
#include "applet-struct.h"
26
#include "applet-item.h"
27
#include "applet-draw.h"
28
#include "applet-host.h"
29
#include "applet-host-ias.h"
31
// Ubuntu sort-of-high-level-Watcher (new or old address)
32
#if (INDICATOR_OLD_NAMES == 0) // Natty
33
#define CD_INDICATOR_APPLICATION_ADDR "com.canonical.indicator.application"
34
#define CD_INDICATOR_APPLICATION_OBJ "/com/canonical/indicator/application/service"
35
#define CD_INDICATOR_APPLICATION_IFACE "com.canonical.indicator.application.service"
37
#define CD_INDICATOR_APPLICATION_ADDR "org.ayatana.indicator.application"
38
#define CD_INDICATOR_APPLICATION_OBJ "/org/ayatana/indicator/application/service"
39
#define CD_INDICATOR_APPLICATION_IFACE "org.ayatana.indicator.application.service"
42
// Ubuntu Indicator Service
43
#define CD_INDICATOR_SERVICE_INTERFACE "org.ayatana.indicator.service"
44
#define CD_INDICATOR_SERVICE_OBJECT "/org/ayatana/indicator/service"
46
#define CD_INDICATOR_APPLICATION_ITEM_OBJ "/org/ayatana/NotificationItem"
48
static DBusGProxyCall *s_pDetectIASCall = NULL;
50
#if (INDICATOR_OLD_NAMES != 0) // Maverick
51
static void _cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING (GClosure *closure,
52
GValue *return_value G_GNUC_UNUSED,
54
const GValue *param_values,
55
gpointer invocation_hint G_GNUC_UNUSED,
56
gpointer marshal_data)
58
//cd_debug ("=== %s ()", __func__);
59
typedef void (*GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING) (
69
register GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING callback;
70
register GCClosure *cc = (GCClosure*) closure;
71
register gpointer data1, data2;
72
g_return_if_fail (n_param_values == 8); // return_value est NULL ici, car la callback ne renvoit rien.
74
if (G_CCLOSURE_SWAP_DATA (closure))
76
data1 = closure->data;
77
data2 = g_value_peek_pointer (param_values + 0);
81
data1 = g_value_peek_pointer (param_values + 0);
82
data2 = closure->data;
84
callback = (GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING) (marshal_data ? marshal_data : cc->callback);
87
(char*) g_value_get_string (param_values + 1),
88
g_value_get_int (param_values + 2),
89
(char*) g_value_get_string (param_values + 3),
90
(char*) g_value_get_string (param_values + 4),
91
(char*) g_value_get_string (param_values + 5),
92
(char*) g_value_get_string (param_values + 6),
93
(char*) g_value_get_string (param_values + 7),
97
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
98
static void _cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING_STRING (
99
#elif (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
100
static void _cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING (
102
static void _cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING (
105
GValue *return_value G_GNUC_UNUSED,
106
guint n_param_values,
107
const GValue *param_values,
108
gpointer invocation_hint G_GNUC_UNUSED,
109
gpointer marshal_data)
111
//cd_debug ("=== %s ()", __func__);
112
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
113
typedef void (*GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING_STRING) (
114
#elif (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
115
typedef void (*GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING) (
117
typedef void (*GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING) (
128
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
130
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
135
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
136
register GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING_STRING callback;
137
#elif (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
138
register GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING callback;
140
register GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING callback;
142
register GCClosure *cc = (GCClosure*) closure;
143
register gpointer data1, data2;
144
// return_value est NULL ici, car la callback ne renvoit rien.
145
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
146
g_return_if_fail (n_param_values == 11);
147
#elif (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
148
g_return_if_fail (n_param_values == 10);
150
g_return_if_fail (n_param_values == 9);
153
if (G_CCLOSURE_SWAP_DATA (closure))
155
data1 = closure->data;
156
data2 = g_value_peek_pointer (param_values + 0);
160
data1 = g_value_peek_pointer (param_values + 0);
161
data2 = closure->data;
163
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
164
callback = (GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING_STRING)
165
#elif (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
166
callback = (GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING)
168
callback = (GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING)
170
(marshal_data ? marshal_data : cc->callback);
173
(char*) g_value_get_string (param_values + 1),
174
g_value_get_int (param_values + 2),
175
(char*) g_value_get_string (param_values + 3),
176
(char*) g_value_get_boxed (param_values + 4),
177
(char*) g_value_get_string (param_values + 5),
178
(char*) g_value_get_string (param_values + 6),
179
(char*) g_value_get_string (param_values + 7),
180
(char*) g_value_get_string (param_values + 8),
181
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
182
(char*) g_value_get_string (param_values + 9),
183
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
184
(char*) g_value_get_string (param_values + 10),
191
static void _cd_cclosure_marshal_VOID__INT_STRING_STRING (GClosure *closure,
192
GValue *return_value G_GNUC_UNUSED,
193
guint n_param_values,
194
const GValue *param_values,
195
gpointer invocation_hint G_GNUC_UNUSED,
196
gpointer marshal_data)
198
//cd_debug ("=== %s ()", __func__);
199
typedef void (*GMarshalFunc_VOID__INT_STRING_STRING) (
205
register GMarshalFunc_VOID__INT_STRING_STRING callback;
206
register GCClosure *cc = (GCClosure*) closure;
207
register gpointer data1, data2;
208
g_return_if_fail (n_param_values == 4); // return_value est NULL ici, car la callback ne renvoit rien.
210
if (G_CCLOSURE_SWAP_DATA (closure))
212
data1 = closure->data;
213
data2 = g_value_peek_pointer (param_values + 0);
217
data1 = g_value_peek_pointer (param_values + 0);
218
data2 = closure->data;
220
callback = (GMarshalFunc_VOID__INT_STRING_STRING) (marshal_data ? marshal_data : cc->callback);
223
g_value_get_int (param_values + 1),
224
(char*) g_value_get_string (param_values + 2),
225
(char*) g_value_get_string (param_values + 3),
229
static void _cd_cclosure_marshal_VOID__INT_STRING (GClosure *closure,
230
GValue *return_value G_GNUC_UNUSED,
231
guint n_param_values,
232
const GValue *param_values,
233
gpointer invocation_hint G_GNUC_UNUSED,
234
gpointer marshal_data)
236
//cd_debug ("=== %s ()", __func__);
237
typedef void (*GMarshalFunc_VOID__INT_STRING) (
242
register GMarshalFunc_VOID__INT_STRING callback;
243
register GCClosure *cc = (GCClosure*) closure;
244
register gpointer data1, data2;
245
g_return_if_fail (n_param_values == 3); // return_value est NULL ici, car la callback ne renvoit rien.
247
if (G_CCLOSURE_SWAP_DATA (closure))
249
data1 = closure->data;
250
data2 = g_value_peek_pointer (param_values + 0);
254
data1 = g_value_peek_pointer (param_values + 0);
255
data2 = closure->data;
257
callback = (GMarshalFunc_VOID__INT_STRING) (marshal_data ? marshal_data : cc->callback);
260
g_value_get_int (param_values + 1),
261
(char*) g_value_get_string (param_values + 2),
269
static void on_new_application (DBusGProxy *proxy_watcher, const gchar *cIconName, gint iPosition, const gchar *cAddress, const gchar *cObjectPath, const gchar *cIconThemePath, const gchar *cLabel, const gchar *cLabelGuide,
270
#if (INDICATOR_OLD_NAMES == 0) // Natty
271
const gchar *cAccessbleDesc, // WTF is this new param ??
272
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
273
const gchar *cHint, // <irony> is this a hint to work around a clumsy API ? </irony>
274
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
279
GldiModuleInstance *myApplet)
282
cd_debug ("=== %s (%s, %s, %s, %s, %d)", __func__, cAddress, cObjectPath, cIconName, cIconThemePath, iPosition);
283
#if (INDICATOR_OLD_NAMES == 0) // Natty
284
cd_debug (" %s", cAccessbleDesc);
285
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
286
cd_debug (" %s", cHint);
287
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
288
cd_debug (" %s", cTitle);
293
// position +1 for items placed after this one.
294
CDStatusNotifierItem *pItem;
296
for (it = myData.pItems; it != NULL; it = it->next)
299
if (pItem->iPosition >= iPosition)
302
cd_debug ("=== %s -> %d -> %d", pItem->cId, pItem->iPosition-1, pItem->iPosition);
306
cd_satus_notifier_add_new_item_with_default (cAddress, cObjectPath, iPosition,
307
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
308
cIconName ? cIconName : cHint,
313
#if (INDICATOR_OLD_NAMES == 0)
314
cAccessbleDesc && *cAccessbleDesc != '\0' ? cAccessbleDesc :
315
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
316
cTitle && *cTitle != '\0' ? cTitle :
325
static void on_removed_application (DBusGProxy *proxy_watcher, gint iPosition, GldiModuleInstance *myApplet)
328
cd_debug ("=== %s (%d)", __func__, iPosition);
330
cd_satus_notifier_remove_item (NULL, iPosition);
332
// position -1 for items placed after this one.
333
CDStatusNotifierItem *pItem;
335
for (it = myData.pItems; it != NULL; it = it->next)
338
if (pItem->iPosition >= iPosition)
341
cd_debug ("=== %s -> %d -> %d", pItem->cId, pItem->iPosition+1, pItem->iPosition);
348
static void on_application_icon_changed (DBusGProxy *proxy_watcher, gint iPosition, const gchar *cIconName, const gchar *cIconDesc, GldiModuleInstance *myApplet)
351
cd_debug ("=== %s (%d, %s, %s)", __func__, iPosition, cIconName, cIconDesc);
353
CDStatusNotifierItem *pItem = cd_satus_notifier_find_item_from_position (iPosition);
354
g_return_if_fail (pItem != NULL);
356
if (g_strcmp0 (pItem->cIconName, cIconName) == 0) // discard useless updates (skype...)
358
g_free (pItem->cIconName);
359
pItem->cIconName = g_strdup (cIconName);
360
g_free (pItem->cAccessibleDesc);
361
pItem->cAccessibleDesc = g_strdup (cIconDesc);
363
if (pItem->iStatus != CD_STATUS_NEEDS_ATTENTION)
365
cd_satus_notifier_update_item_image (pItem);
371
static void on_application_icon_theme_path_changed (DBusGProxy *proxy_watcher, gint iPosition, const gchar *cIconThemePath, GldiModuleInstance *myApplet)
374
cd_debug ("=== %s (%d, %s)", __func__, iPosition, cIconThemePath);
376
CDStatusNotifierItem *pItem = cd_satus_notifier_find_item_from_position (iPosition);
377
g_return_if_fail (pItem != NULL);
379
if (g_strcmp0 (cIconThemePath, pItem->cIconThemePath) != 0)
381
if (pItem->cIconThemePath != NULL) // if the item previously provided a theme, remove it first.
382
cd_satus_notifier_remove_theme_path (pItem->cIconThemePath);
383
g_free (pItem->cIconThemePath);
384
pItem->cIconThemePath = g_strdup (cIconThemePath);
386
cd_satus_notifier_add_theme_path (cIconThemePath); // and add the new one.
388
if (pItem->cIconName != NULL)
390
cd_satus_notifier_update_item_image (pItem);
396
static void on_application_label_changed (DBusGProxy *proxy_watcher, gint iPosition, const gchar *cLabel, const gchar *cLabelGuide, GldiModuleInstance *myApplet)
399
cd_debug ("=== %s (%d, %s, %s)", __func__, iPosition, cLabel, cLabelGuide);
401
CDStatusNotifierItem *pItem = cd_satus_notifier_find_item_from_position (iPosition);
402
g_return_if_fail (pItem != NULL);
404
g_free (pItem->cLabel);
405
pItem->cLabel = g_strdup (cLabel);
406
g_free (pItem->cLabelGuide);
407
pItem->cLabelGuide = g_strdup (cLabelGuide);
412
static void on_application_title_changed (DBusGProxy *proxy_watcher, gint iPosition, const gchar *cTitle, GldiModuleInstance *myApplet)
415
cd_debug ("=== %s (%d, %s)", __func__, iPosition, cTitle);
417
CDStatusNotifierItem *pItem = cd_satus_notifier_find_item_from_position (iPosition);
418
g_return_if_fail (pItem != NULL);
422
g_free (pItem->cTitle);
423
pItem->cTitle = g_strdup (cTitle);
433
static void _on_get_applications_from_service (DBusGProxy *proxy, DBusGProxyCall *call_id, GldiModuleInstance *myApplet)
435
cd_debug ("=== %s ()", __func__);
438
//\______________________ get the applications list from the service.
439
GPtrArray *pApplications = NULL;
440
GError *erreur = NULL;
441
GType g_type_ptrarray = dbus_g_type_get_collection ("GPtrArray",
442
dbus_g_type_get_struct("GValueArray",
443
G_TYPE_STRING, // iconname
444
G_TYPE_INT, // position
445
G_TYPE_STRING, // dbusaddress
446
DBUS_TYPE_G_OBJECT_PATH, // dbusobject
447
G_TYPE_STRING, // iconpath
448
G_TYPE_STRING, // label
449
G_TYPE_STRING, // labelguide
450
#if (INDICATOR_OLD_NAMES == 0) // Natty
451
G_TYPE_STRING, // accessibledesc
452
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
453
G_TYPE_STRING, // hint
454
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
455
G_TYPE_STRING, // title
460
dbus_g_proxy_end_call (proxy,
463
g_type_ptrarray, &pApplications,
467
cd_debug ("=== couldn't get applications in the systray (%s)", erreur->message);
468
g_error_free (erreur);
471
if (pApplications == NULL)
474
//\______________________ build each items.
475
cd_debug ("=== got %d applications", pApplications->len);
479
CDStatusNotifierItem *pItem = NULL;
480
//cd_debug ("=== %d apps in the systray", pApplications->len);
481
for (i = 0; i < pApplications->len; i ++)
483
// get the properties of the item
484
cd_debug ("=== %d) %p", i, pApplications->pdata[i]);
485
va = pApplications->pdata[i];
489
const gchar *cIconName = NULL;
491
const gchar *cAddress = NULL;
492
const gchar *cObjectPath = NULL;
493
const gchar *cIconThemePath = NULL;
494
const gchar *cLabel = NULL;
495
const gchar *cLabelGuide = NULL;
496
const gchar *cAccessibleDesc = NULL; // natty
497
// const gchar *cHint = NULL; // oneiric
498
const gchar *cTitle = NULL; // precise
500
v = g_value_array_get_nth (va, 0); // GValueArray is deprecated from 2.32, yet it's so convenient to map the g_type_ptrarray type ...
501
if (v && G_VALUE_HOLDS_STRING (v))
502
cIconName = g_value_get_string (v);
504
v = g_value_array_get_nth (va, 1);
505
if (v && G_VALUE_HOLDS_INT (v))
506
iPosition = g_value_get_int (v);
508
v = g_value_array_get_nth (va, 2);
509
if (v && G_VALUE_HOLDS_STRING (v))
510
cAddress = g_value_get_string (v);
512
v = g_value_array_get_nth (va, 3);
513
if (v && G_VALUE_HOLDS (v, DBUS_TYPE_G_OBJECT_PATH))
514
cObjectPath = (gchar*)g_value_get_boxed (v);
516
/*cd_debug ("=== cObjectPath : %s", cObjectPath);
517
if (cObjectPath != NULL && strncmp (cObjectPath, CD_INDICATOR_APPLICATION_ITEM_OBJ, strlen (CD_INDICATOR_APPLICATION_ITEM_OBJ)) == 0)
519
gchar *str = strrchr (cObjectPath, '/'); // I think this is because this path is actually the menu path, and fortunately it's just under the item object's path.
522
}*/ // => we will do that in cd_satus_notifier_create_item because this function is also called when a new application is added => host.c
524
v = g_value_array_get_nth (va, 4);
525
if (v && G_VALUE_HOLDS_STRING (v))
526
cIconThemePath = g_value_get_string (v);
528
v = g_value_array_get_nth (va, 5);
529
if (v && G_VALUE_HOLDS_STRING (v))
530
cLabel = g_value_get_string (v);
532
v = g_value_array_get_nth (va, 6);
533
if (v && G_VALUE_HOLDS_STRING (v))
534
cLabelGuide = g_value_get_string (v);
536
#if (INDICATOR_OLD_NAMES == 0)
537
v = g_value_array_get_nth (va, 7);
538
if (v && G_VALUE_HOLDS_STRING (v))
539
cAccessibleDesc = g_value_get_string (v);
541
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
542
v = g_value_array_get_nth (va, 9);
543
if (v && G_VALUE_HOLDS_STRING (v))
544
cTitle = g_value_get_string (v);
548
cd_debug ("=== + item {%s ; %d ; %s ; %s ; %s ; %s ; %s ; %s ; %s}",
562
// ensure we're not duplicating an existing item (this should never happen if the service is ok, but since it doesn't depend on us, let's be careful).
564
for (it = myData.pItems; it != NULL; it = it->next)
567
if (strcmp (cAddress, pItem->cService) == 0) // pItem->cService is never NULL
569
cd_warning ("Duplicated item: %s (%s)", cIconName, cAddress);
572
if (iPosition != -1 && pItem->iPosition == iPosition)
574
cd_warning ("Possible duplicated item: %s/%s/%d , %s/%s/%d)", cIconName, cAddress, iPosition, pItem->cIconName, pItem->cService, pItem->iPosition);
578
// make a new item based on these properties.
579
pItem = cd_satus_notifier_create_item (cAddress, cObjectPath);
582
if (pItem->iPosition == -1)
583
pItem->iPosition = iPosition;
584
if (pItem->cTitle == NULL && pItem->cLabel == NULL && pItem->cAccessibleDesc == NULL)
585
pItem->cLabel = g_strdup (cAccessibleDesc && *cAccessibleDesc != '\0' ? cAccessibleDesc :
586
cLabel && *cLabel != '\0' ? cLabel :
587
cTitle && *cTitle != '\0' ? cTitle :
588
NULL); // don't use cId as a fallback, because it often has cryptic names (nm-applet ; dropbox-xxxx). If the appli doesn't provide a title, it's its fault.
589
cd_status_notifier_add_item_in_list (pItem);
592
if (myConfig.bCompactMode)
594
cd_satus_notifier_reload_compact_mode ();
598
cd_satus_notifier_load_icons_from_items ();
601
g_ptr_array_free (pApplications, TRUE);
605
void cd_satus_notifier_get_items_from_ias (void)
607
if (! myData.bIASWatched)
609
cd_debug ("=== %s ()", __func__);
611
g_return_if_fail (myData.pProxyIndicatorApplicationService == NULL);
613
myData.pProxyIndicatorApplicationService = cairo_dock_create_new_session_proxy (
614
CD_INDICATOR_APPLICATION_ADDR,
615
CD_INDICATOR_APPLICATION_OBJ,
616
CD_INDICATOR_APPLICATION_IFACE);
618
// get the current items
619
dbus_g_proxy_begin_call (myData.pProxyIndicatorApplicationService,
621
(DBusGProxyCallNotify)_on_get_applications_from_service,
623
(GDestroyNotify) NULL,
626
// connect to the signals to keep the list of items up-to-date.
627
#if (INDICATOR_OLD_NAMES != 0) // Maverick
628
dbus_g_object_register_marshaller(_cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING,
629
G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
631
dbus_g_object_register_marshaller(
632
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
633
_cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING_STRING,
634
#elif (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
635
_cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING,
637
_cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING,
639
G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING,
640
DBUS_TYPE_G_OBJECT_PATH, // dbusobject
641
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
642
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
644
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
650
dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationAdded",
651
G_TYPE_STRING, // iconname
652
G_TYPE_INT, // position
653
G_TYPE_STRING, // dbusaddress
654
#if (INDICATOR_OLD_NAMES != 0) // Maverick
655
G_TYPE_STRING, // dbusobject
657
DBUS_TYPE_G_OBJECT_PATH, // dbusobject
659
G_TYPE_STRING, // iconpath
660
G_TYPE_STRING, // label
661
G_TYPE_STRING, // labelguide
662
#if (INDICATOR_OLD_NAMES == 0) // Natty
663
G_TYPE_STRING, // accessibledesc
664
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
665
G_TYPE_STRING, // hint => only with indicator-0.4 (Oneiric)
666
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
667
G_TYPE_STRING, // title => only with indicator-0.4.90 (Precise)
672
dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationAdded",
673
G_CALLBACK(on_new_application), myApplet, NULL);
675
dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationRemoved",
676
G_TYPE_INT, // position
678
dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationRemoved",
679
G_CALLBACK(on_removed_application), myApplet, NULL);
681
// we add the following signals because some program don't support the StatusNotifier API (skype, once again...) but only the IAS one.
682
dbus_g_object_register_marshaller(_cd_cclosure_marshal_VOID__INT_STRING_STRING,
683
G_TYPE_NONE, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
684
dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationIconChanged",
685
G_TYPE_INT, // position
686
G_TYPE_STRING, // icon name
687
G_TYPE_STRING, // icon desc (?)
689
dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationIconChanged",
690
G_CALLBACK(on_application_icon_changed), myApplet, NULL);
692
dbus_g_object_register_marshaller(_cd_cclosure_marshal_VOID__INT_STRING,
693
G_TYPE_NONE, G_TYPE_INT, G_TYPE_STRING, G_TYPE_INVALID);
694
dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationIconThemePathChanged",
695
G_TYPE_INT, // position
696
G_TYPE_STRING, // icon name
697
G_TYPE_STRING, // icon desc (Note: I'm quite sure they will eventually remove it ...)
699
dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationIconThemePathChanged",
700
G_CALLBACK(on_application_icon_theme_path_changed), myApplet, NULL);
702
dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationLabelChanged",
703
G_TYPE_INT, // position
704
G_TYPE_STRING, // label
705
G_TYPE_STRING, // guide
707
dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationLabelChanged",
708
G_CALLBACK(on_application_label_changed), myApplet, NULL);
710
dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationTitleChanged",
711
G_TYPE_INT, // position
712
G_TYPE_STRING, // title
714
dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationTitleChanged",
715
G_CALLBACK(on_application_title_changed), myApplet, NULL);
722
static void _on_start_service (DBusGProxy *proxy, guint status, GError *error, gpointer data)
724
// if service has not started, then we'll assume we don't need it (eg.: KDE)
725
if (status != DBUS_START_REPLY_SUCCESS && status != DBUS_START_REPLY_ALREADY_RUNNING) // service is not started.
727
if (error != NULL) // couldn't start the service
728
cd_debug ("=== Unable to start the indicator service (%s), assuming we don't need it", error->message);
730
cd_debug ("=== Unable to start the indicator service (got status %d), assuming we don't need it", status);
731
myData.bNoIAS = TRUE;
732
cd_satus_notifier_launch_our_watcher ();
735
cd_debug ("=== Indicator Service has started");
737
static void _on_watch_service (DBusGProxy *proxy, DBusGProxyCall *call, gpointer data)
740
GError *error = NULL;
741
guint service_api_version=0, this_service_version=0;
742
dbus_g_proxy_end_call (proxy, call, &error,
743
G_TYPE_UINT, &service_api_version,
744
G_TYPE_UINT, &this_service_version,
746
cd_debug ("=== got indicator service (API: %d, service: %d, broken watcher: %d)", service_api_version, this_service_version, myData.bBrokenWatcher);
748
if (service_api_version > 0) /// shouldn't the 2 versions be equal ?...
750
myData.bIASWatched = TRUE; // now we're friend with the IAS
752
if (myData.bBrokenWatcher) // if the watcher is not our friend, let's ask the IAS the current items.
754
cd_satus_notifier_get_items_from_ias ();
759
static void _on_ias_owner_changed (const gchar *cName, gboolean bOwned, gpointer data)
762
cd_debug ("=== Indicator Applications Service is on the bus (%d)", bOwned);
766
myData.bNoIAS = FALSE;
767
// set up a proxy to the Service
768
myData.pProxyIndicatorService = cairo_dock_create_new_session_proxy (
769
CD_INDICATOR_APPLICATION_ADDR,
770
CD_INDICATOR_SERVICE_OBJECT,
771
CD_INDICATOR_SERVICE_INTERFACE);
774
cd_debug ("=== watch it");
775
dbus_g_proxy_begin_call (myData.pProxyIndicatorService,
777
(DBusGProxyCallNotify)_on_watch_service,
779
(GDestroyNotify) NULL,
782
else // no more IAS on the bus.
784
g_object_unref (myData.pProxyIndicatorService);
785
myData.pProxyIndicatorService = NULL;
787
g_object_unref (myData.pProxyIndicatorApplicationService);
788
myData.pProxyIndicatorApplicationService = NULL;
790
myData.bIASWatched = FALSE;
792
myData.bNoIAS = TRUE;
793
cd_satus_notifier_launch_our_watcher ();
797
static void _on_detect_ias (gboolean bPresent, gpointer data)
800
cd_debug ("=== Indicator Applications Service is present: %d", bPresent);
801
s_pDetectIASCall = NULL;
802
// if present, set up proxy, else try to start the service.
805
_on_ias_owner_changed (CD_INDICATOR_APPLICATION_ADDR, TRUE, NULL);
807
else // not present, maybe the service is not started => try starting it.
809
cd_debug ("=== try to start the Indicator Service...");
810
DBusGProxy *dbus_proxy = cairo_dock_get_main_proxy ();
811
org_freedesktop_DBus_start_service_by_name_async (dbus_proxy,
812
CD_INDICATOR_APPLICATION_ADDR,
817
// watch whenever the Service goes up or down.
818
cairo_dock_watch_dbus_name_owner (CD_INDICATOR_APPLICATION_ADDR,
819
(CairoDockDbusNameOwnerChangedFunc) _on_ias_owner_changed,
825
void cd_satus_notifier_detect_ias (void)
827
s_pDetectIASCall = cairo_dock_dbus_detect_application_async (CD_INDICATOR_APPLICATION_ADDR,
828
(CairoDockOnAppliPresentOnDbus) _on_detect_ias,
833
void cd_satus_notifier_unregister_from_ias (void)
835
if (myData.pProxyIndicatorApplicationService != NULL)
837
g_object_unref (myData.pProxyIndicatorApplicationService);
838
g_object_unref (myData.pProxyIndicatorService);
841
if (s_pDetectIASCall != NULL)
843
DBusGProxy *pProxy = cairo_dock_get_main_proxy ();
844
dbus_g_proxy_cancel_call (pProxy, s_pDetectIASCall);
845
s_pDetectIASCall = NULL;
848
cairo_dock_stop_watching_dbus_name_owner (CD_INDICATOR_APPLICATION_ADDR,
849
(CairoDockDbusNameOwnerChangedFunc) _on_ias_owner_changed);