summaryrefslogtreecommitdiff
path: root/gtk/gtkradiobutton.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2015-03-29 00:24:35 -0400
committerMatthias Clasen <mclasen@redhat.com>2015-03-29 00:24:35 -0400
commit06484533396c64913c2f7cf5496bd45e190f6dad (patch)
treeb46caebc88e79c7d67a36fabdbe657111c880f9c /gtk/gtkradiobutton.c
parent505fed1383fc3f092f8ee1f9d2f1f840f8579953 (diff)
downloadgtk+-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/gtkradiobutton.c')
-rw-r--r--gtk/gtkradiobutton.c103
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;