/[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 466 - (hide annotations)
Mon Sep 8 08:27:57 2003 UTC (20 years, 8 months ago) by astrand
File MIME type: text/plain
File size: 16369 byte(s)
Added my copyright

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

  ViewVC Help
Powered by ViewVC 1.1.26