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

« back to all changes in this revision

Viewing changes to .pc/25_dynamic_fusa_detection.patch/gnome-panel/applet.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
 
/* Gnome panel: general applet functionality
2
 
 * (C) 1997 the Free Software Foundation
3
 
 *
4
 
 * Authors:  George Lebl
5
 
 *           Federico Mena
6
 
 *           Miguel de Icaza
7
 
 */
8
 
 
9
 
#include <config.h>
10
 
#include <string.h>
11
 
#include <signal.h>
12
 
#include <unistd.h>
13
 
 
14
 
#include <glib/gi18n.h>
15
 
#include <gdk/gdkx.h>
16
 
 
17
 
#include <libpanel-util/panel-show.h>
18
 
 
19
 
#include "button-widget.h"
20
 
#include "drawer.h"
21
 
#include "launcher.h"
22
 
#include "panel-addto.h"
23
 
#include "panel-gconf.h"
24
 
#include "panel-config-global.h"
25
 
#include "panel-applet-frame.h"
26
 
#include "panel-action-button.h"
27
 
#include "panel-menu-bar.h"
28
 
#include "panel-separator.h"
29
 
#include "panel-compatibility.h"
30
 
#include "panel-toplevel.h"
31
 
#include "panel-util.h"
32
 
#include "panel-profile.h"
33
 
#include "panel-menu-button.h"
34
 
#include "panel-globals.h"
35
 
#include "panel-properties-dialog.h"
36
 
#include "panel-lockdown.h"
37
 
 
38
 
#define SMALL_ICON_SIZE 20
39
 
 
40
 
static GSList *registered_applets = NULL;
41
 
static GSList *queued_position_saves = NULL;
42
 
static guint   queued_position_source = 0;
43
 
 
44
 
 
45
 
static inline PanelWidget *
46
 
panel_applet_get_panel_widget (AppletInfo *info)
47
 
{
48
 
        return PANEL_WIDGET (gtk_widget_get_parent (info->widget));
49
 
}
50
 
 
51
 
static void
52
 
panel_applet_set_dnd_enabled (AppletInfo *info,
53
 
                              gboolean    dnd_enabled)
54
 
{
55
 
        switch (info->type) {
56
 
        case PANEL_OBJECT_DRAWER:
57
 
                panel_drawer_set_dnd_enabled (info->data, dnd_enabled);
58
 
                break;
59
 
        case PANEL_OBJECT_MENU:
60
 
                panel_menu_button_set_dnd_enabled (PANEL_MENU_BUTTON (info->widget),
61
 
                                                   dnd_enabled);
62
 
                break;
63
 
        case PANEL_OBJECT_LAUNCHER:
64
 
                panel_launcher_set_dnd_enabled (info->data, dnd_enabled);
65
 
                break;
66
 
        case PANEL_OBJECT_APPLET:
67
 
                break;
68
 
        case PANEL_OBJECT_LOGOUT:
69
 
        case PANEL_OBJECT_LOCK:
70
 
        case PANEL_OBJECT_ACTION:
71
 
                panel_action_button_set_dnd_enabled (PANEL_ACTION_BUTTON (info->widget),
72
 
                                                     dnd_enabled);
73
 
                break;
74
 
        case PANEL_OBJECT_MENU_BAR:
75
 
        case PANEL_OBJECT_SEPARATOR:
76
 
                break;
77
 
        default:
78
 
                g_assert_not_reached ();
79
 
                break;
80
 
        }
81
 
 
82
 
}
83
 
 
84
 
gboolean
85
 
panel_applet_toggle_locked (AppletInfo *info)
86
 
{
87
 
        PanelWidget *panel_widget;
88
 
        gboolean     locked;
89
 
 
90
 
        panel_widget = panel_applet_get_panel_widget (info);
91
 
        
92
 
        locked = panel_widget_toggle_applet_locked (panel_widget, info->widget);
93
 
 
94
 
        panel_applet_save_position (info, info->id, TRUE);
95
 
        panel_applet_set_dnd_enabled (info, !locked);
96
 
 
97
 
        return locked;
98
 
}
99
 
 
100
 
static void
101
 
panel_applet_lock (GtkCheckMenuItem *menuitem,
102
 
                   AppletInfo       *info)
103
 
{
104
 
        gboolean locked;
105
 
 
106
 
        locked = panel_applet_toggle_locked (info);
107
 
 
108
 
        gtk_check_menu_item_set_active (menuitem, locked);
109
 
 
110
 
        if (info->move_item)
111
 
                gtk_widget_set_sensitive (info->move_item, !locked);
112
 
}
113
 
 
114
 
static void
115
 
move_applet_callback (GtkWidget *widget, AppletInfo *info)
116
 
{
117
 
        GtkWidget   *parent;
118
 
        PanelWidget *panel;
119
 
 
120
 
        g_return_if_fail (info != NULL);
121
 
        g_return_if_fail (info->widget != NULL);
122
 
 
123
 
        parent = gtk_widget_get_parent (info->widget);
124
 
 
125
 
        g_return_if_fail (parent != NULL);
126
 
        g_return_if_fail (PANEL_IS_WIDGET (parent));
127
 
 
128
 
        panel = PANEL_WIDGET (parent);
129
 
 
130
 
        panel_widget_applet_drag_start (panel, info->widget,
131
 
                                        PW_DRAG_OFF_CENTER,
132
 
                                        GDK_CURRENT_TIME);
133
 
}
134
 
 
135
 
/* permanently remove an applet - all non-permanent
136
 
 * cleanups should go in panel_applet_destroy()
137
 
 */
138
 
void
139
 
panel_applet_clean (AppletInfo *info)
140
 
{
141
 
        g_return_if_fail (info != NULL);
142
 
 
143
 
        if (info->type == PANEL_OBJECT_LAUNCHER)
144
 
                panel_launcher_delete (info->data);
145
 
 
146
 
        if (info->widget) {
147
 
                GtkWidget *widget = info->widget;
148
 
 
149
 
                info->widget = NULL;
150
 
                gtk_widget_destroy (widget);
151
 
        }
152
 
}
153
 
 
154
 
static void
155
 
panel_applet_recreate_menu (AppletInfo  *info)
156
 
{
157
 
        GList *l;
158
 
 
159
 
        if (!info->menu)
160
 
                return;
161
 
 
162
 
        for (l = info->user_menu; l; l = l->next) {
163
 
                AppletUserMenu *menu = l->data;
164
 
 
165
 
                menu->menuitem =NULL;
166
 
                menu->submenu =NULL;
167
 
        }
168
 
 
169
 
        g_object_unref (info->menu);
170
 
        info->menu = panel_applet_create_menu (info);
171
 
}
172
 
 
173
 
static void
174
 
panel_applet_locked_change_notify (GConfClient *client,
175
 
                                   guint        cnxn_id,
176
 
                                   GConfEntry  *entry,
177
 
                                   GtkWidget   *applet)
178
 
