/[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 39 by matthewc, Fri Apr 5 07:57:43 2002 UTC revision 548 by astrand, Tue Nov 11 14:01:31 2003 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-2002
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>  
30  #include <string.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"
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
39    
40    extern Display *g_display;
41    extern Window g_wnd;
42  extern char keymapname[16];  extern char keymapname[16];
43  extern int keylayout;  extern int keylayout;
44    extern int g_win_button_size;
45    extern BOOL g_enable_compose;
46    extern BOOL g_use_rdp5;
47    
48    static BOOL keymap_loaded;
49    static key_translation keymap[KEYMAP_SIZE];
50    static int min_keycode;
51    static uint16 remote_modifier_state = 0;
52    static uint16 saved_remote_modifier_state = 0;
53    
54    static void update_modifier_state(uint8 scancode, BOOL pressed);
55    
56    static void
57    add_to_keymap(char *keyname, uint8 scancode, uint16 modifiers, char *mapname)
58    {
59            KeySym keysym;
60    
61            keysym = XStringToKeysym(keyname);
62            if (keysym == NoSymbol)
63            {
64                    DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring)\n", keyname, mapname));
65                    return;
66            }
67    
68            DEBUG_KBD(("Adding translation, keysym=0x%x, scancode=0x%x, "
69                       "modifiers=0x%x\n", (unsigned int) keysym, scancode, modifiers));
70    
71  static uint8 keymap[KEYMAP_SIZE];          keymap[keysym & KEYMAP_MASK].scancode = scancode;
72  static unsigned int min_keycode;          keymap[keysym & KEYMAP_MASK].modifiers = modifiers;
73    
74  static BOOL xkeymap_read(char *mapname)          return;
75    }
76    
77    
78    static BOOL
79    xkeymap_read(char *mapname)
80  {  {
81          FILE *fp;          FILE *fp;
82          char line[PATH_MAX], path[PATH_MAX];          char line[KEYMAP_MAX_LINE_LENGTH];
83            char path[PATH_MAX], inplace_path[PATH_MAX];
84            unsigned int line_num = 0;
85            unsigned int line_length = 0;
86          char *keyname, *p;          char *keyname, *p;
87          KeySym keysym;          char *line_rest;
88          unsigned char keycode;          uint8 scancode;
89          unsigned int mapcode = 0;          uint16 modifiers;
90    
91    
92          strcpy(path, KEYMAP_PATH);          strcpy(path, KEYMAP_PATH);
93          strncat(path, mapname, sizeof(path) - sizeof(KEYMAP_PATH));          strncat(path, mapname, sizeof(path) - sizeof(KEYMAP_PATH));
# Line 50  static BOOL xkeymap_read(char *mapname) Line 95  static BOOL xkeymap_read(char *mapname)
95          fp = fopen(path, "r");          fp = fopen(path, "r");
96          if (fp == NULL)          if (fp == NULL)
97          {          {
98                  error("Failed to open keymap %s\n", path);                  /* in case we are running from the source tree */
99                  return False;                  strcpy(inplace_path, "keymaps/");
100                    strncat(inplace_path, mapname, sizeof(inplace_path) - sizeof("keymaps/"));
101    
102                    fp = fopen(inplace_path, "r");
103                    if (fp == NULL)
104                    {
105                            error("Failed to open keymap %s\n", path);
106                            return False;
107                    }
108          }          }
109    
110            /* FIXME: More tolerant on white space */
111          while (fgets(line, sizeof(line), fp) != NULL)          while (fgets(line, sizeof(line), fp) != NULL)
112          {          {
113                    line_num++;
114    
115                    /* Replace the \n with \0 */
116                  p = strchr(line, '\n');                  p = strchr(line, '\n');
117                  if (p != NULL)                  if (p != NULL)
118                          *p = 0;                          *p = 0;
119    
120                  keycode = strtol(line, &keyname, 16);                  line_length = strlen(line);
121                  if ((keycode != 0) && (*keyname == ' '))  
122                    /* Completely empty line */
123                    if (strspn(line, " \t\n\r\f\v") == line_length)
124                  {                  {
125                          do                          continue;
126                          {                  }
127                                  keyname++;  
128                                  p = strchr(keyname, ' ');                  /* Include */
129                                  if (p != NULL)                  if (strncmp(line, "include ", 8) == 0)
130                                          *p = 0;                  {
131                            if (!xkeymap_read(line + 8))
132                                    return False;
133                            continue;
134                    }
135    
136                                  keysym = XStringToKeysym(keyname);                  /* map */
137                                  if (keysym == NoSymbol)                  if (strncmp(line, "map ", 4) == 0)
138                                          error("Bad keysym %s in keymap %s\n", keyname, mapname);                  {
139                            keylayout = strtol(line + 4, NULL, 16);
140                            DEBUG_KBD(("Keylayout 0x%x\n", keylayout));
141                            continue;
142                    }
143    
144                                  keymap[keysym & KEYMAP_MASK] = keycode;                  /* compose */
145                                  keyname = p;                  if (strncmp(line, "enable_compose", 15) == 0)
146                    {
147                            DEBUG_KBD(("Enabling compose handling\n"));
148                            g_enable_compose = True;
149                            continue;
150                    }
151    
152                          } while (keyname != NULL);                  /* Comment */
153                    if (line[0] == '#')
154                    {
155                            continue;
156                  }                  }
157                  else if (strncmp(line, "include ", 8) == 0)  
158                    /* Normal line */
159                    keyname = line;
160                    p = strchr(line, ' ');
161                    if (p == NULL)
162                  {                  {
163                          if (!xkeymap_read(line+8))                          error("Bad line %d in keymap %s\n", line_num, mapname);
164                                  return False;                          continue;
165                    }
166                    else
167                    {
168                            *p = 0;
169                    }
170    
171                    /* scancode */
172                    p++;
173                    scancode = strtol(p, &line_rest, 16);
174    
175                    /* flags */
176                    /* FIXME: Should allow case-insensitive flag names.
177                       Fix by using lex+yacc... */
178                    modifiers = 0;
179                    if (strstr(line_rest, "altgr"))
180                    {
181                            MASK_ADD_BITS(modifiers, MapAltGrMask);
182                    }
183    
184                    if (strstr(line_rest, "shift"))
185                    {
186                            MASK_ADD_BITS(modifiers, MapLeftShiftMask);
187                    }
188    
189                    if (strstr(line_rest, "localstate"))
190                    {
191                            MASK_ADD_BITS(modifiers, MapLocalStateMask);
192                  }                  }
193                  else if (strncmp(line, "map ", 4) == 0)  
194                    if (strstr(line_rest, "inhibit"))
195                  {                  {
196                          keylayout = strtol(line+4, NULL, 16);                          MASK_ADD_BITS(modifiers, MapInhibitMask);
197                  }                  }
198                  else if (line[0] != '#')  
199                    add_to_keymap(keyname, scancode, modifiers, mapname);
200    
201                    if (strstr(line_rest, "addupper"))
202                  {                  {
203                          error("Malformed line in keymap %s\n", mapname);                          /* Automatically add uppercase key, with same modifiers
204                               plus shift */
205                            for (p = keyname; *p; p++)
206                                    *p = toupper((int) *p);
207                            MASK_ADD_BITS(modifiers, MapLeftShiftMask);
208                            add_to_keymap(keyname, scancode, modifiers, mapname);
209                  }                  }
210          }          }
211    
# Line 98  static BOOL xkeymap_read(char *mapname) Line 213  static BOOL xkeymap_read(char *mapname)
213          return True;          return True;
214  }  }
215    
216  void xkeymap_init(Display *display)  
217    /* Before connecting and creating UI */
218    void
219    xkeymap_init(void)
220  {  {
221          unsigned int max_keycode;          unsigned int max_keycode;
222            char *mapname_ptr;
223    
224          XDisplayKeycodes(display, &min_keycode, &max_keycode);          /* Make keymapname lowercase */
225            mapname_ptr = keymapname;
226            while (*mapname_ptr)
227            {
228                    *mapname_ptr = tolower((int) *mapname_ptr);
229                    mapname_ptr++;
230            }
231    
232          if (strcmp(keymapname, "none"))          if (strcmp(keymapname, "none"))
233                  xkeymap_read(keymapname);          {
234                    if (xkeymap_read(keymapname))
235                            keymap_loaded = True;
236            }
237    
238            XDisplayKeycodes(g_display, &min_keycode, (int *) &max_keycode);
239  }  }
240    
241  uint8 xkeymap_translate_key(KeySym keysym, unsigned int keycode)  static void
242    send_winkey(uint32 ev_time, BOOL pressed, BOOL leftkey)
243  {  {
244          uint8 scancode;          uint8 winkey;
245    
246            if (leftkey)
247                    winkey = SCANCODE_CHAR_LWIN;
248            else
249                    winkey = SCANCODE_CHAR_RWIN;
250    
251            if (pressed)
252            {
253                    if (g_use_rdp5)
254                    {
255                            rdp_send_scancode(ev_time, RDP_KEYPRESS, winkey);
256                    }
257                    else
258                    {
259                            /* RDP4 doesn't support winkey. Fake with Ctrl-Esc */
260                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LCTRL);
261                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_ESC);
262                    }
263            }
264            else
265            {
266                    /* key released */
267                    if (g_use_rdp5)
268                    {
269                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, winkey);
270                    }
271                    else
272                    {
273                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_ESC);
274                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
275                    }
276            }
277    }
278    
279    static void
280    reset_winkey(uint32 ev_time)
281    {
282            if (g_use_rdp5)
283            {
284                    /* For some reason, it seems to suffice to release
285                     *either* the left or right winkey. */
286                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LWIN);
287            }
288    }
289    
290    /* Handles, for example, multi-scancode keypresses (which is not
291       possible via keymap-files) */
292    BOOL
293    handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)
294    {
295            switch (keysym)
296            {
297                    case XK_Return:
298                            if ((get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R))
299                                && (get_key_state(state, XK_Control_L)
300                                    || get_key_state(state, XK_Control_R)))
301                            {
302                                    /* Ctrl-Alt-Enter: toggle full screen */
303                                    if (pressed)
304                                            xwin_toggle_fullscreen();
305                                    return True;
306                            }
307                            break;
308    
309                    case XK_Break:
310                            /* Send Break sequence E0 46 E0 C6 */
311                            if (pressed)
312                            {
313                                    rdp_send_scancode(ev_time, RDP_KEYPRESS,
314                                                      (SCANCODE_EXTENDED | 0x46));
315                                    rdp_send_scancode(ev_time, RDP_KEYPRESS,
316                                                      (SCANCODE_EXTENDED | 0xc6));
317                            }
318                            /* No release sequence */
319                            return True;
320    
321                    case XK_Pause:
322                            /* According to MS Keyboard Scan Code
323                               Specification, pressing Pause should result
324                               in E1 1D 45 E1 9D C5. I'm not exactly sure
325                               of how this is supposed to be sent via
326                               RDP. The code below seems to work, but with
327                               the side effect that Left Ctrl stays
328                               down. Therefore, we release it when Pause
329                               is released. */
330                            if (pressed)
331                            {
332                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
333                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0);
334                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x45, 0);
335                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
336                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x9d, 0);
337                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xc5, 0);
338                            }
339                            else
340                            {
341                                    /* Release Left Ctrl */
342                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYRELEASE,
343                                                   0x1d, 0);
344                            }
345                            return True;
346    
347                    case XK_Meta_L: /* Windows keys */
348                    case XK_Super_L:
349                    case XK_Hyper_L:
350                            send_winkey(ev_time, pressed, True);
351                            return True;
352    
353                    case XK_Meta_R:
354                    case XK_Super_R:
355                    case XK_Hyper_R:
356                            send_winkey(ev_time, pressed, False);
357                            return True;
358    
359                    case XK_space:
360                            /* Prevent access to the Windows system menu in single app mode */
361                            if (g_win_button_size
362                                && (get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R)))
363                                    return True;
364    
365            }
366            return False;
367    }
368    
369    
370    key_translation
371    xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state)
372    {
373            key_translation tr = { 0, 0 };
374    
375            tr = keymap[keysym & KEYMAP_MASK];
376    
377          scancode = keymap[keysym & KEYMAP_MASK];          if (tr.modifiers & MapInhibitMask)
378          if (scancode != 0)          {
379                  return scancode;                  DEBUG_KBD(("Inhibiting key\n"));
380                    tr.scancode = 0;
381                    return tr;
382            }
383    
384            if (tr.modifiers & MapLocalStateMask)
385            {
386                    /* The modifiers to send for this key should be obtained
387                       from the local state. Currently, only shift is implemented. */
388                    if (state & ShiftMask)
389                    {
390                            tr.modifiers = MapLeftShiftMask;
391                    }
392            }
393    
394            if (tr.scancode != 0)
395            {
396                    DEBUG_KBD(("Found key translation, scancode=0x%x, modifiers=0x%x\n",
397                               tr.scancode, tr.modifiers));
398                    return tr;
399            }
400    
401            if (keymap_loaded)
402                    warning("No translation for (keysym 0x%lx, %s)\n", keysym, get_ksname(keysym));
403    
404          /* not in keymap, try to interpret the raw scancode */          /* not in keymap, try to interpret the raw scancode */
405            if (((int) keycode >= min_keycode) && (keycode <= 0x60))
406            {
407                    tr.scancode = keycode - min_keycode;
408    
409          if ((keycode >= min_keycode) && (keycode <= 0x60))                  /* The modifiers to send for this key should be
410                  return (uint8)(keycode - min_keycode);                     obtained from the local state. Currently, only
411                       shift is implemented. */
412                    if (state & ShiftMask)
413                    {
414                            tr.modifiers = MapLeftShiftMask;
415                    }
416    
417          switch (keycode)                  DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));
418            }
419            else
420          {          {
421                  case 0x61:      /* home */                  DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));
                         return 0x47 | 0x80;  
                 case 0x62:      /* up arrow */  
                         return 0x48 | 0x80;  
                 case 0x63:      /* page up */  
                         return 0x49 | 0x80;  
                 case 0x64:      /* left arrow */  
                         return 0x4b | 0x80;  
                 case 0x66:      /* right arrow */  
                         return 0x4d | 0x80;  
                 case 0x67:      /* end */  
                         return 0x4f | 0x80;  
                 case 0x68:      /* down arrow */  
                         return 0x50 | 0x80;  
                 case 0x69:      /* page down */  
                         return 0x51 | 0x80;  
                 case 0x6a:      /* insert */  
                         return 0x52 | 0x80;  
                 case 0x6b:      /* delete */  
                         return 0x53 | 0x80;  
                 case 0x6c:      /* keypad enter */  
                         return 0x1c | 0x80;  
                 case 0x6d:      /* right ctrl */  
                         return 0x1d | 0x80;  
                 case 0x6f:      /* ctrl - print screen */  
                         return 0x37 | 0x80;  
                 case 0x70:      /* keypad '/' */  
                         return 0x35 | 0x80;  
                 case 0x71:      /* right alt */  
                         return 0x38 | 0x80;  
                 case 0x72:      /* ctrl break */  
                         return 0x46 | 0x80;  
                 case 0x73:      /* left window key */  
                         return 0x5b | 0x80;  
                 case 0x74:      /* right window key */  
                         return 0x5c | 0x80;  
                 case 0x75:      /* menu key */  
                         return 0x5d | 0x80;  
