~cairo-dock-team/ubuntu/precise/cairo-dock-plug-ins/3.0.0.0rc1

« back to all changes in this revision

Viewing changes to Status-Notifier/src/applet-host.c

  • Committer: Matthieu Baerts
  • Date: 2011-08-09 19:51:45 UTC
  • mfrom: (1.1.12 upstream)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: matttbe@gmail.com-20110809195145-6t55jtykipujuyn5
* New upstream release. (LP: #823514)
* Upstream (short) ChangeLog:
 - The Power-Manager applet has been rewritten to work on any plateform.
 - Compiz-icon applet has been replaced by Composite-Manager.
 - Improved integration in the XFCE, LXDE and GNOME3 desktop.
 - Logout is now working even if there is no/an unknow session manager.
 - Several new DBus methods lets you interact on the dock more easily.
 - Added the possibility to shutdown/logout with GMenu.
 - Improved Status-Notifier and added its own watcher.
 - Added a new applet: Impulse (still need testing).
 - Fixed a few bugs as usual.
* debian/patches:
 - Removed all patches (they was already unapplied).
* debian/copyright:
 - Updated with new files/directory.
* debian/cairo-dock-plug-ins.install:
 - Added status-notifier-watcher used by Status-Notifier applet.
* debian/control:
 - Updated the version of cairo-dock-[core;data;dev].
 - Bump Standard-Version to 3.9.2.
 - Added fftw3, pulse (Impulse) and upower-glib (Logout)
    as new dependences for the build process.
 - Added indicator-[me;messages] as new recommendations
    for cairo-dock-plug-ins (needed for [Me;Messaging]Menu applets).
 - Removed gawk from the build dependences list (no longer needed).
* cairo-dock-plug-ins package needs to be recompiled (LP: #811579)

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include "applet-item.h"
27
27
#include "applet-draw.h"
28
28
#include "applet-host.h"
 
29
#include "applet-host-kde.h"
 
30
#include "applet-host-ias.h"
29
31
 
30
32
// our address basename
31
33
#define CD_STATUS_NOTIFIER_HOST_ADDR "org.kde.StatusNotifierHost"
32
34
 
33
 
// KDE watcher (old names)
34
 
//~ #define CD_STATUS_NOTIFIER_WATCHER_ADDR2 "org.kde.NotificationItemWatcher"
35
 
//~ #define CD_STATUS_NOTIFIER_WATCHER_OBJ2 "/NotificationItemWatcher"
36
 
//~ #define CD_STATUS_NOTIFIER_WATCHER_IFACE2 "org.kde.NotificationItemWatcher"
37
 
 
38
 
// KDE watcher
39
 
#define CD_STATUS_NOTIFIER_WATCHER_ADDR "org.kde.StatusNotifierWatcher"
40
 
#define CD_STATUS_NOTIFIER_WATCHER_OBJ "/StatusNotifierWatcher"
41
 
#define CD_STATUS_NOTIFIER_WATCHER_IFACE "org.kde.StatusNotifierWatcher"
42
 
 
43
 
// Ubuntu sort-of-high-level-Watcher (new or old address)
44
 
#if (INDICATOR_OLD_NAMES == 0)  // Natty
45
 
#define CD_INDICATOR_APPLICATION_ADDR "com.canonical.indicator.application"
46
 
#define CD_INDICATOR_APPLICATION_OBJ "/com/canonical/indicator/application/service"
47
 
#define CD_INDICATOR_APPLICATION_IFACE "com.canonical.indicator.application.service"
48
 
#else
49
 
#define CD_INDICATOR_APPLICATION_ADDR "org.ayatana.indicator.application"
50
 
#define CD_INDICATOR_APPLICATION_OBJ "/org/ayatana/indicator/application/service"
51
 
#define CD_INDICATOR_APPLICATION_IFACE "org.ayatana.indicator.application.service"
52
 
#endif
53
 
 
54
 
// Ubuntu Indicator Service
55
 
#define  CD_INDICATOR_SERVICE_INTERFACE "org.ayatana.indicator.service"
56
 
#define  CD_INDICATOR_SERVICE_OBJECT "/org/ayatana/indicator/service"
57
 
 
58
 
static DBusGProxyCall *s_pDetectWatcherCall = NULL;
59
 
static DBusGProxyCall *s_pDetectIASCall = NULL;
60
 
 
61
 
#if (INDICATOR_OLD_NAMES != 0)  // Maverick
62
 
static void _cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING (GClosure *closure,
63
 
        GValue *return_value G_GNUC_UNUSED,
64
 
        guint n_param_values,
65
 
        const GValue *param_values,
66
 
        gpointer invocation_hint G_GNUC_UNUSED,
67
 
        gpointer marshal_data)
68
 
{
69
 
        //cd_debug ("=== %s ()\n", __func__);
70
 
        typedef void (*GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING) (
71
 
                gpointer     data1,
72
 
                gchar      *arg_1,
73
 
                gint        arg_2,
74
 
                gchar      *arg_3,
75
 
                gchar      *arg_4,
76
 
                gchar      *arg_5,
77
 
                gchar      *arg_6,
78
 
                gchar      *arg_7,
79
 
                gpointer     data2);
80
 
        register GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING callback;
81
 
        register GCClosure *cc = (GCClosure*) closure;
82
 
        register gpointer data1, data2;
83
 
        g_return_if_fail (n_param_values == 8);  // return_value est NULL ici, car la callback ne renvoit rien.
84
 
 
85
 
        if (G_CCLOSURE_SWAP_DATA (closure))
86
 
        {
87
 
                data1 = closure->data;
88
 
                data2 = g_value_peek_pointer (param_values + 0);
89
 
        }
90
 
        else
91
 
        {
92
 
                data1 = g_value_peek_pointer (param_values + 0);
93
 
                data2 = closure->data;
94
 
        }
95
 
        callback = (GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING) (marshal_data ? marshal_data : cc->callback);
96
 
 
97
 
        callback (data1,
98
 
                (char*) g_value_get_string (param_values + 1),
99
 
                g_value_get_int (param_values + 2),
100
 
                (char*) g_value_get_string (param_values + 3),
101
 
                (char*) g_value_get_string (param_values + 4),
102
 
                (char*) g_value_get_string (param_values + 5),
103
 
                (char*) g_value_get_string (param_values + 6),
104
 
                (char*) g_value_get_string (param_values + 7),
105
 
                data2);
106
 
}
107
 
#else  // Natty
108
 
static void _cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING (GClosure *closure,
109
 
        GValue *return_value G_GNUC_UNUSED,
110
 
        guint n_param_values,
111
 
        const GValue *param_values,
112
 
        gpointer invocation_hint G_GNUC_UNUSED,
113
 
        gpointer marshal_data)
114
 
{
115
 
        //cd_debug ("=== %s ()\n", __func__);
116
 
        typedef void (*GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING) (
117
 
                gpointer     data1,
118
 
                gchar      *arg_1,
119
 
                gint        arg_2,
120
 
                gchar      *arg_3,
121
 
                gchar      *arg_4,
122
 
                gchar      *arg_5,
123
 
                gchar      *arg_6,
124
 
                gchar      *arg_7,
125
 
                gchar      *arg_8,
126
 
                gpointer     data2);
127
 
        register GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING callback;
128
 
        register GCClosure *cc = (GCClosure*) closure;
129
 
        register gpointer data1, data2;
130
 
        g_return_if_fail (n_param_values == 9);  // return_value est NULL ici, car la callback ne renvoit rien.
131
 
 
132
 
        if (G_CCLOSURE_SWAP_DATA (closure))
133
 
        {
134
 
                data1 = closure->data;
135
 
                data2 = g_value_peek_pointer (param_values + 0);
136
 
        }
137
 
        else
138
 
        {
139
 
                data1 = g_value_peek_pointer (param_values + 0);
140
 
                data2 = closure->data;
141
 
        }
142
 
        callback = (GMarshalFunc_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING) (marshal_data ? marshal_data : cc->callback);
143
 
 
144
 
        callback (data1,
145
 
                (char*) g_value_get_string (param_values + 1),
146
 
                g_value_get_int (param_values + 2),
147
 
                (char*) g_value_get_string (param_values + 3),
148
 
                (char*) g_value_get_boxed (param_values + 4),
149
 
                (char*) g_value_get_string (param_values + 5),
150
 
                (char*) g_value_get_string (param_values + 6),
151
 
                (char*) g_value_get_string (param_values + 7),
152
 
                (char*) g_value_get_string (param_values + 8),
153
 
                data2);
154
 
}
155
 
#endif
156
35
 
157
36
static CDStatusNotifierItem * _cd_satus_notifier_find_item_from_service (const gchar *cService)
158
37
{
182
61
}
183
62
 
184
63
 
185
 
  ///////////////////////////////
186
 
 /// Signals add/remove item ///
187
 
///////////////////////////////
 
64
  ///////////////////////
 
65
 /// Add/remove item ///
 
66
///////////////////////
188
67
 
189
 
static inline void _add_new_item (const gchar *cService, const gchar *cObjectPath, int iPosition)
 
68
void cd_satus_notifier_add_new_item (const gchar *cService, const gchar *cObjectPath, int iPosition)
190
69
{
191
70
        CDStatusNotifierItem *pItem = _cd_satus_notifier_find_item_from_service (cService);
192
71
        g_return_if_fail (pItem == NULL);  // on evite d'ajouter 2 fois le meme service.
213
92
        }
214
93
}
215
94
 
216
 
static inline void _remove_item (const gchar *cService, int iPosition)
 
95
void cd_satus_notifier_remove_item (const gchar *cService, int iPosition)
217
96
{
218
97
        CDStatusNotifierItem *pItem = (cService ? _cd_satus_notifier_find_item_from_service (cService) : _cd_satus_notifier_find_item_from_position (iPosition));
219
98
        g_return_if_fail (pItem != NULL);
236
115
        cd_free_item (pItem);
237
116
}
238
117
 
239
 
static void on_new_item (DBusGProxy *proxy_watcher, const gchar *cService, CairoDockModuleInstance *myApplet)
240
 
{
241
 
        CD_APPLET_ENTER;
242
 
        cd_debug ("=== %s (%s)", __func__, cService);
243
 
        
244
 
        _add_new_item (cService, NULL, -1);  // on suppose que leur indicator-application ne mettra jamais -1 comme position.
245
 
        
246
 
        CD_APPLET_LEAVE ();
247
 
}
248
 
 
249
 
static void on_removed_item (DBusGProxy *proxy_watcher, const gchar *cService, CairoDockModuleInstance *myApplet)
250
 
{
251
 
        CD_APPLET_ENTER;
252
 
        cd_debug ("=== %s (%s)", __func__, cService);
253
 
        
254
 
        gchar *str = strchr (cService, '/');
255
 
        if (str)
256
 
                *str = '\0';
257
 
        
258
 
        _remove_item (cService, -1);
259
 
        
260
 
        CD_APPLET_LEAVE ();
261
 
}
262
 
 
263
 
static void on_new_application (DBusGProxy *proxy_watcher, const gchar *cIconName, gint iPosition, const gchar *cAdress, const gchar *cObjectPath, const gchar *cIconThemePath, const gchar *cLabel, const gchar *cLabelGuide,
264
 
#if (INDICATOR_OLD_NAMES == 0)  // Natty
265
 
const gchar *cAccessbleDesc,  // WTF is this new param ??
266
 
#endif
267
 
CairoDockModuleInstance *myApplet)
268
 
{
269
 
        CD_APPLET_ENTER;
270
 
        cd_debug ("=== %s (%s, %s, %s, %s, %d)", __func__, cAdress, cObjectPath, cIconName, cIconThemePath, iPosition);
271
 
        #if (INDICATOR_OLD_NAMES == 0)  // Natty
272
 
        cd_debug ("    %s", cAccessbleDesc);
273
 
        #endif
274
 
        /// position +1 for items placed after this one...
275
 
        CDStatusNotifierItem *pItem;
276
 
        GList *it;
277
 
        for (it = myData.pItems; it != NULL; it = it->next)
278
 
        {
279
 
                pItem = it->data;
280
 
                if (pItem->iPosition >= iPosition)
281
 
                {
282
 
                        pItem->iPosition ++;
283
 
                        cd_debug ("===  %s -> %d -> %d", pItem->cId, pItem->iPosition-1, pItem->iPosition);
284
 
                }
285
 
        }
286
 
        
287
 
        _add_new_item (cAdress, cObjectPath, iPosition);
288
 
        
289
 
        CD_APPLET_LEAVE ();
290
 
}
291
 
 
292
 
static void on_removed_application (DBusGProxy *proxy_watcher, gint iPosition, CairoDockModuleInstance *myApplet)
293
 
{
294
 
        CD_APPLET_ENTER;
295
 
        cd_debug ("=== %s (%d)", __func__, iPosition);
296
 
        
297
 
        _remove_item (NULL, iPosition);
298
 
        
299
 
        /// position -1 for items placed after this one...
300
 
        CDStatusNotifierItem *pItem;
301
 
        GList *it;
302
 
        for (it = myData.pItems; it != NULL; it = it->next)
303
 
        {
304
 
                pItem = it->data;
305
 
                if (pItem->iPosition >= iPosition)
306
 
                {
307
 
                        pItem->iPosition --;
308
 
                        cd_debug ("===  %s -> %d -> %d", pItem->cId, pItem->iPosition+1, pItem->iPosition);
309
 
                }
310
 
        }
311
 
        
312
 
        CD_APPLET_LEAVE ();
313
 
}
314
 
 
315
 
 
316
 
  /////////////////
317
 
 /// Get Items ///
318
 
/////////////////
319
 
 
320
 
static void _on_get_applications_from_service (DBusGProxy *proxy, DBusGProxyCall *call_id, CairoDockModuleInstance *myApplet)
321
 
{
322
 
        cd_debug ("=== %s ()", __func__);
323
 
        CD_APPLET_ENTER;
324
 
        
325
 
        //\______________________ get the applications list from the service.
326
 
        GPtrArray *pApplications = NULL;
327
 
        GError *erreur = NULL;
328
 
        GType g_type_ptrarray = g_type_ptrarray = dbus_g_type_get_collection ("GPtrArray",
329
 
                dbus_g_type_get_struct("GValueArray",
330
 
                        G_TYPE_STRING,  // iconname
331
 
                        G_TYPE_INT,  // position
332
 
                        G_TYPE_STRING,  // dbusaddress
333
 
                        DBUS_TYPE_G_OBJECT_PATH,  // dbusobject
334
 
                        G_TYPE_STRING,  // iconpath
335
 
                        G_TYPE_STRING,  // label
336
 
                        G_TYPE_STRING,  // labelguide
337
 
                        G_TYPE_INVALID));
338
 
        gboolean bSuccess = dbus_g_proxy_end_call (proxy,
339
 
                call_id,
340
 
                &erreur,
341
 
                g_type_ptrarray, &pApplications,
342
 
                G_TYPE_INVALID);
343
 
        if (erreur != NULL)
344
 
        {
345
 
                cd_debug ("=== couldn't get applications in the systray (%s)", erreur->message);
346
 
                g_error_free (erreur);
347
 
                erreur = NULL;
348
 
        }
349
 
        if (pApplications == NULL)
350
 
                CD_APPLET_LEAVE ();
351
 
        
352
 
        //\______________________ build each items.
353
 
        cd_debug ("=== got %d aplications", pApplications->len);
354
 
        guint i, j;
355
 
        GValueArray *va;
356
 
        GValue *v;
357
 
        CDStatusNotifierItem *pItem=NULL;
358
 
        //cd_debug ("=== %d apps in the systray", pApplications->len);
359
 
        for (i = 0; i < pApplications->len; i ++)
360
 
        {
361
 
                cd_debug ("=== %d) %p", i, pApplications->pdata[i]);
362
 
                va = pApplications->pdata[i];
363
 
                if (! va)
364
 
                        continue;
365
 
                
366
 
                const gchar *cIconName = NULL;
367
 
                gint iPosition = -1;
368
 
                const gchar *cAdress = NULL;
369
 
                const gchar *cObjectPath = NULL;
370
 
                const gchar *cIconThemePath = NULL;
371
 
                const gchar *cLabel = NULL;
372
 
                const gchar *cLabelGuide = NULL;
373
 
                
374
 
                v = g_value_array_get_nth (va, 0);
375
 
                if (v && G_VALUE_HOLDS_STRING (v))
376
 
                        cIconName = g_value_get_string (v);
377
 
                
378
 
                v = g_value_array_get_nth (va, 1);
379
 
                if (v && G_VALUE_HOLDS_INT (v))
380
 
                        iPosition = g_value_get_int (v);
381
 
                
382
 
                v = g_value_array_get_nth (va, 2);
383
 
                if (v && G_VALUE_HOLDS_STRING (v))
384
 
                        cAdress = g_value_get_string (v);
385
 
                
386
 
                v = g_value_array_get_nth (va, 3);
387
 
                if (v && G_VALUE_HOLDS_BOXED (v))
388
 
                        cObjectPath = (gchar*)g_value_get_boxed (v);
389
 
                
390
 
                v = g_value_array_get_nth (va, 4);
391
 
                if (v && G_VALUE_HOLDS_STRING (v))
392
 
                        cIconThemePath = g_value_get_string (v);
393
 
                
394
 
                v = g_value_array_get_nth (va, 5);
395
 
                if (v && G_VALUE_HOLDS_STRING (v))
396
 
                        cLabel = g_value_get_string (v);
397
 
                
398
 
                v = g_value_array_get_nth (va, 6);
399
 
                if (v && G_VALUE_HOLDS_STRING (v))
400
 
                        cLabelGuide = g_value_get_string (v);
401
 
                
402
 
                cd_debug ("===  + item {%s ; %d ; %s ; %s ; %s ; %s ; %s}",
403
 
                        cIconName,
404
 
                        iPosition,
405
 
                        cAdress,
406
 
                        cObjectPath,
407
 
                        cIconThemePath,
408
 
                        cLabel,
409
 
                        cLabelGuide);
410
 
                
411
 
                pItem = cd_satus_notifier_create_item (cAdress, cObjectPath);
412
 
                if (! pItem)
413
 
                        continue;
414
 
                if (pItem->iPosition == -1)
415
 
                        pItem->iPosition = iPosition;
416
 
                if (pItem->cTitle == NULL && pItem->cLabel == NULL)
417
 
                        pItem->cLabel = g_strdup (cLabel && *cLabel != '\0' ? cLabel : pItem->cId);
418
 
                myData.pItems = g_list_prepend (myData.pItems, pItem);
419
 
        }
420
 
        
421
 
        if (myConfig.bCompactMode)
422
 
        {
423
 
                cd_satus_notifier_reload_compact_mode ();
424
 
        }
425
 
        else
426
 
        {
427
 
                cd_satus_notifier_load_icons_from_items ();
428
 
        }
429
 
        
430
 
        g_ptr_array_free (pApplications, TRUE);
431
 
        CD_APPLET_LEAVE ();
432
 
}
433
 
 
434
 
static void _cd_satus_notifier_get_items_from_ias (void)
435
 
{
436
 
        if (! myData.bIASWatched)
437
 
                return;
438
 
        cd_debug ("=== %s ()", __func__);
439
 
        
440
 
        g_return_if_fail (myData.pProxyIndicatorApplicationService == NULL);
441
 
        
442
 
        myData.pProxyIndicatorApplicationService = cairo_dock_create_new_session_proxy (
443
 
                CD_INDICATOR_APPLICATION_ADDR,
444
 
                CD_INDICATOR_APPLICATION_OBJ,
445
 
                CD_INDICATOR_APPLICATION_IFACE);
446
 
        
447
 
        // get the current items
448
 
        dbus_g_proxy_begin_call (myData.pProxyIndicatorApplicationService,
449
 
                "GetApplications",
450
 
                (DBusGProxyCallNotify)_on_get_applications_from_service,
451
 
                myApplet,
452
 
                (GDestroyNotify) NULL,
453
 
                G_TYPE_INVALID);
454
 
        
455
 
        // connect to the signals to keep the list of items up-to-date.
456
 
        #if (INDICATOR_OLD_NAMES != 0)  // Maverick
457
 
        dbus_g_object_register_marshaller(_cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING,
458
 
                        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);
459
 
        #else  // Natty
460
 
        dbus_g_object_register_marshaller(_cd_cclosure_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING_STRING,
461
 
                        G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING,
462
 
                        #if (INDICATOR_OLD_NAMES != 0)  // Maverick
463
 
                        G_TYPE_STRING,  // dbusobject
464
 
                        #else  // Natty
465
 
                        DBUS_TYPE_G_OBJECT_PATH,  // dbusobject
466
 
                        #endif
467
 
                        G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
468
 
        #endif
469
 
        dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationAdded",
470
 
                G_TYPE_STRING,  // iconname
471
 
                G_TYPE_INT,  // position
472
 
                G_TYPE_STRING,  // dbusaddress
473
 
                #if (INDICATOR_OLD_NAMES != 0)  // Maverick
474
 
                G_TYPE_STRING,  // dbusobject
475
 
                #else  // Natty
476
 
                DBUS_TYPE_G_OBJECT_PATH,  // dbusobject
477
 
                #endif
478
 
                G_TYPE_STRING,  // iconpath
479
 
                G_TYPE_STRING,  // label
480
 
                G_TYPE_STRING,  // labelguide
481
 
                #if (INDICATOR_OLD_NAMES == 0)  // Natty
482
 
                G_TYPE_STRING,  // accessibledesc
483
 
                #endif
484
 
                G_TYPE_INVALID);
485
 
        dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationAdded",
486
 
                G_CALLBACK(on_new_application), myApplet, NULL);
487
 
        
488
 
        dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationRemoved",
489
 
                G_TYPE_INT,  // position
490
 
                G_TYPE_INVALID);