{
179
 
        GConfValue  *value;
180
 
        gboolean     locked;
181
 
        gboolean     applet_locked;
182
 
        AppletInfo  *info;
183
 
        PanelWidget *panel_widget;
184
 
 
185
 
        g_assert (applet != NULL);
186
 
 
187
 
        info = (AppletInfo  *) g_object_get_data (G_OBJECT (applet),
188
 
                                                  "applet_info");
189
 
        if (info == NULL)
190
 
                return;
191
 
 
192
 
        value = gconf_entry_get_value (entry);
193
 
        if (value == NULL || value->type != GCONF_VALUE_BOOL)
194
 
                return;
195
 
 
196
 
        locked = gconf_value_get_bool (value);
197
 
 
198
 
        panel_widget = panel_applet_get_panel_widget (info);
199
 
        applet_locked = panel_widget_get_applet_locked (panel_widget,
200
 
                                                        info->widget);
201
 
 
202
 
        if ((locked && applet_locked) || !(locked || applet_locked))
203
 
                return;
204
 
 
205
 
        panel_applet_toggle_locked (info);
206
 
 
207
 
        if (info->type == PANEL_OBJECT_APPLET)
208
 
                panel_applet_frame_sync_menu_state (PANEL_APPLET_FRAME (info->widget));
209
 
        else
210
 
                panel_applet_recreate_menu (info);
211
 
}
212
 
 
213
 
static void
214
 
applet_remove_callback (GtkWidget  *widget,
215
 
                        AppletInfo *info)
216
 
{
217
 
 
218
 
        if (info->type == PANEL_OBJECT_DRAWER)
219
 
                drawer_query_deletion (info->data);
220
 
        else
221
 
                panel_profile_delete_object (info);
222
 
}
223
 
 
224
 
static inline GdkScreen *
225
 
applet_user_menu_get_screen (AppletUserMenu *menu)
226
 
{
227
 
        PanelWidget *panel_widget;
228
 
 
229
 
        panel_widget = panel_applet_get_panel_widget (menu->info);
230
 
 
231
 
        return gtk_window_get_screen (GTK_WINDOW (panel_widget->toplevel));
232
 
}
233
 
 
234
 
static void
235
 
applet_callback_callback (GtkWidget      *widget,
236
 
                          AppletUserMenu *menu)
237
 
{
238
 
        GdkScreen *screen;
239
 
 
240
 
        g_return_if_fail (menu->info != NULL);
241
 
 
242
 
        screen = applet_user_menu_get_screen (menu);
243
 
 
244
 
        switch (menu->info->type) {
245
 
        case PANEL_OBJECT_LAUNCHER:
246
 
                if (!strcmp (menu->name, "launch"))
247
 
                        launcher_launch (menu->info->data, widget);
248
 
                else if (!strcmp (menu->name, "properties"))
249
 
                        launcher_properties (menu->info->data);
250
 
                break;
251
 
        case PANEL_OBJECT_DRAWER: 
252
 
                if (strcmp (menu->name, "add") == 0) {
253
 
                        Drawer *drawer = menu->info->data;
254
 
 
255
 
                        panel_addto_present (GTK_MENU_ITEM (widget),
256
 
                                             panel_toplevel_get_panel_widget (drawer->toplevel));
257
 
                } else if (strcmp (menu->name, "properties") == 0) {
258
 
                        Drawer *drawer = menu->info->data;
259
 
 
260
 
                        panel_properties_dialog_present (drawer->toplevel);
261
 
                } else if (strcmp (menu->name, "help") == 0) {
262
 
                        panel_show_help (screen,
263
 
                                         "user-guide", "gospanel-18", NULL);
264
 
                }
265
 
                break;
266
 
        case PANEL_OBJECT_MENU:
267
 
                panel_menu_button_invoke_menu (
268
 
                        PANEL_MENU_BUTTON (menu->info->widget), menu->name);
269
 
                break;
270
 
        case PANEL_OBJECT_ACTION:
271
 
        case PANEL_OBJECT_LOGOUT:
272
 
        case PANEL_OBJECT_LOCK:
273
 
                panel_action_button_invoke_menu (
274
 
                        PANEL_ACTION_BUTTON (menu->info->widget), menu->name);
275
 
                break;
276
 
        case PANEL_OBJECT_MENU_BAR:
277
 
                panel_menu_bar_invoke_menu (
278
 
                        PANEL_MENU_BAR (menu->info->widget), menu->name);
279
 
                break;
280
 
 
281
 
        case PANEL_OBJECT_APPLET:
282
 
                /*
283
 
                 * Applet's menu's are handled differently
284
 
                 */
285
 
                break;
286
 
        case PANEL_OBJECT_SEPARATOR:
287
 
                break;
288
 
        default:
289
 
                g_assert_not_reached ();
290
 
                break;
291
 
        }
292
 
}
293
 
 
294
 
static void
295
 
applet_menu_show (GtkWidget *w,
296
 
                  AppletInfo *info)
297
 
{
298
 
        PanelWidget *panel_widget;
299
 
 
300
 
        panel_widget = panel_applet_get_panel_widget (info);
301
 
 
302
 
        panel_toplevel_push_autohide_disabler (panel_widget->toplevel);
303
 
}
304
 
 
305
 
 
306
 
static void
307
 
applet_menu_deactivate (GtkWidget *w,
308
 
                        AppletInfo *info)
309
 
{
310
 
        PanelWidget *panel_widget;
311
 
 
312
 
        panel_widget = panel_applet_get_panel_widget (info);
313
 
 
314
 
        panel_toplevel_pop_autohide_disabler (panel_widget->toplevel);
315
 
}
316
 
 
317
 
AppletUserMenu *
318
 
panel_applet_get_callback (GList      *user_menu,
319
 
                           const char *name)
320
 
{
321
 
        GList *l;
322
 
 
323
 
        for (l = user_menu; l; l = l->next) {
324
 
                AppletUserMenu *menu = l->data;
325
 
 
326
 
                if (strcmp (menu->name, name) == 0)
327
 
                        return menu;
328
 
        }
329
 
 
330
 
        return NULL;    
331
 
}
332
 
 
333
 
void
334
 
panel_applet_add_callback (AppletInfo          *info,
335
 
                           const char          *callback_name,
336
 
                           const char          *stock_item,
337
 
                           const char          *menuitem_text,
338
 
                           CallbackEnabledFunc  is_enabled_func)
339
 
{
340
 
        AppletUserMenu *menu;
341
 
 
342
 
        g_return_if_fail (info != NULL);
343
 
        g_return_if_fail (panel_applet_get_callback (info->user_menu,
344
 
                                                     callback_name) == NULL);
345
 
 
346
 
        menu                  = g_new0 (AppletUserMenu, 1);
347
 
        menu->name            = g_strdup (callback_name);
348
 
        menu->stock_item      = g_strdup (stock_item);
349
 
        menu->text            = g_strdup (menuitem_text);
350
 
        menu->is_enabled_func = is_enabled_func;
351
 
        menu->sensitive       = TRUE;
352
 
        menu->info            = info;
353
 
        menu->menuitem        = NULL;
354
 
        menu->submenu         = NULL;
355
 
 
356
 
        info->user_menu = g_list_append (info->user_menu, menu);
357
 
 
358
 
        panel_applet_recreate_menu (info);
359
 
}
360
 
 
361
 
static void
362
 
setup_an_item (AppletUserMenu *menu,
363
 
               GtkWidget      *submenu,
364
 
               int             is_submenu)
365
 
{
366
 
        GtkWidget *image = NULL;
367
 
 
368
 
        menu->menuitem = gtk_image_menu_item_new_with_mnemonic (menu->text);
369
 
        if (menu->stock_item && menu->stock_item [0]) {
370
 
                image = gtk_image_new_from_stock (menu->stock_item,
371
 
                                                  GTK_ICON_SIZE_MENU);
372
 
                gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu->menuitem),
373
 
                                               image);
374
 
        }
375
 
        gtk_widget_show (menu->menuitem);
