/[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 225 by astrand, Fri Oct 11 08:54:08 2002 UTC revision 955 by astrand, Wed Aug 3 07:08:17 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, included 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  static BOOL  static BOOL
159  xkeymap_read(char *mapname)  xkeymap_read(char *mapname)
# Line 126  xkeymap_read(char *mapname) Line 216  xkeymap_read(char *mapname)
216                  /* map */                  /* map */
217                  if (strncmp(line, "map ", 4) == 0)                  if (strncmp(line, "map ", 4) == 0)
218                  {                  {
219                          keylayout = strtol(line + 4, NULL, 16);                          g_keylayout = strtol(line + 4, NULL, 16);
220                          DEBUG_KBD(("Keylayout 0x%x\n", keylayout));                          DEBUG_KBD(("Keylayout 0x%x\n", g_keylayout));
221                          continue;                          continue;
222                  }                  }
223    
# Line 135  xkeymap_read(char *mapname) Line 225  xkeymap_read(char *mapname)
225                  if (strncmp(line, "enable_compose", 15) == 0)                  if (strncmp(line, "enable_compose", 15) == 0)
226                  {                  {
227                          DEBUG_KBD(("Enabling compose handling\n"));                          DEBUG_KBD(("Enabling compose handling\n"));
228                          enable_compose = True;                          g_enable_compose = True;
229                            continue;
230                    }
231    
232                    /* sequence */
233                    if (strncmp(line, "sequence", 8) == 0)
234                    {
235                            add_sequence(line + 8, mapname);
236                          continue;                          continue;
237                  }                  }
238    
# Line 198  xkeymap_read(char *mapname) Line 295  xkeymap_read(char *mapname)
295                          /* Automatically add uppercase key, with same modifiers                          /* Automatically add uppercase key, with same modifiers
296                             plus shift */                             plus shift */
297                          for (p = keyname; *p; p++)                          for (p = keyname; *p; p++)
298                                  *p = toupper(*p);                                  *p = toupper((int) *p);
299                          MASK_ADD_BITS(modifiers, MapLeftShiftMask);                          MASK_ADD_BITS(modifiers, MapLeftShiftMask);
300                          add_to_keymap(keyname, scancode, modifiers, mapname);                          add_to_keymap(keyname, scancode, modifiers, mapname);
301                  }                  }
# Line 218  xkeymap_init(void) Line 315  xkeymap_init(void)
315    
316          /* Make keymapname lowercase */          /* Make keymapname lowercase */
317          mapname_ptr = keymapname;          mapname_ptr = keymapname;
318          while (*mapname_ptr)          while (*mapname_ptr)
319              *mapname_ptr++ = tolower(*mapname_ptr);          {
320                    *mapname_ptr = tolower((int) *mapname_ptr);
321                    mapname_ptr++;
322            }
323    
324          if (strcmp(keymapname, "none"))          if (strcmp(keymapname, "none"))
325          {          {
# Line 227  xkeymap_init(void) Line 327  xkeymap_init(void)
327                          keymap_loaded = True;                          keymap_loaded = True;
328          }          }
329    
330          XDisplayKeycodes(display, &min_keycode, (int *) &max_keycode);          XDisplayKeycodes(g_display, &min_keycode, (int *) &max_keycode);
331    }
332    
333    static void
334    send_winkey(uint32 ev_time, BOOL pressed, BOOL leftkey)
335    {
336            uint8 winkey;
337    
338            if (leftkey)
339                    winkey = SCANCODE_CHAR_LWIN;
340            else
341                    winkey = SCANCODE_CHAR_RWIN;
342    
343            if (pressed)
344            {
345                    if (g_use_rdp5)
346                    {
347                            rdp_send_scancode(ev_time, RDP_KEYPRESS, winkey);
348                    }
349                    else
350                    {
351                            /* RDP4 doesn't support winkey. Fake with Ctrl-Esc */
352                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LCTRL);
353                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_ESC);
354                    }
355            }
356            else
357            {
358                    /* key released */
359                    if (g_use_rdp5)
360                    {
361                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, winkey);
362                    }
363                    else
364                    {
365                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_ESC);
366                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
367                    }
368            }
369    }
370    
371    static void
372    reset_winkey(uint32 ev_time)
373    {
374            if (g_use_rdp5)
375            {
376                    /* For some reason, it seems to suffice to release
377                     *either* the left or right winkey. */
378                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LWIN);
379            }
380  }  }
381    
382  /* Handles, for example, multi-scancode keypresses (which is not  /* Handle special key combinations */
    possible via keymap-files) */  
