~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to hw/xwin/winkeybd.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
 
3
 *
 
4
 *Permission is hereby granted, free of charge, to any person obtaining
 
5
 * a copy of this software and associated documentation files (the
 
6
 *"Software"), to deal in the Software without restriction, including
 
7
 *without limitation the rights to use, copy, modify, merge, publish,
 
8
 *distribute, sublicense, and/or sell copies of the Software, and to
 
9
 *permit persons to whom the Software is furnished to do so, subject to
 
10
 *the following conditions:
 
11
 *
 
12
 *The above copyright notice and this permission notice shall be
 
13
 *included in all copies or substantial portions of the Software.
 
14
 *
 
15
 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
16
 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
17
 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
18
 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
 
19
 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 
20
 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 
21
 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
22
 *
 
23
 *Except as contained in this notice, the name of the XFree86 Project
 
24
 *shall not be used in advertising or otherwise to promote the sale, use
 
25
 *or other dealings in this Software without prior written authorization
 
26
 *from the XFree86 Project.
 
27
 *
 
28
 * Authors:     Dakshinamurthy Karra
 
29
 *              Suhaib M Siddiqi
 
30
 *              Peter Busch
 
31
 *              Harold L Hunt II
 
32
 */
 
33
/* $XFree86: xc/programs/Xserver/hw/xwin/winkeybd.c,v 1.12 2002/10/17 08:18:22 alanh Exp $ */
 
34
 
 
35
 
 
36
#ifdef HAVE_XWIN_CONFIG_H
 
37
#include <xwin-config.h>
 
38
#endif
 
39
#include "win.h"
 
40
#include "winkeybd.h"
 
41
#include "winconfig.h"
 
42
#include "winmsg.h"
 
43
 
 
44
#ifdef XKB
 
45
#ifndef XKB_IN_SERVER
 
46
#define XKB_IN_SERVER
 
47
#endif
 
48
#include <X11/extensions/XKBsrv.h>
 
49
#endif
 
50
 
 
51
static Bool g_winKeyState[NUM_KEYCODES];
 
52
 
 
53
/* Stored to get internal mode key states.  Must be read-only.  */
 
54
static unsigned short const *g_winInternalModeKeyStatesPtr = NULL;
 
55
 
 
56
 
 
57
/*
 
58
 * Local prototypes
 
59
 */
 
60
 
 
61
static void
 
62
winGetKeyMappings (KeySymsPtr pKeySyms, CARD8 *pModMap);
 
63
 
 
64
static void
 
65
winKeybdBell (int iPercent, DeviceIntPtr pDeviceInt,
 
66
              pointer pCtrl, int iClass);
 
67
 
 
68
static void
 
69
winKeybdCtrl (DeviceIntPtr pDevice, KeybdCtrl *pCtrl);
 
70
 
 
71
 
 
72
/* 
 
73
 * Translate a Windows WM_[SYS]KEY(UP/DOWN) message
 
74
 * into an ASCII scan code.
 
75
 *
 
76
 * We do this ourselves, rather than letting Windows handle it,
 
77
 * because Windows tends to munge the handling of special keys,
 
78
 * like AltGr on European keyboards.
 
79
 */
 
80
 
 
81
void
 
82
winTranslateKey (WPARAM wParam, LPARAM lParam, int *piScanCode)
 
83
{
 
84
  int           iKeyFixup = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 1];
 
85
  int           iKeyFixupEx = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 2];
 
86
  int           iParamScanCode = LOBYTE (HIWORD (lParam));
 
87
 
 
88
  /* Branch on special extended, special non-extended, or normal key */
 
89
  if ((HIWORD (lParam) & KF_EXTENDED) && iKeyFixupEx)
 
90
    *piScanCode = iKeyFixupEx;
 
91
  else if (iKeyFixup)
 
92
    *piScanCode = iKeyFixup;
 
93
  else if (wParam == 0 && iParamScanCode == 0x70)
 