376
 
 
377
 
        g_signal_connect (G_OBJECT (menu->menuitem), "destroy",
378
 
                          G_CALLBACK (gtk_widget_destroyed),
379
 
                          &menu->menuitem);
380
 
 
381
 
        if(submenu)
382
 
                gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menu->menuitem);
383
 
 
384
 
        /*if an item not a submenu*/
385
 
        if (!is_submenu) {
386
 
                g_signal_connect (menu->menuitem, "activate",
387
 
                                  G_CALLBACK (applet_callback_callback),
388
 
                                  menu);
389
 
                g_signal_connect (submenu, "destroy",
390
 
                                  G_CALLBACK (gtk_widget_destroyed),
391
 
                                  &menu->submenu);
392
 
        /* if the item is a submenu and doesn't have it's menu
393
 
           created yet*/
394
 
        } else if (!menu->submenu) {
395
 
                menu->submenu = gtk_menu_new ();
396
 
        }
397
 
 
398
 
        if(menu->submenu) {
399
 
                gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu->menuitem),
400
 
                                          menu->submenu);
401
 
                g_signal_connect (G_OBJECT (menu->submenu), "destroy",
402
 
                                    G_CALLBACK (gtk_widget_destroyed),
403
 
                                    &menu->submenu);
404
 
        }
405
 
        
406
 
        gtk_widget_set_sensitive(menu->menuitem,menu->sensitive);
407
 
}
408
 
 
409
 
static void
410
 
add_to_submenus (AppletInfo *info,
411
 
                 const char *path,
412
 
                 const char *name,
413
 
                 AppletUserMenu *menu,
414
 
                 GtkWidget *submenu,
415
 
                 GList *user_menu)
416
 
{
417
 
        char *n = g_strdup (name);
418
 
        char *p = strchr (n, '/');
419
 
        char *t;
420
 
        AppletUserMenu *s_menu;
421
 
 
422
 
        /*this is the last one*/
423
 
        if (p == NULL) {
424
 
                g_free (n);
425
 
                setup_an_item (menu, submenu, FALSE);
426
 
                return;
427
 
        }
428
 
        
429
 
        /*this is the last one and we are a submenu, we have already been
430
 
          set up*/
431
 
        if(p==(n + strlen(n) - 1)) {
432
 
                g_free(n);
433
 
                return;
434
 
        }
435
 
        
436
 
        *p = '\0';
437
 
        p++;
438
 
        
439
 
        t = g_strconcat (path, n, "/", NULL);
440
 
        s_menu = panel_applet_get_callback (user_menu, t);
441
 
        /*the user did not give us this sub menu, whoops, will create an empty
442
 
          one then*/
443
 
        if (s_menu == NULL) {
444
 
                s_menu = g_new0 (AppletUserMenu,1);
445
 
                s_menu->name = g_strdup (t);
446
 
                s_menu->stock_item = NULL;
447
 
                s_menu->text = g_strdup (_("???"));
448
 
                s_menu->sensitive = TRUE;
449
 
                s_menu->info = info;
450
 
                s_menu->menuitem = NULL;
451
 
                s_menu->submenu = NULL;
452
 
                info->user_menu = g_list_append (info->user_menu,s_menu);
453
 
                user_menu = info->user_menu;
454
 
        }
455
 
        
456
 
        if (s_menu->submenu == NULL) {
457
 
                s_menu->submenu = gtk_menu_new ();
458
 
                /*a more elegant way to do this should be done
459
 
                  when I don't want to go to sleep */
460
 
                if (s_menu->menuitem != NULL) {
461
 
                        gtk_widget_destroy (s_menu->menuitem);
462
 
                        s_menu->menuitem = NULL;
463
 
                }
464
 
        }
465
 
        if (s_menu->menuitem == NULL)
466
 
                setup_an_item (s_menu, submenu, TRUE);
467
 
        
468
 
        add_to_submenus (info, t, p, menu, s_menu->submenu, user_menu);
469
 
        
470
 
        g_free(t);
471
 
        g_free(n);
472
 
}
473
 
 
474
 
GtkWidget *
475
 
panel_applet_create_menu (AppletInfo *info)
476
 
{
477
 
        GtkWidget   *menu;
478
 
        GtkWidget   *menuitem;
479
 
        GList       *l;
480
 
        PanelWidget *panel_widget;
481
 
        gboolean     added_anything = FALSE;
482
 
 
483
 
        panel_widget = panel_applet_get_panel_widget (info);
484
 
 
485
 
        menu = g_object_ref_sink (gtk_menu_new ());
486
 
 
487
 
        /* connect the show & deactivate signal, so that we can "disallow" and
488
 
         * "re-allow" autohide when the menu is shown/deactivated.
489
 
         */
490
 
        g_signal_connect (menu, "show",
491
 
                          G_CALLBACK (applet_menu_show), info);
492
 
        g_signal_connect (menu, "deactivate",
493
 
                          G_CALLBACK (applet_menu_deactivate), info);
494
 
 
495
 
        for (l = info->user_menu; l; l = l->next) {
496
 
                AppletUserMenu *user_menu = l->data;
497
 
 
498
 
                if (user_menu->is_enabled_func && !user_menu->is_enabled_func ())
499
 
                        continue;
500
 
 
501
 
                add_to_submenus (info, "", user_menu->name, user_menu, 
502
 
                                 menu, info->user_menu);
503
 
 
504
 
                added_anything = TRUE;
505
 
        }
506
 
 
507
 
        if (!panel_lockdown_get_locked_down ()) {
508
 
                GtkWidget *image;
509
 
                gboolean   locked;
510
 
                gboolean   lockable;
511
 
                gboolean   movable;
512
 
                gboolean   removable;
513
 
 
514
 
                lockable = panel_applet_lockable (info);
515
 
                movable = panel_applet_can_freely_move (info);
516
 
                removable = panel_profile_id_lists_are_writable ();
517
 
 
518
 
                locked = panel_widget_get_applet_locked (panel_widget, info->widget);
519
 
 
520
 
                if (added_anything) {
521
 
                        menuitem = gtk_separator_menu_item_new ();
522
 
                        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
523
 
                        gtk_widget_show (menuitem);
524
 
                }
525
 
 
526
 
                menuitem = gtk_image_menu_item_new_with_mnemonic (_("_Remove From Panel"));
527
 
                image = gtk_image_new_from_stock (GTK_STOCK_REMOVE,
528
 
                                                  GTK_ICON_SIZE_MENU);
529
 
                gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem),
530
 
                                               image);
531
 
                g_signal_connect (menuitem, "activate",
532
 
                                  G_CALLBACK (applet_remove_callback), info);
533
 
                gtk_widget_show (menuitem);
534
 
                gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
535
 
                gtk_widget_set_sensitive (menuitem, (!locked || lockable) && removable);
536
 
                
537
 
                menuitem = gtk_menu_item_new_with_mnemonic (_("_Move"));
538
 
                g_signal_connect (menuitem, "activate",
539
 
                                  G_CALLBACK (move_applet_callback), info);
540
 
                gtk_widget_show (menuitem);
541
 
                gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
542
 
                gtk_widget_set_sensitive (menuitem, !locked && movable);
543
 
 
544
 
                g_assert (info->move_item == NULL);
545
 
 
546
 
                info->move_item = menuitem;
547
 
                g_object_add_weak_pointer (G_OBJECT (menuitem),
548
 
                                           (gpointer *) &info->move_item);
