/[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 64 by astrand, Thu Jul 18 16:38:31 2002 UTC revision 203 by matthewc, Thu Sep 26 14:04:30 2002 UTC
# Line 19  Line 19 
19  */  */
20    
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/keysym.h>  #define XK_MISCELLANY
23  #include <stdio.h>  #include <X11/keysymdef.h>
24  #include <stdlib.h>  #include <ctype.h>
 #include <string.h>  
25  #include <limits.h>  #include <limits.h>
26    #include <time.h>
27  #include "rdesktop.h"  #include "rdesktop.h"
28    #include "scancodes.h"
29    
30  #define KEYMAP_SIZE 4096  #define KEYMAP_SIZE 4096
31  #define KEYMAP_MASK (KEYMAP_SIZE - 1)  #define KEYMAP_MASK (KEYMAP_SIZE - 1)
32    #define KEYMAP_MAX_LINE_LENGTH 80
33    
34  extern Display *display;  extern Display *display;
35  extern char keymapname[16];  extern char keymapname[16];
36  extern int keylayout;  extern int keylayout;
37    extern BOOL enable_compose;
38    
39    static key_translation keymap[KEYMAP_SIZE];
40    static int min_keycode;
41    static uint16 remote_modifier_state = 0;
42    
43    static void update_modifier_state(uint8 scancode, BOOL pressed);
44    
45    static void
46    add_to_keymap(char *keyname, uint8 scancode, uint16 modifiers, char *mapname)
47    {
48            KeySym keysym;
49    
50            keysym = XStringToKeysym(keyname);
51            if (keysym == NoSymbol)
52            {
53                    error("Bad keysym %s in keymap %s\n", keyname, mapname);
54                    return;
55            }
56    
57            DEBUG_KBD(("Adding translation, keysym=0x%x, scancode=0x%x, "
58                       "modifiers=0x%x\n", (unsigned int) keysym, scancode, modifiers));
59    
60            keymap[keysym & KEYMAP_MASK].scancode = scancode;
61            keymap[keysym & KEYMAP_MASK].modifiers = modifiers;
62    
63            return;
64    }
65    
 static uint8 keymap[KEYMAP_SIZE];  
 static unsigned int min_keycode;  
66    
67  static BOOL  static BOOL
68  xkeymap_read(char *mapname)  xkeymap_read(char *mapname)
69  {  {
70          FILE *fp;          FILE *fp;
71          char line[PATH_MAX], path[PATH_MAX];          char line[KEYMAP_MAX_LINE_LENGTH], path[PATH_MAX];
72            unsigned int line_num = 0;
73            unsigned int line_length = 0;
74          char *keyname, *p;          char *keyname, *p;
75          KeySym keysym;          char *line_rest;
76          unsigned char keycode;          uint8 scancode;
77            uint16 modifiers;
78    
79    
80          strcpy(path, KEYMAP_PATH);          strcpy(path, KEYMAP_PATH);
81          strncat(path, mapname, sizeof(path) - sizeof(KEYMAP_PATH));          strncat(path, mapname, sizeof(path) - sizeof(KEYMAP_PATH));
# Line 55  xkeymap_read(char *mapname) Line 87  xkeymap_read(char *mapname)
87                  return False;                  return False;
88          }          }
89    
90            /* FIXME: More tolerant on white space */
91          while (fgets(line, sizeof(line), fp) != NULL)          while (fgets(line, sizeof(line), fp) != NULL)
92          {          {
93                    line_num++;
94    
95                    /* Replace the \n with \0 */
96                  p = strchr(line, '\n');                  p = strchr(line, '\n');
97                  if (p != NULL)                  if (p != NULL)
98                          *p = 0;                          *p = 0;
99    
100                  keycode = strtol(line, &keyname, 16);                  line_length = strlen(line);
                 if ((keycode != 0) && (*keyname == ' '))  
                 {  
                         do  
                         {  
                                 keyname++;  
                                 p = strchr(keyname, ' ');  
                                 if (p != NULL)  
                                         *p = 0;  
   
                                 keysym = XStringToKeysym(keyname);  
                                 if (keysym == NoSymbol)  
                                         error("Bad keysym %s in keymap %s\n",  
                                               keyname, mapname);  
101    
102                                  keymap[keysym & KEYMAP_MASK] = keycode;                  /* Completely empty line */
103                                  keyname = p;                  if (strspn(line, " \t\n\r\f\v") == line_length)
104                    {
105                          }                          continue;
                         while (keyname != NULL);  
106                  }                  }
107                  else if (strncmp(line, "include ", 8) == 0)  
108                    /* Include */
109                    if (strncmp(line, "include ", 8) == 0)
110                  {                  {
111                          if (!xkeymap_read(line + 8))                          if (!xkeymap_read(line + 8))
112                                  return False;                                  return False;
113                            continue;
114                  }                  }
115                  else if (strncmp(line, "map ", 4) == 0)  
116                    /* map */
117                    if (strncmp(line, "map ", 4) == 0)
118                  {                  {
119                          keylayout = strtol(line + 4, NULL, 16);                          keylayout = strtol(line + 4, NULL, 16);
120                            DEBUG_KBD(("Keylayout 0x%x\n", keylayout));
121                            continue;
122                  }                  }
123                  else if (line[0] != '#')  
124                    /* compose */
125                    if (strncmp(line, "enable_compose", 15) == 0)
126                  {                  {
127                          error("Malformed line in keymap %s\n", mapname);                          DEBUG_KBD(("Enabling compose handling\n"));
128                            enable_compose = True;
129                            continue;
130                    }
131    
132                    /* Comment */
133                    if (line[0] == '#')
134                    {
135                            continue;
136                    }
137    
138                    /* Normal line */
139                    keyname = line;
140                    p = strchr(line, ' ');
141                    if (p == NULL)
142                    {
143                            error("Bad line %d in keymap %s\n", line_num, mapname);
144                            continue;
145                    }
146                    else
147                    {
148                            *p = 0;
149                    }
150    
151                    /* scancode */
152                    p++;
153                    scancode = strtol(p, &line_rest, 16);
154    
155                    /* flags */
156                    /* FIXME: Should allow case-insensitive flag names.
157                       Fix by using lex+yacc... */
158                    modifiers = 0;
159                    if (strstr(line_rest, "altgr"))
160                    {
161                            MASK_ADD_BITS(modifiers, MapAltGrMask);
162                    }
163    
164                    if (strstr(line_rest, "shift"))
165                    {
166                            MASK_ADD_BITS(modifiers, MapLeftShiftMask);
167                    }
168    
169                    if (strstr(line_rest, "numlock"))
170                    {
171                            MASK_ADD_BITS(modifiers, MapNumLockMask);
172                    }
173    
174                    if (strstr(line_rest, "localstate"))
175                    {
176                            MASK_ADD_BITS(modifiers, MapLocalStateMask);
177                    }
178    
179                    if (strstr(line_rest, "inhibit"))
180                    {
181                            MASK_ADD_BITS(modifiers, MapInhibitMask);
182                    }
183    
184                    add_to_keymap(keyname, scancode, modifiers, mapname);
185    
186                    if (strstr(line_rest, "addupper"))
187                    {
188                            /* Automatically add uppercase key, with same modifiers
189                               plus shift */
190                            for (p = keyname; *p; p++)
191                                    *p = toupper(*p);
192                            MASK_ADD_BITS(modifiers, MapLeftShiftMask);
193                            add_to_keymap(keyname, scancode, modifiers, mapname);
194                  }                  }
195          }          }
196    
# Line 101  xkeymap_read(char *mapname) Line 198  xkeymap_read(char *mapname)
198          return True;          return True;
199  }  }
200    
201    
202    /* Before connecting and creating UI */
203  void  void
204  xkeymap_init(void)  xkeymap_init(void)
205  {  {
206          unsigned int max_keycode;          unsigned int max_keycode;
207    
         XDisplayKeycodes(display, &min_keycode, &max_keycode);  
   
208          if (strcmp(keymapname, "none"))          if (strcmp(keymapname, "none"))
209                  xkeymap_read(keymapname);                  xkeymap_read(keymapname);
210    
211            XDisplayKeycodes(display, &min_keycode, (int *) &max_keycode);
212  }  }
213    
214  uint8  /* Handles, for example, multi-scancode keypresses (which is not
215  xkeymap_translate_key(unsigned int keysym, unsigned int keycode,     possible via keymap-files) */
216                        uint16 * flags)  BOOL
217    handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)
218  {  {
219          uint8 scancode;          switch (keysym)
220            {
221                    case XK_Break:
222                            if (get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R))
223                            {
224                                    /* toggle full screen */
225                                    if (pressed)
226                                            xwin_toggle_fullscreen();
227    
228                            }
229                            else
230                            {
231                                    /* Send Break sequence E0 46 E0 C6 */
232                                    if (pressed)
233                                    {
234                                            rdp_send_scancode(ev_time, RDP_KEYPRESS,
235                                                              (SCANCODE_EXTENDED | 0x46));
236                                            rdp_send_scancode(ev_time, RDP_KEYPRESS,
237                                                              (SCANCODE_EXTENDED | 0xc6));
238                                    }
239                                    /* No break sequence */
240                            }
241    
242                            return True;
243                            break;
244    
245                    case XK_Pause:
246                            /* According to MS Keyboard Scan Code
247                               Specification, pressing Pause should result
248                               in E1 1D 45 E1 9D C5. I'm not exactly sure
249                               of how this is supposed to be sent via
250                               RDP. The code below seems to work, but with
251                               the side effect that Left Ctrl stays
252                               down. Therefore, we release it when Pause
253                               is released. */
254                            if (pressed)
255                            {
256                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
257                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0);
258                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x45, 0);
259                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
260                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x9d, 0);
261                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xc5, 0);
262                            }
263                            else
264                            {
265                                    // Release Left Ctrl
266                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x1d,
267                                                   0);
268                            }
269    
270                            return True;
271                            break;
272    
273                    case XK_Meta_L: /* Windows keys */
274                    case XK_Super_L:
275                    case XK_Hyper_L:
276                    case XK_Meta_R:
277                    case XK_Super_R:
278                    case XK_Hyper_R:
279                            if (pressed)
280                            {
281                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LCTRL);
282                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_ESC);
283                            }
284                            else
285                            {
286                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_ESC);
287                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
288                            }
289                            return True;
290                            break;
291            }
292            return False;
293    }
294    
295    
296    key_translation
297    xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state)
298    {
299            key_translation tr = { 0, 0 };
300    
301            tr = keymap[keysym & KEYMAP_MASK];
302    
303            if (tr.modifiers & MapInhibitMask)
304            {
305                    DEBUG_KBD(("Inhibiting key\n"));
306                    tr.scancode = 0;
307                    return tr;
308            }
309    
310          scancode = keymap[keysym & KEYMAP_MASK];          if (tr.modifiers & MapLocalStateMask)
         if (scancode != 0)  
311          {          {
312                  if (scancode & 0x80)                  /* The modifiers to send for this key should be obtained
313                          *flags |= KBD_FLAG_EXT;                     from the local state. Currently, only shift is implemented. */
314                    if (state & ShiftMask)
315                    {
316                            tr.modifiers = MapLeftShiftMask;
317                    }
318            }
319    
320                  return (scancode & 0x7f);          if (tr.scancode != 0)
321            {
322                    DEBUG_KBD(("Found key translation, scancode=0x%x, modifiers=0x%x\n",
323                               tr.scancode, tr.modifiers));
324                    return tr;
325          }          }
326    
327          /* not in keymap, try to interpret the raw scancode */          DEBUG_KBD(("No translation for (keysym 0x%lx, %s)\n", keysym, get_ksname(keysym)));
328    
329            /* not in keymap, try to interpret the raw scancode */
330          if ((keycode >= min_keycode) && (keycode <= 0x60))          if ((keycode >= min_keycode) && (keycode <= 0x60))
331                  return (uint8) (keycode - min_keycode);          {
332                    tr.scancode = keycode - min_keycode;
333    
334          *flags |= KBD_FLAG_EXT;                  /* The modifiers to send for this key should be
335                       obtained from the local state. Currently, only
336                       shift is implemented. */
337                    if (state & ShiftMask)
338                    {
339                            tr.modifiers = MapLeftShiftMask;
340                    }
341    
342          switch (keycode)                  DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));
343            }
344            else
345          {          {
346                  case 0x61:      /* home */                  DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));
                         return 0x47;  
                 case 0x62:      /* up arrow */  
                         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;  
