/[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 452 - (hide annotations)
Sun Aug 31 19:45:56 2003 UTC (20 years, 8 months ago) by astrand
File MIME type: text/plain
File size: 16314 byte(s)
Support for (real) Windows keys, if running RDP5.

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

  ViewVC Help
Powered by ViewVC 1.1.26