94
    *piScanCode = KEY_HKTG;
 
95
  else
 
96
    switch (iParamScanCode)
 
97
    {
 
98
      case 0x70:
 
99
        *piScanCode = KEY_HKTG;
 
100
        break;
 
101
      case 0x73:
 
102
        *piScanCode = KEY_BSlash2;
 
103
        break;
 
104
      default: 
 
105
        *piScanCode = iParamScanCode;
 
106
        break;
 
107
    }
 
108
}
 
109
 
 
110
 
 
111
/*
 
112
 * We call this function from winKeybdProc when we are
 
113
 * initializing the keyboard.
 
114
 */
 
115
 
 
116
static void
 
117
winGetKeyMappings (KeySymsPtr pKeySyms, CARD8 *pModMap)
 
118
{
 
119
  int                   i;
 
120
  KeySym                *pMap = map;
 
121
  KeySym                *pKeySym;
 
122
 
 
123
  /*
 
124
   * Initialize all key states to up... which may not be true
 
125
   * but it is close enough.
 
126
   */
 
127
  ZeroMemory (g_winKeyState, sizeof (g_winKeyState[0]) * NUM_KEYCODES);
 
128
 
 
129
  /* MAP_LENGTH is defined in Xserver/include/input.h to be 256 */
 
130
  for (i = 0; i < MAP_LENGTH; i++)
 
131
    pModMap[i] = NoSymbol;  /* make sure it is restored */
 
132
 
 
133
  /* Loop through all valid entries in the key symbol table */
 
134
  for (pKeySym = pMap, i = MIN_KEYCODE;
 
135
       i < (MIN_KEYCODE + NUM_KEYCODES);
 
136
       i++, pKeySym += GLYPHS_PER_KEY)
 
137
    {
 
138
      switch (*pKeySym)
 
139
        {
 
140
        case XK_Shift_L:
 
141
        case XK_Shift_R:
 
142
          pModMap[i] = ShiftMask;
 
143
          break;
 
144
 
 
145
        case XK_Control_L:
 
146
        case XK_Control_R:
 
147
          pModMap[i] = ControlMask;
 
148
          break;
 
149
 
 
150
        case XK_Caps_Lock:
 
151
          pModMap[i] = LockMask;
 
152
          break;
 
153
 
 
154
        case XK_Alt_L:
 
155
        case XK_Alt_R:
 
156
          pModMap[i] = AltMask;
 
157
          break;
 
158
 
 
159
        case XK_Num_Lock:
 
160
          pModMap[i] = NumLockMask;
 
161
          break;
 
162
 
 
163
        case XK_Scroll_Lock:
 
164
          pModMap[i] = ScrollLockMask;
 
165
          break;
 
166
 
 
167
#if 0
 
168
        case XK_Super_L:
 
169
        case XK_Super_R:
 
170
          pModMap[i] = Mod4Mask;
 
171
          break;
 
172
#else
 
173
        /* Hirigana/Katakana toggle */
 
174
        case XK_Kana_Lock:
 
175
        case XK_Kana_Shift:
 
176
          pModMap[i] = KanaMask;
 
177
          break;
 
178
#endif
 
179
 
 
180
        /* alternate toggle for multinational support */
 
181
        case XK_Mode_switch:
 
182
          pModMap[i] = AltLangMask;
 
183
          break;
 
184
        }
 
185
    }
 
186
 
 
187
  pKeySyms->map        = (KeySym *) pMap;
 
188
  pKeySyms->mapWidth   = GLYPHS_PER_KEY;
 
189
  pKeySyms->minKeyCode = MIN_KEYCODE;
 
190
  pKeySyms->maxKeyCode = MAX_KEYCODE;
 
191
}
 
192
 
 
193
 
 
194
/* Ring the keyboard bell (system speaker on PCs) */
 
195
static void
 
196
winKeybdBell (int iPercent, DeviceIntPtr pDeviceInt,
 
197
              pointer pCtrl, int iClass)
 
198
{
 
199
  /*
 
200
   * We can't use Beep () here because it uses the PC speaker
 
201
   * on NT/2000.  MessageBeep (MB_OK) will play the default system
 
202
   * sound on systems with a sound card or it will beep the PC speaker
 
203
   * on systems that do not have a sound card.
 
204
   */
 
205
  MessageBeep (MB_OK);
 
206
}
 
207
 
 
208
 
 
209
/* Change some keyboard configuration parameters */
 
210
static void
 
211
winKeybdCtrl (DeviceIntPtr pDevice, KeybdCtrl *pCtrl)
 
212
{
 
213
  g_winInternalModeKeyStatesPtr = &(pDevice->key->state);
 
214
}
 
215
 
 
216
 
 
217
/* 
 
218
 * See Porting Layer Definition - p. 18
 
219
 * winKeybdProc is known as a DeviceProc.
 
220
 */
 
221
 
 
222
int
 
223
winKeybdProc (DeviceIntPtr pDeviceInt, int iState)
 
224
{
 
225
  KeySymsRec            keySyms;
 
226
  CARD8                 modMap[MAP_LENGTH];
 
227
  DevicePtr             pDevice = (DevicePtr) pDeviceInt;
 
228
#ifdef XKB
 
229
  XkbComponentNamesRec names;
 
230
  XkbSrvInfoPtr       xkbi;
 
231
  XkbControlsPtr      ctrl;
 
232
#endif
 
233
 
 
234
  switch (iState)
 
235
    {
 
236
    case DEVICE_INIT:
 
237
      winConfigKeyboard (pDeviceInt);
 
238
 
 
239
      winGetKeyMappings (&keySyms, modMap);
 
240
 
 
241
#ifdef XKB
 
242
      /* FIXME: Maybe we should use winGetKbdLeds () here? */
 
243
      defaultKeyboardControl.leds = g_winInfo.keyboard.leds;
 
244
#else
 
245
      defaultKeyboardControl.leds = g_winInfo.keyboard.leds;
 
246
#endif
 
247
 
 
248
#ifdef XKB
 
249
      if (g_winInfo.xkb.disable) 
 
250
        {
 
251
#endif
 
252
          InitKeyboardDeviceStruct (pDevice,
 
253
                                    &keySyms,
 
254
                                    modMap,
 
255
                                    winKeybdBell,
 
256
                                    winKeybdCtrl);
 
257
#ifdef XKB
 
258
        } 
 
259
      else 
 
260
        {
 
261
 
 
262
          if (XkbInitialMap) 
 
263
            {
 
264
              names.keymap = XkbInitialMap;
 
265
              names.keycodes = NULL;
 
266
              names.types = NULL;
 
267
              names.compat = NULL;
 
268
              names.symbols = NULL;
 
269
              names.geometry = NULL;
 
270
            } 
 
271
          else 
 
272
            {
 
273
              names.keymap = g_winInfo.xkb.keymap;
 
274
              names.keycodes = g_winInfo.xkb.keycodes;
 
275
              names.types = g_winInfo.xkb.types;
 
276
              names.compat = g_winInfo.xkb.compat;
 
277
              names.symbols = g_winInfo.xkb.symbols;
 
278
              names.geometry = g_winInfo.xkb.geometry;
 
279
            }
 
280
 
 
281
          winErrorFVerb(2, "Rules = \"%s\" Model = \"%s\" Layout = \"%s\""
 
282
                 " Variant = \"%s\" Options = \"%s\"\n",
 
283
                 g_winInfo.xkb.rules, g_winInfo.xkb.model,
 
284
                 g_winInfo.xkb.layout, g_winInfo.xkb.variant,
 
285
                 g_winInfo.xkb.options);
 
286
          
 
287
          XkbSetRulesDflts (g_winInfo.xkb.rules, g_winInfo.xkb.model, 
 
288
                            g_winInfo.xkb.layout, g_winInfo.xkb.variant, 
 
289
                            g_winInfo.xkb.options);
 
290
          XkbInitKeyboardDeviceStruct (pDeviceInt, &names, &keySyms,
 
291
                                       modMap, winKeybdBell, winKeybdCtrl);
 
292
        }
 
293
#endif
 
294
 
 
295
#ifdef XKB
 
296
      if (!g_winInfo.xkb.disable)
 
297
        {  
 
298
          xkbi = pDeviceInt->key->xkbInfo;
 
299
          if (xkbi != NULL)
 
300
            {  
 
301
              ctrl = xkbi->desc->ctrls;
 
302
              ctrl->repeat_delay = g_winInfo.keyboard.delay;
 
303
              ctrl->repeat_interval = 1000/g_winInfo.keyboard.rate;
 
304
            }
 
305
          else
 
306
            {  
 
307
              winErrorFVerb (1, "winKeybdProc - Error initializing keyboard AutoRepeat (No XKB)\n");
 
308
            }
 
309
        }
 
310
#endif
 
311
 
 
312
      g_winInternalModeKeyStatesPtr = &(pDeviceInt->key->state);
 
313
      break;
 
314
      
 
315
    case DEVICE_ON: 
 
316
      pDevice->on = TRUE;
 
317
      g_winInternalModeKeyStatesPtr = &(pDeviceInt->key->state);
 
318
      break;
 
319
 
 
320
    case DEVICE_CLOSE:
 
321
    case DEVICE_OFF: 
 
322
      pDevice->on = FALSE;
 
323
      g_winInternalModeKeyStatesPtr = NULL;
 
324
      break;
 
325
    }
 
326
 
 
327
  return Success;
 
328
}
 
