/[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 216 by matthewc, Tue Oct 8 02:30:20 2002 UTC revision 957 by astrand, Wed Aug 3 08:25:32 2005 UTC
# Line 1  Line 1 
1  /*  /*
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X keyboard mapping     User interface services - X keyboard mapping
4     Copyright (C) Matthew Chapman 1999-2002  
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  #define XK_MISCELLANY  #include <X11/keysym.h>
28  #include <X11/keysymdef.h>  #endif
29    
30  #include <ctype.h>  #include <ctype.h>
31  #include <limits.h>  #include <limits.h>
32  #include <time.h>  #include <time.h>
33  #include "rdesktop.h"  #include "rdesktop.h"
34  #include "scancodes.h"  #include "scancodes.h"
35    
36  #define KEYMAP_SIZE 4096  #define KEYMAP_SIZE 0xffff+1
37  #define KEYMAP_MASK (KEYMAP_SIZE - 1)  #define KEYMAP_MASK 0xffff
38  #define KEYMAP_MAX_LINE_LENGTH 80  #define KEYMAP_MAX_LINE_LENGTH 80
39    
40  extern Display *display;  extern Display *g_display;
41    extern Window g_wnd;
42  extern char keymapname[16];  extern char keymapname[16];
43  extern int keylayout;  extern int g_keylayout;
44  extern BOOL enable_compose;  extern int g_win_button_size;
45    extern BOOL g_enable_compose;
46    extern BOOL g_use_rdp5;
47    extern BOOL g_numlock_sync;
48    
49  static BOOL keymap_loaded;  static BOOL keymap_loaded;
50  static key_translation keymap[KEYMAP_SIZE];  static key_translation *keymap[KEYMAP_SIZE];
51  static int min_keycode;  static int min_keycode;
52  static uint16 remote_modifier_state = 0;  static uint16 remote_modifier_state = 0;
53    static uint16 saved_remote_modifier_state = 0;
54    
55  static void update_modifier_state(uint8 scancode, BOOL pressed);  static void update_modifier_state(uint8 scancode, BOOL pressed);
56    
57    /* Free key_translation structure, including linked list */
58    static void
59    free_key_translation(key_translation * ptr)
60    {
61            key_translation *next;
62    
63            while (ptr)
64            {
65                    next = ptr->next;
66                    xfree(ptr);
67                    ptr = next;
68            }
69    }
70    
71  static void  static void
72  add_to_keymap(char *keyname, uint8 scancode, uint16 modifiers, char *mapname)  add_to_keymap(char *keyname, uint8 scancode, uint16 modifiers, char *mapname)
73  {  {
74          KeySym keysym;          KeySym keysym;
75            key_translation *tr;
76    
77          keysym = XStringToKeysym(keyname);          keysym = XStringToKeysym(keyname);
78          if (keysym == NoSymbol)          if (keysym == NoSymbol)
79          {          {
80                  error("Bad keysym %s in keymap %s\n", keyname, mapname);                  DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring)\n", keyname, mapname));
81                  return;                  return;
82          }          }
83    
84          DEBUG_KBD(("Adding translation, keysym=0x%x, scancode=0x%x, "          DEBUG_KBD(("Adding translation, keysym=0x%x, scancode=0x%x, "
85                     "modifiers=0x%x\n", (unsigned int) keysym, scancode, modifiers));                     "modifiers=0x%x\n", (unsigned int) keysym, scancode, modifiers));
86    
87          keymap[keysym & KEYMAP_MASK].scancode = scancode;          tr = (key_translation *) xmalloc(sizeof(key_translation));
88          keymap[keysym & KEYMAP_MASK].modifiers = modifiers;          memset(tr, 0, sizeof(key_translation));
89            tr->scancode = scancode;
90            tr->modifiers = modifiers;
91            free_key_translation(keymap[keysym & KEYMAP_MASK]);
92            keymap[keysym & KEYMAP_MASK] = tr;
93    
94          return;          return;
95  }  }
96    
97    static void
98    add_sequence(char *rest, char *mapname)
99    {
100            KeySym keysym;
101            key_translation *tr, **prev_next;
102            size_t chars;
103            char keyname[KEYMAP_MAX_LINE_LENGTH];
104    
105            /* Skip over whitespace after the sequence keyword */
106            chars = strspn(rest, " \t");
107            rest += chars;
108    
109            /* Fetch the keysym name */
110            chars = strcspn(rest, " \t\0");
111            STRNCPY(keyname, rest, chars + 1);
112            rest += chars;
113    
114            keysym = XStringToKeysym(keyname);
115            if (keysym == NoSymbol)
116            {
117                    DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring line)\n", keyname, mapname));
118                    return;
119            }
120    
121    
122            DEBUG_KBD(("Adding sequence for keysym (0x%lx, %s) -> ", keysym, keyname));
123    
124            free_key_translation(keymap[keysym & KEYMAP_MASK]);
125            prev_next = &keymap[keysym & KEYMAP_MASK];
126    
127            while (*rest)
128            {
129                    /* Skip whitespace */
130                    chars = strspn(rest, " \t");
131                    rest += chars;
132    
133                    /* Fetch the keysym name */
134                    chars = strcspn(rest, " \t\0");
135                    STRNCPY(keyname, rest, chars + 1);
136                    rest += chars;
137    
138                    keysym = XStringToKeysym(keyname);
139                    if (keysym == NoSymbol)
140                    {
141                            DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring line)\n", keyname,
142                                       mapname));
143                            return;
144                    }
145    
146                    /* Allocate space for key_translation structure */
147                    tr = (key_translation *) xmalloc(sizeof(key_translation));
148                    memset(tr, 0, sizeof(key_translation));
149                    *prev_next = tr;
150                    prev_next = &tr->next;
151                    tr->seq_keysym = keysym;
152    
153                    DEBUG_KBD(("0x%x, ", (unsigned int) keysym));
154            }
155            DEBUG_KBD(("\n"));
156    }
157    
158    /* Joins two path components. The result should be freed with
159       xfree(). */
160    static char *
161    pathjoin(const char *a, const char *b)
162    {
163            char *result;
164            result = xmalloc(PATH_MAX * 2 + 1);
165    
166            if (b[0] == '/')
167            {
168                    strncpy(result, b, PATH_MAX);
169            }
170            else
171            {
172                    strncpy(result, a, PATH_MAX);
173                    strcat(result, "/");
174                    strncat(result, b, PATH_MAX);
175            }
176            return result;
177    }
178    
179    /* Try to open a keymap with fopen() */
180    FILE *
181    xkeymap_open(const char *filename)
182    {
183            char *path1, *path2;
184            char *home;
185            FILE *fp;
186    
187            /* Try KEYMAP_PATH */
188            path1 = pathjoin(KEYMAP_PATH, filename);
189            fp = fopen(path1, "r");
190            xfree(path1);
191            if (fp)
192                    return fp;
193    
194            /* Try ~/.rdesktop/keymaps */
195            home = getenv("HOME");
196            if (home)
197            {
198                    path1 = pathjoin(home, ".rdesktop/keymaps");
199                    path2 = pathjoin(path1, filename);
200                    xfree(path1);
201                    fp = fopen(path2, "r");
202                    xfree(path2);
203                    if (fp)
204                            return fp;
205            }
206    
207            /* Try current directory, in case we are running from the source
208               tree */
209            path1 = pathjoin("keymaps", filename);
210            fp = fopen(path1, "r");
211            xfree(path1);
212            if (fp)
213                    return fp;
214    
215            return NULL;
216    }
217    
218  static BOOL  static BOOL
219  xkeymap_read(char *mapname)  xkeymap_read(char *mapname)
220  {  {
221          FILE *fp;          FILE *fp;
222          char line[KEYMAP_MAX_LINE_LENGTH];          char line[KEYMAP_MAX_LINE_LENGTH];
         char path[PATH_MAX], inplace_path[PATH_MAX];  
223          unsigned int line_num = 0;          unsigned int line_num = 0;
224          unsigned int line_length = 0;          unsigned int line_length = 0;
225          char *keyname, *p;          char *keyname, *p;
# Line 78  xkeymap_read(char *mapname) Line 227  xkeymap_read(char *mapname)
227          uint8 scancode;          uint8 scancode;
228          uint16 modifiers;          uint16 modifiers;
229    
230            fp = xkeymap_open(mapname);
         strcpy(path, KEYMAP_PATH);  
         strncat(path, mapname, sizeof(path) - sizeof(KEYMAP_PATH));  
   
         fp = fopen(path, "r");  
231          if (fp == NULL)          if (fp == NULL)
232          {          {
233                  /* in case we are running from the source tree */                  error("Failed to open keymap %s\n", mapname);
234                  strcpy(inplace_path, "keymaps/");                  return False;
                 strncat(inplace_path, mapname, sizeof(inplace_path) - sizeof("keymaps/"));  
   
                 fp = fopen(inplace_path, "r");  
                 if (fp == NULL)  
                 {  
                         error("Failed to open keymap %s\n", path);  
                         return False;  
                 }  
235          }          }
236    
237          /* FIXME: More tolerant on white space */          /* FIXME: More tolerant on white space */
# Line 126  xkeymap_read(char *mapname) Line 263  xkeymap_read(char *mapname)
263                  /* map */                  /* map */
264                  if (strncmp(line, "map ", 4) == 0)                  if (strncmp(line, "map ", 4) == 0)
265                  {                  {
266                          keylayout = strtol(line + 4, NULL, 16);                          g_keylayout = strtol(line + 4, NULL, 16);
267                          DEBUG_KBD(("Keylayout 0x%x\n", keylayout));                          DEBUG_KBD(("Keylayout 0x%x\n", g_keylayout));
268                          continue;                          continue;
269                  }                  }
270    
# Line 135  xkeymap_read(char *mapname) Line 272  xkeymap_read(char *mapname)
272                  if (strncmp(line, "enable_compose", 15) == 0)                  if (strncmp(line, "enable_compose", 15) == 0)
273                  {                  {
274                          DEBUG_KBD(("Enabling compose handling\n"));                          DEBUG_KBD(("Enabling compose handling\n"));
275                          enable_compose = True;                          g_enable_compose = True;
276                            continue;
277                    }
278    
279                    /* sequence */
280                    if (strncmp(line, "sequence", 8) == 0)
281                    {
282                            add_sequence(line + 8, mapname);
283                          continue;                          continue;
284                  }                  }
285    
# Line 198  xkeymap_read(char *mapname) Line 342  xkeymap_read(char *mapname)
342                          /* Automatically add uppercase key, with same modifiers                          /* Automatically add uppercase key, with same modifiers
343                             plus shift */                             plus shift */
344                          for (p = keyname; *p; p++)                          for (p = keyname; *p; p++)
345                                  *p = toupper(*p);                                  *p = toupper((int) *p);
346                          MASK_ADD_BITS(modifiers, MapLeftShiftMask);                          MASK_ADD_BITS(modifiers, MapLeftShiftMask);
347                          add_to_keymap(keyname, scancode, modifiers, mapname);                          add_to_keymap(keyname, scancode, modifiers, mapname);
348                  }                  }
# Line 214  void Line 358  void
358  xkeymap_init(void)  xkeymap_init(void)
359  {  {
360          unsigned int max_keycode;          unsigned int max_keycode;
361            char *mapname_ptr;
362    
363            /* Make keymapname lowercase */
364            mapname_ptr = keymapname;
365            while (*mapname_ptr)
366            {
367                    *mapname_ptr = tolower((int) *mapname_ptr);
368                    mapname_ptr++;
369            }
370    
371          if (strcmp(keymapname, "none"))          if (strcmp(keymapname, "none"))
372          {          {
# Line 221  xkeymap_init(void) Line 374  xkeymap_init(void)
374                          keymap_loaded = True;                          keymap_loaded = True;
375          }          }
376    
377          XDisplayKeycodes(display, &min_keycode, (int *) &max_keycode);          XDisplayKeycodes(g_display, &min_keycode, (int *) &max_keycode);
378    }
379    
380    static void
381    send_winkey(uint32 ev_time, BOOL pressed, BOOL leftkey)
382    {
383            uint8 winkey;
384    
385            if (leftkey)
386                    winkey = SCANCODE_CHAR_LWIN;
387            else
388                    winkey = SCANCODE_CHAR_RWIN;
389    
390            if (pressed)
391            {
392                    if (g_use_rdp5)
393                    {
394                            rdp_send_scancode(ev_time, RDP_KEYPRESS, winkey);
395                    }
396                    else
397                    {
398                            /* RDP4 doesn't support winkey. Fake with Ctrl-Esc */
399                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LCTRL);
400                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_ESC);
401                    }
402            }
403            else
404            {
405                    /* key released */
406                    if (g_use_rdp5)
407                    {
408                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, winkey);
409                    }
410                    else
411                    {
412                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_ESC);
413                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
414                    }
415            }
416  }  }
417    
418  /* Handles, for example, multi-scancode keypresses (which is not  static void
419     possible via keymap-files) */  reset_winkey(uint32 ev_time)
420    {
421            if (g_use_rdp5)
422            {
423                    /* For some reason, it seems to suffice to release
424                     *either* the left or right winkey. */
425                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LWIN);
426            }
427    }
428    
429    /* Handle special key combinations */
430  BOOL  BOOL
431  handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)  handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)
432  {  {
433          switch (keysym)          switch (keysym)
434          {          {
435                  case XK_Break:                  case XK_Return:
                 case XK_Pause:  
436                          if ((get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R))                          if ((get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R))
437                                  && (get_key_state(state, XK_Control_L) || get_key_state(state, XK_Control_R)))                              && (get_key_state(state, XK_Control_L)
438                                    || get_key_state(state, XK_Control_R)))
439                          {                          {
440                                  /* Ctrl-Alt-Break: toggle full screen */                                  /* Ctrl-Alt-Enter: toggle full screen */
441                                  if (pressed)                                  if (pressed)
442                                          xwin_toggle_fullscreen();                                          xwin_toggle_fullscreen();
443                                    return True;
444                            }
445                            break;
446    
447                    case XK_Break:
448                            /* Send Break sequence E0 46 E0 C6 */
449                            if (pressed)
450                            {
451                                    rdp_send_scancode(ev_time, RDP_KEYPRESS,
452                                                      (SCANCODE_EXTENDED | 0x46));
453                                    rdp_send_scancode(ev_time, RDP_KEYPRESS,
454                                                      (SCANCODE_EXTENDED | 0xc6));
455                          }                          }
456                          else if (keysym == XK_Break)                          /* No release sequence */
457                            return True;
458                            break;
459    
460                    case XK_Pause:
461                            /* According to MS Keyboard Scan Code
462                               Specification, pressing Pause should result
463                               in E1 1D 45 E1 9D C5. I'm not exactly sure
464                               of how this is supposed to be sent via
465                               RDP. The code below seems to work, but with
466                               the side effect that Left Ctrl stays
467                               down. Therefore, we release it when Pause
468                               is released. */
469                            if (pressed)
470                          {                          {
471                                  /* Send Break sequence E0 46 E0 C6 */                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
472                                  if (pressed)                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0);
473                                  {                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x45, 0);
474                                          rdp_send_scancode(ev_time, RDP_KEYPRESS,                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
475                                                            (SCANCODE_EXTENDED | 0x46));                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x9d, 0);
476                                          rdp_send_scancode(ev_time, RDP_KEYPRESS,                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xc5, 0);
                                                           (SCANCODE_EXTENDED | 0xc6));  
                                 }  
                                 /* No break sequence */  