347          }          }
348    
349          return 0;          return tr;
350  }  }
351    
352  uint16  uint16
# Line 198  xkeymap_translate_button(unsigned int bu Line 368  xkeymap_translate_button(unsigned int bu
368    
369          return 0;          return 0;
370  }  }
371    
372    char *
373    get_ksname(uint32 keysym)
374    {
375            char *ksname = NULL;
376    
377            if (keysym == NoSymbol)
378                    ksname = "NoSymbol";
379            else if (!(ksname = XKeysymToString(keysym)))
380                    ksname = "(no name)";
381    
382            return ksname;
383    }
384    
385    
386    void
387    ensure_remote_modifiers(uint32 ev_time, key_translation tr)
388    {
389            /* If this key is a modifier, do nothing */
390            switch (tr.scancode)
391            {
392                    case SCANCODE_CHAR_LSHIFT:
393                    case SCANCODE_CHAR_RSHIFT:
394                    case SCANCODE_CHAR_LCTRL:
395                    case SCANCODE_CHAR_RCTRL:
396                    case SCANCODE_CHAR_LALT:
397                    case SCANCODE_CHAR_RALT:
398                    case SCANCODE_CHAR_LWIN:
399                    case SCANCODE_CHAR_RWIN:
400                    case SCANCODE_CHAR_NUMLOCK:
401                            return;
402                    default:
403                            break;
404            }
405    
406            /* Shift. Left shift and right shift are treated as equal; either is fine. */
407            if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
408                != MASK_HAS_BITS(remote_modifier_state, MapShiftMask))
409            {
410                    /* The remote modifier state is not correct */
411                    if (MASK_HAS_BITS(tr.modifiers, MapLeftShiftMask))
412                    {
413                            /* Needs left shift. Send down. */
414                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LSHIFT);
415                    }
416                    else if (MASK_HAS_BITS(tr.modifiers, MapRightShiftMask))
417                    {
418                            /* Needs right shift. Send down. */
419                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RSHIFT);
420                    }
421                    else
422                    {
423                            /* Should not use this modifier. Send up for shift currently pressed. */
424                            if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask))
425                                    /* Left shift is down */
426                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
427                            else
428                                    /* Right shift is down */
429                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
430                    }
431            }
432    
433            /* AltGr */
434            if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask)
435                != MASK_HAS_BITS(remote_modifier_state, MapAltGrMask))
436            {
437                    /* The remote modifier state is not correct */
438                    if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask))
439                    {
440                            /* Needs this modifier. Send down. */
441                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RALT);
442                    }
443                    else
444                    {
445                            /* Should not use this modifier. Send up. */
446                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
447                    }
448            }
449    
450            /* NumLock */
451            if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)
452                != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask))
453            {
454                    /* The remote modifier state is not correct */
455                    uint16 new_remote_state = 0;
456    
457                    if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask))
458                    {
459                            DEBUG_KBD(("Remote NumLock state is incorrect, activating NumLock.\n"));
460                            new_remote_state |= KBD_FLAG_NUMLOCK;
461                    }
462                    else
463                    {
464                            DEBUG_KBD(("Remote NumLock state is incorrect, deactivating NumLock.\n"));
465                    }
466    
467                    rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0);
468                    update_modifier_state(SCANCODE_CHAR_NUMLOCK, True);
469            }
470    }
471    
472    
473    void
474    reset_modifier_keys(unsigned int state)
475    {
476            /* reset keys */
477            uint32 ev_time;
478            ev_time = time(NULL);
479    
480            if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask) && !get_key_state(state, XK_Shift_L))
481                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
482    
483            if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask) && !get_key_state(state, XK_Shift_R))
484                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
485    
486            if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask) && !get_key_state(state, XK_Control_L))
487                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
488    
489            if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask) && !get_key_state(state, XK_Control_R))
490                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
491    
492            if (MASK_HAS_BITS(remote_modifier_state, MapLeftAltMask) && !get_key_state(state, XK_Alt_L))
493                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
494    
495            if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) &&
496                !get_key_state(state, XK_Alt_R) && !get_key_state(state, XK_Mode_switch))
497                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
498    }
499    
500    
501    static void
502    update_modifier_state(uint8 scancode, BOOL pressed)
503    {
504    #ifdef WITH_DEBUG_KBD
505            uint16 old_modifier_state;
506    
507            old_modifier_state = remote_modifier_state;
508    #endif
509    
510            switch (scancode)
511            {
512                    case SCANCODE_CHAR_LSHIFT:
513                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftShiftMask, pressed);
514                            break;
515                    case SCANCODE_CHAR_RSHIFT:
516                            MASK_CHANGE_BIT(remote_modifier_state, MapRightShiftMask, pressed);
517                            break;
518                    case SCANCODE_CHAR_LCTRL:
519                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftCtrlMask, pressed);
520                            break;
521                    case SCANCODE_CHAR_RCTRL:
522                            MASK_CHANGE_BIT(remote_modifier_state, MapRightCtrlMask, pressed);
523                            break;
524                    case SCANCODE_CHAR_LALT:
525                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftAltMask, pressed);
526                            break;
527                    case SCANCODE_CHAR_RALT:
528                            MASK_CHANGE_BIT(remote_modifier_state, MapRightAltMask, pressed);
529                            break;
530                    case SCANCODE_CHAR_LWIN:
531                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftWinMask, pressed);
532                            break;
533                    case SCANCODE_CHAR_RWIN:
534                            MASK_CHANGE_BIT(remote_modifier_state, MapRightWinMask, pressed);
535                            break;
536                    case SCANCODE_CHAR_NUMLOCK:
537                            /* KeyReleases for NumLocks are sent immediately. Toggle the
538                               modifier state only on Keypress */
539                            if (pressed)
540                            {
541                                    BOOL newNumLockState;
542                                    newNumLockState =
543                                            (MASK_HAS_BITS
544                                             (remote_modifier_state, MapNumLockMask) == False);
545                                    MASK_CHANGE_BIT(remote_modifier_state,
546                                                    MapNumLockMask, newNumLockState);
547                            }
548                            break;
549            }
550    
551    #ifdef WITH_DEBUG_KBD
552            if (old_modifier_state != remote_modifier_state)
553            {
554                    DEBUG_KBD(("Before updating modifier_state:0x%x, pressed=0x%x\n",
555                               old_modifier_state, pressed));
556                    DEBUG_KBD(("After updating modifier_state:0x%x\n", remote_modifier_state));
557            }
558    #endif
559    
560    }
561    
562    /* Send keyboard input */
563    void
564    rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode)
565    {
566            update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));
567    
568            if (scancode & SCANCODE_EXTENDED)
569            {
570                    DEBUG_KBD(("Sending extended scancode=0x%x, flags=0x%x\n",
571                               scancode & ~SCANCODE_EXTENDED, flags));
572                    rdp_send_input(time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,
573                                   scancode & ~SCANCODE_EXTENDED, 0);
574            }
575            else
576            {
577                    DEBUG_KBD(("Sending scancode=0x%x, flags=0x%x\n", scancode, flags));
578                    rdp_send_input(time, RDP_INPUT_SCANCODE, flags, scancode, 0);
579            }
580    }

Legend:
Removed from v.64  
changed lines
  Added in v.203

  ViewVC Help
Powered by ViewVC 1.1.26