383  BOOL  BOOL
384  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)
385  {  {
386          switch (keysym)          switch (keysym)
387          {          {
388                  case XK_Break:                  case XK_Return:
                 case XK_Pause:  
389                          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))
390                                  && (get_key_state(state, XK_Control_L) || get_key_state(state, XK_Control_R)))                              && (get_key_state(state, XK_Control_L)
391                                    || get_key_state(state, XK_Control_R)))
392                          {                          {
393                                  /* Ctrl-Alt-Break: toggle full screen */                                  /* Ctrl-Alt-Enter: toggle full screen */
394                                  if (pressed)                                  if (pressed)
395                                          xwin_toggle_fullscreen();                                          xwin_toggle_fullscreen();
396                                    return True;
397                            }
398                            break;
399    
400                    case XK_Break:
401                            /* Send Break sequence E0 46 E0 C6 */
402                            if (pressed)
403                            {
404                                    rdp_send_scancode(ev_time, RDP_KEYPRESS,
405                                                      (SCANCODE_EXTENDED | 0x46));
406                                    rdp_send_scancode(ev_time, RDP_KEYPRESS,
407                                                      (SCANCODE_EXTENDED | 0xc6));
408                          }                          }
409                          else if (keysym == XK_Break)                          /* No release sequence */
410                            return True;
411                            break;
412    
413                    case XK_Pause:
414                            /* According to MS Keyboard Scan Code
415                               Specification, pressing Pause should result
416                               in E1 1D 45 E1 9D C5. I'm not exactly sure
417                               of how this is supposed to be sent via
418                               RDP. The code below seems to work, but with
419                               the side effect that Left Ctrl stays
420                               down. Therefore, we release it when Pause
421                               is released. */
422                            if (pressed)
423                          {                          {
424                                  /* Send Break sequence E0 46 E0 C6 */                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
425                                  if (pressed)                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0);
426                                  {                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x45, 0);
427                                          rdp_send_scancode(ev_time, RDP_KEYPRESS,                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
428                                                            (SCANCODE_EXTENDED | 0x46));                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x9d, 0);
429                                          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 */  
430                          }                          }
431                          else /* XK_Pause */                          else
432                          {                          {
433                                  /* According to MS Keyboard Scan Code                                  /* Release Left Ctrl */
434                                     Specification, pressing Pause should result                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYRELEASE,
435                                     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);  
                                 }  
436                          }                          }
437                          return True;                          return True;
438                            break;
439    
440                  case XK_Meta_L: /* Windows keys */                  case XK_Meta_L: /* Windows keys */
441                  case XK_Super_L:                  case XK_Super_L:
442                  case XK_Hyper_L:                  case XK_Hyper_L:
443                            send_winkey(ev_time, pressed, True);
444                            return True;
445                            break;
446    
447                  case XK_Meta_R:                  case XK_Meta_R:
448                  case XK_Super_R:                  case XK_Super_R:
449                  case XK_Hyper_R:                  case XK_Hyper_R:
450                          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);  
                         }  
