Re: keycode handling



On 3 Dec 2000, Owen Taylor wrote:

> 
> I agree that we need to figure out how to make this functionality
> easily accesssible to programs not using GTK+'s accelerator
> mechanism. I'm not sure I would exactly do it as you suggest:
> 
>  - There is no reason to add extra fields to GdkEventKey - if additional
>    computed keyvals are wanted, they can be done as accessors
> 
>     guint gdk_event_key_get_base_keyval (GdkEventKey *event);
> 
>    Or something.
>
>  - Magically renaming the fields of the GdkEvent using #defines
>    is not something I generally would consider conducive to
>    the future maintainability of GTK+.

 I don't  think that adding a couple of ifdefs could compilcate
maintainability that much. But using this approach allows not to perform
audit/editing of the code of all apps that hardcode accelerators and improve
their maintainability. I think the advantages by far outweight disadvantages. 
 Also, the task of determining the "canonical keyval" can be handed to Input
Method in the case of growing GdkEventKey - it's much more flexible than
hardcoding the logic in some gtk function.
 
> But more generally, I'm not sure that the algorithm of simply
> using group zero is right, and I'm not even sure that we 
> can decide the best algorithm right now, so we may want
> to hide that from the programmer.

 OK, we may forget about group 0 (g0 in the names of fields I proposed to
add) - they are really better treated as 'canonical group' without particular 
group number.

> The simple case is - 
> 
>  Accelerator: <Control>A
>  Activated:   Whenever <Control> and the key with 'A' (and maybe
>               other things) printed on it is pressed.
> 
> But what about:
> 
>  Accelerator: <Control>{
>
> I can produce the { character on my keyboard as:
> 
>  <Shift>+[   [ G=0, L=1 ] 
>  <AltGr>+7   [ G=1, L=0 ] 
> 
> Clearly, this should be activated when <Control> + either
> of those two combinations is pressed. But I probably would
> not expect it for <Control>+7
> 
> 
> Or, 
> 
>  Accelerator: <Shift>+
> 
> [ Found in GtkCTree as a keybinding ]
> 
> The expectation of the person writing this was the user had a US
> keyboard:
> 
>  /---\ /---\ 
>  | _ | | + |
>  | - | | = |
>  \---/ \---/  
> 
> But the keyboard in Germany, looks more like:
> 
>  /---\      /---\ 
>  | * | ...  | _ |
>  | + |      | - |
>  \---/      \---/  
> 
> [ Suprisingly, the CTree was written by Germans.... ]
> 
> 
> With the German layout, should the accelerator be activated
> for '+' or <Shift>+ == '*'?
> 
> I think the answer here is that the binding should be fixed
> to be simply '+', not '<Shift>+'
> 
> But if the correct binding is '+', should that be activated
> when the user types '='? Does that depend on whether there
> is another binding explicitely for '='?  
> 
> (If the answer to that is yes, remember that keys can be
> handled in various different layers.)

 Nice description of the problem..

> 
> Thise isn't at all trivial, and I don't think simply mapping
> to some sort of 'canonical keysym' that people are supposed to
> use when writing key symbols is the correct approach.
> 
> 
> My current best thought is to suggest people write something
> vaguely like:
> 
>   static GdkAccelMap *map = NULL;
> 
>  if (!map) 
>    {
>      map = gdk_accel_map_new (NULL);
> 
>      gdk_accel_map_add_binding (map, "a",         GUINT_TO_POINTER (ACCELERATE));
>      gdk_accel_map_add_binding (map, "<Shift>a",  GUINT_TO_POINTER (DECELERATE));
>      gdk_accel_map_add_binding (map, "+",         GUINT_TO_POINTER (ZOOM_IN));
>    }
> 
>  switch (GPOINTER_TO_UINT (gdk_accel_map_lookup_event (map,event)))
>    {
>    case ACCELERATE:
>      [...]
>    case DECELERATE:
>      [...]
>    }
> 
> Yes .... more API. And we could use the same GdkAccelMap internally
> in GtkBindingSet, GtkAccelGroup, and even for Havoc's GtkIMContextSimple
> modification.

 As GdkAccelMap - that's the way to get the most inteligent and correct
decision on what action should be returned for the given keypress since all
possible "answers" are known (i.e. all information is provided). I'm all for
it. But it seems this will work correctly only if there is global registry of
all bindings that are active at the given moment (that's not true for gtk as I
know since bindings are registered in binding sets, and mutiplie instances of
bindingsets are allowed).

 And it would be nice to have "hackish" solution too that will make currently
written code i18n-friendly without modifications. Since making currently
written code i18n-friendly without modifications is inherently unreliable
(the use of propsed GdkAccelMap is the correct way for hardwired accels), we
don't have to struggle for correctness in pathological cases as with Shift-+
acclerator you've provided. We can perform mapping to group 0 level 0 (or
current) only for keysyms that are letters (i.e. for keysyms that have 
lowercased and uppercased versions) and store that mapped value into a field
of GdkEventKey to allow swapping it with 'keyval' member (for completness, we 
should add 'original_keyval' field too so that apps that care will be able to 
use precise keyval independant of whether fields were swapping in
GdkEventKey).

 So, it would be nice to have both solutions available in gtk+ (in fact, one
at GDK level, other - at GTK level).

> Regards,
>                                         Owen
> 

 Best regards,
  -Vlad





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