/[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 552 - (show annotations)
Mon Dec 8 12:01:25 2003 UTC (20 years, 5 months ago) by astrand
File MIME type: text/plain
File size: 17618 byte(s)
Reverted to the old numlock-state code. The numlock sync can be enabled via new option -N

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

  ViewVC Help
Powered by ViewVC 1.1.26