keyboard patch
Andreas Mohr
andi at rhlx01.fht-esslingen.de
Sun Aug 4 11:49:24 CDT 2002
Hi all,
- make int09 update the BIOS data segment's keyboard status flags bytes
- implement pause key handling
- let int16/02 read the keyboard status flags bytes instead of calling
GetAsyncKeyState()
- make the keyboard state buffer used for Get*Key*() reflect VK_L/RMENU
properly (WM_KEYUP only handles WM_MENU, but Get*Key*() has more
detailed output !)
- small fixes
This patch *finally* makes Alt-x key combos work properly in IDA :-)
(menu invocation and special functions)
--
Andreas Mohr Stauferstr. 6, D-71272 Renningen, Germany
-------------- next part --------------
Determining best CVS host...
Using CVSROOT :pserver:cvs at rhlx01.fht-esslingen.de:/home/wine
Index: dlls/winedos/dosvm.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/dosvm.c,v
retrieving revision 1.20
diff -u -r1.20 dosvm.c
--- dlls/winedos/dosvm.c 10 Jul 2002 23:22:29 -0000 1.20
+++ dlls/winedos/dosvm.c 4 Aug 2002 16:42:06 -0000
@@ -235,12 +235,16 @@
{
INPUT_RECORD msg;
DWORD res;
- BYTE scan;
+ BYTE scan, ascii;
if (ReadConsoleInputA(GetStdHandle(STD_INPUT_HANDLE),&msg,1,&res)) {
switch (msg.EventType) {
case KEY_EVENT:
scan = msg.Event.KeyEvent.wVirtualScanCode;
+ ascii = msg.Event.KeyEvent.uChar.AsciiChar;
+ TRACE("scan %02x, ascii %02x\n", scan, ascii);
+
+ /* set the "break" (release) flag if key released */
if (!msg.Event.KeyEvent.bKeyDown) scan |= 0x80;
/* check whether extended bit is set,
@@ -248,7 +252,7 @@
if (msg.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY) {
DOSVM_Int09SendScan(0xE0,0);
}
- DOSVM_Int09SendScan(scan,msg.Event.KeyEvent.uChar.AsciiChar);
+ DOSVM_Int09SendScan(scan, ascii);
break;
case MOUSE_EVENT:
DOSVM_Int33Console(&msg.Event.MouseEvent);
Index: dlls/winedos/int09.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/int09.c,v
retrieving revision 1.4
diff -u -r1.4 int09.c
--- dlls/winedos/int09.c 9 Mar 2002 23:44:32 -0000 1.4
+++ dlls/winedos/int09.c 4 Aug 2002 16:42:06 -0000
@@ -39,24 +39,158 @@
} kbdinfo;
+/*
+ * Update the BIOS data segment's keyboard status flags (mem 0x40:0x17/0x18)
+ * if modifier/special keys have been pressed.
+ * FIXME: we merely toggle key status and don't actively set it instead,
+ * so we might be out of sync with the real current system status of these keys.
+ * Probably doesn't matter too much, though.
+ */
+void DOSVM_Int09UpdateKbdStatusFlags(BYTE scan, BOOL extended, BIOSDATA *data, BOOL *modifier)
+{
+ BYTE realscan = scan & 0x7f; /* remove 0x80 make/break flag */
+ BYTE bit1 = 255, bit2 = 255;
+ INPUT_RECORD msg;
+ DWORD res;
+
+ *modifier = TRUE;
+
+ switch (realscan)
+ {
+ case 0x36: /* r shift */
+ bit1 = 0;
+ break;
+ case 0x2a: /* l shift */
+ bit1 = 1;
+ break;
+ case 0x1d: /* l/r control */
+ bit1 = 2;
+ if (!extended) /* left control only */
+ bit2 = 0;
+ break;
+ case 0x37: /* SysRq inner parts */
+ /* SysRq scan code sequence: 38, e0, 37, e0, b7, b8 */
+ FIXME("SysRq not handled yet.\n");
+ break;
+ case 0x38: /* l/r menu/alt, SysRq outer parts */
+ bit1 = 3;
+ if (!extended) /* left alt only */
+ bit2 = 1;
+ break;
+ case 0x46: /* scroll lock */
+ bit1 = 4;
+ if (!extended) /* left ctrl only */
+ bit2 = 4;
+ break;
+ case 0x45: /* num lock, pause */
+ if (extended) /* distinguish from non-extended Pause key */
+ { /* num lock */
+ bit1 = 5;
+ bit2 = 5;
+ }
+ else
+ { /* pause */
+ if (!(scan & 0x80)) /* "make" code */
+ bit2 = 3;
+ }
+ break;
+ case 0x3a: /* caps lock */
+ bit1 = 6;
+ bit2 = 6;
+ break;
+ case 0x52: /* insert */
+ bit1 = 7;
+ bit2 = 7;
+ *modifier = FALSE; /* insert is no modifier: thus pass to int16 */
+ break;
+ }
+ /* now that we know which bits to set, update them */
+ if (!(scan & 0x80)) /* "make" code (keypress) */
+ {
+ if (bit2 != 255)
+ {
+ if (bit2 == 3)
+ {
+ data->KbdFlags2 |= 1 << bit2; /* set "Pause" flag */
+ TRACE("PAUSE key, sleeping !\n");
+ /* wait for keypress to unlock pause */
+ do {
+ Sleep(55);
+ } while (!(ReadConsoleInputA(GetStdHandle(STD_INPUT_HANDLE),&msg,1,&res) && (msg.EventType == KEY_EVENT)));
+ data->KbdFlags2 &= ~(1 << bit2); /* release "Pause" flag */
+ }
+ else
+ data->KbdFlags2 |= 1 << bit2;
+ }
+ if (bit1 != 255)
+ {
+ if (bit1 < 4) /* key "pressed" flag */
+ data->KbdFlags1 |= 1 << bit1;
+ else /* key "active" flag */
+ data->KbdFlags1 ^= 1 << bit1;
+ }
+ }
+ else /* "break" / release */
+ {
+ if (bit2 != 255)
+ data->KbdFlags2 &= ~(1 << bit2);
+ if (bit1 < 4) /* is it a key "pressed" bit ? */
+ data->KbdFlags1 &= ~(1 << bit1);
+ }
+ TRACE("ext. %d, bits %d/%d, KbdFlags %02x/%02x\n", extended, bit1, bit2, data->KbdFlags1, data->KbdFlags2);
+}
+
/**********************************************************************
* DOSVM_Int09Handler
*
* Handler for int 09h.
+ * See http://www.execpc.com/~geezer/osd/kbd/ for a very good description
+ * of keyboard mapping modes.
*/
void WINAPI DOSVM_Int09Handler( CONTEXT86 *context )
{
+ BIOSDATA *data = DOSMEM_BiosData();
BYTE ascii, scan = DOSVM_Int09ReadScan(&ascii);
+ BYTE realscan = scan & 0x7f; /* remove 0x80 make/break flag */
+ BOOL modifier = FALSE;
+ static BOOL extended = FALSE; /* indicates start of extended key sequence */
BYTE ch[2];
int cnt, c2;
- TRACE("scan=%02x\n",scan);
- if (!(scan & 0x80)) {
+ TRACE("scan=%02x, ascii=%02x[%c]\n",scan, ascii, ascii ? ascii : ' ');
+
+ if (scan == 0xe0) /* extended keycode */
+ extended = TRUE;
+
+ /* check for keys concerning keyboard status flags */
+ if ((realscan == 0x52 /* insert */)
+ || (realscan == 0x3a /* caps lock */)
+ || (realscan == 0x45 /* num lock (extended) or pause/break */)
+ || (realscan == 0x46 /* scroll lock */)
+ || (realscan == 0x2a /* l shift */)
+ || (realscan == 0x36 /* r shift */)
+ || (realscan == 0x37 /* SysRq */)
+ || (realscan == 0x38 /* l/r menu/alt, SysRq */)
+ || (realscan == 0x1d /* l/r control */))
+ DOSVM_Int09UpdateKbdStatusFlags(scan, extended, data, &modifier);
+
+ if (scan != 0xe0)
+ extended = FALSE; /* reset extended flag now */
+
+ /* only interested in "make" (press) codes, not "break" (release),
+ * and also not in "modifier key only" (w/o ascii) notifications */
+ if (!(scan & 0x80) && !(modifier && !ascii))
+ {
if (ascii) {
/* we already have an ASCII code, no translation necessary */
- ch[0] = ascii;
+ if (data->KbdFlags1 & 8) /* Alt key ? */
+ ch[0] = 0; /* ASCII code needs to be 0 if Alt also pressed */
+ else
+ ch[0] = ascii;
+ /* FIXME: need to handle things such as Shift-F1 etc. */
cnt = 1;
} else {
+ /* translate */
UINT vkey = MapVirtualKeyA(scan&0x7f, 1);
BYTE keystate[256];
GetKeyboardState(keystate);
Index: dlls/winedos/int16.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/int16.c,v
retrieving revision 1.4
diff -u -r1.4 int16.c
--- dlls/winedos/int16.c 3 Jul 2002 01:13:34 -0000 1.4
+++ dlls/winedos/int16.c 4 Aug 2002 16:42:06 -0000
@@ -49,6 +49,8 @@
void WINAPI DOSVM_Int16Handler( CONTEXT86 *context )
{
+ BIOSDATA *data = NULL;
+
switch AH_reg(context) {
case 0x00: /* Get Keystroke */
@@ -77,24 +79,11 @@
break;
case 0x02: /* Get Shift Flags */
- AL_reg(context) = 0;
-
- if (GetAsyncKeyState(VK_RSHIFT))
- AL_reg(context) |= 0x01;
- if (GetAsyncKeyState(VK_LSHIFT))
- AL_reg(context) |= 0x02;
- if (GetAsyncKeyState(VK_LCONTROL) || GetAsyncKeyState(VK_RCONTROL))
- AL_reg(context) |= 0x04;
- if (GetAsyncKeyState(VK_LMENU) || GetAsyncKeyState(VK_RMENU))
- AL_reg(context) |= 0x08;
- if (GetAsyncKeyState(VK_SCROLL))
- AL_reg(context) |= 0x10;
- if (GetAsyncKeyState(VK_NUMLOCK))
- AL_reg(context) |= 0x20;
- if (GetAsyncKeyState(VK_CAPITAL))
- AL_reg(context) |= 0x40;
- if (GetAsyncKeyState(VK_INSERT))
- AL_reg(context) |= 0x80;
+
+ /* read value from BIOS data segment's keyboard status flags field */
+ data = DOSMEM_BiosData();
+ AL_reg(context) = data->KbdFlags1;
+
TRACE("Get Shift Flags: returning 0x%02x\n", AL_reg(context));
break;
Index: dlls/x11drv/keyboard.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/keyboard.c,v
retrieving revision 1.6
diff -u -r1.6 keyboard.c
--- dlls/x11drv/keyboard.c 22 Jun 2002 01:10:37 -0000 1.6
+++ dlls/x11drv/keyboard.c 4 Aug 2002 16:42:07 -0000
@@ -923,12 +923,12 @@
TRACE_(key)("state = %X\n", event->state);
- /* If XKB extensions is used, the state mask for AltGr will used the group
+ /* If XKB extensions is used, the state mask for AltGr will use the group
index instead of the modifier mask. The group index is set in bits
13-14 of the state field in the XKeyEvent structure. So if AltGr is
- pressed, look if the group index is diferent than 0. From XKB
- extension documentation, the group index should for AltGr should
- be 2 (event->state = 0x2000). It's probably better to not assume a
+ pressed, look if the group index is different than 0. From XKB
+ extension documentation, the group index for AltGr should be 2
+ (event->state = 0x2000). It's probably better to not assume a
predefined group index and find it dynamically
Ref: X Keyboard Extension: Library specification (section 14.1.1 and 17.1.1) */
@@ -1333,7 +1333,7 @@
keycode = TSXKeysymToKeycode(display, keysym | 0xFE00);
}
- TRACE("VkKeyScan '%c'(%#lx, %lu): got keycode %#.2x\n",
+ TRACE("'%c'(%#lx, %lu): got keycode %#.2x\n",
cChar,keysym,keysym,keycode);
if (keycode)
@@ -1370,7 +1370,7 @@
#define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; }
- TRACE("MapVirtualKey wCode=0x%x wMapType=%d ... \n", wCode,wMapType);
+ TRACE("wCode=0x%x wMapType=%d ... \n", wCode,wMapType);
switch(wMapType) {
case 0: { /* vkey-code to scan-code */
/* let's do vkey -> keycode -> scan */
@@ -1756,7 +1756,7 @@
}
/* more areas where X returns characters but Windows does not
- CTRL + number or CTRL + symbol*/
+ CTRL + number or CTRL + symbol */
if (e.state & ControlMask)
{
if (((keysym>=33) && (keysym < 'A')) ||
Index: programs/wineconsole/user.c
===================================================================
RCS file: /home/wine/wine/programs/wineconsole/user.c,v
retrieving revision 1.15
diff -u -r1.15 user.c
--- programs/wineconsole/user.c 23 Jul 2002 02:02:46 -0000 1.15
+++ programs/wineconsole/user.c 4 Aug 2002 16:42:08 -0000
@@ -876,7 +876,7 @@
}
/******************************************************************
- * CUSER_GetCtrlKeyState
+ * WCUSER_GetCtrlKeyState
*
* Get the console bit mask equivalent to the VK_ status in keyState
*/
@@ -886,7 +886,6 @@
GetKeyboardState(keyState);
if (keyState[VK_SHIFT] & 0x80) ret |= SHIFT_PRESSED;
- if (keyState[VK_CONTROL] & 0x80) ret |= LEFT_CTRL_PRESSED; /* FIXME: gotta choose one */
if (keyState[VK_LCONTROL] & 0x80) ret |= LEFT_CTRL_PRESSED;
if (keyState[VK_RCONTROL] & 0x80) ret |= RIGHT_CTRL_PRESSED;
if (keyState[VK_LMENU] & 0x80) ret |= LEFT_ALT_PRESSED;
Index: windows/message.c
===================================================================
RCS file: /home/wine/wine/windows/message.c,v
retrieving revision 1.136
diff -u -r1.136 message.c
--- windows/message.c 1 Jul 2002 18:20:16 -0000 1.136
+++ windows/message.c 4 Aug 2002 16:42:09 -0000
@@ -131,9 +131,10 @@
/***********************************************************************
* update_queue_key_state
*/
-static void update_queue_key_state( UINT msg, WPARAM wp )
+static void update_queue_key_state( UINT msg, WPARAM wp, LPARAM lp )
{
- BOOL down = FALSE;
+ BOOL down = FALSE, iskey = FALSE;
+ WPARAM dualkey = 0;
switch (msg)
{
@@ -162,8 +163,25 @@
case WM_KEYUP:
case WM_SYSKEYUP:
wp = wp & 0xff;
+ iskey = TRUE;
break;
}
+ if (iskey)
+ {
+ switch(wp)
+ {
+ case VK_SHIFT:
+ dualkey = (HIWORD(lp) & KF_EXTENDED) ? VK_RSHIFT : VK_LSHIFT;
+ break;
+ case VK_CONTROL:
+ dualkey = (HIWORD(lp) & KF_EXTENDED) ? VK_RCONTROL : VK_LCONTROL;
+ break;
+ case VK_MENU:
+ dualkey = (HIWORD(lp) & KF_EXTENDED) ? VK_RMENU : VK_LMENU;
+ break;
+
+ }
+ }
if (down)
{
BYTE *p = &QueueKeyStateTable[wp];
@@ -171,6 +189,16 @@
*p |= 0x80;
}
else QueueKeyStateTable[wp] &= ~0x80;
+ if (dualkey)
+ { /* also update the "dual" keys properly */
+ if (down)
+ {
+ BYTE *p = &QueueKeyStateTable[dualkey];
+ if (!(*p & 0x80)) *p ^= 0x01;
+ *p |= 0x80;
+ }
+ else QueueKeyStateTable[dualkey] &= ~0x80;
+ }
}
@@ -325,7 +353,7 @@
}
/* if we are going to throw away the message, update the queue state now */
- if (!msg->hwnd) update_queue_key_state( msg->message, msg->wParam );
+ if (!msg->hwnd) update_queue_key_state( msg->message, msg->wParam, msg->lParam );
return (msg->hwnd != 0);
}
@@ -340,7 +368,7 @@
{
if (remove)
{
- update_queue_key_state( msg->message, msg->wParam );
+ update_queue_key_state( msg->message, msg->wParam, msg->lParam );
/* Handle F1 key by sending out WM_HELP message */
if ((msg->message == WM_KEYUP) &&
@@ -472,7 +500,7 @@
raw_message += WM_LBUTTONDOWN - WM_LBUTTONDBLCLK;
}
- if (remove) update_queue_key_state( raw_message, 0 );
+ if (remove) update_queue_key_state( raw_message, 0, 0 );
if (HOOK_IsHooked( WH_MOUSE ))
{
@@ -646,7 +674,7 @@
* GetKeyboardState (USER32.@)
*
* An application calls the GetKeyboardState function in response to a
- * keyboard-input message. This function retrieves the state of the keyboard
+ * keyboard input message. This function retrieves the state of the keyboard
* at the time the input message was generated. (SDK 3.1 Vol 2. p 387)
*/
BOOL WINAPI GetKeyboardState(LPBYTE lpKeyState)
More information about the wine-patches
mailing list