/[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 955 by astrand, Wed Aug 3 07:08:17 2005 UTC revision 1372 by jsorg71, Mon Jan 8 04:47:06 2007 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
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    
5     Copyright (C) Matthew Chapman 1999-2005     Copyright (C) Matthew Chapman 1999-2007
6     Copyright (C) Peter Astrand <peter@cendio.se> 2003     Copyright (C) Peter Astrand <peter@cendio.se> 2003-2007
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
10     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.     (at your option) any later version.
12      
13     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
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
# Line 30  Line 30 
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 39  Line 40 
40    
41  extern Display *g_display;  extern Display *g_display;
42  extern Window g_wnd;  extern Window g_wnd;
43  extern char keymapname[16];  extern char g_keymapname[16];
44  extern int g_keylayout;  extern unsigned int g_keylayout;
45    extern int g_keyboard_type;
46    extern int g_keyboard_subtype;
47    extern int g_keyboard_functionkeys;
48  extern int g_win_button_size;  extern int g_win_button_size;
49  extern BOOL g_enable_compose;  extern RD_BOOL g_enable_compose;
50  extern BOOL g_use_rdp5;  extern RD_BOOL g_use_rdp5;
51  extern BOOL g_numlock_sync;  extern RD_BOOL g_numlock_sync;
52    
53  static BOOL keymap_loaded;  static RD_BOOL keymap_loaded;
54  static key_translation *keymap[KEYMAP_SIZE];  static key_translation *keymap[KEYMAP_SIZE];
55  static int min_keycode;  static int min_keycode;
56  static uint16 remote_modifier_state = 0;  static uint16 remote_modifier_state = 0;
57  static uint16 saved_remote_modifier_state = 0;  static uint16 saved_remote_modifier_state = 0;
58    
59  static void update_modifier_state(uint8 scancode, BOOL pressed);  static void update_modifier_state(uint8 scancode, RD_BOOL pressed);
60    
61  /* Free key_translation structure, included linked list */  /* Free key_translation structure, including linked list */
62  static void  static void
63  free_key_translation(key_translation * ptr)  free_key_translation(key_translation * ptr)
64  {  {
# Line 155  add_sequence(char *rest, char *mapname) Line 159  add_sequence(char *rest, char *mapname)
159          DEBUG_KBD(("\n"));          DEBUG_KBD(("\n"));
160  }  }
161    
162  static BOOL  RD_BOOL
163    xkeymap_from_locale(const char *locale)
164    {
165            char *str, *ptr;
166            FILE *fp;
167    
168            /* Create a working copy */
169            str = xstrdup(locale);
170    
171            /* Truncate at dot and at */
172            ptr = strrchr(str, '.');
173            if (ptr)
174                    *ptr = '\0';
175            ptr = strrchr(str, '@');
176            if (ptr)
177                    *ptr = '\0';
178    
179            /* Replace _ with - */
180            ptr = strrchr(str, '_');
181            if (ptr)
182                    *ptr = '-';
183    
184            /* Convert to lowercase */
185            ptr = str;
186            while (*ptr)
187            {
188                    *ptr = tolower((int) *ptr);
189                    ptr++;
190            }
191    
192            /* Try to open this keymap (da-dk) */
193            fp = xkeymap_open(str);
194            if (fp == NULL)
195            {
196                    /* Truncate at dash */
197                    ptr = strrchr(str, '-');
198                    if (ptr)
199                            *ptr = '\0';
200    
201                    /* Try the short name (da) */
202                    fp = xkeymap_open(str);
203            }
204    
205            if (fp)
206            {
207                    fclose(fp);
208                    STRNCPY(g_keymapname, str, sizeof(g_keymapname));
209                    xfree(str);
210                    return True;
211            }
212    
213            xfree(str);
214            return False;
215    }
216    
217    
218    /* Joins two path components. The result should be freed with
219       xfree(). */
220    static char *
221    pathjoin(const char *a, const char *b)
222    {
223            char *result;
224            result = xmalloc(PATH_MAX * 2 + 1);
225    
226            if (b[0] == '/')
227            {
228                    strncpy(result, b, PATH_MAX);
229            }
230            else
231            {
232                    strncpy(result, a, PATH_MAX);
233                    strcat(result, "/");
234                    strncat(result, b, PATH_MAX);
235            }
236            return result;
237    }
238    
239    /* Try to open a keymap with fopen() */
240    FILE *
241    xkeymap_open(const char *filename)
242    {
243            char *path1, *path2;
244            char *home;
245            FILE *fp;
246    
247            /* Try ~/.rdesktop/keymaps */
248            home = getenv("HOME");
249            if (home)
250            {
251                    path1 = pathjoin(home, ".rdesktop/keymaps");
252                    path2 = pathjoin(path1, filename);
253                    xfree(path1);
254                    fp = fopen(path2, "r");
255                    xfree(path2);
256                    if (fp)
257                            return fp;
258            }
259    
260            /* Try KEYMAP_PATH */
261            path1 = pathjoin(KEYMAP_PATH, filename);
262            fp = fopen(path1, "r");
263            xfree(path1);
264            if (fp)
265                    return fp;
266    
267            /* Try current directory, in case we are running from the source
268               tree */
269            path1 = pathjoin("keymaps", filename);
270            fp = fopen(path1, "r");
271            xfree(path1);
272            if (fp)
273                    return fp;
274    
275            return NULL;
276    }
277    
278    static RD_BOOL
279  xkeymap_read(char *mapname)  xkeymap_read(char *mapname)
280  {  {
281          FILE *fp;          FILE *fp;
282          char line[KEYMAP_MAX_LINE_LENGTH];          char line[KEYMAP_MAX_LINE_LENGTH];
         char path[PATH_MAX], inplace_path[PATH_MAX];  
283          unsigned int line_num = 0;          unsigned int line_num = 0;
284          unsigned int line_length = 0;          unsigned int line_length = 0;
285          char *keyname, *p;          char *keyname, *p;
# Line 168  xkeymap_read(char *mapname) Line 287  xkeymap_read(char *mapname)
287          uint8 scancode;          uint8 scancode;
288          uint16 modifiers;          uint16 modifiers;
289    
290            fp = xkeymap_open(mapname);
         strcpy(path, KEYMAP_PATH);  
         strncat(path, mapname, sizeof(path) - sizeof(KEYMAP_PATH));  
   
         fp = fopen(path, "r");  
291          if (fp == NULL)          if (fp == NULL)
292          {          {
293                  /* in case we are running from the source tree */                  error("Failed to open keymap %s\n", mapname);
294                  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;  
                 }  
295          }          }
296    
297          /* FIXME: More tolerant on white space */          /* FIXME: More tolerant on white space */
# Line 206  xkeymap_read(char *mapname) Line 313  xkeymap_read(char *mapname)
313                  }                  }
314    
315                  /* Include */                  /* Include */
316                  if (strncmp(line, "include ", 8) == 0)                  if (str_startswith(line, "include "))
317                  {                  {
318                          if (!xkeymap_read(line + 8))                          if (!xkeymap_read(line + sizeof("include ") - 1))
319                                  return False;                                  return False;
320                          continue;                          continue;
321                  }                  }
322    
323                  /* map */                  /* map */
324                  if (strncmp(line, "map ", 4) == 0)                  if (str_startswith(line, "map "))
325                  {                  {
326                          g_keylayout = strtol(line + 4, NULL, 16);                          g_keylayout = strtoul(line + sizeof("map ") - 1, NULL, 16);
327                          DEBUG_KBD(("Keylayout 0x%x\n", g_keylayout));                          DEBUG_KBD(("Keylayout 0x%x\n", g_keylayout));
328                          continue;                          continue;
329                  }                  }
330    
331                  /* compose */                  /* compose */
332                  if (strncmp(line, "enable_compose", 15) == 0)                  if (str_startswith(line, "enable_compose"))
333                  {                  {
334                          DEBUG_KBD(("Enabling compose handling\n"));                          DEBUG_KBD(("Enabling compose handling\n"));
335                          g_enable_compose = True;                          g_enable_compose = True;
# Line 230  xkeymap_read(char *mapname) Line 337  xkeymap_read(char *mapname)
337                  }                  }
338    
339                  /* sequence */                  /* sequence */
340                  if (strncmp(line, "sequence", 8) == 0)                  if (str_startswith(line, "sequence"))
341                    {
342                            add_sequence(line + sizeof("sequence") - 1, mapname);
343                            continue;
344                    }
345    
346                    /* keyboard_type */
347                    if (str_startswith(line, "keyboard_type "))
348                  {                  {
349                          add_sequence(line + 8, mapname);                          g_keyboard_type = strtol(line + sizeof("keyboard_type ") - 1, NULL, 16);
350                            DEBUG_KBD(("keyboard_type 0x%x\n", g_keyboard_type));
351                            continue;
352                    }
353    
354                    /* keyboard_subtype */
355                    if (str_startswith(line, "keyboard_subtype "))
356                    {
357                            g_keyboard_subtype =
358                                    strtol(line + sizeof("keyboard_subtype ") - 1, NULL, 16);
359                            DEBUG_KBD(("keyboard_subtype 0x%x\n", g_keyboard_subtype));
360                            continue;
361                    }
362    
363                    /* keyboard_functionkeys */
364                    if (str_startswith(line, "keyboard_functionkeys "))
365                    {
366                            g_keyboard_functionkeys =
367                                    strtol(line + sizeof("keyboard_functionkeys ") - 1, NULL, 16);
368                            DEBUG_KBD(("keyboard_functionkeys 0x%x\n", g_keyboard_functionkeys));
369                          continue;                          continue;
370                  }                  }
371    
# Line 311  void Line 444  void
444  xkeymap_init(void)  xkeymap_init(void)
445  {  {
446          unsigned int max_keycode;          unsigned int max_keycode;
         char *mapname_ptr;  
   
         /* Make keymapname lowercase */  
         mapname_ptr = keymapname;  
         while (*mapname_ptr)  
         {  
                 *mapname_ptr = tolower((int) *mapname_ptr);  
                 mapname_ptr++;  
         }  
447    
448          if (strcmp(keymapname, "none"))          if (strcmp(g_keymapname, "none"))
449          {          {
450                  if (xkeymap_read(keymapname))                  if (xkeymap_read(g_keymapname))
451                          keymap_loaded = True;                          keymap_loaded = True;
452          }          }
453    
# Line 331  xkeymap_init(void) Line 455  xkeymap_init(void)
455  }  }
456    
457  static void  static void
458  send_winkey(uint32 ev_time, BOOL pressed, BOOL leftkey)  send_winkey(uint32 ev_time, RD_BOOL pressed, RD_BOOL leftkey)
459  {  {
460          uint8 winkey;          uint8 winkey;
461    
# Line 380  reset_winkey(uint32 ev_time) Line 504  reset_winkey(uint32 ev_time)
504  }  }
505    
506  /* Handle special key combinations */  /* Handle special key combinations */
507  BOOL  RD_BOOL
508  handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)  handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, RD_BOOL pressed)
509  {  {
510          switch (keysym)          switch (keysym)
511          {          {
# Line 467  handle_special_keys(uint32 keysym, unsig Line 591  handle_special_keys(uint32 keysym, unsig
591                          /* Inhibit */                          /* Inhibit */
592                          return True;                          return True;
593                          break;                          break;
594                    case XK_Overlay1_Enable:
595                            /* Toggle SeamlessRDP */
596                            if (pressed)
597                                    ui_seamless_toggle();
598                            break;
599    
600          }          }
601          return False;          return False;
# Line 485  xkeymap_translate_key(uint32 keysym, uns Line 614  xkeymap_translate_key(uint32 keysym, uns
614                  tr = *ptr;                  tr = *ptr;
615                  if (tr.seq_keysym == 0) /* Normal scancode translation */                  if (tr.seq_keysym == 0) /* Normal scancode translation */
616                  {                  {
617                          if (tr.modifiers & MapInhibitMask)                          if (MASK_HAS_BITS(tr.modifiers, MapInhibitMask))
618                          {                          {
619                                  DEBUG_KBD(("Inhibiting key\n"));                                  DEBUG_KBD(("Inhibiting key\n"));
620                                  tr.scancode = 0;                                  tr.scancode = 0;
621                                  return tr;                                  return tr;
622                          }                          }
623    
624                          if (tr.modifiers & MapLocalStateMask)                          if (MASK_HAS_BITS(tr.modifiers, MapLocalStateMask))
625                          {                          {
626                                  /* The modifiers to send for this key should be obtained                                  /* The modifiers to send for this key should be obtained
627                                     from the local state. Currently, only shift is implemented. */                                     from the local state. Currently, only shift is implemented. */
628                                  if (state & ShiftMask)                                  if (MASK_HAS_BITS(state, ShiftMask))
629                                  {                                  {
630                                          tr.modifiers = MapLeftShiftMask;                                          tr.modifiers = MapLeftShiftMask;
631                                  }                                  }
632                          }                          }
633    
634                          if ((tr.modifiers & MapLeftShiftMask)                          /* Windows interprets CapsLock+Ctrl+key
635                              && ((remote_modifier_state & MapLeftCtrlMask)                             differently from Shift+Ctrl+key. Since we
636                                  || (remote_modifier_state & MapRightCtrlMask))                             are simulating CapsLock with Shifts, things
637                              && get_key_state(state, XK_Caps_Lock))                             like Ctrl+f with CapsLock on breaks. To
638                               solve this, we are releasing Shift if Ctrl
639                               is on, but only if Shift isn't physically pressed. */
640                            if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
641                                && MASK_HAS_BITS(remote_modifier_state, MapCtrlMask)
642                                && !MASK_HAS_BITS(state, ShiftMask))
643                          {                          {
644                                  DEBUG_KBD(("CapsLock + Ctrl pressed, releasing LeftShift\n"));                                  DEBUG_KBD(("Non-physical Shift + Ctrl pressed, releasing Shift\n"));
645                                  tr.modifiers ^= MapLeftShiftMask;                                  MASK_REMOVE_BITS(tr.modifiers, MapShiftMask);
646                          }                          }
647    
648                          DEBUG_KBD(("Found scancode translation, scancode=0x%x, modifiers=0x%x\n",                          DEBUG_KBD(("Found scancode translation, scancode=0x%x, modifiers=0x%x\n",
# Line 529  xkeymap_translate_key(uint32 keysym, uns Line 663  xkeymap_translate_key(uint32 keysym, uns
663                          /* The modifiers to send for this key should be                          /* The modifiers to send for this key should be
664                             obtained from the local state. Currently, only                             obtained from the local state. Currently, only
665                             shift is implemented. */                             shift is implemented. */
666                          if (state & ShiftMask)                          if (MASK_HAS_BITS(state, ShiftMask))
667                          {                          {
668                                  tr.modifiers = MapLeftShiftMask;                                  tr.modifiers = MapLeftShiftMask;
669                          }                          }
# Line 547  xkeymap_translate_key(uint32 keysym, uns Line 681  xkeymap_translate_key(uint32 keysym, uns
681    
682  void  void
683  xkeymap_send_keys(uint32 keysym, unsigned int keycode, unsigned int state, uint32 ev_time,  xkeymap_send_keys(uint32 keysym, unsigned int keycode, unsigned int state, uint32 ev_time,
684                    BOOL pressed)                    RD_BOOL pressed, uint8 nesting)
685  {  {
686          key_translation tr, *ptr;          key_translation tr, *ptr;
687          tr = xkeymap_translate_key(keysym, keycode, state);          tr = xkeymap_translate_key(keysym, keycode, state);
# Line 580  xkeymap_send_keys(uint32 keysym, unsigne Line 714  xkeymap_send_keys(uint32 keysym, unsigne
714                  {                  {
715                          DEBUG_KBD(("Handling sequence element, keysym=0x%x\n",                          DEBUG_KBD(("Handling sequence element, keysym=0x%x\n",
716                                     (unsigned int) ptr->seq_keysym));                                     (unsigned int) ptr->seq_keysym));
717                          xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, True);  
718                          xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, False);                          if (nesting++ > 32)
719                            {
720                                    error("Sequence nesting too deep\n");
721                                    return;
722                            }
723    
724                            xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, True, nesting);
725                            xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, False, nesting);
726                          ptr = ptr->next;                          ptr = ptr->next;
727                  }                  }
728                  while (ptr);                  while (ptr);
# Line 621  get_ksname(uint32 keysym) Line 762  get_ksname(uint32 keysym)
762          return ksname;          return ksname;
763  }  }
764    
765  static BOOL  static RD_BOOL
766  is_modifier(uint8 scancode)  is_modifier(uint8 scancode)
767  {  {
768          switch (scancode)          switch (scancode)
# Line 815  reset_modifier_keys() Line 956  reset_modifier_keys()
956    
957    
958  static void  static void
959  update_modifier_state(uint8 scancode, BOOL pressed)  update_modifier_state(uint8 scancode, RD_BOOL pressed)
960  {  {
961  #ifdef WITH_DEBUG_KBD  #ifdef WITH_DEBUG_KBD
962          uint16 old_modifier_state;          uint16 old_modifier_state;
# Line 854  update_modifier_state(uint8 scancode, BO Line 995  update_modifier_state(uint8 scancode, BO
995                             modifier state only on Keypress */                             modifier state only on Keypress */
996                          if (pressed && !g_numlock_sync)                          if (pressed && !g_numlock_sync)
997                          {                          {
998                                  BOOL newNumLockState;                                  RD_BOOL newNumLockState;
999                                  newNumLockState =                                  newNumLockState =
1000                                          (MASK_HAS_BITS                                          (MASK_HAS_BITS
1001                                           (remote_modifier_state, MapNumLockMask) == False);                                           (remote_modifier_state, MapNumLockMask) == False);

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

  ViewVC Help
Powered by ViewVC 1.1.26