491
 
        dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationRemoved",
492
 
                G_CALLBACK(on_removed_application), myApplet, NULL);
493
 
}
494
 
 
495
 
static void _on_get_applications_from_watcher (DBusGProxy *proxy, DBusGProxyCall *call_id, CairoDockModuleInstance *myApplet)
496
 
{
497
 
        cd_debug ("=== %s ()", __func__);
498
 
        CD_APPLET_ENTER;
499
 
        
500
 
        gchar **pApplications = NULL;
501
 
        GError *erreur = NULL;
502
 
        gboolean bSuccess = dbus_g_proxy_end_call (proxy,
503
 
                call_id,
504
 
                &erreur,
505
 
                G_TYPE_STRV, &pApplications,
506
 
                G_TYPE_INVALID);
507
 
        if (erreur != NULL)
508
 
        {
509
 
                cd_debug ("=== couldn't get applications from the watcher (%s)", erreur->message);
510
 
                g_error_free (erreur);
511
 
                erreur = NULL;
512
 
                bSuccess = FALSE;
513
 
        }
514
 
        
515
 
        if (bSuccess)
516
 
        {
517
 
                if (pApplications == NULL)
518
 
                        CD_APPLET_LEAVE ();
519
 
                guint i;
520
 
                CDStatusNotifierItem *pItem;
521
 
                for (i = 0; pApplications[i] != NULL; i ++)
522
 
                {
523
 
                        pItem = cd_satus_notifier_create_item (pApplications[i], NULL);
524
 
                        if (! pItem)
525
 
                                continue;
526
 
                        cd_debug ("===  => + %s", pItem->cTitle);
527
 
                        myData.pItems = g_list_prepend (myData.pItems, pItem);
528
 
                }
529
 
                
530
 
                g_strfreev (pApplications);
531
 
                
532
 
                if (myConfig.bCompactMode)
533
 
                {
534
 
                        cd_satus_notifier_reload_compact_mode ();
535
 
                }
536
 
                else
537
 
                {
538
 
                        cd_satus_notifier_load_icons_from_items ();
539
 
                }
540
 
        }
541
 
        else   // un watcher asocial comme celui d'Ubuntu, on essaye avec l'"indicator-application".
542
 
        {
543
 
                cd_debug ("=== this watcher is not so friendly, let's try the 'application indicator'");
544
 
                myData.bBrokenWatcher = TRUE;
545
 
                if (myData.bIASWatched)
546
 
                        _cd_satus_notifier_get_items_from_ias ();
547
 
        }
548
 
        CD_APPLET_LEAVE ();
549
 
}
550
 
 
551
 
 
552
 
  /////////////////////////////////
