[gnome-settings-daemon] Implement popup menu for the notification icon.
- From: Sergey V. Udaltsov <svu src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-settings-daemon] Implement popup menu for the notification icon.
- Date: Sat, 26 Dec 2009 23:42:09 +0000 (UTC)
commit 5c162d1806aa72e334c64978d5cedd08c6206aa5
Author: Sergey V. Udaltsov <svu gnome org>
Date: Sat Dec 26 23:40:44 2009 +0000
Implement popup menu for the notification icon.
plugins/keyboard/Makefile.am | 2 +-
plugins/keyboard/gsd-keyboard-xkb.c | 366 ++++++++++++++++++++++++++++++++---
plugins/keyboard/show-layout.ui | 83 ++++++++
po/POTFILES.in | 1 +
4 files changed, 422 insertions(+), 30 deletions(-)
---
diff --git a/plugins/keyboard/Makefile.am b/plugins/keyboard/Makefile.am
index f3e1a22..1b7bc3e 100644
--- a/plugins/keyboard/Makefile.am
+++ b/plugins/keyboard/Makefile.am
@@ -5,7 +5,7 @@ plugin_LTLIBRARIES = \
$(NULL)
uidir = $(pkgdatadir)
-ui_DATA = modmap-dialog.ui
+ui_DATA = modmap-dialog.ui show-layout.ui
libkeyboard_la_SOURCES = \
gsd-keyboard-plugin.h \
diff --git a/plugins/keyboard/gsd-keyboard-xkb.c b/plugins/keyboard/gsd-keyboard-xkb.c
index 987456c..c6fe8aa 100644
--- a/plugins/keyboard/gsd-keyboard-xkb.c
+++ b/plugins/keyboard/gsd-keyboard-xkb.c
@@ -32,14 +32,18 @@
#include <gconf/gconf-client.h>
#include <libgnomekbd/gkbd-status.h>
+#include <libgnomekbd/gkbd-keyboard-drawing.h>
#include <libgnomekbd/gkbd-desktop-config.h>
#include <libgnomekbd/gkbd-keyboard-config.h>
+#include <libgnomekbd/gkbd-util.h>
#include "gsd-xmodmap.h"
#include "gsd-keyboard-xkb.h"
#include "delayed-dialog.h"
#include "gnome-settings-profile.h"
+#define GTK_RESPONSE_PRINT 2
+
static XklEngine *xkl_engine;
static XklConfigRegistry *xkl_registry = NULL;
@@ -62,7 +66,9 @@ static const char KNOWN_FILES_KEY[] =
static const char *gdm_keyboard_layout = NULL;
-static GkbdStatus *icon = NULL;
+static GtkStatusIcon *icon = NULL;
+
+static GHashTable *preview_dialogs = NULL;
#define noGSDKX
@@ -141,24 +147,300 @@ apply_desktop_settings (void)
}
static void
+popup_menu_launch_capplet ()
+{
+ GError *error = NULL;
+
+ gdk_spawn_command_line_on_screen (gdk_screen_get_default (),
+ "gnome-keyboard-properties",
+ &error);
+
+ if (error != NULL) {
+ g_warning
+ ("Could not execute keyboard properties capplet: [%s]\n",
+ error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+show_layout_response (GtkWidget * dialog, gint resp)
+{
+ GdkRectangle rect;
+ GtkWidget *kbdraw;
+ const gchar *groupName;
+
+ switch (resp) {
+ case GTK_RESPONSE_HELP:
+ gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (dialog)),
+ "ghelp:gswitchit?layout-view",
+ gtk_get_current_event_time (), NULL);
+ return;
+ case GTK_RESPONSE_CLOSE:
+ gtk_window_get_position (GTK_WINDOW (dialog), &rect.x,
+ &rect.y);
+ gtk_window_get_size (GTK_WINDOW (dialog), &rect.width,
+ &rect.height);
+ gkbd_preview_save_position (&rect);
+ gtk_widget_destroy (dialog);
+ break;
+ case GTK_RESPONSE_PRINT:
+ kbdraw =
+ GTK_WIDGET (g_object_get_data
+ (G_OBJECT (dialog), "kbdraw"));
+ groupName =
+ (const gchar *) g_object_get_data (G_OBJECT (dialog),
+ "groupName");
+ gkbd_keyboard_drawing_print (GKBD_KEYBOARD_DRAWING
+ (kbdraw), GTK_WINDOW (dialog),
+ groupName ? groupName :
+ _("Unknown"));
+ }
+}
+
+static void
+show_layout_destroy (GtkWidget * dialog, gint group)
+{
+ GtkBuilder *builder =
+ GTK_BUILDER (g_object_get_data
+ (G_OBJECT (dialog), "builderData"));
+ g_object_unref (G_OBJECT (builder));
+ g_hash_table_remove (preview_dialogs, GINT_TO_POINTER (group));
+}
+
+static void
+popup_menu_show_layout ()
+{
+ static GkbdKeyboardDrawingGroupLevel groupsLevels[] = { {
+ 0, 1}, {
+ 0,
+ 3},
+ {
+ 0, 0}, {
+ 0, 2}
+ };
+ static GkbdKeyboardDrawingGroupLevel *pGroupsLevels[] = {
+ groupsLevels, groupsLevels + 1, groupsLevels + 2,
+ groupsLevels + 3
+ };
+
+ GtkBuilder *builder;
+ GtkWidget *dialog, *kbdraw;
+ XkbComponentNamesRec component_names;
+ XklConfigRec *xkl_data;
+ GdkRectangle *rect;
+ GError *error = NULL;
+
+ XklEngine *engine = xkl_engine_get_instance (GDK_DISPLAY ());
+ XklState *xkl_state = xkl_engine_get_current_state (engine);
+ gchar **group_names = gkbd_status_get_group_names ();
+ gpointer p = g_hash_table_lookup (preview_dialogs,
+ GINT_TO_POINTER
+ (xkl_state->group));
+ if (p != NULL) {
+ /* existing window */
+ gtk_window_present (GTK_WINDOW (p));
+ return;
+ }
+
+ builder = gtk_builder_new ();
+ gtk_builder_add_from_file (builder, DATADIR "/show-layout.ui",
+ &error);
+
+ if (error) {
+ g_error ("building ui from %s failed: %s",
+ DATADIR "/show-layout.ui", error->message);
+ g_clear_error (&error);
+ }
+
+
+ dialog =
+ GTK_WIDGET (gtk_builder_get_object
+ (builder, "gswitchit_layout_view"));
+ kbdraw = gkbd_keyboard_drawing_new ();
+
+ if (xkl_state->group >= 0 &&
+ xkl_state->group < g_strv_length (group_names)) {
+ char title[128] = "";
+ snprintf (title, sizeof (title),
+ _("Keyboard Layout \"%s\""),
+ group_names[xkl_state->group]);
+ gtk_window_set_title (GTK_WINDOW (dialog), title);
+ g_object_set_data_full (G_OBJECT (dialog), "group_name",
+ g_strdup (group_names
+ [xkl_state->group]),
+ g_free);
+ }
+
+ gkbd_keyboard_drawing_set_groups_levels (GKBD_KEYBOARD_DRAWING
+ (kbdraw), pGroupsLevels);
+
+ xkl_data = xkl_config_rec_new ();
+ if (xkl_config_rec_get_from_server (xkl_data, engine)) {
+ int num_layouts = g_strv_length (xkl_data->layouts);
+ int num_variants = g_strv_length (xkl_data->variants);
+ if (xkl_state->group >= 0 &&
+ xkl_state->group < num_layouts &&
+ xkl_state->group < num_variants) {
+ char *l =
+ g_strdup (xkl_data->layouts[xkl_state->group]);
+ char *v =
+ g_strdup (xkl_data->
+ variants[xkl_state->group]);
+ char **p;
+ int i;
+
+ if ((p = xkl_data->layouts) != NULL)
+ for (i = num_layouts; --i >= 0;)
+ g_free (*p++);
+
+ if ((p = xkl_data->variants) != NULL)
+ for (i = num_variants; --i >= 0;)
+ g_free (*p++);
+
+ xkl_data->layouts =
+ g_realloc (xkl_data->layouts,
+ sizeof (char *) * 2);
+ xkl_data->variants =
+ g_realloc (xkl_data->variants,
+ sizeof (char *) * 2);
+ xkl_data->layouts[0] = l;
+ xkl_data->variants[0] = v;
+ xkl_data->layouts[1] = xkl_data->variants[1] =
+ NULL;
+ }
+
+ if (xkl_xkb_config_native_prepare
+ (engine, xkl_data, &component_names)) {
+ gkbd_keyboard_drawing_set_keyboard
+ (GKBD_KEYBOARD_DRAWING (kbdraw),
+ &component_names);
+ xkl_xkb_config_native_cleanup (engine,
+ &component_names);
+ }
+ }
+ g_object_unref (G_OBJECT (xkl_data));
+
+ g_object_set_data (G_OBJECT (dialog), "builderData", builder);
+ g_signal_connect (GTK_OBJECT (dialog),
+ "destroy", G_CALLBACK (show_layout_destroy),
+ GINT_TO_POINTER (xkl_state->group));
+ g_signal_connect (G_OBJECT (dialog), "response",
+ G_CALLBACK (show_layout_response), NULL);
+
+ rect = gkbd_preview_load_position ();
+ if (rect != NULL) {
+ gtk_window_move (GTK_WINDOW (dialog), rect->x, rect->y);
+ gtk_window_resize (GTK_WINDOW (dialog), rect->width,
+ rect->height);
+ g_free (rect);
+ } else
+ gtk_window_resize (GTK_WINDOW (dialog), 700, 400);
+
+ gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+
+ gtk_container_add (GTK_CONTAINER
+ (gtk_builder_get_object
+ (builder, "preview_vbox")), kbdraw);
+
+ g_object_set_data (G_OBJECT (dialog), "kbdraw", kbdraw);
+
+ g_hash_table_insert (preview_dialogs,
+ GINT_TO_POINTER (xkl_state->group), dialog);
+
+ gtk_widget_show_all (GTK_WIDGET (dialog));
+}
+
+static void
+popup_menu_set_group (GtkMenuItem * item, gpointer param)
+{
+ gint group_number = GPOINTER_TO_INT(param);
+ XklEngine *engine = gkbd_status_get_xkl_engine ();
+ XklState st;
+ Window cur;
+
+ st.group = group_number;
+ xkl_engine_allow_one_switch_to_secondary_group (engine);
+ cur = xkl_engine_get_current_window (engine);
+ if (cur != (Window) NULL) {
+ xkl_debug (150, "Enforcing the state %d for window %lx\n",
+ st.group, cur);
+ xkl_engine_save_state (engine,
+ xkl_engine_get_current_window
+ (engine), &st);
+/* XSetInputFocus( GDK_DISPLAY(), cur, RevertToNone, CurrentTime );*/
+ } else {
+ xkl_debug (150,
+ "??? Enforcing the state %d for unknown window\n",
+ st.group);
+ /* strange situation - bad things can happen */
+ }
+ xkl_engine_lock_group (engine, st.group);
+}
+
+static void
+status_icon_popup_menu_cb (GtkStatusIcon * icon, guint button, guint time)
+{
+ GtkMenu *popup_menu = GTK_MENU (gtk_menu_new ());
+ GtkMenu *groups_menu = GTK_MENU (gtk_menu_new ());
+ int i = 0;
+ gchar **current_name = gkbd_status_get_group_names ();
+
+ GtkWidget *item = gtk_menu_item_new_with_mnemonic (_("_Groups"));
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item),
+ GTK_WIDGET (groups_menu));
+
+ item =
+ gtk_menu_item_new_with_mnemonic (_("Keyboard _Preferences"));
+ gtk_widget_show (item);
+ g_signal_connect (item, "activate", popup_menu_launch_capplet,
+ NULL);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item);
+
+ item = gtk_menu_item_new_with_mnemonic (_("Show Current _Layout"));
+ gtk_widget_show (item);
+ g_signal_connect (item, "activate", popup_menu_show_layout, NULL);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item);
+
+ for (i = 0; *current_name; i++, current_name++) {
+ item = gtk_menu_item_new_with_label (*current_name);
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (groups_menu), item);
+ g_signal_connect (item, "activate", G_CALLBACK(popup_menu_set_group), GINT_TO_POINTER(i));
+ }
+
+ gtk_menu_popup (popup_menu, NULL, NULL,
+ gtk_status_icon_position_menu,
+ (gpointer) icon, button, time);
+}
+
+static void
show_hide_icon ()
{
- if (g_slist_length(current_kbd_config.layouts_variants) > 1) {
+ if (g_slist_length (current_kbd_config.layouts_variants) > 1) {
if (icon == NULL) {
xkl_debug (150, "Creating new icon\n");
- icon = gkbd_status_new();
+ icon = gkbd_status_new ();
+ g_signal_connect (icon, "popup-menu",
+ G_CALLBACK
+ (status_icon_popup_menu_cb),
+ NULL);
+
}
} else {
if (icon != NULL) {
xkl_debug (150, "Destroying icon\n");
- g_object_unref(icon);
+ g_object_unref (icon);
icon = NULL;
}
}
}
static gboolean
-try_activating_xkb_config_if_new (GkbdKeyboardConfig *current_sys_kbd_config)
+try_activating_xkb_config_if_new (GkbdKeyboardConfig *
+ current_sys_kbd_config)
{
/* Activate - only if different! */
if (!gkbd_keyboard_config_equals
@@ -170,7 +452,7 @@ try_activating_xkb_config_if_new (GkbdKeyboardConfig *current_sys_kbd_config)
return TRUE;
}
} else {
- return FALSE;
+ return FALSE;
}
}
return TRUE;
@@ -188,7 +470,8 @@ filter_xkb_config (void)
xkl_debug (100, "Filtering configuration against the registry\n");
if (!xkl_registry) {
- xkl_registry = xkl_config_registry_get_instance (xkl_engine);
+ xkl_registry =
+ xkl_config_registry_get_instance (xkl_engine);
/* load all materials, unconditionally! */
if (!xkl_config_registry_load (xkl_registry, TRUE)) {
g_object_unref (xkl_registry);
@@ -200,27 +483,41 @@ filter_xkb_config (void)
item = xkl_config_item_new ();
while (lv) {
xkl_debug (100, "Checking [%s]\n", lv->data);
- if (gkbd_keyboard_config_split_items(lv->data, &lname, &vname)) {
- g_snprintf (item->name, sizeof (item->name), "%s", lname);
- if (!xkl_config_registry_find_layout (xkl_registry, item)) {
- xkl_debug (100, "Bad layout [%s]\n", lname);
+ if (gkbd_keyboard_config_split_items
+ (lv->data, &lname, &vname)) {
+ g_snprintf (item->name, sizeof (item->name), "%s",
+ lname);
+ if (!xkl_config_registry_find_layout
+ (xkl_registry, item)) {
+ xkl_debug (100, "Bad layout [%s]\n",
+ lname);
filtered = lv;
lv = lv->next;
g_free (filtered->data);
- current_kbd_config.layouts_variants = g_slist_delete_link (current_kbd_config.layouts_variants,
- filtered);
+ current_kbd_config.layouts_variants =
+ g_slist_delete_link
+ (current_kbd_config.layouts_variants,
+ filtered);
any_change = TRUE;
continue;
}
if (vname) {
- g_snprintf (item->name, sizeof (item->name), "%s", vname);
- if (!xkl_config_registry_find_variant (xkl_registry, lname, item)) {
- xkl_debug(100, "Bad variant [%s(%s)]\n", lname, vname);
+ g_snprintf (item->name,
+ sizeof (item->name), "%s",
+ vname);
+ if (!xkl_config_registry_find_variant
+ (xkl_registry, lname, item)) {
+ xkl_debug (100,
+ "Bad variant [%s(%s)]\n",
+ lname, vname);
filtered = lv;
lv = lv->next;
g_free (filtered->data);
- current_kbd_config.layouts_variants = g_slist_delete_link (current_kbd_config.layouts_variants,
- filtered);
+ current_kbd_config.layouts_variants
+ =
+ g_slist_delete_link
+ (current_kbd_config.layouts_variants,
+ filtered);
any_change = TRUE;
continue;
}
@@ -228,7 +525,7 @@ filter_xkb_config (void)
}
lv = lv->next;
}
- g_object_unref(item);
+ g_object_unref (item);
return any_change;
}
@@ -266,7 +563,7 @@ apply_xkb_settings (void)
if (gdm_layout != NULL) {
GSList *layouts;
GSList *found_node;
- int max_groups;
+ int max_groups;
max_groups = xkl_engine_get_max_num_groups (xkl_engine);
layouts = gconf_client_get_list (conf_client,
@@ -279,21 +576,27 @@ apply_xkb_settings (void)
* prevents the list from becoming full if the user has a habit
* of selecting many different keyboard layouts in GDM. */
- found_node = g_slist_find_custom (layouts, gdm_layout, (GCompareFunc)g_strcmp0);
+ found_node =
+ g_slist_find_custom (layouts, gdm_layout,
+ (GCompareFunc) g_strcmp0);
if (!found_node) {
/* Insert at the last valid place, or at the end of
* list, whichever comes first */
- layouts = g_slist_insert (layouts, g_strdup (gdm_layout), max_groups - 1);
+ layouts =
+ g_slist_insert (layouts, g_strdup (gdm_layout),
+ max_groups - 1);
if (g_slist_length (layouts) > max_groups) {
GSList *last;
GSList *free_layouts;
- last = g_slist_nth (layouts, max_groups - 1);
+ last =
+ g_slist_nth (layouts, max_groups - 1);
free_layouts = last->next;
last->next = NULL;
- g_slist_foreach (free_layouts, (GFunc) g_free, NULL);
+ g_slist_foreach (free_layouts,
+ (GFunc) g_free, NULL);
g_slist_free (free_layouts);
}
@@ -318,12 +621,15 @@ apply_xkb_settings (void)
if (!try_activating_xkb_config_if_new (¤t_sys_kbd_config)) {
if (filter_xkb_config ()) {
- if (!try_activating_xkb_config_if_new (¤t_sys_kbd_config)) {
- g_warning ("Could not activate the filtered XKB configuration");
+ if (!try_activating_xkb_config_if_new
+ (¤t_sys_kbd_config)) {
+ g_warning
+ ("Could not activate the filtered XKB configuration");
activation_error ();
}
} else {
- g_warning ("Could not activate the XKB configuration");
+ g_warning
+ ("Could not activate the XKB configuration");
activation_error ();
}
} else
@@ -546,6 +852,7 @@ gsd_keyboard_xkb_init (GConfClient * client)
apply_xkb_settings ();
gnome_settings_profile_end ("apply_xkb_settings");
}
+ preview_dialogs = g_hash_table_new (g_direct_hash, g_direct_equal);
gnome_settings_profile_end (NULL);
}
@@ -557,13 +864,14 @@ gsd_keyboard_xkb_shutdown (void)
pa_callback = NULL;
pa_callback_user_data = NULL;
+ g_hash_table_destroy (preview_dialogs);
+
if (!inited_ok)
return;
xkl_engine_stop_listen (xkl_engine);
- gdk_window_remove_filter (NULL,
- (GdkFilterFunc)
+ gdk_window_remove_filter (NULL, (GdkFilterFunc)
gsd_keyboard_xkb_evt_filter, NULL);
client = gconf_client_get_default ();
diff --git a/plugins/keyboard/show-layout.ui b/plugins/keyboard/show-layout.ui
new file mode 100644
index 0000000..026ba63
--- /dev/null
+++ b/plugins/keyboard/show-layout.ui
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<!--*- mode: xml -*-->
+<interface>
+ <object class="GtkDialog" id="gswitchit_layout_view">
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Keyboard Layout</property>
+ <property name="resizable">False</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkVBox" id="preview_vbox">
+ <property name="visible">True</property>
+ <property name="border_width">5</property>
+ <property name="spacing">18</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+ <child>
+ <object class="GtkButton" id="btnPrint">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label">gtk-print</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="btnHelp">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="label">gtk-help</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="btnClose">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="label">gtk-close</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="2">btnPrint</action-widget>
+ <action-widget response="-11">btnHelp</action-widget>
+ <action-widget response="-7">btnClose</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 7d281b3..55dd2da 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -26,6 +26,7 @@ plugins/keybindings/gsd-keybindings-manager.c
[type: gettext/ini]plugins/keybindings/keybindings.gnome-settings-plugin.in
[type: gettext/ini]plugins/keyboard/keyboard.gnome-settings-plugin.in
[type: gettext/glade]plugins/keyboard/modmap-dialog.ui
+[type: gettext/glade]plugins/keyboard/show-layout.ui
plugins/media-keys/gsd-media-keys-manager.c
plugins/media-keys/cut-n-paste/gvc-mixer-control.c
[type: gettext/ini]plugins/media-keys/media-keys.gnome-settings-plugin.in
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]