477                          }                          }
478                          else /* XK_Pause */                          else
479                          {                          {
480                                  /* According to MS Keyboard Scan Code                                  /* Release Left Ctrl */
481                                     Specification, pressing Pause should result                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYRELEASE,
482                                     in E1 1D 45 E1 9D C5. I'm not exactly sure                                                 0x1d, 0);
                                    of how this is supposed to be sent via  
                                    RDP. The code below seems to work, but with  
                                    the side effect that Left Ctrl stays  
                                    down. Therefore, we release it when Pause  
                                    is released. */  
                                 if (pressed)  
                                 {  
                                         rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);  
                                         rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0);  
                                         rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x45, 0);  
                                         rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);  
                                         rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x9d, 0);  
                                         rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xc5, 0);  
                                 }  
                                 else  
                                 {  
                                         /* Release Left Ctrl */  
                                         rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x1d,  
                                                        0);  
                                 }  
483                          }                          }
484                          return True;                          return True;
485                            break;
486    
487                  case XK_Meta_L: /* Windows keys */                  case XK_Meta_L: /* Windows keys */
488                  case XK_Super_L:                  case XK_Super_L:
489                  case XK_Hyper_L:                  case XK_Hyper_L:
490                            send_winkey(ev_time, pressed, True);
491                            return True;
492                            break;
493    
494                  case XK_Meta_R:                  case XK_Meta_R:
495                  case XK_Super_R:                  case XK_Super_R:
496                  case XK_Hyper_R:                  case XK_Hyper_R:
497                          if (pressed)                          send_winkey(ev_time, pressed, False);
                         {  
                                 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LCTRL);  
                                 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_ESC);  
                         }  
                         else  
                         {  
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_ESC);  
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);  
                         }  
