/[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 543 by astrand, Mon Nov 3 13:33:35 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 *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 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 uint8 keymap[KEYMAP_SIZE];  static void update_modifier_state(uint8 scancode, BOOL pressed);
 static unsigned int min_keycode;  
55    
56  static BOOL xkeymap_read(char *mapname)  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            keymap[keysym & KEYMAP_MASK].scancode = scancode;
72            keymap[keysym & KEYMAP_MASK].modifiers = modifiers;
73    
74            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            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                          {                  }
                                 keyname++;  
                                 p = strchr(keyname, ' ');  
                                 if (p != NULL)  
                                         *p = 0;  
127    
128                                  keysym = XStringToKeysym(keyname);                  /* Include */
129                                  if (keysym == NoSymbol)                  if (strncmp(line, "include ", 8) == 0)
130                                          error("Bad keysym %s in keymap %s\n", keyname, mapname);                  {
131                            if (!xkeymap_read(line + 8))
132                                    return False;
133                            continue;
134                    }
135    
136                                  keymap[keysym & KEYMAP_MASK] = keycode;                  /* map */
137                                  keyname = p;                  if (strncmp(line, "map ", 4) == 0)
138                    {
139                            keylayout = strtol(line + 4, NULL, 16);
140                            DEBUG_KBD(("Keylayout 0x%x\n", keylayout));
141                            continue;
142                    }
143    
144                          } while (keyname != NULL);                  /* compose */
145                    if (strncmp(line, "enable_compose", 15) == 0)
146                    {
147                            DEBUG_KBD(("Enabling compose handling\n"));
148                            g_enable_compose = True;
149                            continue;
150                  }                  }
151                  else if (strncmp(line, "include ", 8) == 0)  
152                    /* Comment */
153                    if (line[0] == '#')
154                  {                  {
155                          if (!xkeymap_read(line+8))                          continue;
156                                  return False;                  }
157    
158                    /* Normal line */
159                    keyname = line;
160                    p = strchr(line, ' ');
161                    if (p == NULL)
162                    {
163                            error("Bad line %d in keymap %s\n", line_num, mapname);
164                            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(void)  
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(unsigned int keysym, unsigned int keycode, uint16 *flags)  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          scancode = keymap[keysym & KEYMAP_MASK];  /* Handles, for example, multi-scancode keypresses (which is not
280          if (scancode != 0)     possible via keymap-files) */
281    BOOL
282    handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)
283    {
284            switch (keysym)
285          {          {
286                  if (scancode & 0x80)                  case XK_Return:
287                          *flags |= KBD_FLAG_EXT;                          if ((get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R))
288                                && (get_key_state(state, XK_Control_L)
289                                    || get_key_state(state, XK_Control_R)))
290                            {
291                                    /* Ctrl-Alt-Enter: toggle full screen */
292                                    if (pressed)
293                                            xwin_toggle_fullscreen();
294                                    return True;
295                            }
296                            break;
297    
298                    case XK_Break:
299                            /* Send Break sequence E0 46 E0 C6 */
300                            if (pressed)
301                            {
302                                    rdp_send_scancode(ev_time, RDP_KEYPRESS,
303                                                      (SCANCODE_EXTENDED | 0x46));
304                                    rdp_send_scancode(ev_time, RDP_KEYPRESS,
305                                                      (SCANCODE_EXTENDED | 0xc6));
306                            }
307                            /* No release sequence */
308                            return True;
309    
310                    case XK_Pause:
311                            /* According to MS Keyboard Scan Code
312                               Specification, pressing Pause should result
313                               in E1 1D 45 E1 9D C5. I'm not exactly sure
314                               of how this is supposed to be sent via
315                               RDP. The code below seems to work, but with
316                               the side effect that Left Ctrl stays
317                               down. Therefore, we release it when Pause
318                               is released. */
319                            if (pressed)
320                            {
321                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
322                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0);
323                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x45, 0);
324                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
325                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x9d, 0);
326                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xc5, 0);
327                            }
328                            else
329                            {
330                                    /* Release Left Ctrl */
331                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYRELEASE,
332                                                   0x1d, 0);
333                            }
334                            return True;
335    
336                    case XK_Meta_L: /* Windows keys */
337                    case XK_Super_L:
338                    case XK_Hyper_L:
339                            send_winkey(ev_time, pressed, True);
340                            return True;
341    
342                    case XK_Meta_R:
343                    case XK_Super_R:
344                    case XK_Hyper_R:
345                            send_winkey(ev_time, pressed, False);
346                            return True;
347    
348                    case XK_space:
349                            /* Prevent access to the Windows system menu in single app mode */
350                            if (g_win_button_size
351                                && (get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R)))
352                                    return True;
353    
                 return (scancode & 0x7f);  
354          }          }
355            return False;
356    }
357    
         /* not in keymap, try to interpret the raw scancode */  