549
 
 
550
 
                menuitem = gtk_separator_menu_item_new ();
551
 
                gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
552
 
                gtk_widget_show (menuitem);
553
 
 
554
 
                menuitem = gtk_check_menu_item_new_with_mnemonic (_("Loc_k To Panel"));
555
 
                gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
556
 
                                                locked);
557
 
                g_signal_connect (menuitem, "toggled",
558
 
                                  G_CALLBACK (panel_applet_lock), info);
559
 
                gtk_widget_show (menuitem);
560
 
                gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
561
 
                gtk_widget_set_sensitive (menuitem, lockable);
562
 
 
563
 
                added_anything = TRUE;
564
 
        }
565
 
 
566
 
        if ( ! added_anything) {
567
 
                g_object_unref (menu);
568
 
                return NULL;
569
 
        }
570
 
 
571
 
        return menu;
572
 
}
573
 
 
574
 
void
575
 
panel_applet_menu_set_recurse (GtkMenu     *menu,
576
 
                               const gchar *key,
577
 
                               gpointer     data)
578
 
{
579
 
        GList *children;
580
 
        GList *l;
581
 
 
582
 
        g_object_set_data (G_OBJECT (menu), key, data);
583
 
 
584
 
        children = gtk_container_get_children (GTK_CONTAINER (menu));
585
 
 
586
 
        for (l = children; l; l = l->next) {
587
 
                GtkWidget *submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (l->data));
588
 
 
589
 
                if (submenu)
590
 
                        panel_applet_menu_set_recurse (
591
 
                                GTK_MENU (submenu), key, data);
592
 
        }
593
 
 
594
 
        g_list_free (children);
595
 
}
596
 
 
597
 
void
598
 
panel_applet_position_menu (GtkMenu   *menu,
599
 
                            int       *x,
600
 
                            int       *y,
601
 
                            gboolean  *push_in,
602
 
                            GtkWidget *applet)
603
 
{
604
 
        GtkAllocation   allocation;
605
 
        GtkRequisition  requisition;
606
 
        GdkScreen      *screen;
607
 
        GtkWidget      *parent;
608
 
        int             menu_x = 0;
609
 
        int             menu_y = 0;
610
 
        int             pointer_x;
611
 
        int             pointer_y;
612
 
 
613
 
        parent = gtk_widget_get_parent (applet);
614
 
 
615
 
        g_return_if_fail (PANEL_IS_WIDGET (parent));
616
 
 
617
 
        screen = gtk_widget_get_screen (applet);
618
 
 
619
 
        gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
620
 
 
621
 
        gdk_window_get_origin (gtk_widget_get_window (applet), &menu_x, &menu_y);
622
 
        gtk_widget_get_pointer (applet, &pointer_x, &pointer_y);
623
 
 
624
 
        gtk_widget_get_allocation (applet, &allocation);
625
 
 
626
 
        if (!gtk_widget_get_has_window (applet)) {
627
 
                menu_x += allocation.x;
628
 
                menu_y += allocation.y;
629
 
        }
630
 
 
631
 
        if (PANEL_WIDGET (parent)->orient == GTK_ORIENTATION_HORIZONTAL) {
632
 
                if (gtk_widget_get_direction (GTK_WIDGET (menu)) != GTK_TEXT_DIR_RTL) {
633
 
                        if (pointer_x < allocation.width &&
634
 
                            requisition.width < pointer_x)
635
 
                                menu_x += MIN (pointer_x,
636
 
                                               allocation.width - requisition.width);
637
 
                } else {
638
 
                        menu_x += allocation.width - requisition.width;
639
 
                        if (pointer_x > 0 && pointer_x < allocation.width &&
640
 
                            pointer_x < allocation.width - requisition.width) {
641
 
                                menu_x -= MIN (allocation.width - pointer_x,
642
 
                                               allocation.width - requisition.width);
643
 
                        }
644
 
                }
645
 
                menu_x = MIN (menu_x, gdk_screen_get_width (screen) - requisition.width);
646
 
 
647
 
                if (menu_y > gdk_screen_get_height (screen) / 2)
648
 
                        menu_y -= requisition.height;
649
 
                else
650
 
                        menu_y += allocation.height;
651
 
        } else {
652
 
                if (pointer_y < allocation.height &&
653
 
                    requisition.height < pointer_y)
654
 
                        menu_y += MIN (pointer_y, allocation.height - requisition.height);
655
 
                menu_y = MIN (menu_y, gdk_screen_get_height (screen) - requisition.height);
656
 
 
657
 
                if (menu_x > gdk_screen_get_width (screen) / 2)
658
 
                        menu_x -= requisition.width;
659
 
                else
660
 
                        menu_x += allocation.width;
661
 
        }
662
 
 
663
 
        *x = menu_x;
664
 
        *y = menu_y;
665
 
        *push_in = TRUE;
666
 
}
667
 
 
668
 
static void
669
 
applet_show_menu (AppletInfo     *info,
670
 
                  GdkEventButton *event)
671
 
{
672
 
        PanelWidget *panel_widget;
673
 
 
674
 
        g_return_if_fail (info != NULL);
675
 
 
676
 
        panel_widget = panel_applet_get_panel_widget (info);
677
 
 
678
 
        if (info->menu == NULL)
679
 
                info->menu = panel_applet_create_menu (info);
680
 
 
681
 
        if (info->menu == NULL)
682
 
                return;
683
 
 
684
 
        panel_applet_menu_set_recurse (GTK_MENU (info->menu),
685
 
                                       "menu_panel",
686
 
                                       panel_widget);
687
 
 
688
 
        gtk_menu_set_screen (GTK_MENU (info->menu),
689
 
                             gtk_window_get_screen (GTK_WINDOW (panel_widget->toplevel)));
690
 
 
691
 
        if (!gtk_widget_get_realized (info->menu))
692
 
                gtk_widget_show (info->menu);
693
 
 
694
 
        gtk_menu_popup (GTK_MENU (info->menu),
695
 
                        NULL,
696
 
                        NULL,
697
 
                        (GtkMenuPositionFunc) panel_applet_position_menu,
698
 
                        info->widget,
699
 
                        event->button,
700
 
                        event->time);
701
 
}
702
 
 
703
 
static gboolean
704
 
applet_do_popup_menu (GtkWidget      *widget,
705
 
                      GdkEventButton *event,
706
 
                      AppletInfo     *info)
707
 
{
708
 
        if (panel_applet_is_in_drag ())
709
 
                return FALSE;
710
 
 
711
 
        if (info->type == PANEL_OBJECT_APPLET)
712
 
                return FALSE;
713
 
 
714
 
        applet_show_menu (info, event);
715
 
 
716
 
        return TRUE;
717
 
}
718
 
 
719
 
static gboolean
720
 
applet_popup_menu (GtkWidget      *widget,
721
 
                   AppletInfo     *info)
722
 
{
723
 
        GdkEventButton event;
724
 
 
725
 
        event.button = 3;
726
 
        event.time = GDK_CURRENT_TIME;
727
 
 
728
 
        return applet_do_popup_menu (widget, &event, info);
729
 
}
730
 
 
731
 
static gboolean
732
 
applet_button_press (GtkWidget      *widget,
733
 
                     GdkEventButton *event,
734
 
                     AppletInfo     *info)
735
 
{
736
 
        if (event->button == 3)
737
 
                return applet_do_popup_menu (widget, event, info);
738
 
 
739
 
        return FALSE;
740
 
}
741
 
 
742
 