498                          return True;                          return True;
499                            break;
500    
501                    case XK_space:
502                            /* Prevent access to the Windows system menu in single app mode */
503                            if (g_win_button_size
504                                && (get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R)))
505                                    return True;
506                            break;
507    
508                    case XK_Num_Lock:
509                            /* Synchronize on key release */
510                            if (g_numlock_sync && !pressed)
511                                    rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
512                                                   ui_get_numlock_state(read_keyboard_state()), 0);
513    
514                            /* Inhibit */
515                            return True;
516                            break;
517    
518          }          }
519          return False;          return False;
520  }  }
# Line 306  handle_special_keys(uint32 keysym, unsig Line 523  handle_special_keys(uint32 keysym, unsig
523  key_translation  key_translation
524  xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state)  xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state)
525  {  {
526          key_translation tr = { 0, 0 };          key_translation tr = { 0, 0, 0, 0 };
527            key_translation *ptr;
         tr = keymap[keysym & KEYMAP_MASK];  
528    
529          if (tr.modifiers & MapInhibitMask)          ptr = keymap[keysym & KEYMAP_MASK];
530            if (ptr)
531          {          {
532                  DEBUG_KBD(("Inhibiting key\n"));                  tr = *ptr;
533                  tr.scancode = 0;                  if (tr.seq_keysym == 0) /* Normal scancode translation */
534                  return tr;                  {
535          }                          if (tr.modifiers & MapInhibitMask)
536                            {
537                                    DEBUG_KBD(("Inhibiting key\n"));
538                                    tr.scancode = 0;
539                                    return tr;
540                            }
541    
542                            if (tr.modifiers & MapLocalStateMask)
543                            {
544                                    /* The modifiers to send for this key should be obtained
545                                       from the local state. Currently, only shift is implemented. */
546                                    if (state & ShiftMask)
547                                    {
548                                            tr.modifiers = MapLeftShiftMask;
549                                    }
550                            }
551    
552          if (tr.modifiers & MapLocalStateMask)                          if ((tr.modifiers & MapLeftShiftMask)
553                                && ((remote_modifier_state & MapLeftCtrlMask)
554                                    || (remote_modifier_state & MapRightCtrlMask))
555                                && get_key_state(state, XK_Caps_Lock))
556                            {
557                                    DEBUG_KBD(("CapsLock + Ctrl pressed, releasing LeftShift\n"));
558                                    tr.modifiers ^= MapLeftShiftMask;
559                            }
560    
561                            DEBUG_KBD(("Found scancode translation, scancode=0x%x, modifiers=0x%x\n",
562                                       tr.scancode, tr.modifiers));
563                    }
564            }
565            else
566          {          {
567                  /* The modifiers to send for this key should be obtained                  if (keymap_loaded)
568                     from the local state. Currently, only shift is implemented. */                          warning("No translation for (keysym 0x%lx, %s)\n", keysym,
569                  if (state & ShiftMask)                                  get_ksname(keysym));
570    
571                    /* not in keymap, try to interpret the raw scancode */
572                    if (((int) keycode >= min_keycode) && (keycode <= 0x60))
573                    {
574                            tr.scancode = keycode - min_keycode;
575    
576                            /* The modifiers to send for this key should be
577                               obtained from the local state. Currently, only
578                               shift is implemented. */
579                            if (state & ShiftMask)
580                            {
581                                    tr.modifiers = MapLeftShiftMask;
582                            }
583    
584                            DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));
585                    }
586                    else
587                  {                  {
588                          tr.modifiers = MapLeftShiftMask;                          DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));
589                  }                  }
590          }          }
591    
592          if (tr.scancode != 0)          return tr;
593          {  }
                 DEBUG_KBD(("Found key translation, scancode=0x%x, modifiers=0x%x\n",  
                            tr.scancode, tr.modifiers));  
                 return tr;  
         }  
