Re: keynav question
- From: "Padraig O'Briain" <Padraig Obriain Sun COM>
- To: gtk-devel-list gnome org, tap2k yahoo com
- Cc: karunakar netcore co in
- Subject: Re: keynav question
- Date: Mon, 22 Jul 2002 16:51:18 +0100 (BST)
I have attached notes I made a few months ago about how keynav works,
I believe that they are accurate. If you have further questions I will try to
> I am working on a Gtk app where i want to have some standard
> keyboard / icon based navigation to shift focus between widgets /
> I see from some stuff at developer.gnome.org that this is already
> being done to a certain extent. Now my question is
> - Where is the keyboard nav code to be found? Where can i see how
> the keyboard events are handled and processed? (Im somewhat new w/
> Gtk so the more specificity the better... ;)
> Presumably this will allow me to answer my 2nd question...
> - How can i emit these signals myself?
> Thanks for your help,
> Tapan Parikh
> tap2k yahoo com
> gtk-devel-list mailing list
> gtk-devel-list gnome org
Normally, focus is moved from widget to widget by pressing Tab, Shift+Tab and
the arrow keys.
In the file gtkwindow.c the action signal "move_focus" is defined. There are
a number of calls to gtk_binding_entry_add_signal() which define how
move_focus signal handler should be called in response to a particular key
strokes, i.e. Tab, Shift+Tab and arrow keys. These are the key bindings for
the top level.
I digress to discuss how a key_press_event is handled. A key press will cause
a key_press_event signal to be emitted on the GtkWindow; this happens in
gtkmain.c but we do not need to go there for this discussion. As this
signal, defined in gtkwidget.c, is a RUN_LAST signal, any signal
handlers defined for that signal are executed before the default signal handler,
which is gtk_window_key_press_event(). This function first
checks whether the key press is a mnemonic or accelerator and, if so,
handles it (_gtk_window_activate_key). If there is a focus widget, the
key press event is passed to the focus widget to be handled (gtk_widget_event).
If not handled it is passed up the hierarchy to the parent widgets. If no
widget has handled the event the parent class's key_press_event function
is called. This causes gtk_widget_real_key_press_event() to be called which
activates the binding defined for the event on the window. This is what causes
the function gtk_window_move_focus() to be called when, for example, Tab is
pressed to move focus.
The function gtk_window_move_focus() calls gtk_widget_child_focus(). This
function emits a "focus" signal on the calling widget, which in this case
is a GtkWindow and this causes gtk_window_focus() to be called.
When a widget has focus each GtkContainer in the hierarchy between the
GtkWindow and the focus widget has focus_child set to the ancestor of the
The function gtk_window_focus() normally causes gtk_widget_child_focus() to be
called for the focus_child of the window. Note that the focus_child for the
window is different from the focus_widget for the window.
The most important file for understanding how focus movement works is
gtkcontainer.c as most widgets in the hierarchy derive from GtkContainer.
The function gtk_container_focus() is GtkContainer's default signal handler
for "focus" signal.
The function gtk_container_focus() does not permit a GtkContainer and its
children to be focusable.
The function gtk_container_focus() builds a list of the children using the
requested direction to determine the order of the children in the list and
then moves focus to the next child.
There are number of problems in this area with the arrow keys (e.g.
bug 60690) but they are not easy to fix.
A particular widget, e.g. GtkEntry for the key stroke GDK_Left, can override
this action by defining its own key bindings. These key bindings are activated
when the widget has focus, by the default key_press event signal handler for
GtkWidget, the function gtk_widget_real_key_press_event referred to earlier.
Keyboard navigation for menus uses something completely different.
Activation of the menu bar using F10.
In gtksettings.c, the default keybinding to activate the menu bar is specified
as F10. When a GtkMenuBar is added to the widget hierarchy,
gtk_widget_set_parent() is called for the GtkMenuBar. This function emits
the signal "hierarchy-changed". GtkMenuBar defines a default signal
handler for that signal, gtk_menu_bar_hierarchy_changed(). This function
calls add_to_window() which defines a signal handler, window_key_press_handler,
for the signal key_press_event, for the first GtkMenuBar added to the
GtkWindow. This means that when there is a GtkMenuBar in the GtkWindow, every
keystroke will cause the function window_key_press_handler() to be called before
the default signal handler gtk_window_key_press_event_handler discussed
earlier.. If the key was F10, the activate_item signal is emitted for the
first child of the GtkMenuBar.
The default signal handler for this signal, gtk_menu_item_real_activate_item,
calls gtk_grab_add() and pops up a window. This has the effect that when an
event is processed in gtk_main_do_event() the event is sent to the window of
the popped up menu.
The comments the block Terminology in gtkmenushell.c are useful in
understanding menu navigation and the appropriate terminology.
Navigating of menus and menubars is controlled by the action signal defined in
gtkmenushell.c Both GtkMenuBar and GtkMenu, which derive from GtkMenuShell,
define key bindings (the arrow keys) for move_current and the default signal
handler for move_current is gtk_real_menu_shell_move_current() actually moves
the current menu item.
] [Thread Prev