ReactOS 0.4.15-dev-8428-g6910fa6
xkeymap.c
Go to the documentation of this file.
1/* -*- c-basic-offset: 8 -*-
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 along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 <string.h>
34#include "rdesktop.h"
35#include "scancodes.h"
36
37#define KEYMAP_MASK 0xffff
38#define KEYMAP_MAX_LINE_LENGTH 80
39
40static void update_modifier_state(RDPCLIENT * This, uint8 scancode, BOOL pressed);
41
42/* Free key_translation structure, including linked list */
43static void
45{
47
48 while (ptr)
49 {
50 next = ptr->next;
51 xfree(ptr);
52 ptr = next;
53 }
54}
55
56static void
57add_to_keymap(RDPCLIENT * This, char *keyname, uint8 scancode, uint16 modifiers, char *mapname)
58{
59 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 tr = (key_translation *) xmalloc(sizeof(key_translation));
73 memset(tr, 0, sizeof(key_translation));
74 tr->scancode = scancode;
75 tr->modifiers = modifiers;
76 free_key_translation(This->xkeymap.keymap[keysym & KEYMAP_MASK]);
77 This->xkeymap.keymap[keysym & KEYMAP_MASK] = tr;
78
79 return;
80}
81
82static void
83add_sequence(RDPCLIENT * This, char *rest, char *mapname)
84{
85 KeySym keysym;
86 key_translation *tr, **prev_next;
87 size_t chars;
88 char keyname[KEYMAP_MAX_LINE_LENGTH];
89
90 /* Skip over whitespace after the sequence keyword */
91 chars = strspn(rest, " \t");
92 rest += chars;
93
94 /* Fetch the keysym name */
95 chars = strcspn(rest, " \t\0");
96 STRNCPY(keyname, rest, chars + 1);
97 rest += chars;
98
99 keysym = XStringToKeysym(keyname);
100 if (keysym == NoSymbol)
101 {
102 DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring line)\n", keyname, mapname));
103 return;
104 }
105
106
107 DEBUG_KBD(("Adding sequence for keysym (0x%lx, %s) -> ", keysym, keyname));
108
109 free_key_translation(This->xkeymap.keymap[keysym & KEYMAP_MASK]);
110 prev_next = &This->xkeymap.keymap[keysym & KEYMAP_MASK];
111
112 while (*rest)
113 {
114 /* Skip whitespace */
115 chars = strspn(rest, " \t");
116 rest += chars;
117
118 /* Fetch the keysym name */
119 chars = strcspn(rest, " \t\0");
120 STRNCPY(keyname, rest, chars + 1);
121 rest += chars;
122
123 keysym = XStringToKeysym(keyname);
124 if (keysym == NoSymbol)
125 {
126 DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring line)\n", keyname,
127 mapname));
128 return;
129 }
130
131 /* Allocate space for key_translation structure */
132 tr = (key_translation *) xmalloc(sizeof(key_translation));
133 memset(tr, 0, sizeof(key_translation));
134 *prev_next = tr;
135 prev_next = &tr->next;
136 tr->seq_keysym = keysym;
137
138 DEBUG_KBD(("0x%x, ", (unsigned int) keysym));
139 }
140 DEBUG_KBD(("\n"));
141}
142
143BOOL
145{
146 char *str, *ptr;
147 FILE *fp;
148
149 /* Create a working copy */
150 str = xstrdup(locale);
151
152 /* Truncate at dot and at */
153 ptr = strrchr(str, '.');
154 if (ptr)
155 *ptr = '\0';
156 ptr = strrchr(str, '@');
157 if (ptr)
158 *ptr = '\0';
159
160 /* Replace _ with - */
161 ptr = strrchr(str, '_');
162 if (ptr)
163 *ptr = '-';
164
165 /* Convert to lowercase */
166 ptr = str;
167 while (*ptr)
168 {
169 *ptr = tolower((int) *ptr);
170 ptr++;
171 }
172
173 /* Try to open this keymap (da-dk) */
174 fp = xkeymap_open(str);
175 if (fp == NULL)
176 {
177 /* Truncate at dash */
178 ptr = strrchr(str, '-');
179 if (ptr)
180 *ptr = '\0';
181
182 /* Try the short name (da) */
183 fp = xkeymap_open(str);
184 }
185
186 if (fp)
187 {
188 fclose(fp);
189 STRNCPY(This->keymapname, str, sizeof(This->keymapname));
190 xfree(str);
191 return True;
192 }
193
194 xfree(str);
195 return False;
196}
197
198
199/* Joins two path components. The result should be freed with
200 xfree(). */
201static char *
202pathjoin(const char *a, const char *b)
203{
204 char *result;
205 result = xmalloc(PATH_MAX * 2 + 1);
206
207 if (b[0] == '/')
208 {
210 }
211 else
212 {
214 strcat(result, "/");
216 }
217 return result;
218}
219
220/* Try to open a keymap with fopen() */
221FILE *
223{
224 char *path1, *path2;
225 char *home;
226 FILE *fp;
227
228 /* Try ~/.rdesktop/keymaps */
229 home = getenv("HOME");
230 if (home)
231 {
232 path1 = pathjoin(home, ".rdesktop/keymaps");
234 xfree(path1);
235 fp = fopen(path2, "r");
236 xfree(path2);
237 if (fp)
238 return fp;
239 }
240
241 /* Try KEYMAP_PATH */
242 path1 = pathjoin(KEYMAP_PATH, filename);
243 fp = fopen(path1, "r");
244 xfree(path1);
245 if (fp)
246 return fp;
247
248 /* Try current directory, in case we are running from the source
249 tree */
250 path1 = pathjoin("keymaps", filename);
251 fp = fopen(path1, "r");
252 xfree(path1);
253 if (fp)
254 return fp;
255
256 return NULL;
257}
258
259static BOOL
260xkeymap_read(RDPCLIENT * This, char *mapname)
261{
262 FILE *fp;
264 unsigned int line_num = 0;
265 unsigned int line_length = 0;
266 char *keyname, *p;
267 char *line_rest;
268 uint8 scancode;
269 uint16 modifiers;
270
271 fp = xkeymap_open(mapname);
272 if (fp == NULL)
273 {
274 error("Failed to open keymap %s\n", mapname);
275 return False;
276 }
277
278 /* FIXME: More tolerant on white space */
279 while (fgets(line, sizeof(line), fp) != NULL)
280 {
281 line_num++;
282
283 /* Replace the \n with \0 */
284 p = strchr(line, '\n');
285 if (p != NULL)
286 *p = 0;
287
288 line_length = strlen(line);
289
290 /* Completely empty line */
291 if (strspn(line, " \t\n\r\f\v") == line_length)
292 {
293 continue;
294 }
295
296 /* Include */
297 if (str_startswith(line, "include "))
298 {
299 if (!xkeymap_read(This, line + sizeof("include ") - 1))
300 return False;
301 continue;
302 }
303
304 /* map */
305 if (str_startswith(line, "map "))
306 {
307 This->keylayout = strtoul(line + sizeof("map ") - 1, NULL, 16);
308 DEBUG_KBD(("Keylayout 0x%x\n", This->keylayout));
309 continue;
310 }
311
312 /* compose */
313 if (str_startswith(line, "enable_compose"))
314 {
315 DEBUG_KBD(("Enabling compose handling\n"));
316 This->enable_compose = True;
317 continue;
318 }
319
320 /* sequence */
321 if (str_startswith(line, "sequence"))
322 {
323 add_sequence(This, line + sizeof("sequence") - 1, mapname);
324 continue;
325 }
326
327 /* keyboard_type */
328 if (str_startswith(line, "keyboard_type "))
329 {
330 This->keyboard_type = strtol(line + sizeof("keyboard_type ") - 1, NULL, 16);
331 DEBUG_KBD(("keyboard_type 0x%x\n", This->keyboard_type));
332 continue;
333 }
334
335 /* keyboard_subtype */
336 if (str_startswith(line, "keyboard_subtype "))
337 {
338 This->keyboard_subtype =
339 strtol(line + sizeof("keyboard_subtype ") - 1, NULL, 16);
340 DEBUG_KBD(("keyboard_subtype 0x%x\n", This->keyboard_subtype));
341 continue;
342 }
343
344 /* keyboard_functionkeys */
345 if (str_startswith(line, "keyboard_functionkeys "))
346 {
347 This->keyboard_functionkeys =
348 strtol(line + sizeof("keyboard_functionkeys ") - 1, NULL, 16);
349 DEBUG_KBD(("keyboard_functionkeys 0x%x\n", This->keyboard_functionkeys));
350 continue;
351 }
352
353 /* Comment */
354 if (line[0] == '#')
355 {
356 continue;
357 }
358
359 /* Normal line */
360 keyname = line;
361 p = strchr(line, ' ');
362 if (p == NULL)
363 {
364 error("Bad line %d in keymap %s\n", line_num, mapname);
365 continue;
366 }
367 else
368 {
369 *p = 0;
370 }
371
372 /* scancode */
373 p++;
374 scancode = strtol(p, &line_rest, 16);
375
376 /* flags */
377 /* FIXME: Should allow case-insensitive flag names.
378 Fix by using lex+yacc... */
379 modifiers = 0;
380 if (strstr(line_rest, "altgr"))
381 {
382 MASK_ADD_BITS(modifiers, MapAltGrMask);
383 }
384
385 if (strstr(line_rest, "shift"))
386 {
388 }
389
390 if (strstr(line_rest, "numlock"))
391 {
392 MASK_ADD_BITS(modifiers, MapNumLockMask);
393 }
394
395 if (strstr(line_rest, "localstate"))
396 {
398 }
399
400 if (strstr(line_rest, "inhibit"))
401 {
402 MASK_ADD_BITS(modifiers, MapInhibitMask);
403 }
404
405 add_to_keymap(This, keyname, scancode, modifiers, mapname);
406
407 if (strstr(line_rest, "addupper"))
408 {
409 /* Automatically add uppercase key, with same modifiers
410 plus shift */
411 for (p = keyname; *p; p++)
412 *p = toupper((int) *p);
414 add_to_keymap(This, keyname, scancode, modifiers, mapname);
415 }
416 }
417
418 fclose(fp);
419 return True;
420}
421
422
423/* Before connecting and creating UI */
424void
426{
427 unsigned int max_keycode;
428
429 if (strcmp(This->keymapname, "none"))
430 {
431 if (xkeymap_read(This, This->keymapname))
432 This->xkeymap.keymap_loaded = True;
433 }
434
435 XDisplayKeycodes(This->display, &This->xkeymap.min_keycode, (int *) &max_keycode);
436}
437
438static void
439send_winkey(RDPCLIENT * This, uint32 ev_time, BOOL pressed, BOOL leftkey)
440{
441 uint8 winkey;
442
443 if (leftkey)
444 winkey = SCANCODE_CHAR_LWIN;
445 else
446 winkey = SCANCODE_CHAR_RWIN;
447
448 if (pressed)
449 {
450 if (This->use_rdp5)
451 {
452 rdp_send_scancode(This, ev_time, RDP_KEYPRESS, winkey);
453 }
454 else
455 {
456 /* RDP4 doesn't support winkey. Fake with Ctrl-Esc */
459 }
460 }
461 else
462 {
463 /* key released */
464 if (This->use_rdp5)
465 {
466 rdp_send_scancode(This, ev_time, RDP_KEYRELEASE, winkey);
467 }
468 else
469 {
472 }
473 }
474}
475
476static void
478{
479 if (This->use_rdp5)
480 {
481 /* For some reason, it seems to suffice to release
482 *either* the left or right winkey. */
484 }
485}
486
487/* Handle special key combinations */
488BOOL
489handle_special_keys(RDPCLIENT * This, uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)
490{
491 switch (keysym)
492 {
493 case XK_Return:
494 if ((get_key_state(This, state, XK_Alt_L) || get_key_state(This, state, XK_Alt_R))
495 && (get_key_state(This, state, XK_Control_L)
496 || get_key_state(This, state, XK_Control_R)))
497 {
498 /* Ctrl-Alt-Enter: toggle full screen */
499 if (pressed)
501 return True;
502 }
503 break;
504
505 case XK_Break:
506 /* Send Break sequence E0 46 E0 C6 */
507 if (pressed)
508 {
510 (SCANCODE_EXTENDED | 0x46));
512 (SCANCODE_EXTENDED | 0xc6));
513 }
514 /* No release sequence */
515 return True;
516 break;
517
518 case XK_Pause:
519 /* According to MS Keyboard Scan Code
520 Specification, pressing Pause should result
521 in E1 1D 45 E1 9D C5. I'm not exactly sure
522 of how this is supposed to be sent via
523 RDP. The code below seems to work, but with
524 the side effect that Left Ctrl stays
525 down. Therefore, we release it when Pause
526 is released. */
527 if (pressed)
528 {
535 }
536 else
537 {
538 /* Release Left Ctrl */
540 0x1d, 0);
541 }
542 return True;
543 break;
544
545 case XK_Meta_L: /* Windows keys */
546 case XK_Super_L:
547 case XK_Hyper_L:
548 send_winkey(This, ev_time, pressed, True);
549 return True;
550 break;
551
552 case XK_Meta_R:
553 case XK_Super_R:
554 case XK_Hyper_R:
555 send_winkey(This, ev_time, pressed, False);
556 return True;
557 break;
558
559 case XK_space:
560 /* Prevent access to the Windows system menu in single app mode */
561 if (This->win_button_size
562 && (get_key_state(This, state, XK_Alt_L) || get_key_state(This, state, XK_Alt_R)))
563 return True;
564 break;
565
566 case XK_Num_Lock:
567 /* Synchronize on key release */
568 if (This->numlock_sync && !pressed)
571
572 /* Inhibit */
573 return True;
574 break;
575 case XK_Overlay1_Enable:
576 /* Toggle SeamlessRDP */
577 if (pressed)
579 break;
580
581 }
582 return False;
583}
584
585
587xkeymap_translate_key(RDPCLIENT * This, uint32 keysym, unsigned int keycode, unsigned int state)
588{
589 key_translation tr = { 0, 0, 0, 0 };
591
592 ptr = This->xkeymap.keymap[keysym & KEYMAP_MASK];
593 if (ptr)
594 {
595 tr = *ptr;
596 if (tr.seq_keysym == 0) /* Normal scancode translation */
597 {
599 {
600 DEBUG_KBD(("Inhibiting key\n"));
601 tr.scancode = 0;
602 return tr;
603 }
604
606 {
607 /* The modifiers to send for this key should be obtained
608 from the local state. Currently, only shift is implemented. */
610 {
612 }
613 }
614
615 /* Windows interprets CapsLock+Ctrl+key
616 differently from Shift+Ctrl+key. Since we
617 are simulating CapsLock with Shifts, things
618 like Ctrl+f with CapsLock on breaks. To
619 solve this, we are releasing Shift if Ctrl
620 is on, but only if Shift isn't physically pressed. */
622 && MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapCtrlMask)
624 {
625 DEBUG_KBD(("Non-physical Shift + Ctrl pressed, releasing Shift\n"));
627 }
628
629 DEBUG_KBD(("Found scancode translation, scancode=0x%x, modifiers=0x%x\n",
630 tr.scancode, tr.modifiers));
631 }
632 }
633 else
634 {
635 if (This->xkeymap.keymap_loaded)
636 warning("No translation for (keysym 0x%lx, %s)\n", keysym,
637 get_ksname(keysym));
638
639 /* not in keymap, try to interpret the raw scancode */
640 if (((int) keycode >= This->xkeymap.min_keycode) && (keycode <= 0x60))
641 {
642 tr.scancode = keycode - This->xkeymap.min_keycode;
643
644 /* The modifiers to send for this key should be
645 obtained from the local state. Currently, only
646 shift is implemented. */
648 {
650 }
651
652 DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));
653 }
654 else
655 {
656 DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));
657 }
658 }
659
660 return tr;
661}
662
663void
664xkeymap_send_keys(RDPCLIENT * This, uint32 keysym, unsigned int keycode, unsigned int state, uint32 ev_time,
665 BOOL pressed, uint8 nesting)
666{
667 key_translation tr, *ptr;
668 tr = xkeymap_translate_key(This, keysym, keycode, state);
669
670 if (tr.seq_keysym == 0)
671 {
672 /* Scancode translation */
673 if (tr.scancode == 0)
674 return;
675
676 if (pressed)
677 {
679 ensure_remote_modifiers(This, ev_time, tr);
682 }
683 else
684 {
686 }
687 return;
688 }
689
690 /* Sequence, only on key down */
691 if (pressed)
692 {
693 ptr = &tr;
694 do
695 {
696 DEBUG_KBD(("Handling sequence element, keysym=0x%x\n",
697 (unsigned int) ptr->seq_keysym));
698
699 if (nesting++ > 32)
700 {
701 error("Sequence nesting too deep\n");
702 return;
703 }
704
705 xkeymap_send_keys(This, ptr->seq_keysym, keycode, state, ev_time, True, nesting);
706 xkeymap_send_keys(This, ptr->seq_keysym, keycode, state, ev_time, False, nesting);
707 ptr = ptr->next;
708 }
709 while (ptr);
710 }
711}
712
713uint16
715{
716 switch (button)
717 {
718 case Button1: /* left */
719 return MOUSE_FLAG_BUTTON1;
720 case Button2: /* middle */
721 return MOUSE_FLAG_BUTTON3;
722 case Button3: /* right */
723 return MOUSE_FLAG_BUTTON2;
724 case Button4: /* wheel up */
725 return MOUSE_FLAG_BUTTON4;
726 case Button5: /* wheel down */
727 return MOUSE_FLAG_BUTTON5;
728 }
729
730 return 0;
731}
732
733char *
735{
736 char *ksname = NULL;
737
738 if (keysym == NoSymbol)
739 ksname = "NoSymbol";
740 else if (!(ksname = XKeysymToString(keysym)))
741 ksname = "(no name)";
742
743 return ksname;
744}
745
746static BOOL
748{
749 switch (scancode)
750 {
760 return True;
761 default:
762 break;
763 }
764 return False;
765}
766
767void
769{
770 if (is_modifier(scancode))
771 return;
772
773 This->xkeymap.saved_remote_modifier_state = This->xkeymap.remote_modifier_state;
774}
775
776void
778{
780
781 if (is_modifier(scancode))
782 return;
783
784 dummy.scancode = 0;
785 dummy.modifiers = This->xkeymap.saved_remote_modifier_state;
787}
788
789void
791{
792 /* If this key is a modifier, do nothing */
793 if (is_modifier(tr.scancode))
794 return;
795
796 if (!This->numlock_sync)
797 {
798 /* NumLock */
800 != MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapNumLockMask))
801 {
802 /* The remote modifier state is not correct */
803 uint16 new_remote_state;
804
806 {
807 DEBUG_KBD(("Remote NumLock state is incorrect, activating NumLock.\n"));
808 new_remote_state = KBD_FLAG_NUMLOCK;
809 This->xkeymap.remote_modifier_state = MapNumLockMask;
810 }
811 else
812 {
813 DEBUG_KBD(("Remote NumLock state is incorrect, deactivating NumLock.\n"));
814 new_remote_state = 0;
815 This->xkeymap.remote_modifier_state = 0;
816 }
817
818 rdp_send_input(This, 0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0);
819 }
820 }
821
822
823 /* Shift. Left shift and right shift are treated as equal; either is fine. */
825 != MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapShiftMask))
826 {
827 /* The remote modifier state is not correct */
829 {
830 /* Needs left shift. Send down. */
832 }
834 {
835 /* Needs right shift. Send down. */
837 }
838 else
839 {
840 /* Should not use this modifier. Send up for shift currently pressed. */
841 if (MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapLeftShiftMask))
842 /* Left shift is down */
844 else
845 /* Right shift is down */
847 }
848 }
849
850 /* AltGr */
852 != MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapAltGrMask))
853 {
854 /* The remote modifier state is not correct */
856 {
857 /* Needs this modifier. Send down. */
859 }
860 else
861 {
862 /* Should not use this modifier. Send up. */
864 }
865 }
866
867
868}
869
870
871unsigned int
873{
874#ifdef RDP2VNC
875 return 0;
876#else
877 unsigned int state;
878 Window wdummy;
879 int dummy;
880
881 XQueryPointer(This->display, This->wnd, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
882 return state;
883#endif
884}
885
886
887uint16
889{
890 uint16 numlock_state = 0;
891
892 if (get_key_state(This, state, XK_Num_Lock))
893 numlock_state = KBD_FLAG_NUMLOCK;
894
895 return numlock_state;
896}
897
898
899void
901{
902 unsigned int state = read_keyboard_state(This);
903
904 /* reset keys */
905 uint32 ev_time;
906 ev_time = time(NULL);
907
908 if (MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapLeftShiftMask)
909 && !get_key_state(This, state, XK_Shift_L))
911
912 if (MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapRightShiftMask)
913 && !get_key_state(This, state, XK_Shift_R))
915
916 if (MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapLeftCtrlMask)
917 && !get_key_state(This, state, XK_Control_L))
919
920 if (MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapRightCtrlMask)
921 && !get_key_state(This, state, XK_Control_R))
923
924 if (MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapLeftAltMask) && !get_key_state(This, state, XK_Alt_L))
926
927 if (MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapRightAltMask) &&
928 !get_key_state(This, state, XK_Alt_R) && !get_key_state(This, state, XK_Mode_switch)
929 && !get_key_state(This, state, XK_ISO_Level3_Shift))
931
932 reset_winkey(This, ev_time);
933
934 if (This->numlock_sync)
936}
937
938
939static void
941{
942#ifdef WITH_DEBUG_KBD
943 uint16 old_modifier_state;
944
945 old_modifier_state = This->xkeymap.remote_modifier_state;
946#endif
947
948 switch (scancode)
949 {
951 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapLeftShiftMask, pressed);
952 break;
954 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapRightShiftMask, pressed);
955 break;
957 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapLeftCtrlMask, pressed);
958 break;
960 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapRightCtrlMask, pressed);
961 break;
963 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapLeftAltMask, pressed);
964 break;
966 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapRightAltMask, pressed);
967 break;
969 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapLeftWinMask, pressed);
970 break;
972 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapRightWinMask, pressed);
973 break;
975 /* KeyReleases for NumLocks are sent immediately. Toggle the
976 modifier state only on Keypress */
977 if (pressed && !This->numlock_sync)
978 {
979 BOOL newNumLockState;
980 newNumLockState =
982 (This->xkeymap.remote_modifier_state, MapNumLockMask) == False);
983 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state,
984 MapNumLockMask, newNumLockState);
985 }
986 }
987
988#ifdef WITH_DEBUG_KBD
989 if (old_modifier_state != This->xkeymap.remote_modifier_state)
990 {
991 DEBUG_KBD(("Before updating modifier_state:0x%x, pressed=0x%x\n",
992 old_modifier_state, pressed));
993 DEBUG_KBD(("After updating modifier_state:0x%x\n", This->xkeymap.remote_modifier_state));
994 }
995#endif
996
997}
998
999/* Send keyboard input */
1000void
1002{
1004
1005 if (scancode & SCANCODE_EXTENDED)
1006 {
1007 DEBUG_KBD(("Sending extended scancode=0x%x, flags=0x%x\n",
1008 scancode & ~SCANCODE_EXTENDED, flags));
1010 scancode & ~SCANCODE_EXTENDED, 0);
1011 }
1012 else
1013 {
1014 DEBUG_KBD(("Sending scancode=0x%x, flags=0x%x\n", scancode, flags));
1016 }
1017}
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
char * strncat(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:605
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int toupper(int c)
Definition: utclib.c:881
int tolower(int c)
Definition: utclib.c:902
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
char * strchr(const char *String, int ch)
Definition: utclib.c:501
static int state
Definition: maze.c:121
#define MapRightWinMask
Definition: constants.h:375
#define RDP_KEYPRESS
Definition: constants.h:251
#define MapCtrlMask
Definition: constants.h:373
#define MOUSE_FLAG_BUTTON5
Definition: constants.h:259
#define MapRightShiftMask
Definition: constants.h:363
#define MapLocalStateMask
Definition: constants.h:382
#define KBD_FLAG_NUMLOCK
Definition: constants.h:247
#define MapLeftCtrlMask
Definition: constants.h:372
#define RDP_KEYRELEASE
Definition: constants.h:252
#define MOUSE_FLAG_BUTTON1
Definition: constants.h:255
#define MapNumLockMask
Definition: constants.h:379
#define MapRightCtrlMask
Definition: constants.h:371
#define MOUSE_FLAG_BUTTON2
Definition: constants.h:256
#define MapRightAltMask
Definition: constants.h:367
#define MapLeftWinMask
Definition: constants.h:376
#define MOUSE_FLAG_BUTTON4
Definition: constants.h:258
#define MASK_REMOVE_BITS(var, mask)
Definition: constants.h:387
#define MOUSE_FLAG_BUTTON3
Definition: constants.h:257
#define MapAltGrMask
Definition: constants.h:369
#define MASK_CHANGE_BIT(var, mask, active)
Definition: constants.h:389
@ RDP_INPUT_SYNCHRONIZE
Definition: constants.h:231
@ RDP_INPUT_SCANCODE
Definition: constants.h:234
#define MapInhibitMask
Definition: constants.h:384
#define MASK_HAS_BITS(var, mask)
Definition: constants.h:388
#define KBD_FLAG_EXT
Definition: constants.h:240
#define MapShiftMask
Definition: constants.h:365
#define MapLeftShiftMask
Definition: constants.h:364
#define MASK_ADD_BITS(var, mask)
Definition: constants.h:386
#define MapLeftAltMask
Definition: constants.h:368
void xfree(void *mem)
Definition: uimain.c:758
void reset_modifier_keys(void)
RD_BOOL str_startswith(const char *s, const char *prefix)
Definition: rdesktop.c:1235
char * xstrdup(const char *s)
Definition: uimain.c:768
unsigned int read_keyboard_state(void)
Definition: uimain.c:632
void ui_seamless_toggle(void)
void rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
Definition: rdp.c:551
void xkeymap_init(void)
void xwin_toggle_fullscreen(void)
Definition: vnc.c:124
RD_BOOL get_key_state(unsigned int state, uint32 keysym)
Definition: vnc.c:146
void * xmalloc(int size)
Definition: uimain.c:747
#define STRNCPY(dst, src, n)
Definition: rdesktop.h:168
#define DEBUG_KBD(args)
Definition: rdesktop.h:135
unsigned short uint16
Definition: types.h:30
unsigned int uint32
Definition: types.h:32
#define False
Definition: types.h:25
#define True
Definition: types.h:24
unsigned char uint8
Definition: types.h:28
#define PATH_MAX
Definition: types.h:280
Definition: _locale.h:75
#define NULL
Definition: types.h:112
unsigned int BOOL
Definition: ntddk_ex.h:94
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLbitfield flags
Definition: glext.h:7161
GLfloat GLfloat p
Definition: glext.h:8902
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLuint64EXT * result
Definition: glext.h:11304
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ long __cdecl strtol(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix)
_Check_return_ char *__cdecl getenv(_In_z_ const char *_VarName)
const char * filename
Definition: ioapi.h:137
__u16 time
Definition: mkdosfs.c:8
#define error(str)
Definition: mkdosfs.c:1605
static PVOID ptr
Definition: dispmode.c:27
DWORD button
Definition: button.c:166
static const WCHAR path1[]
Definition: path.c:28
static const WCHAR path2[]
Definition: path.c:29
static unsigned __int64 next
Definition: rand_nt.c:6
const WCHAR * str
#define SCANCODE_CHAR_RALT
Definition: scancodes.h:209
#define SCANCODE_CHAR_NUMLOCK
Definition: scancodes.h:255
#define SCANCODE_EXTENDED
Definition: scancodes.h:24
#define SCANCODE_CHAR_RCTRL
Definition: scancodes.h:214
#define SCANCODE_CHAR_ESC
Definition: scancodes.h:313
#define SCANCODE_CHAR_LALT
Definition: scancodes.h:203
#define SCANCODE_CHAR_LWIN
Definition: scancodes.h:366
#define SCANCODE_CHAR_LCTRL
Definition: scancodes.h:198
#define SCANCODE_CHAR_LSHIFT
Definition: scancodes.h:156
#define SCANCODE_CHAR_RSHIFT
Definition: scancodes.h:195
#define SCANCODE_CHAR_RWIN
Definition: scancodes.h:368
_Check_return_ _CRTIMP size_t __cdecl strspn(_In_z_ const char *_Str, _In_z_ const char *_Control)
_Check_return_ _CRTIMP size_t __cdecl strcspn(_In_z_ const char *_Str, _In_z_ const char *_Control)
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
#define warning(s)
Definition: debug.h:83
#define memset(x, y, z)
Definition: compat.h:39
Definition: window.c:28
uint16 modifiers
Definition: types.h:133
uint8 scancode
Definition: types.h:132
uint32 seq_keysym
Definition: types.h:135
struct _key_translation * next
Definition: types.h:136
Definition: tftpd.h:38
Definition: parser.c:49
void XDisplayKeycodes(Display *display, int *min_keycode, int *max_keycode)
Definition: x11stubs.c:1400
const char * XKeysymToString(KeySym keysym)
Definition: x11stubs.c:1391
KeySym XStringToKeysym(const char *str)
Definition: x11stubs.c:1382
#define Button1
Definition: x11stubs.h:19
#define Button3
Definition: x11stubs.h:21
#define ShiftMask
Definition: x11stubs.h:11
#define NoSymbol
Definition: x11stubs.h:10
rfbKeySym KeySym
Definition: x11stubs.h:27
#define Button2
Definition: x11stubs.h:20
#define Button5
Definition: x11stubs.h:23
#define Button4
Definition: x11stubs.h:22
static BOOL is_modifier(uint8 scancode)
Definition: xkeymap.c:747
void rdp_send_scancode(RDPCLIENT *This, uint32 time, uint16 flags, uint8 scancode)
Definition: xkeymap.c:1001
FILE * xkeymap_open(const char *filename)
Definition: xkeymap.c:222
void restore_remote_modifiers(RDPCLIENT *This, uint32 ev_time, uint8 scancode)
Definition: xkeymap.c:777
static char * pathjoin(const char *a, const char *b)
Definition: xkeymap.c:202
static void update_modifier_state(RDPCLIENT *This, uint8 scancode, BOOL pressed)
Definition: xkeymap.c:940
#define KEYMAP_MAX_LINE_LENGTH
Definition: xkeymap.c:38
char * get_ksname(uint32 keysym)
Definition: xkeymap.c:734
void ensure_remote_modifiers(RDPCLIENT *This, uint32 ev_time, key_translation tr)
Definition: xkeymap.c:790
BOOL handle_special_keys(RDPCLIENT *This, uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)
Definition: xkeymap.c:489
static void add_sequence(RDPCLIENT *This, char *rest, char *mapname)
Definition: xkeymap.c:83
void save_remote_modifiers(RDPCLIENT *This, uint8 scancode)
Definition: xkeymap.c:768
static BOOL xkeymap_read(RDPCLIENT *This, char *mapname)
Definition: xkeymap.c:260
static void send_winkey(RDPCLIENT *This, uint32 ev_time, BOOL pressed, BOOL leftkey)
Definition: xkeymap.c:439
#define KEYMAP_MASK
Definition: xkeymap.c:37
static void reset_winkey(RDPCLIENT *This, uint32 ev_time)
Definition: xkeymap.c:477
uint16 xkeymap_translate_button(unsigned int button)
Definition: xkeymap.c:714
BOOL xkeymap_from_locale(RDPCLIENT *This, const char *locale)
Definition: xkeymap.c:144
static void free_key_translation(key_translation *ptr)
Definition: xkeymap.c:44
key_translation xkeymap_translate_key(RDPCLIENT *This, uint32 keysym, unsigned int keycode, unsigned int state)
Definition: xkeymap.c:587
void xkeymap_send_keys(RDPCLIENT *This, uint32 keysym, unsigned int keycode, unsigned int state, uint32 ev_time, BOOL pressed, uint8 nesting)
Definition: xkeymap.c:664
static void add_to_keymap(RDPCLIENT *This, char *keyname, uint8 scancode, uint16 modifiers, char *mapname)
Definition: xkeymap.c:57
uint16 ui_get_numlock_state(RDPCLIENT *This, unsigned int state)
Definition: xkeymap.c:888