/[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 961 - (hide annotations)
Wed Aug 3 09:32:22 2005 UTC (18 years, 10 months ago) by astrand
File MIME type: text/plain
File size: 21661 byte(s)
The keymap names are now case sensitive, since the -k argument now specifies a file name.

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

  ViewVC Help
Powered by ViewVC 1.1.26