/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/xkeymap.c

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

revision 297 by matthewc, Tue Jan 28 12:27:28 2003 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-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 <string.h>
34  #include "rdesktop.h"  #include "rdesktop.h"
35  #include "scancodes.h"  #include "scancodes.h"
36    
# Line 31  Line 38 
38  #define KEYMAP_MASK 0xffff  #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 BOOL keymap_loaded;  static BOOL keymap_loaded;
51  static key_translation keymap[KEYMAP_SIZE];  static key_translation *keymap[KEYMAP_SIZE];
52  static int min_keycode;  static int min_keycode;
53  static uint16 remote_modifier_state = 0;  static uint16 remote_modifier_state = 0;
54    static uint16 saved_remote_modifier_state = 0;
55    
56  static void update_modifier_state(uint8 scancode, BOOL pressed);  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                  warning("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];          char line[KEYMAP_MAX_LINE_LENGTH];
         char path[PATH_MAX], inplace_path[PATH_MAX];  
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 78  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                  /* in case we are running from the source tree */                  error("Failed to open keymap %s\n", mapname);
235                  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;  
                 }  
236          }          }
237    
238          /* FIXME: More tolerant on white space */          /* FIXME: More tolerant on white space */
# Line 126  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 135  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 198  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 216  xkeymap_init(void) Line 361  xkeymap_init(void)
361          unsigned int max_keycode;          unsigned int max_keycode;
362          char *mapname_ptr;          char *mapname_ptr;
363    
         /* Make keymapname lowercase */  
         mapname_ptr = keymapname;  
         while (*mapname_ptr)  
         {  
                 *mapname_ptr = tolower(*mapname_ptr);  
                 mapname_ptr++;  
         }  
   
364          if (strcmp(keymapname, "none"))          if (strcmp(keymapname, "none"))
365          {          {
366                  if (xkeymap_read(keymapname))                  if (xkeymap_read(keymapname))
367                          keymap_loaded = True;                          keymap_loaded = True;
368          }          }
369    
370          XDisplayKeycodes(display, &min_keycode, (int *) &max_keycode);          XDisplayKeycodes(g_display, &min_keycode, (int *) &max_keycode);
371    }
372    
373    static void
374    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  /* Handles, for example, multi-scancode keypresses (which is not  /* Handle special key combinations */
    possible via keymap-files) */  
423  BOOL  BOOL
424  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)
425  {  {
# Line 263  handle_special_keys(uint32 keysym, unsig Line 448  handle_special_keys(uint32 keysym, unsig
448                          }                          }
449                          /* No release sequence */                          /* No release sequence */
450                          return True;                          return True;
451                            break;
452    
453                  case XK_Pause:                  case XK_Pause:
454                          /* According to MS Keyboard Scan Code                          /* According to MS Keyboard Scan Code
# Line 289  handle_special_keys(uint32 keysym, unsig Line 475  handle_special_keys(uint32 keysym, unsig
475                                                 0x1d, 0);                                                 0x1d, 0);
476                          }                          }
477                          return True;                          return True;
478                            break;
479    
480                  case XK_Meta_L: /* Windows keys */                  case XK_Meta_L: /* Windows keys */
481                  case XK_Super_L:                  case XK_Super_L:
482                  case XK_Hyper_L:                  case XK_Hyper_L:
483                            send_winkey(ev_time, pressed, True);
484                            return True;
485                            break;
486    
487                  case XK_Meta_R:                  case XK_Meta_R:
488                  case XK_Super_R:                  case XK_Super_R:
489                  case XK_Hyper_R:                  case XK_Hyper_R:
490                          if (pressed)                          send_winkey(ev_time, pressed, False);
491                          {                          return True;
492                                  rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LCTRL);                          break;
493                                  rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_ESC);  
494                          }                  case XK_space:
495                          else                          /* Prevent access to the Windows system menu in single app mode */
496                          {                          if (g_win_button_size
497                                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_ESC);                              && (get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R)))
498                                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);                                  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;                          return True;
509                            break;
510    
511          }          }
512          return False;          return False;
513  }  }
# Line 315  handle_special_keys(uint32 keysym, unsig Line 516  handle_special_keys(uint32 keysym, unsig
516  key_translation  key_translation
517  xkeymap_translate_key(uint32 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;
521    
522          tr = keymap[keysym & KEYMAP_MASK];          ptr = keymap[keysym & KEYMAP_MASK];
523            if (ptr)
         if (tr.modifiers & MapInhibitMask)  
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          if (keymap_loaded)  void
589                  warning("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,
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                  DEBUG_KBD(("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                  DEBUG_KBD(("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 402  get_ksname(uint32 keysym) Line 661  get_ksname(uint32 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 418  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. 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. */
742          if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)          if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
# Line 467  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(unsigned int state)  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);
# Line 517  reset_modifier_keys(unsigned int state) Line 843  reset_modifier_keys(unsigned int state)
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(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)
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    
# Line 560  update_modifier_state(uint8 scancode, BO Line 892  update_modifier_state(uint8 scancode, BO
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 569  update_modifier_state(uint8 scancode, BO Line 901  update_modifier_state(uint8 scancode, BO
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

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

  ViewVC Help
Powered by ViewVC 1.1.26