451                          return True;                          return True;
452                            break;
453    
454                    case XK_space:
455                            /* Prevent access to the Windows system menu in single app mode */
456                            if (g_win_button_size
457                                && (get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R)))
458                                    return True;
459                            break;
460    
461                    case XK_Num_Lock:
462                            /* Synchronize on key release */
463                            if (g_numlock_sync && !pressed)
464                                    rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
465                                                   ui_get_numlock_state(read_keyboard_state()), 0);
466    
467                            /* Inhibit */
468                            return True;
469                            break;
470    
471          }          }
472          return False;          return False;
473  }  }
# Line 312  handle_special_keys(uint32 keysym, unsig Line 476  handle_special_keys(uint32 keysym, unsig
476  key_translation  key_translation
477  xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state)  xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state)
478  {  {
479          key_translation tr = { 0, 0 };          key_translation tr = { 0, 0, 0, 0 };
480            key_translation *ptr;
481    
482          tr = keymap[keysym & KEYMAP_MASK];          ptr = keymap[keysym & KEYMAP_MASK];
483            if (ptr)
         if (tr.modifiers & MapInhibitMask)  
484          {          {
485                  DEBUG_KBD(("Inhibiting key\n"));                  tr = *ptr;
486                  tr.scancode = 0;                  if (tr.seq_keysym == 0) /* Normal scancode translation */
487                  return tr;                  {
488          }                          if (tr.modifiers & MapInhibitMask)
489                            {
490                                    DEBUG_KBD(("Inhibiting key\n"));
491                                    tr.scancode = 0;
492                                    return tr;
493                            }
494    
495                            if (tr.modifiers & MapLocalStateMask)
496                            {
497                                    /* The modifiers to send for this key should be obtained
498                                       from the local state. Currently, only shift is implemented. */
499                                    if (state & ShiftMask)
500                                    {
501                                            tr.modifiers = MapLeftShiftMask;
502                                    }
503                            }
504    
505          if (tr.modifiers & MapLocalStateMask)                          if ((tr.modifiers & MapLeftShiftMask)
506                                && ((remote_modifier_state & MapLeftCtrlMask)
507                                    || (remote_modifier_state & MapRightCtrlMask))
508                                && get_key_state(state, XK_Caps_Lock))
509                            {
510                                    DEBUG_KBD(("CapsLock + Ctrl pressed, releasing LeftShift\n"));
511                                    tr.modifiers ^= MapLeftShiftMask;
512                            }
513    
514                            DEBUG_KBD(("Found scancode translation, scancode=0x%x, modifiers=0x%x\n",
515                                       tr.scancode, tr.modifiers));
516                    }
517            }
518            else
519          {          {
520                  /* The modifiers to send for this key should be obtained                  if (keymap_loaded)
521                     from the local state. Currently, only shift is implemented. */                          warning("No translation for (keysym 0x%lx, %s)\n", keysym,
522                  if (state & ShiftMask)                                  get_ksname(keysym));
523    
524                    /* not in keymap, try to interpret the raw scancode */
525                    if (((int) keycode >= min_keycode) && (keycode <= 0x60))
526                    {
527                            tr.scancode = keycode - min_keycode;
528    
529                            /* The modifiers to send for this key should be
530                               obtained from the local state. Currently, only
531                               shift is implemented. */
532                            if (state & ShiftMask)
533                            {
534                                    tr.modifiers = MapLeftShiftMask;
535                            }
536    
537                            DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));
538                    }
539                    else
540                  {                  {
541                          tr.modifiers = MapLeftShiftMask;                          DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));
542                  }                  }
543          }          }
544    
545          if (tr.scancode != 0)          return tr;
546          {  }
                 DEBUG_KBD(("Found key translation, scancode=0x%x, modifiers=0x%x\n",  
                            tr.scancode, tr.modifiers));  
                 return tr;  
         }  
