- 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. - Small fixes.
This commit is contained in:
parent
26a470e1f0
commit
90ce2c896f
|
@ -240,12 +240,16 @@ static void DOSVM_ProcessConsole(void)
|
|||
{
|
||||
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,
|
||||
|
@ -253,7 +257,7 @@ static void DOSVM_ProcessConsole(void)
|
|||
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);
|
||||
|
|
|
@ -39,24 +39,158 @@ static struct
|
|||
} 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 = BIOS_DATA;
|
||||
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);
|
||||
|
|
|
@ -51,7 +51,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(int);
|
|||
|
||||
void WINAPI DOSVM_Int16Handler( CONTEXT86 *context )
|
||||
{
|
||||
BYTE ascii, scan;
|
||||
BIOSDATA *data = NULL;
|
||||
BYTE ascii, scan;
|
||||
|
||||
switch AH_reg(context) {
|
||||
|
||||
case 0x00: /* Get Keystroke */
|
||||
|
@ -84,24 +86,11 @@ void WINAPI DOSVM_Int16Handler( CONTEXT86 *context )
|
|||
break;
|
||||
|
||||
case 0x02: /* Get Shift Flags */
|
||||
SET_AL( context, 0 );
|
||||
|
||||
if (GetAsyncKeyState(VK_RSHIFT))
|
||||
context->Eax |= 0x01;
|
||||
if (GetAsyncKeyState(VK_LSHIFT))
|
||||
context->Eax |= 0x02;
|
||||
if (GetAsyncKeyState(VK_LCONTROL) || GetAsyncKeyState(VK_RCONTROL))
|
||||
context->Eax |= 0x04;
|
||||
if (GetAsyncKeyState(VK_LMENU) || GetAsyncKeyState(VK_RMENU))
|
||||
context->Eax |= 0x08;
|
||||
if (GetAsyncKeyState(VK_SCROLL))
|
||||
context->Eax |= 0x10;
|
||||
if (GetAsyncKeyState(VK_NUMLOCK))
|
||||
context->Eax |= 0x20;
|
||||
if (GetAsyncKeyState(VK_CAPITAL))
|
||||
context->Eax |= 0x40;
|
||||
if (GetAsyncKeyState(VK_INSERT))
|
||||
context->Eax |= 0x80;
|
||||
/* read value from BIOS data segment's keyboard status flags field */
|
||||
data = BIOS_DATA;
|
||||
SET_AL( context, data->KbdFlags1 );
|
||||
|
||||
TRACE("Get Shift Flags: returning 0x%02x\n", AL_reg(context));
|
||||
break;
|
||||
|
||||
|
|
|
@ -874,7 +874,7 @@ static LRESULT WCUSER_Create(HWND hWnd, LPCREATESTRUCT lpcs)
|
|||
}
|
||||
|
||||
/******************************************************************
|
||||
* CUSER_GetCtrlKeyState
|
||||
* WCUSER_GetCtrlKeyState
|
||||
*
|
||||
* Get the console bit mask equivalent to the VK_ status in keyState
|
||||
*/
|
||||
|
@ -884,7 +884,6 @@ static DWORD WCUSER_GetCtrlKeyState(BYTE* keyState)
|
|||
|
||||
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;
|
||||
|
|
|
@ -134,9 +134,10 @@ static void queue_hardware_message( MSG *msg, ULONG_PTR extra_info, enum message
|
|||
/***********************************************************************
|
||||
* 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)
|
||||
{
|
||||
|
@ -165,8 +166,25 @@ static void update_queue_key_state( UINT msg, WPARAM wp )
|
|||
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];
|
||||
|
@ -174,6 +192,16 @@ static void update_queue_key_state( UINT msg, WPARAM wp )
|
|||
*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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -328,7 +356,7 @@ static BOOL process_raw_keyboard_message( MSG *msg, ULONG_PTR extra_info )
|
|||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
@ -343,7 +371,7 @@ static BOOL process_cooked_keyboard_message( MSG *msg, BOOL remove )
|
|||
{
|
||||
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) &&
|
||||
|
@ -483,7 +511,7 @@ static BOOL process_cooked_mouse_message( MSG *msg, ULONG_PTR extra_info, BOOL r
|
|||
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 ))
|
||||
{
|
||||
|
@ -662,7 +690,7 @@ SHORT WINAPI GetKeyState(INT vkey)
|
|||
* 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)
|
||||
|
|
Loading…
Reference in New Issue