diff options
author | Matthias Clasen <mclasen@redhat.com> | 2015-03-29 00:24:35 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2015-03-29 00:24:35 -0400 |
commit | 06484533396c64913c2f7cf5496bd45e190f6dad (patch) | |
tree | b46caebc88e79c7d67a36fabdbe657111c880f9c /gtk | |
parent | 505fed1383fc3f092f8ee1f9d2f1f840f8579953 (diff) | |
download | gtk+-06484533396c64913c2f7cf5496bd45e190f6dad.tar.gz |
radio button: Fix directional navigation
GtkRadioButton had a deficient copy of the focus sort code
in GtkContainer, causing focus to jump over the next button
in the list. Just use _gtk_container_focus_sort() here,
which fixes the bug _and_ saves 80 lines of code.
https://bugzilla.gnome.org/show_bug.cgi?id=746817
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/gtkradiobutton.c | 103 |
1 files changed, 23 insertions, 80 deletions
diff --git a/gtk/gtkradiobutton.c b/gtk/gtkradiobutton.c index e13062a4dc..9bc6b71755 100644 --- a/gtk/gtkradiobutton.c +++ b/gtk/gtkradiobutton.c @@ -26,6 +26,7 @@ #include "gtkradiobutton.h" +#include "gtkcontainerprivate.h" #include "gtkbuttonprivate.h" #include "gtktogglebuttonprivate.h" #include "gtklabel.h" @@ -593,53 +594,6 @@ gtk_radio_button_destroy (GtkWidget *widget) GTK_WIDGET_CLASS (gtk_radio_button_parent_class)->destroy (widget); } -static void -get_coordinates (GtkWidget *widget, - GtkWidget *reference, - gint *x, - gint *y) -{ - GtkAllocation allocation; - - gtk_widget_get_allocation (widget, &allocation); - *x = allocation.x + allocation.width / 2; - *y = allocation.y + allocation.height / 2; - - gtk_widget_translate_coordinates (widget, reference, *x, *y, x, y); -} - -static gint -left_right_compare (gconstpointer a, - gconstpointer b, - gpointer data) -{ - gint x1, y1, x2, y2; - - get_coordinates ((GtkWidget *)a, data, &x1, &y1); - get_coordinates ((GtkWidget *)b, data, &x2, &y2); - - if (y1 == y2) - return (x1 < x2) ? -1 : ((x1 == x2) ? 0 : 1); - else - return (y1 < y2) ? -1 : 1; -} - -static gint -up_down_compare (gconstpointer a, - gconstpointer b, - gpointer data) -{ - gint x1, y1, x2, y2; - - get_coordinates ((GtkWidget *)a, data, &x1, &y1); - get_coordinates ((GtkWidget *)b, data, &x2, &y2); - - if (x1 == x2) - return (y1 < y2) ? -1 : ((y1 == y2) ? 0 : 1); - else - return (x1 < x2) ? -1 : 1; -} - static gboolean gtk_radio_button_focus (GtkWidget *widget, GtkDirectionType direction) @@ -653,45 +607,34 @@ gtk_radio_button_focus (GtkWidget *widget, */ if (!gtk_toggle_button_get_mode (GTK_TOGGLE_BUTTON (widget))) return GTK_WIDGET_CLASS (gtk_radio_button_parent_class)->focus (widget, direction); - + if (gtk_widget_is_focus (widget)) { - GSList *focus_list, *tmp_list; - GtkWidget *toplevel = gtk_widget_get_toplevel (widget); + GList *children, *focus_list, *tmp_list; + GtkWidget *toplevel; GtkWidget *new_focus = NULL; + GSList *l; - switch (direction) - { - case GTK_DIR_LEFT: - case GTK_DIR_RIGHT: - focus_list = g_slist_copy (priv->group); - focus_list = g_slist_sort_with_data (focus_list, left_right_compare, toplevel); - break; - case GTK_DIR_UP: - case GTK_DIR_DOWN: - focus_list = g_slist_copy (priv->group); - focus_list = g_slist_sort_with_data (focus_list, up_down_compare, toplevel); - break; - case GTK_DIR_TAB_FORWARD: - case GTK_DIR_TAB_BACKWARD: - /* fall through */ - default: - return FALSE; - } + if (direction == GTK_DIR_TAB_FORWARD || + direction == GTK_DIR_TAB_BACKWARD) + return FALSE; - if (direction == GTK_DIR_LEFT || direction == GTK_DIR_UP) - focus_list = g_slist_reverse (focus_list); + toplevel = gtk_widget_get_toplevel (widget); + children = NULL; + for (l = priv->group; l; l = l->next) + children = g_list_prepend (children, l->data); - tmp_list = g_slist_find (focus_list, widget); + focus_list = _gtk_container_focus_sort (GTK_CONTAINER (toplevel), children, direction, widget); + tmp_list = g_list_find (focus_list, widget); if (tmp_list) { tmp_list = tmp_list->next; - + while (tmp_list) { GtkWidget *child = tmp_list->data; - + if (gtk_widget_get_mapped (child) && gtk_widget_is_sensitive (child)) { new_focus = child; @@ -709,18 +652,19 @@ gtk_radio_button_focus (GtkWidget *widget, while (tmp_list) { GtkWidget *child = tmp_list->data; - + if (gtk_widget_get_mapped (child) && gtk_widget_is_sensitive (child)) { new_focus = child; break; } - + tmp_list = tmp_list->next; } } - - g_slist_free (focus_list); + + g_list_free (focus_list); + g_list_free (children); if (new_focus) { @@ -734,12 +678,11 @@ gtk_radio_button_focus (GtkWidget *widget, else { GtkRadioButton *selected_button = NULL; - + /* We accept the focus if, we don't have the focus and * - we are the currently active button in the group * - there is no currently active radio button. */ - tmp_slist = priv->group; while (tmp_slist) { @@ -748,7 +691,7 @@ gtk_radio_button_focus (GtkWidget *widget, selected_button = tmp_slist->data; tmp_slist = tmp_slist->next; } - + if (selected_button && selected_button != radio_button) return FALSE; |