Instantly share code, notes, and snippets.
Misko-2083/applicationsmenu.c Secret
Created
June 28, 2024 16:34
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save Misko-2083/acebf1a0a5db15f62ac27fe971e25142 to your computer and use it in GitHub Desktop.
Closing applications menu with the Super_L key
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (C) 2010 Nick Schermer <nick@xfce.org> | |
* | |
* This library is free software; you can redistribute it and/or modify it | |
* under the terms of the GNU General Public License as published by the Free | |
* Software Foundation; either version 2 of the License, or (at your option) | |
* any later version. | |
* | |
* This library is distributed in the hope that it will be useful, but WITHOUT | |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
* more details. | |
* | |
* You should have received a copy of the GNU Lesser General Public | |
* License along with this library; if not, write to the Free Software | |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
*/ | |
#ifdef HAVE_CONFIG_H | |
#include <config.h> | |
#endif | |
#include <exo/exo.h> | |
#include <garcon/garcon.h> | |
#include <garcon-gtk/garcon-gtk.h> | |
#include <libxfce4ui/libxfce4ui.h> | |
#include <libxfce4util/libxfce4util.h> | |
#include <libxfce4panel/libxfce4panel.h> | |
#include <common/panel-xfconf.h> | |
#include <common/panel-utils.h> | |
#include <common/panel-private.h> | |
#include <common/panel-debug.h> | |
#include "applicationsmenu.h" | |
#include "applicationsmenu-dialog_ui.h" | |
/* I18N: default tooltip of the application menu */ | |
#define DEFAULT_TITLE _("Applications") | |
#define DEFAULT_ICON_NAME "org.xfce.panel.applicationsmenu" | |
#define DEFAULT_ICON_SIZE (16) | |
#define DIALOG_ICON_SIZE (48) | |
#define DEFAULT_EDITOR "menulibre" | |
struct _ApplicationsMenuPluginClass | |
{ | |
XfcePanelPluginClass __parent__; | |
}; | |
struct _ApplicationsMenuPlugin | |
{ | |
XfcePanelPlugin __parent__; | |
GtkWidget *button; | |
GtkWidget *box; | |
GtkWidget *image; | |
GtkWidget *label; | |
GtkWidget *menu; | |
guint is_constructed : 1; | |
guint show_button_title : 1; | |
guint small : 1; | |
gchar *button_title; | |
gchar *button_icon; | |
gboolean custom_menu; | |
gchar *custom_menu_file; | |
gchar *menu_editor; | |
gulong style_updated_id; | |
gulong screen_changed_id; | |
gulong theme_changed_id; | |
}; | |
enum | |
{ | |
PROP_0, | |
PROP_SHOW_GENERIC_NAMES, | |
PROP_SHOW_MENU_ICONS, | |
PROP_SHOW_TOOLTIPS, | |
PROP_SHOW_BUTTON_TITLE, | |
PROP_SMALL, | |
PROP_BUTTON_TITLE, | |
PROP_BUTTON_ICON, | |
PROP_CUSTOM_MENU, | |
PROP_CUSTOM_MENU_FILE, | |
PROP_MENU_EDITOR | |
}; | |
static void applications_menu_plugin_get_property (GObject *object, | |
guint prop_id, | |
GValue *value, | |
GParamSpec *pspec); | |
static void applications_menu_plugin_set_property (GObject *object, | |
guint prop_id, | |
const GValue *value, | |
GParamSpec *pspec); | |
static void applications_menu_plugin_construct (XfcePanelPlugin *panel_plugin); | |
static void applications_menu_plugin_free_data (XfcePanelPlugin *panel_plugin); | |
static gboolean applications_menu_plugin_size_changed (XfcePanelPlugin *panel_plugin, | |
gint size); | |
static void applications_menu_plugin_mode_changed (XfcePanelPlugin *panel_plugin, | |
XfcePanelPluginMode mode); | |
static void applications_menu_plugin_configure_plugin (XfcePanelPlugin *panel_plugin); | |
static gboolean applications_menu_plugin_remote_event (XfcePanelPlugin *panel_plugin, | |
const gchar *name, | |
const GValue *value); | |
static gboolean applications_menu_plugin_menu_key_release (GtkWidget *widget, | |
GdkEventKey *event, | |
ApplicationsMenuPlugin *plugin); | |
static void connect_key_release_to_submenus (GtkWidget *menu, | |
ApplicationsMenuPlugin *plugin); | |
static gboolean applications_menu_plugin_menu (GtkWidget *button, | |
GdkEventButton *event, | |
ApplicationsMenuPlugin *plugin); | |
static void applications_menu_plugin_menu_selection_done (GtkMenuShell *menu, | |
ApplicationsMenuPlugin *plugin); | |
static void applications_menu_plugin_set_garcon_menu (ApplicationsMenuPlugin *plugin); | |
static void applications_menu_button_theme_changed (ApplicationsMenuPlugin *plugin); | |
/* define the plugin */ | |
XFCE_PANEL_DEFINE_PLUGIN (ApplicationsMenuPlugin, applications_menu_plugin) | |
static void | |
applications_menu_plugin_class_init (ApplicationsMenuPluginClass *klass) | |
{ | |
XfcePanelPluginClass *plugin_class; | |
GObjectClass *gobject_class; | |
gobject_class = G_OBJECT_CLASS (klass); | |
gobject_class->get_property = applications_menu_plugin_get_property; | |
gobject_class->set_property = applications_menu_plugin_set_property; | |
plugin_class = XFCE_PANEL_PLUGIN_CLASS (klass); | |
plugin_class->construct = applications_menu_plugin_construct; | |
plugin_class->free_data = applications_menu_plugin_free_data; | |
plugin_class->size_changed = applications_menu_plugin_size_changed; | |
plugin_class->mode_changed = applications_menu_plugin_mode_changed; | |
plugin_class->configure_plugin = applications_menu_plugin_configure_plugin; | |
plugin_class->remote_event = applications_menu_plugin_remote_event; | |
g_object_class_install_property (gobject_class, | |
PROP_SHOW_GENERIC_NAMES, | |
g_param_spec_boolean ("show-generic-names", | |
NULL, NULL, | |
FALSE, | |
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
g_object_class_install_property (gobject_class, | |
PROP_SHOW_MENU_ICONS, | |
g_param_spec_boolean ("show-menu-icons", | |
NULL, NULL, | |
TRUE, | |
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
g_object_class_install_property (gobject_class, | |
PROP_SHOW_TOOLTIPS, | |
g_param_spec_boolean ("show-tooltips", | |
NULL, NULL, | |
FALSE, | |
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
g_object_class_install_property (gobject_class, | |
PROP_SHOW_BUTTON_TITLE, | |
g_param_spec_boolean ("show-button-title", | |
NULL, NULL, | |
TRUE, | |
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
g_object_class_install_property (gobject_class, | |
PROP_SMALL, | |
g_param_spec_boolean ("small", | |
NULL, NULL, | |
FALSE, | |
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
g_object_class_install_property (gobject_class, | |
PROP_BUTTON_TITLE, | |
g_param_spec_string ("button-title", | |
NULL, NULL, | |
DEFAULT_TITLE, | |
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
g_object_class_install_property (gobject_class, | |
PROP_BUTTON_ICON, | |
g_param_spec_string ("button-icon", | |
NULL, NULL, | |
DEFAULT_ICON_NAME, | |
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
g_object_class_install_property (gobject_class, | |
PROP_CUSTOM_MENU, | |
g_param_spec_boolean ("custom-menu", | |
NULL, NULL, | |
FALSE, | |
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
g_object_class_install_property (gobject_class, | |
PROP_CUSTOM_MENU_FILE, | |
g_param_spec_string ("custom-menu-file", | |
NULL, NULL, | |
NULL, | |
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
g_object_class_install_property (gobject_class, | |
PROP_MENU_EDITOR, | |
g_param_spec_string ("menu-editor", | |
NULL, NULL, | |
DEFAULT_EDITOR, | |
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
} | |
static void | |
applications_menu_plugin_init (ApplicationsMenuPlugin *plugin) | |
{ | |
GtkIconTheme *icon_theme; | |
/* init garcon environment */ | |
garcon_set_environment_xdg (GARCON_ENVIRONMENT_XFCE); | |
icon_theme = gtk_icon_theme_get_default (); | |
plugin->button = xfce_panel_create_toggle_button (); | |
xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (plugin), plugin->button); | |
gtk_container_add (GTK_CONTAINER (plugin), plugin->button); | |
gtk_widget_set_name (plugin->button, "applicationmenu-button"); | |
gtk_button_set_relief (GTK_BUTTON (plugin->button), GTK_RELIEF_NONE); | |
gtk_widget_set_tooltip_text (plugin->button, DEFAULT_TITLE); | |
g_signal_connect (G_OBJECT (plugin->button), "button-press-event", | |
G_CALLBACK (applications_menu_plugin_menu), plugin); | |
plugin->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); | |
gtk_container_set_border_width (GTK_CONTAINER (plugin->box), 0); | |
gtk_container_add (GTK_CONTAINER (plugin->button), plugin->box); | |
gtk_widget_show (plugin->box); | |
plugin->button_icon = g_strdup (DEFAULT_ICON_NAME); | |
plugin->image = gtk_image_new_from_icon_name (plugin->button_icon, DEFAULT_ICON_SIZE); | |
gtk_box_pack_start (GTK_BOX (plugin->box), plugin->image, FALSE, FALSE, 0); | |
gtk_widget_show (plugin->image); | |
plugin->label = gtk_label_new (DEFAULT_TITLE); | |
gtk_box_pack_start (GTK_BOX (plugin->box), plugin->label, FALSE, FALSE, 0); | |
plugin->show_button_title = TRUE; | |
gtk_widget_show (plugin->label); | |
/* prepare the menu: some situations, such as cancelling a dnd, require connecting to | |
* "selection-done" instead of "deactivate" */ | |
plugin->menu = garcon_gtk_menu_new (NULL); | |
g_signal_connect (G_OBJECT (plugin->menu), "selection-done", | |
G_CALLBACK (applications_menu_plugin_menu_selection_done), plugin); | |
plugin->style_updated_id = g_signal_connect_swapped (G_OBJECT (plugin->button), "style-updated", | |
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); | |
plugin->theme_changed_id = g_signal_connect_swapped (G_OBJECT (icon_theme), "changed", | |
G_CALLBACK (applications_menu_plugin_set_garcon_menu), plugin); | |
} | |
static void | |
applications_menu_plugin_get_property (GObject *object, | |
guint prop_id, | |
GValue *value, | |
GParamSpec *pspec) | |
{ | |
ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (object); | |
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))); | |
break; | |
case PROP_SHOW_MENU_ICONS: | |
g_value_set_boolean (value, | |
garcon_gtk_menu_get_show_menu_icons (GARCON_GTK_MENU (plugin->menu))); | |
break; | |
case PROP_SHOW_TOOLTIPS: | |
g_value_set_boolean (value, | |
garcon_gtk_menu_get_show_tooltips (GARCON_GTK_MENU (plugin->menu))); | |
break; | |
case PROP_SHOW_BUTTON_TITLE: | |
g_value_set_boolean (value, plugin->show_button_title); | |
break; | |
case PROP_SMALL: | |
g_value_set_boolean (value, plugin->small); | |
break; | |
case PROP_BUTTON_TITLE: | |
g_value_set_string (value, plugin->button_title == NULL ? | |
DEFAULT_TITLE : plugin->button_title); | |
break; | |
case PROP_BUTTON_ICON: | |
g_value_set_string (value, plugin->button_icon); | |
break; | |
case PROP_CUSTOM_MENU: | |
g_value_set_boolean (value, plugin->custom_menu); | |
break; | |
case PROP_CUSTOM_MENU_FILE: | |
g_value_set_string (value, plugin->custom_menu_file); | |
break; | |
case PROP_MENU_EDITOR: | |
g_value_set_string (value, plugin->menu_editor); | |
break; | |
default: | |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | |
break; | |
} | |
} | |
static void | |
applications_menu_plugin_set_property (GObject *object, | |
guint prop_id, | |
const GValue *value, | |
GParamSpec *pspec) | |
{ | |
ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (object); | |
gboolean force_a_resize = 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)); | |
break; | |
case PROP_SHOW_MENU_ICONS: | |
garcon_gtk_menu_set_show_menu_icons (GARCON_GTK_MENU (plugin->menu), | |
g_value_get_boolean (value)); | |
break; | |
case PROP_SHOW_TOOLTIPS: | |
garcon_gtk_menu_set_show_tooltips (GARCON_GTK_MENU (plugin->menu), | |
g_value_get_boolean (value)); | |
break; | |
case PROP_SHOW_BUTTON_TITLE: | |
plugin->show_button_title = g_value_get_boolean (value); | |
if (plugin->show_button_title) | |
gtk_widget_show (plugin->label); | |
else | |
gtk_widget_hide (plugin->label); | |
applications_menu_plugin_size_changed (XFCE_PANEL_PLUGIN (plugin), | |
xfce_panel_plugin_get_size (XFCE_PANEL_PLUGIN (plugin))); | |
return; | |
case PROP_SMALL: | |
plugin->small = g_value_get_boolean (value); | |
xfce_panel_plugin_set_small (XFCE_PANEL_PLUGIN (plugin), plugin->small); | |
applications_menu_plugin_size_changed (XFCE_PANEL_PLUGIN (plugin), | |
xfce_panel_plugin_get_size (XFCE_PANEL_PLUGIN (plugin))); | |
break; | |
case PROP_BUTTON_TITLE: | |
g_free (plugin->button_title); | |
plugin->button_title = g_value_dup_string (value); | |
gtk_label_set_text (GTK_LABEL (plugin->label), | |
plugin->button_title != NULL ? plugin->button_title : ""); | |
gtk_widget_set_tooltip_text (plugin->button, | |
panel_str_is_empty (plugin->button_title) ? NULL : plugin->button_title); | |
/* check if the label still fits */ | |
if (xfce_panel_plugin_get_mode (XFCE_PANEL_PLUGIN (plugin)) == XFCE_PANEL_PLUGIN_MODE_DESKBAR | |
&& plugin->show_button_title) | |
{ | |
force_a_resize = TRUE; | |
} | |
break; | |
case PROP_BUTTON_ICON: | |
g_free (plugin->button_icon); | |
plugin->button_icon = | |
panel_str_is_empty (g_value_get_string (value)) ? g_strdup (DEFAULT_ICON_NAME) | |
: g_value_dup_string (value); | |
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); | |
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); | |
break; | |
case PROP_MENU_EDITOR: | |
plugin->menu_editor = g_value_dup_string (value); | |
break; | |
default: | |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | |
break; | |
} | |
if (force_a_resize) | |
{ | |
applications_menu_plugin_size_changed (XFCE_PANEL_PLUGIN (plugin), | |
xfce_panel_plugin_get_size (XFCE_PANEL_PLUGIN (plugin))); | |
} | |
} | |
static void | |
applications_menu_plugin_construct (XfcePanelPlugin *panel_plugin) | |
{ | |
ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin); | |
const PanelProperty properties[] = | |
{ | |
{ "show-generic-names", G_TYPE_BOOLEAN }, | |
{ "show-menu-icons", G_TYPE_BOOLEAN }, | |
{ "show-button-title", G_TYPE_BOOLEAN }, | |
{ "show-tooltips", G_TYPE_BOOLEAN }, | |
{ "small", G_TYPE_BOOLEAN }, | |
{ "button-title", G_TYPE_STRING }, | |
{ "button-icon", G_TYPE_STRING }, | |
{ "custom-menu", G_TYPE_BOOLEAN }, | |
{ "custom-menu-file", G_TYPE_STRING }, | |
{ "menu-editor", G_TYPE_STRING }, | |
{ NULL } | |
}; | |
xfce_panel_plugin_menu_show_configure (XFCE_PANEL_PLUGIN (plugin)); | |
/* bind all properties */ | |
panel_properties_bind (NULL, G_OBJECT (plugin), | |
xfce_panel_plugin_get_property_base (panel_plugin), | |
properties, FALSE); | |
/* make sure the menu is set */ | |
applications_menu_plugin_set_garcon_menu (plugin); | |
if (!plugin->menu_editor) | |
plugin->menu_editor = DEFAULT_EDITOR; | |
gtk_widget_show (plugin->button); | |
applications_menu_plugin_size_changed (panel_plugin, | |
xfce_panel_plugin_get_size (panel_plugin)); | |
plugin->is_constructed = TRUE; | |
} | |
static void | |
applications_menu_plugin_free_data (XfcePanelPlugin *panel_plugin) | |
{ | |
ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin); | |
GtkIconTheme *icon_theme; | |
if (plugin->menu != NULL) | |
gtk_widget_destroy (plugin->menu); | |
if (plugin->style_updated_id != 0) | |
{ | |
g_signal_handler_disconnect (plugin->button, plugin->style_updated_id); | |
plugin->style_updated_id = 0; | |
} | |
if (plugin->screen_changed_id != 0) | |
{ | |
g_signal_handler_disconnect (plugin->button, plugin->screen_changed_id); | |
plugin->screen_changed_id = 0; | |
} | |
if (plugin->theme_changed_id != 0) | |
{ | |
icon_theme = gtk_icon_theme_get_default (); | |
g_signal_handler_disconnect (G_OBJECT (icon_theme), | |
plugin->theme_changed_id); | |
plugin->theme_changed_id = 0; | |
} | |
g_free (plugin->button_title); | |
g_free (plugin->button_icon); | |
g_free (plugin->custom_menu_file); | |
} | |
static gboolean | |
applications_menu_plugin_size_changed (XfcePanelPlugin *panel_plugin, | |
gint size) | |
{ | |
ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin); | |
XfcePanelPluginMode mode; | |
GtkRequisition label_size; | |
GtkOrientation orientation; | |
gint border_thickness; | |
gint icon_size; | |
GdkScreen *screen; | |
GtkIconTheme *icon_theme = NULL; | |
GtkStyleContext *ctx; | |
GtkBorder padding, border; | |
gtk_box_set_child_packing (GTK_BOX (plugin->box), plugin->image, | |
!plugin->show_button_title, | |
!plugin->show_button_title, | |
0, GTK_PACK_START); | |
mode = xfce_panel_plugin_get_mode (panel_plugin); | |
if (mode == XFCE_PANEL_PLUGIN_MODE_HORIZONTAL) | |
orientation = GTK_ORIENTATION_HORIZONTAL; | |
else | |
orientation = GTK_ORIENTATION_VERTICAL; | |
/* style thickness */ | |
ctx = gtk_widget_get_style_context (plugin->button); | |
gtk_style_context_get_padding (ctx, gtk_widget_get_state_flags (plugin->button), &padding); | |
gtk_style_context_get_border (ctx, gtk_widget_get_state_flags (plugin->button), &border); | |
border_thickness = MAX (padding.left + padding.right + border.left + border.right, | |
padding.top + padding.bottom + border.top + border.bottom); | |
icon_size = xfce_panel_plugin_get_icon_size (panel_plugin); | |
if (! plugin->small) | |
icon_size *= xfce_panel_plugin_get_nrows (panel_plugin); | |
screen = gtk_widget_get_screen (GTK_WIDGET (plugin)); | |
if (G_LIKELY (screen != NULL)) | |
icon_theme = gtk_icon_theme_get_for_screen (screen); | |
xfce_panel_set_image_from_source (GTK_IMAGE (plugin->image), plugin->button_icon, | |
icon_theme, icon_size, | |
gtk_widget_get_scale_factor (GTK_WIDGET (plugin))); | |
if (plugin->show_button_title && | |
mode == XFCE_PANEL_PLUGIN_MODE_DESKBAR) | |
{ | |
/* check if the label (minimum size) fits next to the icon */ | |
gtk_widget_get_preferred_size (GTK_WIDGET (plugin->label), &label_size, NULL); | |
if (label_size.width <= size - icon_size - 2 - border_thickness) | |
orientation = GTK_ORIENTATION_HORIZONTAL; | |
} | |
gtk_orientable_set_orientation (GTK_ORIENTABLE (plugin->box), orientation); | |
return TRUE; | |
} | |
static void | |
applications_menu_plugin_mode_changed (XfcePanelPlugin *panel_plugin, | |
XfcePanelPluginMode mode) | |
{ | |
ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin); | |
gint angle; | |
angle = (mode == XFCE_PANEL_PLUGIN_MODE_VERTICAL) ? 270 : 0; | |
gtk_label_set_angle (GTK_LABEL (plugin->label), angle); | |
applications_menu_plugin_size_changed (panel_plugin, | |
xfce_panel_plugin_get_size (panel_plugin)); | |
} | |
static void | |
applications_menu_plugin_configure_plugin_file_set (GtkFileChooserButton *button, | |
ApplicationsMenuPlugin *plugin) | |
{ | |
gchar *filename; | |
panel_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button)); | |
panel_return_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin)); | |
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (button)); | |
g_object_set (G_OBJECT (plugin), "custom-menu-file", filename, NULL); | |
g_free (filename); | |
} | |
static void | |
applications_menu_plugin_configure_plugin_icon_chooser (GtkWidget *button, | |
ApplicationsMenuPlugin *plugin) | |
{ | |
GtkWidget *chooser, *image; | |
gchar *icon; | |
panel_return_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin)); | |
chooser = exo_icon_chooser_dialog_new (_("Select An Icon"), | |
GTK_WINDOW (gtk_widget_get_toplevel (button)), | |
_("_Cancel"), GTK_RESPONSE_CANCEL, | |
_("_OK"), GTK_RESPONSE_ACCEPT, | |
NULL); | |
gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_ACCEPT); | |
exo_icon_chooser_dialog_set_icon (EXO_ICON_CHOOSER_DIALOG (chooser), plugin->button_icon); | |
if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT) | |
{ | |
icon = exo_icon_chooser_dialog_get_icon (EXO_ICON_CHOOSER_DIALOG (chooser)); | |
g_object_set (G_OBJECT (plugin), "button-icon", icon, NULL); | |
g_free (icon); | |
image = gtk_image_new (); | |
xfce_panel_set_image_from_source (GTK_IMAGE (image), plugin->button_icon, | |
NULL, DIALOG_ICON_SIZE, | |
gtk_widget_get_scale_factor (GTK_WIDGET (plugin))); | |
gtk_container_remove (GTK_CONTAINER (button), gtk_bin_get_child (GTK_BIN (button))); | |
gtk_container_add (GTK_CONTAINER (button), image); | |
gtk_widget_show (image); | |
} | |
gtk_widget_destroy (chooser); | |
} | |
static void | |
applications_menu_plugin_configure_plugin_edit (GtkWidget *button, | |
ApplicationsMenuPlugin *plugin) | |
{ | |
GError *error = NULL; | |
panel_return_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin)); | |
panel_return_if_fail (GTK_IS_WIDGET (button)); | |
if (!xfce_spawn_command_line (gtk_widget_get_screen (button), plugin->menu_editor, | |
FALSE, FALSE, TRUE, &error)) | |
{ | |
xfce_dialog_show_error (NULL, error, _("Failed to execute command \"%s\"."), plugin->menu_editor); | |
g_error_free (error); | |
} | |
} | |
static void | |
applications_menu_plugin_configure_plugin (XfcePanelPlugin *panel_plugin) | |
{ | |
ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin); | |
GtkBuilder *builder; | |
GtkWidget *image; | |
GObject *dialog, *object, *object2; | |
guint i; | |
gchar *path; | |
const gchar *check_names[] = { "show-generic-names", "show-menu-icons", | |
"show-tooltips", "show-button-title", "small" }; | |
/* setup the dialog */ | |
PANEL_UTILS_LINK_4UI | |
builder = panel_utils_builder_new (panel_plugin, applicationsmenu_dialog_ui, | |
applicationsmenu_dialog_ui_length, &dialog); | |
if (G_UNLIKELY (builder == NULL)) | |
return; | |
for (i = 0; i < G_N_ELEMENTS (check_names); ++i) | |
{ | |
object = gtk_builder_get_object (builder, check_names[i]); | |
panel_return_if_fail (GTK_IS_CHECK_BUTTON (object)); | |
g_object_bind_property (G_OBJECT (plugin), check_names[i], | |
G_OBJECT (object), "active", | |
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); | |
} | |
object = gtk_builder_get_object (builder, "button-title"); | |
panel_return_if_fail (GTK_IS_ENTRY (object)); | |
g_object_bind_property (G_OBJECT (plugin), "button-title", | |
G_OBJECT (object), "text", | |
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); | |
object = gtk_builder_get_object (builder, "icon-button"); | |
panel_return_if_fail (GTK_IS_BUTTON (object)); | |
g_signal_connect (G_OBJECT (object), "clicked", | |
G_CALLBACK (applications_menu_plugin_configure_plugin_icon_chooser), plugin); | |
image = gtk_image_new (); | |
xfce_panel_set_image_from_source (GTK_IMAGE (image), plugin->button_icon, | |
NULL, DIALOG_ICON_SIZE, | |
gtk_widget_get_scale_factor (GTK_WIDGET (plugin))); | |
gtk_container_add (GTK_CONTAINER (object), image); | |
gtk_widget_show (image); | |
/* whether we show the edit menu button */ | |
object = gtk_builder_get_object (builder, "edit-menu-button"); | |
panel_return_if_fail (GTK_IS_BUTTON (object)); | |
path = g_find_program_in_path (plugin->menu_editor); | |
if (path != NULL) | |
{ | |
object2 = gtk_builder_get_object (builder, "use-default-menu"); | |
panel_return_if_fail (GTK_IS_RADIO_BUTTON (object2)); | |
g_object_bind_property (G_OBJECT (object2), "active", | |
G_OBJECT (object), "sensitive", | |
G_BINDING_SYNC_CREATE); | |
g_signal_connect (G_OBJECT (object), "clicked", | |
G_CALLBACK (applications_menu_plugin_configure_plugin_edit), plugin); | |
} | |
else | |
{ | |
gtk_widget_hide (GTK_WIDGET (object)); | |
} | |
g_free (path); | |
object = gtk_builder_get_object (builder, "use-custom-menu"); | |
panel_return_if_fail (GTK_IS_RADIO_BUTTON (object)); | |
g_object_bind_property (G_OBJECT (plugin), "custom-menu", | |
G_OBJECT (object), "active", | |
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); | |
/* sensitivity of custom file selector */ | |
object2 = gtk_builder_get_object (builder, "custom-box"); | |
panel_return_if_fail (GTK_IS_WIDGET (object2)); | |
g_object_bind_property (G_OBJECT (object), "active", | |
G_OBJECT (object2), "sensitive", | |
G_BINDING_SYNC_CREATE); | |
object = gtk_builder_get_object (builder, "custom-file"); | |
panel_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (object)); | |
if (!panel_str_is_empty (plugin->custom_menu_file)) | |
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (object), plugin->custom_menu_file); | |
g_signal_connect (G_OBJECT (object), "file-set", | |
G_CALLBACK (applications_menu_plugin_configure_plugin_file_set), plugin); | |
gtk_widget_show (GTK_WIDGET (dialog)); | |
} | |
static gboolean | |
applications_menu_plugin_remote_event (XfcePanelPlugin *panel_plugin, | |
const gchar *name, | |
const GValue *value) | |
{ | |
ApplicationsMenuPlugin *plugin = XFCE_APPLICATIONS_MENU_PLUGIN (panel_plugin); | |
GtkWidget *invisible; | |
panel_return_val_if_fail (value == NULL || G_IS_VALUE (value), FALSE); | |
/* try next plugin or indicate that it failed */ | |
if (strcmp (name, "popup") != 0 | |
|| ! gtk_widget_get_visible (GTK_WIDGET (panel_plugin))) | |
return FALSE; | |
invisible = gtk_invisible_new (); | |
gtk_widget_show (invisible); | |
/* a menu is already shown, don't popup another one */ | |
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (plugin->button)) | |
|| ! panel_utils_device_grab (invisible)) | |
{ | |
gtk_widget_destroy (invisible); | |
return TRUE; | |
} | |
/* | |
* The menu will take over the grab when it is shown or it will be lost when destroying | |
* invisible below. This way we are sure that other invocations of the command by | |
* keyboard shortcut will not interfere. | |
*/ | |
if (value != NULL | |
&& G_VALUE_HOLDS_BOOLEAN (value) | |
&& g_value_get_boolean (value)) | |
{ | |
/* popup menu at pointer */ | |
applications_menu_plugin_menu (NULL, NULL, plugin); | |
} | |
else | |
{ | |
/* popup menu at button */ | |
applications_menu_plugin_menu (plugin->button, NULL, plugin); | |
} | |
gtk_widget_destroy (invisible); | |
/* don't popup another menu */ | |
return TRUE; | |
} | |
static void | |
applications_menu_plugin_menu_selection_done (GtkMenuShell *menu, | |
ApplicationsMenuPlugin *plugin) | |
{ | |
panel_return_if_fail (plugin->button == NULL || GTK_IS_TOGGLE_BUTTON (plugin->button)); | |
panel_return_if_fail (GTK_IS_MENU (menu)); | |
/* button is NULL when we popup the menu under the cursor position */ | |
if (plugin->button != NULL) | |
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->button), FALSE); | |
} | |
static void | |
applications_menu_plugin_set_garcon_menu (ApplicationsMenuPlugin *plugin) | |
{ | |
GarconMenu *menu = NULL; | |
gchar *filename; | |
GFile *file; | |
panel_return_if_fail (XFCE_IS_APPLICATIONS_MENU_PLUGIN (plugin)); | |
panel_return_if_fail (GARCON_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)); | |
panel_debug (PANEL_DEBUG_APPLICATIONSMENU, | |
"menu from \"%s\"", filename); | |
g_free (filename); | |
} | |
g_object_unref (G_OBJECT (menu)); | |
} | |
static gboolean | |
applications_menu_plugin_menu_key_release (GtkWidget *widget, | |
GdkEventKey *event, | |
ApplicationsMenuPlugin *plugin) | |
{ | |
/* Check for Super key release */ | |
if (event->keyval == GDK_KEY_Super_L) | |
{ | |
/* Close the menu */ | |
gtk_menu_popdown (GTK_MENU (plugin->menu)); | |
if (plugin->button != NULL) | |
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->button), FALSE); | |
} | |
return TRUE; | |
} | |
static void | |
connect_key_release_to_submenus (GtkWidget *menu, ApplicationsMenuPlugin *plugin) | |
{ | |
if (!GTK_IS_MENU(menu)) | |
return; | |
GList *children; | |
GtkWidget *child; | |
GtkWidget *submenu; | |
GList *iter; | |
g_signal_connect (G_OBJECT (menu), "key-release-event", | |
G_CALLBACK (applications_menu_plugin_menu_key_release), plugin); | |
children = gtk_container_get_children(GTK_CONTAINER(menu)); | |
for (iter = children; iter != NULL; iter = g_list_next(iter)) { | |
child = GTK_WIDGET(iter->data); | |
if (GTK_IS_MENU_ITEM(child)) { | |
submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(child)); | |
if (submenu) { | |
connect_key_release_to_submenus(submenu, plugin); | |
} | |
} | |
} | |
g_list_free(children); | |
} | |
static gboolean | |
applications_menu_plugin_menu (GtkWidget *button, | |
GdkEventButton *event, | |
ApplicationsMenuPlugin *plugin) | |
{ | |
GdkEvent *free_event = NULL; | |
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 */ | |
&& !(event->button == 1 | |
&& event->type == GDK_BUTTON_PRESS | |
&& !PANEL_HAS_FLAG (event->state, GDK_CONTROL_MASK))) | |
return FALSE; | |
if (button != NULL) | |
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); | |
/* Connect key release event to close menu and its submenus */ | |
connect_key_release_to_submenus(plugin->menu, plugin); | |
/* Panel plugin remote events don't send actual GdkEvents, so construct a minimal one so that | |
* gtk_menu_popup_at_pointer/rect can extract a location correctly from a GdkWindow */ | |
if (event == NULL) | |
{ | |
GdkSeat *seat = gdk_display_get_default_seat (gdk_display_get_default ()); | |
free_event = gdk_event_new (GDK_BUTTON_PRESS); | |
free_event->button.window = g_object_ref (gdk_get_default_root_window ()); | |
gdk_event_set_device (free_event, gdk_seat_get_pointer (seat)); | |
event = (GdkEventButton *)free_event; | |
} | |
/* do not block panel autohide if popup-command at pointer */ | |
if (button == NULL) | |
gtk_menu_popup_at_pointer (GTK_MENU (plugin->menu), (GdkEvent *) event); | |
else | |
xfce_panel_plugin_popup_menu (XFCE_PANEL_PLUGIN (plugin), GTK_MENU (plugin->menu), | |
button, (GdkEvent *) event); | |
if (free_event != NULL) | |
gdk_event_free (free_event); | |
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)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment