2 * kbdptr.c - deal with keyboard and pointer device over TCP & UDP.
8 * Copyright (C) 2002-2003 RealVNC Ltd.
9 * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
11 * This is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This software is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this software; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
31 #include "X11/Xproto.h"
34 #include <X11/keysym.h>
36 #include <mipointer.h>
41 extern WindowPtr *WindowTable; /* Why isn't this in a header file? */
43 #define KEY_IS_PRESSED(keycode) \
44 (kbdDevice->key->down[(keycode) >> 3] & (1 << ((keycode) & 7)))
47 static void XConvertCase(KeySym sym, KeySym *lower, KeySym *upper);
49 static DeviceIntPtr kbdDevice;
51 #define MIN_KEY_CODE 8
52 #define MAX_KEY_CODE 255
53 #define NO_OF_KEYS (MAX_KEY_CODE - MIN_KEY_CODE + 1)
54 #define GLYPHS_PER_KEY 2
56 static KeySym kbdMap[] = {
60 XK_Control_L, NoSymbol,
61 #define CONTROL_L_KEY_CODE MIN_KEY_CODE
63 XK_Control_R, NoSymbol,
64 #define CONTROL_R_KEY_CODE (MIN_KEY_CODE + 1)
67 #define SHIFT_L_KEY_CODE (MIN_KEY_CODE + 2)
70 #define SHIFT_R_KEY_CODE (MIN_KEY_CODE + 3)
73 #define META_L_KEY_CODE (MIN_KEY_CODE + 4)
76 #define META_R_KEY_CODE (MIN_KEY_CODE + 5)
79 #define ALT_L_KEY_CODE (MIN_KEY_CODE + 6)
82 #define ALT_R_KEY_CODE (MIN_KEY_CODE + 7)
84 /* Standard US keyboard */
98 XK_minus, XK_underscore,
100 XK_bracketleft, XK_braceleft,
101 XK_bracketright, XK_braceright,
102 XK_semicolon, XK_colon,
103 XK_apostrophe, XK_quotedbl,
104 XK_grave, XK_asciitilde,
106 XK_period, XK_greater,
107 XK_slash, XK_question,
108 XK_backslash, XK_bar,
137 /* Other useful keys */
139 XK_BackSpace, NoSymbol,
147 XK_Page_Up, NoSymbol,
148 XK_Page_Down, NoSymbol,
167 /* Plus blank ones which can be filled in using xmodmap */
171 #define N_PREDEFINED_KEYS (sizeof(kbdMap) / (sizeof(KeySym) * GLYPHS_PER_KEY))
181 KbdDeviceInit(pDevice, pKeySyms, pModMap)
182 DeviceIntPtr pDevice;
190 for (i = 0; i < MAP_LENGTH; i++)
191 pModMap[i] = NoSymbol;
193 pModMap[CONTROL_L_KEY_CODE] = ControlMask;
194 pModMap[CONTROL_R_KEY_CODE] = ControlMask;
195 pModMap[SHIFT_L_KEY_CODE] = ShiftMask;
196 pModMap[SHIFT_R_KEY_CODE] = ShiftMask;
197 pModMap[META_L_KEY_CODE] = Mod1Mask;
198 pModMap[META_R_KEY_CODE] = Mod1Mask;
199 pModMap[ALT_L_KEY_CODE] = Mod1Mask;
200 pModMap[ALT_R_KEY_CODE] = Mod1Mask;
202 pKeySyms->minKeyCode = MIN_KEY_CODE;
203 pKeySyms->maxKeyCode = MAX_KEY_CODE;
204 pKeySyms->mapWidth = GLYPHS_PER_KEY;
206 pKeySyms->map = (KeySym *)xalloc(sizeof(KeySym)
207 * MAP_LENGTH * GLYPHS_PER_KEY);
209 if (!pKeySyms->map) {
210 rfbLog("xalloc failed\n");
214 for (i = 0; i < MAP_LENGTH * GLYPHS_PER_KEY; i++)
215 pKeySyms->map[i] = NoSymbol;
217 for (i = 0; i < N_PREDEFINED_KEYS * GLYPHS_PER_KEY; i++) {
218 pKeySyms->map[i] = kbdMap[i];
250 PtrDeviceControl(dev, ctrl)
258 KbdAddEvent(down, keySym, cl)
264 KeySymsPtr keySyms = &kbdDevice->key->curKeySyms;
269 Bool fakeShiftPress = FALSE;
270 Bool fakeShiftLRelease = FALSE;
271 Bool fakeShiftRRelease = FALSE;
272 Bool shiftMustBeReleased = FALSE;
273 Bool shiftMustBePressed = FALSE;
276 CARD32 clientId = cl->sock;
277 ChangeWindowProperty(WindowTable[0], VNC_LAST_CLIENT_ID, XA_INTEGER,
278 32, PropModeReplace, 1, (pointer)&clientId, TRUE);
282 if (rfbTrace) rfbLog("KeyPress: 0x%x\n",keySym);
283 ev.u.u.type = KeyPress;
285 ev.u.u.type = KeyRelease;
288 /* First check if it's one of our predefined keys. If so then we can make
289 some attempt at allowing an xmodmap inside a VNC desktop behave
290 something like you'd expect - e.g. if keys A & B are swapped over and
291 the VNC client sends an A, then map it to a B when generating the X
292 event. We don't attempt to do this for keycodes which we make up on the
293 fly because it's too hard... */
295 for (i = 0; i < N_PREDEFINED_KEYS * GLYPHS_PER_KEY; i++) {
296 if (keySym == kbdMap[i]) {
297 keyCode = MIN_KEY_CODE + i / GLYPHS_PER_KEY;
299 if (kbdMap[(i/GLYPHS_PER_KEY) * GLYPHS_PER_KEY + 1] != NoSymbol) {
301 /* this keycode has more than one symbol associated with it,
302 so shift state is important */
304 if ((i % GLYPHS_PER_KEY) == 0)
305 shiftMustBeReleased = TRUE;
307 shiftMustBePressed = TRUE;
315 /* not one of our predefined keys - see if it's in the current keyboard
316 mapping (i.e. we've already allocated an extra keycode for it) */
318 if (keySyms->mapWidth < 2) {
319 rfbLog("KbdAddEvent: Sanity check failed - Keyboard mapping has "
320 "less than 2 keysyms per keycode (KeySym 0x%x)\n", keySym);
324 for (i = 0; i < NO_OF_KEYS * keySyms->mapWidth; i++) {
325 if (keySym == keySyms->map[i]) {
326 keyCode = MIN_KEY_CODE + i / keySyms->mapWidth;
328 if (keySyms->map[(i / keySyms->mapWidth)
329 * keySyms->mapWidth + 1] != NoSymbol) {
331 /* this keycode has more than one symbol associated with
332 it, so shift state is important */
334 if ((i % keySyms->mapWidth) == 0)
335 shiftMustBeReleased = TRUE;
337 shiftMustBePressed = TRUE;
341 if ((freeIndex == -1) && (keySyms->map[i] == NoSymbol)
342 && (i % keySyms->mapWidth) == 0)
352 /* we don't have an existing keycode - make one up on the fly and add
353 it to the keyboard mapping. Thanks to Vlad Harchev for pointing
354 out problems with non-ascii capitalisation. */
356 if (freeIndex == -1) {
357 rfbLog("KbdAddEvent: ignoring KeySym 0x%x - no free KeyCodes\n",
362 keyCode = MIN_KEY_CODE + freeIndex / keySyms->mapWidth;
364 XConvertCase(keySym, &lower, &upper);
366 if (lower == upper) {
367 keySyms->map[freeIndex] = keySym;
370 keySyms->map[freeIndex] = lower;
371 keySyms->map[freeIndex+1] = upper;
374 shiftMustBeReleased = TRUE;
376 shiftMustBePressed = TRUE;
379 SendMappingNotify(MappingKeyboard, keyCode, 1, serverClient);
381 rfbLog("KbdAddEvent: unknown KeySym 0x%x - allocating KeyCode %d\n",
385 time = GetTimeInMillis();
388 if (shiftMustBePressed && !(kbdDevice->key->state & ShiftMask)) {
389 fakeShiftPress = TRUE;
390 fake.u.u.type = KeyPress;
391 fake.u.u.detail = SHIFT_L_KEY_CODE;
392 fake.u.keyButtonPointer.time = time;
395 if (shiftMustBeReleased && (kbdDevice->key->state & ShiftMask)) {
396 if (KEY_IS_PRESSED(SHIFT_L_KEY_CODE)) {
397 fakeShiftLRelease = TRUE;
398 fake.u.u.type = KeyRelease;
399 fake.u.u.detail = SHIFT_L_KEY_CODE;
400 fake.u.keyButtonPointer.time = time;
403 if (KEY_IS_PRESSED(SHIFT_R_KEY_CODE)) {
404 fakeShiftRRelease = TRUE;
405 fake.u.u.type = KeyRelease;
406 fake.u.u.detail = SHIFT_R_KEY_CODE;
407 fake.u.keyButtonPointer.time = time;
413 ev.u.u.detail = keyCode;
414 ev.u.keyButtonPointer.time = time;
417 if (fakeShiftPress) {
418 fake.u.u.type = KeyRelease;
419 fake.u.u.detail = SHIFT_L_KEY_CODE;
420 fake.u.keyButtonPointer.time = time;
423 if (fakeShiftLRelease) {
424 fake.u.u.type = KeyPress;
425 fake.u.u.detail = SHIFT_L_KEY_CODE;
426 fake.u.keyButtonPointer.time = time;
429 if (fakeShiftRRelease) {
430 fake.u.u.type = KeyPress;
431 fake.u.u.detail = SHIFT_R_KEY_CODE;
432 fake.u.keyButtonPointer.time = time;
438 PtrAddEvent(buttonMask, x, y, cl)
447 static int oldButtonMask = 0;
450 CARD32 clientId = cl->sock;
451 ChangeWindowProperty(WindowTable[0], VNC_LAST_CLIENT_ID, XA_INTEGER,
452 32, PropModeReplace, 1, (pointer)&clientId, TRUE);
455 time = GetTimeInMillis();
457 miPointerAbsoluteCursor(x, y, time);
459 for (i = 0; i < 5; i++) {
460 if ((buttonMask ^ oldButtonMask) & (1<<i)) {
461 if (buttonMask & (1<<i)) {
462 ev.u.u.type = ButtonPress;
463 ev.u.u.detail = i + 1;
464 ev.u.keyButtonPointer.time = time;
467 ev.u.u.type = ButtonRelease;
468 ev.u.u.detail = i + 1;
469 ev.u.keyButtonPointer.time = time;
475 oldButtonMask = buttonMask;
483 unsigned long time = GetTimeInMillis();
485 for (i = 0; i < DOWN_LENGTH; i++) {
486 if (kbdDevice->key->down[i] != 0) {
487 for (j = 0; j < 8; j++) {
488 if (kbdDevice->key->down[i] & (1 << j)) {
489 ev.u.u.type = KeyRelease;
490 ev.u.u.detail = (i << 3) | j;
491 ev.u.keyButtonPointer.time = time;
500 /* copied from Xlib source */
502 static void XConvertCase(KeySym sym, KeySym *lower, KeySym *upper)
507 case 0: /* Latin 1 */
508 if ((sym >= XK_A) && (sym <= XK_Z))
509 *lower += (XK_a - XK_A);
510 else if ((sym >= XK_a) && (sym <= XK_z))
511 *upper -= (XK_a - XK_A);
512 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
513 *lower += (XK_agrave - XK_Agrave);
514 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
515 *upper -= (XK_agrave - XK_Agrave);
516 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
517 *lower += (XK_oslash - XK_Ooblique);
518 else if ((sym >= XK_oslash) && (sym <= XK_thorn))
519 *upper -= (XK_oslash - XK_Ooblique);
521 case 1: /* Latin 2 */
522 /* Assume the KeySym is a legal value (ignore discontinuities) */
523 if (sym == XK_Aogonek)
525 else if (sym >= XK_Lstroke && sym <= XK_Sacute)
526 *lower += (XK_lstroke - XK_Lstroke);
527 else if (sym >= XK_Scaron && sym <= XK_Zacute)
528 *lower += (XK_scaron - XK_Scaron);
529 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
530 *lower += (XK_zcaron - XK_Zcaron);
531 else if (sym == XK_aogonek)
533 else if (sym >= XK_lstroke && sym <= XK_sacute)
534 *upper -= (XK_lstroke - XK_Lstroke);
535 else if (sym >= XK_scaron && sym <= XK_zacute)
536 *upper -= (XK_scaron - XK_Scaron);
537 else if (sym >= XK_zcaron && sym <= XK_zabovedot)
538 *upper -= (XK_zcaron - XK_Zcaron);
539 else if (sym >= XK_Racute && sym <= XK_Tcedilla)
540 *lower += (XK_racute - XK_Racute);
541 else if (sym >= XK_racute && sym <= XK_tcedilla)
542 *upper -= (XK_racute - XK_Racute);
544 case 2: /* Latin 3 */
545 /* Assume the KeySym is a legal value (ignore discontinuities) */
546 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
547 *lower += (XK_hstroke - XK_Hstroke);
548 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
549 *lower += (XK_gbreve - XK_Gbreve);
550 else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
551 *upper -= (XK_hstroke - XK_Hstroke);
552 else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
553 *upper -= (XK_gbreve - XK_Gbreve);
554 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
555 *lower += (XK_cabovedot - XK_Cabovedot);
556 else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
557 *upper -= (XK_cabovedot - XK_Cabovedot);
559 case 3: /* Latin 4 */
560 /* Assume the KeySym is a legal value (ignore discontinuities) */
561 if (sym >= XK_Rcedilla && sym <= XK_Tslash)
562 *lower += (XK_rcedilla - XK_Rcedilla);
563 else if (sym >= XK_rcedilla && sym <= XK_tslash)
564 *upper -= (XK_rcedilla - XK_Rcedilla);
565 else if (sym == XK_ENG)
567 else if (sym == XK_eng)
569 else if (sym >= XK_Amacron && sym <= XK_Umacron)
570 *lower += (XK_amacron - XK_Amacron);
571 else if (sym >= XK_amacron && sym <= XK_umacron)
572 *upper -= (XK_amacron - XK_Amacron);
574 case 6: /* Cyrillic */
575 /* Assume the KeySym is a legal value (ignore discontinuities) */
576 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
577 *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
578 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
579 *upper += (XK_Serbian_DJE - XK_Serbian_dje);
580 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
581 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
582 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
583 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
586 /* Assume the KeySym is a legal value (ignore discontinuities) */
587 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
588 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
589 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
590 sym != XK_Greek_iotaaccentdieresis &&
591 sym != XK_Greek_upsilonaccentdieresis)
592 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
593 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
594 *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
595 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
596 sym != XK_Greek_finalsmallsigma)
597 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);