This is the mail archive of the cygwin-xfree@cygwin.com mailing list for the Cygwin XFree86 project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: AltGR problems with Windows XP


Andreas,

Interesting. I think you may have found the reason (and solution) for why a select few users with non-U.S. keyboard layouts are still having problems with fake Control_L presses and releases.

I appreciate the FSM state transition table, but could you give me a few sentences describing how the new code detects the fake Control_L presses and releases? That will make it a little easier for me to understand your table.

Thanks for the patch,

Harold

Andreas Schessner wrote:

Hello,

I use the X server of Cygwin/XFree86 (XWin) and it is working fine on my
Windows 2000 Workstation but
running the same version on my Notebook (Windows XP) causes problems
with the AltGr handling.

I've noticed that pressing the AltGr Key produces a
KeyPress-Control_L
KeyPress-Mode_switch
KeyRelease-Control_L
KeyRelease-Mode_switch
event sequence (see xev output at the end of this mail).

I began to trace the code (winkeybd.c, function winIsFakeCtrl_L) and
found out that on my XP notebook the windows messages VK_CONTROL (the
faked Control_L) and VK_MENU don't have the same timestamp and it is not
always possible to get the following VK_MENU message by issuing the
PeekMessage().

I don't know if this problem is relating to my Notebook (Dell Latitude)
or to Windows XP. Are there other people having the same problems?

Andreas


PS.
For now I've implemented a workarround. I'm using a translation of the
incomming windows messages, which recognizes the fake Control_L messages
and filters them out.
Changes were made on following sources: win.h, winkeybd.c, winwndproc.c
The modified sources can be obtained from mee if desired:
This works fine for me...


The algorithm is desccribed below as a deterministic finite automata (DFA)

input \ state | 0 (start) | 1 | 2 | 3
--------------------------------------------------------------------------------
KeyPressed-CtrlL (PCL) | 1 - | 1 - | 2 PCL | 1 -
KeyReleased-CtrlL (RCL) | 0 RCL | 0 PCL,RCL | 3 - | 0 RCL
KeyPressed-AltR (PAR) | 0 PAR | 2 PAR | 2 PAR | 0 PAR
KeyReleased-AltR (RAR) | 0 RAR | 0 PCL,RAR | 1 RAR | 0 RAR any other key (*) | 0 * | 0 PCL,* | 2 * | 0 *

States:
0 (start),1,2,3
input and output alphabet:
KeyPressed-CtrlL (PCL), KeyReleased-CtrlL (RCL),
KeyPressed-AltR (PAR), KeyReleased-AltR (RAR),
no key (-), any other key(*)

the table shows the transitions:
<new-state> <output>

e.g. assume you are in state "1" and you receive a KeyReleased-CtrlL message
then the new state of the DFA would be "0" and the events for
KeyPressed-CtrlL and KeyReleased-CtrlL
are sent to the XWin X-Server.


Implementation:
=========================================================