329
 
 
330
 
 
331
/*
 
332
 * Detect current mode key states upon server startup.
 
333
 *
 
334
 * Simulate a press and release of any key that is currently
 
335
 * toggled.
 
336
 */
 
337
 
 
338
void
 
339
winInitializeModeKeyStates (void)
 
340
{
 
341
  /* Restore NumLock */
 
342
  if (GetKeyState (VK_NUMLOCK) & 0x0001)
 
343
    {
 
344
      winSendKeyEvent (KEY_NumLock, TRUE);
 
345
      winSendKeyEvent (KEY_NumLock, FALSE);
 
346
    }
 
347
 
 
348
  /* Restore CapsLock */
 
349
  if (GetKeyState (VK_CAPITAL) & 0x0001)
 
350
    {
 
351
      winSendKeyEvent (KEY_CapsLock, TRUE);
 
352
      winSendKeyEvent (KEY_CapsLock, FALSE);
 
353
    }
 
354
 
 
355
  /* Restore ScrollLock */
 
356
  if (GetKeyState (VK_SCROLL) & 0x0001)
 
357
    {
 
358
      winSendKeyEvent (KEY_ScrollLock, TRUE);
 
359
      winSendKeyEvent (KEY_ScrollLock, FALSE);
 
360
    }
 
361
 
 
362
  /* Restore KanaLock */
 
363
  if (GetKeyState (VK_KANA) & 0x0001)
 
364
    {
 
365
      winSendKeyEvent (KEY_HKTG, TRUE);
 
366
      winSendKeyEvent (KEY_HKTG, FALSE);
 
367
    }
 
368
}
 
369
 
 
370
 
 
371
/*
 
372
 * Upon regaining the keyboard focus we must
 
373
 * resynchronize our internal mode key states
 
374
 * with the actual state of the keys.
 
375
 */
 
376
 
 
377
void
 
378
winRestoreModeKeyStates ()
 