553
 
 /// connection to the Watcher ///
554
 
/////////////////////////////////
555
 
 
556
 
static void _on_register_host (DBusGProxy *proxy, DBusGProxyCall *call_id, CairoDockModuleInstance *myApplet)
557
 
{
558
 
        cd_debug ("=== %s ()", __func__);
559
 
        CD_APPLET_ENTER;
560
 
        GError *erreur = NULL;
561
 
        gboolean bSuccess = dbus_g_proxy_end_call (proxy,
562
 
                call_id,
563
 
                &erreur,
564
 
                G_TYPE_INVALID);
565
 
        if (erreur != NULL)
566
 
        {
567
 
                cd_debug ("couldn't register to the Notification Watcher (%s)", erreur->message);
568
 
                g_error_free (erreur);
569
 
                erreur = NULL;
570
 
                bSuccess = FALSE;
571
 
        }
572
 
        
573
 
        if (bSuccess)  // we are friend now, let's ask him the current items.
574
 
        {
575
 
                cd_debug ("=== found a friendly watcher, now ask for the items...");
576
 
                // get the current items
577
 
                myData.pProxyWatcherProps = cairo_dock_create_new_session_proxy (
578
 
                        CD_STATUS_NOTIFIER_WATCHER_ADDR,
579
 
                        CD_STATUS_NOTIFIER_WATCHER_OBJ,
580
 
                        DBUS_INTERFACE_PROPERTIES);
581
 
                dbus_g_proxy_begin_call (myData.pProxyWatcherProps,
582
 
                        "Get",
583
 
                        (DBusGProxyCallNotify)_on_get_applications_from_watcher,
584
 
                        myApplet,
585
 
                        (GDestroyNotify) NULL,
586
 
                        G_TYPE_STRING, CD_STATUS_NOTIFIER_WATCHER_IFACE,
587
 
                        G_TYPE_STRING, "RegisteredStatusNotifierItems",
588
 
                        G_TYPE_INVALID);
589
 
                
590
 
                // connect to the signals to keep the list of items up-to-date.
591
 
                dbus_g_proxy_add_signal(myData.pProxyWatcher, "ServiceRegistered",
592
 
                        G_TYPE_STRING, G_TYPE_INVALID);  // StatusNotifierItemRegistered
593
 
                dbus_g_proxy_connect_signal(myData.pProxyWatcher, "ServiceRegistered",
594
 
                        G_CALLBACK(on_new_item), myApplet, NULL);
595
 
                
596
 
                dbus_g_proxy_add_signal(myData.pProxyWatcher, "ServiceUnregistered",
597
 
                        G_TYPE_STRING, G_TYPE_INVALID);  // StatusNotifierItemUnregistered
598
 
                dbus_g_proxy_connect_signal(myData.pProxyWatcher, "ServiceUnregistered",
599
 
                        G_CALLBACK(on_removed_item), myApplet, NULL);
600
 
        }
601
 
        else  // an asocial watcher like the Ubuntu's one, let's try with the IAS if availeble.
602
 
        {
603
 
                cd_debug ("=== no friendy watcher, let's try the 'application indicator'");
604
 
                myData.bBrokenWatcher = TRUE;
605
 
                if (myData.bIASWatched)
606
 
                        _cd_satus_notifier_get_items_from_ias ();
607
 
        }
608
 
        CD_APPLET_LEAVE ();
609
 
}
610
 
