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

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

  ViewVC Help
Powered by ViewVC 1.1.26