/[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 67 by jsorg71, Tue Jul 23 01:53:04 2002 UTC revision 951 by astrand, Tue Aug 2 18:07:56 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 "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 int g_win_button_size;
45  static key_translation keymap[KEYMAP_SIZE];  extern BOOL g_enable_compose;
46  static unsigned int min_keycode;  extern BOOL g_use_rdp5;
47    extern BOOL g_numlock_sync;
48    
49    static BOOL keymap_loaded;
50    static key_translation *keymap[KEYMAP_SIZE];
51    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);
56    
57    /* Free key_translation structure, included linked list */
58    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=0x%x\n", (unsigned int) keysym, scancode, modifiers));
                   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)
160  {  {
161          FILE *fp;          FILE *fp;
162          char line[KEYMAP_MAX_LINE_LENGTH], path[PATH_MAX];          char line[KEYMAP_MAX_LINE_LENGTH];
163            char path[PATH_MAX], inplace_path[PATH_MAX];
164          unsigned int line_num = 0;          unsigned int line_num = 0;
165          unsigned int line_length = 0;          unsigned int line_length = 0;
166          char *keyname, *p;          char *keyname, *p;
# Line 82  xkeymap_read(char *mapname) Line 175  xkeymap_read(char *mapname)
175          fp = fopen(path, "r");          fp = fopen(path, "r");
176          if (fp == NULL)          if (fp == NULL)
177          {          {
178                  error("Failed to open keymap %s\n", path);                  /* in case we are running from the source tree */
179                  return False;                  strcpy(inplace_path, "keymaps/");
180                    strncat(inplace_path, mapname, sizeof(inplace_path) - sizeof("keymaps/"));
181    
182                    fp = fopen(inplace_path, "r");
183                    if (fp == NULL)
184                    {
185                            error("Failed to open keymap %s\n", path);
186                            return False;
187                    }
188          }          }
189    
190          /* FIXME: More tolerant on white space */          /* FIXME: More tolerant on white space */
# Line 115  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;
222                    }
223    
224                    /* compose */
225                    if (strncmp(line, "enable_compose", 15) == 0)
226                    {
227                            DEBUG_KBD(("Enabling compose handling\n"));
228                            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 131  xkeymap_read(char *mapname) Line 247  xkeymap_read(char *mapname)
247                  p = strchr(line, ' ');                  p = strchr(line, ' ');
248                  if (p == NULL)                  if (p == NULL)
249                  {                  {
250                          error("Bad line %d in keymap %s\n", line_num,                          error("Bad line %d in keymap %s\n", line_num, mapname);
                               mapname);  
251                          continue;                          continue;
252                  }                  }
253                  else                  else
# Line 163  xkeymap_read(char *mapname) Line 278  xkeymap_read(char *mapname)
278                          MASK_ADD_BITS(modifiers, MapNumLockMask);                          MASK_ADD_BITS(modifiers, MapNumLockMask);
279                  }                  }
280    
281                    if (strstr(line_rest, "localstate"))
282                    {
283                            MASK_ADD_BITS(modifiers, MapLocalStateMask);
284                    }
285    
286                    if (strstr(line_rest, "inhibit"))
287                    {
288                            MASK_ADD_BITS(modifiers, MapInhibitMask);
289                    }
290    
291                  add_to_keymap(keyname, scancode, modifiers, mapname);                  add_to_keymap(keyname, scancode, modifiers, mapname);
292    
293                  if (strstr(line_rest, "addupper"))                  if (strstr(line_rest, "addupper"))
# Line 170  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 183  xkeymap_read(char *mapname) Line 308  xkeymap_read(char *mapname)
308    
309  /* Before connecting and creating UI */  /* Before connecting and creating UI */
310  void  void
311  xkeymap_init1(void)  xkeymap_init(void)
312  {  {
313          int i;          unsigned int max_keycode;
314            char *mapname_ptr;
315    
316          /* Zeroing keymap */          /* Make keymapname lowercase */
317          for (i = 0; i < KEYMAP_SIZE; i++)          mapname_ptr = keymapname;
318            while (*mapname_ptr)
319          {          {
320                  keymap[i].scancode = 0;                  *mapname_ptr = tolower((int) *mapname_ptr);
321                  keymap[i].modifiers = 0;                  mapname_ptr++;
322          }          }
323    
324          if (strcmp(keymapname, "none"))          if (strcmp(keymapname, "none"))
325          {          {
326                  xkeymap_read(keymapname);                  if (xkeymap_read(keymapname))
327                            keymap_loaded = True;
328          }          }
329    
330            XDisplayKeycodes(g_display, &min_keycode, (int *) &max_keycode);
331  }  }
332    
333  /* After connecting and creating UI */  static void
334  void  send_winkey(uint32 ev_time, BOOL pressed, BOOL leftkey)
 xkeymap_init2(void)  