static void _on_watcher_owner_changed (gboolean bOwned, gpointer data)
611
 
{
612
 
        cd_debug ("=== Watcher is on the bus (%d)", bOwned);
613
 
        
614
 
        if (bOwned)
615
 
        {
616
 
                // set up a proxy to the Watcher
617
 
                myData.pProxyWatcher = cairo_dock_create_new_session_proxy (
618
 
                        CD_STATUS_NOTIFIER_WATCHER_ADDR,
619
 
                        CD_STATUS_NOTIFIER_WATCHER_OBJ,
620
 
                        CD_STATUS_NOTIFIER_WATCHER_IFACE);  // whenever it appears on the bus, we'll get it.
621
 
                
622
 
                // and register to it.
623
 
                cd_debug ("=== register to the it");
624
 
                dbus_g_proxy_begin_call (myData.pProxyWatcher, "RegisterNotificationHost",
625
 
                        (DBusGProxyCallNotify)_on_register_host,
626
 
                        myApplet,
627
 
                        (GDestroyNotify) NULL,
628
 
                        G_TYPE_STRING, myData.cHostName,
629
 
                        G_TYPE_INVALID);
630
 
        }
631
 
        else  // no more watcher on the bus.
632
 
        {
633
 
                g_object_unref (myData.pProxyWatcher);
634
 
                myData.pProxyWatcher = NULL;
635
 
                
636
 
                g_object_unref (myData.pProxyWatcherProps);
637
 
                myData.pProxyWatcherProps = NULL;
638
 
                
639
 
                g_list_foreach (myData.pItems, (GFunc) cd_free_item, NULL);
640
 
                g_list_free (myData.pItems);
641
 
                myData.pItems = NULL;
642
 
                
643
 
                g_hash_table_remove_all (myData.pThemePaths);
644
 
                
645
 
                // empty the list of items and redraw.
646
 
                if (! myConfig.bCompactMode)
647
 
                {
648
 
                        CD_APPLET_DELETE_MY_ICONS_LIST;
649
 
                }
650
 
                else
651
 
                {
652
 
                        // draw an 'failed' image to not have an empty icon.
653
 
                        CD_APPLET_SET_IMAGE_ON_MY_ICON (MY_APPLET_SHARE_DATA_DIR"/icon-broken.svg");
654
 
                }
655
 
                myData.bBrokenWatcher = FALSE;
656
 
        }
657
 
}
658
 