379
{
 
380
  DWORD                 dwKeyState;
 
381
  BOOL                  processEvents = TRUE;
 
382
  unsigned short        internalKeyStates;
 
383
 
 
384
  /* X server is being initialized */
 
385
  if (!g_winInternalModeKeyStatesPtr)
 
386
    return;
 
387
 
 
388
  /* Only process events if the rootwindow is mapped. The keyboard events
 
389
   * will cause segfaults otherwise */
 
390
  if (WindowTable && WindowTable[0] && WindowTable[0]->mapped == FALSE)
 
391
    processEvents = FALSE;    
 
392
  
 
393
  /* Force to process all pending events in the mi event queue */
 
394
  if (processEvents)
 
395
    mieqProcessInputEvents ();
 
396
  
 
397
  /* Read the mode key states of our X server */
 
398
  internalKeyStates = *g_winInternalModeKeyStatesPtr;
 
399
 
 
400
  /* 
 
401
   * NOTE: The C XOR operator, ^, will not work here because it is
 
402
   * a bitwise operator, not a logical operator.  C does not
 
403
   * have a logical XOR operator, so we use a macro instead.
 
404
   */
 
405
 
 
406
  /* Has the key state changed? */
 
407
  dwKeyState = GetKeyState (VK_NUMLOCK) & 0x0001;
 
408
  if (WIN_XOR (internalKeyStates & NumLockMask, dwKeyState))
 
409
    {
 
410
      winSendKeyEvent (KEY_NumLock, TRUE);
 
411
      winSendKeyEvent (KEY_NumLock, FALSE);
 
412
    }
 
413
 
 
414
  /* Has the key state changed? */
 
415
  dwKeyState = GetKeyState (VK_CAPITAL) & 0x0001;
 
416
  if (WIN_XOR (internalKeyStates & LockMask, dwKeyState))
 
417
    {
 
418
      winSendKeyEvent (KEY_CapsLock, TRUE);
 
419
      winSendKeyEvent (KEY_CapsLock, FALSE);
 
420
    }
 
421
 
 
422
  /* Has the key state changed? */
 
423
  dwKeyState = GetKeyState (VK_SCROLL) & 0x0001;
 
424
  if (WIN_XOR (internalKeyStates & ScrollLockMask, dwKeyState))
 
425
    {
 
426
      winSendKeyEvent (KEY_ScrollLock, TRUE);
 
427
      winSendKeyEvent (KEY_ScrollLock, FALSE);
 
428
    }
 
429
 
 
430
  /* Has the key state changed? */
 
431
  dwKeyState = GetKeyState (VK_KANA) & 0x0001;
 
432
  if (WIN_XOR (internalKeyStates & KanaMask, dwKeyState))
 
433
    {
 
434
      winSendKeyEvent (KEY_HKTG, TRUE);
 
435
      winSendKeyEvent (KEY_HKTG, FALSE);
 
436
    }
 
437
}
 
438
 
 
439
 
 
440
/*
 
441
 * Look for the lovely fake Control_L press/release generated by Windows
 
442
 * when AltGr is pressed/released on a non-U.S. keyboard.
 
443
 */
 
444
 
 
445
Bool
 
446
winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam)
 
447
{
 
448
  MSG           msgNext;
 
449
  LONG          lTime;
 
450
  Bool          fReturn;
 
451
 
 
452
  /*
 
453
   * Fake Ctrl_L presses will be followed by an Alt_R keypress
 
454
   * with the same timestamp as the Ctrl_L press.
 
455
   */
 
456
  if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
 
457
      && wParam == VK_CONTROL
 
458
      && (HIWORD (lParam) & KF_EXTENDED) == 0)
 
