~ubuntu-branches/ubuntu/oneiric/gnome-panel/oneiric

« back to all changes in this revision

Viewing changes to gnome-panel/panel-object-loader.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher, Sebastien Bacher, Jeremy Bicha
  • Date: 2011-05-30 11:04:49 UTC
  • mfrom: (1.13.10 upstream) (2.2.5 experimental)
  • Revision ID: james.westby@ubuntu.com-20110530110449-hinl17kxkcefjw6x
Tags: 1:3.0.2-0ubuntu1
[ Sebastien Bacher ]
* New upstream version
* debian/control.in:
  - the new libgweather version is in oneiric, use it
  - drop the python and python-gconf depends, 
    they were added for gnome-panel-add which is still using gconf and buggy
* debian/gnome-panel-data.install:
  - don't install the apport hook, it's only getting gconf datas which 
    doesn't work since gnome-panel uses gsettings
* debian/patches/90_build_fixes.patch:
  - restore build fix from git not applied in the new serie
* debian/patches/01_panel_submenus.patch:
  - don't take that Debian diff, the .menus use the upstream naming in Ubuntu
* debian/patches/06_no_resize_grip.patch:
  - dropped, the issue is fixed in the new version
* debian/patches/50_fix-potfiles.patch:
  - dropped, the issue is fixed in the new version
* debian/watch:
  - track unstable series as well

Drop those delta, since gnome-panel is not the default Ubuntu session now we
can go back to an experience closer to the upstream one: 
* debian/control.in:
  - drop the indicators recommends, unity-2d is the ubuntu fallback session
    so we can get back to use an upstream config for gnome-panel and reduce
    the delta we carry
* debian/patches/04_default_panel_config.patch:
  - don't modify the upstream layout
* debian/patches/05_no_session_delay.patch:
  - no need to tweak the upstream session to optimize it
* debian/patches/16_compiz_workspace_switcher.patch:
  - go back to the upstream switcher behaviour    
* debian/patches/25_dynamic_fusa_detection.patch:
  - not needed since we use the upstream layout, could be ported if someone
    is wanting to do the work though
* debian/patches/30_disable-initial-animation.patch, debian/rules:
  - drop the --disable-initial-animation, that was some login optimization
    but since it's not the default desktop you should go back to the 
    upstream behaviour

[ Jeremy Bicha ]   
* New upstream version
* Merge from Debian experimental, remaining Ubuntu changes:
* debian/control:
  - Recommends gnome-settings-daemon which has the timezone polkit service
* debian/rules:
  - Update translations template.
* debian/gnome-panel-data.install:
  - Install apport hook
  - Install the "About Ubuntu" menu item.
* debian/patches/01_layout.patch:
  - Disabled, Help & About Ubuntu don't fit as well in Gnome Panel 3
* debian/patches/01_panel_submenus.patch.
  - Dropped
* debian/patches/03_dnd_places_link.patch:
  - Disabled, when using Drag'n'Drop from Places menu, install a link launcher
    (.desktop file) instead of copying the entire directory.
* debian/patches/17_about-ubuntu-translation.patch:
  - List ubuntu-about.desktop for translation.
* debian/patches/40_unset_menuproxy.patch:
  - Make sure gnome-panel and the applets don't pick up menu proxies.
* debian/patches/50_fix-potfiles.patch
  - Fix i18n
* debian/patches/85_disable_shutdown_on_ltsp.patch:
  - Suppress the shutdown option in the panel if LTSP_CLIENT is set.
* debian/patches/71_change_bookmark_submenu_limit_value.patch
  - Dropped, picked up by Debian
* debian/patches/18_lockdown_lock_editor.patch:
* debian/patches/90_git_wnck_show_realize.patch:
* debian/patches/90_fix_linking_DSO_link.patch:
* debian/patches/91_gir_annotations.patch
* debian/patches/92_git_calendar_day.patch
* debian/patches/92_git_fix_applets_in_multiscreen.patch:
  - Dropped, applied upstream
* debian/watch:
  - watch unstable versions

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * panel-object-loader.c: object loader
 
3
 * vim: set et:
 
4
 *
 
5
 * Copyright (C) 2011 Novell, Inc.
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU General Public License as
 
9
 * published by the Free Software Foundation; either version 2 of the
 
