/[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

Diff of /sourceforge.net/trunk/rdesktop/xkeymap.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 77 by astrand, Mon Jul 29 20:17:10 2002 UTC revision 962 by astrand, Wed Aug 3 09:56:17 2005 UTC
# Line 1  Line 1 
1  /*  /*
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X keyboard mapping     User interface services - X keyboard mapping
4     Copyright (C) Matthew Chapman 1999-2001  
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     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     it under the terms of the GNU General Public License as published by
# Line 12  Line 14 
14     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.     GNU General Public License for more details.
17      
18     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
19     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
20     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     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>  #include <X11/Xlib.h>
27  #include <X11/keysym.h>  #include <X11/keysym.h>
28  #include <stdio.h>  #endif
29  #include <stdlib.h>  
 #include <string.h>  
30  #include <ctype.h>  #include <ctype.h>
31  #include <limits.h>  #include <limits.h>
32    #include <time.h>
33    #include <string.h>
34  #include "rdesktop.h"  #include "rdesktop.h"
35  #include "scancodes.h"  #include "scancodes.h"
36    
37  #define KEYMAP_SIZE 4096  #define KEYMAP_SIZE 0xffff+1
38  #define KEYMAP_MASK (KEYMAP_SIZE - 1)  #define KEYMAP_MASK 0xffff
39  #define KEYMAP_MAX_LINE_LENGTH 80  #define KEYMAP_MAX_LINE_LENGTH 80
40    
41  extern Display *display;  extern Display *g_display;
42    extern Window g_wnd;
43  extern char keymapname[16];  extern char keymapname[16];
44  extern int keylayout;  extern int g_keylayout;
45  extern BOOL enable_compose;  extern int g_win_button_size;
46    extern BOOL g_enable_compose;
47    extern BOOL g_use_rdp5;
48    extern BOOL g_numlock_sync;
49    
50  static key_translation keymap[KEYMAP_SIZE];  static BOOL keymap_loaded;
51    static key_translation *keymap[KEYMAP_SIZE];
52  static int min_keycode;  static int min_keycode;
53  static uint16 remote_modifier_state = 0;  static uint16 remote_modifier_state = 0;
54    static uint16 saved_remote_modifier_state = 0;
55    
56    static void update_modifier_state(uint8 scancode, BOOL pressed);
57    
58    /* Free key_translation structure, including linked list */
59    static void
60    free_key_translation(key_translation * ptr)
61    {
62            key_translation *next;
63    
64            while (ptr)
65            {
66                    next = ptr->next;
67                    xfree(ptr);
68                    ptr = next;
69            }
70    }
71    
72  static void  static void
73  add_to_keymap(char *keyname, uint8 scancode, uint16 modifiers, char *mapname)  add_to_keymap(char *keyname, uint8 scancode, uint16 modifiers, char *mapname)
74  {  {
75          KeySym keysym;          KeySym keysym;
76            key_translation *tr;
77    
78          keysym = XStringToKeysym(keyname);          keysym = XStringToKeysym(keyname);
79          if (keysym == NoSymbol)          if (keysym == NoSymbol)
80          {          {
81                  error("Bad keysym %s in keymap %s\n", keyname, mapname);                  DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring)\n", keyname, mapname));
82                  return;                  return;
83          }          }
84    
85          DEBUG_KBD("Adding translation, keysym=0x%x, scancode=0x%x, "          DEBUG_KBD(("Adding translation, keysym=0x%x, scancode=0x%x, "
86                    "modifiers=0x%x\n", (unsigned int) keysym, scancode,                     "modifiers=0x%x\n", (unsigned int) keysym, scancode, modifiers));
                   modifiers);  
87    
88          keymap[keysym & KEYMAP_MASK].scancode = scancode;          tr = (key_translation *) xmalloc(sizeof(key_translation));
89          keymap[keysym & KEYMAP_MASK].modifiers = modifiers;          memset(tr, 0, sizeof(key_translation));
90            tr->scancode = scancode;
91            tr->modifiers = modifiers;
92            free_key_translation(keymap[keysym & KEYMAP_MASK]);
93            keymap[keysym & KEYMAP_MASK] = tr;
94    
95          return;          return;
96  }  }
97    
98    static void
99    add_sequence(char *rest, char *mapname)
100    {
101            KeySym keysym;
102            key_translation *tr, **prev_next;
103            size_t chars;
104            char keyname[KEYMAP_MAX_LINE_LENGTH];
105    
106            /* Skip over whitespace after the sequence keyword */
107            chars = strspn(rest, " \t");
108            rest += chars;
109    
110            /* Fetch the keysym name */
111            chars = strcspn(rest, " \t\0");
112            STRNCPY(keyname, rest, chars + 1);
113            rest += chars;
114    
115            keysym = XStringToKeysym(keyname);
116            if (keysym == NoSymbol)
117            {
118                    DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring line)\n", keyname, mapname));
119                    return;
120            }
121    
122    
123            DEBUG_KBD(("Adding sequence for keysym (0x%lx, %s) -> ", keysym, keyname));
124    
125            free_key_translation(keymap[keysym & KEYMAP_MASK]);
126            prev_next = &keymap[keysym & KEYMAP_MASK];
127    
128            while (*rest)
129            {
130                    /* Skip whitespace */
131                    chars = strspn(rest, " \t");
132                    rest += chars;
133    
134                    /* Fetch the keysym name */
135                    chars = strcspn(rest, " \t\0");
136                    STRNCPY(keyname, rest, chars + 1);
137                    rest += chars;
138    
139                    keysym = XStringToKeysym(keyname);
140                    if (keysym == NoSymbol)
141                    {
142                            DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring line)\n", keyname,
143                                       mapname));
144                            return;
145                    }
146    
147                    /* Allocate space for key_translation structure */
148                    tr = (key_translation *) xmalloc(sizeof(key_translation));
149                    memset(tr, 0, sizeof(key_translation));
150                    *prev_next = tr;
151                    prev_next = &tr->next;
152                    tr->seq_keysym = keysym;
153    
154                    DEBUG_KBD(("0x%x, ", (unsigned int) keysym));
155            }
156            DEBUG_KBD(("\n"));
157    }
158    
159    void
160    xkeymap_from_locale(const char *locale)
161    {
162            char *str, *ptr;
163            FILE *fp;
164    
165            /* Create a working copy */
166            str = strdup(locale);
167            if (str == NULL)
168            {
169                    perror("strdup");
170                    exit(1);
171            }
172    
173            /* Truncate at dot and at */
174            ptr = strrchr(str, '.');
175            if (ptr)
176                    *ptr = '\0';
177            ptr = strrchr(str, '@');
178            if (ptr)
179                    *ptr = '\0';
180    
181            /* Replace _ with - */
182            ptr = strrchr(str, '_');
183            if (ptr)
184                    *ptr = '-';
185    
186            /* Convert to lowercase */
187            ptr = str;
188            while (*ptr)
189            {
190                    *ptr = tolower((int) *ptr);
191                    ptr++;
192            }
193    
194            /* Try to open this keymap (da-dk) */
195            fp = xkeymap_open(str);
196            if (fp == NULL)
197            {
198                    /* Truncate at dash */
199                    ptr = strrchr(str, '-');
200                    if (ptr)
201                            *ptr = '\0';
202    
203                    /* Try the short name (da) */
204                    fp = xkeymap_open(str);
205            }
206    
207            if (fp)
208            {
209                    fclose(fp);
210                    STRNCPY(keymapname, str, sizeof(keymapname));
211                    fprintf(stderr, "Autoselected keyboard map %s.\n", keymapname);
212            }
213    }
214    
215    
216    /* Joins two path components. The result should be freed with
217       xfree(). */
218    static char *
219    pathjoin(const char *a, const char *b)
220    {
221            char *result;
222            result = xmalloc(PATH_MAX * 2 + 1);
223    
224            if (b[0] == '/')
225            {
226                    strncpy(result, b, PATH_MAX);
227            }
228            else
229            {
230                    strncpy(result, a, PATH_MAX);
231                    strcat(result, "/");
232                    strncat(result, b, PATH_MAX);
233            }
234            return result;
235    }
236    
237    /* Try to open a keymap with fopen() */
238    FILE *
239    xkeymap_open(const char *filename)
240    {
241            char *path1, *path2;
242            char *home;
243            FILE *fp;
244    
245            /* Try ~/.rdesktop/keymaps */
246            home = getenv("HOME");
247            if (home)
248            {
249                    path1 = pathjoin(home, ".rdesktop/keymaps");
250                    path2 = pathjoin(path1, filename);
251                    xfree(path1);
252                    fp = fopen(path2, "r");
253                    xfree(path2);
254                    if (fp)
255                            return fp;
256            }
257    
258            /* Try KEYMAP_PATH */
259            path1 = pathjoin(KEYMAP_PATH, filename);
260            fp = fopen(path1, "r");
261            xfree(path1);
262            if (fp)
263                    return fp;
264    
265            /* Try current directory, in case we are running from the source
266               tree */
267            path1 = pathjoin("keymaps", filename);
268            fp = fopen(path1, "r");
269            xfree(path1);
270            if (fp)
271                    return fp;
272    
273            return NULL;
274    }
275    
276  static BOOL  static BOOL
277  xkeymap_read(char *mapname)  xkeymap_read(char *mapname)
278  {  {
279          FILE *fp;          FILE *fp;
280          char line[KEYMAP_MAX_LINE_LENGTH], path[PATH_MAX];          char line[KEYMAP_MAX_LINE_LENGTH];
281          unsigned int line_num = 0;          unsigned int line_num = 0;
282          unsigned int line_length = 0;          unsigned int line_length = 0;
283          char *keyname, *p;          char *keyname, *p;
# Line 76  xkeymap_read(char *mapname) Line 285  xkeymap_read(char *mapname)
285          uint8 scancode;          uint8 scancode;
286          uint16 modifiers;          uint16 modifiers;
287    
288            fp = xkeymap_open(mapname);
         strcpy(path, KEYMAP_PATH);  
         strncat(path, mapname, sizeof(path) - sizeof(KEYMAP_PATH));  
   
         fp = fopen(path, "r");  
289          if (fp == NULL)          if (fp == NULL)
290          {          {
291                  error("Failed to open keymap %s\n", path);                  error("Failed to open keymap %s\n", mapname);
292                  return False;                  return False;
293          }          }
294    
# Line 116  xkeymap_read(char *mapname) Line 321  xkeymap_read(char *mapname)
321                  /* map */                  /* map */
322                  if (strncmp(line, "map ", 4) == 0)                  if (strncmp(line, "map ", 4) == 0)
323                  {                  {
324                          keylayout = strtol(line + 4, NULL, 16);                          g_keylayout = strtol(line + 4, NULL, 16);
325                          DEBUG_KBD("Keylayout 0x%x\n", keylayout);                          DEBUG_KBD(("Keylayout 0x%x\n", g_keylayout));
326                          continue;                          continue;
327                  }                  }
328    
329                  /* compose */                  /* compose */
330                  if (strncmp(line, "enable_compose", 15) == 0)                  if (strncmp(line, "enable_compose", 15) == 0)
331                  {                  {
332                          DEBUG_KBD("Enabling compose handling\n");                          DEBUG_KBD(("Enabling compose handling\n"));
333                          enable_compose = True;                          g_enable_compose = True;
334                            continue;
335                    }
336    
337                    /* sequence */
338                    if (strncmp(line, "sequence", 8) == 0)
339                    {
340                            add_sequence(line + 8, mapname);
341                          continue;                          continue;
342                  }                  }
343    
# Line 140  xkeymap_read(char *mapname) Line 352  xkeymap_read(char *mapname)
352                  p = strchr(line, ' ');                  p = strchr(line, ' ');
353                  if (p == NULL)                  if (p == NULL)
354                  {                  {
355                          error("Bad line %d in keymap %s\n", line_num,                          error("Bad line %d in keymap %s\n", line_num, mapname);
                               mapname);  
356                          continue;                          continue;
357                  }                  }
358                  else                  else
# Line 177  xkeymap_read(char *mapname) Line 388  xkeymap_read(char *mapname)
388                          MASK_ADD_BITS(modifiers, MapLocalStateMask);                          MASK_ADD_BITS(modifiers, MapLocalStateMask);
389                  }                  }
390    
391                    if (strstr(line_rest, "inhibit"))
392                    {
393                            MASK_ADD_BITS(modifiers, MapInhibitMask);
394                    }
395    
396                  add_to_keymap(keyname, scancode, modifiers, mapname);                  add_to_keymap(keyname, scancode, modifiers, mapname);
397    
398                  if (strstr(line_rest, "addupper"))                  if (strstr(line_rest, "addupper"))
# Line 184  xkeymap_read(char *mapname) Line 400  xkeymap_read(char *mapname)
400                          /* Automatically add uppercase key, with same modifiers                          /* Automatically add uppercase key, with same modifiers
401                             plus shift */                             plus shift */
402                          for (p = keyname; *p; p++)                          for (p = keyname; *p; p++)
403                                  *p = toupper(*p);                                  *p = toupper((int) *p);
404                          MASK_ADD_BITS(modifiers, MapLeftShiftMask);                          MASK_ADD_BITS(modifiers, MapLeftShiftMask);
405                          add_to_keymap(keyname, scancode, modifiers, mapname);                          add_to_keymap(keyname, scancode, modifiers, mapname);
406                  }                  }
# Line 197  xkeymap_read(char *mapname) Line 413  xkeymap_read(char *mapname)
413    
414  /* Before connecting and creating UI */  /* Before connecting and creating UI */
415  void  void
416  xkeymap_init1(void)  xkeymap_init(void)
417  {  {
418          int i;          unsigned int max_keycode;
419    
420          /* Zeroing keymap */          if (strcmp(keymapname, "none"))
         for (i = 0; i < KEYMAP_SIZE; i++)  
421          {          {
422                  keymap[i].scancode = 0;                  if (xkeymap_read(keymapname))
423                  keymap[i].modifiers = 0;                          keymap_loaded = True;
424          }          }
425    
426          if (strcmp(keymapname, "none"))          XDisplayKeycodes(g_display, &min_keycode, (int *) &max_keycode);
427    }
428    
429    static void
430    send_winkey(uint32 ev_time, BOOL pressed, BOOL leftkey)
431    {
432            uint8 winkey;
433    
434            if (leftkey)
435                    winkey = SCANCODE_CHAR_LWIN;
436            else
437                    winkey = SCANCODE_CHAR_RWIN;
438    
439            if (pressed)
440          {          {
441                  xkeymap_read(keymapname);                  if (g_use_rdp5)
442                    {
443                            rdp_send_scancode(ev_time, RDP_KEYPRESS, winkey);
444                    }
445                    else
446                    {
447                            /* RDP4 doesn't support winkey. Fake with Ctrl-Esc */
448                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LCTRL);
449                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_ESC);
450                    }
451            }
452            else
453            {
454                    /* key released */
455                    if (g_use_rdp5)
456                    {
457                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, winkey);
458                    }
459                    else
460                    {
461                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_ESC);
462                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
463                    }
464          }          }
465    }
466    
467    static void
468    reset_winkey(uint32 ev_time)
469    {
470            if (g_use_rdp5)
471            {
472                    /* For some reason, it seems to suffice to release
473                     *either* the left or right winkey. */
474                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LWIN);
475            }
476  }  }
477    
478  /* After connecting and creating UI */  /* Handle special key combinations */
479  void  BOOL
480  xkeymap_init2(void)  handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)
481  {  {
482          unsigned int max_keycode;          switch (keysym)
483          XDisplayKeycodes(display, &min_keycode, (int *) &max_keycode);          {
484                    case XK_Return:
485                            if ((get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R))
486                                && (get_key_state(state, XK_Control_L)
487                                    || get_key_state(state, XK_Control_R)))
488                            {
489                                    /* Ctrl-Alt-Enter: toggle full screen */
490                                    if (pressed)
491                                            xwin_toggle_fullscreen();
492                                    return True;
493                            }
494                            break;
495    
496                    case XK_Break:
497                            /* Send Break sequence E0 46 E0 C6 */
498                            if (pressed)
499                            {
500                                    rdp_send_scancode(ev_time, RDP_KEYPRESS,
501                                                      (SCANCODE_EXTENDED | 0x46));
502                                    rdp_send_scancode(ev_time, RDP_KEYPRESS,
503                                                      (SCANCODE_EXTENDED | 0xc6));
504                            }
505                            /* No release sequence */
506                            return True;
507                            break;
508    
509                    case XK_Pause:
510                            /* According to MS Keyboard Scan Code
511                               Specification, pressing Pause should result
512                               in E1 1D 45 E1 9D C5. I'm not exactly sure
513                               of how this is supposed to be sent via
514                               RDP. The code below seems to work, but with
515                               the side effect that Left Ctrl stays
516                               down. Therefore, we release it when Pause
517                               is released. */
518                            if (pressed)
519                            {
520                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
521                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0);
522                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x45, 0);
523                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
524                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x9d, 0);
525                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xc5, 0);
526                            }
527                            else
528                            {
529                                    /* Release Left Ctrl */
530                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYRELEASE,
531                                                   0x1d, 0);
532                            }
533                            return True;
534                            break;
535    
536                    case XK_Meta_L: /* Windows keys */
537                    case XK_Super_L:
538                    case XK_Hyper_L:
539                            send_winkey(ev_time, pressed, True);
540                            return True;
541                            break;
542    
543                    case XK_Meta_R:
544                    case XK_Super_R:
545                    case XK_Hyper_R:
546                            send_winkey(ev_time, pressed, False);
547                            return True;
548                            break;
549    
550                    case XK_space:
551                            /* Prevent access to the Windows system menu in single app mode */
552                            if (g_win_button_size
553                                && (get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R)))
554                                    return True;
555                            break;
556    
557                    case XK_Num_Lock:
558                            /* Synchronize on key release */
559                            if (g_numlock_sync && !pressed)
560                                    rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
561                                                   ui_get_numlock_state(read_keyboard_state()), 0);
562    
563                            /* Inhibit */
564                            return True;
565                            break;
566    
567            }
568            return False;
569  }  }
570    
571    
572  key_translation  key_translation
573  xkeymap_translate_key(KeySym keysym, unsigned int keycode, unsigned int state)  xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state)
574  {  {
575          key_translation tr = { 0, 0 };          key_translation tr = { 0, 0, 0, 0 };
576            key_translation *ptr;
577    
578          tr = keymap[keysym & KEYMAP_MASK];          ptr = keymap[keysym & KEYMAP_MASK];
579            if (ptr)
         if (tr.modifiers & MapLocalStateMask)  
580          {          {
581                  /* The modifiers to send for this key should be obtained                  tr = *ptr;
582                     from the local state. Currently, only shift is implemented. */                  if (tr.seq_keysym == 0) /* Normal scancode translation */
                 if (state & ShiftMask)  
583                  {                  {
584                          tr.modifiers = MapLeftShiftMask;                          if (tr.modifiers & MapInhibitMask)
585                            {
586                                    DEBUG_KBD(("Inhibiting key\n"));
587                                    tr.scancode = 0;
588                                    return tr;
589                            }
590    
591                            if (tr.modifiers & MapLocalStateMask)
592                            {
593                                    /* The modifiers to send for this key should be obtained
594                                       from the local state. Currently, only shift is implemented. */
595                                    if (state & ShiftMask)
596                                    {
597                                            tr.modifiers = MapLeftShiftMask;
598                                    }
599                            }
600    
601                            if ((tr.modifiers & MapLeftShiftMask)
602                                && ((remote_modifier_state & MapLeftCtrlMask)
603                                    || (remote_modifier_state & MapRightCtrlMask))
604                                && get_key_state(state, XK_Caps_Lock))
605                            {
606                                    DEBUG_KBD(("CapsLock + Ctrl pressed, releasing LeftShift\n"));
607                                    tr.modifiers ^= MapLeftShiftMask;
608                            }
609    
610                            DEBUG_KBD(("Found scancode translation, scancode=0x%x, modifiers=0x%x\n",
611                                       tr.scancode, tr.modifiers));
612                  }                  }
613          }          }
614            else
         if (tr.scancode != 0)  
615          {          {
616                  DEBUG_KBD                  if (keymap_loaded)
617                          ("Found key translation, scancode=0x%x, modifiers=0x%x\n",                          warning("No translation for (keysym 0x%lx, %s)\n", keysym,
618                           tr.scancode, tr.modifiers);                                  get_ksname(keysym));
619                  return tr;  
620                    /* not in keymap, try to interpret the raw scancode */
621                    if (((int) keycode >= min_keycode) && (keycode <= 0x60))
622                    {
623                            tr.scancode = keycode - min_keycode;
624    
625                            /* The modifiers to send for this key should be
626                               obtained from the local state. Currently, only
627                               shift is implemented. */
628                            if (state & ShiftMask)
629                            {
630                                    tr.modifiers = MapLeftShiftMask;
631                            }
632    
633                            DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));
634                    }
635                    else
636                    {
637                            DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));
638                    }
639          }          }
640    
641          printf("No translation for (keysym 0x%lx, %s)\n", keysym,          return tr;
642                 get_ksname(keysym));  }
643    
644    void
645    xkeymap_send_keys(uint32 keysym, unsigned int keycode, unsigned int state, uint32 ev_time,
646                      BOOL pressed)
647    {
648            key_translation tr, *ptr;
649            tr = xkeymap_translate_key(keysym, keycode, state);
650    
651          /* not in keymap, try to interpret the raw scancode */          if (tr.seq_keysym == 0)
         if ((keycode >= min_keycode) && (keycode <= 0x60))  
652          {          {
653                  tr.scancode = keycode - min_keycode;                  /* Scancode translation */
654                  printf("Sending guessed scancode 0x%x\n", tr.scancode);                  if (tr.scancode == 0)
655                            return;
656    
657                    if (pressed)
658                    {
659                            save_remote_modifiers(tr.scancode);
660                            ensure_remote_modifiers(ev_time, tr);
661                            rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
662                            restore_remote_modifiers(ev_time, tr.scancode);
663                    }
664                    else
665                    {
666                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
667                    }
668                    return;
669          }          }
670          else  
671            /* Sequence, only on key down */
672            if (pressed)
673          {          {
674                  printf("No good guess for keycode 0x%x found\n", keycode);                  ptr = &tr;
675                    do
676                    {
677                            DEBUG_KBD(("Handling sequence element, keysym=0x%x\n",
678                                       (unsigned int) ptr->seq_keysym));
679                            xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, True);
680                            xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, False);
681                            ptr = ptr->next;
682                    }
683                    while (ptr);
684          }          }
   
         return tr;  