594    
595          if (keymap_loaded)  void
596                  error("No translation for (keysym 0x%lx, %s)\n", keysym, get_ksname(keysym));  xkeymap_send_keys(uint32 keysym, unsigned int keycode, unsigned int state, uint32 ev_time,
597                      BOOL pressed)
598    {
599            key_translation tr, *ptr;
600            tr = xkeymap_translate_key(keysym, keycode, state);
601    
602          /* not in keymap, try to interpret the raw scancode */          if (tr.seq_keysym == 0)
         if ((keycode >= min_keycode) && (keycode <= 0x60))  
603          {          {
604                  tr.scancode = keycode - min_keycode;                  /* Scancode translation */
605                    if (tr.scancode == 0)
606                            return;
607    
608                  /* The modifiers to send for this key should be                  if (pressed)
                    obtained from the local state. Currently, only  
                    shift is implemented. */  
                 if (state & ShiftMask)  
609                  {                  {
610                          tr.modifiers = MapLeftShiftMask;                          save_remote_modifiers(tr.scancode);
611                            ensure_remote_modifiers(ev_time, tr);
612                            rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
613                            restore_remote_modifiers(ev_time, tr.scancode);
614                  }                  }
615                    else
616                  DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));                  {
617                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
618                    }
619                    return;
620          }          }
621          else  
622            /* Sequence, only on key down */
623            if (pressed)
624          {          {
625                  DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));                  ptr = &tr;
626                    do
627                    {
628                            DEBUG_KBD(("Handling sequence element, keysym=0x%x\n",
629                                       (unsigned int) ptr->seq_keysym));
630                            xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, True);
631                            xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, False);
632                            ptr = ptr->next;
633                    }
634                    while (ptr);
635          }          }
   
         return tr;  