335  {  {
336          unsigned int max_keycode;          uint8 winkey;
337          XDisplayKeycodes(display, &min_keycode, &max_keycode);  
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  key_translation  /* Handles, for example, multi-scancode keypresses (which is not
383  xkeymap_translate_key(KeySym keysym, unsigned int keycode)     possible via keymap-files) */
384    BOOL
385    handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)
386  {  {
387          key_translation tr = { 0, 0 };          switch (keysym)
388            {
389                    case XK_Return:
390                            if ((get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R))
391                                && (get_key_state(state, XK_Control_L)
392                                    || get_key_state(state, XK_Control_R)))
393                            {
394                                    /* Ctrl-Alt-Enter: toggle full screen */
395                                    if (pressed)
396                                            xwin_toggle_fullscreen();
397                                    return True;
398                            }
399                            break;
400    
401          tr = keymap[keysym & KEYMAP_MASK];                  case XK_Break:
402                            /* Send Break sequence E0 46 E0 C6 */
403                            if (pressed)
404                            {
405                                    rdp_send_scancode(ev_time, RDP_KEYPRESS,
406                                                      (SCANCODE_EXTENDED | 0x46));
407                                    rdp_send_scancode(ev_time, RDP_KEYPRESS,
408                                                      (SCANCODE_EXTENDED | 0xc6));
409                            }
410                            /* No release sequence */
411                            return True;
412                            break;
413    
414                    case XK_Pause:
415                            /* According to MS Keyboard Scan Code
416                               Specification, pressing Pause should result
417                               in E1 1D 45 E1 9D C5. I'm not exactly sure
418                               of how this is supposed to be sent via
419                               RDP. The code below seems to work, but with
420                               the side effect that Left Ctrl stays
421                               down. Therefore, we release it when Pause
422                               is released. */
423                            if (pressed)
424                            {
425                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
426                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0);
427                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x45, 0);
428                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
429                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x9d, 0);
430                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xc5, 0);
431                            }
432                            else
433                            {
434                                    /* Release Left Ctrl */
435                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYRELEASE,
436                                                   0x1d, 0);
437                            }
438                            return True;
439                            break;
440    
441                    case XK_Meta_L: /* Windows keys */
442                    case XK_Super_L:
443                    case XK_Hyper_L:
444                            send_winkey(ev_time, pressed, True);
445                            return True;
446                            break;
447    
448                    case XK_Meta_R:
449                    case XK_Super_R:
450                    case XK_Hyper_R:
451                            send_winkey(ev_time, pressed, False);
452                            return True;
453                            break;
454    
455                    case XK_space:
456                            /* Prevent access to the Windows system menu in single app mode */
457                            if (g_win_button_size
458                                && (get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R)))
459                                    return True;
460                            break;
461    
462                    case XK_Num_Lock:
463                            /* Synchronize on key release */
464                            if (g_numlock_sync && !pressed)
465                                    rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
466                                                   ui_get_numlock_state(read_keyboard_state()), 0);
467    
468                            /* Inhibit */
469                            return True;
470                            break;
471    
         if (tr.scancode != 0)  
         {  
                 DEBUG_KBD  
                         ("Found key translation, scancode=0x%x, modifiers=0x%x\n",  
                          tr.scancode, tr.modifiers);  
                 return tr;  
472          }          }
473            return False;
474    }
475    
         printf("No translation for (keysym 0x%lx, %s)\n", keysym,  
                get_ksname(keysym));  
