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"
47
static DBusGProxyCall *s_pDetectIASCall = NULL;
49
#if (INDICATOR_OLD_NAMES != 0) // Maverick
50
static void _cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING (GClosure *closure,
51
GValue *return_value G_GNUC_UNUSED,
53
const GValue *param_values,
54
gpointer invocation_hint G_GNUC_UNUSED,
55
gpointer marshal_data)
57
//cd_debug ("=== %s ()", __func__);
58
typedef void (*GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING) (
68
register GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING callback;
69
register GCClosure *cc = (GCClosure*) closure;
70
register gpointer data1, data2;
71
g_return_if_fail (n_param_values == 8); // return_value est NULL ici, car la callback ne renvoit rien.
73
if (G_CCLOSURE_SWAP_DATA (closure))
75
data1 = closure->data;
76
data2 = g_value_peek_pointer (param_values + 0);
80
data1 = g_value_peek_pointer (param_values + 0);
81
data2 = closure->data;
83
callback = (GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING) (marshal_data ? marshal_data : cc->callback);
86
(char*) g_value_get_string (param_values + 1),
87
g_value_get_int (param_values + 2),
88
(char*) g_value_get_string (param_values + 3),
89
(char*) g_value_get_string (param_values + 4),
90
(char*) g_value_get_string (param_values + 5),
91
(char*) g_value_get_string (param_values + 6),
92
(char*) g_value_get_string (param_values + 7),
96
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
97
static void _cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING_STRING (
98
#elif (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
99
static void _cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING (
101
static void _cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING (
104
GValue *return_value G_GNUC_UNUSED,
105
guint n_param_values,
106
const GValue *param_values,
107
gpointer invocation_hint G_GNUC_UNUSED,
108
gpointer marshal_data)
110
//cd_debug ("=== %s ()", __func__);
111
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
112
typedef void (*GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING_STRING) (
113
#elif (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
114
typedef void (*GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING) (
116
typedef void (*GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING) (
127
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
129
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
134
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
135
register GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING_STRING callback;
136
#elif (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
137
register GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING callback;
139
register GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING callback;
141
register GCClosure *cc = (GCClosure*) closure;
142
register gpointer data1, data2;
143
// return_value est NULL ici, car la callback ne renvoit rien.
144
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
145
g_return_if_fail (n_param_values == 11);
146
#elif (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
147
g_return_if_fail (n_param_values == 10);
149
g_return_if_fail (n_param_values == 9);
152
if (G_CCLOSURE_SWAP_DATA (closure))
154
data1 = closure->data;
155
data2 = g_value_peek_pointer (param_values + 0);
159
data1 = g_value_peek_pointer (param_values + 0);
160
data2 = closure->data;
162
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
163
callback = (GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING_STRING)
164
#elif (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
165
callback = (GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING)
167
callback = (GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING)
169
(marshal_data ? marshal_data : cc->callback);
172
(char*) g_value_get_string (param_values + 1),
173
g_value_get_int (param_values + 2),
174
(char*) g_value_get_string (param_values + 3),
175
(char*) g_value_get_boxed (param_values + 4),
176
(char*) g_value_get_string (param_values + 5),
177
(char*) g_value_get_string (param_values + 6),
178
(char*) g_value_get_string (param_values + 7),
179
(char*) g_value_get_string (param_values + 8),
180
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
181
(char*) g_value_get_string (param_values + 9),
182
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
183
(char*) g_value_get_string (param_values + 10),
190
static void _cd_cclosure_marshal_VOID__INT_STRING_STRING (GClosure *closure,
191
GValue *return_value G_GNUC_UNUSED,
192
guint n_param_values,
193
const GValue *param_values,
194
gpointer invocation_hint G_GNUC_UNUSED,
195
gpointer marshal_data)
197
//cd_debug ("=== %s ()", __func__);
198
typedef void (*GMarshalFunc_VOID__INT_STRING_STRING) (
204
register GMarshalFunc_VOID__INT_STRING_STRING callback;
205
register GCClosure *cc = (GCClosure*) closure;
206
register gpointer data1, data2;
207
g_return_if_fail (n_param_values == 4); // return_value est NULL ici, car la callback ne renvoit rien.
209
if (G_CCLOSURE_SWAP_DATA (closure))
211
data1 = closure->data;
212
data2 = g_value_peek_pointer (param_values + 0);
216
data1 = g_value_peek_pointer (param_values + 0);
217
data2 = closure->data;
219
callback = (GMarshalFunc_VOID__INT_STRING_STRING) (marshal_data ? marshal_data : cc->callback);
222
g_value_get_int (param_values + 1),
223
(char*) g_value_get_string (param_values + 2),
224
(char*) g_value_get_string (param_values + 3),
228
static void _cd_cclosure_marshal_VOID__INT_STRING (GClosure *closure,
229
GValue *return_value G_GNUC_UNUSED,
230
guint n_param_values,
231
const GValue *param_values,
232
gpointer invocation_hint G_GNUC_UNUSED,
233
gpointer marshal_data)
235
//cd_debug ("=== %s ()", __func__);
236
typedef void (*GMarshalFunc_VOID__INT_STRING) (
241
register GMarshalFunc_VOID__INT_STRING callback;
242
register GCClosure *cc = (GCClosure*) closure;
243
register gpointer data1, data2;
244
g_return_if_fail (n_param_values == 3); // return_value est NULL ici, car la callback ne renvoit rien.
246
if (G_CCLOSURE_SWAP_DATA (closure))
248
data1 = closure->data;
249
data2 = g_value_peek_pointer (param_values + 0);
253
data1 = g_value_peek_pointer (param_values + 0);
254
data2 = closure->data;
256
callback = (GMarshalFunc_VOID__INT_STRING) (marshal_data ? marshal_data : cc->callback);
259
g_value_get_int (param_values + 1),
260
(char*) g_value_get_string (param_values + 2),
268
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,
269
#if (INDICATOR_OLD_NAMES == 0) // Natty
270
const gchar *cAccessbleDesc, // WTF is this new param ??
271
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
272
const gchar *cHint, // <irony> is this a hint to work around a clumsy API ? </irony>
273
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
278
GldiModuleInstance *myApplet)
281
cd_debug ("=== %s (%s, %s, %s, %s, %d)", __func__, cAddress, cObjectPath, cIconName, cIconThemePath, iPosition);
282
#if (INDICATOR_OLD_NAMES == 0) // Natty
283
cd_debug (" %s", cAccessbleDesc);
284
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
285
cd_debug (" %s", cHint);
286
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
287
cd_debug (" %s", cTitle);
292
// position +1 for items placed after this one.
293
CDStatusNotifierItem *pItem;
295
for (it = myData.pItems; it != NULL; it = it->next)
298
if (pItem->iPosition >= iPosition)
301
cd_debug ("=== %s -> %d -> %d", pItem->cId, pItem->iPosition-1, pItem->iPosition);
305
cd_satus_notifier_add_new_item_with_default (cAddress, cObjectPath, iPosition,
306
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
307
cIconName ? cIconName : cHint,
312
#if (INDICATOR_OLD_NAMES == 0)
313
cAccessbleDesc && *cAccessbleDesc != '\0' ? cAccessbleDesc :
314
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
315
cTitle && *cTitle != '\0' ? cTitle :
324
static void on_removed_application (DBusGProxy *proxy_watcher, gint iPosition, GldiModuleInstance *myApplet)
327
cd_debug ("=== %s (%d)", __func__, iPosition);
329
cd_satus_notifier_remove_item (NULL, iPosition);
331
// position -1 for items placed after this one.
332
CDStatusNotifierItem *pItem;
334
for (it = myData.pItems; it != NULL; it = it->next)
337
if (pItem->iPosition >= iPosition)
340
cd_debug ("=== %s -> %d -> %d", pItem->cId, pItem->iPosition+1, pItem->iPosition);
347
static void on_application_icon_changed (DBusGProxy *proxy_watcher, gint iPosition, const gchar *cIconName, const gchar *cIconDesc, GldiModuleInstance *myApplet)
350
cd_debug ("=== %s (%d, %s, %s)", __func__, iPosition, cIconName, cIconDesc);
352
CDStatusNotifierItem *pItem = cd_satus_notifier_find_item_from_position (iPosition);
353
g_return_if_fail (pItem != NULL);
355
if (g_strcmp0 (pItem->cIconName, cIconName) == 0) // discard useless updates (skype...)
357
g_free (pItem->cIconName);
358
pItem->cIconName = g_strdup (cIconName);
359
g_free (pItem->cAccessibleDesc);
360
pItem->cAccessibleDesc = g_strdup (cIconDesc);
362
if (pItem->iStatus != CD_STATUS_NEEDS_ATTENTION)
364
cd_satus_notifier_update_item_image (pItem);
370
static void on_application_icon_theme_path_changed (DBusGProxy *proxy_watcher, gint iPosition, const gchar *cIconThemePath, GldiModuleInstance *myApplet)
373
cd_debug ("=== %s (%d, %s)", __func__, iPosition, cIconThemePath);
375
CDStatusNotifierItem *pItem = cd_satus_notifier_find_item_from_position (iPosition);
376
g_return_if_fail (pItem != NULL);
378
if (g_strcmp0 (cIconThemePath, pItem->cIconThemePath) != 0)
380
if (pItem->cIconThemePath != NULL) // if the item previously provided a theme, remove it first.
381
cd_satus_notifier_remove_theme_path (pItem->cIconThemePath);
382
g_free (pItem->cIconThemePath);
383
pItem->cIconThemePath = g_strdup (cIconThemePath);
385
cd_satus_notifier_add_theme_path (cIconThemePath); // and add the new one.
387
if (pItem->cIconName != NULL)
389
cd_satus_notifier_update_item_image (pItem);
395
static void on_application_label_changed (DBusGProxy *proxy_watcher, gint iPosition, const gchar *cLabel, const gchar *cLabelGuide, GldiModuleInstance *myApplet)
398
cd_debug ("=== %s (%d, %s, %s)", __func__, iPosition, cLabel, cLabelGuide);
400
CDStatusNotifierItem *pItem = cd_satus_notifier_find_item_from_position (iPosition);
401
g_return_if_fail (pItem != NULL);
403
g_free (pItem->cLabel);
404
pItem->cLabel = g_strdup (cLabel);
405
g_free (pItem->cLabelGuide);
406
pItem->cLabelGuide = g_strdup (cLabelGuide);
411
static void on_application_title_changed (DBusGProxy *proxy_watcher, gint iPosition, const gchar *cTitle, GldiModuleInstance *myApplet)
414
cd_debug ("=== %s (%d, %s)", __func__, iPosition, cTitle);
416
CDStatusNotifierItem *pItem = cd_satus_notifier_find_item_from_position (iPosition);
417
g_return_if_fail (pItem != NULL);
421
g_free (pItem->cTitle);
422
pItem->cTitle = g_strdup (cTitle);
432
static void _on_get_applications_from_service (DBusGProxy *proxy, DBusGProxyCall *call_id, GldiModuleInstance *myApplet)
434
cd_debug ("=== %s ()", __func__);
437
//\______________________ get the applications list from the service.
438
GPtrArray *pApplications = NULL;
439
GError *erreur = NULL;
440
GType g_type_ptrarray = dbus_g_type_get_collection ("GPtrArray",
441
dbus_g_type_get_struct("GValueArray",
442
G_TYPE_STRING, // iconname
443
G_TYPE_INT, // position
444
G_TYPE_STRING, // dbusaddress
445
DBUS_TYPE_G_OBJECT_PATH, // dbusobject
446
G_TYPE_STRING, // iconpath
447
G_TYPE_STRING, // label
448
G_TYPE_STRING, // labelguide
449
#if (INDICATOR_OLD_NAMES == 0) // Natty
450
G_TYPE_STRING, // accessibledesc
451
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
452
G_TYPE_STRING, // hint
453
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
454
G_TYPE_STRING, // title
459
dbus_g_proxy_end_call (proxy,
462
g_type_ptrarray, &pApplications,
466
cd_debug ("=== couldn't get applications in the systray (%s)", erreur->message);
467
g_error_free (erreur);
470
if (pApplications == NULL)
473
//\______________________ build each items.
474
cd_debug ("=== got %d applications", pApplications->len);
478
CDStatusNotifierItem *pItem = NULL;
479
//cd_debug ("=== %d apps in the systray", pApplications->len);
480
for (i = 0; i < pApplications->len; i ++)
482
// get the properties of the item
483
cd_debug ("=== %d) %p", i, pApplications->pdata[i]);
484
va = pApplications->pdata[i];
488
const gchar *cIconName = NULL;
490
const gchar *cAddress = NULL;
491
const gchar *cObjectPath = NULL;
492
const gchar *cIconThemePath = NULL;
493
const gchar *cLabel = NULL;
494
const gchar *cLabelGuide = NULL;
495
const gchar *cAccessibleDesc = NULL; // natty
496
// const gchar *cHint = NULL; // oneiric
497
const gchar *cTitle = NULL; // precise
499
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 ...
500
if (v && G_VALUE_HOLDS_STRING (v))
501
cIconName = g_value_get_string (v);
503
v = g_value_array_get_nth (va, 1);
504
if (v && G_VALUE_HOLDS_INT (v))
505
iPosition = g_value_get_int (v);
507
v = g_value_array_get_nth (va, 2);
508
if (v && G_VALUE_HOLDS_STRING (v))
509
cAddress = g_value_get_string (v);
511
v = g_value_array_get_nth (va, 3);
512
if (v && G_VALUE_HOLDS (v, DBUS_TYPE_G_OBJECT_PATH))
513
cObjectPath = (gchar*)g_value_get_boxed (v);
515
v = g_value_array_get_nth (va, 4);
516
if (v && G_VALUE_HOLDS_STRING (v))
517
cIconThemePath = g_value_get_string (v);
519
v = g_value_array_get_nth (va, 5);
520
if (v && G_VALUE_HOLDS_STRING (v))
521
cLabel = g_value_get_string (v);
523
v = g_value_array_get_nth (va, 6);
524
if (v && G_VALUE_HOLDS_STRING (v))
525
cLabelGuide = g_value_get_string (v);
527
#if (INDICATOR_OLD_NAMES == 0)
528
v = g_value_array_get_nth (va, 7);
529
if (v && G_VALUE_HOLDS_STRING (v))
530
cAccessibleDesc = g_value_get_string (v);
532
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
533
v = g_value_array_get_nth (va, 9);
534
if (v && G_VALUE_HOLDS_STRING (v))
535
cTitle = g_value_get_string (v);
539
cd_debug ("=== + item {%s ; %d ; %s ; %s ; %s ; %s ; %s ; %s ; %s}",
553
// 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).
555
for (it = myData.pItems; it != NULL; it = it->next)
558
if (strcmp (cAddress, pItem->cService) == 0) // pItem->cService is never NULL
560
cd_warning ("Duplicated item: %s (%s)", cIconName, cAddress);
563
if (iPosition != -1 && pItem->iPosition == iPosition)
565
cd_warning ("Possible duplicated item: %s/%s/%d , %s/%s/%d)", cIconName, cAddress, iPosition, pItem->cIconName, pItem->cService, pItem->iPosition);
569
// make a new item based on these properties.
570
pItem = cd_satus_notifier_create_item (cAddress, cObjectPath);
573
if (pItem->iPosition == -1)
574
pItem->iPosition = iPosition;
575
if (pItem->cTitle == NULL && pItem->cLabel == NULL && pItem->cAccessibleDesc == NULL)
576
pItem->cLabel = g_strdup (cAccessibleDesc && *cAccessibleDesc != '\0' ? cAccessibleDesc :
577
cLabel && *cLabel != '\0' ? cLabel :
578
cTitle && *cTitle != '\0' ? cTitle :
579
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.
582
if (myConfig.bCompactMode)
584
cd_satus_notifier_reload_compact_mode ();
588
cd_satus_notifier_load_icons_from_items ();
591
g_ptr_array_free (pApplications, TRUE);
595
void cd_satus_notifier_get_items_from_ias (void)
597
if (! myData.bIASWatched)
599
cd_debug ("=== %s ()", __func__);
601
g_return_if_fail (myData.pProxyIndicatorApplicationService == NULL);
603
myData.pProxyIndicatorApplicationService = cairo_dock_create_new_session_proxy (
604
CD_INDICATOR_APPLICATION_ADDR,
605
CD_INDICATOR_APPLICATION_OBJ,
606
CD_INDICATOR_APPLICATION_IFACE);
608
// get the current items
609
dbus_g_proxy_begin_call (myData.pProxyIndicatorApplicationService,
611
(DBusGProxyCallNotify)_on_get_applications_from_service,
613
(GDestroyNotify) NULL,
616
// connect to the signals to keep the list of items up-to-date.
617
#if (INDICATOR_OLD_NAMES != 0) // Maverick
618
dbus_g_object_register_marshaller(_cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING,
619
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);
621
dbus_g_object_register_marshaller(
622
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
623
_cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING_STRING,
624
#elif (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
625
_cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING_STRING,
627
_cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING,
629
G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING,
630
DBUS_TYPE_G_OBJECT_PATH, // dbusobject
631
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
632
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
634
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
640
dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationAdded",
641
G_TYPE_STRING, // iconname
642
G_TYPE_INT, // position
643
G_TYPE_STRING, // dbusaddress
644
#if (INDICATOR_OLD_NAMES != 0) // Maverick
645
G_TYPE_STRING, // dbusobject
647
DBUS_TYPE_G_OBJECT_PATH, // dbusobject
649
G_TYPE_STRING, // iconpath
650
G_TYPE_STRING, // label
651
G_TYPE_STRING, // labelguide
652
#if (INDICATOR_OLD_NAMES == 0) // Natty
653
G_TYPE_STRING, // accessibledesc
654
#if (INDICATOR_APPLICATIONADDED_HAS_HINT == 1)
655
G_TYPE_STRING, // hint => only with indicator-0.4 (Oneiric)
656
#if (INDICATOR_APPLICATIONADDED_HAS_TITLE == 1)
657
G_TYPE_STRING, // title => only with indicator-0.4.90 (Precise)
662
dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationAdded",
663
G_CALLBACK(on_new_application), myApplet, NULL);
665
dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationRemoved",
666
G_TYPE_INT, // position
668
dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationRemoved",
669
G_CALLBACK(on_removed_application), myApplet, NULL);
671
// we add the following signals because some program don't support the StatusNotifier API (skype, once again...) but only the IAS one.
672
dbus_g_object_register_marshaller(_cd_cclosure_marshal_VOID__INT_STRING_STRING,
673
G_TYPE_NONE, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
674
dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationIconChanged",
675
G_TYPE_INT, // position
676
G_TYPE_STRING, // icon name
677
G_TYPE_STRING, // icon desc (?)
679
dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationIconChanged",
680
G_CALLBACK(on_application_icon_changed), myApplet, NULL);
682
dbus_g_object_register_marshaller(_cd_cclosure_marshal_VOID__INT_STRING,
683
G_TYPE_NONE, G_TYPE_INT, G_TYPE_STRING, G_TYPE_INVALID);
684
dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationIconThemePathChanged",
685
G_TYPE_INT, // position
686
G_TYPE_STRING, // icon name
687
G_TYPE_STRING, // icon desc (Note: I'm quite sure they will eventually remove it ...)
689
dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationIconThemePathChanged",
690
G_CALLBACK(on_application_icon_theme_path_changed), myApplet, NULL);
692
dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationLabelChanged",
693
G_TYPE_INT, // position
694
G_TYPE_STRING, // label
695
G_TYPE_STRING, // guide
697
dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationLabelChanged",
698
G_CALLBACK(on_application_label_changed), myApplet, NULL);
700
dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationTitleChanged",
701
G_TYPE_INT, // position
702
G_TYPE_STRING, // title
704
dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationTitleChanged",
705
G_CALLBACK(on_application_title_changed), myApplet, NULL);
712
static void _on_start_service (DBusGProxy *proxy, guint status, GError *error, gpointer data)
714
// if service has not started, then we'll assume we don't need it (eg.: KDE)
715
if (status != DBUS_START_REPLY_SUCCESS && status != DBUS_START_REPLY_ALREADY_RUNNING) // service is not started.
717
if (error != NULL) // couldn't start the service
718
cd_debug ("=== Unable to start the indicator service (%s), assuming we don't need it", error->message);
720
cd_debug ("=== Unable to start the indicator service (got status %d), assuming we don't need it", status);
721
myData.bNoIAS = TRUE;
722
cd_satus_notifier_launch_our_watcher ();
725
cd_debug ("=== Indicator Service has started");
727
static void _on_watch_service (DBusGProxy *proxy, DBusGProxyCall *call, gpointer data)
730
GError *error = NULL;
731
guint service_api_version=0, this_service_version=0;
732
dbus_g_proxy_end_call (proxy, call, &error,
733
G_TYPE_UINT, &service_api_version,
734
G_TYPE_UINT, &this_service_version,
738
cd_debug ("Unable to watch the service: %s", error->message);
739
g_error_free (error);
740
/* Note: Not a big deal, let start getting items: it seems that the
741
* service is no longer available and *no longer needed* on Ubuntu 14.04
742
* https://bazaar.launchpad.net/~indicator-applet-developers/indicator-application/trunk.14.04/revision/246
743
* https://bugs.launchpad.net/bugs/1303731
744
* TODO: remove this ugly hack...
746
#if (INDICATOR_OLD_NAMES == 0)
747
service_api_version = 1;
750
cd_debug ("=== got indicator service (API: %d, service: %d, broken watcher: %d)", service_api_version, this_service_version, myData.bBrokenWatcher);
752
if (service_api_version > 0) /// shouldn't the 2 versions be equal ?...
754
myData.bIASWatched = TRUE; // now we're friend with the IAS
756
if (myData.bBrokenWatcher) // if the watcher is not our friend, let's ask the IAS the current items.
758
cd_satus_notifier_get_items_from_ias ();
763
static void _on_ias_owner_changed (const gchar *cName, gboolean bOwned, gpointer data)
766
cd_debug ("=== Indicator Applications Service is on the bus (%d)", bOwned);
770
myData.bNoIAS = FALSE;
771
// set up a proxy to the Service
772
myData.pProxyIndicatorService = cairo_dock_create_new_session_proxy (
773
CD_INDICATOR_APPLICATION_ADDR,
774
CD_INDICATOR_SERVICE_OBJECT,
775
CD_INDICATOR_SERVICE_INTERFACE);
778
cd_debug ("=== watch it");
779
dbus_g_proxy_begin_call (myData.pProxyIndicatorService,
781
(DBusGProxyCallNotify)_on_watch_service,
783
(GDestroyNotify) NULL,
786
else // no more IAS on the bus.
788
g_object_unref (myData.pProxyIndicatorService);
789
myData.pProxyIndicatorService = NULL;
791
g_object_unref (myData.pProxyIndicatorApplicationService);
792
myData.pProxyIndicatorApplicationService = NULL;
794
myData.bIASWatched = FALSE;
796
myData.bNoIAS = TRUE;
797
cd_satus_notifier_launch_our_watcher ();
801
static void _on_detect_ias (gboolean bPresent, gpointer data)
804
cd_debug ("=== Indicator Applications Service is present: %d", bPresent);
805
s_pDetectIASCall = NULL;
806
// if present, set up proxy, else try to start the service.
809
_on_ias_owner_changed (CD_INDICATOR_APPLICATION_ADDR, TRUE, NULL);
811
else // not present, maybe the service is not started => try starting it.
813
cd_debug ("=== try to start the Indicator Service...");
814
DBusGProxy *dbus_proxy = cairo_dock_get_main_proxy ();
815
org_freedesktop_DBus_start_service_by_name_async (dbus_proxy,
816
CD_INDICATOR_APPLICATION_ADDR,
821
// watch whenever the Service goes up or down.
822
cairo_dock_watch_dbus_name_owner (CD_INDICATOR_APPLICATION_ADDR,
823
(CairoDockDbusNameOwnerChangedFunc) _on_ias_owner_changed,
829
void cd_satus_notifier_detect_ias (void)
831
s_pDetectIASCall = cairo_dock_dbus_detect_application_async (CD_INDICATOR_APPLICATION_ADDR,
832
(CairoDockOnAppliPresentOnDbus) _on_detect_ias,
837
void cd_satus_notifier_unregister_from_ias (void)
839
if (myData.pProxyIndicatorApplicationService != NULL)
841
g_object_unref (myData.pProxyIndicatorApplicationService);
842
g_object_unref (myData.pProxyIndicatorService);
845
if (s_pDetectIASCall != NULL)
847
DBusGProxy *pProxy = cairo_dock_get_main_proxy ();
848
dbus_g_proxy_cancel_call (pProxy, s_pDetectIASCall);
849
s_pDetectIASCall = NULL;
852
cairo_dock_stop_watching_dbus_name_owner (CD_INDICATOR_APPLICATION_ADDR,
853
(CairoDockDbusNameOwnerChangedFunc) _on_ias_owner_changed);