422          }          }
423    
424          return 0;          return tr;
425  }  }
426    
427  uint16 xkeymap_translate_button(unsigned int button)  uint16
428    xkeymap_translate_button(unsigned int button)
429  {  {
430          switch (button)          switch (button)
431          {          {
432                  case Button1:   /* left */                  case Button1:   /* left */
433                          return MOUSE_FLAG_BUTTON1;                          return MOUSE_FLAG_BUTTON1;
434                  case Button2:   /* middle */                  case Button2:   /* middle */
435                          return MOUSE_FLAG_BUTTON3;                          return MOUSE_FLAG_BUTTON3;
436                  case Button3:   /* right */                  case Button3:   /* right */
437                          return MOUSE_FLAG_BUTTON2;                          return MOUSE_FLAG_BUTTON2;
438                    case Button4:   /* wheel up */
439                            return MOUSE_FLAG_BUTTON4;
440                    case Button5:   /* wheel down */
441                            return MOUSE_FLAG_BUTTON5;
442          }          }
443    
444          return 0;          return 0;
445  }  }
446    
447    char *
448    get_ksname(uint32 keysym)
449    {
450            char *ksname = NULL;
451    
452            if (keysym == NoSymbol)
453                    ksname = "NoSymbol";
454            else if (!(ksname = XKeysymToString(keysym)))
455                    ksname = "(no name)";
456    
457            return ksname;
458    }
459    
460    static BOOL
461    is_modifier(uint8 scancode)
462    {
463            switch (scancode)
464            {
465                    case SCANCODE_CHAR_LSHIFT:
466                    case SCANCODE_CHAR_RSHIFT:
467                    case SCANCODE_CHAR_LCTRL:
468                    case SCANCODE_CHAR_RCTRL:
469                    case SCANCODE_CHAR_LALT:
470                    case SCANCODE_CHAR_RALT:
471                    case SCANCODE_CHAR_LWIN:
472                    case SCANCODE_CHAR_RWIN:
473                    case SCANCODE_CHAR_NUMLOCK:
474                            return True;
475                    default:
476                            break;
477            }
478            return False;
479    }
480    
481    void
482    save_remote_modifiers(uint8 scancode)
483    {
484            if (is_modifier(scancode))
485                    return;
486    
487            saved_remote_modifier_state = remote_modifier_state;
488    }
489    
490    void
491    restore_remote_modifiers(uint32 ev_time, uint8 scancode)
492    {
493            key_translation dummy;
494    
495            if (is_modifier(scancode))
496                    return;
497    
498            dummy.scancode = 0;
499            dummy.modifiers = saved_remote_modifier_state;
500            ensure_remote_modifiers(ev_time, dummy);
501    }
502    
503    void
504    ensure_remote_modifiers(uint32 ev_time, key_translation tr)
505    {
506            /* If this key is a modifier, do nothing */
507            if (is_modifier(tr.scancode))
508                    return;
509    
510            /* Shift. Left shift and right shift are treated as equal; either is fine. */
511            if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
512                != MASK_HAS_BITS(remote_modifier_state, MapShiftMask))
513            {
514                    /* The remote modifier state is not correct */
515                    if (MASK_HAS_BITS(tr.modifiers, MapLeftShiftMask))
516                    {
517                            /* Needs left shift. Send down. */
518                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LSHIFT);
519                    }
520                    else if (MASK_HAS_BITS(tr.modifiers, MapRightShiftMask))
521                    {
522                            /* Needs right shift. Send down. */
523                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RSHIFT);
524                    }
525                    else
526                    {
527                            /* Should not use this modifier. Send up for shift currently pressed. */
528                            if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask))
529                                    /* Left shift is down */
530                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
531                            else
532                                    /* Right shift is down */
533                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
534                    }
535            }
536    
537            /* AltGr */
538            if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask)
539                != MASK_HAS_BITS(remote_modifier_state, MapAltGrMask))
540            {
541                    /* The remote modifier state is not correct */
542                    if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask))
543                    {
544                            /* Needs this modifier. Send down. */
545                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RALT);
546                    }
547                    else
548                    {
549                            /* Should not use this modifier. Send up. */
550                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
551                    }
552            }
553    
554    
555    }
556    
557    
558    unsigned int
559    read_keyboard_state()
560    {
561            unsigned int state;
562            Window wdummy;
563            int dummy;
564    
565            XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
566            return state;
567    }
568    
569    
570    uint16
571    ui_get_numlock_state(unsigned int state)
572    {
573            uint16 numlock_state = 0;
574    
575            if (get_key_state(state, XK_Num_Lock))
576                    numlock_state = KBD_FLAG_NUMLOCK;
577    
578            return numlock_state;
579    }
580    
581    
582    void
583    reset_modifier_keys()
584    {
585            unsigned int state = read_keyboard_state();
586    
587            /* reset keys */
588            uint32 ev_time;
589            ev_time = time(NULL);
590    
591            if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask)
592                && !get_key_state(state, XK_Shift_L))
593                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
594    
595            if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask)
596                && !get_key_state(state, XK_Shift_R))
597                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
598    
599            if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask)
600                && !get_key_state(state, XK_Control_L))
601                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
602    
603            if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask)
604                && !get_key_state(state, XK_Control_R))
605                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
606    
607            if (MASK_HAS_BITS(remote_modifier_state, MapLeftAltMask) && !get_key_state(state, XK_Alt_L))
608                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
609    
610            if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) &&
611                !get_key_state(state, XK_Alt_R) && !get_key_state(state, XK_Mode_switch))
612                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
613    
614            reset_winkey(ev_time);
615    
616            rdp_send_input(ev_time, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(state), 0);
617    }
618    
619    
620    static void
621    update_modifier_state(uint8 scancode, BOOL pressed)
622    {
623    #ifdef WITH_DEBUG_KBD
624            uint16 old_modifier_state;
625    
626            old_modifier_state = remote_modifier_state;
627    #endif
628    
629            switch (scancode)
630            {
631                    case SCANCODE_CHAR_LSHIFT:
632                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftShiftMask, pressed);
633                            break;
634                    case SCANCODE_CHAR_RSHIFT:
635                            MASK_CHANGE_BIT(remote_modifier_state, MapRightShiftMask, pressed);
636                            break;
637                    case SCANCODE_CHAR_LCTRL:
638                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftCtrlMask, pressed);
639                            break;
640                    case SCANCODE_CHAR_RCTRL:
641                            MASK_CHANGE_BIT(remote_modifier_state, MapRightCtrlMask, pressed);
642                            break;
643                    case SCANCODE_CHAR_LALT:
644                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftAltMask, pressed);
645                            break;
646                    case SCANCODE_CHAR_RALT:
647                            MASK_CHANGE_BIT(remote_modifier_state, MapRightAltMask, pressed);
648                            break;
649                    case SCANCODE_CHAR_LWIN:
650                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftWinMask, pressed);
651                            break;
652                    case SCANCODE_CHAR_RWIN:
653                            MASK_CHANGE_BIT(remote_modifier_state, MapRightWinMask, pressed);
654                            break;
655            }
656    
657    #ifdef WITH_DEBUG_KBD
658            if (old_modifier_state != remote_modifier_state)
659            {
660                    DEBUG_KBD(("Before updating modifier_state:0x%x, pressed=0x%x\n",
661                               old_modifier_state, pressed));
662                    DEBUG_KBD(("After updating modifier_state:0x%x\n", remote_modifier_state));
663            }
664    #endif
665    
666    }
667    
668    /* Send keyboard input */
669    void
670    rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode)
671    {
672            update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));
673    
674            if (scancode & SCANCODE_EXTENDED)
675            {
676                    DEBUG_KBD(("Sending extended scancode=0x%x, flags=0x%x\n",
677                               scancode & ~SCANCODE_EXTENDED, flags));
678                    rdp_send_input(time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,
679                                   scancode & ~SCANCODE_EXTENDED, 0);
680            }
681            else
682            {
683                    DEBUG_KBD(("Sending scancode=0x%x, flags=0x%x\n", scancode, flags));
684                    rdp_send_input(time, RDP_INPUT_SCANCODE, flags, scancode, 0);
685            }
686    }

Legend:
Removed from v.39  
changed lines
  Added in v.548

  ViewVC Help
Powered by ViewVC 1.1.26