547    
548          if (keymap_loaded)  void
549                  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,
550                      BOOL pressed)
551    {
552            key_translation tr, *ptr;
553            tr = xkeymap_translate_key(keysym, keycode, state);
554    
555          /* not in keymap, try to interpret the raw scancode */          if (tr.seq_keysym == 0)
         if ((keycode >= min_keycode) && (keycode <= 0x60))  
556          {          {
557                  tr.scancode = keycode - min_keycode;                  /* Scancode translation */
558                    if (tr.scancode == 0)
559                            return;
560    
561                  /* The modifiers to send for this key should be                  if (pressed)
                    obtained from the local state. Currently, only  
                    shift is implemented. */  
                 if (state & ShiftMask)  
562                  {                  {
563                          tr.modifiers = MapLeftShiftMask;                          save_remote_modifiers(tr.scancode);
564                            ensure_remote_modifiers(ev_time, tr);
565                            rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
566                            restore_remote_modifiers(ev_time, tr.scancode);
567                  }                  }
568                    else
569                  DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));                  {
570                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
571                    }
572                    return;
573          }          }
574          else  
575            /* Sequence, only on key down */
576            if (pressed)
577          {          {
578                  DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));                  ptr = &tr;
579                    do
580                    {
581                            DEBUG_KBD(("Handling sequence element, keysym=0x%x\n",
582                                       (unsigned int) ptr->seq_keysym));
583                            xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, True);
584                            xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, False);
585                            ptr = ptr->next;
586                    }
587                    while (ptr);
588          }          }
   
         return tr;  
589  }  }
590    
591  uint16  uint16
# Line 399  get_ksname(uint32 keysym) Line 621  get_ksname(uint32 keysym)
621          return ksname;          return ksname;
622  }  }
623    
624    static BOOL
625  void  is_modifier(uint8 scancode)
 ensure_remote_modifiers(uint32 ev_time, key_translation tr)  
