Re: on menu accelerators and key press handlers

Paul Barton-Davis <pbd op net> writes:
> i want to try to make sure i understand the mindset of the GTK API
> crew when it comes to combining menu accelerators with key press
> handlers. 
> i've discovered (the hard way) that you don't want to have an
> accelerator *and* a key press handler both handling the same key. what
> happens is that (assuming the right widget has focus), the
> app-provided key press handler will run first (causing <foo> to
> happen). then we finish the regular gtk_handlers_run() for the
> event. This returns the value of the *last* handler, which is the
> default handler, and is almost certainly FALSE. then, back in
> gtk_window_key_press_event(), this FALSE return causes us to then move
> on and activate the accelerators, which cause the action to be
> performed all over again.
> i can see a couple of ways to stop this. 
>   2) use gtk_signal_emit_stop_by_name() from the key press handler
>         if the key press was really handled. 
>       * i don't know if this will actually work, but it seems as if 
>         it should
>   3) don't handle the accelerator keys from within the key press handler
>       * seems reasonable, i think
>   4) use gtk_signal_connect_after() to override the FALSE return
>         from the default handler
>       * seems like a kludge
> So, I want to find out what the conceptual model is for the
> interaction between these two methods of handling key press events is,
> so that I can "do the right thing". Thanks,

These are all fine solutions I think. 

As I understand it, the concept is:
 - all key events are handled by GtkWindow initially 
 - in its default handler, what GtkWindow does is to see whether the
   focus widget handles the event, if so it stops processing, if not
   it tries to handle the event itself by first seeing if there's an
   accelerator then doing the key navigation stuff (tab, etc.)

You can hook into this on any number of levels. If you connect to
key_press_event on the toplevel window, you would usually want to
emit_stop_by_name() to keep the default handler from running. 

On a focused child widget, you may want to get the emission to return
TRUE to override further action in the GtkWindow default handler
(which means either overriding the default handler with a subclass, or
connect_after(), or the hackier emit_stop_by_name()).

Last I heard, the plan in GTK+ 2.0 is that returning TRUE from an
event handler stops the emission, which is what people seem to expect
anyway, and this will make things simpler to use. Essentially it just
does the emit_stop_by_name() on your behalf.


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