/[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 894 - (show annotations)
Mon Apr 25 05:32:23 2005 UTC (19 years, 1 month ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/xkeymap.c
File MIME type: text/plain
File size: 18034 byte(s)
disable caps_lock fix.
this killed ctrl-alt-entf. need to llook into that later

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

  ViewVC Help
Powered by ViewVC 1.1.26