static void
743
 
panel_applet_destroy (GtkWidget  *widget,
744
 
                      AppletInfo *info)
745
 
{
746
 
        GList *l;
747
 
 
748
 
        g_return_if_fail (info != NULL);
749
 
 
750
 
        info->widget = NULL;
751
 
 
752
 
        registered_applets = g_slist_remove (registered_applets, info);
753
 
 
754
 
        queued_position_saves =
755
 
                g_slist_remove (queued_position_saves, info);
756
 
 
757
 
        if (info->type == PANEL_OBJECT_DRAWER) {
758
 
                Drawer *drawer = info->data;
759
 
 
760
 
                if (drawer->toplevel) {
761
 
                        PanelWidget *panel_widget;
762
 
 
763
 
                        panel_widget = panel_toplevel_get_panel_widget (
764
 
                                                        drawer->toplevel);
765
 
                        panel_widget->master_widget = NULL;
766
 
 
767
 
                        gtk_widget_destroy (GTK_WIDGET (drawer->toplevel));
768
 
                        drawer->toplevel = NULL;
769
 
                }
770
 
        }
771
 
 
772
 
        if (info->type != PANEL_OBJECT_APPLET)
773
 
                panel_lockdown_notify_remove (G_CALLBACK (panel_applet_recreate_menu),
774
 
                                              info);
775
 
 
776
 
        if (info->menu)
777
 
                g_object_unref (info->menu);
778
 
        info->menu = NULL;
779
 
 
780
 
        if (info->data_destroy)
781
 
                info->data_destroy (info->data);
782
 
        info->data = NULL;
783
 
 
784
 
        for (l = info->user_menu; l != NULL; l = l->next) {
785
 
                AppletUserMenu *umenu = l->data;
786
 
 
787
 
                g_free (umenu->name);
788
 
                g_free (umenu->stock_item);
789
 
                g_free (umenu->text);
790
 
 
791
 
                g_free (umenu);
792
 
        }
793
 
 
794
 
        g_list_free (info->user_menu);
795
 
        info->user_menu = NULL;
796
 
 
797
 
        g_free (info->id);
798
 
        info->id = NULL;
799
 
 
800
 
        g_free (info);
801
 
}
802
 
 
803
 
typedef struct {
804
 
        char            *id;
805
 
        PanelObjectType  type;
806
 
        char            *toplevel_id;
807
 
        int              position;
808
 
        guint            right_stick : 1;
809
 
        guint            locked : 1;
810
 
} PanelAppletToLoad;
811
 
 
812
 
/* Each time those lists get both empty,
813
 
 * panel_applet_queue_initial_unhide_toplevels() should be called */
814
 
static GSList  *panel_applets_to_load = NULL;
815
 
static GSList  *panel_applets_loading = NULL;
816
 
/* We have a timeout to always unhide toplevels after a delay, in case of some
817
 
 * blocking applet */
818
 
#define         UNHIDE_TOPLEVELS_TIMEOUT_SECONDS 5
819
 
static guint    panel_applet_unhide_toplevels_timeout = 0;
820
 
 
821
 
static gboolean panel_applet_have_load_idle = FALSE;
822
 
 
823
 
static void
824
 
free_applet_to_load (PanelAppletToLoad *applet)
825
 
{
826
 
        g_free (applet->id);
827
 
        applet->id = NULL;
828
 
 
829
 
        g_free (applet->toplevel_id);
830
 
        applet->toplevel_id = NULL;
831
 
 
832
 
        g_free (applet);
833
 
}
834
 
 
835
 
gboolean
836
 
panel_applet_on_load_queue (const char *id)
837
 
{
838
 
        GSList *li;
839
 
        for (li = panel_applets_to_load; li != NULL; li = li->next) {
840
 
                PanelAppletToLoad *applet = li->data;
841
 
                if (strcmp (applet->id, id) == 0)
842
 
                        return TRUE;
843
 
        }
844
 
        for (li = panel_applets_loading; li != NULL; li = li->next) {
845
 
                PanelAppletToLoad *applet = li->data;
846
 
                if (strcmp (applet->id, id) == 0)
847
 
                        return TRUE;
848
 
        }
849
 
        return FALSE;
850
 
}
851
 
 
852
 
/* This doesn't do anything if the initial unhide already happened */
853
 
static gboolean
854
 
panel_applet_queue_initial_unhide_toplevels (gpointer user_data)
855
 
{
856
 
        GSList *l;
857
 
 
858
 
        if (panel_applet_unhide_toplevels_timeout != 0) {
859
 
                g_source_remove (panel_applet_unhide_toplevels_timeout);
860
 
                panel_applet_unhide_toplevels_timeout = 0;
861
 
        }
862
 
 
863
 
        for (l = panel_toplevel_list_toplevels (); l != NULL; l = l->next)
864
 
                panel_toplevel_queue_initial_unhide ((PanelToplevel *) l->data);
865
 
 
866
 
        return FALSE;
867
 
}
868
 
 
869
 
void
870
 
panel_applet_stop_loading (const char *id)
871
 
{
872
 
        PanelAppletToLoad *applet;
873
 
        GSList *l;
874
 
 
875
 
        for (l = panel_applets_loading; l; l = l->next) {
876
 
                applet = l->data;
877
 
 
878
 
                if (strcmp (applet->id, id) == 0)
879
 
                        break;
880
 
        }
881
 
 
882
 
        /* this can happen if we reload an applet after it crashed,
883
 
         * for example */
884
 
        if (l != NULL) {
885
 
                panel_applets_loading = g_slist_delete_link (panel_applets_loading, l);
886
 
                free_applet_to_load (applet);
887
 
        }
888
 
 
889
 
        if (panel_applets_loading == NULL && panel_applets_to_load == NULL)
890
 
                panel_applet_queue_initial_unhide_toplevels (NULL);
891
 
}
892
 
 
893
 
static gboolean
894
 
panel_applet_load_idle_handler (gpointer dummy)
895
 
