/[rdesktop]/jpeg/rdesktop/trunk/xkeymap.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /jpeg/rdesktop/trunk/xkeymap.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 910 - (show annotations)
Tue Jun 7 11:21:53 2005 UTC (18 years, 11 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/xkeymap.c
File MIME type: text/plain
File size: 18139 byte(s)
At XK_Num_Lock events, use RDP_INPUT_SYNCHRONIZE, if using numlock
sync.

1 /*
2 rdesktop: A Remote Desktop Protocol client.
3 User interface services - X keyboard mapping
4
5 Copyright (C) Matthew Chapman 1999-2005
6 Copyright (C) Peter Astrand <peter@cendio.se> 2003
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #ifdef RDP2VNC
24 #include "vnc/x11stubs.h"
25 #else
26 #include <X11/Xlib.h>
27 #include <X11/keysym.h>
28 #endif
29
30 #include <ctype.h>
31 #include <limits.h>
32 #include <time.h>
33 #include "rdesktop.h"
34 #include "scancodes.h"
35
36 #define KEYMAP_SIZE 0xffff+1
37 #define KEYMAP_MASK 0xffff
38 #define KEYMAP_MAX_LINE_LENGTH 80
39
40 extern Display *g_display;
41 extern Window g_wnd;
42 extern char keymapname[16];
43 extern int g_keylayout;
44 extern int g_win_button_size;
45 extern BOOL g_enable_compose;
46 extern BOOL g_use_rdp5;
47 extern BOOL g_numlock_sync;
48
49 static BOOL keymap_loaded;
50 static key_translation keymap[KEYMAP_SIZE];
51 static int min_keycode;
52 static uint16 remote_modifier_state = 0;
53 static uint16 saved_remote_modifier_state = 0;
54
55 static void update_modifier_state(uint8 scancode, BOOL pressed);
56
57 static void
58 add_to_keymap(char *keyname, uint8 scancode, uint16 modifiers, char *mapname)
59 {
60 KeySym keysym;
61
62 keysym = XStringToKeysym(keyname);
63 if (keysym == NoSymbol)
64 {
65 DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring)\n", keyname, mapname));
66 return;
67 }
68
69 DEBUG_KBD(("Adding translation, keysym=0x%x, scancode=0x%x, "
70 "modifiers=0x%x\n", (unsigned int) keysym, scancode, modifiers));
71
72 keymap[keysym & KEYMAP_MASK].scancode = scancode;
73 keymap[keysym & KEYMAP_MASK].modifiers = modifiers;
74
75 return;
76 }
77
78
79 static BOOL
80 xkeymap_read(char *mapname)
81 {
82 FILE *fp;
83 char line[KEYMAP_MAX_LINE_LENGTH];
84 char path[PATH_MAX], inplace_path[PATH_MAX];
85 unsigned int line_num = 0;
86 unsigned int line_length = 0;
87 char *keyname, *p;
88 char *line_rest;
89 uint8 scancode;
90 uint16 modifiers;
91
92
93 strcpy(path, KEYMAP_PATH);
94 strncat(path, mapname, sizeof(path) - sizeof(KEYMAP_PATH));
95
96 fp = fopen(path, "r");
97 if (fp == NULL)
98 {
99 /* in case we are running from the source tree */
100 strcpy(inplace_path, "keymaps/");
101 strncat(inplace_path, mapname, sizeof(inplace_path) - sizeof("keymaps/"));
102
103 fp = fopen(inplace_path, "r");
104 if (fp == NULL)
105 {
106 error("Failed to open keymap %s\n", path);
107 return False;
108 }
109 }
110
111 /* FIXME: More tolerant on white space */
112 while (fgets(line, sizeof(line), fp) != NULL)
113 {
114 line_num++;
115
116 /* Replace the \n with \0 */
117 p = strchr(line, '\n');
118 if (p != NULL)
119 *p = 0;
120
121 line_length = strlen(line);
122
123 /* Completely empty line */
124 if (strspn(line, " \t\n\r\f\v") == line_length)
125 {
126 continue;
127 }
128
129 /* Include */
130 if (strncmp(line, "include ", 8) == 0)
131 {
132 if (!xkeymap_read(line + 8))
133 return False;
134 continue;
135 }
136
137 /* map */
138 if (strncmp(line, "map ", 4) == 0)
139 {
140 g_keylayout = strtol(line + 4, NULL, 16);
141 DEBUG_KBD(("Keylayout 0x%x\n", g_keylayout));
142 continue;
143 }
144
145 /* compose */
146 if (strncmp(line, "enable_compose", 15) == 0)
147 {
148 DEBUG_KBD(("Enabling compose handling\n"));
149 g_enable_compose = True;
150 continue;
151 }
152
153 /* Comment */
154 if (line[0] == '#')
155 {
156 continue;
157 }
158
159 /* Normal line */
160 keyname = line;
161 p = strchr(line, ' ');
162 if (p == NULL)
163 {
164 error("Bad line %d in keymap %s\n", line_num, mapname);
165 continue;
166 }
167 else
168 {
169 *p = 0;
170 }
171
172 /* scancode */
173 p++;
174 scancode = strtol(p, &line_rest, 16);
175
176 /* flags */
177 /* FIXME: Should allow case-insensitive flag names.
178 Fix by using lex+yacc... */
179 modifiers = 0;
180 if (strstr(line_rest, "altgr"))
181 {
182 MASK_ADD_BITS(modifiers, MapAltGrMask);
183 }
184
185 if (strstr(line_rest, "shift"))
186 {
187 MASK_ADD_BITS(modifiers, MapLeftShiftMask);
188 }
189
190 if (strstr(line_rest, "numlock"))
191 {
192 MASK_ADD_BITS(modifiers, MapNumLockMask);
193 }
194
195 if (strstr(line_rest, "localstate"))
196 {
197 MASK_ADD_BITS(modifiers, MapLocalStateMask);
198 }
199
200 if (strstr(line_rest, "inhibit"))
201 {
202 MASK_ADD_BITS(modifiers, MapInhibitMask);
203 }
204
205 add_to_keymap(keyname, scancode, modifiers, mapname);
206
207 if (strstr(line_rest, "addupper"))
208 {
209 /* Automatically add uppercase key, with same modifiers
210 plus shift */
211 for (p = keyname; *p; p++)
212 *p = toupper((int) *p);
213 MASK_ADD_BITS(modifiers, MapLeftShiftMask);
214 add_to_keymap(keyname, scancode, modifiers, mapname);
215 }
216 }
217
218 fclose(fp);
219 return True;
220 }
221
222
223 /* Before connecting and creating UI */
224 void
225 xkeymap_init(void)
226 {
227 unsigned int max_keycode;
228 char *mapname_ptr;
229
230 /* Make keymapname lowercase */
231 mapname_ptr = keymapname;
232 while (*mapname_ptr)
233 {
234 *mapname_ptr = tolower((int) *mapname_ptr);
235 mapname_ptr++;
236 }
237
238 if (strcmp(keymapname, "none"))
239 {
240 if (xkeymap_read(keymapname))
241 keymap_loaded = True;
242 }
243
244 XDisplayKeycodes(g_display, &min_keycode, (int *) &max_keycode);
245 }
246
247 static void
248 send_winkey(uint32 ev_time, BOOL pressed, BOOL leftkey)
249 {
250 uint8 winkey;
251
252 if (leftkey)
253 winkey = SCANCODE_CHAR_LWIN;
254 else
255 winkey = SCANCODE_CHAR_RWIN;
256
257 if (pressed)
258 {
259 if (g_use_rdp5)
260 {
261 rdp_send_scancode(ev_time, RDP_KEYPRESS, winkey);
262 }
263 else
264 {
265 /* RDP4 doesn't support winkey. Fake with Ctrl-Esc */
266 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LCTRL);
267 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_ESC);
268 }
269 }
270 else
271 {
272 /* key released */
273 if (g_use_rdp5)
274 {
275 rdp_send_scancode(ev_time, RDP_KEYRELEASE, winkey);
276 }
277 else
278 {
279 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_ESC);
280 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
281 }
282 }
283 }
284
285 static void
286 reset_winkey(uint32 ev_time)
287 {
288 if (g_use_rdp5)
289 {
290 /* For some reason, it seems to suffice to release
291 *either* the left or right winkey. */
292 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LWIN);
293 }
294 }
295
296 /* Handles, for example, multi-scancode keypresses (which is not
297 possible via keymap-files) */
298 BOOL
299 handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)
300 {
301 switch (keysym)
302 {
303 case XK_Return:
304 if ((get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R))
305 && (get_key_state(state, XK_Control_L)
306 || get_key_state(state, XK_Control_R)))
307 {
308 /* Ctrl-Alt-Enter: toggle full screen */
309 if (pressed)
310 xwin_toggle_fullscreen();
311 return True;
312 }
313 break;
314
315 case XK_Break:
316 /* Send Break sequence E0 46 E0 C6 */
317 if (pressed)
318 {
319 rdp_send_scancode(ev_time, RDP_KEYPRESS,
320 (SCANCODE_EXTENDED | 0x46));
321 rdp_send_scancode(ev_time, RDP_KEYPRESS,
322 (SCANCODE_EXTENDED | 0xc6));
323 }
324 /* No release sequence */
325 return True;
326 break;
327
328 case XK_Pause:
329 /* According to MS Keyboard Scan Code
330 Specification, pressing Pause should result
331 in E1 1D 45 E1 9D C5. I'm not exactly sure
332 of how this is supposed to be sent via
333 RDP. The code below seems to work, but with
334 the side effect that Left Ctrl stays
335 down. Therefore, we release it when Pause
336 is released. */
337 if (pressed)
338 {
339 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
340 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0);
341 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x45, 0);
342 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
343 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x9d, 0);
344 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xc5, 0);
345 }
346 else
347 {
348 /* Release Left Ctrl */
349 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYRELEASE,
350 0x1d, 0);
351 }
352 return True;
353 break;
354
355 case XK_Meta_L: /* Windows keys */
356 case XK_Super_L:
357 case XK_Hyper_L:
358 send_winkey(ev_time, pressed, True);
359 return True;
360 break;
361
362 case XK_Meta_R:
363 case XK_Super_R:
364 case XK_Hyper_R:
365 send_winkey(ev_time, pressed, False);
366 return True;
367 break;
368
369 case XK_space:
370 /* Prevent access to the Windows system menu in single app mode */
371 if (g_win_button_size
372 && (get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R)))
373 return True;
374 break;
375
376 case XK_Num_Lock:
377 /* Synchronize on key release */
378 if (g_numlock_sync && !pressed)
379 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
380 ui_get_numlock_state(read_keyboard_state()), 0);
381
382 /* Inhibit */
383 return True;
384 break;
385
386 }
387 return False;
388 }
389
390
391 key_translation
392 xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state)
393 {
394 key_translation tr = { 0, 0 };
395
396 tr = keymap[keysym & KEYMAP_MASK];
397
398 if (tr.modifiers & MapInhibitMask)
399 {
400 DEBUG_KBD(("Inhibiting key\n"));
401 tr.scancode = 0;
402 return tr;
403 }
404
405 if (tr.modifiers & MapLocalStateMask)
406 {
407 /* The modifiers to send for this key should be obtained
408 from the local state. Currently, only shift is implemented. */
409 if (state & ShiftMask)
410 {
411 tr.modifiers = MapLeftShiftMask;
412 }
413 }
414
415 if ((tr.modifiers & MapLeftShiftMask) && ((remote_modifier_state & MapLeftCtrlMask)
416 || (remote_modifier_state & MapRightCtrlMask))
417 && get_key_state(state, XK_Caps_Lock))
418 {
419 DEBUG_KBD(("CapsLock + Ctrl pressed, releasing LeftShift\n"));
420 tr.modifiers ^= MapLeftShiftMask;
421 }
422
423 if (tr.scancode != 0)
424 {
425 DEBUG_KBD(("Found key translation, scancode=0x%x, modifiers=0x%x\n",
426 tr.scancode, tr.modifiers));
427 return tr;
428 }
429
430 if (keymap_loaded)
431 warning("No translation for (keysym 0x%lx, %s)\n", keysym, get_ksname(keysym));
432
433 /* not in keymap, try to interpret the raw scancode */
434 if (((int) keycode >= min_keycode) && (keycode <= 0x60))
435 {
436 tr.scancode = keycode - min_keycode;
437
438 /* The modifiers to send for this key should be
439 obtained from the local state. Currently, only
440 shift is implemented. */
441 if (state & ShiftMask)
442 {
443 tr.modifiers = MapLeftShiftMask;
444 }
445
446 DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));
447 }
448 else
449 {
450 DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));
451 }
452
453 return tr;
454 }
455
456 uint16
457 xkeymap_translate_button(unsigned int button)
458 {
459 switch (button)
460 {
461 case Button1: /* left */
462 return MOUSE_FLAG_BUTTON1;
463 case Button2: /* middle */
464 return MOUSE_FLAG_BUTTON3;
465 case Button3: /* right */
466 return MOUSE_FLAG_BUTTON2;
467 case Button4: /* wheel up */
468 return MOUSE_FLAG_BUTTON4;
469 case Button5: /* wheel down */
470 return MOUSE_FLAG_BUTTON5;
471 }
472
473 return 0;
474 }
475
476 char *
477 get_ksname(uint32 keysym)
478 {
479 char *ksname = NULL;
480
481 if (keysym == NoSymbol)
482 ksname = "NoSymbol";
483 else if (!(ksname = XKeysymToString(keysym)))
484 ksname = "(no name)";
485
486 return ksname;
487 }
488
489 static BOOL
490 is_modifier(uint8 scancode)
491 {
492 switch (scancode)
493 {
494 case SCANCODE_CHAR_LSHIFT:
495 case SCANCODE_CHAR_RSHIFT:
496 case SCANCODE_CHAR_LCTRL:
497 case SCANCODE_CHAR_RCTRL:
498 case SCANCODE_CHAR_LALT:
499 case SCANCODE_CHAR_RALT:
500 case SCANCODE_CHAR_LWIN:
501 case SCANCODE_CHAR_RWIN:
502 case SCANCODE_CHAR_NUMLOCK:
503 return True;
504 default:
505 break;
506 }
507 return False;
508 }
509
510 void
511 save_remote_modifiers(uint8 scancode)
512 {
513 if (is_modifier(scancode))
514 return;
515
516 saved_remote_modifier_state = remote_modifier_state;
517 }
518
519 void
520 restore_remote_modifiers(uint32 ev_time, uint8 scancode)
521 {
522 key_translation dummy;
523
524 if (is_modifier(scancode))
525 return;
526
527 dummy.scancode = 0;
528 dummy.modifiers = saved_remote_modifier_state;
529 ensure_remote_modifiers(ev_time, dummy);
530 }
531
532 void
533 ensure_remote_modifiers(uint32 ev_time, key_translation tr)
534 {
535 /* If this key is a modifier, do nothing */
536 if (is_modifier(tr.scancode))
537 return;
538
539 if (!g_numlock_sync)
540 {
541 /* NumLock */
542 if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)
543 != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask))
544 {
545 /* The remote modifier state is not correct */
546 uint16 new_remote_state;
547
548 if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask))
549 {
550 DEBUG_KBD(("Remote NumLock state is incorrect, activating NumLock.\n"));
551 new_remote_state = KBD_FLAG_NUMLOCK;
552 remote_modifier_state = MapNumLockMask;
553 }
554 else
555 {
556 DEBUG_KBD(("Remote NumLock state is incorrect, deactivating NumLock.\n"));
557 new_remote_state = 0;
558 remote_modifier_state = 0;
559 }
560
561 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0);
562 }
563 }
564
565
566 /* Shift. Left shift and right shift are treated as equal; either is fine. */
567 if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
568 != MASK_HAS_BITS(remote_modifier_state, MapShiftMask))
569 {
570 /* The remote modifier state is not correct */
571 if (MASK_HAS_BITS(tr.modifiers, MapLeftShiftMask))
572 {
573 /* Needs left shift. Send down. */
574 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LSHIFT);
575 }
576 else if (MASK_HAS_BITS(tr.modifiers, MapRightShiftMask))
577 {
578 /* Needs right shift. Send down. */
579 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RSHIFT);
580 }
581 else
582 {
583 /* Should not use this modifier. Send up for shift currently pressed. */
584 if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask))
585 /* Left shift is down */
586 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
587 else
588 /* Right shift is down */
589 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
590 }
591 }
592
593 /* AltGr */
594 if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask)
595 != MASK_HAS_BITS(remote_modifier_state, MapAltGrMask))
596 {
597 /* The remote modifier state is not correct */
598 if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask))
599 {
600 /* Needs this modifier. Send down. */
601 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RALT);
602 }
603 else
604 {
605 /* Should not use this modifier. Send up. */
606 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
607 }
608 }
609
610
611 }
612
613
614 unsigned int
615 read_keyboard_state()
616 {
617 #ifdef RDP2VNC
618 return 0;
619 #else
620 unsigned int state;
621 Window wdummy;
622 int dummy;
623
624 XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
625 return state;
626 #endif
627 }
628
629
630 uint16
631 ui_get_numlock_state(unsigned int state)
632 {
633 uint16 numlock_state = 0;
634
635 if (get_key_state(state, XK_Num_Lock))
636 numlock_state = KBD_FLAG_NUMLOCK;
637
638 return numlock_state;
639 }
640
641
642 void
643 reset_modifier_keys()
644 {
645 unsigned int state = read_keyboard_state();
646
647 /* reset keys */
648 uint32 ev_time;
649 ev_time = time(NULL);
650
651 if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask)
652 && !get_key_state(state, XK_Shift_L))
653 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
654
655 if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask)
656 && !get_key_state(state, XK_Shift_R))
657 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
658
659 if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask)
660 && !get_key_state(state, XK_Control_L))
661 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
662
663 if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask)
664 && !get_key_state(state, XK_Control_R))
665 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
666
667 if (MASK_HAS_BITS(remote_modifier_state, MapLeftAltMask) && !get_key_state(state, XK_Alt_L))
668 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
669
670 if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) &&
671 !get_key_state(state, XK_Alt_R) && !get_key_state(state, XK_Mode_switch)
672 && !get_key_state(state, XK_ISO_Level3_Shift))
673 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
674
675 reset_winkey(ev_time);
676
677 if (g_numlock_sync)
678 rdp_send_input(ev_time, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(state), 0);
679 }
680
681
682 static void
683 update_modifier_state(uint8 scancode, BOOL pressed)
684 {
685 #ifdef WITH_DEBUG_KBD
686 uint16 old_modifier_state;
687
688 old_modifier_state = remote_modifier_state;
689 #endif
690
691 switch (scancode)
692 {
693 case SCANCODE_CHAR_LSHIFT:
694 MASK_CHANGE_BIT(remote_modifier_state, MapLeftShiftMask, pressed);
695 break;
696 case SCANCODE_CHAR_RSHIFT:
697 MASK_CHANGE_BIT(remote_modifier_state, MapRightShiftMask, pressed);
698 break;
699 case SCANCODE_CHAR_LCTRL:
700 MASK_CHANGE_BIT(remote_modifier_state, MapLeftCtrlMask, pressed);
701 break;
702 case SCANCODE_CHAR_RCTRL:
703 MASK_CHANGE_BIT(remote_modifier_state, MapRightCtrlMask, pressed);
704 break;
705 case SCANCODE_CHAR_LALT:
706 MASK_CHANGE_BIT(remote_modifier_state, MapLeftAltMask, pressed);
707 break;
708 case SCANCODE_CHAR_RALT:
709 MASK_CHANGE_BIT(remote_modifier_state, MapRightAltMask, pressed);
710 break;
711 case SCANCODE_CHAR_LWIN:
712 MASK_CHANGE_BIT(remote_modifier_state, MapLeftWinMask, pressed);
713 break;
714 case SCANCODE_CHAR_RWIN:
715 MASK_CHANGE_BIT(remote_modifier_state, MapRightWinMask, pressed);
716 break;
717 case SCANCODE_CHAR_NUMLOCK:
718 /* KeyReleases for NumLocks are sent immediately. Toggle the
719 modifier state only on Keypress */
720 if (pressed && !g_numlock_sync)
721 {
722 BOOL newNumLockState;
723 newNumLockState =
724 (MASK_HAS_BITS
725 (remote_modifier_state, MapNumLockMask) == False);
726 MASK_CHANGE_BIT(remote_modifier_state,
727 MapNumLockMask, newNumLockState);
728 }
729 }
730
731 #ifdef WITH_DEBUG_KBD
732 if (old_modifier_state != remote_modifier_state)
733 {
734 DEBUG_KBD(("Before updating modifier_state:0x%x, pressed=0x%x\n",
735 old_modifier_state, pressed));
736 DEBUG_KBD(("After updating modifier_state:0x%x\n", remote_modifier_state));
737 }
738 #endif
739
740 }
741
742 /* Send keyboard input */
743 void
744 rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode)
745 {
746 update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));
747
748 if (scancode & SCANCODE_EXTENDED)
749 {
750 DEBUG_KBD(("Sending extended scancode=0x%x, flags=0x%x\n",
751 scancode & ~SCANCODE_EXTENDED, flags));
752 rdp_send_input(time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,
753 scancode & ~SCANCODE_EXTENDED, 0);
754 }
755 else
756 {
757 DEBUG_KBD(("Sending scancode=0x%x, flags=0x%x\n", scancode, flags));
758 rdp_send_input(time, RDP_INPUT_SCANCODE, flags, scancode, 0);
759 }
760 }

  ViewVC Help
Powered by ViewVC 1.1.26