476    
477          /* not in keymap, try to interpret the raw scancode */  key_translation
478          if ((keycode >= min_keycode) && (keycode <= 0x60))  xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state)
479    {
480            key_translation tr = { 0, 0, 0, 0 };
481            key_translation *ptr;
482    
483            ptr = keymap[keysym & KEYMAP_MASK];
484            if (ptr)
485          {          {
486                  tr.scancode = keycode - min_keycode;                  tr = *ptr;
487                  printf("Sending guessed scancode 0x%x\n", tr.scancode);                  if (tr.seq_keysym == 0) /* Normal scancode translation */
488                    {
489                            if (tr.modifiers & MapInhibitMask)
490                            {
491                                    DEBUG_KBD(("Inhibiting key\n"));
492                                    tr.scancode = 0;
493                                    return tr;
494                            }
495    
496                            if (tr.modifiers & MapLocalStateMask)
497                            {
498                                    /* The modifiers to send for this key should be obtained
499                                       from the local state. Currently, only shift is implemented. */
500                                    if (state & ShiftMask)
501                                    {
502                                            tr.modifiers = MapLeftShiftMask;
503                                    }
504                            }
505    
506                            if ((tr.modifiers & MapLeftShiftMask)
507                                && ((remote_modifier_state & MapLeftCtrlMask)
508                                    || (remote_modifier_state & MapRightCtrlMask))
509                                && get_key_state(state, XK_Caps_Lock))
510                            {
511                                    DEBUG_KBD(("CapsLock + Ctrl pressed, releasing LeftShift\n"));
512                                    tr.modifiers ^= MapLeftShiftMask;
513                            }
514    
515                            DEBUG_KBD(("Found scancode translation, scancode=0x%x, modifiers=0x%x\n",
516                                       tr.scancode, tr.modifiers));
517                    }
518          }          }
519          else          else
520          {          {
521                  printf("No good guess for keycode 0x%x found\n", keycode);                  if (keymap_loaded)
522                            warning("No translation for (keysym 0x%lx, %s)\n", keysym,
523                                    get_ksname(keysym));
524    
525                    /* not in keymap, try to interpret the raw scancode */
526                    if (((int) keycode >= min_keycode) && (keycode <= 0x60))
527                    {
528                            tr.scancode = keycode - min_keycode;
529    
530                            /* The modifiers to send for this key should be
531                               obtained from the local state. Currently, only
532                               shift is implemented. */
533                            if (state & ShiftMask)
534                            {
535                                    tr.modifiers = MapLeftShiftMask;
536                            }
537    
538                            DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));
539                    }
540                    else
541                    {
542                            DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));
543                    }
544          }          }
545    
546          return tr;          return tr;
547  }  }
548    
549    void
550    xkeymap_send_keys(uint32 keysym, unsigned int keycode, unsigned int state, uint32 ev_time,
551                      BOOL pressed)
552    {
553            key_translation tr, *ptr;
554            tr = xkeymap_translate_key(keysym, keycode, state);
555    
556            if (tr.seq_keysym == 0)
557            {
558                    /* Scancode translation */
559                    if (tr.scancode == 0)
560                            return;
561    
562                    if (pressed)
563                    {
564                            save_remote_modifiers(tr.scancode);
565                            ensure_remote_modifiers(ev_time, tr);
566                            rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
567                            restore_remote_modifiers(ev_time, tr.scancode);
568                    }
569                    else
570                    {
571                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
572                    }
573                    return;
574            }
575    
576            /* Sequence, only on key down */
577            if (pressed)
578            {
579                    ptr = &tr;
580                    do
581                    {
582                            DEBUG_KBD(("Handling sequence element, keysym=0x%x\n",
583                                       (unsigned int) ptr->seq_keysym));
584                            xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, True);
585                            xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, False);
586                            ptr = ptr->next;
587                    }
588                    while (ptr);
589            }
590    }
591    
592  uint16  uint16
593  xkeymap_translate_button(unsigned int button)  xkeymap_translate_button(unsigned int button)
594  {  {
# Line 263  xkeymap_translate_button(unsigned int bu Line 610  xkeymap_translate_button(unsigned int bu
610  }  }
611    
612  char *  char *
613  get_ksname(KeySym keysym)  get_ksname(uint32 keysym)
614  {  {
615          char *ksname = NULL;          char *ksname = NULL;
616    
# Line 275  get_ksname(KeySym keysym) Line 622  get_ksname(KeySym keysym)
622          return ksname;          return ksname;
623  }  }
624    
625  BOOL  static BOOL
626  inhibit_key(KeySym keysym)  is_modifier(uint8 scancode)
627  {  {
628          switch (keysym)          switch (scancode)
629          {          {
630                  case XK_Caps_Lock:                  case SCANCODE_CHAR_LSHIFT:
631                          return True;                  case SCANCODE_CHAR_RSHIFT:
632                          break;                  case SCANCODE_CHAR_LCTRL:
633                  case XK_Multi_key:                  case SCANCODE_CHAR_RCTRL:
634                    case SCANCODE_CHAR_LALT:
635                    case SCANCODE_CHAR_RALT:
636                    case SCANCODE_CHAR_LWIN:
637                    case SCANCODE_CHAR_RWIN:
638                    case SCANCODE_CHAR_NUMLOCK:
639                          return True;                          return True;
                         break;  
640                  default:                  default:
641                          break;                          break;
642          }          }
# Line 293  inhibit_key(KeySym keysym) Line 644  inhibit_key(KeySym keysym)
644  }  }
645    
646  void  void
647    save_remote_modifiers(uint8 scancode)
648    {
649            if (is_modifier(scancode))
650                    return;
651    
652            saved_remote_modifier_state = remote_modifier_state;
653    }
654    
655    void
656    restore_remote_modifiers(uint32 ev_time, uint8 scancode)
657    {
658            key_translation dummy;
659    
660            if (is_modifier(scancode))
661                    return;
662    
663            dummy.scancode = 0;
664            dummy.modifiers = saved_remote_modifier_state;
665            ensure_remote_modifiers(ev_time, dummy);
666    }
667    
668    void
669  ensure_remote_modifiers(uint32 ev_time, key_translation tr)  ensure_remote_modifiers(uint32 ev_time, key_translation tr)
670  {  {
671          /* If this key is a modifier, do nothing */          /* If this key is a modifier, do nothing */
672          switch (tr.scancode)          if (is_modifier(tr.scancode))
673                    return;
674    
675            if (!g_numlock_sync)
676          {          {
677                  case SCANCODE_CHAR_LSHIFT:                  /* NumLock */
678                  case SCANCODE_CHAR_RSHIFT:                  if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)
679                  case SCANCODE_CHAR_LCTRL:                      != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask))
680                  case SCANCODE_CHAR_RCTRL:                  {
681                  case SCANCODE_CHAR_LALT:                          /* The remote modifier state is not correct */
682                  case SCANCODE_CHAR_RALT:                          uint16 new_remote_state;
683                  case SCANCODE_CHAR_LWIN:  
684                  case SCANCODE_CHAR_RWIN:                          if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask))
685                  case SCANCODE_CHAR_NUMLOCK:                          {
686                          return;                                  DEBUG_KBD(("Remote NumLock state is incorrect, activating NumLock.\n"));
687                  default:                                  new_remote_state = KBD_FLAG_NUMLOCK;
688                          break;                                  remote_modifier_state = MapNumLockMask;
689                            }
690                            else
691                            {
692                                    DEBUG_KBD(("Remote NumLock state is incorrect, deactivating NumLock.\n"));
693                                    new_remote_state = 0;
694                                    remote_modifier_state = 0;
695                            }
696    
697                            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0);
698                    }
699          }          }
700    
701          /* Shift */  
702            /* Shift. Left shift and right shift are treated as equal; either is fine. */
703          if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)          if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
704              != MASK_HAS_BITS(remote_modifier_state, MapShiftMask))              != MASK_HAS_BITS(remote_modifier_state, MapShiftMask))
705          {          {
706                  /* The remote modifier state is not correct */                  /* The remote modifier state is not correct */
707                  if (MASK_HAS_BITS(tr.modifiers, MapShiftMask))                  if (MASK_HAS_BITS(tr.modifiers, MapLeftShiftMask))
708                  {                  {
709                          /* Needs this modifier. Send down. */                          /* Needs left shift. Send down. */
710                          rdp_send_scancode(ev_time, RDP_KEYPRESS,                          rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LSHIFT);
711                                            SCANCODE_CHAR_LSHIFT);                  }
712                    else if (MASK_HAS_BITS(tr.modifiers, MapRightShiftMask))
713                    {
714                            /* Needs right shift. Send down. */
715                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RSHIFT);
716                  }                  }
717                  else                  else
718                  {                  {
719                          /* Should not use this modifier. Send up. */                          /* Should not use this modifier. Send up for shift currently pressed. */
720                          rdp_send_scancode(ev_time, RDP_KEYRELEASE,                          if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask))
721                                            SCANCODE_CHAR_LSHIFT);                                  /* Left shift is down */
722                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
723                            else
724                                    /* Right shift is down */
725                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
726                  }                  }
727          }          }
728    
# Line 339  ensure_remote_modifiers(uint32 ev_time, Line 734  ensure_remote_modifiers(uint32 ev_time,
734                  if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask))                  if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask))
735                  {                  {
736                          /* Needs this modifier. Send down. */                          /* Needs this modifier. Send down. */
737                          rdp_send_scancode(ev_time, RDP_KEYPRESS,                          rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RALT);
                                           SCANCODE_CHAR_RALT);  
738                  }                  }
739                  else                  else
740                  {                  {
741                          /* Should not use this modifier. Send up. */                          /* Should not use this modifier. Send up. */
742                          rdp_send_scancode(ev_time, RDP_KEYRELEASE,                          rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
                                           SCANCODE_CHAR_RALT);  
743                  }                  }
744          }          }
745    
         /* NumLock */  
         if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)  
             != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask))  
         {  
                 /* The remote modifier state is not correct */  
                 DEBUG_KBD("Remote NumLock state is incorrect. Toggling\n");  
                 if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask))  
                 {  
                         /* Needs this modifier. Toggle */  
                         rdp_send_scancode(ev_time, RDP_KEYPRESS,  
                                           SCANCODE_CHAR_NUMLOCK);  
                         rdp_send_scancode(ev_time, RDP_KEYRELEASE,  
                                           SCANCODE_CHAR_NUMLOCK);  
                 }  
                 else  
                 {  
                         /* Should not use this modifier. Toggle */  
                         rdp_send_scancode(ev_time, RDP_KEYPRESS,  
                                           SCANCODE_CHAR_NUMLOCK);  
                         rdp_send_scancode(ev_time, RDP_KEYRELEASE,  
                                           SCANCODE_CHAR_NUMLOCK);  
                 }  
         }  