{
896
 
        PanelObjectType    applet_type;
897
 
        PanelAppletToLoad *applet = NULL;
898
 
        PanelToplevel     *toplevel = NULL;
899
 
        PanelWidget       *panel_widget;
900
 
        GSList            *l;
901
 
 
902
 
        if (!panel_applets_to_load) {
903
 
                panel_applet_have_load_idle = FALSE;
904
 
                return FALSE;
905
 
        }
906
 
 
907
 
        for (l = panel_applets_to_load; l; l = l->next) {
908
 
                applet = l->data;
909
 
 
910
 
                toplevel = panel_profile_get_toplevel_by_id (applet->toplevel_id);
911
 
                if (toplevel)
912
 
                        break;
913
 
        }
914
 
 
915
 
        if (!l) {
916
 
                /* All the remaining applets don't have a panel */
917
 
                for (l = panel_applets_to_load; l; l = l->next)
918
 
                        free_applet_to_load (l->data);
919
 
                g_slist_free (panel_applets_to_load);
920
 
                panel_applets_to_load = NULL;
921
 
                panel_applet_have_load_idle = FALSE;
922
 
 
923
 
                if (panel_applets_loading == NULL) {
924
 
                        /* unhide any potential initially hidden toplevel */
925
 
                        panel_applet_queue_initial_unhide_toplevels (NULL);
926
 
                }
927
 
 
928
 
                return FALSE;
929
 
        }
930
 
 
931
 
        panel_applets_to_load = g_slist_delete_link (panel_applets_to_load, l);
932
 
        panel_applets_loading = g_slist_append (panel_applets_loading, applet);
933
 
 
934
 
        panel_widget = panel_toplevel_get_panel_widget (toplevel);
935
 
 
936
 
        if (applet->right_stick) {
937
 
                if (!panel_widget->packed)
938
 
                        applet->position = panel_widget->size - applet->position;
939
 
                else
940
 
                        applet->position = -1;
941
 
        }
942
 
 
943
 
        /* We load applets asynchronously, so we specifically don't call
944
 
         * panel_applet_stop_loading() for this type. However, in case of
945
 
         * failure during the load, we might call panel_applet_stop_loading()
946
 
         * synchronously, which will make us lose the content of the applet
947
 
         * variable. So we save the type to be sure we always ignore the
948
 
         * applets. */
949
 
        applet_type = applet->type;
950
 
 
951
 
        switch (applet_type) {
952
 
        case PANEL_OBJECT_APPLET:
953
 
                panel_applet_frame_load_from_gconf (
954
 
                                        panel_widget,
955
 
                                        applet->locked,
956
 
                                        applet->position,
957
 
                                        applet->id);
958
 
                break;
959
 
        case PANEL_OBJECT_DRAWER:
960
 
                drawer_load_from_gconf (panel_widget,
961
 
                                        applet->locked,
962
 
                                        applet->position,
963
 
                                        applet->id);
964
 
                break;
965
 
        case PANEL_OBJECT_MENU:
966
 
                panel_menu_button_load_from_gconf (panel_widget,
967
 
                                                   applet->locked,
968
 
                                                   applet->position,
969
 
                                                   TRUE,
970
 
                                                   applet->id);
971
 
                break;
972
 
        case PANEL_OBJECT_LAUNCHER:
973
 
                launcher_load_from_gconf (panel_widget,
974
 
                                          applet->locked,
975
 
                                          applet->position,
976
 
                                          applet->id);
977
 
                break;
978
 
        case PANEL_OBJECT_LOGOUT:
979
 
        case PANEL_OBJECT_LOCK:
980
 
                panel_action_button_load_compatible (
981
 
                                applet->type,
982
 
                                panel_widget,
983
 
                                applet->locked,
984
 
                                applet->position,
985
 
                                TRUE,
986
 
                                applet->id);
987
 
                break;
988
 
        case PANEL_OBJECT_ACTION:
989
 
                panel_action_button_load_from_gconf (
990
 
                                panel_widget,
991
 
                                applet->locked,
992
 
                                applet->position,
993
 
                                TRUE,
994
 
                                applet->id);
995
 
                break;
996
 
        case PANEL_OBJECT_MENU_BAR:
997
 
                panel_menu_bar_load_from_gconf (
998
 
                                panel_widget,
999
 
                                applet->locked,
1000
 
                                applet->position,
1001
 
                                TRUE,
1002
 
                                applet->id);
1003
 
                break;
1004
 
        case PANEL_OBJECT_SEPARATOR:
1005
 
                panel_separator_load_from_gconf (panel_widget,
1006
 
                                                 applet->locked,
1007
 
                                                 applet->position,
1008
 
                                                 applet->id);
1009
 
                break;
1010
 
        default:
1011
 
                g_assert_not_reached ();
1012
 
                break;
1013
 
        }
1014
 
 
1015
 
        /* Only the real applets will do a late stop_loading */
1016
 
        if (applet_type != PANEL_OBJECT_APPLET)
1017
 
                panel_applet_stop_loading (applet->id);
1018
 
 
1019
 
        return TRUE;
1020
 
}
1021
 
 
1022
 
void
1023
 
panel_applet_queue_applet_to_load (const char      *id,
1024
 
                                   PanelObjectType  type,
1025
 
                                   const char      *toplevel_id,
1026
 
                                   int              position,
1027
 
                                   gboolean         right_stick,
1028
 
                                   gboolean         locked)
1029
 
{
1030
 
        PanelAppletToLoad *applet;
1031
 
 
1032
 
        if (!toplevel_id) {
1033
 
                g_warning ("No toplevel on which to load object '%s'\n", id);
1034
 
                return;
1035
 
        }
1036
 
 
1037
 
        applet = g_new0 (PanelAppletToLoad, 1);
1038
 
 
1039
 
        applet->id          = g_strdup (id);
1040
 
        applet->type        = type;
1041
 
        applet->toplevel_id = g_strdup (toplevel_id);
1042
 
        applet->position    = position;
1043
 
        applet->right_stick = right_stick != FALSE;
1044
 
        applet->locked      = locked != FALSE;
1045
 
 
1046
 
        panel_applets_to_load = g_slist_prepend (panel_applets_to_load, applet);
1047
 
}
1048
 
 
1049
 
static int
1050
 
panel_applet_compare (const PanelAppletToLoad *a,
1051
 
                      const PanelAppletToLoad *b)
1052
 
{
1053
 
        int c;
1054
 
 
1055
 
        if ((c = strcmp (a->toplevel_id, b->toplevel_id)))
1056
 
                return c;
1057
 
        else if (a->right_stick != b->right_stick)
1058
 
                return b->right_stick ? -1 : 1;
1059
 
        else
1060
 
                return a->position - b->position;
1061
 
}
1062
 
 
1063
 
void
1064
 
panel_applet_load_queued_applets (gboolean initial_load)
1065
 
{
1066
 
        if (!panel_applets_to_load) {
1067
 
                panel_applet_queue_initial_unhide_toplevels (NULL);
1068
 
                return;
1069
 
        }
1070
 
 
1071
 
        if (panel_applets_to_load && panel_applet_unhide_toplevels_timeout == 0) {
1072
 
                /* Install a timeout to make sure we don't block the
1073
 
                 * unhiding because of an applet that doesn't load */
1074
 
                panel_applet_unhide_toplevels_timeout =
1075
 
                        g_timeout_add_seconds (UNHIDE_TOPLEVELS_TIMEOUT_SECONDS,
1076
 
                                               panel_applet_queue_initial_unhide_toplevels,
1077
 
                                               NULL);
1078
 
        }
1079
 
 
1080
 
        panel_applets_to_load = g_slist_sort (panel_applets_to_load,
1081
 
                                              (GCompareFunc) panel_applet_compare);
1082
 
 
1083
 
        if ( ! panel_applet_have_load_idle) {
1084
 
                /* on panel startup, we don't care about redraws of the
1085
 
                 * toplevels since they are hidden, so we give a higher
1086
 
                 * priority to loading of applets */
1087
 
                if (initial_load)
1088
 
                        g_idle_add_full (G_PRIORITY_HIGH_IDLE,
1089
 
                                         panel_applet_load_idle_handler,
1090
 
                                         NULL, NULL);
1091
 
                else
1092
 
                        g_idle_add (panel_applet_load_idle_handler, NULL);
1093
 
 
1094
 
                panel_applet_have_load_idle = TRUE;
1095
 
        }
1096
 
}
1097
 
 
1098
 
static G_CONST_RETURN char *
1099
 
panel_applet_get_toplevel_id (AppletInfo *applet)
1100
 
{
1101
 
        PanelWidget *panel_widget;
1102
 
 
1103
 
        g_return_val_if_fail (applet != NULL, NULL);
1104
 
        g_return_val_if_fail (GTK_IS_WIDGET (applet->widget), NULL);
1105
 
 
1106
 
        panel_widget = panel_applet_get_panel_widget (applet);
1107
 
        if (!panel_widget)
1108
 
                return NULL;
1109
 
 
1110
 
        return panel_profile_get_toplevel_id (panel_widget->toplevel);
1111
 
}
1112
 
 
1113
 
