[network-manager-applet] editor: improve navigation in address/route treeview (rh #1201412)
- From: Jiří Klimeš <jklimes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [network-manager-applet] editor: improve navigation in address/route treeview (rh #1201412)
- Date: Wed, 18 Mar 2015 17:21:31 +0000 (UTC)
commit b988a2e1c65c05e4b4ce9ae8b71a78609f7f06b5
Author: Jiří Klimeš <jklimes redhat com>
Date: Tue Mar 17 17:56:41 2015 +0100
editor: improve navigation in address/route treeview (rh #1201412)
The commit makes these changes:
* Shift-Tab allows moving backwards (instead of messing up the cells)
* Up arrow key moves backwards as well
* Pressing Enter key in the last cell closes the row without cycling to
the first column
https://bugzilla.redhat.com/show_bug.cgi?id=1201412
src/connection-editor/ip4-routes-dialog.c | 60 ++++++++++++++++++----------
src/connection-editor/ip6-routes-dialog.c | 59 ++++++++++++++++++---------
src/connection-editor/page-ip4.c | 61 +++++++++++++++++++---------
src/connection-editor/page-ip6.c | 61 +++++++++++++++++++---------
src/utils/utils.c | 17 ++++++++
src/utils/utils.h | 2 +
6 files changed, 179 insertions(+), 81 deletions(-)
---
diff --git a/src/connection-editor/ip4-routes-dialog.c b/src/connection-editor/ip4-routes-dialog.c
index 1d1f271..42e3a6a 100644
--- a/src/connection-editor/ip4-routes-dialog.c
+++ b/src/connection-editor/ip4-routes-dialog.c
@@ -328,6 +328,9 @@ cell_editing_canceled (GtkCellRenderer *renderer, gpointer user_data)
validate (GTK_WIDGET (gtk_builder_get_object (builder, "ip4_routes_dialog")));
}
+#define DO_NOT_CYCLE_TAG "do-not-cycle"
+#define DIRECTION_TAG "direction"
+
static void
cell_edited (GtkCellRendererText *cell,
const gchar *path_string,
@@ -342,6 +345,8 @@ cell_edited (GtkCellRendererText *cell,
guint32 column;
GtkTreeViewColumn *next_col;
GtkCellRenderer *next_cell;
+ gboolean can_cycle;
+ int direction, tmp;
/* Free auxiliary stuff */
g_free (last_edited);
@@ -358,12 +363,22 @@ cell_edited (GtkCellRendererText *cell,
gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path);
gtk_list_store_set (store, &iter, column, new_text, -1);
- /* Move focus to the next column */
- column = (column >= COL_LAST) ? 0 : column + 1;
+ /* Move focus to the next/previous column */
+ can_cycle = g_object_get_data (G_OBJECT (cell), DO_NOT_CYCLE_TAG) == NULL;
+ direction = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), DIRECTION_TAG));
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, NULL);
+ g_object_set_data (G_OBJECT (cell), DO_NOT_CYCLE_TAG, NULL);
+ if (direction == 0) /* Move forward by default */
+ direction = 1;
+
+ tmp = column + direction;
+ if (can_cycle)
+ column = tmp < 0 ? COL_LAST : tmp > COL_LAST ? 0 : tmp;
+ else
+ column = tmp;
next_col = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), column);
dialog = GTK_WIDGET (gtk_builder_get_object (builder, "ip4_routes_dialog"));
next_cell = g_slist_nth_data (g_object_get_data (G_OBJECT (dialog), "renderers"), column);
-
gtk_tree_view_set_cursor_on_cell (GTK_TREE_VIEW (widget), path, next_col, next_cell, TRUE);
gtk_tree_path_free (path);
@@ -481,12 +496,12 @@ cell_changed_cb (GtkEditable *editable,
}
static gboolean
-key_pressed_cb (GtkWidget *widget,
- GdkEvent *event,
- gpointer user_data)
+key_pressed_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
- GdkKeymapKey *keys = NULL;
- gint n_keys;
+ GdkModifierType modifiers;
+ GtkCellRenderer *cell = (GtkCellRenderer *) user_data;
+
+ modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
/*
* Tab should behave the same way as Enter (cycling on cells).
@@ -496,17 +511,20 @@ key_pressed_cb (GtkWidget *widget,
* But unfortunately, it showed up crash occurred with XIM input (GTK_IM_MODULE=xim).
* https://bugzilla.redhat.com/show_bug.cgi?id=747368
*/
- if (event->type == GDK_KEY_PRESS && event->key.keyval == GDK_KEY_Tab) {
- /* Get hardware keycode for GDK_KEY_Return */
- if (gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), GDK_KEY_Return, &keys,
&n_keys)) {
- /* Change 'Tab' to 'Enter' key */
- event->key.keyval = GDK_KEY_Return;
- event->key.hardware_keycode = keys[0].keycode;
- }
- g_free (keys);
- }
-
- return FALSE;
+ if (event->keyval == GDK_KEY_Tab && modifiers == 0) {
+ /* Tab */
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, GINT_TO_POINTER (1));
+ utils_fake_return_key (event);
+ } else if (event->keyval == GDK_KEY_ISO_Left_Tab && modifiers == GDK_SHIFT_MASK) {
+ /* Shift-Tab */
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, GINT_TO_POINTER (-1));
+ utils_fake_return_key (event);
+ } else if (event->keyval == GDK_KEY_Up)
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, GINT_TO_POINTER (-1));
+ else if (event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_ISO_Enter)
+ g_object_set_data (G_OBJECT (cell), DO_NOT_CYCLE_TAG, GUINT_TO_POINTER (TRUE));
+
+ return FALSE; /* Allow default handler to be called */
}
static void
@@ -544,7 +562,7 @@ ip4_cell_editing_started (GtkCellRenderer *cell,
/* Set up key pressed handler - need to handle Tab key */
g_signal_connect (G_OBJECT (editable), "key-press-event",
(GCallback) key_pressed_cb,
- user_data);
+ cell);
}
static void
@@ -609,7 +627,7 @@ uint_cell_editing_started (GtkCellRenderer *cell,
/* Set up key pressed handler - need to handle Tab key */
g_signal_connect (G_OBJECT (editable), "key-press-event",
(GCallback) key_pressed_cb,
- user_data);
+ cell);
}
static gboolean
diff --git a/src/connection-editor/ip6-routes-dialog.c b/src/connection-editor/ip6-routes-dialog.c
index 1a3242f..3cfdb74 100644
--- a/src/connection-editor/ip6-routes-dialog.c
+++ b/src/connection-editor/ip6-routes-dialog.c
@@ -282,6 +282,9 @@ cell_editing_canceled (GtkCellRenderer *renderer, gpointer user_data)
validate (GTK_WIDGET (gtk_builder_get_object (builder, "ip6_routes_dialog")));
}
+#define DO_NOT_CYCLE_TAG "do-not-cycle"
+#define DIRECTION_TAG "direction"
+
static void
cell_edited (GtkCellRendererText *cell,
const gchar *path_string,
@@ -296,6 +299,8 @@ cell_edited (GtkCellRendererText *cell,
guint32 column;
GtkTreeViewColumn *next_col;
GtkCellRenderer *next_cell;
+ gboolean can_cycle;
+ int direction, tmp;
/* Free auxiliary stuff */
g_free (last_edited);
@@ -312,8 +317,19 @@ cell_edited (GtkCellRendererText *cell,
gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path);
gtk_list_store_set (store, &iter, column, new_text, -1);
- /* Move focus to the next column */
- column = (column >= COL_LAST) ? 0 : column + 1;
+ /* Move focus to the next/previous column */
+ can_cycle = g_object_get_data (G_OBJECT (cell), DO_NOT_CYCLE_TAG) == NULL;
+ direction = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), DIRECTION_TAG));
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, NULL);
+ g_object_set_data (G_OBJECT (cell), DO_NOT_CYCLE_TAG, NULL);
+ if (direction == 0) /* Move forward by default */
+ direction = 1;
+
+ tmp = column + direction;
+ if (can_cycle)
+ column = tmp < 0 ? COL_LAST : tmp > COL_LAST ? 0 : tmp;
+ else
+ column = tmp;
next_col = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), column);
dialog = GTK_WIDGET (gtk_builder_get_object (builder, "ip6_routes_dialog"));
next_cell = g_slist_nth_data (g_object_get_data (G_OBJECT (dialog), "renderers"), column);
@@ -425,12 +441,12 @@ cell_changed_cb (GtkEditable *editable,
}
static gboolean
-key_pressed_cb (GtkWidget *widget,
- GdkEvent *event,
- gpointer user_data)
+key_pressed_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
- GdkKeymapKey *keys = NULL;
- gint n_keys;
+ GdkModifierType modifiers;
+ GtkCellRenderer *cell = (GtkCellRenderer *) user_data;
+
+ modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
/*
* Tab should behave the same way as Enter (cycling on cells).
@@ -440,17 +456,20 @@ key_pressed_cb (GtkWidget *widget,
* But unfortunately, it showed up crash occurred with XIM input (GTK_IM_MODULE=xim).
* https://bugzilla.redhat.com/show_bug.cgi?id=747368
*/
- if (event->type == GDK_KEY_PRESS && event->key.keyval == GDK_KEY_Tab) {
- /* Get hardware keycode for GDK_KEY_Return */
- if (gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), GDK_KEY_Return, &keys,
&n_keys)) {
- /* Change 'Tab' to 'Enter' key */
- event->key.keyval = GDK_KEY_Return;
- event->key.hardware_keycode = keys[0].keycode;
- }
- g_free (keys);
- }
-
- return FALSE;
+ if (event->keyval == GDK_KEY_Tab && modifiers == 0) {
+ /* Tab */
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, GINT_TO_POINTER (1));
+ utils_fake_return_key (event);
+ } else if (event->keyval == GDK_KEY_ISO_Left_Tab && modifiers == GDK_SHIFT_MASK) {
+ /* Shift-Tab */
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, GINT_TO_POINTER (-1));
+ utils_fake_return_key (event);
+ } else if (event->keyval == GDK_KEY_Up)
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, GINT_TO_POINTER (-1));
+ else if (event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_ISO_Enter)
+ g_object_set_data (G_OBJECT (cell), DO_NOT_CYCLE_TAG, GUINT_TO_POINTER (TRUE));
+
+ return FALSE; /* Allow default handler to be called */
}
static void
@@ -488,7 +507,7 @@ ip6_cell_editing_started (GtkCellRenderer *cell,
/* Set up key pressed handler - need to handle Tab key */
g_signal_connect (G_OBJECT (editable), "key-press-event",
(GCallback) key_pressed_cb,
- user_data);
+ cell);
}
static void
@@ -553,7 +572,7 @@ uint_cell_editing_started (GtkCellRenderer *cell,
/* Set up key pressed handler - need to handle Tab key */
g_signal_connect (G_OBJECT (editable), "key-press-event",
(GCallback) key_pressed_cb,
- user_data);
+ cell);
}
static gboolean
diff --git a/src/connection-editor/page-ip4.c b/src/connection-editor/page-ip4.c
index 07d4eac..f2cbb02 100644
--- a/src/connection-editor/page-ip4.c
+++ b/src/connection-editor/page-ip4.c
@@ -542,6 +542,9 @@ cell_editing_canceled (GtkCellRenderer *renderer, gpointer user_data)
priv->last_column = -1;
}
+#define DO_NOT_CYCLE_TAG "do-not-cycle"
+#define DIRECTION_TAG "direction"
+
static void
cell_edited (GtkCellRendererText *cell,
const gchar *path_string,
@@ -555,6 +558,9 @@ cell_edited (GtkCellRendererText *cell,
GtkTreeIter iter;
guint32 column;
GtkTreeViewColumn *next_col;
+ GtkCellRenderer *next_cell;
+ gboolean can_cycle;
+ int direction, tmp;
/* Free auxiliary stuff */
g_free (priv->last_edited);
@@ -588,10 +594,22 @@ cell_edited (GtkCellRendererText *cell,
g_free (prefix);
}
- /* Move focus to the next column */
- column = (column >= COL_LAST) ? 0 : column + 1;
+ /* Move focus to the next/previous column */
+ can_cycle = g_object_get_data (G_OBJECT (cell), DO_NOT_CYCLE_TAG) == NULL;
+ direction = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), DIRECTION_TAG));
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, NULL);
+ g_object_set_data (G_OBJECT (cell), DO_NOT_CYCLE_TAG, NULL);
+ if (direction == 0) /* Move forward by default */
+ direction = 1;
+
+ tmp = column + direction;
+ if (can_cycle)
+ column = tmp < 0 ? COL_LAST : tmp > COL_LAST ? 0 : tmp;
+ else
+ column = tmp;
next_col = gtk_tree_view_get_column (priv->addr_list, column);
- gtk_tree_view_set_cursor_on_cell (priv->addr_list, path, next_col, priv->addr_cells[column], TRUE);
+ next_cell = column <= COL_LAST ? priv->addr_cells[column] : NULL;
+ gtk_tree_view_set_cursor_on_cell (priv->addr_list, path, next_col, next_cell, TRUE);
gtk_tree_path_free (path);
ce_page_changed (CE_PAGE (self));
@@ -721,12 +739,12 @@ cell_changed_cb (GtkEditable *editable,
}
static gboolean
-key_pressed_cb (GtkWidget *widget,
- GdkEvent *event,
- gpointer user_data)
+key_pressed_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
- GdkKeymapKey *keys = NULL;
- gint n_keys;
+ GdkModifierType modifiers;
+ GtkCellRenderer *cell = (GtkCellRenderer *) user_data;
+
+ modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
/*
* Tab should behave the same way as Enter (cycling on cells).
@@ -736,17 +754,20 @@ key_pressed_cb (GtkWidget *widget,
* But unfortunately, it showed up crash occurred with XIM input (GTK_IM_MODULE=xim).
* https://bugzilla.redhat.com/show_bug.cgi?id=747368
*/
- if (event->type == GDK_KEY_PRESS && event->key.keyval == GDK_KEY_Tab) {
- /* Get hardware keycode for GDK_KEY_Return */
- if (gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), GDK_KEY_Return, &keys,
&n_keys)) {
- /* Change 'Tab' to 'Enter' key */
- event->key.keyval = GDK_KEY_Return;
- event->key.hardware_keycode = keys[0].keycode;
- }
- g_free (keys);
- }
-
- return FALSE;
+ if (event->keyval == GDK_KEY_Tab && modifiers == 0) {
+ /* Tab */
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, GINT_TO_POINTER (1));
+ utils_fake_return_key (event);
+ } else if (event->keyval == GDK_KEY_ISO_Left_Tab && modifiers == GDK_SHIFT_MASK) {
+ /* Shift-Tab */
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, GINT_TO_POINTER (-1));
+ utils_fake_return_key (event);
+ } else if (event->keyval == GDK_KEY_Up)
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, GINT_TO_POINTER (-1));
+ else if (event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_ISO_Enter)
+ g_object_set_data (G_OBJECT (cell), DO_NOT_CYCLE_TAG, GUINT_TO_POINTER (TRUE));
+
+ return FALSE; /* Allow default handler to be called */
}
static void
@@ -787,7 +808,7 @@ cell_editing_started (GtkCellRenderer *cell,
/* Set up key pressed handler - need to handle Tab key */
g_signal_connect (G_OBJECT (editable), "key-press-event",
(GCallback) key_pressed_cb,
- user_data);
+ cell);
}
static void
diff --git a/src/connection-editor/page-ip6.c b/src/connection-editor/page-ip6.c
index 4e71712..cfa09ff 100644
--- a/src/connection-editor/page-ip6.c
+++ b/src/connection-editor/page-ip6.c
@@ -585,6 +585,9 @@ cell_editing_canceled (GtkCellRenderer *renderer, gpointer user_data)
priv->last_column = -1;
}
+#define DO_NOT_CYCLE_TAG "do-not-cycle"
+#define DIRECTION_TAG "direction"
+
static void
cell_edited (GtkCellRendererText *cell,
const gchar *path_string,
@@ -598,6 +601,9 @@ cell_edited (GtkCellRendererText *cell,
GtkTreeIter iter;
guint32 column;
GtkTreeViewColumn *next_col;
+ GtkCellRenderer *next_cell;
+ gboolean can_cycle;
+ int direction, tmp;
/* Free auxiliary stuff */
g_free (priv->last_edited);
@@ -610,10 +616,22 @@ cell_edited (GtkCellRendererText *cell,
gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path);
gtk_list_store_set (store, &iter, column, new_text, -1);
- /* Move focus to the next column */
- column = (column >= COL_LAST) ? 0 : column + 1;
+ /* Move focus to the next/previous column */
+ can_cycle = g_object_get_data (G_OBJECT (cell), DO_NOT_CYCLE_TAG) == NULL;
+ direction = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), DIRECTION_TAG));
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, NULL);
+ g_object_set_data (G_OBJECT (cell), DO_NOT_CYCLE_TAG, NULL);
+ if (direction == 0) /* Move forward by default */
+ direction = 1;
+
+ tmp = column + direction;
+ if (can_cycle)
+ column = tmp < 0 ? COL_LAST : tmp > COL_LAST ? 0 : tmp;
+ else
+ column = tmp;
next_col = gtk_tree_view_get_column (priv->addr_list, column);
- gtk_tree_view_set_cursor_on_cell (priv->addr_list, path, next_col, priv->addr_cells[column], TRUE);
+ next_cell = column <= COL_LAST ? priv->addr_cells[column] : NULL;
+ gtk_tree_view_set_cursor_on_cell (priv->addr_list, path, next_col, next_cell, TRUE);
gtk_tree_path_free (path);
ce_page_changed (CE_PAGE (self));
@@ -717,12 +735,12 @@ cell_changed_cb (GtkEditable *editable,
}
static gboolean
-key_pressed_cb (GtkWidget *widget,
- GdkEvent *event,
- gpointer user_data)
+key_pressed_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
- GdkKeymapKey *keys = NULL;
- gint n_keys;
+ GdkModifierType modifiers;
+ GtkCellRenderer *cell = (GtkCellRenderer *) user_data;
+
+ modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
/*
* Tab should behave the same way as Enter (cycling on cells).
@@ -732,17 +750,20 @@ key_pressed_cb (GtkWidget *widget,
* But unfortunately, it showed up crash occurred with XIM input (GTK_IM_MODULE=xim).
* https://bugzilla.redhat.com/show_bug.cgi?id=747368
*/
- if (event->type == GDK_KEY_PRESS && event->key.keyval == GDK_KEY_Tab) {
- /* Get hardware keycode for GDK_KEY_Return */
- if (gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), GDK_KEY_Return, &keys,
&n_keys)) {
- /* Change 'Tab' to 'Enter' key */
- event->key.keyval = GDK_KEY_Return;
- event->key.hardware_keycode = keys[0].keycode;
- }
- g_free (keys);
- }
-
- return FALSE;
+ if (event->keyval == GDK_KEY_Tab && modifiers == 0) {
+ /* Tab */
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, GINT_TO_POINTER (1));
+ utils_fake_return_key (event);
+ } else if (event->keyval == GDK_KEY_ISO_Left_Tab && modifiers == GDK_SHIFT_MASK) {
+ /* Shift-Tab */
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, GINT_TO_POINTER (-1));
+ utils_fake_return_key (event);
+ } else if (event->keyval == GDK_KEY_Up)
+ g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, GINT_TO_POINTER (-1));
+ else if (event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_ISO_Enter)
+ g_object_set_data (G_OBJECT (cell), DO_NOT_CYCLE_TAG, GUINT_TO_POINTER (TRUE));
+
+ return FALSE; /* Allow default handler to be called */
}
static void
@@ -788,7 +809,7 @@ cell_editing_started (GtkCellRenderer *cell,
/* Set up key pressed handler - need to handle Tab key */
g_signal_connect (G_OBJECT (editable), "key-press-event",
(GCallback) key_pressed_cb,
- user_data);
+ cell);
}
static void
diff --git a/src/utils/utils.c b/src/utils/utils.c
index 64ceee8..f4b2ce7 100644
--- a/src/utils/utils.c
+++ b/src/utils/utils.c
@@ -539,3 +539,20 @@ utils_set_cell_background (GtkCellRenderer *cell,
} else
g_object_set (G_OBJECT (cell), "cell-background-set", FALSE, NULL);
}
+
+/* Change key in @event to 'Enter' key. */
+void
+utils_fake_return_key (GdkEventKey *event)
+{
+ GdkKeymapKey *keys = NULL;
+ gint n_keys;
+
+ /* Get hardware keycode for GDK_KEY_Return */
+ if (gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), GDK_KEY_Return, &keys, &n_keys)) {
+ event->keyval = GDK_KEY_Return;
+ event->hardware_keycode = keys[0].keycode;
+ event->state = 0;
+ }
+ g_free (keys);
+}
+
diff --git a/src/utils/utils.h b/src/utils/utils.h
index 6d4147f..b005dcc 100644
--- a/src/utils/utils.h
+++ b/src/utils/utils.h
@@ -105,5 +105,7 @@ void utils_set_cell_background (GtkCellRenderer *cell,
const char *color,
const char *value);
+void utils_fake_return_key (GdkEventKey *event);
+
#endif /* UTILS_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]