/[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 216 - (hide annotations)
Tue Oct 8 02:30:20 2002 UTC (21 years, 7 months ago) by matthewc
File MIME type: text/plain
File size: 14948 byte(s)
Also look for keymaps in keymaps/%s so that rdesktop can be run "in place"
without installation... I find this useful for testing and it might avoid
some user complaints as well.

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 matthewc 38
218     if (strcmp(keymapname, "none"))
219 matthewc 205 {
220     if (xkeymap_read(keymapname))
221     keymap_loaded = True;
222     }
223 astrand 66
224 astrand 77 XDisplayKeycodes(display, &min_keycode, (int *) &max_keycode);
225 astrand 66 }
226 matthewc 38
227 astrand 118 /* Handles, for example, multi-scancode keypresses (which is not
228     possible via keymap-files) */
229     BOOL
230 matthewc 203 handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)
231 astrand 118 {
232     switch (keysym)
233     {
234 astrand 199 case XK_Break:
235 matthewc 212 case XK_Pause:
236     if ((get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R))
237     && (get_key_state(state, XK_Control_L) || get_key_state(state, XK_Control_R)))
238 astrand 118 {
239 matthewc 212 /* Ctrl-Alt-Break: toggle full screen */
240 matthewc 193 if (pressed)
241     xwin_toggle_fullscreen();
242 astrand 199
243 astrand 118 }
244 matthewc 212 else if (keysym == XK_Break)
245 astrand 199 {
246     /* Send Break sequence E0 46 E0 C6 */
247     if (pressed)
248     {
249     rdp_send_scancode(ev_time, RDP_KEYPRESS,
250     (SCANCODE_EXTENDED | 0x46));
251     rdp_send_scancode(ev_time, RDP_KEYPRESS,
252     (SCANCODE_EXTENDED | 0xc6));
253     }
254     /* No break sequence */
255     }
256 matthewc 212 else /* XK_Pause */
257 astrand 197 {
258 matthewc 212 /* According to MS Keyboard Scan Code
259     Specification, pressing Pause should result
260     in E1 1D 45 E1 9D C5. I'm not exactly sure
261     of how this is supposed to be sent via
262     RDP. The code below seems to work, but with
263     the side effect that Left Ctrl stays
264     down. Therefore, we release it when Pause
265     is released. */
266     if (pressed)
267     {
268     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
269     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0);
270     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x45, 0);
271     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
272     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x9d, 0);
273     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xc5, 0);
274     }
275     else
276     {
277     /* Release Left Ctrl */
278     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x1d,
279     0);
280     }
281 astrand 197 }
282     return True;
283    
284 astrand 118 case XK_Meta_L: /* Windows keys */
285     case XK_Super_L:
286     case XK_Hyper_L:
287     case XK_Meta_R:
288     case XK_Super_R:
289     case XK_Hyper_R:
290     if (pressed)
291     {
292     rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LCTRL);
293     rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_ESC);
294     }
295     else
296     {
297     rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_ESC);
298     rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
299     }
300     return True;
301     }
302     return False;
303     }
304    
305    
306 astrand 66 key_translation
307 matthewc 190 xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state)
308 astrand 66 {
309     key_translation tr = { 0, 0 };
310    
311     tr = keymap[keysym & KEYMAP_MASK];
312    
313 astrand 116 if (tr.modifiers & MapInhibitMask)
314     {
315     DEBUG_KBD(("Inhibiting key\n"));
316     tr.scancode = 0;
317     return tr;
318     }
319    
320 astrand 69 if (tr.modifiers & MapLocalStateMask)
321     {
322     /* The modifiers to send for this key should be obtained
323     from the local state. Currently, only shift is implemented. */
324     if (state & ShiftMask)
325     {
326     tr.modifiers = MapLeftShiftMask;
327     }
328     }
329    
330 astrand 66 if (tr.scancode != 0)
331 matthewc 50 {
332 matthewc 190 DEBUG_KBD(("Found key translation, scancode=0x%x, modifiers=0x%x\n",
333 astrand 197 tr.scancode, tr.modifiers));
334 astrand 66 return tr;
335 matthewc 50 }
336    
337 matthewc 205 if (keymap_loaded)
338     error("No translation for (keysym 0x%lx, %s)\n", keysym, get_ksname(keysym));
339 astrand 66
340 matthewc 38 /* not in keymap, try to interpret the raw scancode */
341     if ((keycode >= min_keycode) && (keycode <= 0x60))
342     {
343 astrand 66 tr.scancode = keycode - min_keycode;
344 astrand 165
345     /* The modifiers to send for this key should be
346     obtained from the local state. Currently, only
347     shift is implemented. */
348     if (state & ShiftMask)
349     {
350     tr.modifiers = MapLeftShiftMask;
351     }
352    
353 matthewc 190 DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));
354 matthewc 38 }
355 astrand 66 else
356     {
357 matthewc 190 DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));
358 astrand 66 }
359 matthewc 38
360 astrand 66 return tr;
361 matthewc 38 }
362    
363 astrand 64 uint16
364     xkeymap_translate_button(unsigned int button)
365 matthewc 38 {
366     switch (button)
367     {
368 astrand 64 case Button1: /* left */
369 matthewc 38 return MOUSE_FLAG_BUTTON1;
370 astrand 64 case Button2: /* middle */
371 matthewc 38 return MOUSE_FLAG_BUTTON3;
372 astrand 64 case Button3: /* right */
373 matthewc 38 return MOUSE_FLAG_BUTTON2;
374 jsorg71 67 case Button4: /* wheel up */
375     return MOUSE_FLAG_BUTTON4;
376     case Button5: /* wheel down */
377     return MOUSE_FLAG_BUTTON5;
378 matthewc 38 }
379    
380     return 0;
381     }
382 astrand 66
383     char *
384 matthewc 190 get_ksname(uint32 keysym)
385 astrand 66 {
386     char *ksname = NULL;
387    
388     if (keysym == NoSymbol)
389     ksname = "NoSymbol";
390     else if (!(ksname = XKeysymToString(keysym)))
391     ksname = "(no name)";
392    
393     return ksname;
394     }
395    
396    
397     void
398     ensure_remote_modifiers(uint32 ev_time, key_translation tr)
399     {
400     /* If this key is a modifier, do nothing */
401     switch (tr.scancode)
402     {
403     case SCANCODE_CHAR_LSHIFT:
404     case SCANCODE_CHAR_RSHIFT:
405     case SCANCODE_CHAR_LCTRL:
406     case SCANCODE_CHAR_RCTRL:
407     case SCANCODE_CHAR_LALT:
408     case SCANCODE_CHAR_RALT:
409     case SCANCODE_CHAR_LWIN:
410     case SCANCODE_CHAR_RWIN:
411     case SCANCODE_CHAR_NUMLOCK:
412     return;
413     default:
414     break;
415     }
416    
417 astrand 183 /* Shift. Left shift and right shift are treated as equal; either is fine. */
418 astrand 66 if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
419     != MASK_HAS_BITS(remote_modifier_state, MapShiftMask))
420     {
421     /* The remote modifier state is not correct */
422 astrand 183 if (MASK_HAS_BITS(tr.modifiers, MapLeftShiftMask))
423 astrand 66 {
424 astrand 183 /* Needs left shift. Send down. */
425 astrand 82 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LSHIFT);
426 astrand 66 }
427 astrand 183 else if (MASK_HAS_BITS(tr.modifiers, MapRightShiftMask))
428     {
429     /* Needs right shift. Send down. */
430     rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RSHIFT);
431     }
432 astrand 66 else
433     {
434 astrand 183 /* Should not use this modifier. Send up for shift currently pressed. */
435     if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask))
436     /* Left shift is down */
437     rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
438     else
439     /* Right shift is down */
440     rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
441 astrand 66 }
442     }
443    
444     /* AltGr */
445     if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask)
446     != MASK_HAS_BITS(remote_modifier_state, MapAltGrMask))
447     {
448     /* The remote modifier state is not correct */
449     if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask))
450     {
451     /* Needs this modifier. Send down. */
452 astrand 82 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RALT);
453 astrand 66 }
454     else
455     {
456     /* Should not use this modifier. Send up. */
457 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
458 astrand 66 }
459     }
460    
461     /* NumLock */
462     if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)
463     != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask))
464     {
465     /* The remote modifier state is not correct */
466 astrand 115 uint16 new_remote_state = 0;
467    
468 astrand 66 if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask))
469     {
470 astrand 115 DEBUG_KBD(("Remote NumLock state is incorrect, activating NumLock.\n"));
471     new_remote_state |= KBD_FLAG_NUMLOCK;
472 astrand 66 }
473     else
474     {
475 astrand 115 DEBUG_KBD(("Remote NumLock state is incorrect, deactivating NumLock.\n"));
476 astrand 66 }
477 astrand 115
478     rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0);
479     update_modifier_state(SCANCODE_CHAR_NUMLOCK, True);
480 astrand 66 }
481     }
482    
483    
484 astrand 170 void
485 matthewc 203 reset_modifier_keys(unsigned int state)
486 astrand 170 {
487     /* reset keys */
488     uint32 ev_time;
489     ev_time = time(NULL);
490    
491 matthewc 203 if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask) && !get_key_state(state, XK_Shift_L))
492 astrand 170 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
493    
494 matthewc 203 if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask) && !get_key_state(state, XK_Shift_R))
495 astrand 170 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
496    
497 matthewc 203 if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask) && !get_key_state(state, XK_Control_L))
498 astrand 170 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
499    
500 matthewc 203 if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask) && !get_key_state(state, XK_Control_R))
501 astrand 170 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
502    
503 matthewc 203 if (MASK_HAS_BITS(remote_modifier_state, MapLeftAltMask) && !get_key_state(state, XK_Alt_L))
504 astrand 170 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
505    
506     if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) &&
507 matthewc 203 !get_key_state(state, XK_Alt_R) && !get_key_state(state, XK_Mode_switch))
508 astrand 170 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
509     }
510    
511    
512 astrand 66 static void
513 matthewc 203 update_modifier_state(uint8 scancode, BOOL pressed)
514 astrand 66 {
515 astrand 113 #ifdef WITH_DEBUG_KBD
516     uint16 old_modifier_state;
517 astrand 66
518 astrand 113 old_modifier_state = remote_modifier_state;
519     #endif
520    
521 matthewc 203 switch (scancode)
522 astrand 66 {
523     case SCANCODE_CHAR_LSHIFT:
524 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapLeftShiftMask, pressed);
525 astrand 66 break;
526     case SCANCODE_CHAR_RSHIFT:
527 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapRightShiftMask, pressed);
528 astrand 66 break;
529     case SCANCODE_CHAR_LCTRL:
530 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapLeftCtrlMask, pressed);
531 astrand 66 break;
532     case SCANCODE_CHAR_RCTRL:
533 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapRightCtrlMask, pressed);
534 astrand 66 break;
535     case SCANCODE_CHAR_LALT:
536 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapLeftAltMask, pressed);
537 astrand 66 break;
538     case SCANCODE_CHAR_RALT:
539 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapRightAltMask, pressed);
540 astrand 66 break;
541     case SCANCODE_CHAR_LWIN:
542 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapLeftWinMask, pressed);
543 astrand 66 break;
544     case SCANCODE_CHAR_RWIN:
545 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapRightWinMask, pressed);
546 astrand 66 break;
547     case SCANCODE_CHAR_NUMLOCK:
548     /* KeyReleases for NumLocks are sent immediately. Toggle the
549     modifier state only on Keypress */
550     if (pressed)
551     {
552     BOOL newNumLockState;
553     newNumLockState =
554     (MASK_HAS_BITS
555 astrand 82 (remote_modifier_state, MapNumLockMask) == False);
556 astrand 66 MASK_CHANGE_BIT(remote_modifier_state,
557 astrand 82 MapNumLockMask, newNumLockState);
558 astrand 66 }
559     break;
560     }
561    
562 astrand 113 #ifdef WITH_DEBUG_KBD
563     if (old_modifier_state != remote_modifier_state)
564     {
565     DEBUG_KBD(("Before updating modifier_state:0x%x, pressed=0x%x\n",
566     old_modifier_state, pressed));
567     DEBUG_KBD(("After updating modifier_state:0x%x\n", remote_modifier_state));
568     }
569     #endif
570    
571 astrand 66 }
572    
573     /* Send keyboard input */
574     void
575 matthewc 203 rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode)
576 astrand 66 {
577     update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));
578    
579     if (scancode & SCANCODE_EXTENDED)
580     {
581 astrand 84 DEBUG_KBD(("Sending extended scancode=0x%x, flags=0x%x\n",
582     scancode & ~SCANCODE_EXTENDED, flags));
583 astrand 66 rdp_send_input(time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,
584     scancode & ~SCANCODE_EXTENDED, 0);
585     }
586     else
587     {
588 astrand 85 DEBUG_KBD(("Sending scancode=0x%x, flags=0x%x\n", scancode, flags));
589     rdp_send_input(time, RDP_INPUT_SCANCODE, flags, scancode, 0);
590 astrand 66 }
591     }

  ViewVC Help
Powered by ViewVC 1.1.26