static void _on_detect_watcher (gboolean bPresent, gpointer data)
659
 
{
660
 
        cd_debug ("=== Watcher is present: %d", bPresent);
661
 
        s_pDetectWatcherCall = NULL;
662
 
        // if present, set up proxy.
663
 
        if (bPresent)
664
 
        {
665
 
                _on_watcher_owner_changed (TRUE, NULL);
666
 
        }
667
 
        else if (myConfig.bCompactMode)  // in compact mode, draw an 'failed' image to not have an empty icon.
668
 
        {
669
 
                CD_APPLET_SET_IMAGE_ON_MY_ICON (MY_APPLET_SHARE_DATA_DIR"/icon-broken.svg");
670
 
        }
671
 
        
672
 
        // watch whenever the Watcher goes up or down.
673
 
        cairo_dock_watch_dbus_name_owner (CD_STATUS_NOTIFIER_WATCHER_ADDR,
674
 
                (CairoDockDbusNameOwnerChangedFunc) _on_watcher_owner_changed,
675
 
                NULL);
676
 
}
677
 
 
678
 
  /////////////////////////////
679
 
 /// connection to the IAS ///
680
 
/////////////////////////////
681
 
 
682
 
static void _on_start_service (DBusGProxy *proxy, guint status, GError *error, gpointer user_data)
683
 