void winProcessKeyEvent (DWORD dwVirtualKey, DWORD dwKeyData)
{
static int iState = 0; /* initial State of DFA */
static int iCtrlCode = 0; /* initialized when first pressed... */

Bool fDown = ((dwKeyData & 0x80000000) == 0);
Bool fExt = ((HIWORD(dwKeyData) & KF_EXTENDED) != 0);
int iPreKeyCode = XK_VoidSymbol;

Bool fCtrlUp, fCtrlDown, fMenuUp, fMenuDown;
int iKeyCode, i;


winTranslateKey (dwVirtualKey, dwKeyData, &iKeyCode);

/*
* determine the input for the DFA
* (we use boolean indicators instead of an real alphabet)
*/
fCtrlUp = fCtrlDown = fMenuUp = fMenuDown = FALSE;

if (dwVirtualKey == VK_CONTROL) {
iCtrlCode = iKeyCode; /* save the scan code for VK_CONTROL */
if (fDown) fCtrlDown=TRUE;
else fCtrlUp =TRUE;
}
else if (dwVirtualKey == VK_MENU && fExt) {
if (fDown) fMenuDown=TRUE;
else fMenuUp =TRUE;
}

#if CYGDEBUG
ErrorF("winProcessKeyEvent: 0x%0x, 0x%0x\n",dwVirtualKey,dwKeyData);
ErrorF("State=%d Input=0x%0x (%s) ",iState,dwVirtualKey,(fDown?"DOWN":"UP"));
#endif

switch (iState) {

default:
case 0 :
if (fCtrlDown) { iState=1; iKeyCode=XK_VoidSymbol; }
else { iState=0; }
break;


case 1 :
if (fCtrlDown) { iState=1; }
else if (fMenuDown) { iState=2; }
else { iState=0; iPreKeyCode=iCtrlCode; }
break;


case 2 :
if (fCtrlUp) { iState=3; }
else if (fMenuUp) { iState=1; }
else { iState=2; }
break;

case 3 :
if (fCtrlDown) { iState=1; iKeyCode=XK_VoidSymbol; }
else { iState=0; }
break;

}

#if CYGDEBUG
ErrorF(" -> State=%d", iState);
if (iPreKeyCode != XK_VoidSymbol) ErrorF(" 0x%0x [0x0],",iPreKeyCode);
ErrorF(" 0x%0x [0x%0x]\n",iKeyCode,dwKeyData);
#endif

if (iPreKeyCode != XK_VoidSymbol)
winSendKeyEvent(iPreKeyCode,TRUE);

if (iKeyCode != XK_VoidSymbol)
for (i = 0; i < LOWORD(dwKeyData); ++i)
winSendKeyEvent(iKeyCode, (dwKeyData & 0x80000000)==0);

}


Output of xev with the original XWin:
=========================================================
KeyPress event, serial 22, synthetic NO, window 0xa00001,
root 0x36, subw 0xa00002, time 249118172, (38,43), root:(591,66),
state 0x0, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
XLookupString gives 0 characters: ""

KeyPress event, serial 22, synthetic NO, window 0xa00001,
root 0x36, subw 0xa00002, time 249118172, (38,43), root:(591,66),
state 0x4, keycode 113 (keysym 0xff7e, Mode_switch), same_screen YES,
XLookupString gives 0 characters: ""

KeyRelease event, serial 22, synthetic NO, window 0xa00001,
root 0x36, subw 0xa00002, time 249118303, (38,43), root:(591,66),
state 0x2004, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
XLookupString gives 0 characters: ""

KeyRelease event, serial 22, synthetic NO, window 0xa00001,
root 0x36, subw 0xa00002, time 249118303, (38,43), root:(591,66),
state 0x2000, keycode 113 (keysym 0xff7e, Mode_switch), same_screen YES,
XLookupString gives 0 characters: ""

KeyPress event, serial 22, synthetic NO, window 0xa00001,
root 0x36, subw 0xa00002, time 249119024, (38,43), root:(591,66),
state 0x0, keycode 38 (keysym 0x61, a), same_screen YES,
XLookupString gives 1 characters: "a"

....

KeyPress event, serial 22, synthetic NO, window 0xa00001,
root 0x36, subw 0xa00002, time 249131181, (38,43), root:(591,66),
state 0x0, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
XLookupString gives 0 characters: ""

KeyPress event, serial 22, synthetic NO, window 0xa00001,
root 0x36, subw 0xa00002, time 249131191, (38,43), root:(591,66),
state 0x4, keycode 113 (keysym 0xff7e, Mode_switch), same_screen YES,
XLookupString gives 0 characters: ""

KeyRelease event, serial 22, synthetic NO, window 0xa00001,
root 0x36, subw 0xa00002, time 249131381, (38,43), root:(591,66),
state 0x2004, keycode 113 (keysym 0xff7e, Mode_switch), same_screen YES,
XLookupString gives 0 characters: ""

KeyPress event, serial 22, synthetic NO, window 0xa00001,
root 0x36, subw 0xa00002, time 249132383, (38,43), root:(591,66),
state 0x4, keycode 38 (keysym 0x61, a), same_screen YES,
XLookupString gives 1 characters: ""









Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]