[gnome-control-center] keyboard: Add common XKB options to the Typing shortcuts section
- From: Rui Matos <rtcm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center] keyboard: Add common XKB options to the Typing shortcuts section
- Date: Mon, 20 Aug 2012 16:57:57 +0000 (UTC)
commit 978ab40f3eb6e4ec2a632941cd8f879919aa2e02
Author: Rui Matos <tiagomatos gmail com>
Date: Tue Jul 31 18:27:17 2012 +0200
keyboard: Add common XKB options to the Typing shortcuts section
Both the compose key and the 3rd level chooser are common and useful
enough to expose in the control center.
Since these shortcuts are a small pre-defined set of only modifier
keys we present them in combo cell renderers.
https://bugzilla.gnome.org/show_bug.cgi?id=682069
configure.ac | 8 +-
panels/keyboard/Makefile.am | 2 +
panels/keyboard/cc-keyboard-option.c | 449 ++++++++++++++++++++++++++++++++++
panels/keyboard/cc-keyboard-option.h | 48 ++++
panels/keyboard/keyboard-shortcuts.c | 291 ++++++++++++++++++-----
5 files changed, 736 insertions(+), 62 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 80b70b9..0463769 100644
--- a/configure.ac
+++ b/configure.ac
@@ -103,8 +103,8 @@ POLKIT_REQUIRED_VERSION=0.103
GSD_REQUIRED_VERSION=3.5.2
NETWORK_MANAGER_REQUIRED_VERSION=0.8.992
LIBNOTIFY_REQUIRED_VERSION=0.7.3
-GNOME_DESKTOP_REQUIRED_VERSION=3.5.3
-SCHEMAS_REQUIRED_VERSION=3.5.3
+GNOME_DESKTOP_REQUIRED_VERSION=3.5.6
+SCHEMAS_REQUIRED_VERSION=3.5.5
LIBWACOM_REQUIRED_VERSION=0.5
CLUTTER_REQUIRED_VERSION=1.11.3
GOA_REQUIRED_VERSION=3.5.90
@@ -130,7 +130,9 @@ PKG_CHECK_MODULES(DATETIME_PANEL, $COMMON_MODULES
PKG_CHECK_MODULES(DISPLAY_PANEL, $COMMON_MODULES gnome-desktop-3.0 >= 3.1.0)
PKG_CHECK_MODULES(INFO_PANEL, $COMMON_MODULES libgtop-2.0
polkit-gobject-1 >= $POLKIT_REQUIRED_VERSION)
-PKG_CHECK_MODULES(KEYBOARD_PANEL, $COMMON_MODULES x11)
+PKG_CHECK_MODULES(KEYBOARD_PANEL, $COMMON_MODULES
+ gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION
+ x11)
PKG_CHECK_MODULES(MEDIA_PANEL, $COMMON_MODULES)
PKG_CHECK_MODULES(MOUSE_PANEL, $COMMON_MODULES xi >= 1.2
gnome-settings-daemon >= $GSD_REQUIRED_VERSION x11)
diff --git a/panels/keyboard/Makefile.am b/panels/keyboard/Makefile.am
index 9623403..e3d7fc6 100644
--- a/panels/keyboard/Makefile.am
+++ b/panels/keyboard/Makefile.am
@@ -10,6 +10,8 @@ libkeyboard_la_SOURCES = \
cc-keyboard-panel.h \
cc-keyboard-item.c \
cc-keyboard-item.h \
+ cc-keyboard-option.c \
+ cc-keyboard-option.h \
wm-common.c \
wm-common.h \
keyboard-general.c \
diff --git a/panels/keyboard/cc-keyboard-option.c b/panels/keyboard/cc-keyboard-option.c
new file mode 100644
index 0000000..229ceae
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-option.c
@@ -0,0 +1,449 @@
+/*
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Written by: Rui Matos <rmatos redhat com>
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <glib/gi18n.h>
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-xkb-info.h>
+
+#include "cc-keyboard-option.h"
+
+#define CC_TYPE_KEYBOARD_OPTION (cc_keyboard_option_get_type ())
+#define CC_KEYBOARD_OPTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CC_TYPE_KEYBOARD_OPTION, CcKeyboardOption))
+#define CC_KEYBOARD_OPTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CC_TYPE_KEYBOARD_OPTION, CcKeyboardOptionClass))
+#define CC_IS_KEYBOARD_OPTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CC_TYPE_KEYBOARD_OPTION))
+#define CC_IS_KEYBOARD_OPTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CC_TYPE_KEYBOARD_OPTION))
+#define CC_KEYBOARD_OPTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CC_TYPE_KEYBOARD_OPTION, CcKeyboardOptionClass))
+
+#define INPUT_SOURCES_SCHEMA "org.gnome.desktop.input-sources"
+#define XKB_OPTIONS_KEY "xkb-options"
+
+#define XKB_OPTION_GROUP_LVL3 "lv3"
+#define XKB_OPTION_GROUP_COMP "Compose key"
+
+enum
+{
+ PROP_0,
+ PROP_GROUP,
+ PROP_DESCRIPTION
+};
+
+enum
+{
+ CHANGED_SIGNAL,
+ LAST_SIGNAL
+};
+
+struct _CcKeyboardOption
+{
+ GObject parent_object;
+
+ gchar *group;
+ gchar *description;
+ gchar *current_value;
+ GtkListStore *store;
+
+ const gchar * const *whitelist;
+};
+
+typedef struct _CcKeyboardOptionClass CcKeyboardOptionClass;
+struct _CcKeyboardOptionClass
+{
+ GObjectClass parent_class;
+};
+
+static guint keyboard_option_signals[LAST_SIGNAL] = { 0 };
+
+static GnomeXkbInfo *xkb_info = NULL;
+static GSettings *input_sources_settings = NULL;
+static gchar **current_xkb_options = NULL;
+
+static const gchar *xkb_option_lvl3_whitelist[] = {
+ "lv3:switch",
+ "lv3:menu_switch",
+ "lv3:rwin_switch",
+ "lv3:lalt_switch",
+ "lv3:ralt_switch",
+ "lv3:caps_switch",
+ NULL
+};
+
+static const gchar *xkb_option_comp_whitelist[] = {
+ "compose:ralt",
+ "compose:rwin",
+ "compose:menu",
+ "compose:lctrl",
+ "compose:rctrl",
+ "compose:caps",
+ NULL
+};
+
+static GList *objects_list = NULL;
+
+GType cc_keyboard_option_get_type (void);
+
+G_DEFINE_TYPE (CcKeyboardOption, cc_keyboard_option, G_TYPE_OBJECT);
+
+static gboolean
+strv_contains (const gchar * const *strv,
+ const gchar *str)
+{
+ const gchar * const *p = strv;
+ for (p = strv; *p; p++)
+ if (g_strcmp0 (*p, str) == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+reload_setting (CcKeyboardOption *self)
+{
+ gchar **iter;
+
+ for (iter = current_xkb_options; *iter; ++iter)
+ if (strv_contains (self->whitelist, *iter))
+ {
+ if (g_strcmp0 (self->current_value, *iter) != 0)
+ {
+ g_free (self->current_value);
+ self->current_value = g_strdup (*iter);
+ g_signal_emit (self, keyboard_option_signals[CHANGED_SIGNAL], 0);
+ }
+ break;
+ }
+
+ if (*iter == NULL && self->current_value != NULL)
+ {
+ g_clear_pointer (&self->current_value, g_free);
+ g_signal_emit (self, keyboard_option_signals[CHANGED_SIGNAL], 0);
+ }
+}
+
+static void
+xkb_options_changed (GSettings *settings,
+ gchar *key,
+ gpointer data)
+{
+ GList *l;
+
+ g_strfreev (current_xkb_options);
+ current_xkb_options = g_settings_get_strv (settings, key);
+
+ for (l = objects_list; l; l = l->next)
+ reload_setting (CC_KEYBOARD_OPTION (l->data));
+}
+
+static void
+cc_keyboard_option_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcKeyboardOption *self;
+
+ self = CC_KEYBOARD_OPTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_GROUP:
+ g_value_set_string (value, self->group);
+ break;
+ case PROP_DESCRIPTION:
+ g_value_set_string (value, self->description);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_keyboard_option_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcKeyboardOption *self;
+
+ self = CC_KEYBOARD_OPTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_GROUP:
+ self->group = g_value_dup_string (value);
+ break;
+ case PROP_DESCRIPTION:
+ self->description = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_keyboard_option_init (CcKeyboardOption *self)
+{
+}
+
+static void
+cc_keyboard_option_finalize (GObject *object)
+{
+ CcKeyboardOption *self = CC_KEYBOARD_OPTION (object);
+
+ g_clear_pointer (&self->group, g_free);
+ g_clear_pointer (&self->description, g_free);
+ g_clear_pointer (&self->current_value, g_free);
+ g_clear_object (&self->store);
+
+ G_OBJECT_CLASS (cc_keyboard_option_parent_class)->finalize (object);
+}
+
+static void
+cc_keyboard_option_constructed (GObject *object)
+{
+ GtkTreeIter iter;
+ GList *options, *l;
+ gchar *option_id;
+ CcKeyboardOption *self = CC_KEYBOARD_OPTION (object);
+
+ G_OBJECT_CLASS (cc_keyboard_option_parent_class)->constructed (object);
+
+ if (g_str_equal (self->group, XKB_OPTION_GROUP_LVL3))
+ self->whitelist = xkb_option_lvl3_whitelist;
+ else if (g_str_equal (self->group, XKB_OPTION_GROUP_COMP))
+ self->whitelist = xkb_option_comp_whitelist;
+ else
+ g_assert_not_reached ();
+
+ self->store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+ gtk_list_store_append (self->store, &iter);
+ gtk_list_store_set (self->store, &iter,
+ XKB_OPTION_DESCRIPTION_COLUMN, _("Disabled"),
+ XKB_OPTION_ID_COLUMN, NULL,
+ -1);
+ options = gnome_xkb_info_get_options_for_group (xkb_info, self->group);
+ for (l = options; l; l = l->next)
+ {
+ option_id = l->data;
+ if (strv_contains (self->whitelist, option_id))
+ {
+ gtk_list_store_append (self->store, &iter);
+ gtk_list_store_set (self->store, &iter,
+ XKB_OPTION_DESCRIPTION_COLUMN,
+ gnome_xkb_info_description_for_option (xkb_info, self->group, option_id),
+ XKB_OPTION_ID_COLUMN,
+ option_id,
+ -1);
+ }
+ }
+ g_list_free (options);
+
+ reload_setting (self);
+}
+
+static void
+cc_keyboard_option_class_init (CcKeyboardOptionClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->get_property = cc_keyboard_option_get_property;
+ gobject_class->set_property = cc_keyboard_option_set_property;
+ gobject_class->finalize = cc_keyboard_option_finalize;
+ gobject_class->constructed = cc_keyboard_option_constructed;
+
+ g_object_class_install_property (gobject_class,
+ PROP_GROUP,
+ g_param_spec_string ("group",
+ "group",
+ "xkb option group identifier",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
+ g_object_class_install_property (gobject_class,
+ PROP_DESCRIPTION,
+ g_param_spec_string ("description",
+ "description",
+ "translated option description",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
+
+ keyboard_option_signals[CHANGED_SIGNAL] = g_signal_new ("changed",
+ CC_TYPE_KEYBOARD_OPTION,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 0);
+}
+
+GList *
+cc_keyboard_option_get_all (void)
+{
+ if (objects_list)
+ return objects_list;
+
+ xkb_info = gnome_xkb_info_new ();
+
+ input_sources_settings = g_settings_new (INPUT_SOURCES_SCHEMA);
+
+ g_signal_connect (input_sources_settings, "changed::" XKB_OPTIONS_KEY,
+ G_CALLBACK (xkb_options_changed), NULL);
+
+ xkb_options_changed (input_sources_settings, XKB_OPTIONS_KEY, NULL);
+
+ objects_list = g_list_prepend (objects_list,
+ g_object_new (CC_TYPE_KEYBOARD_OPTION,
+ "group", XKB_OPTION_GROUP_LVL3,
+ "description", _("Alternative Characters Key"),
+ NULL));
+ objects_list = g_list_prepend (objects_list,
+ g_object_new (CC_TYPE_KEYBOARD_OPTION,
+ "group", XKB_OPTION_GROUP_COMP,
+ "description", _("Compose Key"),
+ NULL));
+ return objects_list;
+}
+
+const gchar *
+cc_keyboard_option_get_description (CcKeyboardOption *self)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_OPTION (self), NULL);
+
+ return self->description;
+}
+
+GtkListStore *
+cc_keyboard_option_get_store (CcKeyboardOption *self)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_OPTION (self), NULL);
+
+ return self->store;
+}
+
+const gchar *
+cc_keyboard_option_get_current_value_description (CcKeyboardOption *self)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_OPTION (self), NULL);
+
+ if (!self->current_value)
+ return _("Disabled");
+
+ return gnome_xkb_info_description_for_option (xkb_info, self->group, self->current_value);
+}
+
+static void
+remove_value (const gchar *value)
+{
+ gchar **p;
+
+ for (p = current_xkb_options; *p; ++p)
+ if (g_str_equal (*p, value))
+ {
+ g_free (*p);
+ break;
+ }
+
+ for (++p; *p; ++p)
+ *(p - 1) = *p;
+
+ *(p - 1) = NULL;
+}
+
+static void
+add_value (const gchar *value)
+{
+ gchar **new_xkb_options;
+ gchar **a, **b;
+
+ new_xkb_options = g_new0 (gchar *, g_strv_length (current_xkb_options) + 2);
+
+ a = new_xkb_options;
+ for (b = current_xkb_options; *b; ++a, ++b)
+ *a = g_strdup (*b);
+
+ *a = g_strdup (value);
+
+ g_strfreev (current_xkb_options);
+ current_xkb_options = new_xkb_options;
+}
+
+static void
+replace_value (const gchar *old,
+ const gchar *new)
+{
+ gchar **iter;
+
+ if (g_str_equal (old, new))
+ return;
+
+ for (iter = current_xkb_options; *iter; ++iter)
+ if (g_str_equal (*iter, old))
+ {
+ g_free (*iter);
+ *iter = g_strdup (new);
+ break;
+ }
+}
+
+void
+cc_keyboard_option_set_selection (CcKeyboardOption *self,
+ GtkTreeIter *iter)
+{
+ gchar *new_value = NULL;
+
+ g_return_if_fail (CC_IS_KEYBOARD_OPTION (self));
+
+ gtk_tree_model_get (GTK_TREE_MODEL (self->store), iter,
+ XKB_OPTION_ID_COLUMN, &new_value,
+ -1);
+
+ if (!new_value)
+ {
+ if (self->current_value)
+ remove_value (self->current_value);
+ }
+ else
+ {
+ if (self->current_value)
+ replace_value (self->current_value, new_value);
+ else
+ add_value (new_value);
+ }
+
+ g_settings_set_strv (input_sources_settings, XKB_OPTIONS_KEY,
+ (const gchar * const *) current_xkb_options);
+
+ g_free (new_value);
+}
+
+void
+cc_keyboard_option_clear_all (void)
+{
+ GList *l;
+
+ for (l = objects_list; l; l = l->next)
+ g_object_unref (l->data);
+
+ g_clear_pointer (&objects_list, g_list_free);
+ g_clear_pointer (¤t_xkb_options, g_strfreev);
+ g_clear_object (&input_sources_settings);
+ g_clear_object (&xkb_info);
+}
diff --git a/panels/keyboard/cc-keyboard-option.h b/panels/keyboard/cc-keyboard-option.h
new file mode 100644
index 0000000..011481f
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-option.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Written by: Rui Matos <rmatos redhat com>
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __CC_KEYBOARD_OPTION_H__
+#define __CC_KEYBOARD_OPTION_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+enum
+{
+ XKB_OPTION_DESCRIPTION_COLUMN,
+ XKB_OPTION_ID_COLUMN,
+ XKB_OPTION_N_COLUMNS
+};
+
+typedef struct _CcKeyboardOption CcKeyboardOption;
+
+GList * cc_keyboard_option_get_all (void);
+const gchar * cc_keyboard_option_get_description (CcKeyboardOption *self);
+GtkListStore * cc_keyboard_option_get_store (CcKeyboardOption *self);
+const gchar * cc_keyboard_option_get_current_value_description (CcKeyboardOption *self);
+void cc_keyboard_option_set_selection (CcKeyboardOption *self,
+ GtkTreeIter *iter);
+void cc_keyboard_option_clear_all (void);
+
+G_END_DECLS
+
+#endif /* __CC_KEYBOARD_OPTION_H__ */
diff --git a/panels/keyboard/keyboard-shortcuts.c b/panels/keyboard/keyboard-shortcuts.c
index 093c713..8013670 100644
--- a/panels/keyboard/keyboard-shortcuts.c
+++ b/panels/keyboard/keyboard-shortcuts.c
@@ -22,8 +22,10 @@
#include <config.h>
#include <glib/gi18n.h>
+
#include "keyboard-shortcuts.h"
#include "cc-keyboard-item.h"
+#include "cc-keyboard-option.h"
#include "wm-common.h"
#define BINDINGS_SCHEMA "org.gnome.settings-daemon.plugins.media-keys"
@@ -53,10 +55,17 @@ typedef struct
char *name; /* GSettings schema path, or GSettings key name depending on type */
} KeyListEntry;
+typedef enum
+{
+ SHORTCUT_TYPE_KEY_ENTRY,
+ SHORTCUT_TYPE_XKB_OPTION,
+} ShortcutType;
+
enum
{
DETAIL_DESCRIPTION_COLUMN,
DETAIL_KEYENTRY_COLUMN,
+ DETAIL_TYPE_COLUMN,
DETAIL_N_COLUMNS
};
@@ -668,34 +677,53 @@ accel_set_func (GtkTreeViewColumn *tree_column,
GtkTreeIter *iter,
gpointer data)
{
- CcKeyboardItem *item;
+ gpointer entry;
+ ShortcutType type;
gtk_tree_model_get (model, iter,
- DETAIL_KEYENTRY_COLUMN, &item,
+ DETAIL_KEYENTRY_COLUMN, &entry,
+ DETAIL_TYPE_COLUMN, &type,
-1);
- if (item == NULL)
- g_object_set (cell,
- "visible", FALSE,
- NULL);
- else if (! item->editable)
- g_object_set (cell,
- "visible", TRUE,
- "editable", FALSE,
- "accel-key", item->keyval,
- "accel-mods", item->mask,
- "keycode", item->keycode,
- "style", PANGO_STYLE_ITALIC,
- NULL);
- else
- g_object_set (cell,
- "visible", TRUE,
- "editable", TRUE,
- "accel-key", item->keyval,
- "accel-mods", item->mask,
- "keycode", item->keycode,
- "style", PANGO_STYLE_NORMAL,
- NULL);
+ gtk_cell_renderer_set_visible (cell, FALSE);
+
+ if (type == SHORTCUT_TYPE_XKB_OPTION &&
+ GTK_IS_CELL_RENDERER_COMBO (cell))
+ {
+ CcKeyboardOption *option = entry;
+
+ gtk_cell_renderer_set_visible (cell, TRUE);
+ g_object_set (cell,
+ "model", cc_keyboard_option_get_store (option),
+ "text", cc_keyboard_option_get_current_value_description (option),
+ NULL);
+ }
+ else if (type == SHORTCUT_TYPE_KEY_ENTRY &&
+ GTK_IS_CELL_RENDERER_TEXT (cell) &&
+ !GTK_IS_CELL_RENDERER_COMBO (cell) &&
+ entry != NULL)
+ {
+ CcKeyboardItem *item = entry;
+
+ gtk_cell_renderer_set_visible (cell, TRUE);
+
+ if (item->editable)
+ g_object_set (cell,
+ "editable", TRUE,
+ "accel-key", item->keyval,
+ "accel-mods", item->mask,
+ "keycode", item->keycode,
+ "style", PANGO_STYLE_NORMAL,
+ NULL);
+ else
+ g_object_set (cell,
+ "editable", FALSE,
+ "accel-key", item->keyval,
+ "accel-mods", item->mask,
+ "keycode", item->keycode,
+ "style", PANGO_STYLE_ITALIC,
+ NULL);
+ }
}
static void
@@ -705,21 +733,34 @@ description_set_func (GtkTreeViewColumn *tree_column,
GtkTreeIter *iter,
gpointer data)
{
+ gchar *description;
CcKeyboardItem *item;
+ ShortcutType type;
gtk_tree_model_get (model, iter,
+ DETAIL_DESCRIPTION_COLUMN, &description,
DETAIL_KEYENTRY_COLUMN, &item,
+ DETAIL_TYPE_COLUMN, &type,
-1);
- if (item != NULL)
- g_object_set (cell,
- "editable", FALSE,
- "text", item->description != NULL ?
- item->description : _("<Unknown Action>"),
- NULL);
+ if (type == SHORTCUT_TYPE_XKB_OPTION)
+ {
+ g_object_set (cell, "text", description, NULL);
+ }
else
- g_object_set (cell,
- "editable", FALSE, NULL);
+ {
+ if (item != NULL)
+ g_object_set (cell,
+ "editable", FALSE,
+ "text", item->description != NULL ?
+ item->description : _("<Unknown Action>"),
+ NULL);
+ else
+ g_object_set (cell,
+ "editable", FALSE, NULL);
+ }
+
+ g_free (description);
}
static void
@@ -730,12 +771,17 @@ shortcut_selection_changed (GtkTreeSelection *selection, gpointer data)
GtkTreeIter iter;
CcKeyboardItem *item;
gboolean can_remove;
+ ShortcutType type;
can_remove = FALSE;
if (gtk_tree_selection_get_selected (selection, &model, &iter))
{
- gtk_tree_model_get (model, &iter, DETAIL_KEYENTRY_COLUMN, &item, -1);
- if (item && item->command != NULL && item->editable)
+ gtk_tree_model_get (model, &iter,
+ DETAIL_KEYENTRY_COLUMN, &item,
+ DETAIL_TYPE_COLUMN, &type,
+ -1);
+ if (type == SHORTCUT_TYPE_KEY_ENTRY &&
+ item && item->command != NULL && item->editable)
can_remove = TRUE;
}
@@ -743,6 +789,25 @@ shortcut_selection_changed (GtkTreeSelection *selection, gpointer data)
}
static void
+fill_xkb_options_shortcuts (GtkTreeModel *model)
+{
+ GList *l;
+ GtkTreeIter iter;
+
+ for (l = cc_keyboard_option_get_all (); l; l = l->next)
+ {
+ CcKeyboardOption *option = l->data;
+
+ gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+ DETAIL_DESCRIPTION_COLUMN, cc_keyboard_option_get_description (option),
+ DETAIL_KEYENTRY_COLUMN, option,
+ DETAIL_TYPE_COLUMN, SHORTCUT_TYPE_XKB_OPTION,
+ -1);
+ }
+}
+
+static void
section_selection_changed (GtkTreeSelection *selection, gpointer data)
{
GtkTreeIter iter;
@@ -769,7 +834,6 @@ section_selection_changed (GtkTreeSelection *selection, gpointer data)
g_free (description);
return;
}
- g_free (description);
gtk_widget_set_sensitive (WID (builder, "remove-toolbutton"), FALSE);
@@ -787,8 +851,14 @@ section_selection_changed (GtkTreeSelection *selection, gpointer data)
gtk_list_store_set (GTK_LIST_STORE (shortcut_model), &new_row,
DETAIL_DESCRIPTION_COLUMN, item->description,
DETAIL_KEYENTRY_COLUMN, item,
+ DETAIL_TYPE_COLUMN, SHORTCUT_TYPE_KEY_ENTRY,
-1);
}
+
+ if (g_str_equal (description, _("Typing")))
+ fill_xkb_options_shortcuts (shortcut_model);
+
+ g_free (description);
}
}
@@ -907,6 +977,7 @@ start_editing_cb (GtkTreeView *tree_view,
{
GtkTreePath *path;
GtkTreeViewColumn *column;
+ GtkCellRenderer *cell = user_data;
if (event->window != gtk_tree_view_get_bin_window (tree_view))
return FALSE;
@@ -920,32 +991,41 @@ start_editing_cb (GtkTreeView *tree_view,
GtkTreeModel *model;
GtkTreeIter iter;
CcKeyboardItem *item;
+ ShortcutType type;
model = gtk_tree_view_get_model (tree_view);
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_model_get (model, &iter,
DETAIL_KEYENTRY_COLUMN, &item,
+ DETAIL_TYPE_COLUMN, &type,
-1);
+ if (type == SHORTCUT_TYPE_XKB_OPTION)
+ {
+ gtk_tree_path_free (path);
+ return FALSE;
+ }
+
/* if only the accel can be edited on the selected row
* always select the accel column */
if (item->desc_editable &&
column == gtk_tree_view_get_column (tree_view, 0))
{
gtk_widget_grab_focus (GTK_WIDGET (tree_view));
- gtk_tree_view_set_cursor (tree_view, path,
- gtk_tree_view_get_column (tree_view, 0),
+ gtk_tree_view_set_cursor (tree_view,
+ path,
+ column,
FALSE);
update_custom_shortcut (model, &iter);
}
else
{
gtk_widget_grab_focus (GTK_WIDGET (tree_view));
- gtk_tree_view_set_cursor (tree_view,
- path,
- item->desc_editable ? column :
- gtk_tree_view_get_column (tree_view, 1),
- TRUE);
+ gtk_tree_view_set_cursor_on_cell (tree_view,
+ path,
+ gtk_tree_view_get_column (tree_view, 1),
+ cell,
+ TRUE);
}
g_signal_stop_emission_by_name (tree_view, "button_press_event");
gtk_tree_path_free (path);
@@ -954,39 +1034,47 @@ start_editing_cb (GtkTreeView *tree_view,
}
static void
-start_editing_kb_cb (GtkTreeView *treeview,
- GtkTreePath *path,
- GtkTreeViewColumn *column,
- gpointer user_data)
+start_editing_kb_cb (GtkTreeView *treeview,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ gpointer user_data)
{
GtkTreeModel *model;
GtkTreeIter iter;
CcKeyboardItem *item;
+ ShortcutType type;
+ GtkCellRenderer *cell = user_data;
model = gtk_tree_view_get_model (treeview);
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_model_get (model, &iter,
DETAIL_KEYENTRY_COLUMN, &item,
+ DETAIL_TYPE_COLUMN, &type,
-1);
+ if (type == SHORTCUT_TYPE_XKB_OPTION)
+ return;
+
/* if only the accel can be edited on the selected row
* always select the accel column */
if (item->desc_editable &&
column == gtk_tree_view_get_column (treeview, 0))
{
gtk_widget_grab_focus (GTK_WIDGET (treeview));
- gtk_tree_view_set_cursor (treeview, path,
- gtk_tree_view_get_column (treeview, 0),
+ gtk_tree_view_set_cursor (treeview,
+ path,
+ column,
FALSE);
update_custom_shortcut (model, &iter);
}
else
{
gtk_widget_grab_focus (GTK_WIDGET (treeview));
- gtk_tree_view_set_cursor (treeview,
- path,
- gtk_tree_view_get_column (treeview, 1),
- TRUE);
+ gtk_tree_view_set_cursor_on_cell (treeview,
+ path,
+ gtk_tree_view_get_column (treeview, 1),
+ cell,
+ TRUE);
}
}
@@ -1466,6 +1554,74 @@ sections_separator_func (GtkTreeModel *model,
}
static void
+xkb_options_combo_changed (GtkCellRendererCombo *combo,
+ gchar *model_path,
+ GtkTreeIter *model_iter,
+ gpointer data)
+{
+ GtkTreeView *shortcut_treeview;
+ GtkTreeModel *shortcut_model;
+ GtkTreeIter shortcut_iter;
+ GtkTreeSelection *selection;
+ CcKeyboardOption *option;
+ ShortcutType type;
+ GtkBuilder *builder = data;
+
+ shortcut_treeview = GTK_TREE_VIEW (gtk_builder_get_object (builder, "shortcut_treeview"));
+ selection = gtk_tree_view_get_selection (shortcut_treeview);
+ if (!gtk_tree_selection_get_selected (selection, &shortcut_model, &shortcut_iter))
+ return;
+
+ gtk_tree_model_get (shortcut_model, &shortcut_iter,
+ DETAIL_KEYENTRY_COLUMN, &option,
+ DETAIL_TYPE_COLUMN, &type,
+ -1);
+
+ if (type != SHORTCUT_TYPE_XKB_OPTION)
+ return;
+
+ cc_keyboard_option_set_selection (option, model_iter);
+}
+
+static gboolean
+poke_xkb_option_row (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer option)
+{
+ gpointer item;
+
+ gtk_tree_model_get (model, iter,
+ DETAIL_KEYENTRY_COLUMN, &item,
+ -1);
+
+ if (item != option)
+ return FALSE;
+
+ gtk_tree_model_row_changed (model, path, iter);
+ return TRUE;
+}
+
+static void
+xkb_option_changed (CcKeyboardOption *option,
+ gpointer data)
+{
+ GtkTreeModel *model = data;
+
+ gtk_tree_model_foreach (model, poke_xkb_option_row, option);
+}
+
+static void
+setup_keyboard_options (GtkListStore *store)
+{
+ GList *l;
+
+ for (l = cc_keyboard_option_get_all (); l; l = l->next)
+ g_signal_connect (l->data, "changed",
+ G_CALLBACK (xkb_option_changed), store);
+}
+
+static void
setup_dialog (CcPanel *panel, GtkBuilder *builder)
{
GtkCellRenderer *renderer;
@@ -1529,11 +1685,6 @@ setup_dialog (CcPanel *panel, GtkBuilder *builder)
binding_settings = g_settings_new (BINDINGS_SCHEMA);
- g_signal_connect (treeview, "button_press_event",
- G_CALLBACK (start_editing_cb), builder);
- g_signal_connect (treeview, "row-activated",
- G_CALLBACK (start_editing_kb_cb), NULL);
-
renderer = gtk_cell_renderer_text_new ();
g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
@@ -1548,10 +1699,14 @@ setup_dialog (CcPanel *panel, GtkBuilder *builder)
"accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
NULL);
+ g_signal_connect (treeview, "button_press_event",
+ G_CALLBACK (start_editing_cb), renderer);
+ g_signal_connect (treeview, "row-activated",
+ G_CALLBACK (start_editing_kb_cb), renderer);
+
g_signal_connect (renderer, "accel_edited",
G_CALLBACK (accel_edited_callback),
treeview);
-
g_signal_connect (renderer, "accel_cleared",
G_CALLBACK (accel_cleared_callback),
treeview);
@@ -1561,12 +1716,28 @@ setup_dialog (CcPanel *panel, GtkBuilder *builder)
gtk_tree_view_column_set_resizable (column, FALSE);
gtk_tree_view_column_set_expand (column, FALSE);
+ renderer = (GtkCellRenderer *) g_object_new (GTK_TYPE_CELL_RENDERER_COMBO,
+ "has-entry", FALSE,
+ "text-column", XKB_OPTION_DESCRIPTION_COLUMN,
+ "editable", TRUE,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ "width-chars", 25,
+ NULL);
+ g_signal_connect (renderer, "changed",
+ G_CALLBACK (xkb_options_combo_changed), builder);
+
+ gtk_tree_view_column_pack_end (column, renderer, FALSE);
+
+ gtk_tree_view_column_set_cell_data_func (column, renderer, accel_set_func, NULL, NULL);
+
gtk_tree_view_append_column (treeview, column);
- model = gtk_list_store_new (DETAIL_N_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER);
+ model = gtk_list_store_new (DETAIL_N_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT);
gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (model));
g_object_unref (model);
+ setup_keyboard_options (model);
+
widget = GTK_WIDGET (gtk_builder_get_object (builder, "actions_swindow"));
context = gtk_widget_get_style_context (widget);
gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
@@ -1639,4 +1810,6 @@ keyboard_shortcuts_dispose (CcPanel *panel)
}
g_clear_object (&binding_settings);
+
+ cc_keyboard_option_clear_all ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]