/[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 910 - (hide annotations)
Tue Jun 7 11:21:53 2005 UTC (18 years, 11 months ago) by astrand
File MIME type: text/plain
File size: 18139 byte(s)
At XK_Num_Lock events, use RDP_INPUT_SYNCHRONIZE, if using numlock
sync.

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

  ViewVC Help
Powered by ViewVC 1.1.26