static gboolean
1114
 
panel_applet_position_save_timeout (gpointer dummy)
1115
 
{
1116
 
        GSList *l;
1117
 
 
1118
 
        queued_position_source = 0;
1119
 
 
1120
 
        for (l = queued_position_saves; l; l = l->next) {
1121
 
                AppletInfo *info = l->data;
1122
 
 
1123
 
                panel_applet_save_position (info, info->id, TRUE);
1124
 
        }
1125
 
 
1126
 
        g_slist_free (queued_position_saves);
1127
 
        queued_position_saves = NULL;
1128
 
 
1129
 
        return FALSE;
1130
 
}
1131
 
 
1132
 
void
1133
 
panel_applet_save_position (AppletInfo *applet_info,
1134
 
                            const char *id,
1135
 
                            gboolean    immediate)
1136
 
{
1137
 
        PanelGConfKeyType  key_type;
1138
 
        GConfClient       *client;
1139
 
        PanelWidget       *panel_widget;
1140
 
        const char        *key;
1141
 
        const char        *toplevel_id;
1142
 
        char              *old_toplevel_id;
1143
 
        gboolean           right_stick;
1144
 
        gboolean           locked;
1145
 
        int                position;
1146
 
 
1147
 
        g_return_if_fail (applet_info != NULL);
1148
 
 
1149
 
        if (!immediate) {
1150
 
                if (!queued_position_source)
1151
 
                        queued_position_source =
1152
 
                                g_timeout_add_seconds (1,
1153
 
                                                       (GSourceFunc) panel_applet_position_save_timeout,
1154
 
                                                       NULL);
1155
 
 
1156
 
                if (!g_slist_find (queued_position_saves, applet_info))
1157
 
                        queued_position_saves =
1158
 
                                g_slist_prepend (queued_position_saves, applet_info);
1159
 
 
1160
 
                return;
1161
 
        }
1162
 
 
1163
 
        if (!(toplevel_id = panel_applet_get_toplevel_id (applet_info)))
1164
 
                return;
1165
 
 
1166
 
        client  = panel_gconf_get_client ();
1167
 
 
1168
 
        key_type = applet_info->type == PANEL_OBJECT_APPLET ? PANEL_GCONF_APPLETS : PANEL_GCONF_OBJECTS;
1169
 
        
1170
 
        panel_widget = panel_applet_get_panel_widget (applet_info);
1171
 
 
1172
 
        /* FIXME: Instead of getting keys, comparing and setting, there
1173
 
           should be a dirty flag */
1174
 
 
1175
 
        key = panel_gconf_full_key (key_type, id, "toplevel_id");
1176
 
        old_toplevel_id = gconf_client_get_string (client, key, NULL);
1177
 
        if (old_toplevel_id == NULL || strcmp (old_toplevel_id, toplevel_id) != 0)
1178
 
                gconf_client_set_string (client, key, toplevel_id, NULL);
1179
 
        g_free (old_toplevel_id);
1180
 
 
1181
 
        /* Note: changing some properties of the panel that may not be locked down
1182
 
           (e.g. background) can change the state of the "panel_right_stick" and
1183
 
           "position" properties of an applet that may in fact be locked down.
1184
 
           So check if these are writable before attempting to write them */
1185
 
 
1186
 
        right_stick = panel_is_applet_right_stick (applet_info->widget) ? 1 : 0;
1187
 
        key = panel_gconf_full_key (
1188
 
                        key_type, id, "panel_right_stick");
1189
 
        if (gconf_client_key_is_writable (client, key, NULL) &&
1190
 
            (gconf_client_get_bool (client, key, NULL) ? 1 : 0) != right_stick)
1191
 
                gconf_client_set_bool (client, key, right_stick, NULL);
1192
 
 
1193
 
        position = panel_applet_get_position (applet_info);
1194
 
        if (right_stick && !panel_widget->packed)
1195
 
                position = panel_widget->size - position;
1196
 
 
1197
 
        key = panel_gconf_full_key (key_type, id, "position");
1198
 
        if (gconf_client_key_is_writable (client, key, NULL) &&
1199
 
            gconf_client_get_int (client, key, NULL) != position)
1200
 
                gconf_client_set_int (client, key, position, NULL);
1201
 
        
1202
 
        locked = panel_widget_get_applet_locked (panel_widget, applet_info->widget) ? 1 : 0;
1203
 
        key = panel_gconf_full_key (key_type, id, "locked");
1204
 
        if (gconf_client_get_bool (client, key, NULL) ? 1 : 0 != locked)
1205
 
                gconf_client_set_bool (client, key, locked, NULL);
1206
 
}
1207
 
 
1208
 
const char *
1209
 
panel_applet_get_id (AppletInfo *info)
1210
 
{
1211
 
        if (!info)
1212
 
                return NULL;
1213
 
 
1214
 
        return info->id;
1215
 
}
1216
 
 
1217
 
const char *
1218
 
panel_applet_get_id_by_widget (GtkWidget *applet_widget)
1219
 
{
1220
 
        GSList *l;
1221
 
 
1222
 
        if (!applet_widget)
1223
 
                return NULL;
1224
 
 
1225
 
        for (l = registered_applets; l; l = l->next) {
1226
 
                AppletInfo *info = l->data;
1227
 
 
1228
 
                if (info->widget == applet_widget)
1229
 
                        return info->id;
1230
 
        }
1231
 
 
1232
 
        return NULL;
1233
 
}
1234
 
 
1235
 
AppletInfo *
1236
 
panel_applet_get_by_id (const char *id)
1237
 
{
1238
 
        GSList *l;
1239
 
 
1240
 
        for (l = registered_applets; l; l = l->next) {
1241
 
                AppletInfo *info = l->data;
1242
 
 
1243
 
                if (!strcmp (info->id, id))
1244
 
                        return info;
1245
 
        }
1246
 
 
1247
 
        return NULL;
1248
 
}
1249
 
 
1250
 
GSList *
1251
 
panel_applet_list_applets (void)
1252
 
{
1253
 
        return registered_applets;
1254
 
}
1255
 
 
1256
 
AppletInfo *
1257
 
panel_applet_get_by_type (PanelObjectType object_type, GdkScreen *screen)
1258
 
{
1259
 
        GSList *l;
1260
 
 
1261
 
        for (l = registered_applets; l; l = l->next) {
1262
 
                AppletInfo *info = l->data;
1263
 
 
1264
 
                if (info->type == object_type) {
1265
 
                        if (screen) {
1266
 
                                if (screen == gtk_widget_get_screen (info->widget))
1267
 
                                        return info;
1268
 
                        } else
1269
 
                                return info;
1270
 
                }
1271
 
        }
1272
 
 
1273
 
        return NULL;
1274
 
}
1275
 
 
1276
 
AppletInfo *
1277
 
panel_applet_register (GtkWidget       *applet,
1278
 
                       gpointer         data,
1279
 
                       GDestroyNotify   data_destroy,
1280
 
                       PanelWidget     *panel,
1281
 
                       gboolean         locked,
1282
 
                       gint             pos,
1283
 
                       gboolean         exactpos,
1284
 
                       PanelObjectType  type,
1285
 
                       const char      *id)
1286
 
