Toolbar keyboard navigation / secondary focus chain



[It looks like I managed to screw up sending this mail, so I am
retrying. Sorry if this is a duplicate.]

Below is a description of what I think should be done for toolbar
keyboard navigation, and also how it should be done. It turned out to
much more complex than I initially expected. Comments are
appreciated. If I don't hear anything, I expect to start implementing
this next weekend.


What to do
----------

There are three different suggestions for toolbar keyboard navigation:

	a) Toolbar items are not part of the regular tab sequence. You
	   press F10 to cycle between menubars, toolbars and the "no
	   menu/tool bar" state.

	b) Toolbar items are part of the regular TAB sequence

	c) As a), but some tool-items such as location entries can be
	   part of the tab sequence.

I think b) is just a bad idea. Gnumeric, for example, has more than 50
toolitems.  If we are putting all those items in the tab sequence, I
think there should at least be a way to skip from toolbar to toolbar
so that you don't have to tab though them all.

c) will probably have to rely on the application to provide
information about what tool-items should be part of the regular tab
chain. We could add a new method on EggToolItem,

	egg_tool_item_set_in_tab_chain (EggToolItem *, gboolean)

that would set whether the item was on the regular chain or not. It
is possible to implement (a) so that (c) is easy to do later on.


Calum suggested that toolitems should only be focusable with the
keyboard, not with the mouse. This is easy to do for buttons, and in
fact both the curren GtkToolbar and EggToolbar already do it. Doing
this for items such as entries would be wrong though, because they
would be next to useless if you couldn't focus them with the mouse.

Since buttons are by far the most common toolitem, and they are easy
to make keyboard-focusable only, I think doing this only for buttons
is fine.

One thing that needs to be taken care of is GtkHandleBox. Handleboxes
should also be in the F10 sequence, and in fact, if the toolbars and
menubars are inside handleboxes, only the handles should get focos on
F10 (and navigating to the menu or toolbar should then be done with
arrow keys), because to the user the handle will just be another
gadget on the toolbar.

Michael wants there to be public API so that applications can add
their own widgets to the F10 chain. This makes sense to me since I
don't think gtk+ can anticipate everything that will ever need to go
into this chain. Only allowing menubars, toolbars and handleboxes in
the chain would be much simpler, though.


How to do it
------------

The F10 tab chain should be managed by GtkWindow, because the menu and
toolbars only have local information while the window has global
information. Global information is needed if widgets unknown to gtk+
can be added to the chain. In addition, the the original focus needs
to be saved and restored, and GtkWindow is best suited to do this.

To make this possible, the window needs to know 

	(1) what widgets are in the F10 chain
	(2) how to make focus enter the widgets
	(3) when widgets are done doing keyboard navigation

(1) is complicated by the fact that bars both with and without handles
need to be in the chain. This means that if widgets just register
themselves with the window, the window needs to figure out that only
the topmost of the registered widgets need to get focus.

On the other hand, it is complicated to have widgets manage the
connection to the window themselves. They would need to keep track of
which of their children would like to receive F10 focus. So it seems
best to let widgets register themselves "I want to receive F10 focus",
and have the window sort out what widgets to actually focus.


(2) Widgets need to know when they should start F10 focusing. 

	- add a new signal "set_secondary_focus" with a boolean
          parameter on GtkWidget

	- a new "secondary_focusable" interface

	- overload gtk_widget_grab_focus(). The menu/toolbar would
	  implement special focus_in methods.

	- Have widgets provide an activation function when they
          register themselves.

In my opinion, only the two first options are sane, and the second one
is overkill.  So this leaves adding a new signal on GtkWidget. When
this "set_secondary_focus" signalis emitted with TRUE as the
parameter, the widget makes sure its "focus" method does not return
FALSE. The signal is propagated down the widget hierarchy so that when
the signal is emitted on a handlebox with a toolbar inside, both the
handlebox and the toolbar will enter the "secondary focus
mode". Focusing then proceeds pretty much as normal.  This has the
(nice?) side-effect that crazy things like menubars inside toolbars
would work.

The secondary widgets must let the focus key propagate up to the
window, so that it can handle the focus cycling.

When the signal is emitted with FALSE, the focus mode is turned off

(3) can be done with a simple gtk_window_stop_secondary_focusing()
method on GtkWindow.  This function would emit "set_focus_mode
(FALSE)" signals, and restore focus to the widget that had focus
before F10 navigation started.


GtkHandleBox changes
--------------------

The handle box would need to implement the signal and when in focus
mode propagate focus into its child.


EggToolbar changes
------------------

Currently, the EggToolbar turns off focus for buttons simply by
unsetting their GTK_CAN_FOCUS flag. Still doing this means:

	- By using the mouse or a mnemonic, you can still focus other
	  items than buttons.  This is correct behavior, because
	  toolitems such as entries would be useless otherwise.

	- When keyboard navigation starts, the CAN_FOCUS flags will
	  have to be turned on again. When keyboard navigation ends,
	  the flags should be turned off. This is easy to do since the
	  "set_secondary_focus" signal propagates down. the
	  hierarchy. Toolitems that have turned off CAN_FOCUS can turn
	  it back on in their handler.

Although turning CAN_FOCUS on and off dynamically seems a bit dubious,
it will probably work well in practice.

GtkMenu[Bar] changes
--------------------

The biggest changes would be making the menu widgets use the focus
system to move focus around. I think this is doable, although getting
keypresses to propagate correctly will be tricky.

A nice side effect of having GtkMenuItem be a GTK_CAN_FOCUS widget is
that it should be feasible to popup tooltips with Shift-F1.

[Keyboard navigation inside menus doesn't work very well currently,
 but that is another discussion. Using the focus system should not
 make it any harder to fix this].



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]