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

Legend:
Removed from v.170  
changed lines
  Added in v.961

  ViewVC Help
Powered by ViewVC 1.1.26