Key navigation with reduced set of keys
- From: "markku vire suomi24 fi" <markku vire suomi24 fi>
- To: gtk-devel-list gnome org
- Subject: Key navigation with reduced set of keys
- Date: Wed, 9 Nov 2005 12:06:53 +0100 (MET)
Hi,
When keys are used for navigation, gtk+ uses arrow keys and
different tab + modifier
combinations to move focus around. With normal
keyboard this works nicely.
When the used hardware has limited set of
keys, problems start to pile up. If only arrow keys
are available (but
no tab, shift, ctrl etc), everything looks good at first, but it will
soon come
clear that there are problems. This is because some widgets
handle arrow keys themselves and
do not allow to use them for
navigation. For example, GtkEntry uses left/right arrows to
move the
cursor horizontally and GtkTextView also up/down arrows to move cursor
vertically. And
then there are comboboxes, spinbuttons, treeviews
etc...
Under normal desktop use you have to use shift/ctrl modifiers
to escape widgets of this kind,
but otherwise you are jammed. Things
are even worse if no pointer device is available...
(see http:
//bugzilla.gnome.org/show_bug.cgi?id=318827).
For entries and
textviews it would be logical that the focus would move to next widget
in the desired
direction if the cursor cannot be moved further into
desired direction.
There is also an open bug in gnome bugzilla about
navigating past end of buffer
(see http://bugzilla.gnome.org/show_bug.
cgi?id=70986). Even though the wanted effect is different
(beep wanted
when out of buffer navigation takes place), the actual problem is the
same.
So, I'm proposing new api addition to gtk that would allow both
of the mentioned
problems to be solved: Widgets that have some king of
internal navigation, could send
an "out-of-bounds" or similar signal.
For example:
--- gtk+-2.6.10/gtk/gtkwidget.h 2005-08-18 17:10:
59.000000000 +0300
+++ gtk+-2.6.10/gtk/gtkwidget.h 2005-11-07 13:29:
54.000000000 +0200
@@ -406,8 +406,11 @@
gboolean
(*can_activate_accel) (GtkWidget *widget,
guint signal_id);
+ /*
Navigation past-end-of-buffer support for various widgets */
+
gboolean (*out_of_bounds) (GtkWidget *widget,
+ GtkDirectionType dir);
+
/*
Padding for future expansion */
- void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
void (*_gtk_reserved5) (void);
@@ -569,6 +572,10 @@
void
gtk_widget_get_size_request (GtkWidget *widget,
gint *width,
gint
*height);
+
+gboolean gtk_widget_out_of_bounds (GtkWidget
*widget,
+ GtkDirectionType
dir);
+
#ifndef GTK_DISABLE_DEPRECATED
void
gtk_widget_set_uposition (GtkWidget *widget,
gint x,
---
gtk+-2.6.10/gtk/gtkwidget.c 2005-08-18 17:10:59.000000000 +0300
+++
gtk+-2.6.10/gtk/gtkwidget.c 2005-11-07 13:57:26.000000000 +0200
@@
-120,6 +120,7 @@
ACCEL_CLOSURES_CHANGED,
SCREEN_CHANGED,
CAN_ACTIVATE_ACCEL,
+ OUT_OF_BOUNDS,
LAST_SIGNAL
};
@@ -1389,6
+1390,15 @@
_gtk_marshal_BOOLEAN__UINT,
G_TYPE_BOOLEAN, 1, G_TYPE_UINT);
+ widget_signals
[OUT_OF_BOUNDS] =
+ g_signal_new ("out_of_bounds",
+
G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkWidgetClass, out_of_bounds),
+ _gtk_boolean_handled_accumulator, NULL,
+ _gtk_marshal_BOOLEAN__ENUM,
+
G_TYPE_BOOLEAN, 1, GTK_TYPE_DIRECTION_TYPE);
+
binding_set =
gtk_binding_set_by_class (klass);
gtk_binding_entry_add_signal
(binding_set, GDK_F10, GDK_SHIFT_MASK,
"popup_menu", 0);
@@ -7600,5 +7610,15 @@
g_object_notify (G_OBJECT
(widget), "no-show-all");
}
+gboolean
+gtk_widget_out_of_bounds
(GtkWidget *widget,
+ GtkDirectionType dir)
+{
+ gboolean result;
+ g_return_val_if_fail (GTK_IS_WIDGET (widget),
FALSE);
+ g_signal_emit (widget, widget_signals[OUT_OF_BOUNDS], 0,
dir, &result);
+ return result;
+}
+
#define __GTK_WIDGET_C__
#include "gtkaliasdef.c"
This could be then be used by various
widgets. GtkEntry, for example:
--- gtk+-2.6.10/gtk/gtkentry.c 2005-
08-18 17:10:57.000000000 +0300
+++ gtk+-2.6.10/gtk/gtkentry.c 2005-11-
07 14:14:08.000000000 +0200
@@ -2386,6 +2386,9 @@
break;
case GTK_MOVEMENT_VISUAL_POSITIONS:
new_pos =
gtk_entry_move_visually (entry, new_pos, count);
+ if (entry-
>current_pos == new_pos && !extend_selection)
+
gtk_widget_out_of_bounds(GTK_WIDGET(entry), count > 0 ? GTK_DIR_RIGHT :
GTK_DIR_LEFT);
+
break;
case GTK_MOVEMENT_WORDS:
while (count > 0)
The default handler of this signal could
then use some GtkSetting to decide whether or not some
kind of message
(visual/beep) is needed and if focus needs to be moved into desired
direction.
This functionality could also be implemented as separate gtk
module using signal emission hook.
I'm not sure if this can solve all
cases with different widgets. For example, GtkComboBoxEntry uses
left/right to move cursor and up/down to change selected item. If we
now would like to navigate below
the widget, we would have to keep
pressing arrow down until we have reached the end of items...
All
ideas, comments and other feedback is highly welcomed ;)
Markku Vire
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]