{
1287
 
        AppletInfo *info;
1288
 
        const char *key;
1289
 
        
1290
 
        g_return_val_if_fail (applet != NULL && panel != NULL, NULL);
1291
 
 
1292
 
        if (gtk_widget_get_has_window (applet))
1293
 
                gtk_widget_set_events (applet, (gtk_widget_get_events (applet) |
1294
 
                                                APPLET_EVENT_MASK) &
1295
 
                                       ~( GDK_POINTER_MOTION_MASK |
1296
 
                                          GDK_POINTER_MOTION_HINT_MASK));
1297
 
 
1298
 
        info = g_new0 (AppletInfo, 1);
1299
 
        info->type         = type;
1300
 
        info->widget       = applet;
1301
 
        info->menu         = NULL;
1302
 
        info->data         = data;
1303
 
        info->data_destroy = data_destroy;
1304
 
        info->user_menu    = NULL;
1305
 
        info->move_item    = NULL;
1306
 
        info->id           = g_strdup (id);
1307
 
 
1308
 
        g_object_set_data (G_OBJECT (applet), "applet_info", info);
1309
 
 
1310
 
        if (type != PANEL_OBJECT_APPLET)
1311
 
                panel_lockdown_notify_add (G_CALLBACK (panel_applet_recreate_menu),
1312
 
                                           info);
1313
 
 
1314
 
        key = panel_gconf_full_key ((type == PANEL_OBJECT_APPLET) ?
1315
 
                                     PANEL_GCONF_APPLETS : PANEL_GCONF_OBJECTS,
1316
 
                                    id, "locked");
1317
 
        panel_gconf_notify_add_while_alive (key,
1318
 
                                            (GConfClientNotifyFunc) panel_applet_locked_change_notify,
1319
 
                                            G_OBJECT (applet));
1320
 
 
1321
 
        if (type == PANEL_OBJECT_DRAWER) {
1322
 
                Drawer *drawer = data;
1323
 
                PanelWidget *assoc_panel;
1324
 
 
1325
 
                assoc_panel = panel_toplevel_get_panel_widget (drawer->toplevel);
1326
 
 
1327
 
                g_object_set_data (G_OBJECT (applet),
1328
 
                                   PANEL_APPLET_ASSOC_PANEL_KEY, assoc_panel);
1329
 
                assoc_panel->master_widget = applet;
1330
 
                g_object_add_weak_pointer (
1331
 
                        G_OBJECT (applet), (gpointer *) &assoc_panel->master_widget);
1332
 
        }
1333
 
 
1334
 
        g_object_set_data (G_OBJECT (applet),
1335
 
                           PANEL_APPLET_FORBIDDEN_PANELS, NULL);
1336
 
 
1337
 
        registered_applets = g_slist_append (registered_applets, info);
1338
 
 
1339
 
        if (panel_widget_add (panel, applet, locked, pos, exactpos) == -1 &&
1340
 
            panel_widget_add (panel, applet, locked, 0, TRUE) == -1) {
1341
 
                GSList *l;
1342
 
 
1343
 
                for (l = panels; l; l = l->next) {
1344
 
                        panel = PANEL_WIDGET (l->data);
1345
 
 
1346
 
                        if (panel_widget_add (panel, applet, locked, 0, TRUE) != -1)
1347
 
                                break;
1348
 
                }
1349
 
 
1350
 
                if (!l) {
1351
 
                        g_warning (_("Cannot find an empty spot"));
1352
 
                        panel_profile_delete_object (info);
1353
 
                        return NULL;
1354
 
                }
1355
 
        }
1356
 
 
1357
 
        if (BUTTON_IS_WIDGET (applet) ||
1358
 
            gtk_widget_get_has_window (applet)) {
1359
 
                g_signal_connect (applet, "button_press_event",
1360
 
                                  G_CALLBACK (applet_button_press),
1361
 
                                  info);
1362
 
 
1363
 
                g_signal_connect (applet, "popup_menu",
1364
 
                                  G_CALLBACK (applet_popup_menu),
1365
 
                                  info);
1366
 
        }
1367
 
 
1368
 
        g_signal_connect (applet, "destroy",
1369
 
                          G_CALLBACK (panel_applet_destroy),
1370
 
                          info);
1371
 
 
1372
 
        panel_applet_set_dnd_enabled (info, !locked);
1373
 
 
1374
 
        gtk_widget_show_all (applet);
1375
 
 
1376
 
        orientation_change (info, panel);
1377
 
        size_change (info, panel);
1378
 
        back_change (info, panel);
1379
 
 
1380
 
        if (type != PANEL_OBJECT_APPLET)
1381
 
                gtk_widget_grab_focus (applet);
1382
 
        else
1383
 
                gtk_widget_child_focus (applet, GTK_DIR_TAB_FORWARD);
1384
 
 
1385
 
        return info;
1386
 
}
1387
 
 
1388
 
int
1389
 
panel_applet_get_position (AppletInfo *applet)
1390
 
{
1391
 
        AppletData *applet_data;
1392
 
 
1393
 
        g_return_val_if_fail (applet != NULL, 0);
1394
 
        g_return_val_if_fail (G_IS_OBJECT (applet->widget), 0);
1395
 
 
1396
 
        applet_data = g_object_get_data (G_OBJECT (applet->widget), PANEL_APPLET_DATA);
1397
 
 
1398
 
        return applet_data->pos;
1399
 
}
1400
 
 
1401
 
gboolean
1402
 
panel_applet_can_freely_move (AppletInfo *applet)
1403
 
{
1404
 
        GConfClient       *client;
1405
 
        PanelGConfKeyType  key_type;
1406
 
        const char        *key;
1407
 
 
1408
 
        if (panel_lockdown_get_locked_down ())
1409
 
                return FALSE;
1410
 
 
1411
 
        client  = panel_gconf_get_client ();
1412
 
        
1413
 
        key_type = (applet->type == PANEL_OBJECT_APPLET) ? PANEL_GCONF_APPLETS : PANEL_GCONF_OBJECTS;
1414
 
       
1415
 
        key = panel_gconf_full_key (key_type, applet->id, "position");
1416
 
        if (!gconf_client_key_is_writable (client, key, NULL))
1417
 
                return FALSE;
1418
 
 
1419
 
        key = panel_gconf_full_key (key_type, applet->id, "toplevel_id");
1420
 
        if (!gconf_client_key_is_writable (client, key, NULL))
1421
 
                return FALSE;
1422
 
 
1423
 
        key = panel_gconf_full_key (key_type, applet->id, "panel_right_stick");
1424
 
        if (!gconf_client_key_is_writable (client, key, NULL))
1425
 
                return FALSE;
1426
 
 
1427
 
        return TRUE;
1428
 
}
1429
 
 
1430
 
gboolean
1431
 
panel_applet_lockable (AppletInfo *applet)
1432
 
{
1433
 
        GConfClient        *client;
1434
 
        PanelGConfKeyType   key_type;
1435
 
        const char         *key;
1436
 
 
1437
 
        if (panel_lockdown_get_locked_down ())
1438
 
                return FALSE;
1439
 
        
1440
 
        client  = panel_gconf_get_client ();
1441
 
        
1442
 
        key_type = (applet->type == PANEL_OBJECT_APPLET) ? PANEL_GCONF_APPLETS : PANEL_GCONF_OBJECTS;
1443
 
 
1444
 
        key = panel_gconf_full_key (key_type, applet->id, "locked");
1445
 
 
1446
 
        return gconf_client_key_is_writable (client, key, NULL);
1447
 
}