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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 951 - (show annotations)
Tue Aug 2 18:07:56 2005 UTC (18 years, 10 months ago) by astrand
File MIME type: text/plain
File size: 21146 byte(s)
Free mem before assigning new objects to keymap.

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

  ViewVC Help
Powered by ViewVC 1.1.26