700 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			700 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
 | 
						|
 *
 | 
						|
 *Permission is hereby granted, free of charge, to any person obtaining
 | 
						|
 * a copy of this software and associated documentation files (the
 | 
						|
 *"Software"), to deal in the Software without restriction, including
 | 
						|
 *without limitation the rights to use, copy, modify, merge, publish,
 | 
						|
 *distribute, sublicense, and/or sell copies of the Software, and to
 | 
						|
 *permit persons to whom the Software is furnished to do so, subject to
 | 
						|
 *the following conditions:
 | 
						|
 *
 | 
						|
 *The above copyright notice and this permission notice shall be
 | 
						|
 *included in all copies or substantial portions of the Software.
 | 
						|
 *
 | 
						|
 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
						|
 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
						|
 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
						|
 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
 | 
						|
 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 | 
						|
 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 | 
						|
 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
						|
 *
 | 
						|
 *Except as contained in this notice, the name of the XFree86 Project
 | 
						|
 *shall not be used in advertising or otherwise to promote the sale, use
 | 
						|
 *or other dealings in this Software without prior written authorization
 | 
						|
 *from the XFree86 Project.
 | 
						|
 *
 | 
						|
 * Authors:	Dakshinamurthy Karra
 | 
						|
 *		Suhaib M Siddiqi
 | 
						|
 *		Peter Busch
 | 
						|
 *		Harold L Hunt II
 | 
						|
 */
 | 
						|
/* $XFree86: xc/programs/Xserver/hw/xwin/winkeybd.c,v 1.13 2003/07/29 21:25:17 dawes Exp $ */
 | 
						|
 | 
						|
 | 
						|
