/[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 50 by matthewc, Sat Apr 20 09:41:03 2002 UTC revision 111 by astrand, Sun Sep 1 12:03:33 2002 UTC
# Line 23  Line 23 
23  #include <stdio.h>  #include <stdio.h>
24  #include <stdlib.h>  #include <stdlib.h>
25  #include <string.h>  #include <string.h>
26    #include <ctype.h>
27  #include <limits.h>  #include <limits.h>
28  #include "rdesktop.h"  #include "rdesktop.h"
29    #include "scancodes.h"
30    
31  #define KEYMAP_SIZE 4096  #define KEYMAP_SIZE 4096
32  #define KEYMAP_MASK (KEYMAP_SIZE - 1)  #define KEYMAP_MASK (KEYMAP_SIZE - 1)
33    #define KEYMAP_MAX_LINE_LENGTH 80
34    
35  extern Display *display;  extern Display *display;
36  extern char keymapname[16];  extern char keymapname[16];
37  extern int keylayout;  extern int keylayout;
38    extern BOOL enable_compose;
39    
40  static uint8 keymap[KEYMAP_SIZE];  static key_translation keymap[KEYMAP_SIZE];
41  static unsigned int min_keycode;  static int min_keycode;
42    static uint16 remote_modifier_state = 0;
43    
44  static BOOL xkeymap_read(char *mapname)  static void
45    add_to_keymap(char *keyname, uint8 scancode, uint16 modifiers, char *mapname)
46    {
47            KeySym keysym;
48    
49            keysym = XStringToKeysym(keyname);
50            if (keysym == NoSymbol)
51            {
52                    error("Bad keysym %s in keymap %s\n", keyname, mapname);
53                    return;
54            }
55    
56            DEBUG_KBD(("Adding translation, keysym=0x%x, scancode=0x%x, "
57                       "modifiers=0x%x\n", (unsigned int) keysym, scancode, modifiers));
58    
59            keymap[keysym & KEYMAP_MASK].scancode = scancode;
60            keymap[keysym & KEYMAP_MASK].modifiers = modifiers;
61    
62            return;
63    }
64    
65    
66    static BOOL
67    xkeymap_read(char *mapname)
68  {  {
69          FILE *fp;          FILE *fp;
70          char line[PATH_MAX], path[PATH_MAX];          char line[KEYMAP_MAX_LINE_LENGTH], path[PATH_MAX];
71            unsigned int line_num = 0;
72            unsigned int line_length = 0;
73          char *keyname, *p;          char *keyname, *p;
74          KeySym keysym;          char *line_rest;
75          unsigned char keycode;          uint8 scancode;
76            uint16 modifiers;
77    
78    
79          strcpy(path, KEYMAP_PATH);          strcpy(path, KEYMAP_PATH);
80          strncat(path, mapname, sizeof(path) - sizeof(KEYMAP_PATH));          strncat(path, mapname, sizeof(path) - sizeof(KEYMAP_PATH));
# Line 54  static BOOL xkeymap_read(char *mapname) Line 86  static BOOL xkeymap_read(char *mapname)
86                  return False;                  return False;
87          }          }
88    
89            /* FIXME: More tolerant on white space */
90          while (fgets(line, sizeof(line), fp) != NULL)          while (fgets(line, sizeof(line), fp) != NULL)
91          {          {
92                    line_num++;
93    
94                    /* Replace the \n with \0 */
95                  p = strchr(line, '\n');                  p = strchr(line, '\n');
96                  if (p != NULL)                  if (p != NULL)
97                          *p = 0;                          *p = 0;
98    
99                  keycode = strtol(line, &keyname, 16);                  line_length = strlen(line);
100                  if ((keycode != 0) && (*keyname == ' '))  
101                    /* Completely empty line */
102                    if (strspn(line, " \t\n\r\f\v") == line_length)
103                  {                  {
104                          do                          continue;
105                          {                  }
                                 keyname++;  
                                 p = strchr(keyname, ' ');  
                                 if (p != NULL)  
                                         *p = 0;  
106    
107                                  keysym = XStringToKeysym(keyname);                  /* Include */
108                                  if (keysym == NoSymbol)                  if (strncmp(line, "include ", 8) == 0)
109                                          error("Bad keysym %s in keymap %s\n", keyname, mapname);                  {
110                            if (!xkeymap_read(line + 8))
111                                    return False;
112                            continue;
113                    }
114    
115                                  keymap[keysym & KEYMAP_MASK] = keycode;                  /* map */
116                                  keyname = p;                  if (strncmp(line, "map ", 4) == 0)
117                    {
118                            keylayout = strtol(line + 4, NULL, 16);
119                            DEBUG_KBD(("Keylayout 0x%x\n", keylayout));
120                            continue;
121                    }
122    
123                          } while (keyname != NULL);                  /* compose */
124                    if (strncmp(line, "enable_compose", 15) == 0)
125                    {
126                            DEBUG_KBD(("Enabling compose handling\n"));
127                            enable_compose = True;
128                            continue;
129                  }                  }
130                  else if (strncmp(line, "include ", 8) == 0)  
131                    /* Comment */
132                    if (line[0] == '#')
133                  {                  {
134                          if (!xkeymap_read(line+8))                          continue;
135                                  return False;                  }
136    
137                    /* Normal line */
138                    keyname = line;
139                    p = strchr(line, ' ');
140                    if (p == NULL)
141                    {
142                            error("Bad line %d in keymap %s\n", line_num, mapname);
143                            continue;
144                    }
145                    else
146                    {
147                            *p = 0;
148                    }
149    
150                    /* scancode */
151                    p++;
152                    scancode = strtol(p, &line_rest, 16);
153    
154                    /* flags */
155                    /* FIXME: Should allow case-insensitive flag names.
156                       Fix by using lex+yacc... */
157                    modifiers = 0;
158                    if (strstr(line_rest, "altgr"))
159                    {
160                            MASK_ADD_BITS(modifiers, MapAltGrMask);
161                    }
162    
163                    if (strstr(line_rest, "shift"))
164                    {
165                            MASK_ADD_BITS(modifiers, MapLeftShiftMask);
166                    }
167    
168                    if (strstr(line_rest, "numlock"))
169                    {
170                            MASK_ADD_BITS(modifiers, MapNumLockMask);
171                  }                  }
172                  else if (strncmp(line, "map ", 4) == 0)  
173                    if (strstr(line_rest, "localstate"))
174                  {                  {
175                          keylayout = strtol(line+4, NULL, 16);                          MASK_ADD_BITS(modifiers, MapLocalStateMask);
176                  }                  }
177                  else if (line[0] != '#')  
178                    add_to_keymap(keyname, scancode, modifiers, mapname);
179    
180                    if (strstr(line_rest, "addupper"))
181                  {                  {
182                          error("Malformed line in keymap %s\n", mapname);                          /* Automatically add uppercase key, with same modifiers
183                               plus shift */
184                            for (p = keyname; *p; p++)
185                                    *p = toupper(*p);
186                            MASK_ADD_BITS(modifiers, MapLeftShiftMask);
187                            add_to_keymap(keyname, scancode, modifiers, mapname);
188                  }                  }
189          }          }
190    
# Line 98  static BOOL xkeymap_read(char *mapname) Line 192  static BOOL xkeymap_read(char *mapname)
192          return True;          return True;
193  }  }
194    
195  void xkeymap_init(void)  
196    /* Before connecting and creating UI */
197    void
198    xkeymap_init1(void)
199  {  {
200          unsigned int max_keycode;          int i;
201    
202          XDisplayKeycodes(display, &min_keycode, &max_keycode);          /* Zeroing keymap */
203            for (i = 0; i < KEYMAP_SIZE; i++)
204            {
205                    keymap[i].scancode = 0;
206                    keymap[i].modifiers = 0;
207            }
208    
209          if (strcmp(keymapname, "none"))          if (strcmp(keymapname, "none"))
210            {
211                  xkeymap_read(keymapname);                  xkeymap_read(keymapname);
212            }
213    
214  }  }
215    
216  uint8 xkeymap_translate_key(unsigned int keysym, unsigned int keycode, uint16 *flags)  /* After connecting and creating UI */
217    void
218    xkeymap_init2(void)
219  {  {
220          uint8 scancode;          unsigned int max_keycode;
221            XDisplayKeycodes(display, &min_keycode, (int *) &max_keycode);
222    }
223    
224    
225          scancode = keymap[keysym & KEYMAP_MASK];  key_translation
226          if (scancode != 0)  xkeymap_translate_key(KeySym keysym, unsigned int keycode, unsigned int state)
227    {
228            key_translation tr = { 0, 0 };
229    
230            tr = keymap[keysym & KEYMAP_MASK];
231    
232            if (tr.modifiers & MapLocalStateMask)
233          {          {
234                  if (scancode & 0x80)                  /* The modifiers to send for this key should be obtained
235                          *flags |= KBD_FLAG_EXT;                     from the local state. Currently, only shift is implemented. */
236                    if (state & ShiftMask)
237                    {
238                            tr.modifiers = MapLeftShiftMask;
239                    }
240            }
241    
242                  return (scancode & 0x7f);          if (tr.scancode != 0)
243            {
244                    DEBUG_KBD
245                            (("Found key translation, scancode=0x%x, modifiers=0x%x\n",
246                              tr.scancode, tr.modifiers));
247                    return tr;
248          }          }
249    
250          /* not in keymap, try to interpret the raw scancode */          fprintf(stderr, "No translation for (keysym 0x%lx, %s)\n", keysym, get_ksname(keysym));
251    
252            /* not in keymap, try to interpret the raw scancode */
253          if ((keycode >= min_keycode) && (keycode <= 0x60))          if ((keycode >= min_keycode) && (keycode <= 0x60))
                 return (uint8)(keycode - min_keycode);  
   
         *flags |= KBD_FLAG_EXT;  
   
         switch (keycode)  
254          {          {
255                  case 0x61:      /* home */                  tr.scancode = keycode - min_keycode;
256                          return 0x47;                  fprintf(stderr, "Sending guessed scancode 0x%x\n", tr.scancode);
257                  case 0x62:      /* up arrow */          }
258                          return 0x48;          else
259                  case 0x63:      /* page up */          {
260                          return 0x49;                  fprintf(stderr, "No good guess for keycode 0x%x found\n", keycode);
                 case 0x64:      /* left arrow */  
                         return 0x4b;  
                 case 0x66:      /* right arrow */  
                         return 0x4d;  
                 case 0x67:      /* end */  
                         return 0x4f;  
                 case 0x68:      /* down arrow */  
                         return 0x50;  
                 case 0x69:      /* page down */  
                         return 0x51;  
                 case 0x6a:      /* insert */  
                         return 0x52;  
                 case 0x6b:      /* delete */  
                         return 0x53;  
                 case 0x6c:      /* keypad enter */  
                         return 0x1c;  
                 case 0x6d:      /* right ctrl */  
                         return 0x1d;  
                 case 0x6f:      /* ctrl - print screen */  
                         return 0x37;  
                 case 0x70:      /* keypad '/' */  
                         return 0x35;  
                 case 0x71:      /* right alt */  
                         return 0x38;  
                 case 0x72:      /* ctrl break */  
                         return 0x46;  
                 case 0x73:      /* left window key */  
                         return 0x5b;  
                 case 0x74:      /* right window key */  
                         return 0x5c;  
                 case 0x75:      /* menu key */  
                         return 0x5d;  
261          }          }
262    
263          return 0;          return tr;
264  }  }
265    
266  uint16 xkeymap_translate_button(unsigned int button)  uint16
267    xkeymap_translate_button(unsigned int button)
268  {  {
269          switch (button)          switch (button)
270          {          {
271                  case Button1:   /* left */                  case Button1:   /* left */
272                          return MOUSE_FLAG_BUTTON1;                          return MOUSE_FLAG_BUTTON1;
273                  case Button2:   /* middle */                  case Button2:   /* middle */
274                          return MOUSE_FLAG_BUTTON3;                          return MOUSE_FLAG_BUTTON3;
275                  case Button3:   /* right */                  case Button3:   /* right */
276                          return MOUSE_FLAG_BUTTON2;                          return MOUSE_FLAG_BUTTON2;
277                    case Button4:   /* wheel up */
278                            return MOUSE_FLAG_BUTTON4;
279                    case Button5:   /* wheel down */
280                            return MOUSE_FLAG_BUTTON5;
281          }          }
282    
283          return 0;          return 0;
284  }  }
285    
286    char *
287    get_ksname(KeySym keysym)
288    {
289            char *ksname = NULL;
290    
291            if (keysym == NoSymbol)
292                    ksname = "NoSymbol";
293            else if (!(ksname = XKeysymToString(keysym)))
294                    ksname = "(no name)";
295    
296            return ksname;
297    }
298    
299    BOOL
300    inhibit_key(KeySym keysym)
301    {
302            switch (keysym)
303            {
304                    case XK_Caps_Lock:
305                            return True;
306                            break;
307                    case XK_Multi_key:
308                            return True;
309                            break;
310                    default:
311                            break;
312            }
313            return False;
314    }
315    
316    void
317    ensure_remote_modifiers(uint32 ev_time, key_translation tr)
318    {
319            /* If this key is a modifier, do nothing */
320            switch (tr.scancode)
321            {
322                    case SCANCODE_CHAR_LSHIFT:
323                    case SCANCODE_CHAR_RSHIFT:
324                    case SCANCODE_CHAR_LCTRL:
325                    case SCANCODE_CHAR_RCTRL:
326                    case SCANCODE_CHAR_LALT:
327                    case SCANCODE_CHAR_RALT:
328                    case SCANCODE_CHAR_LWIN:
329                    case SCANCODE_CHAR_RWIN:
330                    case SCANCODE_CHAR_NUMLOCK:
331                            return;
332                    default:
333                            break;
334            }
335    
336            /* Shift */
337            if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
338                != MASK_HAS_BITS(remote_modifier_state, MapShiftMask))
339            {
340                    /* The remote modifier state is not correct */
341                    if (MASK_HAS_BITS(tr.modifiers, MapShiftMask))
342                    {
343                            /* Needs this modifier. Send down. */
344                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LSHIFT);
345                    }
346                    else
347                    {
348                            /* Should not use this modifier. Send up. */
349                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
350                    }
351            }
352    
353            /* AltGr */
354            if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask)
355                != MASK_HAS_BITS(remote_modifier_state, MapAltGrMask))
356            {
357                    /* The remote modifier state is not correct */
358                    if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask))
359                    {
360                            /* Needs this modifier. Send down. */
361                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RALT);
362                    }
363                    else
364                    {
365                            /* Should not use this modifier. Send up. */
366                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
367                    }
368            }
369    
370            /* NumLock */
371            if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)
372                != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask))
373            {
374                    /* The remote modifier state is not correct */
375                    DEBUG_KBD(("Remote NumLock state is incorrect. Toggling\n"));
376                    if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask))
377                    {
378                            /* Needs this modifier. Toggle */
379                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_NUMLOCK);
380                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_NUMLOCK);
381                    }
382                    else
383                    {
384                            /* Should not use this modifier. Toggle */
385                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_NUMLOCK);
386                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_NUMLOCK);
387                    }
388            }
389    
390    }
391    
392    
393    static void
394    update_modifier_state(uint16 modifiers, BOOL pressed)
395    {
396    
397            DEBUG_KBD(("Before updating modifier_state:0x%x, pressed=0x%x\n",
398                       remote_modifier_state, pressed));
399            switch (modifiers)
400            {
401                    case SCANCODE_CHAR_LSHIFT:
402                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftShiftMask, pressed);
403                            break;
404                    case SCANCODE_CHAR_RSHIFT:
405                            MASK_CHANGE_BIT(remote_modifier_state, MapRightShiftMask, pressed);
406                            break;
407                    case SCANCODE_CHAR_LCTRL:
408                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftCtrlMask, pressed);
409                            break;
410                    case SCANCODE_CHAR_RCTRL:
411                            MASK_CHANGE_BIT(remote_modifier_state, MapRightCtrlMask, pressed);
412                            break;
413                    case SCANCODE_CHAR_LALT:
414                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftAltMask, pressed);
415                            break;
416                    case SCANCODE_CHAR_RALT:
417                            MASK_CHANGE_BIT(remote_modifier_state, MapRightAltMask, pressed);
418                            break;
419                    case SCANCODE_CHAR_LWIN:
420                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftWinMask, pressed);
421                            break;
422                    case SCANCODE_CHAR_RWIN:
423                            MASK_CHANGE_BIT(remote_modifier_state, MapRightWinMask, pressed);
424                            break;
425                    case SCANCODE_CHAR_NUMLOCK:
426                            /* KeyReleases for NumLocks are sent immediately. Toggle the
427                               modifier state only on Keypress */
428                            if (pressed)
429                            {
430                                    BOOL newNumLockState;
431                                    newNumLockState =
432                                            (MASK_HAS_BITS
433                                             (remote_modifier_state, MapNumLockMask) == False);
434                                    MASK_CHANGE_BIT(remote_modifier_state,
435                                                    MapNumLockMask, newNumLockState);
436                            }
437                            break;
438            }
439            DEBUG_KBD(("After updating modifier_state:0x%x\n", remote_modifier_state));
440    
441    }
442    
443    /* Send keyboard input */
444    void
445    rdp_send_scancode(uint32 time, uint16 flags, uint16 scancode)
446    {
447            update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));
448    
449            if (scancode & SCANCODE_EXTENDED)
450            {
451                    DEBUG_KBD(("Sending extended scancode=0x%x, flags=0x%x\n",
452                               scancode & ~SCANCODE_EXTENDED, flags));
453                    rdp_send_input(time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,
454                                   scancode & ~SCANCODE_EXTENDED, 0);
455            }
456            else
457            {
458                    DEBUG_KBD(("Sending scancode=0x%x, flags=0x%x\n", scancode, flags));
459                    rdp_send_input(time, RDP_INPUT_SCANCODE, flags, scancode, 0);
460            }
461    }

Legend:
Removed from v.50  
changed lines
  Added in v.111

  ViewVC Help
Powered by ViewVC 1.1.26