636  }  }
637    
638  uint16  uint16
# Line 393  get_ksname(uint32 keysym) Line 668  get_ksname(uint32 keysym)
668          return ksname;          return ksname;
669  }  }
670    
671    static BOOL
672  void  is_modifier(uint8 scancode)
 ensure_remote_modifiers(uint32 ev_time, key_translation tr)  
673  {  {
674          /* If this key is a modifier, do nothing */          switch (scancode)
         switch (tr.scancode)  
675          {          {
676                  case SCANCODE_CHAR_LSHIFT:                  case SCANCODE_CHAR_LSHIFT:
677                  case SCANCODE_CHAR_RSHIFT:                  case SCANCODE_CHAR_RSHIFT:
# Line 409  ensure_remote_modifiers(uint32 ev_time, Line 682  ensure_remote_modifiers(uint32 ev_time,
682                  case SCANCODE_CHAR_LWIN:                  case SCANCODE_CHAR_LWIN:
683                  case SCANCODE_CHAR_RWIN:                  case SCANCODE_CHAR_RWIN:
684                  case SCANCODE_CHAR_NUMLOCK:                  case SCANCODE_CHAR_NUMLOCK:
685                          return;                          return True;
686                  default:                  default:
687                          break;                          break;
688          }          }
689            return False;
690    }
691    
692    void
693    save_remote_modifiers(uint8 scancode)
694    {
695            if (is_modifier(scancode))
696                    return;
697    
698            saved_remote_modifier_state = remote_modifier_state;
699    }
700    
701    void
702    restore_remote_modifiers(uint32 ev_time, uint8 scancode)
703    {
704            key_translation dummy;
705    
706            if (is_modifier(scancode))
707                    return;
708    
709            dummy.scancode = 0;
710            dummy.modifiers = saved_remote_modifier_state;
711            ensure_remote_modifiers(ev_time, dummy);
712    }
713    
714    void
715    ensure_remote_modifiers(uint32 ev_time, key_translation tr)
716    {
717            /* If this key is a modifier, do nothing */
718            if (is_modifier(tr.scancode))
719                    return;
720    
721            if (!g_numlock_sync)
722            {
723                    /* NumLock */
724                    if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)
725                        != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask))
726                    {
727                            /* The remote modifier state is not correct */
728                            uint16 new_remote_state;
729    
730                            if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask))
731                            {
732                                    DEBUG_KBD(("Remote NumLock state is incorrect, activating NumLock.\n"));
733                                    new_remote_state = KBD_FLAG_NUMLOCK;
734                                    remote_modifier_state = MapNumLockMask;
735                            }
736                            else
737                            {
738                                    DEBUG_KBD(("Remote NumLock state is incorrect, deactivating NumLock.\n"));
739                                    new_remote_state = 0;
740                                    remote_modifier_state = 0;
741                            }
742    
743                            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0);
744                    }
745            }
746    
747    
748          /* Shift. Left shift and right shift are treated as equal; either is fine. */          /* Shift. Left shift and right shift are treated as equal; either is fine. */
749          if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)          if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
# Line 458  ensure_remote_modifiers(uint32 ev_time, Line 789  ensure_remote_modifiers(uint32 ev_time,
789                  }                  }
790          }          }
791    
         /* NumLock */  
         if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)  
             != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask))  
         {  
                 /* The remote modifier state is not correct */  
                 uint16 new_remote_state = 0;  
792    
793                  if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask))  }
                 {  
                         DEBUG_KBD(("Remote NumLock state is incorrect, activating NumLock.\n"));  
                         new_remote_state |= KBD_FLAG_NUMLOCK;  
                 }  
                 else  
                 {  
                         DEBUG_KBD(("Remote NumLock state is incorrect, deactivating NumLock.\n"));  
                 }  
