Hi, I've been debugging a very strange keyboard problem this afternoon: In some cases the key combination AltGr+2 produces "2" (wrong) rather than "@" (correct), when using a Swedish layout. The problem seems to be a race condition: If a KeyEvent occurs almost directly after the "2" key is pressed, the AltGr state is incorrect. The problem has been verified with this simple test program:
/* gcc -Wall xfake.c -o xfake -L/usr/X11R6/lib -lX11 -lXtst */
#include <X11/Xlib.h> #include <X11/extensions/XTest.h>
int main( int argc, char* argv[] ) { Display* dpy; dpy = XOpenDisplay( NULL ); XTestFakeKeyEvent(dpy, 0x71, True, CurrentTime); XTestFakeKeyEvent(dpy, 0xb, True, CurrentTime); XSync(dpy, False); //sleep(1); XTestFakeKeyEvent(dpy, 0x71, False, CurrentTime); XTestFakeKeyEvent(dpy, 0xb, False, CurrentTime); XCloseDisplay( dpy ); return 0; }
(0x71 is Mode_Switch, 0xb is the "2" key). I'm executing the program while having Wines Notepad active. If the sleep() is commented out, a "2" is inserted into Notepad. If the sleep() is active, "@" is inserted.
More evidence: When debugging with WINEDEBUG=keyboard,key, the traces for X11DRV_ToUnicodeEx is printed after the Mode_Switch KeyRelease trace.
Now I wonder, is this a problem with:
1) Wine or 2) The Windows API or 3) The way I'm using X11/the keyboard (generating events that quickly).
? I do understand why this happens: X11DRV_ToUnicodeEx uses the global, static variable AltGrMask. Is this a bug?
Regards,
"Peter Åstrand" astrand@cendio.se wrote:
? I do understand why this happens: X11DRV_ToUnicodeEx uses the global, static variable AltGrMask. Is this a bug?
In X11DRV_ToUnicodeEx we need to restore XKeyEvent from the previous KeyPress event. If you have a better idea how to do it without using global variables please let us know.
On Fri, 24 Mar 2006, Dmitry Timoshkov wrote:
? I do understand why this happens: X11DRV_ToUnicodeEx uses the global, static variable AltGrMask. Is this a bug?
In X11DRV_ToUnicodeEx we need to restore XKeyEvent from the previous KeyPress event. If you have a better idea how to do it without using global variables please let us know.
What about using the thread_input->keystate, just as for Shift, Control, and NumLock?
ToUnicodeEx does have a lpKeyState argument, so to me, it seems very wrong that a static, global variable is needed as well.
TranslateMessage calls GetKeyboardState just before ToUnicode. MSDN documents GetKeyboardState as: "The status changes as a thread removes keyboard messages from its message queue." My interpretation is that this means that ToUnicodeEx consider how the modifiers *was* rather then what they *are*.
The current implementation has another drawback: AltGr key presses never reaches the applications. In Windows, applications recieves VK_CONTROL, VK_MENU when AltGr is pressed.
"Peter Åstrand" astrand@cendio.se wrote:
What about using the thread_input->keystate, just as for Shift, Control, and NumLock?
ToUnicodeEx does have a lpKeyState argument, so to me, it seems very wrong that a static, global variable is needed as well.
I don't see how a thread local keystate would solve a problem with 2 repetitive KeyPress events you reported initially as being the source of the problem.
The current implementation has another drawback: AltGr key presses never reaches the applications. In Windows, applications recieves VK_CONTROL, VK_MENU when AltGr is pressed.
Feel free to investigate it.