/[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 706 - (show annotations)
Tue Jun 1 08:06:02 2004 UTC (19 years, 11 months ago) by astrand
File MIME type: text/plain
File size: 17767 byte(s)
Indent fixes

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

  ViewVC Help
Powered by ViewVC 1.1.26