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

Legend:
Removed from v.70  
changed lines
  Added in v.1293

  ViewVC Help
Powered by ViewVC 1.1.26