/[rdesktop]/sourceforge.net/trunk/rdesktop/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 /sourceforge.net/trunk/rdesktop/xkeymap.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 896 - (show annotations)
Wed Apr 27 10:05:43 2005 UTC (19 years, 1 month ago) by stargo
File MIME type: text/plain
File size: 18065 byte(s)
reactivate fixed caps_lock hack. ctrl-alt-delete works again

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 case XK_Num_Lock:
376 /* FIXME: We might want to do RDP_INPUT_SYNCHRONIZE here, if g_numlock_sync */
377 if (!g_numlock_sync)
378 /* Inhibit */
379 return True;
380 break;
381
382 }
383 return False;
384 }
385
386
387 key_translation
388 xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state)
389 {
390 key_translation tr = { 0, 0 };
391
392 tr = keymap[keysym & KEYMAP_MASK];
393
394 if (tr.modifiers & MapInhibitMask)
395 {
396 DEBUG_KBD(("Inhibiting key\n"));
397 tr.scancode = 0;
398 return tr;
399 }
400
401 if (tr.modifiers & MapLocalStateMask)
402 {
403 /* The modifiers to send for this key should be obtained
404 from the local state. Currently, only shift is implemented. */
405 if (state & ShiftMask)
406 {
407 tr.modifiers = MapLeftShiftMask;
408 }
409 }
410
411 if ((tr.modifiers & MapLeftShiftMask) && ((remote_modifier_state & MapLeftCtrlMask)
412 || (remote_modifier_state & MapRightCtrlMask))
413 && get_key_state(state, XK_Caps_Lock))
414 {
415 DEBUG_KBD(("CapsLock + Ctrl pressed, releasing LeftShift\n"));
416 tr.modifiers ^= MapLeftShiftMask;
417 }
418
419 if (tr.scancode != 0)
420 {
421 DEBUG_KBD(("Found key translation, scancode=0x%x, modifiers=0x%x\n",
422 tr.scancode, tr.modifiers));
423 return tr;
424 }
425
426 if (keymap_loaded)
427 warning("No translation for (keysym 0x%lx, %s)\n", keysym, get_ksname(keysym));
428
429 /* not in keymap, try to interpret the raw scancode */
430 if (((int) keycode >= min_keycode) && (keycode <= 0x60))
431 {
432 tr.scancode = keycode - min_keycode;
433
434 /* The modifiers to send for this key should be
435 obtained from the local state. Currently, only
436 shift is implemented. */
437 if (state & ShiftMask)
438 {
439 tr.modifiers = MapLeftShiftMask;
440 }
441
442 DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));
443 }
444 else
445 {
446 DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));
447 }
448
449 return tr;
450 }
451
452 uint16
453 xkeymap_translate_button(unsigned int button)
454 {
455 switch (button)
456 {
457 case Button1: /* left */
458 return MOUSE_FLAG_BUTTON1;
459 case Button2: /* middle */
460 return MOUSE_FLAG_BUTTON3;
461 case Button3: /* right */
462 return MOUSE_FLAG_BUTTON2;
463 case Button4: /* wheel up */
464 return MOUSE_FLAG_BUTTON4;
465 case Button5: /* wheel down */
466 return MOUSE_FLAG_BUTTON5;
467 }
468
469 return 0;
470 }
471
472 char *
473 get_ksname(uint32 keysym)
474 {
475 char *ksname = NULL;
476
477 if (keysym == NoSymbol)
478 ksname = "NoSymbol";
479 else if (!(ksname = XKeysymToString(keysym)))
480 ksname = "(no name)";
481
482 return ksname;
483 }
484
485 static BOOL
486 is_modifier(uint8 scancode)
487 {
488 switch (scancode)
489 {
490 case SCANCODE_CHAR_LSHIFT:
491 case SCANCODE_CHAR_RSHIFT:
492 case SCANCODE_CHAR_LCTRL:
493 case SCANCODE_CHAR_RCTRL:
494 case SCANCODE_CHAR_LALT:
495 case SCANCODE_CHAR_RALT:
496 case SCANCODE_CHAR_LWIN:
497 case SCANCODE_CHAR_RWIN:
498 case SCANCODE_CHAR_NUMLOCK:
499 return True;
500 default:
501 break;
502 }
503 return False;
504 }
505
506 void
507 save_remote_modifiers(uint8 scancode)
508 {
509 if (is_modifier(scancode))
510 return;
511
512 saved_remote_modifier_state = remote_modifier_state;
513 }
514
515 void
516 restore_remote_modifiers(uint32 ev_time, uint8 scancode)
517 {
518 key_translation dummy;
519
520 if (is_modifier(scancode))
521 return;
522
523 dummy.scancode = 0;
524 dummy.modifiers = saved_remote_modifier_state;
525 ensure_remote_modifiers(ev_time, dummy);
526 }
527
528 void
529 ensure_remote_modifiers(uint32 ev_time, key_translation tr)
530 {
531 /* If this key is a modifier, do nothing */
532 if (is_modifier(tr.scancode))
533 return;
534
535 if (!g_numlock_sync)
536 {
537 /* NumLock */
538 if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)
539 != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask))
540 {
541 /* The remote modifier state is not correct */
542 uint16 new_remote_state;
543
544 if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask))
545 {
546 DEBUG_KBD(("Remote NumLock state is incorrect, activating NumLock.\n"));
547 new_remote_state = KBD_FLAG_NUMLOCK;
548 remote_modifier_state = MapNumLockMask;
549 }
550 else
551 {
552 DEBUG_KBD(("Remote NumLock state is incorrect, deactivating NumLock.\n"));
553 new_remote_state = 0;
554 remote_modifier_state = 0;
555 }
556
557 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0);
558 }
559 }
560
561
562 /* Shift. Left shift and right shift are treated as equal; either is fine. */
563 if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
564 != MASK_HAS_BITS(remote_modifier_state, MapShiftMask))
565 {
566 /* The remote modifier state is not correct */
567 if (MASK_HAS_BITS(tr.modifiers, MapLeftShiftMask))
568 {
569 /* Needs left shift. Send down. */
570 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LSHIFT);
571 }
572 else if (MASK_HAS_BITS(tr.modifiers, MapRightShiftMask))
573 {
574 /* Needs right shift. Send down. */
575 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RSHIFT);
576 }
577 else
578 {
579 /* Should not use this modifier. Send up for shift currently pressed. */
580 if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask))
581 /* Left shift is down */
582 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
583 else
584 /* Right shift is down */
585 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
586 }
587 }
588
589 /* AltGr */
590 if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask)
591 != MASK_HAS_BITS(remote_modifier_state, MapAltGrMask))
592 {
593 /* The remote modifier state is not correct */
594 if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask))
595 {
596 /* Needs this modifier. Send down. */
597 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RALT);
598 }
599 else
600 {
601 /* Should not use this modifier. Send up. */
602 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
603 }
604 }
605
606
607 }
608
609
610 unsigned int
611 read_keyboard_state()
612 {
613 #ifdef RDP2VNC
614 return 0;
615 #else
616 unsigned int state;
617 Window wdummy;
618 int dummy;
619
620 XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
621 return state;
622 #endif
623 }
624
625
626 uint16
627 ui_get_numlock_state(unsigned int state)
628 {
629 uint16 numlock_state = 0;
630
631 if (get_key_state(state, XK_Num_Lock))
632 numlock_state = KBD_FLAG_NUMLOCK;
633
634 return numlock_state;
635 }
636
637
638 void
639 reset_modifier_keys()
640 {
641 unsigned int state = read_keyboard_state();
642
643 /* reset keys */
644 uint32 ev_time;
645 ev_time = time(NULL);
646
647 if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask)
648 && !get_key_state(state, XK_Shift_L))
649 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
650
651 if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask)
652 && !get_key_state(state, XK_Shift_R))
653 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
654
655 if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask)
656 && !get_key_state(state, XK_Control_L))
657 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
658
659 if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask)
660 && !get_key_state(state, XK_Control_R))
661 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
662
663 if (MASK_HAS_BITS(remote_modifier_state, MapLeftAltMask) && !get_key_state(state, XK_Alt_L))
664 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
665
666 if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) &&
667 !get_key_state(state, XK_Alt_R) && !get_key_state(state, XK_Mode_switch)
668 && !get_key_state(state, XK_ISO_Level3_Shift))
669 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
670
671 reset_winkey(ev_time);
672
673 if (g_numlock_sync)
674 rdp_send_input(ev_time, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(state), 0);
675 }
676
677
678 static void
679 update_modifier_state(uint8 scancode, BOOL pressed)
680 {
681 #ifdef WITH_DEBUG_KBD
682 uint16 old_modifier_state;
683
684 old_modifier_state = remote_modifier_state;
685 #endif
686
687 switch (scancode)
688 {
689 case SCANCODE_CHAR_LSHIFT:
690 MASK_CHANGE_BIT(remote_modifier_state, MapLeftShiftMask, pressed);
691 break;
692 case SCANCODE_CHAR_RSHIFT:
693 MASK_CHANGE_BIT(remote_modifier_state, MapRightShiftMask, pressed);
694 break;
695 case SCANCODE_CHAR_LCTRL:
696 MASK_CHANGE_BIT(remote_modifier_state, MapLeftCtrlMask, pressed);
697 break;
698 case SCANCODE_CHAR_RCTRL:
699 MASK_CHANGE_BIT(remote_modifier_state, MapRightCtrlMask, pressed);
700 break;
701 case SCANCODE_CHAR_LALT:
702 MASK_CHANGE_BIT(remote_modifier_state, MapLeftAltMask, pressed);
703 break;
704 case SCANCODE_CHAR_RALT:
705 MASK_CHANGE_BIT(remote_modifier_state, MapRightAltMask, pressed);
706 break;
707 case SCANCODE_CHAR_LWIN:
708 MASK_CHANGE_BIT(remote_modifier_state, MapLeftWinMask, pressed);
709 break;
710 case SCANCODE_CHAR_RWIN:
711 MASK_CHANGE_BIT(remote_modifier_state, MapRightWinMask, pressed);
712 break;
713 case SCANCODE_CHAR_NUMLOCK:
714 /* KeyReleases for NumLocks are sent immediately. Toggle the
715 modifier state only on Keypress */
716 if (pressed && !g_numlock_sync)
717 {
718 BOOL newNumLockState;
719 newNumLockState =
720 (MASK_HAS_BITS
721 (remote_modifier_state, MapNumLockMask) == False);
722 MASK_CHANGE_BIT(remote_modifier_state,
723 MapNumLockMask, newNumLockState);
724 }
725 }
726
727 #ifdef WITH_DEBUG_KBD
728 if (old_modifier_state != remote_modifier_state)
729 {
730 DEBUG_KBD(("Before updating modifier_state:0x%x, pressed=0x%x\n",
731 old_modifier_state, pressed));
732 DEBUG_KBD(("After updating modifier_state:0x%x\n", remote_modifier_state));
733 }
734 #endif
735
736 }
737
738 /* Send keyboard input */
739 void
740 rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode)
741 {
742 update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));
743
744 if (scancode & SCANCODE_EXTENDED)
745 {
746 DEBUG_KBD(("Sending extended scancode=0x%x, flags=0x%x\n",
747 scancode & ~SCANCODE_EXTENDED, flags));
748 rdp_send_input(time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,
749 scancode & ~SCANCODE_EXTENDED, 0);
750 }
751 else
752 {
753 DEBUG_KBD(("Sending scancode=0x%x, flags=0x%x\n", scancode, flags));
754 rdp_send_input(time, RDP_INPUT_SCANCODE, flags, scancode, 0);
755 }
756 }

  ViewVC Help
Powered by ViewVC 1.1.26