Re: [gtk-list] Preventing Up/Down Arrows from Moving Focus

On Thu, 27 May 1999, Melissa Danforth wrote:
> Within an entry widget, pressing the up/down arrow keys causes the focus
> to shift to the next/previous widget. I have an application where I do not
> want this to occur. I noticed that within the text widget, using the up
> and down arrow keys does not cause the focus to move, but even after looking
> at the source, I cannot find how it does that.
> How does one prevent the up/down arrows from shifting the focus? 
> For my application, it is probably sufficient to just allow the mouse
> to change the focus.

It is a bit tricky; there are really lots of ways to do it. The key to
understanding what's going on is to look at gtk_widget_key_press_event() 
in gtkwindow.c.

All key press events originate on a GtkWindow. The GtkWindow maintains a
concept of "focus widget," and forwards events to the focus widget. So if
you look at that function, you'll see that if the focus widget key press
event emission returns TRUE, then the window does not go on to move the
focus widget around. Also, if there is a keyboard accelerator for the key,
the focus doesn't move. So there are two ways to make the focus not move,
by "handling" the event before the window gets around to it.

I don't know which Owen and Tim would suggest as the "official" way. 

Now, there's a trick to making the entry's key press event handler return
TRUE. Because key_press_event is a GTK_RUN_LAST signal (look in
gtk_widget_class_init() to see where it's registered as GTK_RUN_LAST), 
the default handler runs *after* callbacks connected with
gtk_signal_connect(). Which means that even if you gtk_signal_connect() a
handler that returns TRUE, the GtkEntry default handler will return FALSE
for the arrow keys, and you'll have gotten nowhere.

So, to work around this, you need to connect a handler with
gtk_signal_connect_after(); these handlers run *after* the default
handler, even if the default handler is GTK_RUN_LAST. This handler should
look like this:

gint my_key_press_handler(GtkWidget* entry, GdkEventKey* keyevent,
                          gpointer data)
 if (keyevent->keyval == GDK_Up)
   return TRUE;

plus whatever else you want it to do, of course.

A final way to approach the problem is to subclass GtkEntry, creating a
new widget, and override the default key event handler. This may well be
the cleanest solution.

Note that I haven't actually tried any of this, but it sounds pretty good.


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