/[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 960 - (hide annotations)
Wed Aug 3 08:41:02 2005 UTC (18 years, 10 months ago) by astrand
File MIME type: text/plain
File size: 21793 byte(s)
~/.rdesktop/keymaps is now tried before KEYMAP_PATH

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

  ViewVC Help
Powered by ViewVC 1.1.26