GNOME Bugzilla – Bug 119888
Calculator does respond to key press
Last modified: 2004-12-22 21:47:04 UTC
Hi Rich, While using gcalctool, I discovered it's possible for it to ignore key press events. Here are the steps that cause the strange behaivor. 1. Lanuch Calculator in Basic Mode. 2. Type: Alt-V (to select the view menu) 3. Type: s (to select the scientific mode) 4. Type: 0,1,2,3,4,5,6,7,8, or 9 (gcaltool ignores them) I am teaching a class this afternoon and won't have time to investigate until tonight. Thanks, Dennis
Hi Dennis. Here's what's happening. I added the following two lines of debug at the beginning of kframe_key_press_cb and kframe_key_release_cb: Index: gtk.c =================================================================== RCS file: /cvs/gnome/gcalctool/gcalctool/gtk.c,v retrieving revision 1.97 diff -u -r1.97 gtk.c --- gtk.c 14 Aug 2003 14:39:53 -0000 1.97 +++ gtk.c 14 Aug 2003 18:05:38 -0000 @@ -1357,6 +1357,9 @@ GtkWidget *focus; int retval = FALSE; +/**/fprintf(stderr, "press cb: keyval: %d modetype: %d\n", event->keyval, v->modetype); +/**/fprintf(stderr, "press cb: alt_l: %d alt_r: %d ctrl_l: %d ctrl_r: %d shft_l: %d shft_r: %d\n", X->alt_l, X->alt_r, X->ctrl_l, X->ctrl_r, X->shft_l, X->shft_r); + if (event->keyval == GDK_Alt_L) { X->alt_l = TRUE; return(TRUE); @@ -1415,6 +1418,8 @@ static gboolean kframe_key_release_cb(GtkWidget *widget, GdkEventKey *event, gpointer data) { +/**/fprintf(stderr, "release cb: keyval: %d modetype: %d\n", event->keyval, v->modetype); +/**/fprintf(stderr, "release cb: alt_l: %d alt_r: %d ctrl_l: %d ctrl_r: %d shft_l: %d shft_r: %d\n", X->alt_l, X->alt_r, X->ctrl_l, X->ctrl_r, X->shft_l, X->shft_r); if (event->keyval == GDK_Alt_L) { X->alt_l = FALSE; return(TRUE); These two routines adjust various flags in the X struct (alt_l, alt_r, ctrl_l, ctrl_r, shft_l, shft_r) on receipt of Alt/Ctrl/Shift key press and release events. When I run gcalctool and performs the steps you gave, I get: % ./gcalctool press cb: keyval: 65513 modetype: 0 press cb: alt_l: 0 alt_r: 0 ctrl_l: 0 ctrl_r: 0 shft_l: 0 shft_r: 0 press cb: keyval: 118 modetype: 0 press cb: alt_l: 1 alt_r: 0 ctrl_l: 0 ctrl_r: 0 shft_l: 0 shft_r: 0 release cb: keyval: 115 modetype: 2 release cb: alt_l: 1 alt_r: 0 ctrl_l: 0 ctrl_r: 0 shft_l: 0 shft_r: 0 press cb: keyval: 49 modetype: 2 press cb: alt_l: 1 alt_r: 0 ctrl_l: 0 ctrl_r: 0 shft_l: 0 shft_r: 0 release cb: keyval: 49 modetype: 2 release cb: alt_l: 1 alt_r: 0 ctrl_l: 0 ctrl_r: 0 shft_l: 0 shft_r: 0 So what I'm reading here is that I get a left Alt key press event which sets X->alt_l but I don't get a corresponding left Alt key release event that would allow me to clear the flag. So when you then type 1, the testing logic still thinks the left Alt key is down. A workaround is to press/release the left Alt key, and the calculator starts functioning properly again. I've cc:'ed Owen on this one for his take on this. Am I misunderstanding how menu keyboard accelerators like Alt v work here or should there be a corresponding Alt key release event generated?
No, key events are not guaranteed to be paired. By the time the menu pops up, the keyboard is grabbed, and the release will be delivered to the menu. You should be able to trigger the same bug, by pressing the alt key, clicking on another window to focus it, and then releasing the alt key. Why are you trying to track modifier state by watching key press/release events? Can't you just look at event->state?
Yes I probably can. I didn't realise it was there. Thanks! Lemme see if I can cons up a patch...
Created attachment 19225 [details] Proposed fix.
Well I do like a fix where you can take a load of crappy code out and replace it with something that is simpler and cleaner. Dennis, could you give the attached patch a try please? If it fixes the problem (and doesn't break anything else), feel free to check it in. I'm away for a long weekend later today, so I won't be able to do it until Monday morning at the earliest. Thanks.
Rich, The patch breaks keyboard input when the num lock key is set. For example, set the num lock key then type "1" from either the keyboard or numeric keypad and the key press event is ignored. After a little research, the problem is in check_vals(). When the num lock is set, the value of state is 16. See below for the code change that corrected this problem on my RH9 machine. I will not apply the patch to CVS. I would rather wait until Monday as I am unsure of the logic behind a state of 16, and I do not see it documented in gtk+. Thanks, Dennis @@ -1331,15 +1321,13 @@ j = 0; while (buttons[i].value[j] != 0) { if (buttons[i].value[j] == keyval) { - if ((buttons[i].mods[j] == 0) && - ((X->alt_l | X->alt_r | X->ctrl_l | - X->ctrl_r | X->shft_l | X->shft_r) == 0)) { + if ((buttons[i].mods[j] == 0) && + (state == 0 || state == 16)) { DO_KEY_PRESS(i);
Hi Dennis. Well if I've got my shifting correct, 16 is GDK_MOD2_MASK in the GdkModifierType enum in gdktypes.h, so I'll adjust to use that (and add a comment accordingly to show that it means NumLock). I'll also try it out on Solaris on Monday to make sure they don't do something funkily different there. Thanks!
The NumLock mapping is *not* standardized. You really want to mask in the mods you care about, not mask out the ones you don't care about. E.g.: relevant_state = event_state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK); if (relevant_state == GDK_MOD1_MASK) { /* Do stuff that applies only to Alt and not Alt+Control */ } Of course, you can generally just write: if ((event_state & GDK_MOD1_MASK) != 0) { } gtk_accelerator_get_default_mod_mask() gives you the modifiers that GTK+ cares about (the above three currently), but (without looking at the details of what you are doing), I doubt there is an advantage to using it.
Thanks Owen. I have enough now to rework this. Dennis, I'll do it first thing tomorrow morning and try it out on Solaris. I'll attach it to the bug for you to try. When you give the okay on it, I'll check it into CVS HEAD.
Created attachment 19308 [details] Second version of proposed patch to fix this.
Using the approach Owen suggested, I think the fix is even cleaner. I say "I think" because I've suddenly got a return of the funky keysym vals for my numeric keypad again on my Solaris S9U3 system. Dennis, could you try the second rev. of the patch (already attached), and let me know if this works for you please? Thanks.
Rich, Good morning. This patch works fine on my linux box, and the code looks better too. ;-) Thanks, Dennis
Agreed. Changes checked in (fixed in gcalctool v4.3.2). Thanks Dennis/Owen.