#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;
 | 
						|
 | 
						|
  /* Get the key events */
 | 
						|
  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];
 | 
						|
 | 
						|
  /* Remap extended modifiers to the right version of that key.  */
 | 
						|
  if (fExtended)
 | 
						|
    {
 | 
						|
      switch (dwVirtualKey)
 | 
						|
	{
 | 
						|
	case VK_MENU:
 | 
						|
	  dwVirtualKey = VK_RMENU;
 | 
						|
	  break;
 | 
						|
 | 
						|
	case VK_CONTROL:
 | 
						|
	  dwVirtualKey = VK_RCONTROL;
 | 
						|
	  break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  /* Initialize the modifiers to release flag */
 | 
						|
  kerEvents.dwReleaseModifiers = 0;
 | 
						|
   
 | 
						|
  /* Look up the current virtual key code in the translation table */
 | 
						|
  for (i = 0; i < g_winKeymapEntries; ++i)
 | 
						|
    {
 | 
						|
      /* Did we find a mapping? */
 | 
						|
      if (winKeymap[i].dwVirtualKey == dwVirtualKey)
 | 
						|
	{
 | 
						|
	  /* Mapping found, we have at least one event now */
 | 
						|
	  kerEvents.dwXKeycodes[dwNumEvents] = winKeymap[i].dwXKey;
 | 
						|
	  break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  
 | 
						|
  /* Break out early, if we found the key in the translation table */
 | 
						|
  if (dwNumEvents != 0)
 | 
						|
    {
 | 
						|
      /* Terminate the last of the key events with a void symbol */
 | 
						|
      kerEvents.dwXKeycodes[dwNumEvents] = XK_VoidSymbol;
 | 
						|
      return kerEvents;
 | 
						|
    }
 | 
						|
  
 | 
						|
  /* Get the state of all keyboard keys */
 | 
						|
  GetKeyboardState (bKeyboardState);
 | 
						|
 | 
						|
  /* Try to convert the key to ASCII */
 | 
						|
  iReturn = ToAscii (dwVirtualKey, 0, bKeyboardState, (WORD *) cAscii, 0);
 | 
						|
  
 | 
						|
  /*
 | 
						|
   * Left Control and Alt pressed, combined with a valid result
 | 
						|
   * from ToAscii means that we have found the Windows version of AltGr.
 | 
						|
   */
 | 
						|
  if ((bKeyboardState[VK_MENU] & 0x80) && (bKeyboardState[VK_CONTROL] & 0x80)
 | 
						|
      && (iReturn >= 1)
 | 
						|
      && (((cAscii[0] >= 32) && (cAscii[0] <= 126))
 | 
						|
	  || (cAscii[0] >= 160)))
 | 
						|
    {
 | 
						|
      /* These three calls will return 0 on Windows 95/98/Me */
 | 
						|
      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;
 | 
						|
 | 
						|
      /* Windows 95/98/Me handling - pop all of them */
 | 
						|
      if (kerEvents.dwReleaseModifiers == 0)
 | 
						|
	kerEvents.dwReleaseModifiers
 | 
						|
	  = WIN_MOD_LCONTROL | WIN_MOD_LALT | WIN_MOD_RALT;
 | 
						|
 | 
						|
      /* Copy the string of character events */
 | 
						|
      for (i = 0; i < iReturn; ++i)
 | 
						|
	kerEvents.dwXKeycodes[dwNumEvents++] = cAscii[i];
 | 
						|
    }
 | 
						|
 | 
						|
  /* Handle non Ctrl+Alt cases*/
 | 
						|
  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;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
      
 | 
						|
      /* Send what we've got if its a printable character */
 | 
						|
      if (iReturn >= 1)
 | 
						|
	for (i = 0; i < iReturn; ++i)
 | 
						|
	  kerEvents.dwXKeycodes[dwNumEvents++] = cAscii[i];
 | 
						|
    }
 | 
						|
 | 
						|
  
 | 
						|
  /* Terminate the last of the key events with a void symbol */
 | 
						|
  kerEvents.dwXKeycodes[dwNumEvents] = XK_VoidSymbol;
 | 
						|
  return kerEvents;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#else /* WIN_NEW_KEYBOARD_SUPPORT */
 | 
						|
 | 
						|
 | 
						|
/* 
 | 
						|
 * Translate a Windows WM_[SYS]KEY(UP/DOWN) message
 | 
						|
 * into an ASCII scan code.
 | 
						|
 *
 | 
						|
 * We do this ourselves, rather than letting Windows handle it,
 | 
						|
 * because Windows tends to munge the handling of special keys,
 | 
						|
 * like AltGr on European keyboards.
 | 
						|
 */
 | 
						|
 | 
						|
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];
 | 
						|
 | 
						|
  /* Branch on special extended, special non-extended, or normal key */
 | 
						|
  if ((HIWORD (lParam) & KF_EXTENDED) && iKeyFixupEx)
 | 
						|
    *piScanCode = iKeyFixupEx;
 | 
						|
  else if (iKeyFixup)
 | 
						|
    *piScanCode = iKeyFixup;
 | 
						|
  else
 | 
						|
    *piScanCode = LOBYTE (HIWORD (lParam));
 | 
						|
}
 | 
						|
 | 
						|
#endif /* WIN_NEW_KEYBOARD_SUPPORT */
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * We call this function from winKeybdProc when we are
 | 
						|
 * initializing the keyboard.
 | 
						|
 */
 | 
						|
 | 
						|
void
 | 
						|
winGetKeyMappings (KeySymsPtr pKeySyms, CARD8 *pModMap)
 | 
						|
{
 | 
						|
  int			i;
 | 
						|
  KeySym		*pMap = map;
 | 
						|
  KeySym		*pKeySym;
 | 
						|
 | 
						|
  /*
 | 
						|
   * Initialize all key states to up... which may not be true
 | 
						|
   * but it is close enough.
 | 
						|
   */
 | 
						|
  ZeroMemory (g_winKeyState, sizeof (g_winKeyState[0]) * NUM_KEYCODES);
 | 
						|
 | 
						|
  /* MAP_LENGTH is defined in Xserver/include/input.h to be 256 */
 | 
						|
  for (i = 0; i < MAP_LENGTH; i++)
 | 
						|
    pModMap[i] = NoSymbol;  /* make sure it is restored */
 | 
						|
 | 
						|
  /* Loop through all valid entries in the key symbol table */
 | 
						|
  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;
 | 
						|
 | 
						|
	/* Hirigana/Katakana toggle */
 | 
						|
	case XK_Kana_Lock:
 | 
						|
	case XK_Kana_Shift:
 | 
						|
	  pModMap[i] = KanaMask;
 | 
						|
	  break;
 | 
						|
#endif
 | 
						|
 | 
						|
	/* alternate toggle for multinational support */
 | 
						|
	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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Ring the keyboard bell (system speaker on PCs) */
 | 
						|
void
 | 
						|
winKeybdBell (int iPercent, DeviceIntPtr pDeviceInt,
 | 
						|
	      pointer pCtrl, int iClass)
 | 
						|
{
 | 
						|
  /*
 | 
						|
   * We can't use Beep () here because it uses the PC speaker
 | 
						|
   * on NT/2000.  MessageBeep (MB_OK) will play the default system
 | 
						|
   * sound on systems with a sound card or it will beep the PC speaker
 | 
						|
   * on systems that do not have a sound card.
 | 
						|
   */
 | 
						|
  MessageBeep (MB_OK);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Change some keyboard configuration parameters */
 | 
						|
void
 | 
						|
winKeybdCtrl (DeviceIntPtr pDevice, KeybdCtrl *pCtrl)
 | 
						|
{
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* 
 | 
						|
 * See Porting Layer Definition - p. 18
 | 
						|
 * winKeybdProc is known as a DeviceProc.
 | 
						|
 */
 | 
						|
 | 
						|
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
 | 
						|
      /* FIXME: Maybe we should use winGetKbdLeds () here? */
 | 
						|
      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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Detect current mode key states upon server startup.
 | 
						|
 *
 | 
						|
 * Simulate a press and release of any key that is currently
 | 
						|
 * toggled.
 | 
						|
 */
 | 
						|
 | 
						|
void
 | 
						|
winInitializeModeKeyStates (void)
 | 
						|
{
 | 
						|
#if !WIN_NEW_KEYBOARD_SUPPORT
 | 
						|
  /* Restore NumLock */
 | 
						|
  if (GetKeyState (VK_NUMLOCK) & 0x0001)
 | 
						|
    {
 | 
						|
      winSendKeyEvent (KEY_NumLock, TRUE);
 | 
						|
      winSendKeyEvent (KEY_NumLock, FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
  /* Restore CapsLock */
 | 
						|
  if (GetKeyState (VK_CAPITAL) & 0x0001)
 | 
						|
    {
 | 
						|
      winSendKeyEvent (KEY_CapsLock, TRUE);
 | 
						|
      winSendKeyEvent (KEY_CapsLock, FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
  /* Restore ScrollLock */
 | 
						|
  if (GetKeyState (VK_SCROLL) & 0x0001)
 | 
						|
    {
 | 
						|
      winSendKeyEvent (KEY_ScrollLock, TRUE);
 | 
						|
      winSendKeyEvent (KEY_ScrollLock, FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
  /* Restore KanaLock */
 | 
						|
  if (GetKeyState (VK_KANA) & 0x0001)
 | 
						|
    {
 | 
						|
      winSendKeyEvent (KEY_HKTG, TRUE);
 | 
						|
      winSendKeyEvent (KEY_HKTG, FALSE);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * We have to store the last state of each mode
 | 
						|
 * key before we lose the keyboard focus.
 | 
						|
 */
 | 
						|
 | 
						|
void
 | 
						|
winStoreModeKeyStates (ScreenPtr pScreen)
 | 
						|
{
 | 
						|
#if !WIN_NEW_KEYBOARD_SUPPORT
 | 
						|
  winScreenPriv(pScreen);
 | 
						|
 | 
						|
  /* Initialize all mode key states to off */
 | 
						|
  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
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Upon regaining the keyboard focus we must
 | 
						|
 * resynchronize our internal mode key states
 | 
						|
 * with the actual state of the keys.
 | 
						|
 */
 | 
						|
 | 
						|
void
 | 
						|
winRestoreModeKeyStates (ScreenPtr pScreen)
 | 
						|
{
 | 
						|
#if !WIN_NEW_KEYBOARD_SUPPORT
 | 
						|
  winScreenPriv(pScreen);
 | 
						|
  DWORD			dwKeyState;
 | 
						|
 | 
						|
  /* 
 | 
						|
   * NOTE: The C XOR operator, ^, will not work here because it is
 | 
						|
   * a bitwise operator, not a logical operator.  C does not
 | 
						|
   * have a logical XOR operator, so we use a macro instead.
 | 
						|
   */
 | 
						|
 | 
						|
  /* Has the key state changed? */
 | 
						|
  dwKeyState = GetKeyState (VK_NUMLOCK) & 0x0001;
 | 
						|
  if (WIN_XOR (pScreenPriv->dwModeKeyStates & NumLockMask, dwKeyState))
 | 
						|
    {
 | 
						|
      winSendKeyEvent (KEY_NumLock, TRUE);
 | 
						|
      winSendKeyEvent (KEY_NumLock, FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
  /* Has the key state changed? */
 | 
						|
  dwKeyState = GetKeyState (VK_CAPITAL) & 0x0001;
 | 
						|
  if (WIN_XOR (pScreenPriv->dwModeKeyStates & LockMask, dwKeyState))
 | 
						|
    {
 | 
						|
      winSendKeyEvent (KEY_CapsLock, TRUE);
 | 
						|
      winSendKeyEvent (KEY_CapsLock, FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
  /* Has the key state changed? */
 | 
						|
  dwKeyState = GetKeyState (VK_SCROLL) & 0x0001;
 | 
						|
  if (WIN_XOR (pScreenPriv->dwModeKeyStates & ScrollLockMask, dwKeyState))
 | 
						|
    {
 | 
						|
      winSendKeyEvent (KEY_ScrollLock, TRUE);
 | 
						|
      winSendKeyEvent (KEY_ScrollLock, FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
  /* Has the key state changed? */
 | 
						|
  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
 | 
						|
/*
 | 
						|
 * Look for the lovely fake Control_L press/release generated by Windows
 | 
						|
 * when AltGr is pressed/released on a non-U.S. keyboard.
 | 
						|
 */
 | 
						|
 | 
						|
Bool
 | 
						|
winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam)
 | 
						|
{
 | 
						|
  MSG		msgNext;
 | 
						|
  LONG		lTime;
 | 
						|
  Bool		fReturn;
 | 
						|
 | 
						|
  /*
 | 
						|
   * Fake Ctrl_L presses will be followed by an Alt_R keypress
 | 
						|
   * with the same timestamp as the Ctrl_L press.
 | 
						|
   */
 | 
						|
  if (message == WM_KEYDOWN
 | 
						|
      && wParam == VK_CONTROL
 | 
						|
      && (HIWORD (lParam) & KF_EXTENDED) == 0)
 | 
						|
    {
 | 
						|
      /* Got a Ctrl_L press */
 | 
						|
 | 
						|
      /* Get time of current message */
 | 
						|
      lTime = GetMessageTime ();
 | 
						|
      			
 | 
						|
      /* Look for fake Ctrl_L preceeding an Alt_R press. */
 | 
						|
      fReturn = PeekMessage (&msgNext, NULL,
 | 
						|
			     WM_KEYDOWN, WM_KEYDOWN,
 | 
						|
			     PM_NOREMOVE);
 | 
						|
 | 
						|
      /* Is next press an Alt_R with the same timestamp? */
 | 
						|
      if (fReturn && msgNext.wParam == VK_MENU
 | 
						|
	  && msgNext.time == lTime
 | 
						|
	  && (HIWORD (msgNext.lParam) & KF_EXTENDED))
 | 
						|
	{
 | 
						|
	  /* 
 | 
						|
	   * Next key press is Alt_R with same timestamp as current
 | 
						|
	   * Ctrl_L message.  Therefore, this Ctrl_L press is a fake
 | 
						|
	   * event, so discard it.
 | 
						|
	   */
 | 
						|
	  return TRUE;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  /* 
 | 
						|
   * Fake Ctrl_L releases will be followed by an Alt_R release
 | 
						|
   * with the same timestamp as the Ctrl_L release.
 | 
						|
   */
 | 
						|
  if ((message == WM_KEYUP || message == WM_SYSKEYUP)
 | 
						|
      && wParam == VK_CONTROL
 | 
						|
      && (HIWORD (lParam) & KF_EXTENDED) == 0)
 | 
						|
    {
 | 
						|
      /* Got a Ctrl_L release */
 | 
						|
 | 
						|
      /* Get time of current message */
 | 
						|
      lTime = GetMessageTime ();
 | 
						|
 | 
						|
      /* Look for fake Ctrl_L release preceeding an Alt_R release. */
 | 
						|
      fReturn = PeekMessage (&msgNext, NULL,
 | 
						|
			     WM_KEYUP, WM_SYSKEYUP, 
 | 
						|
			     PM_NOREMOVE);
 | 
						|
 | 
						|
      /* Is next press an Alt_R with the same timestamp? */
 | 
						|
      if (fReturn
 | 
						|
	  && (msgNext.message == WM_KEYUP
 | 
						|
	      || msgNext.message == WM_SYSKEYUP)
 | 
						|
	  && msgNext.wParam == VK_MENU
 | 
						|
	  && msgNext.time == lTime
 | 
						|
	  && (HIWORD (msgNext.lParam) & KF_EXTENDED))
 | 
						|
	{
 | 
						|
	  /*
 | 
						|
	   * Next key release is Alt_R with same timestamp as current
 | 
						|
	   * Ctrl_L message. Therefore, this Ctrl_L release is a fake
 | 
						|
	   * event, so discard it.
 | 
						|
	   */
 | 
						|
	  return TRUE;
 | 
						|
	}
 | 
						|
    }
 | 
						|
  
 | 
						|
  /* Not a fake control left press/release */
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
#endif /* WIN_NEW_KEYBOARD_SUPPORT */
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Lift any modifier keys that are pressed
 | 
						|
 */
 | 
						|
 | 
						|
void
 | 
						|
winKeybdReleaseKeys ()
 | 
						|
{
 | 
						|
#if !WIN_NEW_KEYBOARD_SUPPORT
 | 
						|
  int				i;
 | 
						|
 | 
						|
  /* Verify that the mi input system has been initialized */
 | 
						|
  if (g_fdMessageQueue == WIN_FD_INVALID)
 | 
						|
    return;
 | 
						|
 | 
						|
  /* Loop through all keys */
 | 
						|
  for (i = 0; i < NUM_KEYCODES; ++i)
 | 
						|
    {
 | 
						|
      /* Pop key if pressed */
 | 
						|
      if (g_winKeyState[i])
 | 
						|
	winSendKeyEvent (i, FALSE);
 | 
						|
 | 
						|
      /* Reset pressed flag for keys */
 | 
						|
      g_winKeyState[i] = FALSE;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Take a raw X key code and send an up or down event for it.
 | 
						|
 *
 | 
						|
 * Thanks to VNC for inspiration, though it is a simple function.
 | 
						|
 */
 | 
						|
 | 
						|
void
 | 
						|
winSendKeyEvent (DWORD dwKey, Bool fDown)
 | 
						|
{
 | 
						|
  xEvent			xCurrentEvent;
 | 
						|
 | 
						|
  /*
 | 
						|
   * When alt-tabing between screens we can get phantom key up messages
 | 
						|
   * Here we only pass them through it we think we should!
 | 
						|
   */
 | 
						|
  if (g_winKeyState[dwKey] == FALSE && fDown == FALSE) return;
 | 
						|
 | 
						|
  /* Update the keyState map */
 | 
						|
  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);
 | 
						|
}
 |