459
    {
 
460
      /* Got a Ctrl_L press */
 
461
 
 
462
      /* Get time of current message */
 
463
      lTime = GetMessageTime ();
 
464
 
 
465
      /* Look for fake Ctrl_L preceeding an Alt_R press. */
 
466
      fReturn = PeekMessage (&msgNext, NULL,
 
467
                             WM_KEYDOWN, WM_SYSKEYDOWN,
 
468
                             PM_NOREMOVE);
 
469
 
 
470
      /*
 
471
       * Try again if the first call fails.
 
472
       * NOTE: This usually happens when TweakUI is enabled.
 
473
       */
 
474
      if (!fReturn)
 
475
        {
 
476
          /* Voodoo to make sure that the Alt_R message has posted */
 
477
          Sleep (0);
 
478
 
 
479
          /* Look for fake Ctrl_L preceeding an Alt_R press. */
 
480
          fReturn = PeekMessage (&msgNext, NULL,
 
481
                                 WM_KEYDOWN, WM_SYSKEYDOWN,
 
482
                                 PM_NOREMOVE);
 
483
        }
 
484
      if (msgNext.message != WM_KEYDOWN && msgNext.message != WM_SYSKEYDOWN)
 
485
          fReturn = 0;
 
486
 
 
487
      /* Is next press an Alt_R with the same timestamp? */
 
488
      if (fReturn && msgNext.wParam == VK_MENU
 
489
          && msgNext.time == lTime
 
490
          && (HIWORD (msgNext.lParam) & KF_EXTENDED))
 
491
        {
 
492
          /* 
 
493
           * Next key press is Alt_R with same timestamp as current
 
494
           * Ctrl_L message.  Therefore, this Ctrl_L press is a fake
 
495
           * event, so discard it.
 
496
           */
 
497
          return TRUE;
 
498
        }
 
499
    }
 
500
 
 
501
  /* 
 
502
   * Fake Ctrl_L releases will be followed by an Alt_R release
 
503
   * with the same timestamp as the Ctrl_L release.
 
504
   */
 
505
  if ((message == WM_KEYUP || message == WM_SYSKEYUP)
 
506
      && wParam == VK_CONTROL
 
507
      && (HIWORD (lParam) & KF_EXTENDED) == 0)
 
508
    {
 
509
      /* Got a Ctrl_L release */
 
510
 
 
511
      /* Get time of current message */
 
512
      lTime = GetMessageTime ();
 
513
 
 
514
      /* Look for fake Ctrl_L release preceeding an Alt_R release. */
 
515
      fReturn = PeekMessage (&msgNext, NULL,
 
516
                             WM_KEYUP, WM_SYSKEYUP, 
 
517
                             PM_NOREMOVE);
 
518
 
 
519
      /*
 
520
       * Try again if the first call fails.
 
521
       * NOTE: This usually happens when TweakUI is enabled.
 
522
       */
 
523
      if (!fReturn)
 
524
        {
 
525
          /* Voodoo to make sure that the Alt_R message has posted */
 
526
          Sleep (0);
 
527
 
 
528
          /* Look for fake Ctrl_L release preceeding an Alt_R release. */
 
529
          fReturn = PeekMessage (&msgNext, NULL,
 
530
                                 WM_KEYUP, WM_SYSKEYUP, 
 
531
                                 PM_NOREMOVE);
 
532
        }
 
533
 
 
534
      if (msgNext.message != WM_KEYUP && msgNext.message != WM_SYSKEYUP)
 
535
          fReturn = 0;
 
536
      
 
537
      /* Is next press an Alt_R with the same timestamp? */
 
538
      if (fReturn
 
539
          && (msgNext.message == WM_KEYUP
 
540
              || msgNext.message == WM_SYSKEYUP)
 
541
          && msgNext.wParam == VK_MENU
 
542
          && msgNext.time == lTime
 
543
          && (HIWORD (msgNext.lParam) & KF_EXTENDED))
 
544
        {
 
545
          /*
 
546
           * Next key release is Alt_R with same timestamp as current
 
547
           * Ctrl_L message. Therefore, this Ctrl_L release is a fake
 
548
           * event, so discard it.
 
549
           */
 
550
          return TRUE;
 
551
        }
 
552
    }
 
553
  
 
554
  /* Not a fake control left press/release */
 
555
  return FALSE;
 
556
}
 
557
 
 
558
 
 
559
/*
 
560
 * Lift any modifier keys that are pressed
 
561
 */
 
