1 /*
2 * Copyright (C) 2010 Nick Schermer <nick@xfce.org>
3 *
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This library is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <exo/exo.h>
24 #include <garcon/garcon.h>
25 #include <garcon-gtk/garcon-gtk.h>
26 #include <libxfce4ui/libxfce4ui.h>
27 #include <libxfce4util/libxfce4util.h>
28 #include <libxfce4panel/libxfce4panel.h>
29 #include <common/panel-xfconf.h>
30 #include <common/panel-utils.h>
31 #include <common/panel-private.h>
32 #include <common/panel-debug.h>
33
34 #include "applicationsmenu.h"
35 #include "applicationsmenu-dialog_ui.h"
36
37
38 /* I18N: default tooltip of the application menu */
39 #define DEFAULT_TITLE _("Applications")
40 #define DEFAULT_ICON_NAME "org.xfce.panel.applicationsmenu"
41 #define DEFAULT_ICON_SIZE (16)
42 #define DEFAULT_EDITOR "menulibre"
43
44
45 struct _ApplicationsMenuPluginClass
46 {
47 XfcePanelPluginClass __parent__;
48 };
49
50 struct _ApplicationsMenuPlugin
51 {
52 XfcePanelPlugin __parent__;
53
54 GtkWidget *button;
55 GtkWidget *box;
56 GtkWidget *icon;
57 GtkWidget *label;
58 GtkWidget *menu;
59
60 guint is_constructed : 1;
61
62 guint show_button_title : 1;
63 gchar *button_title;
64 gchar *button_icon;
65 gboolean custom_menu;
66 gchar *custom_menu_file;
67 gchar *menu_editor;
68
69 /* temp item we store here when the
70 * properties dialog is opened */
71 GtkWidget *dialog_icon;
72
73 gulong style_set_id;
74 gulong screen_changed_id;
75 gulong theme_changed_id;
76 };
77
78 enum
79 {
80 PROP_0,
81 PROP_SHOW_GENERIC_NAMES,
82 PROP_SHOW_MENU_ICONS,
83 PROP_SHOW_TOOLTIPS,
84 PROP_SHOW_BUTTON_TITLE,
85 PROP_BUTTON_TITLE,
86 PROP_BUTTON_ICON,
87 PROP_CUSTOM_MENU,
88 PROP_CUSTOM_MENU_FILE,
89 PROP_MENU_EDITOR
90 };
91
92
93
94 static void applications_menu_plugin_get_property (GObject *object,
95 guint prop_id,
96 GValue *value,
97 GParamSpec *pspec);
98 static void applications_menu_plugin_set_property (GObject *object,
99 guint prop_id,
100 const GValue *value,
101 GParamSpec *pspec);
102 static void applications_menu_plugin_construct (XfcePanelPlugin *panel_plugin);
103 static void applications_menu_plugin_free_data (XfcePanelPlugin *panel_plugin);
104 static gboolean applications_menu_plugin_size_changed (XfcePanelPlugin *panel_plugin,
105 gint size);
106 static void applications_menu_plugin_mode_changed (XfcePanelPlugin *panel_plugin,
107 XfcePanelPluginMode mode);
108 static void applications_menu_plugin_configure_plugin (XfcePanelPlugin *panel_plugin);
109 static gboolean applications_menu_plugin_remote_event (XfcePanelPlugin *panel_plugin,
110 const gchar *name,
111 const GValue *value);
112 static gboolean applications_menu_plugin_menu (GtkWidget *button,
113 GdkEventButton *event,
114 ApplicationsMenuPlugin *plugin);
115 static void applications_menu_plugin_menu_deactivate (GtkWidget *menu,
116 ApplicationsMenuPlugin *plugin);
117 static void applications_menu_plugin_set_garcon_menu (ApplicationsMenuPlugin *plugin);
118 static void applications_menu_button_theme_changed (ApplicationsMenuPlugin *plugin);
119
120
121
122 /* define the plugin */
XFCE_PANEL_DEFINE_PLUGIN(ApplicationsMenuPlugin,applications_menu_plugin)123 XFCE_PANEL_DEFINE_PLUGIN (ApplicationsMenuPlugin, applications_menu_plugin)
124
125
126
127 static void
128 applications_menu_plugin_class_init (ApplicationsMenuPluginClass *klass)
129 {
130 XfcePanelPluginClass *plugin_class;
131 GObjectClass *gobject_class;
132
133 gobject_class = G_OBJECT_CLASS (klass);
134 gobject_class->get_property = applications_menu_plugin_get_property;
135 gobject_class->set_property = applications_menu_plugin_set_property;
136
137 plugin_class = XFCE_PANEL_PLUGIN_CLASS (klass);
138 plugin_class->construct = applications_menu_plugin_construct;
139 plugin_class->free_data = applications_menu_plugin_free_data;
140 plugin_class->size_changed = applications_menu_plugin_size_changed;
141 plugin_class->mode_changed = applications_menu_plugin_mode_changed;
142 plugin_class->configure_plugin = applications_menu_plugin_configure_plugin;
143 plugin_class->remote_event = applications_menu_plugin_remote_event;
144
145 g_object_class_install_property (gobject_class,
146 PROP_SHOW_GENERIC_NAMES,
147 g_param_spec_boolean ("show-generic-names",
148 NULL, NULL,
149 FALSE,
150 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
151
152 g_object_class_install_property (gobject_class,
153 PROP_SHOW_MENU_ICONS,
154 g_param_spec_boolean ("show-menu-icons",
155 NULL, NULL,
156 TRUE,
157 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
158 g_object_class_install_property (gobject_class,
159 PROP_SHOW_TOOLTIPS,
160 g_param_spec_boolean ("show-tooltips",
161 NULL, NULL,
162 FALSE,
163 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
164
165 g_object_class_install_property (gobject_class,
166 PROP_SHOW_BUTTON_TITLE,
167 g_param_spec_boolean ("show-button-title",
168 NULL, NULL,
169 TRUE,
170 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
171
172 g_object_class_install_property (gobject_class,
173 PROP_BUTTON_TITLE,
174 g_param_spec_string ("button-title",
175 NULL, NULL,
176 DEFAULT_TITLE,
177 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
178
179 g_object_class_install_property (gobject_class,
180 PROP_BUTTON_ICON,
181 g_param_spec_string ("button-icon",
182 NULL, NULL,
183 DEFAULT_ICON_NAME,
184 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
185
186 g_object_class_install_property (gobject_class,
187 PROP_CUSTOM_MENU,
188 g_param_spec_boolean ("custom-menu",
189 NULL, NULL,
190 FALSE,
191 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
192
193 g_object_class_install_property (gobject_class,
194 PROP_CUSTOM_MENU_FILE,
195 g_param_spec_string ("custom-menu-file",
196 NULL, NULL,
197 NULL,
198 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
199
200 g_object_class_install_property (gobject_class,
201 PROP_MENU_EDITOR,
202 g_param_spec_string ("menu-editor",
203 NULL, NULL,
204 DEFAULT_EDITOR,
205 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
206 }
207
208
209
210 static void
applications_menu_plugin_init(ApplicationsMenuPlugin * plugin)211 applications_menu_plugin_init (ApplicationsMenuPlugin *plugin)
212 {
213 GtkIconTheme *icon_theme;
214
215 /* init garcon environment */
216 garcon_set_environment_xdg (GARCON_ENVIRONMENT_XFCE);
217
218 icon_theme = gtk_icon_theme_get_default ();
219
220 plugin->button = xfce_panel_create_toggle_button ();
221 xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (plugin), plugin->button);
222 gtk_container_add (GTK_CONTAINER (plugin), plugin->button);
223 gtk_widget_set_name (plugin->button, "applicationmenu-button");
224 gtk_button_set_relief (GTK_BUTTON (plugin->button), GTK_RELIEF_NONE);
225 gtk_widget_set_tooltip_text (plugin->button, DEFAULT_TITLE);
226 g_signal_connect (G_OBJECT (plugin->button), "button-press-event",
227 G_CALLBACK (applications_menu_plugin_menu), plugin);
228
229 plugin->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
230 gtk_container_set_border_width (GTK_CONTAINER (plugin->box), 0);
231 gtk_container_add (GTK_CONTAINER (plugin->button), plugin->box);
232 gtk_widget_show (plugin->box);
233
234 plugin->icon = gtk_image_new_from_icon_name (DEFAULT_ICON_NAME, DEFAULT_ICON_SIZE);
235 gtk_box_pack_start (GTK_BOX (plugin->box), plugin->icon, FALSE, FALSE, 0);
236 gtk_widget_show (plugin->icon);
237
238 plugin->label = gtk_label_new (DEFAULT_TITLE);
239 gtk_box_pack_start (GTK_BOX (plugin->box), plugin->label, FALSE, FALSE, 0);
240 plugin->show_button_title = TRUE;
241 gtk_widget_show (plugin->label);
242
243 /* prepare the menu */
244 plugin->menu = garcon_gtk_menu_new (NULL);
245 g_signal_connect (G_OBJECT (plugin->menu), "selection-done",
246 G_CALLBACK (applications_menu_plugin_menu_deactivate), plugin);
247
248 plugin->style_set_id = g_signal_connect_swapped (G_OBJECT (plugin->button), "style-set",
249 G_CALLBACK (applications_menu_button_theme_changed), plugin);
250 plugin->screen_changed_id = g_signal_connect_swapped (G_OBJECT (plugin->button), "screen-changed",
251 G_CALLBACK (applications_menu_button_theme_changed), plugin);
252 plugin->theme_changed_id = g_signal_connect_swapped (G_OBJECT (icon_theme), "changed",
253 G_CALLBACK (applications_menu_plugin_set_garcon_menu), plugin);
254 }
255
256
257
258 static void
applications_menu_plugin_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)259 applications_menu_plugin_get_property (GObject *object,
260 guint prop_id,
261 GValue *value,
262 GParamSpec *pspec)
263 {
264 ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (object);
265
266 switch (prop_id)
267 {
268 case PROP_SHOW_GENERIC_NAMES:
269 g_value_set_boolean (value,
270 garcon_gtk_menu_get_show_generic_names (GARCON_GTK_MENU (plugin->menu)));
271 break;
272
273 case PROP_SHOW_MENU_ICONS:
274 g_value_set_boolean (value,
275 garcon_gtk_menu_get_show_menu_icons (GARCON_GTK_MENU (plugin->menu)));
276 break;
277
278 case PROP_SHOW_TOOLTIPS:
279 g_value_set_boolean (value,
280 garcon_gtk_menu_get_show_tooltips (GARCON_GTK_MENU (plugin->menu)));
281 break;
282
283 case PROP_SHOW_BUTTON_TITLE:
284 g_value_set_boolean (value, plugin->show_button_title);
285 break;
286
287 case PROP_BUTTON_TITLE:
288 g_value_set_string (value, plugin->button_title == NULL ?
289 DEFAULT_TITLE : plugin->button_title);
290 break;
291
292 case PROP_BUTTON_ICON:
293 g_value_set_string (value, panel_str_is_empty (plugin->button_icon) ?
294 DEFAULT_ICON_NAME : plugin->button_icon);
295 break;
296
297 case PROP_CUSTOM_MENU:
298 g_value_set_boolean (value, plugin->custom_menu);
299 break;
300
301 case PROP_CUSTOM_MENU_FILE:
302 g_value_set_string (value, plugin->custom_menu_file);
303 break;
304
305 case PROP_MENU_EDITOR:
306 g_value_set_string (value, plugin->menu_editor);
307 break;
308
309 default:
310 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
311 break;
312 }
313 }
314
315
316
317 static void
applications_menu_plugin_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)318 applications_menu_plugin_set_property (GObject *object,
319 guint prop_id,
320 const GValue *value,
321 GParamSpec *pspec)
322 {
323 ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (object);
324 gboolean force_a_resize = FALSE;
325
326 switch (prop_id)
327 {
328 case PROP_SHOW_GENERIC_NAMES:
329 garcon_gtk_menu_set_show_generic_names (GARCON_GTK_MENU (plugin->menu),
330 g_value_get_boolean (value));
331 break;
332
333 case PROP_SHOW_MENU_ICONS:
334 garcon_gtk_menu_set_show_menu_icons (GARCON_GTK_MENU (plugin->menu),
335 g_value_get_boolean (value));
336 break;
337
338 case PROP_SHOW_TOOLTIPS:
339 garcon_gtk_menu_set_show_tooltips (GARCON_GTK_MENU (plugin->menu),
340 g_value_get_boolean (value));
341 break;
342
343 case PROP_SHOW_BUTTON_TITLE:
344 plugin->show_button_title = g_value_get_boolean (value);
345 if (plugin->show_button_title)
346 gtk_widget_show (plugin->label);
347 else
348 gtk_widget_hide (plugin->label);
349 applications_menu_plugin_size_changed (XFCE_PANEL_PLUGIN (plugin),
350 xfce_panel_plugin_get_size (XFCE_PANEL_PLUGIN (plugin)));
351 return;
352
353 case PROP_BUTTON_TITLE:
354 g_free (plugin->button_title);
355 plugin->button_title = g_value_dup_string (value);
356 gtk_label_set_text (GTK_LABEL (plugin->label),
357 plugin->button_title != NULL ? plugin->button_title : "");
358 gtk_widget_set_tooltip_text (plugin->button,
359 panel_str_is_empty (plugin->button_title) ? NULL : plugin->button_title);
360
361 /* check if the label still fits */
362 if (xfce_panel_plugin_get_mode (XFCE_PANEL_PLUGIN (plugin)) == XFCE_PANEL_PLUGIN_MODE_DESKBAR
363 && plugin->show_button_title)
364 {
365 force_a_resize = TRUE;
366 }
367 break;
368
369 case PROP_BUTTON_ICON:
370 g_free (plugin->button_icon);
371 plugin->button_icon = g_value_dup_string (value);
372
373 force_a_resize = TRUE;
374 break;
375
376 case PROP_CUSTOM_MENU:
377 plugin->custom_menu = g_value_get_boolean (value);
378
379 if (plugin->is_constructed)
380 applications_menu_plugin_set_garcon_menu (plugin);
381 break;
382
383 case PROP_CUSTOM_MENU_FILE:
384 g_free (plugin->custom_menu_file);
385 plugin->custom_menu_file = g_value_dup_string (value);
386
387 if (plugin->is_constructed)
388 applications_menu_plugin_set_garcon_menu (plugin);
389 break;
390
391 case PROP_MENU_EDITOR:
392 plugin->menu_editor = g_value_dup_string (value);
393 break;
394
395 default:
396 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
397 break;
398 }
399
400 if (force_a_resize)
401 {
402 applications_menu_plugin_size_changed (XFCE_PANEL_PLUGIN (plugin),
403 xfce_panel_plugin_get_size (XFCE_PANEL_PLUGIN (plugin)));
404 }
405 }
406
407
408
409 static void
applications_menu_plugin_construct(XfcePanelPlugin * panel_plugin)410 applications_menu_plugin_construct (XfcePanelPlugin *panel_plugin)
411 {
412 ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin);
413 const PanelProperty properties[] =
414 {
415 { "show-generic-names", G_TYPE_BOOLEAN },
416 { "show-menu-icons", G_TYPE_BOOLEAN },
417 { "show-button-title", G_TYPE_BOOLEAN },
418 { "show-tooltips", G_TYPE_BOOLEAN },
419 { "button-title", G_TYPE_STRING },
420 { "button-icon", G_TYPE_STRING },
421 { "custom-menu", G_TYPE_BOOLEAN },
422 { "custom-menu-file", G_TYPE_STRING },
423 { "menu-editor", G_TYPE_STRING },
424 { NULL }
425 };
426
427 xfce_panel_plugin_menu_show_configure (XFCE_PANEL_PLUGIN (plugin));
428
429 /* bind all properties */
430 panel_properties_bind (NULL, G_OBJECT (plugin),
431 xfce_panel_plugin_get_property_base (panel_plugin),
432 properties, FALSE);
433
434 /* make sure the menu is set */
435 applications_menu_plugin_set_garcon_menu (plugin);
436
437 if (!plugin->menu_editor)
438 plugin->menu_editor = DEFAULT_EDITOR;
439
440 gtk_widget_show (plugin->button);
441
442 applications_menu_plugin_size_changed (panel_plugin,
443 xfce_panel_plugin_get_size (panel_plugin));
444 plugin->is_constructed = TRUE;
445 }
446
447
448
449 static void
applications_menu_plugin_free_data(XfcePanelPlugin * panel_plugin)450 applications_menu_plugin_free_data (XfcePanelPlugin *panel_plugin)
451 {
452 ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin);
453 GtkIconTheme *icon_theme;
454
455 if (plugin->menu != NULL)
456 gtk_widget_destroy (plugin->menu);
457
458 if (plugin->style_set_id != 0)
459 {
460 g_signal_handler_disconnect (plugin->button, plugin->style_set_id);
461 plugin->style_set_id = 0;
462 }
463
464 if (plugin->screen_changed_id != 0)
465 {
466 g_signal_handler_disconnect (plugin->button, plugin->screen_changed_id);
467 plugin->screen_changed_id = 0;
468 }
469
470 if (plugin->theme_changed_id != 0)
471 {
472 icon_theme = gtk_icon_theme_get_default ();
473 g_signal_handler_disconnect (G_OBJECT (icon_theme),
474 plugin->theme_changed_id);
475 plugin->theme_changed_id = 0;
476 }
477
478 g_free (plugin->button_title);
479 g_free (plugin->button_icon);
480 g_free (plugin->custom_menu_file);
481 }
482
483
484
485 static gboolean
applications_menu_plugin_size_changed(XfcePanelPlugin * panel_plugin,gint size)486 applications_menu_plugin_size_changed (XfcePanelPlugin *panel_plugin,
487 gint size)
488 {
489 ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin);
490 XfcePanelPluginMode mode;
491 GtkRequisition label_size;
492 GtkOrientation orientation;
493 gint border_thickness;
494 GdkPixbuf *icon;
495 gint icon_size;
496 GdkScreen *screen;
497 GtkIconTheme *icon_theme = NULL;
498 gchar *icon_name;
499 GtkStyleContext *ctx;
500 GtkBorder padding, border;
501
502 gtk_box_set_child_packing (GTK_BOX (plugin->box), plugin->icon,
503 !plugin->show_button_title,
504 !plugin->show_button_title,
505 0, GTK_PACK_START);
506
507 mode = xfce_panel_plugin_get_mode (panel_plugin);
508
509 if (mode == XFCE_PANEL_PLUGIN_MODE_HORIZONTAL)
510 orientation = GTK_ORIENTATION_HORIZONTAL;
511 else
512 orientation = GTK_ORIENTATION_VERTICAL;
513
514 /* style thickness */
515 ctx = gtk_widget_get_style_context (plugin->button);
516 gtk_style_context_get_padding (ctx, gtk_widget_get_state_flags (plugin->button), &padding);
517 gtk_style_context_get_border (ctx, gtk_widget_get_state_flags (plugin->button), &border);
518 border_thickness = MAX (padding.left + padding.right + border.left + border.right,
519 padding.top + padding.bottom + border.top + border.bottom);
520
521 icon_size = xfce_panel_plugin_get_icon_size (panel_plugin);
522
523 screen = gtk_widget_get_screen (GTK_WIDGET (plugin));
524 if (G_LIKELY (screen != NULL))
525 icon_theme = gtk_icon_theme_get_for_screen (screen);
526
527 icon_name = panel_str_is_empty (plugin->button_icon) ?
528 DEFAULT_ICON_NAME : plugin->button_icon;
529
530 icon = xfce_panel_pixbuf_from_source_at_size (icon_name,
531 icon_theme,
532 icon_size,
533 icon_size);
534
535 if (G_LIKELY (icon != NULL))
536 {
537 gtk_image_set_from_pixbuf (GTK_IMAGE (plugin->icon), icon);
538 g_object_unref (G_OBJECT (icon));
539 }
540
541 if (plugin->show_button_title &&
542 mode == XFCE_PANEL_PLUGIN_MODE_DESKBAR)
543 {
544 /* check if the label (minimum size) fits next to the icon */
545 gtk_widget_get_preferred_size (GTK_WIDGET (plugin->label), &label_size, NULL);
546 if (label_size.width <= size - icon_size - 2 - border_thickness)
547 orientation = GTK_ORIENTATION_HORIZONTAL;
548 }
549
550 gtk_orientable_set_orientation (GTK_ORIENTABLE (plugin->box), orientation);
551
552 return TRUE;
553 }
554
555
556
557 static void
applications_menu_plugin_mode_changed(XfcePanelPlugin * panel_plugin,XfcePanelPluginMode mode)558 applications_menu_plugin_mode_changed (XfcePanelPlugin *panel_plugin,
559 XfcePanelPluginMode mode)
560 {
561 ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin);
562 gint angle;
563
564 angle = (mode == XFCE_PANEL_PLUGIN_MODE_VERTICAL) ? 270 : 0;
565 gtk_label_set_angle (GTK_LABEL (plugin->label), angle);
566
567 applications_menu_plugin_size_changed (panel_plugin,
568 xfce_panel_plugin_get_size (panel_plugin));
569 }
570
571
572
573 static void
applications_menu_plugin_configure_plugin_file_set(GtkFileChooserButton * button,ApplicationsMenuPlugin * plugin)574 applications_menu_plugin_configure_plugin_file_set (GtkFileChooserButton *button,
575 ApplicationsMenuPlugin *plugin)
576 {
577 gchar *filename;
578
579 panel_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button));
580 panel_return_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin));
581
582 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (button));
583 g_object_set (G_OBJECT (plugin), "custom-menu-file", filename, NULL);
584 g_free (filename);
585 }
586
587
588
589 static void
applications_menu_plugin_configure_plugin_icon_chooser(GtkWidget * button,ApplicationsMenuPlugin * plugin)590 applications_menu_plugin_configure_plugin_icon_chooser (GtkWidget *button,
591 ApplicationsMenuPlugin *plugin)
592 {
593 #ifdef EXO_CHECK_VERSION
594 GtkWidget *chooser;
595 gchar *icon;
596
597 panel_return_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin));
598 panel_return_if_fail (GTK_IMAGE (plugin->dialog_icon));
599
600 chooser = exo_icon_chooser_dialog_new (_("Select An Icon"),
601 GTK_WINDOW (gtk_widget_get_toplevel (button)),
602 _("_Cancel"), GTK_RESPONSE_CANCEL,
603 _("_OK"), GTK_RESPONSE_ACCEPT,
604 NULL);
605 gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_ACCEPT);
606
607 exo_icon_chooser_dialog_set_icon (EXO_ICON_CHOOSER_DIALOG (chooser),
608 panel_str_is_empty (plugin->button_icon) ? DEFAULT_ICON_NAME : plugin->button_icon);
609
610 if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT)
611 {
612 icon = exo_icon_chooser_dialog_get_icon (EXO_ICON_CHOOSER_DIALOG (chooser));
613 g_object_set (G_OBJECT (plugin), "button-icon", icon, NULL);
614 gtk_image_set_from_icon_name (GTK_IMAGE (plugin->dialog_icon),
615 exo_str_is_empty (plugin->button_icon) ?
616 DEFAULT_ICON_NAME : plugin->button_icon,
617 GTK_ICON_SIZE_DIALOG);
618 g_free (icon);
619 }
620
621 gtk_widget_destroy (chooser);
622 #endif
623 }
624
625
626
627 static void
applications_menu_plugin_configure_plugin_edit(GtkWidget * button,ApplicationsMenuPlugin * plugin)628 applications_menu_plugin_configure_plugin_edit (GtkWidget *button,
629 ApplicationsMenuPlugin *plugin)
630 {
631 GError *error = NULL;
632
633 panel_return_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin));
634 panel_return_if_fail (GTK_IS_WIDGET (button));
635
636 if (!xfce_spawn_command_line (gtk_widget_get_screen (button), plugin->menu_editor,
637 FALSE, FALSE, TRUE, &error))
638 {
639 xfce_dialog_show_error (NULL, error, _("Failed to execute command \"%s\"."), plugin->menu_editor);
640 g_error_free (error);
641 }
642 }
643
644
645
646 static void
applications_menu_plugin_configure_plugin(XfcePanelPlugin * panel_plugin)647 applications_menu_plugin_configure_plugin (XfcePanelPlugin *panel_plugin)
648 {
649 ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin);
650 GtkBuilder *builder;
651 GObject *dialog, *object, *object2;
652 guint i;
653 gchar *path;
654 const gchar *check_names[] = { "show-generic-names", "show-menu-icons",
655 "show-tooltips", "show-button-title" };
656
657 /* setup the dialog */
658 PANEL_UTILS_LINK_4UI
659 builder = panel_utils_builder_new (panel_plugin, applicationsmenu_dialog_ui,
660 applicationsmenu_dialog_ui_length, &dialog);
661 if (G_UNLIKELY (builder == NULL))
662 return;
663
664 for (i = 0; i < G_N_ELEMENTS (check_names); ++i)
665 {
666 object = gtk_builder_get_object (builder, check_names[i]);
667 panel_return_if_fail (GTK_IS_CHECK_BUTTON (object));
668 g_object_bind_property (G_OBJECT (plugin), check_names[i],
669 G_OBJECT (object), "active",
670 G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
671 }
672
673 object = gtk_builder_get_object (builder, "button-title");
674 panel_return_if_fail (GTK_IS_ENTRY (object));
675 g_object_bind_property (G_OBJECT (plugin), "button-title",
676 G_OBJECT (object), "text",
677 G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
678
679 object = gtk_builder_get_object (builder, "icon-button");
680 panel_return_if_fail (GTK_IS_BUTTON (object));
681 g_signal_connect (G_OBJECT (object), "clicked",
682 G_CALLBACK (applications_menu_plugin_configure_plugin_icon_chooser), plugin);
683
684 plugin->dialog_icon = gtk_image_new_from_icon_name (
685 panel_str_is_empty (plugin->button_icon) ? DEFAULT_ICON_NAME : plugin->button_icon,
686 GTK_ICON_SIZE_DIALOG);
687 gtk_container_add (GTK_CONTAINER (object), plugin->dialog_icon);
688 g_object_add_weak_pointer (G_OBJECT (plugin->dialog_icon), (gpointer) &plugin->dialog_icon);
689 gtk_widget_show (plugin->dialog_icon);
690
691 /* whether we show the edit menu button */
692 object = gtk_builder_get_object (builder, "edit-menu-button");
693 panel_return_if_fail (GTK_IS_BUTTON (object));
694 path = g_find_program_in_path (plugin->menu_editor);
695 if (path != NULL)
696 {
697 object2 = gtk_builder_get_object (builder, "use-default-menu");
698 panel_return_if_fail (GTK_IS_RADIO_BUTTON (object2));
699 g_object_bind_property (G_OBJECT (object2), "active",
700 G_OBJECT (object), "sensitive",
701 G_BINDING_SYNC_CREATE);
702 g_signal_connect (G_OBJECT (object), "clicked",
703 G_CALLBACK (applications_menu_plugin_configure_plugin_edit), plugin);
704 }
705 else
706 {
707 gtk_widget_hide (GTK_WIDGET (object));
708 }
709 g_free (path);
710
711 object = gtk_builder_get_object (builder, "use-custom-menu");
712 panel_return_if_fail (GTK_IS_RADIO_BUTTON (object));
713 g_object_bind_property (G_OBJECT (plugin), "custom-menu",
714 G_OBJECT (object), "active",
715 G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
716
717 /* sensitivity of custom file selector */
718 object2 = gtk_builder_get_object (builder, "custom-box");
719 panel_return_if_fail (GTK_IS_WIDGET (object2));
720 g_object_bind_property (G_OBJECT (object), "active",
721 G_OBJECT (object2), "sensitive",
722 G_BINDING_SYNC_CREATE);
723
724 object = gtk_builder_get_object (builder, "custom-file");
725 panel_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (object));
726 if (!panel_str_is_empty (plugin->custom_menu_file))
727 gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (object), plugin->custom_menu_file);
728 g_signal_connect (G_OBJECT (object), "file-set",
729 G_CALLBACK (applications_menu_plugin_configure_plugin_file_set), plugin);
730
731 gtk_widget_show (GTK_WIDGET (dialog));
732 }
733
734
735
736 static gboolean
applications_menu_plugin_remote_event(XfcePanelPlugin * panel_plugin,const gchar * name,const GValue * value)737 applications_menu_plugin_remote_event (XfcePanelPlugin *panel_plugin,
738 const gchar *name,
739 const GValue *value)
740 {
741 ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin);
742
743 panel_return_val_if_fail (value == NULL || G_IS_VALUE (value), FALSE);
744
745 if (strcmp (name, "popup") == 0
746 && gtk_widget_get_visible (GTK_WIDGET (panel_plugin))
747 && !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (plugin->button))
748 && panel_utils_grab_available ())
749 {
750 if (value != NULL
751 && G_VALUE_HOLDS_BOOLEAN (value)
752 && g_value_get_boolean (value))
753 {
754 /* show menu under cursor */
755 applications_menu_plugin_menu (NULL, NULL, plugin);
756 }
757 else
758 {
759 /* show the menu at the button */
760 applications_menu_plugin_menu (plugin->button, NULL, plugin);
761 }
762
763 /* don't popup another menu */
764 return TRUE;
765 }
766
767 return FALSE;
768 }
769
770
771
772 static void
applications_menu_plugin_menu_deactivate(GtkWidget * menu,ApplicationsMenuPlugin * plugin)773 applications_menu_plugin_menu_deactivate (GtkWidget *menu,
774 ApplicationsMenuPlugin *plugin)
775 {
776 panel_return_if_fail (plugin->button == NULL || GTK_IS_TOGGLE_BUTTON (plugin->button));
777 panel_return_if_fail (GTK_IS_MENU (menu));
778
779 xfce_panel_plugin_block_autohide (XFCE_PANEL_PLUGIN (plugin), FALSE);
780
781 /* button is NULL when we popup the menu under the cursor position */
782 if (plugin->button != NULL)
783 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->button), FALSE);
784
785 gtk_menu_popdown (GTK_MENU (menu));
786 }
787
788
789
790 static void
applications_menu_plugin_set_garcon_menu(ApplicationsMenuPlugin * plugin)791 applications_menu_plugin_set_garcon_menu (ApplicationsMenuPlugin *plugin)
792 {
793 GarconMenu *menu = NULL;
794 gchar *filename;
795 GFile *file;
796
797 panel_return_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin));
798 panel_return_if_fail (GARCON_GTK_IS_MENU (plugin->menu));
799
800 /* load the custom menu if set */
801 if (plugin->custom_menu
802 && plugin->custom_menu_file != NULL)
803 menu = garcon_menu_new_for_path (plugin->custom_menu_file);
804
805 /* use the applications menu, this also respects the
806 * XDG_MENU_PREFIX environment variable */
807 if (G_LIKELY (menu == NULL))
808 menu = garcon_menu_new_applications ();
809
810 /* set the menu */
811 garcon_gtk_menu_set_menu (GARCON_GTK_MENU (plugin->menu), menu);
812
813 /* debugging information */
814 if (0)
815 {
816 file = garcon_menu_get_file (menu);
817 filename = g_file_get_parse_name (file);
818 g_object_unref (G_OBJECT (file));
819
820 panel_debug (PANEL_DEBUG_APPLICATIONSMENU,
821 "menu from \"%s\"", filename);
822 g_free (filename);
823 }
824
825 g_object_unref (G_OBJECT (menu));
826 }
827
828
829
830 static gboolean
applications_menu_plugin_menu(GtkWidget * button,GdkEventButton * event,ApplicationsMenuPlugin * plugin)831 applications_menu_plugin_menu (GtkWidget *button,
832 GdkEventButton *event,
833 ApplicationsMenuPlugin *plugin)
834 {
835 panel_return_val_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin), FALSE);
836 panel_return_val_if_fail (button == NULL || plugin->button == button, FALSE);
837
838 if (event != NULL /* remove event */
839 && !(event->button == 1
840 && event->type == GDK_BUTTON_PRESS
841 && !PANEL_HAS_FLAG (event->state, GDK_CONTROL_MASK)))
842 return FALSE;
843
844 xfce_panel_plugin_block_autohide (XFCE_PANEL_PLUGIN (plugin), TRUE);
845
846 if (button != NULL)
847 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
848
849 /* show the menu */
850 gtk_menu_popup_at_widget (GTK_MENU (plugin->menu), button,
851 xfce_panel_plugin_get_orientation (XFCE_PANEL_PLUGIN (plugin)) == GTK_ORIENTATION_VERTICAL
852 ? GDK_GRAVITY_NORTH_EAST : GDK_GRAVITY_SOUTH_WEST,
853 GDK_GRAVITY_NORTH_WEST,
854 (GdkEvent *) event);
855
856 return TRUE;
857 }
858
859
860
861 static void
applications_menu_button_theme_changed(ApplicationsMenuPlugin * plugin)862 applications_menu_button_theme_changed (ApplicationsMenuPlugin *plugin)
863 {
864 XfcePanelPlugin *panel_plugin = XFCE_PANEL_PLUGIN (plugin);
865
866 applications_menu_plugin_size_changed (panel_plugin,
867 xfce_panel_plugin_get_size (panel_plugin));
868 }
869