winkeybd.c revision 6747b715
105b261ecSmrg/* 205b261ecSmrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 305b261ecSmrg * 405b261ecSmrg *Permission is hereby granted, free of charge, to any person obtaining 505b261ecSmrg * a copy of this software and associated documentation files (the 605b261ecSmrg *"Software"), to deal in the Software without restriction, including 705b261ecSmrg *without limitation the rights to use, copy, modify, merge, publish, 805b261ecSmrg *distribute, sublicense, and/or sell copies of the Software, and to 905b261ecSmrg *permit persons to whom the Software is furnished to do so, subject to 1005b261ecSmrg *the following conditions: 1105b261ecSmrg * 1205b261ecSmrg *The above copyright notice and this permission notice shall be 1305b261ecSmrg *included in all copies or substantial portions of the Software. 1405b261ecSmrg * 1505b261ecSmrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1605b261ecSmrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1705b261ecSmrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1805b261ecSmrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR 1905b261ecSmrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 2005b261ecSmrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2105b261ecSmrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2205b261ecSmrg * 2305b261ecSmrg *Except as contained in this notice, the name of the XFree86 Project 2405b261ecSmrg *shall not be used in advertising or otherwise to promote the sale, use 2505b261ecSmrg *or other dealings in this Software without prior written authorization 2605b261ecSmrg *from the XFree86 Project. 2705b261ecSmrg * 2805b261ecSmrg * Authors: Dakshinamurthy Karra 2905b261ecSmrg * Suhaib M Siddiqi 3005b261ecSmrg * Peter Busch 3105b261ecSmrg * Harold L Hunt II 3205b261ecSmrg */ 3305b261ecSmrg 3405b261ecSmrg 3505b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H 3605b261ecSmrg#include <xwin-config.h> 3705b261ecSmrg#endif 3805b261ecSmrg#include "win.h" 3905b261ecSmrg#include "winkeybd.h" 4005b261ecSmrg#include "winconfig.h" 4105b261ecSmrg#include "winmsg.h" 4205b261ecSmrg 436747b715Smrg#include "xkbsrv.h" 4405b261ecSmrg 4505b261ecSmrgstatic Bool g_winKeyState[NUM_KEYCODES]; 4605b261ecSmrg 4705b261ecSmrg/* 4805b261ecSmrg * Local prototypes 4905b261ecSmrg */ 5005b261ecSmrg 5105b261ecSmrgstatic void 5205b261ecSmrgwinKeybdBell (int iPercent, DeviceIntPtr pDeviceInt, 5305b261ecSmrg pointer pCtrl, int iClass); 5405b261ecSmrg 5505b261ecSmrgstatic void 5605b261ecSmrgwinKeybdCtrl (DeviceIntPtr pDevice, KeybdCtrl *pCtrl); 5705b261ecSmrg 5805b261ecSmrg 5905b261ecSmrg/* 6005b261ecSmrg * Translate a Windows WM_[SYS]KEY(UP/DOWN) message 6105b261ecSmrg * into an ASCII scan code. 6205b261ecSmrg * 6305b261ecSmrg * We do this ourselves, rather than letting Windows handle it, 6405b261ecSmrg * because Windows tends to munge the handling of special keys, 6505b261ecSmrg * like AltGr on European keyboards. 6605b261ecSmrg */ 6705b261ecSmrg 6805b261ecSmrgvoid 6905b261ecSmrgwinTranslateKey (WPARAM wParam, LPARAM lParam, int *piScanCode) 7005b261ecSmrg{ 7105b261ecSmrg int iKeyFixup = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 1]; 7205b261ecSmrg int iKeyFixupEx = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 2]; 736747b715Smrg int iParam = HIWORD (lParam); 746747b715Smrg int iParamScanCode = LOBYTE (iParam); 756747b715Smrg 766747b715Smrg/* WM_ key messages faked by Vista speech recognition (WSR) don't have a 776747b715Smrg * scan code. 786747b715Smrg * 796747b715Smrg * Vocola 3 (Rick Mohr's supplement to WSR) uses 806747b715Smrg * System.Windows.Forms.SendKeys.SendWait(), which appears always to give a 816747b715Smrg * scan code of 1 826747b715Smrg */ 836747b715Smrg if (iParamScanCode <= 1) 846747b715Smrg { 856747b715Smrg if (VK_PRIOR <= wParam && wParam <= VK_DOWN) 866747b715Smrg /* Trigger special case table to translate to extended 876747b715Smrg * keycode, otherwise if num_lock is on, we can get keypad 886747b715Smrg * numbers instead of navigation keys. */ 896747b715Smrg iParam |= KF_EXTENDED; 906747b715Smrg else 916747b715Smrg iParamScanCode = MapVirtualKeyEx(wParam, 926747b715Smrg /*MAPVK_VK_TO_VSC*/0, 936747b715Smrg GetKeyboardLayout(0)); 946747b715Smrg } 9505b261ecSmrg 9605b261ecSmrg /* Branch on special extended, special non-extended, or normal key */ 976747b715Smrg if ((iParam & KF_EXTENDED) && iKeyFixupEx) 9805b261ecSmrg *piScanCode = iKeyFixupEx; 9905b261ecSmrg else if (iKeyFixup) 10005b261ecSmrg *piScanCode = iKeyFixup; 10105b261ecSmrg else if (wParam == 0 && iParamScanCode == 0x70) 10205b261ecSmrg *piScanCode = KEY_HKTG; 10305b261ecSmrg else 10405b261ecSmrg switch (iParamScanCode) 10505b261ecSmrg { 10605b261ecSmrg case 0x70: 10705b261ecSmrg *piScanCode = KEY_HKTG; 10805b261ecSmrg break; 10905b261ecSmrg case 0x73: 11005b261ecSmrg *piScanCode = KEY_BSlash2; 11105b261ecSmrg break; 11205b261ecSmrg default: 11305b261ecSmrg *piScanCode = iParamScanCode; 11405b261ecSmrg break; 11505b261ecSmrg } 11605b261ecSmrg} 11705b261ecSmrg 11805b261ecSmrg 11905b261ecSmrg/* Ring the keyboard bell (system speaker on PCs) */ 12005b261ecSmrgstatic void 12105b261ecSmrgwinKeybdBell (int iPercent, DeviceIntPtr pDeviceInt, 12205b261ecSmrg pointer pCtrl, int iClass) 12305b261ecSmrg{ 12405b261ecSmrg /* 12505b261ecSmrg * We can't use Beep () here because it uses the PC speaker 12605b261ecSmrg * on NT/2000. MessageBeep (MB_OK) will play the default system 12705b261ecSmrg * sound on systems with a sound card or it will beep the PC speaker 12805b261ecSmrg * on systems that do not have a sound card. 12905b261ecSmrg */ 13005b261ecSmrg MessageBeep (MB_OK); 13105b261ecSmrg} 13205b261ecSmrg 13305b261ecSmrg 13405b261ecSmrg/* Change some keyboard configuration parameters */ 13505b261ecSmrgstatic void 13605b261ecSmrgwinKeybdCtrl (DeviceIntPtr pDevice, KeybdCtrl *pCtrl) 13705b261ecSmrg{ 13805b261ecSmrg} 13905b261ecSmrg 14005b261ecSmrg 14105b261ecSmrg/* 14205b261ecSmrg * See Porting Layer Definition - p. 18 14305b261ecSmrg * winKeybdProc is known as a DeviceProc. 14405b261ecSmrg */ 14505b261ecSmrg 14605b261ecSmrgint 14705b261ecSmrgwinKeybdProc (DeviceIntPtr pDeviceInt, int iState) 14805b261ecSmrg{ 14905b261ecSmrg DevicePtr pDevice = (DevicePtr) pDeviceInt; 15005b261ecSmrg XkbSrvInfoPtr xkbi; 15105b261ecSmrg XkbControlsPtr ctrl; 15205b261ecSmrg 15305b261ecSmrg switch (iState) 15405b261ecSmrg { 15505b261ecSmrg case DEVICE_INIT: 15605b261ecSmrg winConfigKeyboard (pDeviceInt); 15705b261ecSmrg 15805b261ecSmrg /* FIXME: Maybe we should use winGetKbdLeds () here? */ 15905b261ecSmrg defaultKeyboardControl.leds = g_winInfo.keyboard.leds; 16005b261ecSmrg 1616747b715Smrg winErrorFVerb(2, "Rules = \"%s\" Model = \"%s\" Layout = \"%s\"" 1626747b715Smrg " Variant = \"%s\" Options = \"%s\"\n", 1636747b715Smrg g_winInfo.xkb.rules ? g_winInfo.xkb.rules : "none", 1646747b715Smrg g_winInfo.xkb.model ? g_winInfo.xkb.model : "none", 1656747b715Smrg g_winInfo.xkb.layout ? g_winInfo.xkb.layout : "none", 1666747b715Smrg g_winInfo.xkb.variant ? g_winInfo.xkb.variant : "none", 1676747b715Smrg g_winInfo.xkb.options ? g_winInfo.xkb.options : "none"); 1686747b715Smrg 1696747b715Smrg InitKeyboardDeviceStruct (pDeviceInt, 1706747b715Smrg &g_winInfo.xkb, 1716747b715Smrg winKeybdBell, 1726747b715Smrg winKeybdCtrl); 1736747b715Smrg 1746747b715Smrg xkbi = pDeviceInt->key->xkbInfo; 1756747b715Smrg if ((xkbi != NULL) && (xkbi->desc != NULL)) 1766747b715Smrg { 1776747b715Smrg ctrl = xkbi->desc->ctrls; 1786747b715Smrg ctrl->repeat_delay = g_winInfo.keyboard.delay; 1796747b715Smrg ctrl->repeat_interval = 1000/g_winInfo.keyboard.rate; 1806747b715Smrg } 1816747b715Smrg else 1826747b715Smrg { 1836747b715Smrg winErrorFVerb (1, "winKeybdProc - Error initializing keyboard AutoRepeat\n"); 18405b261ecSmrg } 18505b261ecSmrg 18605b261ecSmrg break; 18705b261ecSmrg 18805b261ecSmrg case DEVICE_ON: 18905b261ecSmrg pDevice->on = TRUE; 1906747b715Smrg 1916747b715Smrg // immediately copy the state of this keyboard device to the VCK 1926747b715Smrg // (which otherwise happens lazily after the first keypress) 1936747b715Smrg CopyKeyClass(pDeviceInt, inputInfo.keyboard); 19405b261ecSmrg break; 19505b261ecSmrg 19605b261ecSmrg case DEVICE_CLOSE: 19705b261ecSmrg case DEVICE_OFF: 19805b261ecSmrg pDevice->on = FALSE; 19905b261ecSmrg break; 20005b261ecSmrg } 20105b261ecSmrg 20205b261ecSmrg return Success; 20305b261ecSmrg} 20405b261ecSmrg 20505b261ecSmrg 20605b261ecSmrg/* 20705b261ecSmrg * Detect current mode key states upon server startup. 20805b261ecSmrg * 20905b261ecSmrg * Simulate a press and release of any key that is currently 21005b261ecSmrg * toggled. 21105b261ecSmrg */ 21205b261ecSmrg 21305b261ecSmrgvoid 21405b261ecSmrgwinInitializeModeKeyStates (void) 21505b261ecSmrg{ 21605b261ecSmrg /* Restore NumLock */ 21705b261ecSmrg if (GetKeyState (VK_NUMLOCK) & 0x0001) 21805b261ecSmrg { 21905b261ecSmrg winSendKeyEvent (KEY_NumLock, TRUE); 22005b261ecSmrg winSendKeyEvent (KEY_NumLock, FALSE); 22105b261ecSmrg } 22205b261ecSmrg 22305b261ecSmrg /* Restore CapsLock */ 22405b261ecSmrg if (GetKeyState (VK_CAPITAL) & 0x0001) 22505b261ecSmrg { 22605b261ecSmrg winSendKeyEvent (KEY_CapsLock, TRUE); 22705b261ecSmrg winSendKeyEvent (KEY_CapsLock, FALSE); 22805b261ecSmrg } 22905b261ecSmrg 23005b261ecSmrg /* Restore ScrollLock */ 23105b261ecSmrg if (GetKeyState (VK_SCROLL) & 0x0001) 23205b261ecSmrg { 23305b261ecSmrg winSendKeyEvent (KEY_ScrollLock, TRUE); 23405b261ecSmrg winSendKeyEvent (KEY_ScrollLock, FALSE); 23505b261ecSmrg } 23605b261ecSmrg 23705b261ecSmrg /* Restore KanaLock */ 23805b261ecSmrg if (GetKeyState (VK_KANA) & 0x0001) 23905b261ecSmrg { 24005b261ecSmrg winSendKeyEvent (KEY_HKTG, TRUE); 24105b261ecSmrg winSendKeyEvent (KEY_HKTG, FALSE); 24205b261ecSmrg } 24305b261ecSmrg} 24405b261ecSmrg 24505b261ecSmrg 24605b261ecSmrg/* 24705b261ecSmrg * Upon regaining the keyboard focus we must 24805b261ecSmrg * resynchronize our internal mode key states 24905b261ecSmrg * with the actual state of the keys. 25005b261ecSmrg */ 25105b261ecSmrg 25205b261ecSmrgvoid 2536747b715SmrgwinRestoreModeKeyStates (void) 25405b261ecSmrg{ 25505b261ecSmrg DWORD dwKeyState; 25605b261ecSmrg BOOL processEvents = TRUE; 25705b261ecSmrg unsigned short internalKeyStates; 25805b261ecSmrg 25905b261ecSmrg /* X server is being initialized */ 2606747b715Smrg if (!inputInfo.keyboard) 26105b261ecSmrg return; 26205b261ecSmrg 26305b261ecSmrg /* Only process events if the rootwindow is mapped. The keyboard events 26405b261ecSmrg * will cause segfaults otherwise */ 2656747b715Smrg if (screenInfo.screens[0]->root && screenInfo.screens[0]->root->mapped == FALSE) 26605b261ecSmrg processEvents = FALSE; 26705b261ecSmrg 26805b261ecSmrg /* Force to process all pending events in the mi event queue */ 26905b261ecSmrg if (processEvents) 27005b261ecSmrg mieqProcessInputEvents (); 27105b261ecSmrg 27205b261ecSmrg /* Read the mode key states of our X server */ 2736747b715Smrg /* (stored in the virtual core keyboard) */ 2746747b715Smrg internalKeyStates = XkbStateFieldFromRec(&inputInfo.keyboard->key->xkbInfo->state); 2756747b715Smrg winDebug("winRestoreModeKeyStates: state %d\n", internalKeyStates); 27605b261ecSmrg 27705b261ecSmrg /* 27805b261ecSmrg * NOTE: The C XOR operator, ^, will not work here because it is 27905b261ecSmrg * a bitwise operator, not a logical operator. C does not 28005b261ecSmrg * have a logical XOR operator, so we use a macro instead. 28105b261ecSmrg */ 28205b261ecSmrg 28305b261ecSmrg /* Has the key state changed? */ 28405b261ecSmrg dwKeyState = GetKeyState (VK_NUMLOCK) & 0x0001; 28505b261ecSmrg if (WIN_XOR (internalKeyStates & NumLockMask, dwKeyState)) 28605b261ecSmrg { 28705b261ecSmrg winSendKeyEvent (KEY_NumLock, TRUE); 28805b261ecSmrg winSendKeyEvent (KEY_NumLock, FALSE); 28905b261ecSmrg } 29005b261ecSmrg 29105b261ecSmrg /* Has the key state changed? */ 29205b261ecSmrg dwKeyState = GetKeyState (VK_CAPITAL) & 0x0001; 29305b261ecSmrg if (WIN_XOR (internalKeyStates & LockMask, dwKeyState)) 29405b261ecSmrg { 29505b261ecSmrg winSendKeyEvent (KEY_CapsLock, TRUE); 29605b261ecSmrg winSendKeyEvent (KEY_CapsLock, FALSE); 29705b261ecSmrg } 29805b261ecSmrg 29905b261ecSmrg /* Has the key state changed? */ 30005b261ecSmrg dwKeyState = GetKeyState (VK_SCROLL) & 0x0001; 30105b261ecSmrg if (WIN_XOR (internalKeyStates & ScrollLockMask, dwKeyState)) 30205b261ecSmrg { 30305b261ecSmrg winSendKeyEvent (KEY_ScrollLock, TRUE); 30405b261ecSmrg winSendKeyEvent (KEY_ScrollLock, FALSE); 30505b261ecSmrg } 30605b261ecSmrg 30705b261ecSmrg /* Has the key state changed? */ 30805b261ecSmrg dwKeyState = GetKeyState (VK_KANA) & 0x0001; 30905b261ecSmrg if (WIN_XOR (internalKeyStates & KanaMask, dwKeyState)) 31005b261ecSmrg { 31105b261ecSmrg winSendKeyEvent (KEY_HKTG, TRUE); 31205b261ecSmrg winSendKeyEvent (KEY_HKTG, FALSE); 31305b261ecSmrg } 31405b261ecSmrg} 31505b261ecSmrg 31605b261ecSmrg 31705b261ecSmrg/* 31805b261ecSmrg * Look for the lovely fake Control_L press/release generated by Windows 31905b261ecSmrg * when AltGr is pressed/released on a non-U.S. keyboard. 32005b261ecSmrg */ 32105b261ecSmrg 32205b261ecSmrgBool 32305b261ecSmrgwinIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam) 32405b261ecSmrg{ 32505b261ecSmrg MSG msgNext; 32605b261ecSmrg LONG lTime; 32705b261ecSmrg Bool fReturn; 32805b261ecSmrg 32905b261ecSmrg /* 33005b261ecSmrg * Fake Ctrl_L presses will be followed by an Alt_R keypress 33105b261ecSmrg * with the same timestamp as the Ctrl_L press. 33205b261ecSmrg */ 33305b261ecSmrg if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN) 33405b261ecSmrg && wParam == VK_CONTROL 33505b261ecSmrg && (HIWORD (lParam) & KF_EXTENDED) == 0) 33605b261ecSmrg { 33705b261ecSmrg /* Got a Ctrl_L press */ 33805b261ecSmrg 33905b261ecSmrg /* Get time of current message */ 34005b261ecSmrg lTime = GetMessageTime (); 34105b261ecSmrg 34205b261ecSmrg /* Look for fake Ctrl_L preceeding an Alt_R press. */ 34305b261ecSmrg fReturn = PeekMessage (&msgNext, NULL, 34405b261ecSmrg WM_KEYDOWN, WM_SYSKEYDOWN, 34505b261ecSmrg PM_NOREMOVE); 34605b261ecSmrg 34705b261ecSmrg /* 34805b261ecSmrg * Try again if the first call fails. 34905b261ecSmrg * NOTE: This usually happens when TweakUI is enabled. 35005b261ecSmrg */ 35105b261ecSmrg if (!fReturn) 35205b261ecSmrg { 35305b261ecSmrg /* Voodoo to make sure that the Alt_R message has posted */ 35405b261ecSmrg Sleep (0); 35505b261ecSmrg 35605b261ecSmrg /* Look for fake Ctrl_L preceeding an Alt_R press. */ 35705b261ecSmrg fReturn = PeekMessage (&msgNext, NULL, 35805b261ecSmrg WM_KEYDOWN, WM_SYSKEYDOWN, 35905b261ecSmrg PM_NOREMOVE); 36005b261ecSmrg } 36105b261ecSmrg if (msgNext.message != WM_KEYDOWN && msgNext.message != WM_SYSKEYDOWN) 36205b261ecSmrg fReturn = 0; 36305b261ecSmrg 36405b261ecSmrg /* Is next press an Alt_R with the same timestamp? */ 36505b261ecSmrg if (fReturn && msgNext.wParam == VK_MENU 36605b261ecSmrg && msgNext.time == lTime 36705b261ecSmrg && (HIWORD (msgNext.lParam) & KF_EXTENDED)) 36805b261ecSmrg { 36905b261ecSmrg /* 37005b261ecSmrg * Next key press is Alt_R with same timestamp as current 37105b261ecSmrg * Ctrl_L message. Therefore, this Ctrl_L press is a fake 37205b261ecSmrg * event, so discard it. 37305b261ecSmrg */ 37405b261ecSmrg return TRUE; 37505b261ecSmrg } 37605b261ecSmrg } 37705b261ecSmrg 37805b261ecSmrg /* 37905b261ecSmrg * Fake Ctrl_L releases will be followed by an Alt_R release 38005b261ecSmrg * with the same timestamp as the Ctrl_L release. 38105b261ecSmrg */ 38205b261ecSmrg if ((message == WM_KEYUP || message == WM_SYSKEYUP) 38305b261ecSmrg && wParam == VK_CONTROL 38405b261ecSmrg && (HIWORD (lParam) & KF_EXTENDED) == 0) 38505b261ecSmrg { 38605b261ecSmrg /* Got a Ctrl_L release */ 38705b261ecSmrg 38805b261ecSmrg /* Get time of current message */ 38905b261ecSmrg lTime = GetMessageTime (); 39005b261ecSmrg 39105b261ecSmrg /* Look for fake Ctrl_L release preceeding an Alt_R release. */ 39205b261ecSmrg fReturn = PeekMessage (&msgNext, NULL, 39305b261ecSmrg WM_KEYUP, WM_SYSKEYUP, 39405b261ecSmrg PM_NOREMOVE); 39505b261ecSmrg 39605b261ecSmrg /* 39705b261ecSmrg * Try again if the first call fails. 39805b261ecSmrg * NOTE: This usually happens when TweakUI is enabled. 39905b261ecSmrg */ 40005b261ecSmrg if (!fReturn) 40105b261ecSmrg { 40205b261ecSmrg /* Voodoo to make sure that the Alt_R message has posted */ 40305b261ecSmrg Sleep (0); 40405b261ecSmrg 40505b261ecSmrg /* Look for fake Ctrl_L release preceeding an Alt_R release. */ 40605b261ecSmrg fReturn = PeekMessage (&msgNext, NULL, 40705b261ecSmrg WM_KEYUP, WM_SYSKEYUP, 40805b261ecSmrg PM_NOREMOVE); 40905b261ecSmrg } 41005b261ecSmrg 41105b261ecSmrg if (msgNext.message != WM_KEYUP && msgNext.message != WM_SYSKEYUP) 41205b261ecSmrg fReturn = 0; 41305b261ecSmrg 41405b261ecSmrg /* Is next press an Alt_R with the same timestamp? */ 41505b261ecSmrg if (fReturn 41605b261ecSmrg && (msgNext.message == WM_KEYUP 41705b261ecSmrg || msgNext.message == WM_SYSKEYUP) 41805b261ecSmrg && msgNext.wParam == VK_MENU 41905b261ecSmrg && msgNext.time == lTime 42005b261ecSmrg && (HIWORD (msgNext.lParam) & KF_EXTENDED)) 42105b261ecSmrg { 42205b261ecSmrg /* 42305b261ecSmrg * Next key release is Alt_R with same timestamp as current 42405b261ecSmrg * Ctrl_L message. Therefore, this Ctrl_L release is a fake 42505b261ecSmrg * event, so discard it. 42605b261ecSmrg */ 42705b261ecSmrg return TRUE; 42805b261ecSmrg } 42905b261ecSmrg } 43005b261ecSmrg 43105b261ecSmrg /* Not a fake control left press/release */ 43205b261ecSmrg return FALSE; 43305b261ecSmrg} 43405b261ecSmrg 43505b261ecSmrg 43605b261ecSmrg/* 43705b261ecSmrg * Lift any modifier keys that are pressed 43805b261ecSmrg */ 43905b261ecSmrg 44005b261ecSmrgvoid 4416747b715SmrgwinKeybdReleaseKeys (void) 44205b261ecSmrg{ 44305b261ecSmrg int i; 44405b261ecSmrg 44505b261ecSmrg#ifdef HAS_DEVWINDOWS 44605b261ecSmrg /* Verify that the mi input system has been initialized */ 44705b261ecSmrg if (g_fdMessageQueue == WIN_FD_INVALID) 44805b261ecSmrg return; 44905b261ecSmrg#endif 45005b261ecSmrg 45105b261ecSmrg /* Loop through all keys */ 45205b261ecSmrg for (i = 0; i < NUM_KEYCODES; ++i) 45305b261ecSmrg { 45405b261ecSmrg /* Pop key if pressed */ 45505b261ecSmrg if (g_winKeyState[i]) 45605b261ecSmrg winSendKeyEvent (i, FALSE); 45705b261ecSmrg 45805b261ecSmrg /* Reset pressed flag for keys */ 45905b261ecSmrg g_winKeyState[i] = FALSE; 46005b261ecSmrg } 46105b261ecSmrg} 46205b261ecSmrg 46305b261ecSmrg 46405b261ecSmrg/* 46505b261ecSmrg * Take a raw X key code and send an up or down event for it. 46605b261ecSmrg * 46705b261ecSmrg * Thanks to VNC for inspiration, though it is a simple function. 46805b261ecSmrg */ 46905b261ecSmrg 47005b261ecSmrgvoid 47105b261ecSmrgwinSendKeyEvent (DWORD dwKey, Bool fDown) 47205b261ecSmrg{ 4736747b715Smrg EventListPtr events; 4746747b715Smrg int i, nevents; 47505b261ecSmrg 47605b261ecSmrg /* 47705b261ecSmrg * When alt-tabing between screens we can get phantom key up messages 47805b261ecSmrg * Here we only pass them through it we think we should! 47905b261ecSmrg */ 48005b261ecSmrg if (g_winKeyState[dwKey] == FALSE && fDown == FALSE) return; 48105b261ecSmrg 48205b261ecSmrg /* Update the keyState map */ 48305b261ecSmrg g_winKeyState[dwKey] = fDown; 48405b261ecSmrg 4856747b715Smrg GetEventList(&events); 4866747b715Smrg nevents = GetKeyboardEvents(events, g_pwinKeyboard, fDown ? KeyPress : KeyRelease, dwKey + MIN_KEYCODE); 4876747b715Smrg 4886747b715Smrg for (i = 0; i < nevents; i++) 4896747b715Smrg mieqEnqueue(g_pwinKeyboard, events[i].event); 4906747b715Smrg 4916747b715Smrg#if CYGDEBUG 4926747b715Smrg ErrorF("winSendKeyEvent: dwKey: %d, fDown: %d, nEvents %d\n", 4936747b715Smrg dwKey, fDown, nevents); 4946747b715Smrg#endif 49505b261ecSmrg} 49605b261ecSmrg 49705b261ecSmrgBOOL winCheckKeyPressed(WPARAM wParam, LPARAM lParam) 49805b261ecSmrg{ 49905b261ecSmrg switch (wParam) 50005b261ecSmrg { 50105b261ecSmrg case VK_CONTROL: 50205b261ecSmrg if ((lParam & 0x1ff0000) == 0x11d0000 && g_winKeyState[KEY_RCtrl]) 50305b261ecSmrg return TRUE; 50405b261ecSmrg if ((lParam & 0x1ff0000) == 0x01d0000 && g_winKeyState[KEY_LCtrl]) 50505b261ecSmrg return TRUE; 50605b261ecSmrg break; 50705b261ecSmrg case VK_SHIFT: 50805b261ecSmrg if ((lParam & 0x1ff0000) == 0x0360000 && g_winKeyState[KEY_ShiftR]) 50905b261ecSmrg return TRUE; 51005b261ecSmrg if ((lParam & 0x1ff0000) == 0x02a0000 && g_winKeyState[KEY_ShiftL]) 51105b261ecSmrg return TRUE; 51205b261ecSmrg break; 51305b261ecSmrg default: 51405b261ecSmrg return TRUE; 51505b261ecSmrg } 51605b261ecSmrg return FALSE; 51705b261ecSmrg} 51805b261ecSmrg 51905b261ecSmrg/* Only on shift release message is sent even if both are pressed. 52005b261ecSmrg * Fix this here 52105b261ecSmrg */ 52205b261ecSmrgvoid winFixShiftKeys (int iScanCode) 52305b261ecSmrg{ 52405b261ecSmrg if (GetKeyState (VK_SHIFT) & 0x8000) 52505b261ecSmrg return; 52605b261ecSmrg 52705b261ecSmrg if (iScanCode == KEY_ShiftL && g_winKeyState[KEY_ShiftR]) 52805b261ecSmrg winSendKeyEvent (KEY_ShiftR, FALSE); 52905b261ecSmrg if (iScanCode == KEY_ShiftR && g_winKeyState[KEY_ShiftL]) 53005b261ecSmrg winSendKeyEvent (KEY_ShiftL, FALSE); 53105b261ecSmrg} 532