685  }  }
686    
687  uint16  uint16
# Line 287  xkeymap_translate_button(unsigned int bu Line 705  xkeymap_translate_button(unsigned int bu
705  }  }
706    
707  char *  char *
708  get_ksname(KeySym keysym)  get_ksname(uint32 keysym)
709  {  {
710          char *ksname = NULL;          char *ksname = NULL;
711    
# Line 299  get_ksname(KeySym keysym) Line 717  get_ksname(KeySym keysym)
717          return ksname;          return ksname;
718  }  }
719    
720  BOOL  static BOOL
721  inhibit_key(KeySym keysym)  is_modifier(uint8 scancode)
722  {  {
723          switch (keysym)          switch (scancode)
724          {          {
725                  case XK_Caps_Lock:                  case SCANCODE_CHAR_LSHIFT:
726                          return True;                  case SCANCODE_CHAR_RSHIFT:
727                          break;                  case SCANCODE_CHAR_LCTRL:
728                  case XK_Multi_key:                  case SCANCODE_CHAR_RCTRL:
729                    case SCANCODE_CHAR_LALT:
730                    case SCANCODE_CHAR_RALT:
731                    case SCANCODE_CHAR_LWIN:
732                    case SCANCODE_CHAR_RWIN:
733                    case SCANCODE_CHAR_NUMLOCK:
734                          return True;                          return True;
                         break;  
735                  default:                  default:
736                          break;                          break;
737          }          }
# Line 317  inhibit_key(KeySym keysym) Line 739  inhibit_key(KeySym keysym)
739  }  }
740    
741  void  void
742    save_remote_modifiers(uint8 scancode)
743    {
744            if (is_modifier(scancode))
745                    return;
746    
747            saved_remote_modifier_state = remote_modifier_state;
748    }
749    
750    void
751    restore_remote_modifiers(uint32 ev_time, uint8 scancode)
752    {
753            key_translation dummy;
754    
755            if (is_modifier(scancode))
756                    return;
757    
758            dummy.scancode = 0;
759            dummy.modifiers = saved_remote_modifier_state;
760            ensure_remote_modifiers(ev_time, dummy);
761    }
762    
763    void
764  ensure_remote_modifiers(uint32 ev_time, key_translation tr)  ensure_remote_modifiers(uint32 ev_time, key_translation tr)
765  {  {
766          /* If this key is a modifier, do nothing */          /* If this key is a modifier, do nothing */
767          switch (tr.scancode)          if (is_modifier(tr.scancode))
768                    return;
769    
770            if (!g_numlock_sync)
771          {          {
772                  case SCANCODE_CHAR_LSHIFT:                  /* NumLock */
773                  case SCANCODE_CHAR_RSHIFT:                  if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)
774                  case SCANCODE_CHAR_LCTRL:                      != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask))
775                  case SCANCODE_CHAR_RCTRL:                  {
776                  case SCANCODE_CHAR_LALT:                          /* The remote modifier state is not correct */
777                  case SCANCODE_CHAR_RALT:                          uint16 new_remote_state;
778                  case SCANCODE_CHAR_LWIN:  
779                  case SCANCODE_CHAR_RWIN:                          if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask))
780                  case SCANCODE_CHAR_NUMLOCK:                          {
781                          return;                                  DEBUG_KBD(("Remote NumLock state is incorrect, activating NumLock.\n"));
782                  default:                                  new_remote_state = KBD_FLAG_NUMLOCK;
783                          break;                                  remote_modifier_state = MapNumLockMask;
784                            }
785                            else
786                            {
787                                    DEBUG_KBD(("Remote NumLock state is incorrect, deactivating NumLock.\n"));
788                                    new_remote_state = 0;
789                                    remote_modifier_state = 0;
790                            }
791    
792                            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0);
793                    }
794          }          }
795    
796          /* Shift */  
797            /* Shift. Left shift and right shift are treated as equal; either is fine. */
798          if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)          if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
799              != MASK_HAS_BITS(remote_modifier_state, MapShiftMask))              != MASK_HAS_BITS(remote_modifier_state, MapShiftMask))
800          {          {
801                  /* The remote modifier state is not correct */                  /* The remote modifier state is not correct */
802                  if (MASK_HAS_BITS(tr.modifiers, MapShiftMask))                  if (MASK_HAS_BITS(tr.modifiers, MapLeftShiftMask))
803                  {                  {
804                          /* Needs this modifier. Send down. */                          /* Needs left shift. Send down. */
805                          rdp_send_scancode(ev_time, RDP_KEYPRESS,                          rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LSHIFT);
806                                            SCANCODE_CHAR_LSHIFT);                  }
807                    else if (MASK_HAS_BITS(tr.modifiers, MapRightShiftMask))
808                    {
809                            /* Needs right shift. Send down. */
810                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RSHIFT);
811                  }                  }
812                  else                  else
813                  {                  {
814                          /* Should not use this modifier. Send up. */                          /* Should not use this modifier. Send up for shift currently pressed. */
815                          rdp_send_scancode(ev_time, RDP_KEYRELEASE,                          if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask))
816                                            SCANCODE_CHAR_LSHIFT);                                  /* Left shift is down */
817                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
818                            else
819                                    /* Right shift is down */
820                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
821                  }                  }
822          }          }
823    
# Line 363  ensure_remote_modifiers(uint32 ev_time, Line 829  ensure_remote_modifiers(uint32 ev_time,
829                  if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask))                  if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask))
830                  {                  {
831                          /* Needs this modifier. Send down. */                          /* Needs this modifier. Send down. */
832                          rdp_send_scancode(ev_time, RDP_KEYPRESS,                          rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RALT);
                                           SCANCODE_CHAR_RALT);  
833                  }                  }
834                  else                  else
835                  {                  {
836                          /* Should not use this modifier. Send up. */                          /* Should not use this modifier. Send up. */
837                          rdp_send_scancode(ev_time, RDP_KEYRELEASE,                          rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
                                           SCANCODE_CHAR_RALT);  
838                  }                  }
839          }          }
840    
         /* NumLock */  
         if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)  
             != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask))  
         {  
                 /* The remote modifier state is not correct */  
                 DEBUG_KBD("Remote NumLock state is incorrect. Toggling\n");  
                 if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask))  
                 {  
                         /* Needs this modifier. Toggle */  
                         rdp_send_scancode(ev_time, RDP_KEYPRESS,  
                                           SCANCODE_CHAR_NUMLOCK);  
                         rdp_send_scancode(ev_time, RDP_KEYRELEASE,  
                                           SCANCODE_CHAR_NUMLOCK);  
                 }  
                 else  
                 {  
                         /* Should not use this modifier. Toggle */  
                         rdp_send_scancode(ev_time, RDP_KEYPRESS,  
                                           SCANCODE_CHAR_NUMLOCK);  
                         rdp_send_scancode(ev_time, RDP_KEYRELEASE,  
                                           SCANCODE_CHAR_NUMLOCK);  
                 }  
         }  