626  {  {
627          /* If this key is a modifier, do nothing */          switch (scancode)
         switch (tr.scancode)  
628          {          {
629                  case SCANCODE_CHAR_LSHIFT:                  case SCANCODE_CHAR_LSHIFT:
630                  case SCANCODE_CHAR_RSHIFT:                  case SCANCODE_CHAR_RSHIFT:
# Line 415  ensure_remote_modifiers(uint32 ev_time, Line 635  ensure_remote_modifiers(uint32 ev_time,
635                  case SCANCODE_CHAR_LWIN:                  case SCANCODE_CHAR_LWIN:
636                  case SCANCODE_CHAR_RWIN:                  case SCANCODE_CHAR_RWIN:
637                  case SCANCODE_CHAR_NUMLOCK:                  case SCANCODE_CHAR_NUMLOCK:
638                          return;                          return True;
639                  default:                  default:
640                          break;                          break;
641          }          }
642            return False;
643    }
644    
645    void
646    save_remote_modifiers(uint8 scancode)
647    {
648            if (is_modifier(scancode))
649                    return;
650    
651            saved_remote_modifier_state = remote_modifier_state;
652    }
653    
654    void
655    restore_remote_modifiers(uint32 ev_time, uint8 scancode)
656    {
657            key_translation dummy;
658    
659            if (is_modifier(scancode))
660                    return;
661    
662            dummy.scancode = 0;
663            dummy.modifiers = saved_remote_modifier_state;
664            ensure_remote_modifiers(ev_time, dummy);
665    }
666    
667    void
668    ensure_remote_modifiers(uint32 ev_time, key_translation tr)
669    {
670            /* If this key is a modifier, do nothing */
671            if (is_modifier(tr.scancode))
672                    return;
673    
674            if (!g_numlock_sync)
675            {
676                    /* NumLock */
677                    if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)
678                        != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask))
679                    {
680                            /* The remote modifier state is not correct */
681                            uint16 new_remote_state;
682    
683                            if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask))
684                            {
685                                    DEBUG_KBD(("Remote NumLock state is incorrect, activating NumLock.\n"));
686                                    new_remote_state = KBD_FLAG_NUMLOCK;
687                                    remote_modifier_state = MapNumLockMask;
688                            }
689                            else
690                            {
691                                    DEBUG_KBD(("Remote NumLock state is incorrect, deactivating NumLock.\n"));
692                                    new_remote_state = 0;
693                                    remote_modifier_state = 0;
694                            }
695    
696                            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0);
697                    }
698            }
699    
700    
701          /* 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. */
702          if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)          if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
# Line 464  ensure_remote_modifiers(uint32 ev_time, Line 742  ensure_remote_modifiers(uint32 ev_time,
742                  }                  }
743          }          }
744    
         /* 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;  
745    
746                  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"));  
                 }  
747    
748                  rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0);  
749                  update_modifier_state(SCANCODE_CHAR_NUMLOCK, True);  unsigned int
750          }  read_keyboard_state()
751    {
752    #ifdef RDP2VNC
753            return 0;
754    #else
755            unsigned int state;
756            Window wdummy;
757            int dummy;
758    
759            XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
760            return state;
761    #endif
762    }
763    
764    
765    uint16
766    ui_get_numlock_state(unsigned int state)
767    {
768            uint16 numlock_state = 0;
769    
770            if (get_key_state(state, XK_Num_Lock))
771                    numlock_state = KBD_FLAG_NUMLOCK;
772    
773            return numlock_state;
774  }  }
775    
776    
777  void  void
778  reset_modifier_keys(unsigned int state)  reset_modifier_keys()
779  {  {
780            unsigned int state = read_keyboard_state();
781    
782          /* reset keys */          /* reset keys */
783          uint32 ev_time;          uint32 ev_time;
784          ev_time = time(NULL);          ev_time = time(NULL);
785    
786          if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask) && !get_key_state(state, XK_Shift_L))          if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask)
787                && !get_key_state(state, XK_Shift_L))
788                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
789    
790          if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask) && !get_key_state(state, XK_Shift_R))          if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask)
791                && !get_key_state(state, XK_Shift_R))
792                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
793    
794          if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask) && !get_key_state(state, XK_Control_L))          if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask)
795                && !get_key_state(state, XK_Control_L))
796                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
797    
798          if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask) && !get_key_state(state, XK_Control_R))          if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask)
799                && !get_key_state(state, XK_Control_R))
800                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
801    
802          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))
803                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
804    
805          if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) &&          if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) &&
806              !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)
807                && !get_key_state(state, XK_ISO_Level3_Shift))
808                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
809    
810            reset_winkey(ev_time);
811    
812            if (g_numlock_sync)
813                    rdp_send_input(ev_time, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(state), 0);
814  }  }
815    
816    
# Line 553  update_modifier_state(uint8 scancode, BO Line 852  update_modifier_state(uint8 scancode, BO
852                  case SCANCODE_CHAR_NUMLOCK:                  case SCANCODE_CHAR_NUMLOCK:
853                          /* KeyReleases for NumLocks are sent immediately. Toggle the                          /* KeyReleases for NumLocks are sent immediately. Toggle the
854                             modifier state only on Keypress */                             modifier state only on Keypress */
855                          if (pressed)                          if (pressed && !g_numlock_sync)
856                          {                          {
857                                  BOOL newNumLockState;                                  BOOL newNumLockState;
858                                  newNumLockState =                                  newNumLockState =
# Line 562  update_modifier_state(uint8 scancode, BO Line 861  update_modifier_state(uint8 scancode, BO
861                                  MASK_CHANGE_BIT(remote_modifier_state,                                  MASK_CHANGE_BIT(remote_modifier_state,
862                                                  MapNumLockMask, newNumLockState);                                                  MapNumLockMask, newNumLockState);
863                          }                          }
                         break;  
864          }          }
865    
866  #ifdef WITH_DEBUG_KBD  #ifdef WITH_DEBUG_KBD

Legend:
Removed from v.225  
changed lines
  Added in v.955

  ViewVC Help
Powered by ViewVC 1.1.26