{
684
 
        // if service has not started, then we'll assume we don't need it (eg.: KDE)
685
 
        if (error != NULL)  // couldn't start the service.
686
 
        {
687
 
                cd_debug ("=== Unable to start the indicator service (%s), assuming we don't need it", error->message);
688
 
                return;
689
 
        }
690
 
        if (status != DBUS_START_REPLY_SUCCESS && status != DBUS_START_REPLY_ALREADY_RUNNING)  // started but wrong status.
691
 
        {
692
 
                cd_debug ("=== Unable to start the indicator service (got status %d), assuming we don't need it", status);
693
 
                return;
694
 
        }
695
 
        cd_debug ("=== Indicator Service has started");
696
 
}
697
 
static void _on_watch_service (DBusGProxy *proxy, DBusGProxyCall *call, gpointer data)
698
 
{
699
 
        GError *error = NULL;
700
 
        guint service_api_version=0, this_service_version=0;
701
 
        dbus_g_proxy_end_call (proxy, call, &error,
702
 
                G_TYPE_UINT, &service_api_version,
703
 
                G_TYPE_UINT, &this_service_version,
704
 
                G_TYPE_INVALID);
705
 
        cd_debug ("=== got indicator service (API: %d, service: %d, broken watcher: %d)", service_api_version, this_service_version, myData.bBrokenWatcher);
706
 
        
707
 
        if (service_api_version > 0)  /// shouldn't the 2 versions be equal ?...
708
 
        {
709
 
                myData.bIASWatched = TRUE;  // now we're friend with the IAS
710
 
                
711
 
                if (myData.bBrokenWatcher)  // if the watcher is not our friend, let's ask the IAS the current items.
712
 
                {
713
 
                        _cd_satus_notifier_get_items_from_ias ();
714
 
                }
715
 
        }
716
 
}
717
 