841    
842  }  }
843    
844    
845    unsigned int
846    read_keyboard_state()
847    {
848    #ifdef RDP2VNC
849            return 0;
850    #else
851            unsigned int state;
852            Window wdummy;
853            int dummy;
854    
855            XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
856            return state;
857    #endif
858    }
859    
860    
861    uint16
862    ui_get_numlock_state(unsigned int state)
863    {
864            uint16 numlock_state = 0;
865    
866            if (get_key_state(state, XK_Num_Lock))
867                    numlock_state = KBD_FLAG_NUMLOCK;
868    
869            return numlock_state;
870    }
871    
872    
873    void
874    reset_modifier_keys()
875    {
876            unsigned int state = read_keyboard_state();
877    
878            /* reset keys */
879            uint32 ev_time;
880            ev_time = time(NULL);
881    
882            if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask)
883                && !get_key_state(state, XK_Shift_L))
884                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
885    
886            if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask)
887                && !get_key_state(state, XK_Shift_R))
888                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
889    
890            if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask)
891                && !get_key_state(state, XK_Control_L))
892                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
893    
894            if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask)
895                && !get_key_state(state, XK_Control_R))
896                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
897    
898            if (MASK_HAS_BITS(remote_modifier_state, MapLeftAltMask) && !get_key_state(state, XK_Alt_L))
899                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
900    
901            if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) &&
902                !get_key_state(state, XK_Alt_R) && !get_key_state(state, XK_Mode_switch)
903                && !get_key_state(state, XK_ISO_Level3_Shift))
904                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
905    
906            reset_winkey(ev_time);
907    
908            if (g_numlock_sync)
909                    rdp_send_input(ev_time, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(state), 0);
910    }
911    
912    
913  static void  static void
914  update_modifier_state(uint16 modifiers, BOOL pressed)  update_modifier_state(uint8 scancode, BOOL pressed)
915  {  {
916    #ifdef WITH_DEBUG_KBD
917            uint16 old_modifier_state;
918    
919          DEBUG_KBD("Before updating modifier_state:0x%x, pressed=0x%x\n",          old_modifier_state = remote_modifier_state;
920                    remote_modifier_state, pressed);  #endif
921          switch (modifiers)  
922            switch (scancode)
923          {          {
924                  case SCANCODE_CHAR_LSHIFT:                  case SCANCODE_CHAR_LSHIFT:
925                          MASK_CHANGE_BIT(remote_modifier_state,                          MASK_CHANGE_BIT(remote_modifier_state, MapLeftShiftMask, pressed);
                                         MapLeftShiftMask, pressed);  
926                          break;                          break;
927                  case SCANCODE_CHAR_RSHIFT:                  case SCANCODE_CHAR_RSHIFT:
928                          MASK_CHANGE_BIT(remote_modifier_state,                          MASK_CHANGE_BIT(remote_modifier_state, MapRightShiftMask, pressed);
                                         MapRightShiftMask, pressed);  
929                          break;                          break;
930                  case SCANCODE_CHAR_LCTRL:                  case SCANCODE_CHAR_LCTRL:
931                          MASK_CHANGE_BIT(remote_modifier_state,                          MASK_CHANGE_BIT(remote_modifier_state, MapLeftCtrlMask, pressed);
                                         MapLeftCtrlMask, pressed);  
932                          break;                          break;
933                  case SCANCODE_CHAR_RCTRL:                  case SCANCODE_CHAR_RCTRL:
934                          MASK_CHANGE_BIT(remote_modifier_state,                          MASK_CHANGE_BIT(remote_modifier_state, MapRightCtrlMask, pressed);
                                         MapRightCtrlMask, pressed);  
935                          break;                          break;
936                  case SCANCODE_CHAR_LALT:                  case SCANCODE_CHAR_LALT:
937                          MASK_CHANGE_BIT(remote_modifier_state, MapLeftAltMask,                          MASK_CHANGE_BIT(remote_modifier_state, MapLeftAltMask, pressed);
                                         pressed);  
938                          break;                          break;
939                  case SCANCODE_CHAR_RALT:                  case SCANCODE_CHAR_RALT:
940                          MASK_CHANGE_BIT(remote_modifier_state,                          MASK_CHANGE_BIT(remote_modifier_state, MapRightAltMask, pressed);
                                         MapRightAltMask, pressed);  
941                          break;                          break;
942                  case SCANCODE_CHAR_LWIN:                  case SCANCODE_CHAR_LWIN:
943                          MASK_CHANGE_BIT(remote_modifier_state, MapLeftWinMask,                          MASK_CHANGE_BIT(remote_modifier_state, MapLeftWinMask, pressed);
                                         pressed);  
944                          break;                          break;
945                  case SCANCODE_CHAR_RWIN:                  case SCANCODE_CHAR_RWIN:
946                          MASK_CHANGE_BIT(remote_modifier_state,                          MASK_CHANGE_BIT(remote_modifier_state, MapRightWinMask, pressed);
                                         MapRightWinMask, pressed);  
947                          break;                          break;
948                  case SCANCODE_CHAR_NUMLOCK:                  case SCANCODE_CHAR_NUMLOCK:
949                          /* KeyReleases for NumLocks are sent immediately. Toggle the                          /* KeyReleases for NumLocks are sent immediately. Toggle the
950                             modifier state only on Keypress */                             modifier state only on Keypress */
951                          if (pressed)                          if (pressed && !g_numlock_sync)
952                          {                          {
953                                  BOOL newNumLockState;                                  BOOL newNumLockState;
954                                  newNumLockState =                                  newNumLockState =
955                                          (MASK_HAS_BITS                                          (MASK_HAS_BITS
956                                           (remote_modifier_state,                                           (remote_modifier_state, MapNumLockMask) == False);
                                           MapNumLockMask) == False);  
957                                  MASK_CHANGE_BIT(remote_modifier_state,                                  MASK_CHANGE_BIT(remote_modifier_state,
958                                                  MapNumLockMask,                                                  MapNumLockMask, newNumLockState);
                                                 newNumLockState);  
959                          }                          }
                         break;  
960          }          }
961          DEBUG_KBD("After updating modifier_state:0x%x\n",  
962                    remote_modifier_state);  #ifdef WITH_DEBUG_KBD
963            if (old_modifier_state != remote_modifier_state)
964            {
965                    DEBUG_KBD(("Before updating modifier_state:0x%x, pressed=0x%x\n",
966                               old_modifier_state, pressed));
967                    DEBUG_KBD(("After updating modifier_state:0x%x\n", remote_modifier_state));
968            }
969    #endif
970    
971  }  }
972    
973  /* Send keyboard input */  /* Send keyboard input */
974  void  void
975  rdp_send_scancode(uint32 time, uint16 flags, uint16 scancode)  rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode)
976  {  {
977          update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));          update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));
978    
979          if (scancode & SCANCODE_EXTENDED)          if (scancode & SCANCODE_EXTENDED)
980          {          {
981                  DEBUG_KBD("Sending extended scancode=0x%x, flags=0x%x\n",                  DEBUG_KBD(("Sending extended scancode=0x%x, flags=0x%x\n",
982                            scancode & ~SCANCODE_EXTENDED, flags);                             scancode & ~SCANCODE_EXTENDED, flags));
983                  rdp_send_input(time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,                  rdp_send_input(time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,
984                                 scancode & ~SCANCODE_EXTENDED, 0);                                 scancode & ~SCANCODE_EXTENDED, 0);
985          }          }
986          else          else
987          {          {
988                  DEBUG_KBD("Sending scancode=0x%x, flags=0x%x\n", scancode,                  DEBUG_KBD(("Sending scancode=0x%x, flags=0x%x\n", scancode, flags));
                           flags);  
989                  rdp_send_input(time, RDP_INPUT_SCANCODE, flags, scancode, 0);                  rdp_send_input(time, RDP_INPUT_SCANCODE, flags, scancode, 0);
990          }          }
991  }  }

Legend:
Removed from v.77  
changed lines
  Added in v.962

  ViewVC Help
Powered by ViewVC 1.1.26