/[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

Annotation of /sourceforge.net/trunk/rdesktop/xkeymap.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 225 - (hide annotations)
Fri Oct 11 08:54:08 2002 UTC (21 years, 8 months ago) by astrand
File MIME type: text/plain
File size: 15097 byte(s)
Case-insensitive keymap names.

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

  ViewVC Help
Powered by ViewVC 1.1.26