static void _on_ias_owner_changed (gboolean bOwned, gpointer data)
718
 
{
719
 
        cd_debug ("=== Indicator Applications Service is on the bus (%d)", bOwned);
720
 
        
721
 
        if (bOwned)
722
 
        {
723
 
                // set up a proxy to the Service
724
 
                myData.pProxyIndicatorService = cairo_dock_create_new_session_proxy (
725
 
                        CD_INDICATOR_APPLICATION_ADDR,
726
 
                        CD_INDICATOR_SERVICE_OBJECT,
727
 
                        CD_INDICATOR_SERVICE_INTERFACE);
728
 
                
729
 
                // and watch it.
730
 
                cd_debug ("=== watch it");
731
 
                dbus_g_proxy_begin_call (myData.pProxyIndicatorService,
732
 
                        "Watch",
733
 
                        (DBusGProxyCallNotify)_on_watch_service,
734
 
                        myApplet,
735
 
                        (GDestroyNotify) NULL,
736
 
                        G_TYPE_INVALID);
737
 
        }
738
 
        else  // no more IAS on the bus.
739
 
        {
740
 
                g_object_unref (myData.pProxyIndicatorService);
741
 
                myData.pProxyIndicatorService = NULL;
742
 
                
743
 
                g_object_unref (myData.pProxyIndicatorApplicationService);
744
 
                myData.pProxyIndicatorApplicationService = NULL;
745
 
                
746
 
                myData.bIASWatched = FALSE;
747
 
        }
748
 
}
749
 
