#include "win.h"
#include "winkeybd.h"
#include "winconfig.h"
#ifdef XKB
#define XKB_IN_SERVER
#include "XKBsrv.h"
#endif
static Bool g_winKeyState[NUM_KEYCODES];
#if WIN_NEW_KEYBOARD_SUPPORT
const unsigned int MaxKeysPerKey = 4;
void
winProcessKeyEvent (DWORD dwVirtualKey, DWORD dwKeyData)
{
Bool fDown = ((dwKeyData & 0x80000000) == 0);
winKeyEventsRec kerEvent;
int i;
kerEvent = winTranslateKey (dwVirtualKey, dwKeyData);
if (kerEvent.dwReleaseModifiers & WIN_MOD_LCONTROL)
winSendKeyEvent (XK_Control_L, FALSE);
if (kerEvent.dwReleaseModifiers & WIN_MOD_RCONTROL)
winSendKeyEvent (XK_Control_R, FALSE);
if (kerEvent.dwReleaseModifiers & WIN_MOD_LALT)
winSendKeyEvent (XK_Alt_L, FALSE);
if (kerEvent.dwReleaseModifiers & WIN_MOD_RALT)
winSendKeyEvent (XK_Alt_R, FALSE);
for (i = 0; kerEvent.dwXKeycodes[i] != XK_VoidSymbol; ++i)
winSendKeyEvent (kerEvent.dwXKeycodes[i], fDown);
if (kerEvent.dwReleaseModifiers & WIN_MOD_LCONTROL)
winSendKeyEvent (XK_Control_L, FALSE);
if (kerEvent.dwReleaseModifiers & WIN_MOD_RCONTROL)
winSendKeyEvent (XK_Control_R, TRUE);
if (kerEvent.dwReleaseModifiers & WIN_MOD_LALT)
winSendKeyEvent (XK_Alt_L, FALSE);
if (kerEvent.dwReleaseModifiers & WIN_MOD_RALT)
winSendKeyEvent (XK_Alt_R, TRUE);
}
winKeyEventsRec
winTranslateKey (DWORD dwVirtualKey, DWORD dwKeyData)
{
winKeyEventsRec kerEvents;
Bool fExtended = ((HIWORD (dwKeyData) & KF_EXTENDED) != 0);
int i;
DWORD dwNumEvents = 0;
BYTE bKeyboardState[256];
int iReturn;
unsigned char cAscii[4];
if (fExtended)
{
switch (dwVirtualKey)
{
case VK_MENU:
dwVirtualKey = VK_RMENU;
break;
case VK_CONTROL:
dwVirtualKey = VK_RCONTROL;
break;
}
}
kerEvents.dwReleaseModifiers = 0;
for (i = 0; i < g_winKeymapEntries; ++i)
{
if (winKeymap[i].dwVirtualKey == dwVirtualKey)
{
kerEvents.dwXKeycodes[dwNumEvents] = winKeymap[i].dwXKey;
break;
}
}
if (dwNumEvents != 0)
{
kerEvents.dwXKeycodes[dwNumEvents] = XK_VoidSymbol;
return kerEvents;
}
GetKeyboardState (bKeyboardState);
iReturn = ToAscii (dwVirtualKey, 0, bKeyboardState, (WORD *) cAscii, 0);
if ((bKeyboardState[VK_MENU] & 0x80) && (bKeyboardState[VK_CONTROL] & 0x80)
&& (iReturn >= 1)
&& (((cAscii[0] >= 32) && (cAscii[0] <= 126))
|| (cAscii[0] >= 160)))
{
if ((GetKeyState (VK_LCONTROL) & KF_UP))
kerEvents.dwReleaseModifiers |= WIN_MOD_LCONTROL;
if ((GetKeyState (VK_LMENU) & KF_UP))
kerEvents.dwReleaseModifiers |= WIN_MOD_LALT;
if ((GetKeyState (VK_RMENU) & KF_UP))
kerEvents.dwReleaseModifiers |= WIN_MOD_RALT;
if (kerEvents.dwReleaseModifiers == 0)
kerEvents.dwReleaseModifiers
= WIN_MOD_LCONTROL | WIN_MOD_LALT | WIN_MOD_RALT;
for (i = 0; i < iReturn; ++i)
kerEvents.dwXKeycodes[dwNumEvents++] = cAscii[i];
}
if (dwNumEvents == 0)
{
bKeyboardState[VK_CONTROL] = 0;
bKeyboardState[VK_LCONTROL] = 0;
bKeyboardState[VK_RCONTROL] = 0;
iReturn = ToAscii (dwVirtualKey, 0, bKeyboardState, (WORD *)cAscii, 0);
if (iReturn < 0)
{
switch (cAscii[0])
{
case '`':
kerEvents.dwXKeycodes[dwNumEvents++] = XK_dead_grave;
break;
case '\'':
kerEvents.dwXKeycodes[dwNumEvents++] = XK_dead_acute;
break;
case '~':
kerEvents.dwXKeycodes[dwNumEvents++] = XK_dead_tilde;
break;
case '^':
kerEvents.dwXKeycodes[dwNumEvents++] = XK_dead_circumflex;
break;
}
}
if (iReturn >= 1)
for (i = 0; i < iReturn; ++i)
kerEvents.dwXKeycodes[dwNumEvents++] = cAscii[i];
}
kerEvents.dwXKeycodes[dwNumEvents] = XK_VoidSymbol;
return kerEvents;
}
#else
void
winTranslateKey (WPARAM wParam, LPARAM lParam, int *piScanCode)
{
int iKeyFixup = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 1];
int iKeyFixupEx = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 2];
if ((HIWORD (lParam) & KF_EXTENDED) && iKeyFixupEx)
*piScanCode = iKeyFixupEx;
else if (iKeyFixup)
*piScanCode = iKeyFixup;
else
*piScanCode = LOBYTE (HIWORD (lParam));
}
#endif
void
winGetKeyMappings (KeySymsPtr pKeySyms, CARD8 *pModMap)
{
int i;
KeySym *pMap = map;
KeySym *pKeySym;
ZeroMemory (g_winKeyState, sizeof (g_winKeyState[0]) * NUM_KEYCODES);
for (i = 0; i < MAP_LENGTH; i++)
pModMap[i] = NoSymbol;
for (pKeySym = pMap, i = MIN_KEYCODE;
i < (MIN_KEYCODE + NUM_KEYCODES);
i++, pKeySym += GLYPHS_PER_KEY)
{
switch (*pKeySym)
{
case XK_Shift_L:
case XK_Shift_R:
pModMap[i] = ShiftMask;
break;
case XK_Control_L:
case XK_Control_R:
pModMap[i] = ControlMask;
break;
case XK_Caps_Lock:
pModMap[i] = LockMask;
break;
case XK_Alt_L:
case XK_Alt_R:
pModMap[i] = AltMask;
break;
#if !WIN_NEW_KEYBOARD_SUPPORT
case XK_Num_Lock:
pModMap[i] = NumLockMask;
break;
case XK_Scroll_Lock:
pModMap[i] = ScrollLockMask;
break;
case XK_Kana_Lock:
case XK_Kana_Shift:
pModMap[i] = KanaMask;
break;
#endif
case XK_Mode_switch:
pModMap[i] = AltLangMask;
break;
}
}
pKeySyms->map = (KeySym *) pMap;
pKeySyms->mapWidth = GLYPHS_PER_KEY;
pKeySyms->minKeyCode = MIN_KEYCODE;
pKeySyms->maxKeyCode = MAX_KEYCODE;
}
void
winKeybdBell (int iPercent, DeviceIntPtr pDeviceInt,
pointer pCtrl, int iClass)
{
MessageBeep (MB_OK);
}
void
winKeybdCtrl (DeviceIntPtr pDevice, KeybdCtrl *pCtrl)
{
}
int
winKeybdProc (DeviceIntPtr pDeviceInt, int iState)
{
KeySymsRec keySyms;
CARD8 modMap[MAP_LENGTH];
DevicePtr pDevice = (DevicePtr) pDeviceInt;
#ifdef XKB
XkbComponentNamesRec names;
#endif
switch (iState)
{
case DEVICE_INIT:
winConfigKeyboard (pDeviceInt);
winGetKeyMappings (&keySyms, modMap);
#ifdef XKB
defaultKeyboardControl.leds = g_winInfo.keyboard.leds;
#else
defaultKeyboardControl.leds = g_winInfo.keyboard.leds;
#endif
#ifdef XKB
if (g_winInfo.xkb.disable)
{
#endif
InitKeyboardDeviceStruct (pDevice,
&keySyms,
modMap,
winKeybdBell,
winKeybdCtrl);
#ifdef XKB
}
else
{
if (XkbInitialMap)
{
names.keymap = XkbInitialMap;
names.keycodes = NULL;
names.types = NULL;
names.compat = NULL;
names.symbols = NULL;
names.geometry = NULL;
}
else
{
names.keymap = g_winInfo.xkb.keymap;
names.keycodes = g_winInfo.xkb.keycodes;
names.types = g_winInfo.xkb.types;
names.compat = g_winInfo.xkb.compat;
names.symbols = g_winInfo.xkb.symbols;
names.geometry = g_winInfo.xkb.geometry;
}
ErrorF("Rules = \"%s\" Model = \"%s\" Layout = \"%s\""
" Variant = \"%s\" Options = \"%s\"\n",
g_winInfo.xkb.rules, g_winInfo.xkb.model,
g_winInfo.xkb.layout, g_winInfo.xkb.variant,
g_winInfo.xkb.options);
XkbSetRulesDflts (g_winInfo.xkb.rules, g_winInfo.xkb.model,
g_winInfo.xkb.layout, g_winInfo.xkb.variant,
g_winInfo.xkb.options);
XkbInitKeyboardDeviceStruct (pDeviceInt, &names, &keySyms,
modMap, winKeybdBell, winKeybdCtrl);
}
#endif
break;
case DEVICE_ON:
pDevice->on = TRUE;
break;
case DEVICE_CLOSE:
case DEVICE_OFF:
pDevice->on = FALSE;
break;
}
return Success;
}
void
winInitializeModeKeyStates (void)
{
#if !WIN_NEW_KEYBOARD_SUPPORT
if (GetKeyState (VK_NUMLOCK) & 0x0001)
{
winSendKeyEvent (KEY_NumLock, TRUE);
winSendKeyEvent (KEY_NumLock, FALSE);
}
if (GetKeyState (VK_CAPITAL) & 0x0001)
{
winSendKeyEvent (KEY_CapsLock, TRUE);
winSendKeyEvent (KEY_CapsLock, FALSE);
}
if (GetKeyState (VK_SCROLL) & 0x0001)
{
winSendKeyEvent (KEY_ScrollLock, TRUE);
winSendKeyEvent (KEY_ScrollLock, FALSE);
}
if (GetKeyState (VK_KANA) & 0x0001)
{
winSendKeyEvent (KEY_HKTG, TRUE);
winSendKeyEvent (KEY_HKTG, FALSE);
}
#endif
}
void
winStoreModeKeyStates (ScreenPtr pScreen)
{
#if !WIN_NEW_KEYBOARD_SUPPORT
winScreenPriv(pScreen);
pScreenPriv->dwModeKeyStates = 0x0L;
pScreenPriv->dwModeKeyStates |=
(GetKeyState (VK_NUMLOCK) & 0x0001) << NumLockMapIndex;
pScreenPriv->dwModeKeyStates |=
(GetKeyState (VK_SCROLL) & 0x0001) << ScrollLockMapIndex;
pScreenPriv->dwModeKeyStates |=
(GetKeyState (VK_CAPITAL) & 0x0001) << LockMapIndex;
pScreenPriv->dwModeKeyStates |=
(GetKeyState (VK_KANA) & 0x0001) << KanaMapIndex;
#endif
}
void
winRestoreModeKeyStates (ScreenPtr pScreen)
{
#if !WIN_NEW_KEYBOARD_SUPPORT
winScreenPriv(pScreen);
DWORD dwKeyState;
dwKeyState = GetKeyState (VK_NUMLOCK) & 0x0001;
if (WIN_XOR (pScreenPriv->dwModeKeyStates & NumLockMask, dwKeyState))
{
winSendKeyEvent (KEY_NumLock, TRUE);
winSendKeyEvent (KEY_NumLock, FALSE);
}
dwKeyState = GetKeyState (VK_CAPITAL) & 0x0001;
if (WIN_XOR (pScreenPriv->dwModeKeyStates & LockMask, dwKeyState))
{
winSendKeyEvent (KEY_CapsLock, TRUE);
winSendKeyEvent (KEY_CapsLock, FALSE);
}
dwKeyState = GetKeyState (VK_SCROLL) & 0x0001;
if (WIN_XOR (pScreenPriv->dwModeKeyStates & ScrollLockMask, dwKeyState))
{
winSendKeyEvent (KEY_ScrollLock, TRUE);
winSendKeyEvent (KEY_ScrollLock, FALSE);
}
dwKeyState = GetKeyState (VK_KANA) & 0x0001;
if (WIN_XOR (pScreenPriv->dwModeKeyStates & KanaMask, dwKeyState))
{
winSendKeyEvent (KEY_HKTG, TRUE);
winSendKeyEvent (KEY_HKTG, FALSE);
}
#endif
}
#if !WIN_NEW_KEYBOARD_SUPPORT
Bool
winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam)
{
MSG msgNext;
LONG lTime;
Bool fReturn;
if (message == WM_KEYDOWN
&& wParam == VK_CONTROL
&& (HIWORD (lParam) & KF_EXTENDED) == 0)
{
lTime = GetMessageTime ();
fReturn = PeekMessage (&msgNext, NULL,
WM_KEYDOWN, WM_KEYDOWN,
PM_NOREMOVE);
if (fReturn && msgNext.wParam == VK_MENU
&& msgNext.time == lTime
&& (HIWORD (msgNext.lParam) & KF_EXTENDED))
{
return TRUE;
}
}
if ((message == WM_KEYUP || message == WM_SYSKEYUP)
&& wParam == VK_CONTROL
&& (HIWORD (lParam) & KF_EXTENDED) == 0)
{
lTime = GetMessageTime ();
fReturn = PeekMessage (&msgNext, NULL,
WM_KEYUP, WM_SYSKEYUP,
PM_NOREMOVE);
if (fReturn
&& (msgNext.message == WM_KEYUP
|| msgNext.message == WM_SYSKEYUP)
&& msgNext.wParam == VK_MENU
&& msgNext.time == lTime
&& (HIWORD (msgNext.lParam) & KF_EXTENDED))
{
return TRUE;
}
}
return FALSE;
}
#endif
void
winKeybdReleaseKeys ()
{
#if !WIN_NEW_KEYBOARD_SUPPORT
int i;
if (g_fdMessageQueue == WIN_FD_INVALID)
return;
for (i = 0; i < NUM_KEYCODES; ++i)
{
if (g_winKeyState[i])
winSendKeyEvent (i, FALSE);
g_winKeyState[i] = FALSE;
}
#endif
}
void
winSendKeyEvent (DWORD dwKey, Bool fDown)
{
xEvent xCurrentEvent;
if (g_winKeyState[dwKey] == FALSE && fDown == FALSE) return;
g_winKeyState[dwKey] = fDown;
ZeroMemory (&xCurrentEvent, sizeof (xCurrentEvent));
xCurrentEvent.u.u.type = fDown ? KeyPress : KeyRelease;
xCurrentEvent.u.keyButtonPointer.time =
g_c32LastInputEventTime = GetTickCount ();
xCurrentEvent.u.u.detail = dwKey + MIN_KEYCODE;
mieqEnqueue (&xCurrentEvent);
}