Keynav implementation issues



The following is a list of "hard" implementation issues I'm aware of
in the outstanding keynav bugs, with some thoughts about possible ways
of dealing with them. (This isn't meant to list issues which are
questions of "what should we do" just issues of "how do we do it".)

There are more questions in the following than answers, but hopefully
listing this stuff will allow us to move forward in figuring out
the right way to handle each problem.

If you know of additional issues I've missed here, please let me know.

Regards,
                                        Owen

Bindings on parent widgets:

 The keynav design calls for various bindings on widgets that should
 take effect if focus is on any child widgets. This include:

  Ctrl-PgUp/PgDown to switch pages in a notebook
  Ctrl-Tab to focus out of notebook
  F8 to focus through GtkPaned splitter bars "currently in context"
  F6 to to focus among panes "currently in context"

 The Swing key binding system has a concept where key bindings can:

   - Apply only when the widget has focus
   - Apply when the widget or any child has focus
   - Apply when any widget in the same toplevel has focus

 While something like this could be implemented in GTK+, it probably
 is overkill. There are various possibilities:

   - Hack all such keybindings into GtkWindow.
   - When focus is moved inside such a widget, set up a temporary
     signal connection on the toplevel and handle keystrokes there.
   - Make GTK+ propagate keystrokes not just to the focus widget
     then to the toplevel but through all intermediate widgets
     as well.

  I suspect the last one is the best solution, though there is some
  risk of unintended side effects if you have nested widgets taking
  key input.

Remembering the "last focus" within a child widget.

 The keynav spec specifies that when switching between pages of a
 notebook with Ctrl-PgUp/PgDown or between panes with F6, the last
 focused widget in each page or tab is remembered and returned to.

 You can almost keep track of what descendent of a container has focus
 by watching calls to set_focus_child(), however this doesn't quite
 work because toplevel->focus_widget isn't set at this point. This
 could be gotten around by setting up a temporary connection to
 ::set_focus on the toplevel whenever you get a call to
 ::set_focus_child with child != NULL. Or we could change it so we:

  unset the old container focus widgets
  set toplevel->focus_widget
  set the container focus widgets

 (This would require moving some code from
 gtk_widget_real_grab_focus() to gtk_window_real_set_focus())

Keynav for toolbars:

 The keynav spec specifies that F10 switches between all menus and
 toolbars in the current window. Keynav in menus in GTK+ is not
 currently handled through the focus system. However, toolbars can
 contain normal widgets entries in them and probably need to go
 through the normal focus system.

 (This does raise the issue that if you things like a location entry
 in a toolbar, the location entry possibly should be part of the main
 focus chain.)

 Padraig's current patch in #54047 takes the approach of making key
 navigation in toolbars work like that menus - with a grab and
 handling keystrokes more or less directly without having the focus.

 A different approach would be to handle key navigation in a GtkMenu
 with menus popped down through the normal focus system. (But not put
 menu bars and toolbars in the normal focus chain.) So, F10 would
 focus the menu bar, toolbar, etc, but not establish a grab. The grab
 would only be established when the first menu was popped up.

 (There would then need to be some mechanism for saving the focus
 within the main window since the focus was actually being moved;
 this is related to the above issue.)

Mnemonics activation without alt:

 The proposal suggests that if the current control doesn't accept
 keyboard input, then mnemonics should be accessible without
 the Alt key.

 One way that it might be possible to do this is to handle 
 unmodified mnemonics in gtk_widget_real_key_press_event(); if
 a keystroke was not otherwise intercepted, then it would
 be interpreted as a menomic. Problems with this are:

  - There is no requirement currently for widgets to chain
    up their key_press handlers - they can simply call
    gtk_bindings_activate() themselves.

  - If a widget handled only some unmodified keystrokes and
    not others, the result could be quite confusing.

 A different technique would be to have some sort of widget
 flag "handles_custom_key_input" and do processing of 
 unmodified mnemonics only if the focus widget didn't have
 that flag set. I don't particularly like this idea though -
 people are likely to forget to set/clear this flag; plus
 it just doesn't seem to be the "GTK+ way".

 A simpler fallback (also suggested) would be to  make whether 
 unmodified mnemonics are allowed as a GtkWindow property,
 which could be defaulted to the correct value for 
 GtkMessageBox.

Popping down tooltips

 (I'm not sure if there was a final decision on what the desired
 behavior was. In some experimentation, it seemed to me that
 what might be nice would be if Ctrl-F1 put the window into
 a "keyboard tooltips mode" where the tooltip was always displayed
 for the currently focused widget and never for the mouse,
 and Escape would cancel that mode. Perhaps focusing out of the
 toplevel would deactivate the mode as well.)

 When a tooltip is popped up via the Ctrl-F1 binding, Escape should
 pop it back down. This poses a problem because Escape has a different
 function that should take unless tooltips are popped up.

 If you are willing to hard-code Escape, there are multiple ways
 of doing this - just hardcoding it into gtk_window_key_press() 
 would be the simplest. A little more general than hardcoding
 would be to do it like F10 is currently handled - as a string
 setting that is converted into a key stroke.

 A more general approach would be to add an idea of an "optional
 keybinding" - if the action signals connected to a key
 binding have boolean return values and they all return FALSE,
 then the key press is considered not handled.

 (I don't think the gtk_binding_set_enable_signal() approach taken
 in the patch attached to #53614 is quite right because we only
 know the default binding set, not every binding set that might
 be attached to a widget, and, what's more, the default binding
 set is global to the entire application, and in GTK+-2.2, will
 be global across all displays. An enable/disable API would have
 to be on a signal/widget basis, not a signal/binding-set basis.
 But using signal return values may be nicer.)





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