static void _on_detect_ias (gboolean bPresent, gpointer data)
750
 
{
751
 
        cd_debug ("=== Indicator Applications Service is present: %d", bPresent);
752
 
        s_pDetectIASCall = NULL;
753
 
        // if present, set up proxy, else try to start the service.
754
 
        if (bPresent)
755
 
        {
756
 
                _on_ias_owner_changed (TRUE, NULL);
757
 
        }
758
 
        else  // not present, maybe the service is not started => try starting it.
759
 
        {
760
 
                cd_debug ("=== try to start the Indicator Service...");
761
 
                DBusGProxy *dbus_proxy = cairo_dock_get_main_proxy ();
762
 
                org_freedesktop_DBus_start_service_by_name_async (dbus_proxy,
763
 
                        CD_INDICATOR_APPLICATION_ADDR,
764
 
                        0,
765
 
                        _on_start_service,
766
 
                        myApplet);
767
 
        }
768
 
        // watch whenever the Service goes up or down.
769
 
        cairo_dock_watch_dbus_name_owner (CD_STATUS_NOTIFIER_WATCHER_ADDR,
770
 
                (CairoDockDbusNameOwnerChangedFunc) _on_ias_owner_changed,
771
 
                NULL);
772
 
}
 
118
 
 
119
  //////////////////////////
 
120
 /// Start/stop service ///
 
121
//////////////////////////
773
122
 
774
123
/* watch Watcher + IAS ->
775
124
Watcher ON -> make proxy -> register -> ok => Get items -> ok => load items
791
140
        cairo_dock_register_service_name (myData.cHostName);
792
141
        
793
142
        // see if a Watcher and/or an Indicator Application Service (IAS) is on the bus.
794
 
        s_pDetectWatcherCall = cairo_dock_dbus_detect_application_async (CD_STATUS_NOTIFIER_WATCHER_ADDR,
795
 
                (CairoDockOnAppliPresentOnDbus) _on_detect_watcher,
796
 
                NULL);
797
 
        s_pDetectIASCall = cairo_dock_dbus_detect_application_async (CD_INDICATOR_APPLICATION_ADDR,
798
 
                (CairoDockOnAppliPresentOnDbus) _on_detect_ias,
799
 
                NULL);
 
143
        cd_satus_notifier_detect_watcher ();
 
144
        cd_satus_notifier_detect_ias ();
800
145
}
801
146
 
802
147
 
803
148
void cd_satus_notifier_stop_service (void)
804
149
{
805
 
        if (myData.pProxyWatcher != NULL)
806
 
        {
807
 
                g_object_unref (myData.pProxyWatcher);
808
 
                g_object_unref (myData.pProxyWatcherProps);
809
 
        }
810
 
        if (myData.pProxyIndicatorApplicationService != NULL)
811
 
        {
812
 
                g_object_unref (myData.pProxyIndicatorApplicationService);
813
 
                g_object_unref (myData.pProxyIndicatorService);
814
 
        }
815
 
        
816
 
        if (s_pDetectWatcherCall != NULL)
817
 
        {
818
 
                DBusGProxy *pProxy = cairo_dock_get_main_proxy ();
819
 
                dbus_g_proxy_cancel_call (pProxy, s_pDetectWatcherCall);
820
 
        }
821
 
        if (s_pDetectIASCall != NULL)
822
 
        {
823
 
                DBusGProxy *pProxy = cairo_dock_get_main_proxy ();
824
 
                dbus_g_proxy_cancel_call (pProxy, s_pDetectIASCall);
825
 
        }
826
 
        
 
150
        // disconnect from the watcher
 
151
        cd_satus_notifier_unregister_from_watcher ();
 
152
        cd_satus_notifier_unregister_from_ias ();
 
153
        
 
154
        // free all the items.
827
155
        g_list_foreach (myData.pItems, (GFunc) cd_free_item, NULL);
828
156
        g_list_free (myData.pItems);
829
157
        
830
158
        if (! myConfig.bCompactMode)
831
159
                CD_APPLET_DELETE_MY_ICONS_LIST;
832
160
        
 
161
        // free the themes table.
833
162
        g_hash_table_destroy (myData.pThemePaths);
834
163
}
835
164
 
836
165
 
 
166
void cd_satus_notifier_launch_our_watcher (void)
 
167
{
 
168
        if (myData.bNoIAS && myData.bNoWatcher)
 
169
        {
 
170
                cd_message ("starting our own watcher...\n");
 
171
                cairo_dock_launch_command (CD_PLUGINS_DIR"/status-notifier-watcher");
 
172
        }
 
173
}
 
174
 
837
175
  ///////////////////
838
176
 /// THEMES PATH ///
839
177
///////////////////