~muktupavels/gnome-panel/fix-for-lp-1310929-and-lp-1222339

« back to all changes in this revision

Viewing changes to .pc/01_menus_rename.patch/gnome-panel/panel-menu-button.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-06-19 11:49:35 UTC
  • mfrom: (2.1.20 sid)
  • Revision ID: package-import@ubuntu.com-20130619114935-e912mx6nwxecoaib
Tags: 1:3.6.2-0ubuntu7
* Sync with Debian svn (LP: #1185873). Remaining changes:
  - Use epoch
  - Add apport hook
  - debian/control:
    + Recommend indicator-complete
    + Don't depend on nautilus 3.8 yet
  - debian/patches/14_revert_timedate_change.patch:
    + Dropped, we're using timedated
  - debian/patches/40_unset_menuproxy.patch:
    + Make sure gnome-panel and the applets don't pick up menu proxies.
  - debian/patches/41_classic_layout.patch:
    + Change the defaults to be more "classic Ubuntu": Show indicators
      & show desktop, drop GNOME clock & notification area
  - debian/patches/85_disable_shutdown_on_ltsp.patch:
    + Suppress the shutdown option in the panel if LTSP_CLIENT is set.
* debian/patches/50_ubuntu_sessions.patch:
  - Merge patch from gnome-session to split sessions into GNOME Flashback
    (No effects) using Metacity and GNOME Flashback using Compiz
* debian/patches/51_dont_require_nautilus38.patch:
  - Run Flashback without Nautilus 3.8 since it's not in Saucy yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * panel-menu-button.c: panel menu button
 
3
 *
 
4
 * Copyright (C) 2003 Sun Microsystems, Inc.
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License as
 
8
 * published by the Free Software Foundation; either version 2 of the
 
9
 * License, or (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful, but
 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
19
 * 02111-1307, USA.
 
20
 *
 
21
 * Authors:
 
22
 *      Mark McLoughlin <mark@skynet.ie>
 
23
 */
 
24
 
 
25
#include <config.h>
 
26
 
 
27
#include "panel-menu-button.h"
 
28
 
 
29
#include <string.h>
 
30
#include <glib/gi18n.h>
 
31
 
 
32
#include <gmenu-tree.h>
 
33
 
 
34
#include <libpanel-util/panel-error.h>
 
35
#include <libpanel-util/panel-glib.h>
 
36
#include <libpanel-util/panel-launch.h>
 
37
 
 
38
#include "applet.h"
 
39
#include "panel-widget.h"
 
40
#include "panel-util.h"
 
41
#include "panel-globals.h"
 
42
#include "menu.h"
 
43
#include "panel-lockdown.h"
 
44
#include "panel-a11y.h"
 
45
#include "panel-layout.h"
 
46
#include "panel-icon-names.h"
 
47
#include "panel-schemas.h"
 
48
 
 
49
G_DEFINE_TYPE (PanelMenuButton, panel_menu_button, BUTTON_TYPE_WIDGET)
 
50
 
 
51
#define PANEL_MENU_BUTTON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_MENU_BUTTON, PanelMenuButtonPrivate))
 
52
 
 
53
enum {
 
54
        PROP_0,
 
55
        PROP_MENU_PATH,
 
56
        PROP_CUSTOM_ICON,
 
57
        PROP_TOOLTIP,
 
58
        PROP_DND_ENABLED
 
59
};
 
60
 
 
61
typedef enum {
 
62
        FIRST_MENU,
 
63
        APPLICATIONS_MENU,
 
64
#define DEFAULT_MENU      APPLICATIONS_MENU
 
65
        GNOMECC_MENU,
 
66
        LAST_MENU
 
67
} MenuPathRoot;
 
68
 
 
69
typedef struct {
 
70
        MenuPathRoot  root_id;
 
71
        char         *scheme;
 
72
        char         *filename;
 
73
} MenuPathRootItem;
 
74
 
 
75
static MenuPathRootItem root_items [] = {
 
76
        { APPLICATIONS_MENU, "applications", "applications.menu" },
 
77
        { GNOMECC_MENU,      "gnomecc",      "gnomecc.menu"      }
 
78
};
 
79
 
 
80
struct _PanelMenuButtonPrivate {
 
81
        PanelToplevel         *toplevel;
 
82
        GSettings             *settings_instance;
 
83
 
 
84
        GtkWidget             *menu;
 
85
 
 
86
        char                  *menu_path;
 
87
        char                  *custom_icon;
 
88
        char                  *tooltip;
 
89
 
 
90
        MenuPathRoot           path_root;
 
91
        guint                  dnd_enabled : 1;
 
92
};
 
93
 
 
94
static void panel_menu_button_set_icon              (PanelMenuButton *button);
 
95
 
 
96
static AtkObject *panel_menu_button_get_accessible  (GtkWidget       *widget);
 
97
 
 
98
static const char *
 
99
panel_menu_path_root_to_filename (MenuPathRoot path_root)
 
100
{
 
101
        const char *retval;
 
102
        int         i;
 
103
 
 
104
        retval = NULL;
 
105
 
 
106
        for (i = 0; i < G_N_ELEMENTS (root_items); i++) {
 
107
                if (root_items [i].root_id == path_root) {
 
108
                        retval = root_items [i].filename;
 
109
                        break;
 
110
                }
 
111
        }
 
112
 
 
113
        return retval;
 
114
}
 
115
 
 
116
static const char *
 
117
panel_menu_filename_to_scheme (const char *filename)
 
118
{
 
119
        const char *retval;
 
120
        int         i;
 
121
 
 
122
        retval = NULL;
 
123
        
 
124
        if (!filename)
 
125
                return retval;
 
126
 
 
127
        for (i = 0; i < G_N_ELEMENTS (root_items); i++) {
 
128
                if (root_items [i].filename &&
 
129
                    !strncmp (filename, root_items [i].filename,
 
130
                              strlen (root_items [i].filename))) {
 
131
                        retval = root_items [i].scheme;
 
132
                        break;
 
133
                }
 
134
        }
 
135
 
 
136
        return retval;
 
137
}
 
138
 
 
139
static MenuPathRoot
 
140
panel_menu_scheme_to_path_root (const char *scheme)
 
141
{
 
142
        MenuPathRoot retval;
 
143
        int          i;
 
144
 
 
145
        retval = LAST_MENU;
 
146
        
 
147
        if (!scheme)
 
148
                return retval;
 
149
 
 
150
        for (i = 0; i < G_N_ELEMENTS (root_items); i++) {
 
151
                if (root_items [i].scheme &&
 
152
                    !strncmp (scheme, root_items [i].scheme,
 
153
                              strlen (root_items [i].scheme))) {
 
154
                        retval = root_items [i].root_id;
 
155
                        break;
 
156
                }
 
157
        }
 
158
 
 
159
        return retval;
 
160
}
 
161
 
 
162
static void
 
163
panel_menu_button_init (PanelMenuButton *button)
 
164
{
 
165
        button->priv = PANEL_MENU_BUTTON_GET_PRIVATE (button);
 
166
 
 
167
        button->priv->toplevel          = NULL;
 
168
        button->priv->settings_instance = NULL;
 
169
 
 
170
        button->priv->menu_path   = NULL;
 
171
        button->priv->custom_icon = NULL;
 
172
        button->priv->tooltip = NULL;
 
173
 
 
174
        button->priv->path_root       = LAST_MENU;
 
175
}
 
176
 
 
177
static void
 
178
panel_menu_button_finalize (GObject *object)
 
179
{
 
180
        PanelMenuButton *button = PANEL_MENU_BUTTON (object);
 
181
 
 
182
        if (button->priv->menu) {
 
183
                /* detaching the menu will kill our reference */
 
184
                gtk_menu_detach (GTK_MENU (button->priv->menu));
 
185
                button->priv->menu = NULL;
 
186
        }
 
187
 
 
188
        if (button->priv->settings_instance)
 
189
                g_object_unref (button->priv->settings_instance);
 
190
        button->priv->settings_instance = NULL;
 
191
 
 
192
        g_free (button->priv->menu_path);
 
193
        button->priv->menu_path = NULL;
 
194
 
 
195
        g_free (button->priv->custom_icon);
 
196
        button->priv->custom_icon = NULL;
 
197
 
 
198
        g_free (button->priv->tooltip);
 
199
        button->priv->tooltip = NULL;
 
200
 
 
201
        G_OBJECT_CLASS (panel_menu_button_parent_class)->finalize (object);
 
202
}
 
203
 
 
204
static void
 
205
panel_menu_button_get_property (GObject    *object,
 
206
                                guint       prop_id,
 
207
                                GValue     *value,
 
208
                                GParamSpec *pspec)
 
209
{
 
210
        PanelMenuButton *button;
 
211
 
 
212
        g_return_if_fail (PANEL_IS_MENU_BUTTON (object));
 
213
 
 
214
        button = PANEL_MENU_BUTTON (object);
 
215
 
 
216
        switch (prop_id) {
 
217
        case PROP_MENU_PATH:
 
218
                g_value_set_string (value, button->priv->menu_path);
 
219
                break;
 
220
        case PROP_CUSTOM_ICON:
 
221
                g_value_set_string (value, button->priv->custom_icon);
 
222
                break;
 
223
        case PROP_TOOLTIP:
 
224
                g_value_set_string (value, button->priv->tooltip);
 
225
                break;
 
226
        case PROP_DND_ENABLED:
 
227
                g_value_set_boolean (value, button->priv->dnd_enabled);
 
228
                break;
 
229
        default:
 
230
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
231
                break;
 
232
        }
 
233
}
 
234
 
 
235
static void
 
236
panel_menu_button_set_property (GObject      *object,
 
237
                                guint         prop_id,
 
238
                                const GValue *value,
 
239
                                GParamSpec   *pspec)
 
240
{
 
241
        PanelMenuButton *button;
 
242
 
 
243
        g_return_if_fail (PANEL_IS_MENU_BUTTON (object));
 
244
 
 
245
        button = PANEL_MENU_BUTTON (object);
 
246
 
 
247
        switch (prop_id) {
 
248
        case PROP_MENU_PATH:
 
249
                panel_menu_button_set_menu_path (button, g_value_get_string (value));
 
250
                break;
 
251
        case PROP_CUSTOM_ICON:
 
252
                panel_menu_button_set_custom_icon (button, g_value_get_string (value));
 
253
                break;
 
254
        case PROP_TOOLTIP:
 
255
                panel_menu_button_set_tooltip (button, g_value_get_string (value));
 
256
                break;
 
257
        case PROP_DND_ENABLED:
 
258
                panel_menu_button_set_dnd_enabled (button, g_value_get_boolean (value));
 
259
                break;
 
260
        default:
 
261
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
262
                break;
 
263
        }
 
264
}
 
265
 
 
266
static void
 
267
panel_menu_button_associate_panel (PanelMenuButton *button)
 
268
{
 
269
        PanelWidget *panel_widget = NULL;
 
270
 
 
271
        if (!button->priv->menu)
 
272
                return;
 
273
 
 
274
        if (button->priv->toplevel)
 
275
                panel_widget = panel_toplevel_get_panel_widget (button->priv->toplevel);
 
276
 
 
277
        panel_applet_menu_set_recurse (GTK_MENU (button->priv->menu), "menu_panel", panel_widget);
 
278
}
 
279
 
 
280
static void
 
281
panel_menu_button_parent_set (GtkWidget *widget,
 
282
                              GtkWidget *previous_parent)
 
283
{
 
284
        PanelMenuButton *button = PANEL_MENU_BUTTON (widget);
 
285
        GtkWidget       *parent;
 
286
 
 
287
        parent = gtk_widget_get_parent (widget);
 
288
        g_return_if_fail (!parent || PANEL_IS_WIDGET (parent));
 
289
 
 
290
        if (parent)
 
291
                button->priv->toplevel = PANEL_WIDGET (parent)->toplevel;
 
292
        else
 
293
                button->priv->toplevel = NULL;
 
294
 
 
295
        panel_menu_button_associate_panel (button);
 
296
        panel_menu_button_set_icon (button);
 
297
 
 
298
        if (GTK_WIDGET_CLASS (panel_menu_button_parent_class)->parent_set)
 
299
                GTK_WIDGET_CLASS (panel_menu_button_parent_class)->parent_set (widget, previous_parent);
 
300
}
 
301
 
 
302
static void
 
303
panel_menu_button_drag_data_get (GtkWidget        *widget,
 
304
                                 GdkDragContext   *context,
 
305
                                 GtkSelectionData *selection_data,
 
306
                                 guint             info,
 
307
                                 guint             time)
 
308
{
 
309
        char            *drag_data;
 
310
 
 
311
        g_return_if_fail (PANEL_IS_MENU_BUTTON (widget));
 
312
 
 
313
        drag_data = g_strdup_printf ("MENU:%d", panel_find_applet_index (widget));
 
314
 
 
315
        gtk_selection_data_set (
 
316
                selection_data, gtk_selection_data_get_target (selection_data),
 
317
                8, (guchar *) drag_data, strlen (drag_data));
 
318
 
 
319
        g_free (drag_data);
 
320
}
 
321
 
 
322
static void
 
323
panel_menu_button_menu_deactivated (PanelMenuButton *button)
 
324
{
 
325
        panel_toplevel_pop_autohide_disabler (button->priv->toplevel);
 
326
 
 
327
        gtk_widget_unset_state_flags (GTK_WIDGET (button),
 
328
                                      GTK_STATE_FLAG_PRELIGHT);
 
329
 
 
330
        button_widget_set_ignore_leave (BUTTON_WIDGET (button), FALSE);
 
331
}
 
332
 
 
333
static void 
 
334
panel_menu_button_menu_detacher (PanelMenuButton *button)
 
335
{
 
336
        /*
 
337
         * just in case someone still owns a reference to the
 
338
         * menu (the menu may be up or some such other nonsense)
 
339
         */
 
340
        g_signal_handlers_disconnect_by_func (button->priv->menu,
 
341
                                              G_CALLBACK (panel_menu_button_menu_deactivated),
 
342
                                              button);
 
343
 
 
344
        button->priv->menu = NULL;
 
345
}
 
346
 
 
347
static GtkWidget *
 
348
panel_menu_button_create_menu (PanelMenuButton *button)
 
349
{
 
350
        PanelWidget *panel_widget;
 
351
 
 
352
        if (button->priv->menu)
 
353
                return button->priv->menu;
 
354
 
 
355
        if (!button->priv->toplevel)
 
356
                return NULL;
 
357
 
 
358
        panel_widget = panel_toplevel_get_panel_widget (button->priv->toplevel);
 
359
 
 
360
        if (!PANEL_GLIB_STR_EMPTY (button->priv->menu_path) &&
 
361
            button->priv->path_root > FIRST_MENU            &&
 
362
            button->priv->path_root < LAST_MENU) {
 
363
                const char *filename;
 
364
 
 
365
                filename = panel_menu_path_root_to_filename (button->priv->path_root);
 
366
                button->priv->menu = create_applications_menu (filename,
 
367
                                                               button->priv->menu_path,
 
368
                                                               TRUE);
 
369
        } else
 
370
                button->priv->menu = create_main_menu (panel_widget);
 
371
 
 
372
        gtk_menu_attach_to_widget (GTK_MENU (button->priv->menu),
 
373
                                   GTK_WIDGET (button),
 
374
                                   (GtkMenuDetachFunc) panel_menu_button_menu_detacher);
 
375
 
 
376
        panel_menu_button_associate_panel (button);
 
377
 
 
378
        g_signal_connect_swapped (button->priv->menu, "deactivate",
 
379
                                  G_CALLBACK (panel_menu_button_menu_deactivated),
 
380
                                  button);
 
381
 
 
382
        return button->priv->menu;
 
383
}
 
384
 
 
385
void
 
386
panel_menu_button_popup_menu (PanelMenuButton *button,
 
387
                              guint            n_button,
 
388
                              guint32          activate_time)
 
389
{
 
390
        GdkScreen *screen;
 
391
 
 
392
        g_return_if_fail (PANEL_IS_MENU_BUTTON (button));
 
393
 
 
394
        panel_menu_button_create_menu (button);
 
395
 
 
396
        panel_toplevel_push_autohide_disabler (button->priv->toplevel);
 
397
 
 
398
        button_widget_set_ignore_leave (BUTTON_WIDGET (button), TRUE);
 
399
 
 
400
        screen = gtk_window_get_screen (GTK_WINDOW (button->priv->toplevel));
 
401
        gtk_menu_set_screen (GTK_MENU (button->priv->menu), screen);
 
402
 
 
403
        gtk_menu_popup (GTK_MENU (button->priv->menu),
 
404
                        NULL,
 
405
                        NULL,
 
406
                        (GtkMenuPositionFunc) panel_applet_position_menu,
 
407
                        GTK_WIDGET (button),
 
408
                        n_button,
 
409
                        activate_time);
 
410
}
 
411
 
 
412
static void
 
413
panel_menu_button_pressed (GtkButton *gtk_button)
 
414
{
 
415
        PanelMenuButton *button;
 
416
 
 
417
        g_return_if_fail (PANEL_IS_MENU_BUTTON (gtk_button));
 
418
 
 
419
        button = PANEL_MENU_BUTTON (gtk_button);
 
420
 
 
421
        if (GTK_BUTTON_CLASS (panel_menu_button_parent_class)->pressed)
 
422
                GTK_BUTTON_CLASS (panel_menu_button_parent_class)->pressed (gtk_button);
 
423
 
 
424
        panel_menu_button_popup_menu (button, 0, gtk_get_current_event_time());
 
425
}
 
426
 
 
427
static void
 
428
panel_menu_button_clicked (GtkButton *gtk_button)
 
429
{
 
430
        PanelMenuButton *button;
 
431
        GdkEvent        *event;
 
432
 
 
433
        g_return_if_fail (PANEL_IS_MENU_BUTTON (gtk_button));
 
434
 
 
435
        button = PANEL_MENU_BUTTON (gtk_button);
 
436
 
 
437
        if (GTK_BUTTON_CLASS (panel_menu_button_parent_class)->clicked)
 
438
                GTK_BUTTON_CLASS (panel_menu_button_parent_class)->clicked (gtk_button);
 
439
 
 
440
        if ((event = gtk_get_current_event ())) {
 
441
                panel_menu_button_popup_menu (button,
 
442
                                              event->button.button,
 
443
                                              event->button.time);
 
444
                gdk_event_free (event);
 
445
        } else {
 
446
                panel_menu_button_popup_menu (button, 1, GDK_CURRENT_TIME);
 
447
        }
 
448
}
 
449
 
 
450
static void
 
451
panel_menu_button_class_init (PanelMenuButtonClass *klass)
 
452
{
 
453
        GObjectClass   *gobject_class = (GObjectClass   *) klass;
 
454
        GtkWidgetClass *widget_class  = (GtkWidgetClass *) klass;
 
455
        GtkButtonClass *button_class  = (GtkButtonClass *) klass;
 
456
 
 
457
        gobject_class->finalize     = panel_menu_button_finalize;
 
458
        gobject_class->get_property = panel_menu_button_get_property;
 
459
        gobject_class->set_property = panel_menu_button_set_property;
 
460
 
 
461
        widget_class->parent_set     = panel_menu_button_parent_set;
 
462
        widget_class->drag_data_get  = panel_menu_button_drag_data_get;
 
463
        widget_class->get_accessible = panel_menu_button_get_accessible;
 
464
 
 
465
        button_class->clicked = panel_menu_button_clicked;
 
466
        button_class->pressed = panel_menu_button_pressed;
 
467
 
 
468
        g_type_class_add_private (klass, sizeof (PanelMenuButtonPrivate));
 
469
 
 
470
        g_object_class_install_property (
 
471
                        gobject_class,
 
472
                        PROP_MENU_PATH,
 
473
                        g_param_spec_string ("menu-path",
 
474
                                             "Menu Path",
 
475
                                             "The path from which to construct the menu",
 
476
                                             NULL,
 
477
                                             G_PARAM_READWRITE));
 
478
 
 
479
        g_object_class_install_property (
 
480
                        gobject_class,
 
481
                        PROP_CUSTOM_ICON,
 
482
                        g_param_spec_string ("custom-icon",
 
483
                                             "Custom Icon",
 
484
                                             "The custom icon for the menu",
 
485
                                             NULL,
 
486
                                             G_PARAM_READWRITE));
 
487
 
 
488
        g_object_class_install_property (
 
489
                        gobject_class,
 
490
                        PROP_TOOLTIP,
 
491
                        g_param_spec_string ("tooltip",
 
492
                                             "Tooltip",
 
493
                                             "Tooltip displayed for the menu",
 
494
                                             NULL,
 
495
                                             G_PARAM_READWRITE));
 
496
 
 
497
        g_object_class_install_property (
 
498
                        gobject_class,
 
499
                        PROP_DND_ENABLED,
 
500
                        g_param_spec_boolean ("dnd-enabled",
 
501
                                              "Drag and drop enabled",
 
502
                                              "Whether or not drag and drop is enabled on the widget",
 
503
                                              FALSE,
 
504
                                              G_PARAM_READWRITE));
 
505
}
 
506
 
 
507
static void
 
508
panel_menu_button_settings_changed (GSettings       *settings,
 
509
                                    char            *key,
 
510
                                    PanelMenuButton *button)
 
511
{
 
512
        char *value = NULL;
 
513
 
 
514
        if (g_strcmp0 (key, PANEL_MENU_BUTTON_MENU_PATH_KEY) == 0) {
 
515
                value = g_settings_get_string (settings, key);
 
516
                panel_menu_button_set_menu_path (button, value);
 
517
        } else if (g_strcmp0 (key, PANEL_MENU_BUTTON_CUSTOM_ICON_KEY) == 0) {
 
518
                value = g_settings_get_string (settings, key);
 
519
                panel_menu_button_set_custom_icon (button, value);
 
520
        } else if (g_strcmp0 (key, PANEL_MENU_BUTTON_TOOLTIP_KEY) == 0) {
 
521
                value = g_settings_get_string (settings, key);
 
522
                panel_menu_button_set_tooltip (button, value);
 
523
        }
 
524
 
 
525
        g_free (value);
 
526
}
 
527
 
 
528
static void
 
529
panel_menu_button_load_helper (const char  *menu_path,
 
530
                               const char  *custom_icon,
 
531
                               const char  *tooltip,
 
532
                               PanelWidget *panel,
 
533
                               const char  *id,
 
534
                               GSettings   *settings)
 
535
{
 
536
        PanelMenuButton *button;
 
537
        AppletInfo      *info;
 
538
 
 
539
        g_return_if_fail (panel != NULL);
 
540
 
 
541
        button = g_object_new (PANEL_TYPE_MENU_BUTTON,
 
542
                               "menu-path", menu_path,
 
543
                               "custom-icon", custom_icon,
 
544
                               "tooltip", tooltip,
 
545
                               "has-arrow", TRUE,
 
546
                               NULL);
 
547
 
 
548
        info = panel_applet_register (GTK_WIDGET (button),
 
549
                                      panel,
 
550
                                      PANEL_OBJECT_MENU, id,
 
551
                                      settings,
 
552
                                      NULL, NULL);
 
553
        if (!info) {
 
554
                gtk_widget_destroy (GTK_WIDGET (button));
 
555
                return;
 
556
        }
 
557
 
 
558
        if (panel_is_program_in_path ("alacarte") ||
 
559
            panel_is_program_in_path ("gmenu-simple-editor"))
 
560
                panel_applet_add_callback (info, "edit", NULL,
 
561
                                           _("_Edit Menus"),
 
562
                                           panel_lockdown_get_not_panels_locked_down_s);
 
563
 
 
564
        panel_widget_set_applet_expandable (panel, GTK_WIDGET (button), FALSE, TRUE);
 
565
        panel_widget_set_applet_size_constrained (panel, GTK_WIDGET (button), TRUE);
 
566
 
 
567
        button->priv->settings_instance = panel_layout_get_instance_settings (
 
568
                                                        settings,
 
569
                                                        PANEL_MENU_BUTTON_SCHEMA);
 
570
 
 
571
        g_signal_connect (button->priv->settings_instance, "changed",
 
572
                          G_CALLBACK (panel_menu_button_settings_changed),
 
573
                          button);
 
574
}
 
575
 
 
576
static GIcon *
 
577
panel_menu_button_get_icon (PanelMenuButton *button)
 
578
{
 
579
        GMenuTreeDirectory *directory;
 
580
        GIcon              *retval;
 
581
 
 
582
        retval = NULL;
 
583
 
 
584
        if (!PANEL_GLIB_STR_EMPTY (button->priv->custom_icon))
 
585
                retval = g_themed_icon_new (button->priv->custom_icon);
 
586
 
 
587
        if (!retval                                         &&
 
588
            !PANEL_GLIB_STR_EMPTY (button->priv->menu_path) &&
 
589
            panel_menu_button_create_menu (button)) {
 
590
                directory = g_object_get_data (G_OBJECT (button->priv->menu),
 
591
                                               "panel-menu-tree-directory");
 
592
 
 
593
                if (!directory) {
 
594
                        GMenuTree *tree;
 
595
 
 
596
                        if ((tree = g_object_get_data (G_OBJECT (button->priv->menu),
 
597
                                                       "panel-menu-tree"))) {
 
598
                                directory = gmenu_tree_get_directory_from_path (tree,
 
599
                                                                                button->priv->menu_path);
 
600
                                g_object_set_data_full (G_OBJECT (button->priv->menu),
 
601
                                                        "panel-menu-tree-directory",
 
602
                                                        directory,
 
603
                                                        (GDestroyNotify) gmenu_tree_item_unref);
 
604
                        }
 
605
                }
 
606
 
 
607
                if (directory)
 
608
                        retval = g_object_ref (gmenu_tree_directory_get_icon (directory));
 
609
        }
 
610
 
 
611
        if (!retval)
 
612
                retval = g_themed_icon_new (PANEL_ICON_MAIN_MENU);
 
613
 
 
614
        return retval;
 
615
}
 
616
 
 
617
static void
 
618
panel_menu_button_set_icon (PanelMenuButton *button)
 
619
{
 
620
        GIcon *gicon;
 
621
        char  *icon;
 
622
 
 
623
        gicon = panel_menu_button_get_icon (button);
 
624
        icon = panel_util_get_icon_name_from_g_icon (gicon);
 
625
 
 
626
        button_widget_set_icon_name (BUTTON_WIDGET (button), icon);
 
627
 
 
628
        g_free (icon);
 
629
        g_object_unref (gicon);
 
630
}
 
631
 
 
632
static const char *
 
633
split_menu_uri (const char  *menu_uri,
 
634
                char       **menu_scheme)
 
635
{
 
636
        char *p;
 
637
 
 
638
        if (!menu_uri)
 
639
                return NULL;
 
640
 
 
641
        p = strchr (menu_uri, ':');
 
642
 
 
643
        if (!p || p == menu_uri)
 
644
                return NULL;
 
645
 
 
646
        if (menu_scheme)
 
647
                *menu_scheme = g_strndup (menu_uri, p - menu_uri);
 
648
 
 
649
        if (*(++p) != '/')
 
650
                return NULL;
 
651
 
 
652
        while (*p != '\0' && *(p + 1) == '/') p++;
 
653
 
 
654
        return p;
 
655
}
 
656
 
 
657
gboolean
 
658
panel_menu_button_is_main_menu (PanelMenuButton *button)
 
659
{
 
660
        g_return_val_if_fail (PANEL_IS_MENU_BUTTON (button), FALSE);
 
661
 
 
662
        return PANEL_GLIB_STR_EMPTY (button->priv->menu_path);
 
663
}
 
664
 
 
665
void
 
666
panel_menu_button_set_menu_path (PanelMenuButton *button,
 
667
                                 const char      *menu_uri)
 
668
{
 
669
        const char *menu_path;
 
670
        char       *scheme;
 
671
 
 
672
        g_return_if_fail (PANEL_IS_MENU_BUTTON (button));
 
673
 
 
674
        scheme    = NULL;
 
675
        menu_path = split_menu_uri (menu_uri, &scheme);
 
676
 
 
677
        if (!scheme)
 
678
                return;
 
679
 
 
680
        button->priv->path_root = panel_menu_scheme_to_path_root (scheme);
 
681
        g_free (scheme);
 
682
 
 
683
        if (!button->priv->menu_path && (!menu_path || !menu_path [0]))
 
684
                return;
 
685
 
 
686
        if (button->priv->menu_path && menu_path &&
 
687
            !strcmp (button->priv->menu_path, menu_path))
 
688
                return;
 
689
 
 
690
        g_free (button->priv->menu_path);
 
691
        button->priv->menu_path = NULL;
 
692
 
 
693
        button->priv->menu_path = g_strdup (menu_path);
 
694
 
 
695
        if (button->priv->menu)
 
696
                gtk_menu_detach (GTK_MENU (button->priv->menu));
 
697
        button->priv->menu = NULL;
 
698
 
 
699
        panel_menu_button_set_icon (button);
 
700
}
 
701
 
 
702
void
 
703
panel_menu_button_set_custom_icon (PanelMenuButton *button,
 
704
                                   const char      *custom_icon)
 
705
{
 
706
        g_return_if_fail (PANEL_IS_MENU_BUTTON (button));
 
707
 
 
708
        g_free (button->priv->custom_icon);
 
709
        button->priv->custom_icon = NULL;
 
710
 
 
711
        if (custom_icon && custom_icon [0])
 
712
                button->priv->custom_icon = g_strdup (custom_icon);
 
713
 
 
714
        panel_menu_button_set_icon (button);
 
715
}
 
716
 
 
717
void
 
718
panel_menu_button_set_tooltip (PanelMenuButton *button,
 
719
                               const char      *tooltip)
 
720
{
 
721
        g_return_if_fail (PANEL_IS_MENU_BUTTON (button));
 
722
 
 
723
        g_free (button->priv->tooltip);
 
724
        button->priv->tooltip = g_strdup (tooltip);
 
725
 
 
726
        panel_util_set_tooltip_text (GTK_WIDGET (button), tooltip);
 
727
}
 
728
 
 
729
void
 
730
panel_menu_button_load (PanelWidget *panel,
 
731
                        const char  *id,
 
732
                        GSettings   *settings)
 
733
{
 
734
        GSettings    *settings_instance;
 
735
        char         *scheme;
 
736
        MenuPathRoot  root;
 
737
        char         *menu_path;
 
738
        char         *custom_icon;
 
739
        char         *tooltip;
 
740
 
 
741
        settings_instance = panel_layout_get_instance_settings (settings,
 
742
                                                                PANEL_MENU_BUTTON_SCHEMA);
 
743
 
 
744
        menu_path = g_settings_get_string (settings_instance,
 
745
                                           PANEL_MENU_BUTTON_MENU_PATH_KEY);
 
746
        custom_icon = g_settings_get_string (settings_instance,
 
747
                                             PANEL_MENU_BUTTON_CUSTOM_ICON_KEY);
 
748
        tooltip = g_settings_get_string (settings_instance,
 
749
                                         PANEL_MENU_BUTTON_TOOLTIP_KEY);
 
750
 
 
751
        if (!PANEL_GLIB_STR_EMPTY (menu_path)) {
 
752
                scheme = g_strndup (menu_path, strcspn (menu_path, ":"));
 
753
                root = panel_menu_scheme_to_path_root (scheme);
 
754
                g_free (scheme);
 
755
        } else
 
756
                root = APPLICATIONS_MENU;
 
757
 
 
758
        if (root == LAST_MENU) {
 
759
                g_printerr ("Unknown menu scheme, cannot load menu button\n");
 
760
 
 
761
                g_free (menu_path);
 
762
                g_free (custom_icon);
 
763
                g_free (tooltip);
 
764
                g_object_unref (settings_instance);
 
765
 
 
766
                return;
 
767
        }
 
768
 
 
769
        panel_menu_button_load_helper (menu_path,
 
770
                                       custom_icon,
 
771
                                       tooltip,
 
772
                                       panel,
 
773
                                       id,
 
774
                                       settings);
 
775
 
 
776
        g_free (menu_path);
 
777
        g_free (custom_icon);
 
778
        g_free (tooltip);
 
779
 
 
780
        g_object_unref (settings_instance);
 
781
}
 
782
 
 
783
gboolean
 
784
panel_menu_button_create (PanelToplevel       *toplevel,
 
785
                          PanelObjectPackType  pack_type,
 
786
                          int                  pack_index,
 
787
                          const char          *filename,
 
788
                          const char          *menu_path,
 
789
                          const char          *tooltip)
 
790
{
 
791
        char       *id;
 
792
        GSettings  *settings;
 
793
        GSettings  *settings_instance;
 
794
        const char *scheme;
 
795
 
 
796
        scheme = panel_menu_filename_to_scheme (filename);
 
797
 
 
798
        if (filename && !scheme) {
 
799
                g_warning ("Failed to find menu scheme for %s\n", filename);
 
800
                return FALSE;
 
801
        }
 
802
 
 
803
        id = panel_layout_object_create_start (PANEL_OBJECT_MENU, NULL,
 
804
                                               panel_toplevel_get_id (toplevel),
 
805
                                               pack_type, pack_index,
 
806
                                               &settings);
 
807
 
 
808
        settings_instance = panel_layout_get_instance_settings (settings,
 
809
                                                                PANEL_MENU_BUTTON_SCHEMA);
 
810
 
 
811
        if (!PANEL_GLIB_STR_EMPTY (menu_path) && scheme) {
 
812
                char *menu_uri;
 
813
 
 
814
                menu_uri = g_strconcat (scheme, ":", menu_path, NULL);
 
815
 
 
816
                g_settings_set_string (settings_instance,
 
817
                                       PANEL_MENU_BUTTON_MENU_PATH_KEY,
 
818
                                       menu_uri);
 
819
 
 
820
                g_free (menu_uri);
 
821
        }
 
822
 
 
823
        if (!PANEL_GLIB_STR_EMPTY (tooltip)) {
 
824
                g_settings_set_string (settings_instance,
 
825
                                       PANEL_MENU_BUTTON_TOOLTIP_KEY,
 
826
                                       tooltip);
 
827
        }
 
828
 
 
829
        panel_layout_object_create_finish (id);
 
830
 
 
831
        g_object_unref (settings_instance);
 
832
        g_object_unref (settings);
 
833
        g_free (id);
 
834
 
 
835
        return TRUE;
 
836
}
 
837
                          
 
838
void
 
839
panel_menu_button_invoke_menu (PanelMenuButton *button,
 
840
                               const char   *callback_name)
 
841
{
 
842
        GdkScreen *screen;
 
843
 
 
844
        g_return_if_fail (PANEL_IS_MENU_BUTTON (button));
 
845
        g_return_if_fail (callback_name != NULL);
 
846
 
 
847
        screen = gtk_widget_get_screen (GTK_WIDGET (button));
 
848
 
 
849
        if (!strcmp (callback_name, "edit")) {
 
850
                GError *error = NULL;
 
851
 
 
852
                panel_launch_desktop_file_with_fallback ("alacarte.desktop",
 
853
                                                         "alacarte",
 
854
                                                         screen, &error);
 
855
                if (error) {
 
856
                        g_error_free (error);
 
857
                        panel_launch_desktop_file_with_fallback (
 
858
                                                "gmenu-simple-editor.desktop",
 
859
                                                "gmenu-simple-editor",
 
860
                                                screen, NULL);
 
861
                }
 
862
        }
 
863
}
 
864
 
 
865
void
 
866
panel_menu_button_set_dnd_enabled (PanelMenuButton *button,
 
867
                                   gboolean         dnd_enabled)
 
868
{
 
869
        g_return_if_fail (PANEL_IS_MENU_BUTTON (button));
 
870
 
 
871
        dnd_enabled = dnd_enabled != FALSE;
 
872
 
 
873
        if (button->priv->dnd_enabled == dnd_enabled)
 
874
                return;
 
875
 
 
876
        if (dnd_enabled) {
 
877
                static GtkTargetEntry dnd_targets [] = {
 
878
                        { "application/x-panel-applet-internal", 0, 0 }
 
879
                };
 
880
                GIcon *icon;
 
881
 
 
882
                gtk_widget_set_has_window (GTK_WIDGET (button), TRUE);
 
883
                gtk_drag_source_set (GTK_WIDGET (button), GDK_BUTTON1_MASK,
 
884
                                     dnd_targets, 1,
 
885
                                     GDK_ACTION_COPY | GDK_ACTION_MOVE);
 
886
 
 
887
                icon = panel_menu_button_get_icon (button);
 
888
                if (icon != NULL) {
 
889
                        gtk_drag_source_set_icon_gicon (GTK_WIDGET (button),
 
890
                                                        icon);
 
891
                        g_object_unref (icon);
 
892
                }
 
893
 
 
894
                gtk_widget_set_has_window (GTK_WIDGET (button), FALSE);
 
895
        } else
 
896
                gtk_drag_source_unset (GTK_WIDGET (button));
 
897
}
 
898
 
 
899
/*
 
900
 * An AtkObject implementation for PanelMenuButton.
 
901
 * We need all this just so we can create the menu in ref_child()
 
902
 *
 
903
 * See http://bugzilla.gnome.org/show_bug.cgi?id=138535 for details
 
904
 *
 
905
 * If we ever remove the on-demand creation of the menu, we should
 
906
 * can just remove all this again
 
907
 */
 
908
 
 
909
#define PANEL_IS_MENU_BUTTON_ACCESSIBLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), panel_menu_button_accessible_get_type ()))
 
910
 
 
911
static GType panel_menu_button_accessible_get_type (void);
 
912
static gpointer parent_accessible_class = NULL;
 
913
 
 
914
static int
 
915
panel_menu_button_accessible_get_n_children (AtkObject *obj)
 
916
{
 
917
        g_return_val_if_fail (PANEL_IS_MENU_BUTTON_ACCESSIBLE (obj), 0);
 
918
 
 
919
#if GTK_CHECK_VERSION (2, 21, 0)
 
920
        return gtk_accessible_get_widget (GTK_ACCESSIBLE (obj)) ? 1 : 0;
 
921
#else
 
922
        return GTK_ACCESSIBLE (obj)->widget ? 1 : 0;
 
923
#endif
 
924
}
 
925
 
 
926
static AtkObject *
 
927
panel_menu_button_accessible_ref_child (AtkObject *obj,
 
928
                                        int        index)
 
929
{
 
930
        PanelMenuButton *button;
 
931
        GtkWidget       *menu;
 
932
 
 
933
        g_return_val_if_fail (PANEL_IS_MENU_BUTTON_ACCESSIBLE (obj), NULL);
 
934
 
 
935
        if (index != 0)
 
936
                return NULL;
 
937
 
 
938
#if GTK_CHECK_VERSION (2, 21, 0)
 
939
        if (!(button = PANEL_MENU_BUTTON (gtk_accessible_get_widget (GTK_ACCESSIBLE (obj)))))
 
940
#else
 
941
        if (!(button = PANEL_MENU_BUTTON (GTK_ACCESSIBLE (obj)->widget)))
 
942
#endif
 
943
                return NULL;
 
944
 
 
945
        if (!(menu = panel_menu_button_create_menu (button)))
 
946
                return NULL;
 
947
        /*
 
948
         * This ensures that the menu is populated with all menu items
 
949
         */
 
950
        g_signal_emit_by_name (menu, "show", NULL);
 
951
 
 
952
        return g_object_ref (gtk_widget_get_accessible (menu));
 
953
}
 
954
 
 
955
static const gchar *
 
956
panel_menu_button_accessible_get_name (AtkObject *obj)
 
957
{
 
958
        const char *name;
 
959
 
 
960
        name = ATK_OBJECT_CLASS (parent_accessible_class)->get_name(obj);
 
961
        if (name == NULL)
 
962
                name = _("Main Menu");
 
963
 
 
964
        return name;
 
965
}
 
966
 
 
967
static void
 
968
panel_menu_button_accessible_class_init (AtkObjectClass *klass)
 
969
{
 
970
        klass->get_n_children = panel_menu_button_accessible_get_n_children;
 
971
        klass->ref_child      = panel_menu_button_accessible_ref_child; 
 
972
        klass->get_name       = panel_menu_button_accessible_get_name; 
 
973
 
 
974
        parent_accessible_class = g_type_class_peek_parent (klass);
 
975
}
 
976
 
 
977
static GType
 
978
panel_menu_button_accessible_get_type (void)
 
979
{
 
980
        static GType type = 0;
 
981
 
 
982
        if (!type) {
 
983
                GTypeInfo type_info = { 0 };
 
984
                GType     accessible_parent_type;
 
985
 
 
986
                type_info.class_init =
 
987
                        (GClassInitFunc) panel_menu_button_accessible_class_init;
 
988
 
 
989
                accessible_parent_type =
 
990
                        panel_a11y_query_accessible_parent_type (PANEL_TYPE_MENU_BUTTON,
 
991
                                                                 &type_info);
 
992
 
 
993
                type = g_type_register_static (accessible_parent_type, 
 
994
                                               "PanelMenuButtonAccessible", 
 
995
                                               &type_info, 0);
 
996
        }
 
997
 
 
998
        return type;
 
999
}
 
1000
 
 
1001
static AtkObject *
 
1002
panel_menu_button_accessible_new (GObject *obj)
 
1003
{
 
1004
        AtkObject *accessible;
 
1005
 
 
1006
        g_return_val_if_fail (PANEL_IS_MENU_BUTTON (obj), NULL);
 
1007
 
 
1008
        accessible = g_object_new (panel_menu_button_accessible_get_type (), NULL);
 
1009
        atk_object_initialize (accessible, obj);
 
1010
 
 
1011
        return accessible;
 
1012
}
 
1013
 
 
1014
static void
 
1015
panel_menu_button_accessible_factory_class_init (AtkObjectFactoryClass *klass)
 
1016
{
 
1017
        klass->create_accessible   = panel_menu_button_accessible_new;
 
1018
        klass->get_accessible_type = panel_menu_button_accessible_get_type;
 
1019
}
 
1020
 
 
1021
static GType
 
1022
panel_menu_button_accessible_factory_get_type (void)
 
1023
{
 
1024
        static GType type = 0;
 
1025
 
 
1026
        if (!type) {
 
1027
                static const GTypeInfo info = {
 
1028
                        sizeof (AtkObjectFactoryClass),
 
1029
                        NULL,
 
1030
                        NULL,
 
1031
                        (GClassInitFunc) panel_menu_button_accessible_factory_class_init,
 
1032
                        NULL,
 
1033
                        NULL,
 
1034
                        sizeof (AtkObjectFactory),
 
1035
                        0,
 
1036
                        NULL,
 
1037
                        NULL
 
1038
                };
 
1039
 
 
1040
                type = g_type_register_static (ATK_TYPE_OBJECT_FACTORY, 
 
1041
                                               "PanelMenuButtonAccessibleFactory",
 
1042
                                               &info, 0);
 
1043
        }
 
1044
 
 
1045
        return type;
 
1046
}
 
1047
 
 
1048
static AtkObject *
 
1049
panel_menu_button_get_accessible (GtkWidget *widget)
 
1050
{
 
1051
        static gboolean first_time = TRUE;
 
1052
 
 
1053
        g_return_val_if_fail (widget != NULL, NULL);
 
1054
 
 
1055
        if (first_time && panel_a11y_get_is_a11y_enabled (widget))
 
1056
                atk_registry_set_factory_type (atk_get_default_registry (),
 
1057
                                               PANEL_TYPE_MENU_BUTTON,
 
1058
                                               panel_menu_button_accessible_factory_get_type ());
 
1059
 
 
1060
        first_time = FALSE;
 
1061
         
 
1062
        return GTK_WIDGET_CLASS (panel_menu_button_parent_class)->get_accessible (widget);
 
1063
}