746    
747  }  }
748    
749    
750    unsigned int
751    read_keyboard_state()
752    {
753    #ifdef RDP2VNC
754            return 0;
755    #else
756            unsigned int state;
757            Window wdummy;
758            int dummy;
759    
760            XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
761            return state;
762    #endif
763    }
764    
765    
766    uint16
767    ui_get_numlock_state(unsigned int state)
768    {
769            uint16 numlock_state = 0;
770    
771            if (get_key_state(state, XK_Num_Lock))
772                    numlock_state = KBD_FLAG_NUMLOCK;
773    
774            return numlock_state;
775    }
776    
777    
778    void
779    reset_modifier_keys()
780    {
781            unsigned int state = read_keyboard_state();
782    
783            /* reset keys */
784            uint32 ev_time;
785            ev_time = time(NULL);
786    
787            if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask)
788                && !get_key_state(state, XK_Shift_L))
789                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
790    
791            if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask)
792                && !get_key_state(state, XK_Shift_R))
793                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
794    
795            if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask)
796                && !get_key_state(state, XK_Control_L))
797                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
798    
799            if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask)
800                && !get_key_state(state, XK_Control_R))
801                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
802    
803            if (MASK_HAS_BITS(remote_modifier_state, MapLeftAltMask) && !get_key_state(state, XK_Alt_L))
804                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
805    
806            if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) &&
807                !get_key_state(state, XK_Alt_R) && !get_key_state(state, XK_Mode_switch)
808                && !get_key_state(state, XK_ISO_Level3_Shift))
809                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
810    
811            reset_winkey(ev_time);
812    
813            if (g_numlock_sync)
814                    rdp_send_input(ev_time, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(state), 0);
815    }
816    
817    
818  static void  static void
819  update_modifier_state(uint16 modifiers, BOOL pressed)  update_modifier_state(uint8 scancode, BOOL pressed)
820  {  {
821    #ifdef WITH_DEBUG_KBD
822            uint16 old_modifier_state;
823    
824            old_modifier_state = remote_modifier_state;
825    #endif
826    
827          DEBUG_KBD("Before updating modifier_state:0x%x, pressed=0x%x\n",          switch (scancode)
                   remote_modifier_state, pressed);  
         switch (modifiers)  
828          {          {
829                  case SCANCODE_CHAR_LSHIFT:                  case SCANCODE_CHAR_LSHIFT:
830                          MASK_CHANGE_BIT(remote_modifier_state,                          MASK_CHANGE_BIT(remote_modifier_state, MapLeftShiftMask, pressed);
                                         MapLeftShiftMask, pressed);  
831                          break;                          break;
832                  case SCANCODE_CHAR_RSHIFT:                  case SCANCODE_CHAR_RSHIFT:
833                          MASK_CHANGE_BIT(remote_modifier_state,                          MASK_CHANGE_BIT(remote_modifier_state, MapRightShiftMask, pressed);
                                         MapRightShiftMask, pressed);  
834                          break;                          break;
835                  case SCANCODE_CHAR_LCTRL:                  case SCANCODE_CHAR_LCTRL:
836                          MASK_CHANGE_BIT(remote_modifier_state,                          MASK_CHANGE_BIT(remote_modifier_state, MapLeftCtrlMask, pressed);
                                         MapLeftCtrlMask, pressed);  
837                          break;                          break;
838                  case SCANCODE_CHAR_RCTRL:                  case SCANCODE_CHAR_RCTRL:
839                          MASK_CHANGE_BIT(remote_modifier_state,                          MASK_CHANGE_BIT(remote_modifier_state, MapRightCtrlMask, pressed);
                                         MapRightCtrlMask, pressed);  
840                          break;                          break;
841                  case SCANCODE_CHAR_LALT:                  case SCANCODE_CHAR_LALT:
842                          MASK_CHANGE_BIT(remote_modifier_state, MapLeftAltMask,                          MASK_CHANGE_BIT(remote_modifier_state, MapLeftAltMask, pressed);
                                         pressed);  
843                          break;                          break;
844                  case SCANCODE_CHAR_RALT:                  case SCANCODE_CHAR_RALT:
845                          MASK_CHANGE_BIT(remote_modifier_state,                          MASK_CHANGE_BIT(remote_modifier_state, MapRightAltMask, pressed);
                                         MapRightAltMask, pressed);  
846                          break;                          break;
847                  case SCANCODE_CHAR_LWIN:                  case SCANCODE_CHAR_LWIN:
848                          MASK_CHANGE_BIT(remote_modifier_state, MapLeftWinMask,                          MASK_CHANGE_BIT(remote_modifier_state, MapLeftWinMask, pressed);
                                         pressed);  
849                          break;                          break;
850                  case SCANCODE_CHAR_RWIN:                  case SCANCODE_CHAR_RWIN:
851                          MASK_CHANGE_BIT(remote_modifier_state,                          MASK_CHANGE_BIT(remote_modifier_state, MapRightWinMask, pressed);
                                         MapRightWinMask, pressed);  
852                          break;                          break;
853                  case SCANCODE_CHAR_NUMLOCK:                  case SCANCODE_CHAR_NUMLOCK:
854                          /* KeyReleases for NumLocks are sent immediately. Toggle the                          /* KeyReleases for NumLocks are sent immediately. Toggle the
855                             modifier state only on Keypress */                             modifier state only on Keypress */
856                          if (pressed)                          if (pressed && !g_numlock_sync)
857                          {                          {
858                                  BOOL newNumLockState;                                  BOOL newNumLockState;
859                                  newNumLockState =                                  newNumLockState =
860                                          (MASK_HAS_BITS                                          (MASK_HAS_BITS
861                                           (remote_modifier_state,                                           (remote_modifier_state, MapNumLockMask) == False);
                                           MapNumLockMask) == False);  
862                                  MASK_CHANGE_BIT(remote_modifier_state,                                  MASK_CHANGE_BIT(remote_modifier_state,
863                                                  MapNumLockMask,                                                  MapNumLockMask, newNumLockState);
                                                 newNumLockState);  
864                          }                          }
                         break;  
865          }          }
866          DEBUG_KBD("After updating modifier_state:0x%x\n",  
867                    remote_modifier_state);  #ifdef WITH_DEBUG_KBD
868            if (old_modifier_state != remote_modifier_state)
869            {
870                    DEBUG_KBD(("Before updating modifier_state:0x%x, pressed=0x%x\n",
871                               old_modifier_state, pressed));
872                    DEBUG_KBD(("After updating modifier_state:0x%x\n", remote_modifier_state));
873            }
874    #endif
875    
876  }  }
877    
878  /* Send keyboard input */  /* Send keyboard input */
879  void  void
880  rdp_send_scancode(uint32 time, uint16 flags, uint16 scancode)  rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode)
881  {  {
882          update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));          update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));
883    
884          if (scancode & SCANCODE_EXTENDED)          if (scancode & SCANCODE_EXTENDED)
885          {          {
886                  DEBUG_KBD("Sending extended scancode=0x%x, flags=0x%x\n",                  DEBUG_KBD(("Sending extended scancode=0x%x, flags=0x%x\n",
887                            scancode & ~SCANCODE_EXTENDED, flags);                             scancode & ~SCANCODE_EXTENDED, flags));
888                  rdp_send_input(time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,                  rdp_send_input(time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,
889                                 scancode & ~SCANCODE_EXTENDED, 0);                                 scancode & ~SCANCODE_EXTENDED, 0);
890          }          }
891          else          else
892          {          {
893                  DEBUG_KBD("Sending scancode=0x%x, flags=0x%x\n", scancode,                  DEBUG_KBD(("Sending scancode=0x%x, flags=0x%x\n", scancode, flags));
                           flags);  
894                  rdp_send_input(time, RDP_INPUT_SCANCODE, flags, scancode, 0);                  rdp_send_input(time, RDP_INPUT_SCANCODE, flags, scancode, 0);
895          }          }
896  }  }

Legend:
Removed from v.67  
changed lines
  Added in v.951

  ViewVC Help
Powered by ViewVC 1.1.26