/[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 955 - (show annotations)
Wed Aug 3 07:08:17 2005 UTC (18 years, 9 months ago) by astrand
File MIME type: text/plain
File size: 21093 byte(s)
free_key_translation should be static.

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 static 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 /* Handle special key combinations */
383 BOOL
384 handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)
385 {
386 switch (keysym)
387 {
388 case XK_Return:
389 if ((get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R))
390 && (get_key_state(state, XK_Control_L)
391 || get_key_state(state, XK_Control_R)))
392 {
393 /* Ctrl-Alt-Enter: toggle full screen */
394 if (pressed)
395 xwin_toggle_fullscreen();
396 return True;
397 }
398 break;
399
400 case XK_Break:
401 /* Send Break sequence E0 46 E0 C6 */
402 if (pressed)
403 {
404 rdp_send_scancode(ev_time, RDP_KEYPRESS,
405 (SCANCODE_EXTENDED | 0x46));
406 rdp_send_scancode(ev_time, RDP_KEYPRESS,
407 (SCANCODE_EXTENDED | 0xc6));
408 }
409 /* No release sequence */
410 return True;
411 break;
412
413 case XK_Pause:
414 /* According to MS Keyboard Scan Code
415 Specification, pressing Pause should result
416 in E1 1D 45 E1 9D C5. I'm not exactly sure
417 of how this is supposed to be sent via
418 RDP. The code below seems to work, but with
419 the side effect that Left Ctrl stays
420 down. Therefore, we release it when Pause
421 is released. */
422 if (pressed)
423 {
424 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
425 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0);
426 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x45, 0);
427 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
428 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x9d, 0);
429 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xc5, 0);
430 }
431 else
432 {
433 /* Release Left Ctrl */
434 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYRELEASE,
435 0x1d, 0);
436 }
437 return True;
438 break;
439
440 case XK_Meta_L: /* Windows keys */
441 case XK_Super_L:
442 case XK_Hyper_L:
443 send_winkey(ev_time, pressed, True);
444 return True;
445 break;
446
447 case XK_Meta_R:
448 case XK_Super_R:
449 case XK_Hyper_R:
450 send_winkey(ev_time, pressed, False);
451 return True;
452 break;
453
454 case XK_space:
455 /* Prevent access to the Windows system menu in single app mode */
456 if (g_win_button_size
457 && (get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R)))
458 return True;
459 break;
460
461 case XK_Num_Lock:
462 /* Synchronize on key release */
463 if (g_numlock_sync && !pressed)
464 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
465 ui_get_numlock_state(read_keyboard_state()), 0);
466
467 /* Inhibit */
468 return True;
469 break;
470
471 }
472 return False;
473 }
474
475
476 key_translation
477 xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state)
478 {
479 key_translation tr = { 0, 0, 0, 0 };
480 key_translation *ptr;
481
482 ptr = keymap[keysym & KEYMAP_MASK];
483 if (ptr)
484 {
485 tr = *ptr;
486 if (tr.seq_keysym == 0) /* Normal scancode translation */
487 {
488 if (tr.modifiers & MapInhibitMask)
489 {
490 DEBUG_KBD(("Inhibiting key\n"));
491 tr.scancode = 0;
492 return tr;
493 }
494
495 if (tr.modifiers & MapLocalStateMask)
496 {
497 /* The modifiers to send for this key should be obtained
498 from the local state. Currently, only shift is implemented. */
499 if (state & ShiftMask)
500 {
501 tr.modifiers = MapLeftShiftMask;
502 }
503 }
504
505 if ((tr.modifiers & MapLeftShiftMask)
506 && ((remote_modifier_state & MapLeftCtrlMask)
507 || (remote_modifier_state & MapRightCtrlMask))
508 && get_key_state(state, XK_Caps_Lock))
509 {
510 DEBUG_KBD(("CapsLock + Ctrl pressed, releasing LeftShift\n"));
511 tr.modifiers ^= MapLeftShiftMask;
512 }
513
514 DEBUG_KBD(("Found scancode translation, scancode=0x%x, modifiers=0x%x\n",
515 tr.scancode, tr.modifiers));
516 }
517 }
518 else
519 {
520 if (keymap_loaded)
521 warning("No translation for (keysym 0x%lx, %s)\n", keysym,
522 get_ksname(keysym));
523
524 /* not in keymap, try to interpret the raw scancode */
525 if (((int) keycode >= min_keycode) && (keycode <= 0x60))
526 {
527 tr.scancode = keycode - min_keycode;
528
529 /* The modifiers to send for this key should be
530 obtained from the local state. Currently, only
531 shift is implemented. */
532 if (state & ShiftMask)
533 {
534 tr.modifiers = MapLeftShiftMask;
535 }
536
537 DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));
538 }
539 else
540 {
541 DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));
542 }
543 }
544
545 return tr;
546 }
547
548 void
549 xkeymap_send_keys(uint32 keysym, unsigned int keycode, unsigned int state, uint32 ev_time,
550 BOOL pressed)
551 {
552 key_translation tr, *ptr;
553 tr = xkeymap_translate_key(keysym, keycode, state);
554
555 if (tr.seq_keysym == 0)
556 {
557 /* Scancode translation */
558 if (tr.scancode == 0)
559 return;
560
561 if (pressed)
562 {
563 save_remote_modifiers(tr.scancode);
564 ensure_remote_modifiers(ev_time, tr);
565 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
566 restore_remote_modifiers(ev_time, tr.scancode);
567 }
568 else
569 {
570 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
571 }
572 return;
573 }
574
575 /* Sequence, only on key down */
576 if (pressed)
577 {
578 ptr = &tr;
579 do
580 {
581 DEBUG_KBD(("Handling sequence element, keysym=0x%x\n",
582 (unsigned int) ptr->seq_keysym));
583 xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, True);
584 xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, False);
585 ptr = ptr->next;
586 }
587 while (ptr);
588 }
589 }
590
591 uint16
592 xkeymap_translate_button(unsigned int button)
593 {
594 switch (button)
595 {
596 case Button1: /* left */
597 return MOUSE_FLAG_BUTTON1;
598 case Button2: /* middle */
599 return MOUSE_FLAG_BUTTON3;
600 case Button3: /* right */
601 return MOUSE_FLAG_BUTTON2;
602 case Button4: /* wheel up */
603 return MOUSE_FLAG_BUTTON4;
604 case Button5: /* wheel down */
605 return MOUSE_FLAG_BUTTON5;
606 }
607
608 return 0;
609 }
610
611 char *
612 get_ksname(uint32 keysym)
613 {
614 char *ksname = NULL;
615
616 if (keysym == NoSymbol)
617 ksname = "NoSymbol";
618 else if (!(ksname = XKeysymToString(keysym)))
619 ksname = "(no name)";
620
621 return ksname;
622 }
623
624 static BOOL
625 is_modifier(uint8 scancode)
626 {
627 switch (scancode)
628 {
629 case SCANCODE_CHAR_LSHIFT:
630 case SCANCODE_CHAR_RSHIFT:
631 case SCANCODE_CHAR_LCTRL:
632 case SCANCODE_CHAR_RCTRL:
633 case SCANCODE_CHAR_LALT:
634 case SCANCODE_CHAR_RALT:
635 case SCANCODE_CHAR_LWIN:
636 case SCANCODE_CHAR_RWIN:
637 case SCANCODE_CHAR_NUMLOCK:
638 return True;
639 default:
640 break;
641 }
642 return False;
643 }
644
645 void
646 save_remote_modifiers(uint8 scancode)
647 {
648 if (is_modifier(scancode))
649 return;
650
651 saved_remote_modifier_state = remote_modifier_state;
652 }
653
654 void
655 restore_remote_modifiers(uint32 ev_time, uint8 scancode)
656 {
657 key_translation dummy;
658
659 if (is_modifier(scancode))
660 return;
661
662 dummy.scancode = 0;
663 dummy.modifiers = saved_remote_modifier_state;
664 ensure_remote_modifiers(ev_time, dummy);
665 }
666
667 void
668 ensure_remote_modifiers(uint32 ev_time, key_translation tr)
669 {
670 /* If this key is a modifier, do nothing */
671 if (is_modifier(tr.scancode))
672 return;
673
674 if (!g_numlock_sync)
675 {
676 /* NumLock */
677 if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)
678 != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask))
679 {
680 /* The remote modifier state is not correct */
681 uint16 new_remote_state;
682
683 if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask))
684 {
685 DEBUG_KBD(("Remote NumLock state is incorrect, activating NumLock.\n"));
686 new_remote_state = KBD_FLAG_NUMLOCK;
687 remote_modifier_state = MapNumLockMask;
688 }
689 else
690 {
691 DEBUG_KBD(("Remote NumLock state is incorrect, deactivating NumLock.\n"));
692 new_remote_state = 0;
693 remote_modifier_state = 0;
694 }
695
696 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0);
697 }
698 }
699
700
701 /* Shift. Left shift and right shift are treated as equal; either is fine. */
702 if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
703 != MASK_HAS_BITS(remote_modifier_state, MapShiftMask))
704 {
705 /* The remote modifier state is not correct */
706 if (MASK_HAS_BITS(tr.modifiers, MapLeftShiftMask))
707 {
708 /* Needs left shift. Send down. */
709 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LSHIFT);
710 }
711 else if (MASK_HAS_BITS(tr.modifiers, MapRightShiftMask))
712 {
713 /* Needs right shift. Send down. */
714 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RSHIFT);
715 }
716 else
717 {
718 /* Should not use this modifier. Send up for shift currently pressed. */
719 if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask))
720 /* Left shift is down */
721 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
722 else
723 /* Right shift is down */
724 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
725 }
726 }
727
728 /* AltGr */
729 if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask)
730 != MASK_HAS_BITS(remote_modifier_state, MapAltGrMask))
731 {
732 /* The remote modifier state is not correct */
733 if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask))
734 {
735 /* Needs this modifier. Send down. */
736 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RALT);
737 }
738 else
739 {
740 /* Should not use this modifier. Send up. */
741 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
742 }
743 }
744
745
746 }
747
748
749 unsigned int
750 read_keyboard_state()
751 {
752 #ifdef RDP2VNC
753 return 0;
754 #else
755 unsigned int state;
756 Window wdummy;
757 int dummy;
758
759 XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
760 return state;
761 #endif
762 }
763
764
765 uint16
766 ui_get_numlock_state(unsigned int state)
767 {
768 uint16 numlock_state = 0;
769
770 if (get_key_state(state, XK_Num_Lock))
771 numlock_state = KBD_FLAG_NUMLOCK;
772
773 return numlock_state;
774 }
775
776
777 void
778 reset_modifier_keys()
779 {
780 unsigned int state = read_keyboard_state();
781
782 /* reset keys */
783 uint32 ev_time;
784 ev_time = time(NULL);
785
786 if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask)
787 && !get_key_state(state, XK_Shift_L))
788 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
789
790 if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask)
791 && !get_key_state(state, XK_Shift_R))
792 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
793
794 if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask)
795 && !get_key_state(state, XK_Control_L))
796 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
797
798 if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask)
799 && !get_key_state(state, XK_Control_R))
800 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
801
802 if (MASK_HAS_BITS(remote_modifier_state, MapLeftAltMask) && !get_key_state(state, XK_Alt_L))
803 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
804
805 if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) &&
806 !get_key_state(state, XK_Alt_R) && !get_key_state(state, XK_Mode_switch)
807 && !get_key_state(state, XK_ISO_Level3_Shift))
808 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
809
810 reset_winkey(ev_time);
811
812 if (g_numlock_sync)
813 rdp_send_input(ev_time, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(state), 0);
814 }
815
816
817 static void
818 update_modifier_state(uint8 scancode, BOOL pressed)
819 {
820 #ifdef WITH_DEBUG_KBD
821 uint16 old_modifier_state;
822
823 old_modifier_state = remote_modifier_state;
824 #endif
825
826 switch (scancode)
827 {
828 case SCANCODE_CHAR_LSHIFT:
829 MASK_CHANGE_BIT(remote_modifier_state, MapLeftShiftMask, pressed);
830 break;
831 case SCANCODE_CHAR_RSHIFT:
832 MASK_CHANGE_BIT(remote_modifier_state, MapRightShiftMask, pressed);
833 break;
834 case SCANCODE_CHAR_LCTRL:
835 MASK_CHANGE_BIT(remote_modifier_state, MapLeftCtrlMask, pressed);
836 break;
837 case SCANCODE_CHAR_RCTRL:
838 MASK_CHANGE_BIT(remote_modifier_state, MapRightCtrlMask, pressed);
839 break;
840 case SCANCODE_CHAR_LALT:
841 MASK_CHANGE_BIT(remote_modifier_state, MapLeftAltMask, pressed);
842 break;
843 case SCANCODE_CHAR_RALT:
844 MASK_CHANGE_BIT(remote_modifier_state, MapRightAltMask, pressed);
845 break;
846 case SCANCODE_CHAR_LWIN:
847 MASK_CHANGE_BIT(remote_modifier_state, MapLeftWinMask, pressed);
848 break;
849 case SCANCODE_CHAR_RWIN:
850 MASK_CHANGE_BIT(remote_modifier_state, MapRightWinMask, pressed);
851 break;
852 case SCANCODE_CHAR_NUMLOCK:
853 /* KeyReleases for NumLocks are sent immediately. Toggle the
854 modifier state only on Keypress */
855 if (pressed && !g_numlock_sync)
856 {
857 BOOL newNumLockState;
858 newNumLockState =
859 (MASK_HAS_BITS
860 (remote_modifier_state, MapNumLockMask) == False);
861 MASK_CHANGE_BIT(remote_modifier_state,
862 MapNumLockMask, newNumLockState);
863 }
864 }
865
866 #ifdef WITH_DEBUG_KBD
867 if (old_modifier_state != remote_modifier_state)
868 {
869 DEBUG_KBD(("Before updating modifier_state:0x%x, pressed=0x%x\n",
870 old_modifier_state, pressed));
871 DEBUG_KBD(("After updating modifier_state:0x%x\n", remote_modifier_state));
872 }
873 #endif
874
875 }
876
877 /* Send keyboard input */
878 void
879 rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode)
880 {
881 update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));
882
883 if (scancode & SCANCODE_EXTENDED)
884 {
885 DEBUG_KBD(("Sending extended scancode=0x%x, flags=0x%x\n",
886 scancode & ~SCANCODE_EXTENDED, flags));
887 rdp_send_input(time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,
888 scancode & ~SCANCODE_EXTENDED, 0);
889 }
890 else
891 {
892 DEBUG_KBD(("Sending scancode=0x%x, flags=0x%x\n", scancode, flags));
893 rdp_send_input(time, RDP_INPUT_SCANCODE, flags, scancode, 0);
894 }
895 }

  ViewVC Help
Powered by ViewVC 1.1.26