358    
359          if ((keycode >= min_keycode) && (keycode <= 0x60))  key_translation
360                  return (uint8)(keycode - min_keycode);  xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state)
361    {
362            key_translation tr = { 0, 0 };
363    
364          *flags |= KBD_FLAG_EXT;          tr = keymap[keysym & KEYMAP_MASK];
365    
366          switch (keycode)          if (tr.modifiers & MapInhibitMask)
367          {          {
368                  case 0x61:      /* home */                  DEBUG_KBD(("Inhibiting key\n"));
369                          return 0x47;                  tr.scancode = 0;
370                  case 0x62:      /* up arrow */                  return tr;
                         return 0x48;  
                 case 0x63:      /* page up */  
                         return 0x49;  
                 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;  
371          }          }
372    
373          return 0;          if (tr.modifiers & MapLocalStateMask)
374            {
375                    /* The modifiers to send for this key should be obtained
376                       from the local state. Currently, only shift is implemented. */
377                    if (state & ShiftMask)
378                    {
379                            tr.modifiers = MapLeftShiftMask;
380                    }
381            }
382    
383            if (tr.scancode != 0)
384            {
385                    DEBUG_KBD(("Found key translation, scancode=0x%x, modifiers=0x%x\n",
386                               tr.scancode, tr.modifiers));
387                    return tr;
388            }
389    
390            if (keymap_loaded)
391                    warning("No translation for (keysym 0x%lx, %s)\n", keysym, get_ksname(keysym));
392    
393            /* not in keymap, try to interpret the raw scancode */
394            if (((int) keycode >= min_keycode) && (keycode <= 0x60))
395            {
396                    tr.scancode = keycode - min_keycode;
397    
398                    /* The modifiers to send for this key should be
399                       obtained from the local state. Currently, only
400                       shift is implemented. */
401                    if (state & ShiftMask)
402                    {
403                            tr.modifiers = MapLeftShiftMask;
404                    }
405    
406                    DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));
407            }
408            else
409            {
410                    DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));
411            }
412    
413            return tr;
414  }  }
415    
416  uint16 xkeymap_translate_button(unsigned int button)  uint16
417    xkeymap_translate_button(unsigned int button)
418  {  {
419          switch (button)          switch (button)
420          {          {
421                  case Button1:   /* left */                  case Button1:   /* left */
422                          return MOUSE_FLAG_BUTTON1;                          return MOUSE_FLAG_BUTTON1;
423                  case Button2:   /* middle */                  case Button2:   /* middle */
424                          return MOUSE_FLAG_BUTTON3;                          return MOUSE_FLAG_BUTTON3;
425                  case Button3:   /* right */                  case Button3:   /* right */
426                          return MOUSE_FLAG_BUTTON2;                          return MOUSE_FLAG_BUTTON2;
427                    case Button4:   /* wheel up */
428                            return MOUSE_FLAG_BUTTON4;
429                    case Button5:   /* wheel down */
430                            return MOUSE_FLAG_BUTTON5;
431          }          }
432    
433          return 0;          return 0;
434  }  }
435    
436    char *
437    get_ksname(uint32 keysym)
438    {
439            char *ksname = NULL;
440    
441            if (keysym == NoSymbol)
442                    ksname = "NoSymbol";
443            else if (!(ksname = XKeysymToString(keysym)))
444                    ksname = "(no name)";
445    
446            return ksname;
447    }
448    
449    static BOOL
450    is_modifier(uint8 scancode)
451    {
452            switch (scancode)
453            {
454                    case SCANCODE_CHAR_LSHIFT:
455                    case SCANCODE_CHAR_RSHIFT:
456                    case SCANCODE_CHAR_LCTRL:
457                    case SCANCODE_CHAR_RCTRL:
458                    case SCANCODE_CHAR_LALT:
459                    case SCANCODE_CHAR_RALT:
460                    case SCANCODE_CHAR_LWIN:
461                    case SCANCODE_CHAR_RWIN:
462                    case SCANCODE_CHAR_NUMLOCK:
463                            return True;
464                    default:
465                            break;
466            }
467            return False;
468    }
469    
470    void
471    save_remote_modifiers(uint8 scancode)
472    {
473            if (is_modifier(scancode))
474                    return;
475    
476            saved_remote_modifier_state = remote_modifier_state;
477    }
478    
479    void
480    restore_remote_modifiers(uint32 ev_time, uint8 scancode)
481    {
482            key_translation dummy;
483    
484            if (is_modifier(scancode))
485                    return;
486    
487            dummy.scancode = 0;
488            dummy.modifiers = saved_remote_modifier_state;
489            ensure_remote_modifiers(ev_time, dummy);
490    }
491    
492    void
493    ensure_remote_modifiers(uint32 ev_time, key_translation tr)
494    {
495            /* If this key is a modifier, do nothing */
496            if (is_modifier(tr.scancode))
497                    return;
498    
499            /* Shift. Left shift and right shift are treated as equal; either is fine. */
500            if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
501                != MASK_HAS_BITS(remote_modifier_state, MapShiftMask))
502            {
503                    /* The remote modifier state is not correct */
504                    if (MASK_HAS_BITS(tr.modifiers, MapLeftShiftMask))
505                    {
506                            /* Needs left shift. Send down. */
507                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LSHIFT);
508                    }
509                    else if (MASK_HAS_BITS(tr.modifiers, MapRightShiftMask))
510                    {
511                            /* Needs right shift. Send down. */
512                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RSHIFT);
513                    }
514                    else
515                    {
516                            /* Should not use this modifier. Send up for shift currently pressed. */
517                            if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask))
518                                    /* Left shift is down */
519                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
520                            else
521                                    /* Right shift is down */
522                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
523                    }
524            }
525    
526            /* AltGr */
527            if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask)
528                != MASK_HAS_BITS(remote_modifier_state, MapAltGrMask))
529            {
530                    /* The remote modifier state is not correct */
531                    if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask))
532                    {
533                            /* Needs this modifier. Send down. */
534                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RALT);
535                    }
536                    else
537                    {
538                            /* Should not use this modifier. Send up. */
539                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
540                    }
541            }
542    
543    
544    }
545    
546    
547    unsigned int
548    read_keyboard_state()
549    {
550            unsigned int state;
551            Window wdummy;
552            int dummy;
553    
554            XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
555            return state;
556    }
557    
558    
559    uint16
560    ui_get_numlock_state(unsigned int state)
561    {
562            uint16 numlock_state = 0;
563    
564            if (get_key_state(state, XK_Num_Lock))
565                    numlock_state = KBD_FLAG_NUMLOCK;
566    
567            return numlock_state;
568    }
569    
570    
571    void
572    reset_modifier_keys()
573    {
574            unsigned int state = read_keyboard_state();
575    
576            /* reset keys */
577            uint32 ev_time;
578            ev_time = time(NULL);
579    
580            if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask)
581                && !get_key_state(state, XK_Shift_L))
582                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
583    
584            if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask)
585                && !get_key_state(state, XK_Shift_R))
586                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
587    
588            if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask)
589                && !get_key_state(state, XK_Control_L))
590                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
591    
592            if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask)
593                && !get_key_state(state, XK_Control_R))
594                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
595    
596            if (MASK_HAS_BITS(remote_modifier_state, MapLeftAltMask) && !get_key_state(state, XK_Alt_L))
597                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
598    
599            if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) &&
600                !get_key_state(state, XK_Alt_R) && !get_key_state(state, XK_Mode_switch))
601                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
602    
603            rdp_send_input(ev_time, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(state), 0);
604    }
605    
606    
607    static void
608    update_modifier_state(uint8 scancode, BOOL pressed)
609    {
610    #ifdef WITH_DEBUG_KBD
611            uint16 old_modifier_state;
612    
613            old_modifier_state = remote_modifier_state;
614    #endif
615    
616            switch (scancode)
617            {
618                    case SCANCODE_CHAR_LSHIFT:
619                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftShiftMask, pressed);
620                            break;
621                    case SCANCODE_CHAR_RSHIFT:
622                            MASK_CHANGE_BIT(remote_modifier_state, MapRightShiftMask, pressed);
623                            break;
624                    case SCANCODE_CHAR_LCTRL:
625                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftCtrlMask, pressed);
626                            break;
627                    case SCANCODE_CHAR_RCTRL:
628                            MASK_CHANGE_BIT(remote_modifier_state, MapRightCtrlMask, pressed);
629                            break;
630                    case SCANCODE_CHAR_LALT:
631                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftAltMask, pressed);
632                            break;
633                    case SCANCODE_CHAR_RALT:
634                            MASK_CHANGE_BIT(remote_modifier_state, MapRightAltMask, pressed);
635                            break;
636                    case SCANCODE_CHAR_LWIN:
637                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftWinMask, pressed);
638                            break;
639                    case SCANCODE_CHAR_RWIN:
640                            MASK_CHANGE_BIT(remote_modifier_state, MapRightWinMask, pressed);
641                            break;
642            }
643    
644    #ifdef WITH_DEBUG_KBD
645            if (old_modifier_state != remote_modifier_state)
646            {
647                    DEBUG_KBD(("Before updating modifier_state:0x%x, pressed=0x%x\n",
648                               old_modifier_state, pressed));
649                    DEBUG_KBD(("After updating modifier_state:0x%x\n", remote_modifier_state));
650            }
651    #endif
652    
653    }
654    
655    /* Send keyboard input */
656    void
657    rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode)
658    {
659            update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));
660    
661            if (scancode & SCANCODE_EXTENDED)
662            {
663                    DEBUG_KBD(("Sending extended scancode=0x%x, flags=0x%x\n",
664                               scancode & ~SCANCODE_EXTENDED, flags));
665                    rdp_send_input(time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,
666                                   scancode & ~SCANCODE_EXTENDED, 0);
667            }
668            else
669            {
670                    DEBUG_KBD(("Sending scancode=0x%x, flags=0x%x\n", scancode, flags));
671                    rdp_send_input(time, RDP_INPUT_SCANCODE, flags, scancode, 0);
672            }
673    }

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

  ViewVC Help
Powered by ViewVC 1.1.26