794    
795                  rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0);  
796                  update_modifier_state(SCANCODE_CHAR_NUMLOCK, True);  unsigned int
797          }  read_keyboard_state()
798    {
799    #ifdef RDP2VNC
800            return 0;
801    #else
802            unsigned int state;
803            Window wdummy;
804            int dummy;
805    
806            XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
807            return state;
808    #endif
809    }
810    
811    
812    uint16
813    ui_get_numlock_state(unsigned int state)
814    {
815            uint16 numlock_state = 0;
816    
817            if (get_key_state(state, XK_Num_Lock))
818                    numlock_state = KBD_FLAG_NUMLOCK;
819    
820            return numlock_state;
821  }  }
822    
823    
824  void  void
825  reset_modifier_keys(unsigned int state)  reset_modifier_keys()
826  {  {
827            unsigned int state = read_keyboard_state();
828    
829          /* reset keys */          /* reset keys */
830          uint32 ev_time;          uint32 ev_time;
831          ev_time = time(NULL);          ev_time = time(NULL);
832    
833          if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask) && !get_key_state(state, XK_Shift_L))          if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask)
834                && !get_key_state(state, XK_Shift_L))
835                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
836    
837          if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask) && !get_key_state(state, XK_Shift_R))          if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask)
838                && !get_key_state(state, XK_Shift_R))
839                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
840    
841          if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask) && !get_key_state(state, XK_Control_L))          if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask)
842                && !get_key_state(state, XK_Control_L))
843                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
844    
845          if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask) && !get_key_state(state, XK_Control_R))          if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask)
846                && !get_key_state(state, XK_Control_R))
847                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
848    
849          if (MASK_HAS_BITS(remote_modifier_state, MapLeftAltMask) && !get_key_state(state, XK_Alt_L))          if (MASK_HAS_BITS(remote_modifier_state, MapLeftAltMask) && !get_key_state(state, XK_Alt_L))
850                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
851    
852          if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) &&          if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) &&
853              !get_key_state(state, XK_Alt_R) && !get_key_state(state, XK_Mode_switch))              !get_key_state(state, XK_Alt_R) && !get_key_state(state, XK_Mode_switch)
854                && !get_key_state(state, XK_ISO_Level3_Shift))
855                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
856    
857            reset_winkey(ev_time);
858    
859            if (g_numlock_sync)
860                    rdp_send_input(ev_time, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(state), 0);
861  }  }
862    
863    
# Line 547  update_modifier_state(uint8 scancode, BO Line 899  update_modifier_state(uint8 scancode, BO
899                  case SCANCODE_CHAR_NUMLOCK:                  case SCANCODE_CHAR_NUMLOCK:
900                          /* KeyReleases for NumLocks are sent immediately. Toggle the                          /* KeyReleases for NumLocks are sent immediately. Toggle the
901                             modifier state only on Keypress */                             modifier state only on Keypress */
902                          if (pressed)                          if (pressed && !g_numlock_sync)
903                          {                          {
904                                  BOOL newNumLockState;                                  BOOL newNumLockState;
905                                  newNumLockState =                                  newNumLockState =
# Line 556  update_modifier_state(uint8 scancode, BO Line 908  update_modifier_state(uint8 scancode, BO
908                                  MASK_CHANGE_BIT(remote_modifier_state,                                  MASK_CHANGE_BIT(remote_modifier_state,
909                                                  MapNumLockMask, newNumLockState);                                                  MapNumLockMask, newNumLockState);
910                          }                          }
                         break;  
911          }          }
912    
913  #ifdef WITH_DEBUG_KBD  #ifdef WITH_DEBUG_KBD

Legend:
Removed from v.216  
changed lines
  Added in v.957

  ViewVC Help
Powered by ViewVC 1.1.26