ReactOS  0.4.13-dev-563-g0561610
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 
40 static void update_modifier_state(RDPCLIENT * This, uint8 scancode, BOOL pressed);
41 
42 /* Free key_translation structure, including linked list */
43 static void
45 {
47 
48  while (ptr)
49  {
50  next = ptr->next;
51  xfree(ptr);
52  ptr = next;
53  }
54 }
55 
56 static void
57 add_to_keymap(RDPCLIENT * This, char *keyname, uint8 scancode, uint16 modifiers, char *mapname)
58 {
59  KeySym keysym;
60  key_translation *tr;
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 
82 static void
83 add_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 
143 BOOL
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(). */
201 static char *
202 pathjoin(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() */
221 FILE *
222 xkeymap_open(const char *filename)
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 
259 static BOOL
260 xkeymap_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  {
387  MASK_ADD_BITS(modifiers, MapLeftShiftMask);
388  }
389 
390  if (strstr(line_rest, "numlock"))
391  {
392  MASK_ADD_BITS(modifiers, MapNumLockMask);
393  }
394 
395  if (strstr(line_rest, "localstate"))
396  {
397  MASK_ADD_BITS(modifiers, MapLocalStateMask);
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);
413  MASK_ADD_BITS(modifiers, MapLeftShiftMask);
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 */
424 void
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 
438 static void
439 send_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 
476 static 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 */
488 BOOL
489 handle_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  {
529  rdp_send_input(This, ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
530  rdp_send_input(This, ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0);
531  rdp_send_input(This, ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x45, 0);
532  rdp_send_input(This, ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
533  rdp_send_input(This, ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x9d, 0);
534  rdp_send_input(This, ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xc5, 0);
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 
587 xkeymap_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 
663 void
664 xkeymap_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);
681  restore_remote_modifiers(This, ev_time, tr.scancode);
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 
713 uint16
714 xkeymap_translate_button(unsigned int button)
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 
733 char *
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 
746 static BOOL
748 {
749  switch (scancode)
750  {
753  case SCANCODE_CHAR_LCTRL:
754  case SCANCODE_CHAR_RCTRL:
755  case SCANCODE_CHAR_LALT:
756  case SCANCODE_CHAR_RALT:
757  case SCANCODE_CHAR_LWIN:
758  case SCANCODE_CHAR_RWIN:
760  return True;
761  default:
762  break;
763  }
764  return False;
765 }
766 
767 void
769 {
770  if (is_modifier(scancode))
771  return;
772 
773  This->xkeymap.saved_remote_modifier_state = This->xkeymap.remote_modifier_state;
774 }
775 
776 void
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 
789 void
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 
871 unsigned 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 
887 uint16
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 
899 void
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 
939 static 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;
956  case SCANCODE_CHAR_LCTRL:
957  MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapLeftCtrlMask, pressed);
958  break;
959  case SCANCODE_CHAR_RCTRL:
960  MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapRightCtrlMask, pressed);
961  break;
962  case SCANCODE_CHAR_LALT:
963  MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapLeftAltMask, pressed);
964  break;
965  case SCANCODE_CHAR_RALT:
966  MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapRightAltMask, pressed);
967  break;
968  case SCANCODE_CHAR_LWIN:
969  MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapLeftWinMask, pressed);
970  break;
971  case SCANCODE_CHAR_RWIN:
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 */
1000 void
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));
1015  rdp_send_input(This, time, RDP_INPUT_SCANCODE, flags, scancode, 0);
1016  }
1017 }
#define Button4
Definition: x11stubs.h:22
static const WCHAR path2[]
Definition: path.c:29
#define NoSymbol
Definition: x11stubs.h:10
#define DEBUG_KBD(args)
Definition: rdesktop.h:135
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
#define RDP_KEYPRESS
Definition: constants.h:251
RD_BOOL str_startswith(const char *s, const char *prefix)
Definition: rdesktop.c:1235
#define MapLeftShiftMask
Definition: constants.h:364
void xkeymap_init(RDPCLIENT *This)
Definition: xkeymap.c:425
#define SCANCODE_CHAR_RALT
Definition: scancodes.h:209
#define MASK_CHANGE_BIT(var, mask, active)
Definition: constants.h:389
void reset_modifier_keys(RDPCLIENT *This)
Definition: xkeymap.c:900
#define MASK_REMOVE_BITS(var, mask)
Definition: constants.h:387
#define error(str)
Definition: mkdosfs.c:1605
char * strncat(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:605
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
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
#define SCANCODE_CHAR_RSHIFT
Definition: scancodes.h:195
static void add_sequence(RDPCLIENT *This, char *rest, char *mapname)
Definition: xkeymap.c:83
void ui_seamless_toggle(void)
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define SCANCODE_CHAR_ESC
Definition: scancodes.h:313
#define SCANCODE_CHAR_LWIN
Definition: scancodes.h:366
#define MapLeftAltMask
Definition: constants.h:368
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
_Check_return_ _CRTIMP size_t __cdecl strcspn(_In_z_ const char *_Str, _In_z_ const char *_Control)
unsigned int uint32
Definition: types.h:32
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
#define MapRightShiftMask
Definition: constants.h:363
static void send_winkey(RDPCLIENT *This, uint32 ev_time, BOOL pressed, BOOL leftkey)
Definition: xkeymap.c:439
#define STRNCPY(dst, src, n)
Definition: rdesktop.h:168
#define Button1
Definition: x11stubs.h:19
#define MOUSE_FLAG_BUTTON1
Definition: constants.h:255
_Check_return_ _CRTIMP size_t __cdecl strspn(_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)
struct _key_translation * next
Definition: types.h:136
__u16 time
Definition: mkdosfs.c:366
#define MASK_ADD_BITS(var, mask)
Definition: constants.h:386
const char * filename
Definition: ioapi.h:135
#define MapAltGrMask
Definition: constants.h:369
key_translation xkeymap_translate_key(RDPCLIENT *This, uint32 keysym, unsigned int keycode, unsigned int state)
Definition: xkeymap.c:587
uint16 xkeymap_translate_button(unsigned int button)
Definition: xkeymap.c:714
#define MOUSE_FLAG_BUTTON4
Definition: constants.h:258
unsigned int read_keyboard_state(RDPCLIENT *This)
Definition: xkeymap.c:872
const char * XKeysymToString(KeySym keysym)
Definition: x11stubs.c:1391
static void reset_winkey(RDPCLIENT *This, uint32 ev_time)
Definition: xkeymap.c:477
Definition: window.c:29
void * xmalloc(int size)
Definition: uimain.c:747
Definition: _locale.h:75
#define MapLocalStateMask
Definition: constants.h:382
unsigned int BOOL
Definition: ntddk_ex.h:94
void restore_remote_modifiers(RDPCLIENT *This, uint32 ev_time, uint8 scancode)
Definition: xkeymap.c:777
#define MapRightWinMask
Definition: constants.h:375
static PVOID ptr
Definition: dispmode.c:27
void xwin_toggle_fullscreen(void)
Definition: vnc.c:124
KeySym XStringToKeysym(const char *str)
Definition: x11stubs.c:1382
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
#define SCANCODE_CHAR_RCTRL
Definition: scancodes.h:214
#define MapNumLockMask
Definition: constants.h:379
Definition: parser.c:48
void XDisplayKeycodes(Display *display, int *min_keycode, int *max_keycode)
Definition: x11stubs.c:1400
#define MOUSE_FLAG_BUTTON3
Definition: constants.h:257
static const WCHAR path1[]
Definition: path.c:28
#define SCANCODE_CHAR_LCTRL
Definition: scancodes.h:198
BOOL handle_special_keys(RDPCLIENT *This, uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)
Definition: xkeymap.c:489
#define MapLeftWinMask
Definition: constants.h:376
#define True
Definition: types.h:24
uint16 ui_get_numlock_state(RDPCLIENT *This, unsigned int state)
Definition: xkeymap.c:888
BOOL xkeymap_from_locale(RDPCLIENT *This, const char *locale)
Definition: xkeymap.c:144
#define Button3
Definition: x11stubs.h:21
void rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
Definition: rdp.c:551
int toupper(int c)
Definition: utclib.c:881
#define MASK_HAS_BITS(var, mask)
Definition: constants.h:388
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define False
Definition: types.h:25
void xfree(void *mem)
Definition: uimain.c:758
#define KEYMAP_MASK
Definition: xkeymap.c:37
#define ShiftMask
Definition: x11stubs.h:11
uint32 seq_keysym
Definition: types.h:135
Definition: tftpd.h:37
#define KBD_FLAG_EXT
Definition: constants.h:240
#define PATH_MAX
Definition: types.h:280
unsigned char uint8
Definition: types.h:28
#define SCANCODE_EXTENDED
Definition: scancodes.h:24
GLbitfield flags
Definition: glext.h:7161
#define MapRightCtrlMask
Definition: constants.h:371
void save_remote_modifiers(RDPCLIENT *This, uint8 scancode)
Definition: xkeymap.c:768
#define SCANCODE_CHAR_LSHIFT
Definition: scancodes.h:156
char line[200]
Definition: main.c:97
#define Button2
Definition: x11stubs.h:20
char home[]
Definition: main.c:47
static int state
Definition: maze.c:121
FILE * xkeymap_open(const char *filename)
Definition: xkeymap.c:222
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
#define SCANCODE_CHAR_NUMLOCK
Definition: scancodes.h:255
#define MapShiftMask
Definition: constants.h:365
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
static unsigned __int64 next
Definition: rand_nt.c:6
_Check_return_ char *__cdecl getenv(_In_z_ const char *_VarName)
#define MOUSE_FLAG_BUTTON5
Definition: constants.h:259
uint8 scancode
Definition: types.h:132
static void update_modifier_state(RDPCLIENT *This, uint8 scancode, BOOL pressed)
Definition: xkeymap.c:940
unsigned char dummy
Definition: maze.c:118
#define KEYMAP_MAX_LINE_LENGTH
Definition: xkeymap.c:38
unsigned short uint16
Definition: types.h:30
static void free_key_translation(key_translation *ptr)
Definition: xkeymap.c:44
rfbKeySym KeySym
Definition: x11stubs.h:27
void ensure_remote_modifiers(RDPCLIENT *This, uint32 ev_time, key_translation tr)
Definition: xkeymap.c:790
static BOOL xkeymap_read(RDPCLIENT *This, char *mapname)
Definition: xkeymap.c:260
#define MapRightAltMask
Definition: constants.h:367
#define SCANCODE_CHAR_RWIN
Definition: scancodes.h:368
char * strchr(const char *String, int ch)
Definition: utclib.c:501
static void add_to_keymap(RDPCLIENT *This, char *keyname, uint8 scancode, uint16 modifiers, char *mapname)
Definition: xkeymap.c:57
#define MapCtrlMask
Definition: constants.h:373
#define MOUSE_FLAG_BUTTON2
Definition: constants.h:256
_Check_return_ long __cdecl strtol(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix)
RD_BOOL get_key_state(unsigned int state, uint32 keysym)
Definition: vnc.c:146
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define RDP_KEYRELEASE
Definition: constants.h:252
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
static char * pathjoin(const char *a, const char *b)
Definition: xkeymap.c:202
GLfloat GLfloat p
Definition: glext.h:8902
char * xstrdup(const char *s)
Definition: uimain.c:768
#define MapInhibitMask
Definition: constants.h:384
#define MapLeftCtrlMask
Definition: constants.h:372
GLuint64EXT * result
Definition: glext.h:11304
#define memset(x, y, z)
Definition: compat.h:39
#define SCANCODE_CHAR_LALT
Definition: scancodes.h:203
int tolower(int c)
Definition: utclib.c:902
uint16 modifiers
Definition: types.h:133
#define warning(s)
Definition: debug.h:71
#define Button5
Definition: x11stubs.h:23
void rdp_send_scancode(RDPCLIENT *This, uint32 time, uint16 flags, uint8 scancode)
Definition: xkeymap.c:1001
char * get_ksname(uint32 keysym)
Definition: xkeymap.c:734
static BOOL is_modifier(uint8 scancode)
Definition: xkeymap.c:747
#define KBD_FLAG_NUMLOCK
Definition: constants.h:247