10
 * License, or (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful, but
 
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
20
 * 02111-1307, USA.
 
21
 *
 
22
 * Most of this code is originally from applet.c.
 
23
 *
 
24
 * Authors:
 
25
 *      Vincent Untz <vuntz@gnome.org>
 
26
 */
 
27
 
 
28
#include <config.h>
 
29
 
 
30
#include <string.h>
 
31
 
 
32
#include <gio/gio.h>
 
33
 
 
34
#include <libpanel-util/panel-glib.h>
 
35
 
 
36
#include "panel-enums.h"
 
37
#include "panel-schemas.h"
 
38
#include "panel-toplevel.h"
 
39
 
 
40
/* Includes for objects we can load */
 
41
#include "launcher.h"
 
42
#include "panel-action-button.h"
 
43
#include "panel-applet-frame.h"
 
44
#include "panel-menu-bar.h"
 
45
#include "panel-menu-button.h"
 
46
#include "panel-separator.h"
 
47
#include "panel-user-menu.h"
 
48
 
 
49
#include "panel-object-loader.h"
 
50
 
 
51
typedef struct {
 
52
        char                *id;
 
53
        char                *settings_path;
 
54
        GSettings           *settings;
 
55
        char                *toplevel_id;
 
56
        PanelObjectPackType  pack_type;
 
57
        int                  pack_index;
 
58
} PanelObjectToLoad;
 
59
 
 
60
/* Each time those lists get both empty,
 
61
 * panel_object_loader_queue_initial_unhide_toplevels() should be called */
 
62
static GSList  *panel_objects_to_load = NULL;
 
63
static GSList  *panel_objects_loading = NULL;
 
64
 
 
65
/* We have a timeout to always unhide toplevels after a delay, in case of some
 
66
 * blocking object */
 
67
#define         UNHIDE_TOPLEVELS_TIMEOUT_SECONDS 5
 
68
static guint    panel_object_loader_unhide_toplevels_timeout = 0;
 
69
 
 
70
static gboolean panel_object_loader_have_idle = FALSE;
 
71
 
 
72
static void
 
73
free_object_to_load (PanelObjectToLoad *object)
 
74
{
 
75
        g_free (object->id);
 
76
        object->id = NULL;
 
77
 
 
78
        g_free (object->settings_path);
 
79
        object->settings_path = NULL;
 
80
 
 
81
        g_object_unref (object->settings);
 
82
        object->settings = NULL;
 
83
 
 
84
        g_free (object->toplevel_id);
 
85
        object->toplevel_id = NULL;
 
86
 
 
87
        g_free (object);
 
88
}
 
89
 
 
90
/* This doesn't do anything if the initial unhide already happened */
 
91
static gboolean
 
92
panel_object_loader_queue_initial_unhide_toplevels (gpointer user_data)
 
93
{
 
94
        GSList *l;
 
95
 
 
96
        if (panel_object_loader_unhide_toplevels_timeout != 0) {
 
97
                g_source_remove (panel_object_loader_unhide_toplevels_timeout);
 
98
                panel_object_loader_unhide_toplevels_timeout = 0;
 
99
        }
 
100
 
 
101
        for (l = panel_toplevel_list_toplevels (); l != NULL; l = l->next)
 
102
                panel_toplevel_queue_initial_unhide ((PanelToplevel *) l->data);
 
103
 
 
104
        return FALSE;
 
105
}
 
106
 
 
107
void
 
108
panel_object_loader_stop_loading (const char *id)
 
109
{
 
110
        PanelObjectToLoad *object;
 
111
        GSList *l;
 
112
 
 
113
        for (l = panel_objects_loading; l; l = l->next) {
 
114
                object = l->data;
 
115
                if (g_strcmp0 (object->id, id) == 0)
 
116
                        break;
 
117
        }
 
118
        if (l != NULL) {
 
119
                panel_objects_loading = g_slist_delete_link (panel_objects_loading, l);
 
120
                free_object_to_load (object);
 
121
        }
 
122
 
 
123
        for (l = panel_objects_to_load; l; l = l->next) {
 
124
                object = l->data;
 
125
                if (g_strcmp0 (object->id, id) == 0)
 
126
                        break;
 
127
        }
 
128
        if (l != NULL) {
 
129
                panel_objects_to_load = g_slist_delete_link (panel_objects_to_load, l);
 
130
                free_object_to_load (object);
 
131
        }
 
132
 
 
133
        if (panel_objects_loading == NULL && panel_objects_to_load == NULL)
 
134
                panel_object_loader_queue_initial_unhide_toplevels (NULL);
 
135
}
 
136
 
 
137
static gboolean
 
138
panel_object_loader_idle_handler (gpointer dummy)
 
139
{
 
140
        PanelObjectToLoad *object = NULL;
 
141
        PanelToplevel     *toplevel = NULL;
 
142
        PanelWidget       *panel_widget;
 
143
        GSList            *l;
 
144
        char              *iid = NULL;
 
145
        PanelObjectType    object_type;
 
146
        char              *object_type_detail = NULL;
 
147
        gboolean           ret;
 
148
 
 
149
        if (!panel_objects_to_load) {
 
150
                panel_object_loader_have_idle = FALSE;
 
151
                return FALSE;
 
152
        }
 
153
 
 
154
        for (l = panel_objects_to_load; l; l = l->next) {
 
155
                object = l->data;
 
156
 
 
157
                toplevel = panel_toplevel_get_by_id (object->toplevel_id);
 
158
                if (toplevel)
 
159
                        break;
 
160
        }
 
161
 
 
162
        if (!l) {
 
163
                /* All the remaining objects don't have a panel */
 
164
                for (l = panel_objects_to_load; l; l = l->next)
 
165
                        free_object_to_load (l->data);
 
166
                g_slist_free (panel_objects_to_load);
 
167
                panel_objects_to_load = NULL;
 
168
                panel_object_loader_have_idle = FALSE;
 
169
 
 
170
                if (panel_objects_loading == NULL) {
 
171
                        /* unhide any potential initially hidden toplevel */
 
172
                        panel_object_loader_queue_initial_unhide_toplevels (NULL);
 
173
                }
 
174
 
 
175
                return FALSE;
 
176
        }
 
177
 
 
178
        panel_objects_to_load = g_slist_delete_link (panel_objects_to_load, l);
 
179
        panel_objects_loading = g_slist_append (panel_objects_loading, object);
 
180
 
 
181
        panel_widget = panel_toplevel_get_panel_widget (toplevel);
 
182
 
 
183
        iid = g_settings_get_string (object->settings, PANEL_OBJECT_IID_KEY);
 
184
        ret = panel_object_iid_to_type (iid, &object_type, &object_type_detail);
 
185
 
 
186
        if (!ret) {
 
187
                g_printerr ("Object '%s' has an invalid iid ('%s')\n",
 
188
                            object->id, iid);
 
189
                panel_object_loader_stop_loading (object->id);
 
190
                g_free (iid);
 
191
                return TRUE;
 
192
        }
 
193
 
 
194
        g_free (iid);
 
195
 
 
196
        switch (object_type) {
 
197
        case PANEL_OBJECT_APPLET:
 
198
                panel_applet_frame_load (panel_widget,
 
199
                                         object->id,
 
200
                                         object->settings);
 
201
                break;
 
202
        case PANEL_OBJECT_MENU:
 
203
                panel_menu_button_load (panel_widget,
 
204
                                        object->id,
 
205
                                        object->settings);
 
206
                break;
 
207
        case PANEL_OBJECT_LAUNCHER:
 
208
                launcher_load (panel_widget,
 
209
                               object->id,
 
210
                               object->settings);
 
211
                break;
 
212
        case PANEL_OBJECT_ACTION:
 
213
                panel_action_button_load (panel_widget,
 
214
                                          object->id,
 
215
                                          object->settings,
 
216
                                          object_type_detail);
 
217
                break;
 
218
        case PANEL_OBJECT_MENU_BAR:
 
219
                panel_menu_bar_load (panel_widget,
 
220
                                     object->id,
 
221
                                     object->settings);
 
222
                break;
 
223
        case PANEL_OBJECT_SEPARATOR:
 
224
                panel_separator_load (panel_widget,
 
225
                                      object->id,
 
226
                                      object->settings);
 
227
                break;
 
228
        case PANEL_OBJECT_USER_MENU:
 
229
                panel_user_menu_load (panel_widget,
 
230
                                      object->id,
 
231
                                      object->settings);
 
232
                break;
 
233
        default:
 
234
                g_assert_not_reached ();
 
235
                break;
 
236
        }
 
237
 
 
238
        /* We load applets asynchronously, so we specifically don't call
 
239
         * panel_object_loader_stop_loading() for this type. */
 
240
        if (object_type != PANEL_OBJECT_APPLET)
 
241
                panel_object_loader_stop_loading (object->id);
 
242
 
 
243
        return TRUE;
 
244
}
 
245
 
 
246
void
 
247
panel_object_loader_queue (const char *id,
 
248
                           const char *settings_path)
 
249
{
 
250
        PanelObjectToLoad *object;
 
251
        GSettings         *settings;
 
252
        char              *toplevel_id;
 
253
 
 
254
        if (panel_object_loader_is_queued (id))
 
255
                return;
 
256
 
 
257
        settings = g_settings_new_with_path (PANEL_OBJECT_SCHEMA,
 
258
                                             settings_path);
 
259
        toplevel_id = g_settings_get_string (settings,
 
260
                                             PANEL_OBJECT_TOPLEVEL_ID_KEY);
 
261
 
 
262
        if (PANEL_GLIB_STR_EMPTY (toplevel_id)) {
 
263
                g_warning ("No toplevel on which to load object '%s'\n", id);
 
264
                g_free (toplevel_id);
 
265
                g_object_unref (settings);
 
266
                return;
 
267
        }
 
268
 
 
269
        object = g_new0 (PanelObjectToLoad, 1);
 
270
 
 
271
        object->id            = g_strdup (id);
 
272
        object->settings_path = g_strdup (settings_path);
 
273
        object->settings      = g_object_ref (settings);
 
274
        object->toplevel_id   = toplevel_id;
 
275
        object->pack_type     = g_settings_get_enum (settings,
 
276
                                                     PANEL_OBJECT_PACK_TYPE_KEY);
 
277
        object->pack_index    = g_settings_get_int (settings,
 
278
                                                    PANEL_OBJECT_PACK_INDEX_KEY);
 
279
 
 
280
        panel_objects_to_load = g_slist_prepend (panel_objects_to_load, object);
 
281
 
 
282
        g_object_unref (settings);
 
283
}
 
284
 
 
285
static int
 
286
panel_object_compare (const PanelObjectToLoad *a,
 
287
                      const PanelObjectToLoad *b)
 
288
{
 
289
        int c;
 
290
 
 
291
        if ((c = g_strcmp0 (a->toplevel_id, b->toplevel_id)))
 
292
                return c;
 
293
        else if (a->pack_type != b->pack_type)
 
294
                return a->pack_type - b->pack_type; /* start < center < end */
 
295
        else
 
296
                /* note: for packed-end, we explicitly want to start loading
 
297
                 * from the right/bottom instead of left/top to avoid moving
 
298
                 * applets that are on the inside; so the maths are good even
 
299
                 * in this case */
 
300
                return a->pack_index - b->pack_index;
 
301
}
 
302
 
 
303
void
 
304
panel_object_loader_do_load (gboolean initial_load)
 
305
{
 
306
        if (!panel_objects_to_load) {
 
307
                panel_object_loader_queue_initial_unhide_toplevels (NULL);
 
308
                return;
 
309
        }
 
310
 
 
311
        if (panel_objects_to_load && panel_object_loader_unhide_toplevels_timeout == 0) {
 
312
                /* Install a timeout to make sure we don't block the
 
313
                 * unhiding because of an object that doesn't load */
 
314
                panel_object_loader_unhide_toplevels_timeout =
 
315
                        g_timeout_add_seconds (UNHIDE_TOPLEVELS_TIMEOUT_SECONDS,
 
316
                                               panel_object_loader_queue_initial_unhide_toplevels,
 
317
                                               NULL);
 
318
        }
 
319
 
 
320
        panel_objects_to_load = g_slist_sort (panel_objects_to_load,
 
321
                                              (GCompareFunc) panel_object_compare);
 
322
 
 
323
        if (!panel_object_loader_have_idle) {
 
324
                /* on panel startup, we don't care about redraws of the
 
325
                 * toplevels since they are hidden, so we give a higher
 
326
                 * priority to loading of objects */
 
327
                if (initial_load)
 
328
                        g_idle_add_full (G_PRIORITY_HIGH_IDLE,
 
329
                                         panel_object_loader_idle_handler,
 
330
                                         NULL, NULL);
 
331
                else
 
332
                        g_idle_add (panel_object_loader_idle_handler, NULL);
 
333
 
 
334
                panel_object_loader_have_idle = TRUE;
 
335
        }
 
336
}
 
337
 
 
338
gboolean
 
339
panel_object_loader_is_queued (const char *id)
 
340
{
 
341
        GSList *li;
 
342
        for (li = panel_objects_to_load; li != NULL; li = li->next) {
 
343
                PanelObjectToLoad *object = li->data;
 
344
                if (g_strcmp0 (object->id, id) == 0)
 
345
                        return TRUE;
 
346
        }
 
347
        for (li = panel_objects_loading; li != NULL; li = li->next) {
 
348
                PanelObjectToLoad *object = li->data;
 
349
                if (g_strcmp0 (object->id, id) == 0)
 
350
                        return TRUE;
 
351
        }
 
352
        return FALSE;
 
353
}
 
354
 
 
355
 
 
356
/*******************************\
 
357
 * iid <=> object type mapping *
 
358
\*******************************/
 
359
 
 
360
#define PANEL_INTERNAL_FACTORY "PanelInternalFactory"
 
361
 
 
362
static struct {
 
363
        PanelObjectType  type;
 
364
        const char      *id;
 
365
        gboolean         has_detail;
 
366
} panel_object_iid_map[] = {
 
367
        { PANEL_OBJECT_ACTION,    "ActionButton" , TRUE  },
 
368
        { PANEL_OBJECT_MENU_BAR,  "MenuBar"      , FALSE },
 
369
        { PANEL_OBJECT_MENU,      "MenuButton"   , FALSE },
 
370
        { PANEL_OBJECT_LAUNCHER,  "Launcher"     , FALSE },
 
371
        { PANEL_OBJECT_SEPARATOR, "Separator"    , FALSE },
 
372
        { PANEL_OBJECT_USER_MENU, "UserMenu"     , FALSE }
 
373
};
 
374
 
 
375
char *
 
376
panel_object_type_to_iid (PanelObjectType  type,
 
377
                          const char      *detail)
 
378
{
 
379
        int i;
 
380
 
 
381
        if (type == PANEL_OBJECT_APPLET)
 
382
                return g_strdup (detail);
 
383
 
 
384
        for (i = 0; i < G_N_ELEMENTS (panel_object_iid_map); i++) {
 
385
                if (panel_object_iid_map[i].type != type)
 
386
                        continue;
 
387
 
 
388
                if (panel_object_iid_map[i].has_detail &&
 
389
                    PANEL_GLIB_STR_EMPTY (detail))
 
390
                        return NULL;
 
391
 
 
392
                if (panel_object_iid_map[i].has_detail)
 
393
                        return g_strdup_printf ("%s::%s:%s",
 
394
                                                PANEL_INTERNAL_FACTORY,
 
395
                                                panel_object_iid_map[i].id,
 
396
                                                detail);
 
397
                else
 
398
                        return g_strdup_printf ("%s::%s",
 
399
                                                PANEL_INTERNAL_FACTORY,
 
400
                                                panel_object_iid_map[i].id);
 
401
        }
 
402
 
 
403
        return NULL;
 
404
}
 
405
 
 
406
gboolean
 
407
panel_object_iid_to_type (const char       *iid,
 
408
                          PanelObjectType  *type,
 
409
                          char            **detail)
 
410
{
 
411
        const char *instance_id;
 
412
        char       *factory_id;
 
413
        gboolean    is_applet;;
 
414
        int         i;
 
415
 
 
416
        if (detail)
 
417
                *detail = NULL;
 
418
 
 
419
        instance_id = g_strrstr (iid, "::");
 
420
        if (!instance_id)
 
421
                return FALSE;
 
422
 
 
423
        factory_id = g_strndup (iid, strlen (iid) - strlen (instance_id));
 
424
        is_applet = (g_strcmp0 (factory_id, PANEL_INTERNAL_FACTORY) != 0);
 
425
        g_free (factory_id);
 
426
 
 
427
        if (is_applet) {
 
428
                *type = PANEL_OBJECT_APPLET;
 
429
                return TRUE;
 
430
        }
 
431
 
 
432
        instance_id += 2;
 
433
 
 
434
        for (i = 0; i < G_N_ELEMENTS (panel_object_iid_map); i++) {
 
435
                if (!panel_object_iid_map[i].has_detail &&
 
436
                    g_strcmp0 (panel_object_iid_map[i].id,
 
437
                               instance_id) == 0) {
 
438
                        *type = panel_object_iid_map[i].type;
 
439
                        return TRUE;
 
440
                }
 
441
 
 
442
                if (panel_object_iid_map[i].has_detail) {
 
443
                        const char *d;
 
444
 
 
445
                        if (!g_str_has_prefix (instance_id,
 
446
                                               panel_object_iid_map[i].id))
 
447
                                continue;
 
448
 
 
449
                        d = instance_id + strlen (panel_object_iid_map[i].id);
 
450
                        if (d[0] != ':')
 
451
                                return FALSE;
 
452
 
 
453
                        d += 1;
 
454
                        if (d[0] == '\0')
 
455
                                return FALSE;
 
456
 
 
457
                        *type = panel_object_iid_map[i].type;
 
458
                        if (detail)
 
459
                                *detail = g_strdup (d);
 
460
 
 
461
                        return TRUE;
 
462
                }
 
463
        }
 
464
 
 
465
        /* We don't know this id; it could be provided by an applet now (for
 
466
         * features that moved from being internal to the panel to applets, and
 
467
         * that provide compatibility with the same id). So let's try it.  */
 
468
        *type = PANEL_OBJECT_APPLET;
 
469
        return TRUE;
 
470
}