562
 
 
563
void
 
564
winKeybdReleaseKeys ()
 
565
{
 
566
  int                           i;
 
567
 
 
568
#ifdef HAS_DEVWINDOWS
 
569
  /* Verify that the mi input system has been initialized */
 
570
  if (g_fdMessageQueue == WIN_FD_INVALID)
 
571
    return;
 
572
#endif
 
573
 
 
574
  /* Loop through all keys */
 
575
  for (i = 0; i < NUM_KEYCODES; ++i)
 
576
    {
 
577
      /* Pop key if pressed */
 
578
      if (g_winKeyState[i])
 
579
        winSendKeyEvent (i, FALSE);
 
580
 
 
581
      /* Reset pressed flag for keys */
 
582
      g_winKeyState[i] = FALSE;
 
583
    }
 
584
}
 
585
 
 
586
 
 
587
/*
 
588
 * Take a raw X key code and send an up or down event for it.
 
589
 *
 
590
 * Thanks to VNC for inspiration, though it is a simple function.
 
591
 */
 
592
 
 
593
void
 
594
winSendKeyEvent (DWORD dwKey, Bool fDown)
 
595
{
 
596
  xEvent                        xCurrentEvent;
 
597
 
 
598
  /*
 
599
   * When alt-tabing between screens we can get phantom key up messages
 
600
   * Here we only pass them through it we think we should!
 
601
   */
 
602
  if (g_winKeyState[dwKey] == FALSE && fDown == FALSE) return;
 
603
 
 
604
  /* Update the keyState map */
 
605
  g_winKeyState[dwKey] = fDown;
 
606
  
 
607
  ZeroMemory (&xCurrentEvent, sizeof (xCurrentEvent));
 
608
 
 
609
  xCurrentEvent.u.u.type = fDown ? KeyPress : KeyRelease;
 
610
  xCurrentEvent.u.keyButtonPointer.time =
 
611
    g_c32LastInputEventTime = GetTickCount ();
 
612
  xCurrentEvent.u.u.detail = dwKey + MIN_KEYCODE;
 
613
  mieqEnqueue (&xCurrentEvent);
 
614
}
 
615
 
 
616
BOOL winCheckKeyPressed(WPARAM wParam, LPARAM lParam)
 
617
{
 
618
  switch (wParam)
 
619
  {
 
620
    case VK_CONTROL:
 
621
      if ((lParam & 0x1ff0000) == 0x11d0000 && g_winKeyState[KEY_RCtrl])
 
622
        return TRUE;
 
623
      if ((lParam & 0x1ff0000) == 0x01d0000 && g_winKeyState[KEY_LCtrl])
 
624
        return TRUE;
 
625
      break;
 
626
    case VK_SHIFT:
 
627
      if ((lParam & 0x1ff0000) == 0x0360000 && g_winKeyState[KEY_ShiftR])
 
628
        return TRUE;
 
629
      if ((lParam & 0x1ff0000) == 0x02a0000 && g_winKeyState[KEY_ShiftL])
 
630
        return TRUE;
 
631
      break;
 
632
    default:
 
633
      return TRUE;
 
634
  }
 
635
  return FALSE;
 
636
}
 
637
 
 
638
/* Only on shift release message is sent even if both are pressed.
 
639
 * Fix this here 
 
640
 */
 
641
void winFixShiftKeys (int iScanCode)
 
642
{
 
643
  if (GetKeyState (VK_SHIFT) & 0x8000)
 
644
    return;
 
645
 
 
646
  if (iScanCode == KEY_ShiftL && g_winKeyState[KEY_ShiftR])
 
647
    winSendKeyEvent (KEY_ShiftR, FALSE);
 
648
  if (iScanCode == KEY_ShiftR && g_winKeyState[KEY_ShiftL])
 
649
    winSendKeyEvent (KEY_ShiftL, FALSE);
 
650
}