diff -urN xfce4-panel-4.12.0.orig/plugins/applicationsmenu/applicationsmenu.c xfce4-panel-4.12.0/plugins/applicationsmenu/applicationsmenu.c --- xfce4-panel-4.12.0.orig/plugins/applicationsmenu/applicationsmenu.c 2015-02-26 21:32:17.000000000 +0100 +++ xfce4-panel-4.12.0/plugins/applicationsmenu/applicationsmenu.c 2013-05-05 17:47:07.000000000 +0200 @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -36,7 +35,7 @@ /* I18N: default tooltip of the application menu */ -#define DEFAULT_TITLE _("Applications") +#define DEFAULT_TITLE _("Applications Menu") #define DEFAULT_ICON_NAME "xfce4-panel-menu" #define DEFAULT_ICON_SIZE (16) @@ -57,8 +56,9 @@ GtkWidget *label; GtkWidget *menu; - guint is_constructed : 1; - + guint show_generic_names : 1; + guint show_menu_icons : 1; + guint show_tooltips : 1; guint show_button_title : 1; gchar *button_title; gchar *button_icon; @@ -68,9 +68,6 @@ /* temp item we store here when the * properties dialog is opened */ GtkWidget *dialog_icon; - - gulong style_set_id; - gulong screen_changed_id; }; enum @@ -86,6 +83,10 @@ PROP_CUSTOM_MENU_FILE }; +static const GtkTargetEntry dnd_target_list[] = { + { "text/uri-list", 0, 0 } +}; + static void applications_menu_plugin_get_property (GObject *object, @@ -106,13 +107,10 @@ static gboolean applications_menu_plugin_remote_event (XfcePanelPlugin *panel_plugin, const gchar *name, const GValue *value); +static void applications_menu_plugin_menu_reload (ApplicationsMenuPlugin *plugin); static gboolean applications_menu_plugin_menu (GtkWidget *button, GdkEventButton *event, ApplicationsMenuPlugin *plugin); -static void applications_menu_plugin_menu_deactivate (GtkWidget *menu, - GtkWidget *button); -static void applications_menu_plugin_set_garcon_menu (ApplicationsMenuPlugin *plugin); -static void applications_menu_button_theme_changed (ApplicationsMenuPlugin *plugin); @@ -121,6 +119,10 @@ +static GtkIconSize menu_icon_size = GTK_ICON_SIZE_INVALID; + + + static void applications_menu_plugin_class_init (ApplicationsMenuPluginClass *klass) { @@ -143,7 +145,7 @@ PROP_SHOW_GENERIC_NAMES, g_param_spec_boolean ("show-generic-names", NULL, NULL, - FALSE, + TRUE, EXO_PARAM_READWRITE)); g_object_class_install_property (gobject_class, @@ -193,6 +195,12 @@ NULL, NULL, NULL, EXO_PARAM_READWRITE)); + + menu_icon_size = gtk_icon_size_from_name ("panel-applications-menu"); + if (menu_icon_size == GTK_ICON_SIZE_INVALID) + menu_icon_size = gtk_icon_size_register ("panel-applications-menu", + DEFAULT_ICON_SIZE, + DEFAULT_ICON_SIZE); } @@ -200,8 +208,25 @@ static void applications_menu_plugin_init (ApplicationsMenuPlugin *plugin) { - /* init garcon environment */ - garcon_set_environment_xdg (GARCON_ENVIRONMENT_XFCE); + const gchar *desktop; + + plugin->show_menu_icons = TRUE; + plugin->show_button_title = TRUE; + plugin->custom_menu = FALSE; + + /* if the value is unset, fallback to XFCE, if the + * value is empty, allow all applications in the menu */ + desktop = g_getenv ("XDG_CURRENT_DESKTOP"); + if (G_LIKELY (desktop == NULL)) + desktop = "XFCE"; + else if (*desktop == '\0') + desktop = NULL; + + panel_debug (PANEL_DEBUG_APPLICATIONSMENU, + "XDG_MENU_PREFIX is set to \"%s\", menu environment is \"%s\"", + g_getenv ("XDG_MENU_PREFIX"), desktop); + + garcon_set_environment (desktop); plugin->button = xfce_panel_create_toggle_button (); xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (plugin), plugin->button); @@ -212,28 +237,17 @@ g_signal_connect (G_OBJECT (plugin->button), "button-press-event", G_CALLBACK (applications_menu_plugin_menu), plugin); - plugin->box = xfce_hvbox_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 2); - gtk_container_set_border_width (GTK_CONTAINER (plugin->box), 0); + plugin->box = xfce_hvbox_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 1); gtk_container_add (GTK_CONTAINER (plugin->button), plugin->box); gtk_widget_show (plugin->box); - plugin->icon = gtk_image_new (); + plugin->icon = xfce_panel_image_new_from_source (DEFAULT_ICON_NAME); gtk_box_pack_start (GTK_BOX (plugin->box), plugin->icon, FALSE, FALSE, 0); gtk_widget_show (plugin->icon); plugin->label = gtk_label_new (DEFAULT_TITLE); gtk_box_pack_start (GTK_BOX (plugin->box), plugin->label, FALSE, FALSE, 0); gtk_widget_show (plugin->label); - - /* prepare the menu */ - plugin->menu = garcon_gtk_menu_new (NULL); - g_signal_connect (G_OBJECT (plugin->menu), "selection-done", - G_CALLBACK (applications_menu_plugin_menu_deactivate), plugin->button); - - plugin->style_set_id = g_signal_connect_swapped (G_OBJECT (plugin->button), "style-set", - G_CALLBACK (applications_menu_button_theme_changed), plugin); - plugin->screen_changed_id = g_signal_connect_swapped (G_OBJECT (plugin->button), "screen-changed", - G_CALLBACK (applications_menu_button_theme_changed), plugin); } @@ -249,18 +263,15 @@ switch (prop_id) { case PROP_SHOW_GENERIC_NAMES: - g_value_set_boolean (value, - garcon_gtk_menu_get_show_generic_names (GARCON_GTK_MENU (plugin->menu))); + g_value_set_boolean (value, plugin->show_generic_names); break; case PROP_SHOW_MENU_ICONS: - g_value_set_boolean (value, - garcon_gtk_menu_get_show_menu_icons (GARCON_GTK_MENU (plugin->menu))); + g_value_set_boolean (value, plugin->show_menu_icons); break; case PROP_SHOW_TOOLTIPS: - g_value_set_boolean (value, - garcon_gtk_menu_get_show_tooltips (GARCON_GTK_MENU (plugin->menu))); + g_value_set_boolean (value, plugin->show_tooltips); break; case PROP_SHOW_BUTTON_TITLE: @@ -301,22 +312,23 @@ { ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (object); gboolean force_a_resize = FALSE; + gboolean reload_menu = FALSE; switch (prop_id) { case PROP_SHOW_GENERIC_NAMES: - garcon_gtk_menu_set_show_generic_names (GARCON_GTK_MENU (plugin->menu), - g_value_get_boolean (value)); + plugin->show_generic_names = g_value_get_boolean (value); + reload_menu = TRUE; break; case PROP_SHOW_MENU_ICONS: - garcon_gtk_menu_set_show_menu_icons (GARCON_GTK_MENU (plugin->menu), - g_value_get_boolean (value)); - break; + plugin->show_menu_icons = g_value_get_boolean (value); + reload_menu = TRUE; + break; case PROP_SHOW_TOOLTIPS: - garcon_gtk_menu_set_show_tooltips (GARCON_GTK_MENU (plugin->menu), - g_value_get_boolean (value)); + plugin->show_tooltips = g_value_get_boolean (value); + reload_menu = TRUE; break; case PROP_SHOW_BUTTON_TITLE: @@ -348,23 +360,21 @@ case PROP_BUTTON_ICON: g_free (plugin->button_icon); plugin->button_icon = g_value_dup_string (value); + xfce_panel_image_set_from_source (XFCE_PANEL_IMAGE (plugin->icon), + exo_str_is_empty (plugin->button_icon) ? DEFAULT_ICON_NAME : plugin->button_icon); force_a_resize = TRUE; break; case PROP_CUSTOM_MENU: plugin->custom_menu = g_value_get_boolean (value); - - if (plugin->is_constructed) - applications_menu_plugin_set_garcon_menu (plugin); + reload_menu = TRUE; break; case PROP_CUSTOM_MENU_FILE: g_free (plugin->custom_menu_file); plugin->custom_menu_file = g_value_dup_string (value); - - if (plugin->is_constructed) - applications_menu_plugin_set_garcon_menu (plugin); + reload_menu = TRUE; break; default: @@ -377,6 +387,9 @@ applications_menu_plugin_size_changed (XFCE_PANEL_PLUGIN (plugin), xfce_panel_plugin_get_size (XFCE_PANEL_PLUGIN (plugin))); } + + if (reload_menu) + applications_menu_plugin_menu_reload (plugin); } @@ -405,14 +418,7 @@ xfce_panel_plugin_get_property_base (panel_plugin), properties, FALSE); - /* make sure the menu is set */ - applications_menu_plugin_set_garcon_menu (plugin); - gtk_widget_show (plugin->button); - - applications_menu_plugin_size_changed (panel_plugin, - xfce_panel_plugin_get_size (panel_plugin)); - plugin->is_constructed = TRUE; } @@ -425,18 +431,6 @@ if (plugin->menu != NULL) gtk_widget_destroy (plugin->menu); - if (plugin->style_set_id != 0) - { - g_signal_handler_disconnect (plugin->button, plugin->style_set_id); - plugin->style_set_id = 0; - } - - if (plugin->screen_changed_id != 0) - { - g_signal_handler_disconnect (plugin->button, plugin->screen_changed_id); - plugin->screen_changed_id = 0; - } - g_free (plugin->button_title); g_free (plugin->button_icon); g_free (plugin->custom_menu_file); @@ -450,17 +444,16 @@ { ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin); gint row_size; + gint icon_size; GtkStyle *style; XfcePanelPluginMode mode; GtkRequisition label_size; GtkOrientation orientation; gint border_thickness; + gdouble icon_wh_ratio; GdkPixbuf *icon; - gint icon_width_max, icon_height_max; - gint icon_width = 0; - GdkScreen *screen; - GtkIconTheme *icon_theme = NULL; - gchar *icon_name; + + row_size = size / xfce_panel_plugin_get_nrows (panel_plugin); gtk_box_set_child_packing (GTK_BOX (plugin->box), plugin->icon, !plugin->show_button_title, @@ -474,42 +467,50 @@ else orientation = GTK_ORIENTATION_VERTICAL; - row_size = size / xfce_panel_plugin_get_nrows (panel_plugin); - style = gtk_widget_get_style (plugin->button); - border_thickness = 2 * MAX (style->xthickness, style->ythickness) + 2; - - /* arbitrary limit on non-square icon width in horizontal panel */ - icon_width_max = (mode == XFCE_PANEL_PLUGIN_MODE_HORIZONTAL) ? - 6 * row_size - border_thickness : - size - border_thickness; - icon_height_max = row_size - border_thickness; - - screen = gtk_widget_get_screen (GTK_WIDGET (plugin)); - if (G_LIKELY (screen != NULL)) - icon_theme = gtk_icon_theme_get_for_screen (screen); - - icon_name = exo_str_is_empty (plugin->button_icon) ? - DEFAULT_ICON_NAME : plugin->button_icon; - - icon = xfce_panel_pixbuf_from_source_at_size (icon_name, - icon_theme, - icon_width_max, - icon_height_max); - - if (G_LIKELY (icon != NULL)) + if (!plugin->show_button_title) { - gtk_image_set_from_pixbuf (GTK_IMAGE (plugin->icon), icon); - icon_width = gdk_pixbuf_get_width (icon); - g_object_unref (G_OBJECT (icon)); - } + xfce_panel_image_set_size (XFCE_PANEL_IMAGE (plugin->icon), -1); - if (plugin->show_button_title && - mode == XFCE_PANEL_PLUGIN_MODE_DESKBAR) + /* get scale of the icon for non-squared custom files */ + if (mode != XFCE_PANEL_PLUGIN_MODE_DESKBAR + && plugin->button_icon != NULL + && g_path_is_absolute (plugin->button_icon)) + { + icon = gdk_pixbuf_new_from_file (plugin->button_icon, NULL); + if (G_LIKELY (icon != NULL)) + { + icon_wh_ratio = (gdouble) gdk_pixbuf_get_width (icon) / (gdouble) gdk_pixbuf_get_height (icon); + g_object_unref (G_OBJECT (icon)); + } + } + else + { + icon_wh_ratio = 1.0; + } + + if (mode == XFCE_PANEL_PLUGIN_MODE_HORIZONTAL) + gtk_widget_set_size_request (GTK_WIDGET (panel_plugin), row_size * icon_wh_ratio, size); + else if (mode == XFCE_PANEL_PLUGIN_MODE_VERTICAL) + gtk_widget_set_size_request (GTK_WIDGET (panel_plugin), size, row_size / icon_wh_ratio); + else + gtk_widget_set_size_request (GTK_WIDGET (panel_plugin), size, row_size); + } + else { - /* check if the label fits next to the icon */ - gtk_widget_size_request (GTK_WIDGET (plugin->label), &label_size); - if (label_size.width <= size - border_thickness - icon_width) - orientation = GTK_ORIENTATION_HORIZONTAL; + style = gtk_widget_get_style (plugin->button); + border_thickness = 2 * MAX (style->xthickness, style->ythickness) + 2; + + icon_size = row_size - border_thickness; + xfce_panel_image_set_size (XFCE_PANEL_IMAGE (plugin->icon), icon_size); + gtk_widget_set_size_request (GTK_WIDGET (panel_plugin), -1, -1); + + if (mode == XFCE_PANEL_PLUGIN_MODE_DESKBAR) + { + /* check if the label fits next to the icon */ + gtk_widget_size_request (GTK_WIDGET (plugin->label), &label_size); + if (label_size.width <= size - border_thickness - icon_size) + orientation = GTK_ORIENTATION_HORIZONTAL; + } } gtk_orientable_set_orientation (GTK_ORIENTABLE (plugin->box), orientation); @@ -578,9 +579,6 @@ { icon = exo_icon_chooser_dialog_get_icon (EXO_ICON_CHOOSER_DIALOG (chooser)); g_object_set (G_OBJECT (plugin), "button-icon", icon, NULL); - xfce_panel_image_set_from_source (XFCE_PANEL_IMAGE (plugin->dialog_icon), - exo_str_is_empty (plugin->button_icon) ? - DEFAULT_ICON_NAME : plugin->button_icon); g_free (icon); } @@ -594,7 +592,7 @@ ApplicationsMenuPlugin *plugin) { GError *error = NULL; - const gchar command[] = "alacarte"; + const gchar *command = "alacarte"; panel_return_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin)); panel_return_if_fail (GTK_IS_WIDGET (button)); @@ -745,41 +743,325 @@ static void -applications_menu_plugin_set_garcon_menu (ApplicationsMenuPlugin *plugin) +applications_menu_plugin_append_quoted (GString *string, + const gchar *unquoted) { - GarconMenu *menu = NULL; - gchar *filename; - GFile *file; + gchar *quoted; + + quoted = g_shell_quote (unquoted); + g_string_append (string, quoted); + g_free (quoted); +} + + + +static void +applications_menu_plugin_menu_item_activate (GtkWidget *mi, + GarconMenuItem *item) +{ + GString *string; + const gchar *command; + const gchar *p; + const gchar *tmp; + gchar **argv; + gboolean result = FALSE; + gchar *uri; + GError *error = NULL; + + panel_return_if_fail (GTK_IS_WIDGET (mi)); + panel_return_if_fail (GARCON_IS_MENU_ITEM (item)); + + command = garcon_menu_item_get_command (item); + if (exo_str_is_empty (command)) + return; + + string = g_string_sized_new (100); + + if (garcon_menu_item_requires_terminal (item)) + g_string_append (string, "exo-open --launch TerminalEmulator "); + + /* expand the field codes */ + for (p = command; *p != '\0'; ++p) + { + if (G_UNLIKELY (p[0] == '%' && p[1] != '\0')) + { + switch (*++p) + { + case 'f': case 'F': + case 'u': case 'U': + /* TODO for dnd, not a regression, xfdesktop never had this */ + break; + + case 'i': + tmp = garcon_menu_item_get_icon_name (item); + if (!exo_str_is_empty (tmp)) + { + g_string_append (string, "--icon "); + applications_menu_plugin_append_quoted (string, tmp); + } + break; + + case 'c': + tmp = garcon_menu_item_get_name (item); + if (!exo_str_is_empty (tmp)) + applications_menu_plugin_append_quoted (string, tmp); + break; + + case 'k': + uri = garcon_menu_item_get_uri (item); + if (!exo_str_is_empty (uri)) + applications_menu_plugin_append_quoted (string, uri); + g_free (uri); + break; + + case '%': + g_string_append_c (string, '%'); + break; + } + } + else + { + g_string_append_c (string, *p); + } + } + + /* parse and spawn command */ + if (g_shell_parse_argv (string->str, NULL, &argv, &error)) + { + result = xfce_spawn_on_screen (gtk_widget_get_screen (mi), + garcon_menu_item_get_path (item), + argv, NULL, G_SPAWN_SEARCH_PATH, + garcon_menu_item_supports_startup_notification (item), + gtk_get_current_event_time (), + garcon_menu_item_get_icon_name (item), + &error); + + g_strfreev (argv); + } + + if (G_UNLIKELY (!result)) + { + xfce_dialog_show_error (NULL, error, _("Failed to execute command \"%s\"."), command); + g_error_free (error); + } + + g_string_free (string, TRUE); +} + + +static void +applications_menu_plugin_menu_item_drag_begin (GarconMenuItem *item, + GdkDragContext *drag_context) +{ + const gchar *icon_name; + + panel_return_if_fail (GARCON_IS_MENU_ITEM (item)); + + icon_name = garcon_menu_item_get_icon_name (item); + if (!exo_str_is_empty (icon_name)) + gtk_drag_set_icon_name (drag_context, icon_name, 0, 0); +} + + + +static void +applications_menu_plugin_menu_item_drag_data_get (GarconMenuItem *item, + GdkDragContext *drag_context, + GtkSelectionData *selection_data, + guint info, + guint drag_time) +{ + gchar *uris[2] = { NULL, NULL }; + + panel_return_if_fail (GARCON_IS_MENU_ITEM (item)); + + uris[0] = garcon_menu_item_get_uri (item); + if (G_LIKELY (uris[0] != NULL)) + { + gtk_selection_data_set_uris (selection_data, uris); + g_free (uris[0]); + } +} + + + +static void +applications_menu_plugin_menu_item_drag_end (ApplicationsMenuPlugin *plugin) +{ panel_return_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin)); - panel_return_if_fail (GARCON_GTK_IS_MENU (plugin->menu)); + panel_return_if_fail (GTK_IS_TOGGLE_BUTTON (plugin->button)); + panel_return_if_fail (GTK_IS_MENU (plugin->menu)); - /* load the custom menu if set */ - if (plugin->custom_menu - && plugin->custom_menu_file != NULL) - menu = garcon_menu_new_for_path (plugin->custom_menu_file); - - /* use the applications menu, this also respects the - * XDG_MENU_PREFIX environment variable */ - if (G_LIKELY (menu == NULL)) - menu = garcon_menu_new_applications (); - - /* set the menu */ - garcon_gtk_menu_set_menu (GARCON_GTK_MENU (plugin->menu), menu); - - /* debugging information */ - if (0) - { - file = garcon_menu_get_file (menu); - filename = g_file_get_parse_name (file); - g_object_unref (G_OBJECT (file)); + /* selection-done is never called, so handle that manually */ + applications_menu_plugin_menu_deactivate (plugin->menu, plugin->button); +} - panel_debug (PANEL_DEBUG_APPLICATIONSMENU, - "menu from \"%s\"", filename); - g_free (filename); + + +static void +applications_menu_plugin_menu_reload (ApplicationsMenuPlugin *plugin) +{ + panel_return_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin)); + + if (plugin->menu != NULL) + { + panel_debug (PANEL_DEBUG_APPLICATIONSMENU, + "destroy menu for reload"); + + /* if the menu is opened, do not destroy it under the users' + * cursor, else destroy the menu in an idle, to give garcon + * time to finalize the events that triggered the reload */ + if (GTK_WIDGET_VISIBLE (plugin->menu)) + g_signal_connect (G_OBJECT (plugin->menu), "selection-done", + G_CALLBACK (exo_gtk_object_destroy_later), NULL); + else + exo_gtk_object_destroy_later (GTK_OBJECT (plugin->menu)); } +} + + + +static gboolean +applications_menu_plugin_menu_add (GtkWidget *gtk_menu, + GtkWidget *button, + GarconMenu *menu, + ApplicationsMenuPlugin *plugin) +{ + GList *elements, *li; + GtkWidget *mi, *image; + const gchar *name, *icon_name; + const gchar *comment; + GtkWidget *submenu; + gboolean has_children = FALSE; + gint size = DEFAULT_ICON_SIZE, w, h; + const gchar *command; + GarconMenuDirectory *directory; + + panel_return_val_if_fail (GTK_IS_MENU (gtk_menu), FALSE); + panel_return_val_if_fail (GARCON_IS_MENU (menu), FALSE); + panel_return_val_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin), FALSE); + panel_return_val_if_fail (button == NULL || GTK_IS_TOGGLE_BUTTON (button), FALSE); - g_object_unref (G_OBJECT (menu)); + if (gtk_icon_size_lookup (menu_icon_size, &w, &h)) + size = MIN (w, h); + + elements = garcon_menu_get_elements (menu); + for (li = elements; li != NULL; li = li->next) + { + panel_return_val_if_fail (GARCON_IS_MENU_ELEMENT (li->data), FALSE); + if (GARCON_IS_MENU_ITEM (li->data)) + { + g_signal_connect_swapped (G_OBJECT (li->data), "changed", + G_CALLBACK (applications_menu_plugin_menu_reload), plugin); + + if (!garcon_menu_element_get_visible (li->data)) + continue; + + name = NULL; + if (plugin->show_generic_names) + name = garcon_menu_item_get_generic_name (li->data); + if (name == NULL) + name = garcon_menu_item_get_name (li->data); + if (G_UNLIKELY (name == NULL)) + continue; + + mi = gtk_image_menu_item_new_with_label (name); + gtk_menu_shell_append (GTK_MENU_SHELL (gtk_menu), mi); + g_signal_connect (G_OBJECT (mi), "activate", + G_CALLBACK (applications_menu_plugin_menu_item_activate), li->data); + gtk_widget_show (mi); + + if (plugin->show_tooltips) + { + comment = garcon_menu_item_get_comment (li->data); + if (!exo_str_is_empty (comment)) + gtk_widget_set_tooltip_text (mi, comment); + } + + /* dragging items from the menu to the panel */ + gtk_drag_source_set (mi, GDK_BUTTON1_MASK, dnd_target_list, + G_N_ELEMENTS (dnd_target_list), GDK_ACTION_COPY); + g_signal_connect_swapped (G_OBJECT (mi), "drag-begin", + G_CALLBACK (applications_menu_plugin_menu_item_drag_begin), li->data); + g_signal_connect_swapped (G_OBJECT (mi), "drag-data-get", + G_CALLBACK (applications_menu_plugin_menu_item_drag_data_get), li->data); + g_signal_connect_swapped (G_OBJECT (mi), "drag-end", + G_CALLBACK (applications_menu_plugin_menu_item_drag_end), plugin); + + command = garcon_menu_item_get_command (li->data); + if (G_UNLIKELY (exo_str_is_empty (command))) + gtk_widget_set_sensitive (mi, FALSE); + + if (plugin->show_menu_icons) + { + icon_name = garcon_menu_item_get_icon_name (li->data); + if (exo_str_is_empty (icon_name)) + icon_name = "applications-other"; + + image = xfce_panel_image_new_from_source (icon_name); + xfce_panel_image_set_size (XFCE_PANEL_IMAGE (image), size); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image); + gtk_widget_show (image); + } + + has_children = TRUE; + } + else if (GARCON_IS_MENU_SEPARATOR (li->data)) + { + mi = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (gtk_menu), mi); + gtk_widget_show (mi); + } + else if (GARCON_IS_MENU (li->data)) + { + /* the element check for menu also copies the item list to + * check if all the elements are visible, we do that with the + * return value of this function, so avoid that and only check + * the visibility of the menu directory */ + directory = garcon_menu_get_directory (li->data); + if (directory != NULL + && !garcon_menu_directory_get_visible (directory)) + continue; + + submenu = gtk_menu_new (); + if (applications_menu_plugin_menu_add (submenu, button, li->data, plugin)) + { + name = garcon_menu_element_get_name (li->data); + mi = gtk_image_menu_item_new_with_label (name); + gtk_menu_shell_append (GTK_MENU_SHELL (gtk_menu), mi); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), submenu); + g_signal_connect (G_OBJECT (submenu), "selection-done", + G_CALLBACK (applications_menu_plugin_menu_deactivate), button); + gtk_widget_show (mi); + + g_signal_connect_swapped (G_OBJECT (li->data), "directory-changed", + G_CALLBACK (applications_menu_plugin_menu_reload), plugin); + + if (plugin->show_menu_icons) + { + icon_name = garcon_menu_element_get_icon_name (li->data); + if (exo_str_is_empty (icon_name)) + icon_name = "applications-other"; + + image = xfce_panel_image_new_from_source (icon_name); + xfce_panel_image_set_size (XFCE_PANEL_IMAGE (image), size); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image); + gtk_widget_show (image); + } + + has_children = TRUE; + } + else + { + gtk_widget_destroy (submenu); + } + } + } + + g_list_free (elements); + + return has_children; } @@ -789,10 +1071,16 @@ GdkEventButton *event, ApplicationsMenuPlugin *plugin) { + GtkWidget *mi; + GarconMenu *menu = NULL; + GError *error = NULL; + gchar *filename; + GFile *file; + panel_return_val_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin), FALSE); panel_return_val_if_fail (button == NULL || plugin->button == button, FALSE); - if (event != NULL /* remove event */ + if (event != NULL && !(event->button == 1 && event->type == GDK_BUTTON_PRESS && !PANEL_HAS_FLAG (event->state, GDK_CONTROL_MASK))) @@ -801,7 +1089,64 @@ if (button != NULL) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); - /* show the menu */ + if (plugin->menu == NULL) + { + if (G_UNLIKELY (plugin->custom_menu + && plugin->custom_menu_file != NULL)) + menu = garcon_menu_new_for_path (plugin->custom_menu_file); + + /* use the applications menu, this also respects the + * XDG_MENU_PREFIX environment variable */ + if (G_LIKELY (menu == NULL)) + menu = garcon_menu_new_applications (); + + if (menu != NULL + && garcon_menu_load (menu, NULL, &error)) + { + plugin->menu = gtk_menu_new (); + g_signal_connect (G_OBJECT (plugin->menu), "selection-done", + G_CALLBACK (applications_menu_plugin_menu_deactivate), button); + g_object_add_weak_pointer (G_OBJECT (plugin->menu), (gpointer) &plugin->menu); + + if (!applications_menu_plugin_menu_add (plugin->menu, button, menu, plugin)) + { + mi = gtk_menu_item_new_with_label (_("No applications found")); + gtk_menu_shell_append (GTK_MENU_SHELL (plugin->menu), mi); + gtk_widget_set_sensitive (mi, FALSE); + gtk_widget_show (mi); + } + + /* watch the menu for changes */ + g_object_weak_ref (G_OBJECT (plugin->menu), + (GWeakNotify) g_object_unref, menu); + g_signal_connect_swapped (G_OBJECT (menu), "reload-required", + G_CALLBACK (applications_menu_plugin_menu_reload), plugin); + + /* debugging information */ + file = garcon_menu_get_file (menu); + filename = g_file_get_parse_name (file); + g_object_unref (G_OBJECT (file)); + + panel_debug (PANEL_DEBUG_APPLICATIONSMENU, + "loading from %s", filename); + g_free (filename); + } + else + { + xfce_dialog_show_error (NULL, error, _("Failed to load the applications menu")); + + if (button != NULL) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE); + + if (G_LIKELY (error != NULL)) + g_error_free (error); + if (G_LIKELY (menu != NULL)) + g_object_unref (G_OBJECT (menu)); + + return FALSE; + } + } + gtk_menu_popup (GTK_MENU (plugin->menu), NULL, NULL, button != NULL ? xfce_panel_plugin_position_menu : NULL, plugin, 1, @@ -809,15 +1154,3 @@ return TRUE; } - - - -static void -applications_menu_button_theme_changed (ApplicationsMenuPlugin *plugin) -{ - XfcePanelPlugin *panel_plugin = XFCE_PANEL_PLUGIN (plugin); - - applications_menu_plugin_size_changed (panel_plugin, - xfce_panel_plugin_get_size (panel_plugin)); -} - diff -urN xfce4-panel-4.12.0.orig/plugins/applicationsmenu/applicationsmenu.desktop.in xfce4-panel-4.12.0/plugins/applicationsmenu/applicationsmenu.desktop.in --- xfce4-panel-4.12.0.orig/plugins/applicationsmenu/applicationsmenu.desktop.in 1970-01-01 01:00:00.000000000 +0100 +++ xfce4-panel-4.12.0/plugins/applicationsmenu/applicationsmenu.desktop.in 2013-05-05 17:47:07.000000000 +0200 @@ -0,0 +1,7 @@ +[Xfce Panel] +Type=X-XFCE-PanelPlugin +_Name=Applications Menu +_Comment=Show a menu containing categories of installed applications +Icon=xfce4-panel-menu +X-XFCE-Module=applicationsmenu +X-XFCE-Internal=TRUE diff -urN xfce4-panel-4.12.0.orig/plugins/applicationsmenu/applicationsmenu-dialog.glade xfce4-panel-4.12.0/plugins/applicationsmenu/applicationsmenu-dialog.glade --- xfce4-panel-4.12.0.orig/plugins/applicationsmenu/applicationsmenu-dialog.glade 2014-04-24 22:16:37.000000000 +0200 +++ xfce4-panel-4.12.0/plugins/applicationsmenu/applicationsmenu-dialog.glade 2013-05-05 17:47:07.000000000 +0200 @@ -1,6 +1,6 @@ - + diff -urN xfce4-panel-4.12.0.orig/plugins/applicationsmenu/applicationsmenu-dialog_ui.h xfce4-panel-4.12.0/plugins/applicationsmenu/applicationsmenu-dialog_ui.h --- xfce4-panel-4.12.0.orig/plugins/applicationsmenu/applicationsmenu-dialog_ui.h 2015-02-28 17:22:40.000000000 +0100 +++ xfce4-panel-4.12.0/plugins/applicationsmenu/applicationsmenu-dialog_ui.h 2013-05-05 17:47:21.000000000 +0200 @@ -8,7 +8,7 @@ static const char applicationsmenu_dialog_ui[] = #endif { - "Applications Menugtk-propertiesnor" diff -urN xfce4-panel-4.12.0.orig/plugins/applicationsmenu/Makefile.am xfce4-panel-4.12.0/plugins/applicationsmenu/Makefile.am --- xfce4-panel-4.12.0.orig/plugins/applicationsmenu/Makefile.am 2014-04-24 22:16:37.000000000 +0200 +++ xfce4-panel-4.12.0/plugins/applicationsmenu/Makefile.am 2013-05-05 17:47:07.000000000 +0200 @@ -24,7 +24,6 @@ $(LIBXFCE4UTIL_CFLAGS) \ $(LIBXFCE4UI_CFLAGS) \ $(GARCON_CFLAGS) \ - $(GARCON_GTK2_CFLAGS) \ $(PLATFORM_CFLAGS) libapplicationsmenu_la_LDFLAGS = \ @@ -42,7 +41,6 @@ $(LIBXFCE4UTIL_LIBS) \ $(LIBXFCE4UI_LIBS) \ $(GARCON_LIBS) \ - $(GARCON_GTK2_LIBS) \ $(XFCONF_LIBS) libapplicationsmenu_la_DEPENDENCIES = \ @@ -63,8 +61,8 @@ # .desktop file # desktopdir = $(datadir)/xfce4/panel/plugins -desktop_in_files = applicationsmenu.desktop.in.in -desktop_DATA = $(desktop_in_files:.desktop.in.in=.desktop) +desktop_in_files = applicationsmenu.desktop.in +desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) @INTLTOOL_DESKTOP_RULE@ EXTRA_DIST = \ diff -urN xfce4-panel-4.12.0.orig/plugins/applicationsmenu/Makefile.in xfce4-panel-4.12.0/plugins/applicationsmenu/Makefile.in --- xfce4-panel-4.12.0.orig/plugins/applicationsmenu/Makefile.in 2015-02-28 17:21:58.000000000 +0100 +++ xfce4-panel-4.12.0/plugins/applicationsmenu/Makefile.in 2013-05-05 17:47:11.000000000 +0200 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.13.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -17,61 +17,23 @@ VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ +am__make_dryrun = \ + { \ + am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -94,14 +56,15 @@ @MAINTAINER_MODE_TRUE@ $(libapplicationsmenu_built_sources) subdir = plugins/applicationsmenu +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = applicationsmenu.desktop.in +CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ @@ -208,8 +171,6 @@ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags -am__DIST_COMMON = $(srcdir)/Makefile.in \ - $(srcdir)/applicationsmenu.desktop.in.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ @@ -253,10 +214,6 @@ EXO_VERSION = @EXO_VERSION@ FGREP = @FGREP@ GARCON_CFLAGS = @GARCON_CFLAGS@ -GARCON_GTK2_CFLAGS = @GARCON_GTK2_CFLAGS@ -GARCON_GTK2_LIBS = @GARCON_GTK2_LIBS@ -GARCON_GTK2_REQUIRED_VERSION = @GARCON_GTK2_REQUIRED_VERSION@ -GARCON_GTK2_VERSION = @GARCON_GTK2_VERSION@ GARCON_LIBS = @GARCON_LIBS@ GARCON_REQUIRED_VERSION = @GARCON_REQUIRED_VERSION@ GARCON_VERSION = @GARCON_VERSION@ @@ -280,12 +237,7 @@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ -GTK3_CFLAGS = @GTK3_CFLAGS@ -GTK3_LIBS = @GTK3_LIBS@ -GTK3_REQUIRED_VERSION = @GTK3_REQUIRED_VERSION@ -GTK3_VERSION = @GTK3_VERSION@ GTKDOC_CHECK = @GTKDOC_CHECK@ -GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ @@ -341,7 +293,6 @@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ @@ -472,7 +423,6 @@ $(LIBXFCE4UTIL_CFLAGS) \ $(LIBXFCE4UI_CFLAGS) \ $(GARCON_CFLAGS) \ - $(GARCON_GTK2_CFLAGS) \ $(PLATFORM_CFLAGS) libapplicationsmenu_la_LDFLAGS = \ @@ -490,7 +440,6 @@ $(LIBXFCE4UTIL_LIBS) \ $(LIBXFCE4UI_LIBS) \ $(GARCON_LIBS) \ - $(GARCON_GTK2_LIBS) \ $(XFCONF_LIBS) libapplicationsmenu_la_DEPENDENCIES = \ @@ -509,8 +458,8 @@ # .desktop file # desktopdir = $(datadir)/xfce4/panel/plugins -desktop_in_files = applicationsmenu.desktop.in.in -desktop_DATA = $(desktop_in_files:.desktop.in.in=.desktop) +desktop_in_files = applicationsmenu.desktop.in +desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) EXTRA_DIST = \ applicationsmenu-dialog.glade \ xfce4-popup-applicationsmenu.sh \ @@ -538,6 +487,7 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/applicationsmenu/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu plugins/applicationsmenu/Makefile +.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -555,8 +505,6 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): -applicationsmenu.desktop.in: $(top_builddir)/config.status $(srcdir)/applicationsmenu.desktop.in.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @@ -592,7 +540,6 @@ echo rm -f $${locs}; \ rm -f $${locs}; \ } - libapplicationsmenu.la: $(libapplicationsmenu_la_OBJECTS) $(libapplicationsmenu_la_DEPENDENCIES) $(EXTRA_libapplicationsmenu_la_DEPENDENCIES) $(AM_V_CCLD)$(libapplicationsmenu_la_LINK) -rpath $(plugindir) $(libapplicationsmenu_la_OBJECTS) $(libapplicationsmenu_la_LIBADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @@ -644,14 +591,14 @@ @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -907,8 +854,6 @@ tags tags-am uninstall uninstall-am uninstall-binSCRIPTS \ uninstall-desktopDATA uninstall-pluginLTLIBRARIES -.PRECIOUS: Makefile - xfce4-popup-applicationsmenu: xfce4-popup-applicationsmenu.sh Makefile $(AM_V_GEN) $(SED) -e "s,\@bindir\@,$(bindir),g" \