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

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 951 /* Free key_translation structure, included 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 64 static BOOL
159     xkeymap_read(char *mapname)
160 matthewc 38 {
161     FILE *fp;
162 matthewc 216 char line[KEYMAP_MAX_LINE_LENGTH];
163     char path[PATH_MAX], inplace_path[PATH_MAX];
164 astrand 66 unsigned int line_num = 0;
165     unsigned int line_length = 0;
166 matthewc 38 char *keyname, *p;
167 astrand 66 char *line_rest;
168     uint8 scancode;
169     uint16 modifiers;
170 matthewc 38
171 astrand 66
172 matthewc 38 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 matthewc 216 /* 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 matthewc 38 }
189    
190 astrand 66 /* FIXME: More tolerant on white space */
191 matthewc 38 while (fgets(line, sizeof(line), fp) != NULL)
192     {
193 astrand 66 line_num++;
194    
195     /* Replace the \n with \0 */
196 matthewc 38 p = strchr(line, '\n');
197     if (p != NULL)
198     *p = 0;
199    
200 astrand 66 line_length = strlen(line);
201    
202     /* Completely empty line */
203     if (strspn(line, " \t\n\r\f\v") == line_length)
204 matthewc 38 {
205 astrand 66 continue;
206     }
207 matthewc 38
208 astrand 66 /* Include */
209     if (strncmp(line, "include ", 8) == 0)
210 matthewc 38 {
211 astrand 64 if (!xkeymap_read(line + 8))
212 matthewc 38 return False;
213 astrand 66 continue;
214 matthewc 38 }
215 astrand 66
216     /* map */
217     if (strncmp(line, "map ", 4) == 0)
218 matthewc 38 {
219 jsorg71 710 g_keylayout = strtol(line + 4, NULL, 16);
220     DEBUG_KBD(("Keylayout 0x%x\n", g_keylayout));
221 astrand 66 continue;
222 matthewc 38 }
223 astrand 66
224 astrand 70 /* compose */
225     if (strncmp(line, "enable_compose", 15) == 0)
226     {
227 astrand 84 DEBUG_KBD(("Enabling compose handling\n"));
228 jsorg71 447 g_enable_compose = True;
229 astrand 70 continue;
230     }
231    
232 astrand 949 /* sequence */
233     if (strncmp(line, "sequence", 8) == 0)
234     {
235     add_sequence(line + 8, mapname);
236     continue;
237     }
238    
239 astrand 66 /* Comment */
240     if (line[0] == '#')
241 matthewc 38 {
242 astrand 66 continue;
243 matthewc 38 }
244 astrand 66
245     /* Normal line */
246     keyname = line;
247     p = strchr(line, ' ');
248     if (p == NULL)
249     {
250 astrand 82 error("Bad line %d in keymap %s\n", line_num, mapname);
251 astrand 66 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 astrand 552 if (strstr(line_rest, "numlock"))
277     {
278     MASK_ADD_BITS(modifiers, MapNumLockMask);
279     }
280    
281 astrand 69 if (strstr(line_rest, "localstate"))
282     {
283     MASK_ADD_BITS(modifiers, MapLocalStateMask);
284     }
285    
286 astrand 116 if (strstr(line_rest, "inhibit"))
287     {
288     MASK_ADD_BITS(modifiers, MapInhibitMask);
289     }
290    
291 astrand 66 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 astrand 318 *p = toupper((int) *p);
299 astrand 66 MASK_ADD_BITS(modifiers, MapLeftShiftMask);
300     add_to_keymap(keyname, scancode, modifiers, mapname);
301     }
302 matthewc 38 }
303    
304     fclose(fp);
305     return True;
306     }
307    
308 astrand 66
309     /* Before connecting and creating UI */
310 astrand 64 void
311 matthewc 121 xkeymap_init(void)
312 matthewc 38 {
313 matthewc 121 unsigned int max_keycode;
314 astrand 225 char *mapname_ptr;
315 matthewc 38
316 astrand 225 /* Make keymapname lowercase */
317     mapname_ptr = keymapname;
318 astrand 226 while (*mapname_ptr)
319 astrand 227 {
320 astrand 318 *mapname_ptr = tolower((int) *mapname_ptr);
321 astrand 227 mapname_ptr++;
322     }
323 astrand 225
324 matthewc 38 if (strcmp(keymapname, "none"))
325 matthewc 205 {
326     if (xkeymap_read(keymapname))
327     keymap_loaded = True;
328     }
329 astrand 66
330 jsorg71 450 XDisplayKeycodes(g_display, &min_keycode, (int *) &max_keycode);
331 astrand 66 }
332 matthewc 38
333 astrand 452 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 astrand 548 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 astrand 952 /* Handle special key combinations */
383 astrand 118 BOOL
384 matthewc 203 handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)
385 astrand 118 {
386     switch (keysym)
387     {
388 matthewc 244 case XK_Return:
389 matthewc 212 if ((get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R))
390 astrand 226 && (get_key_state(state, XK_Control_L)
391     || get_key_state(state, XK_Control_R)))
392 astrand 118 {
393 matthewc 244 /* Ctrl-Alt-Enter: toggle full screen */
394 matthewc 193 if (pressed)
395     xwin_toggle_fullscreen();
396 matthewc 244 return True;
397     }
398     break;
399 astrand 199
400 matthewc 244 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 astrand 118 }
409 matthewc 244 /* No release sequence */
410     return True;
411 astrand 553 break;
412 matthewc 244
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 astrand 199 {
424 astrand 260 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 astrand 199 }
431 matthewc 244 else
432 astrand 197 {
433 matthewc 244 /* Release Left Ctrl */
434     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYRELEASE,
435     0x1d, 0);
436 astrand 197 }
437     return True;
438 astrand 553 break;
439 astrand 197
440 astrand 118 case XK_Meta_L: /* Windows keys */
441     case XK_Super_L:
442     case XK_Hyper_L:
443 astrand 452 send_winkey(ev_time, pressed, True);
444     return True;
445 astrand 553 break;
446 astrand 452
447 astrand 118 case XK_Meta_R:
448     case XK_Super_R:
449     case XK_Hyper_R:
450 astrand 452 send_winkey(ev_time, pressed, False);
451 astrand 118 return True;
452 astrand 553 break;
453 astrand 331
454     case XK_space:
455     /* Prevent access to the Windows system menu in single app mode */
456 jsorg71 450 if (g_win_button_size
457 astrand 331 && (get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R)))
458     return True;
459 astrand 553 break;
460 astrand 910
461 astrand 552 case XK_Num_Lock:
462 astrand 910 /* 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 astrand 553 break;
470 astrand 331
471 astrand 118 }
472     return False;
473     }
474    
475    
476 astrand 66 key_translation
477 matthewc 190 xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state)
478 astrand 66 {
479 astrand 949 key_translation tr = { 0, 0, 0, 0 };
480     key_translation *ptr;
481 astrand 66
482 astrand 949 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 astrand 66
495 astrand 949 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 astrand 116 {
520 astrand 949 if (keymap_loaded)
521     warning("No translation for (keysym 0x%lx, %s)\n", keysym,
522     get_ksname(keysym));
523 astrand 116
524 astrand 949 /* not in keymap, try to interpret the raw scancode */
525     if (((int) keycode >= min_keycode) && (keycode <= 0x60))
526 astrand 69 {
527 astrand 949 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 astrand 69 }
539 astrand 949 else
540     {
541     DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));
542     }
543 astrand 69 }
544    
545 astrand 949 return tr;
546     }
547 stargo 810
548 astrand 949 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 matthewc 50
555 astrand 949 if (tr.seq_keysym == 0)
556 matthewc 38 {
557 astrand 949 /* Scancode translation */
558     if (tr.scancode == 0)
559     return;
560 astrand 165
561 astrand 949 if (pressed)
562 astrand 165 {
563 astrand 949 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 astrand 165 }
568 astrand 949 else
569     {
570     rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
571     }
572     return;
573     }
574 astrand 165
575 astrand 949 /* Sequence, only on key down */
576     if (pressed)
577 astrand 66 {
578 astrand 949 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 astrand 66 }
589 matthewc 38 }
590    
591 astrand 64 uint16
592     xkeymap_translate_button(unsigned int button)
593 matthewc 38 {
594     switch (button)
595     {
596 astrand 64 case Button1: /* left */
597 matthewc 38 return MOUSE_FLAG_BUTTON1;
598 astrand 64 case Button2: /* middle */
599 matthewc 38 return MOUSE_FLAG_BUTTON3;
600 astrand 64 case Button3: /* right */
601 matthewc 38 return MOUSE_FLAG_BUTTON2;
602 jsorg71 67 case Button4: /* wheel up */
603     return MOUSE_FLAG_BUTTON4;
604     case Button5: /* wheel down */
605     return MOUSE_FLAG_BUTTON5;
606 matthewc 38 }
607    
608     return 0;
609     }
610 astrand 66
611     char *
612 matthewc 190 get_ksname(uint32 keysym)
613 astrand 66 {
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 astrand 470 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 astrand 449 void
646 astrand 470 save_remote_modifiers(uint8 scancode)
647 astrand 449 {
648 astrand 470 if (is_modifier(scancode))
649     return;
650    
651 astrand 449 saved_remote_modifier_state = remote_modifier_state;
652     }
653 astrand 66
654     void
655 astrand 470 restore_remote_modifiers(uint32 ev_time, uint8 scancode)
656 astrand 449 {
657     key_translation dummy;
658    
659 astrand 470 if (is_modifier(scancode))
660     return;
661    
662 astrand 449 dummy.scancode = 0;
663     dummy.modifiers = saved_remote_modifier_state;
664     ensure_remote_modifiers(ev_time, dummy);
665     }
666    
667     void
668 astrand 66 ensure_remote_modifiers(uint32 ev_time, key_translation tr)
669     {
670     /* If this key is a modifier, do nothing */
671 astrand 470 if (is_modifier(tr.scancode))
672     return;
673 astrand 66
674 astrand 552 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 astrand 183 /* Shift. Left shift and right shift are treated as equal; either is fine. */
702 astrand 66 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 astrand 183 if (MASK_HAS_BITS(tr.modifiers, MapLeftShiftMask))
707 astrand 66 {
708 astrand 183 /* Needs left shift. Send down. */
709 astrand 82 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LSHIFT);
710 astrand 66 }
711 astrand 183 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 astrand 66 else
717     {
718 astrand 183 /* 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 astrand 66 }
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 astrand 82 rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RALT);
737 astrand 66 }
738     else
739     {
740     /* Should not use this modifier. Send up. */
741 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
742 astrand 66 }
743     }
744    
745 astrand 115
746 astrand 66 }
747    
748    
749 astrand 543 unsigned int
750     read_keyboard_state()
751     {
752 stargo 648 #ifdef RDP2VNC
753     return 0;
754     #else
755 astrand 543 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 stargo 648 #endif
762 astrand 543 }
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 astrand 170 void
778 astrand 543 reset_modifier_keys()
779 astrand 170 {
780 astrand 543 unsigned int state = read_keyboard_state();
781    
782 astrand 170 /* reset keys */
783     uint32 ev_time;
784     ev_time = time(NULL);
785    
786 astrand 226 if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask)
787     && !get_key_state(state, XK_Shift_L))
788 astrand 170 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
789    
790 astrand 226 if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask)
791     && !get_key_state(state, XK_Shift_R))
792 astrand 170 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
793    
794 astrand 226 if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask)
795     && !get_key_state(state, XK_Control_L))
796 astrand 170 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
797    
798 astrand 226 if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask)
799     && !get_key_state(state, XK_Control_R))
800 astrand 170 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
801    
802 matthewc 203 if (MASK_HAS_BITS(remote_modifier_state, MapLeftAltMask) && !get_key_state(state, XK_Alt_L))
803 astrand 170 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
804    
805     if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) &&
806 astrand 706 !get_key_state(state, XK_Alt_R) && !get_key_state(state, XK_Mode_switch)
807     && !get_key_state(state, XK_ISO_Level3_Shift))
808 astrand 170 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
809 astrand 543
810 astrand 548 reset_winkey(ev_time);
811    
812 astrand 552 if (g_numlock_sync)
813     rdp_send_input(ev_time, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(state), 0);
814 astrand 170 }
815    
816    
817 astrand 66 static void
818 matthewc 203 update_modifier_state(uint8 scancode, BOOL pressed)
819 astrand 66 {
820 astrand 113 #ifdef WITH_DEBUG_KBD
821     uint16 old_modifier_state;
822 astrand 66
823 astrand 113 old_modifier_state = remote_modifier_state;
824     #endif
825    
826 matthewc 203 switch (scancode)
827 astrand 66 {
828     case SCANCODE_CHAR_LSHIFT:
829 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapLeftShiftMask, pressed);
830 astrand 66 break;
831     case SCANCODE_CHAR_RSHIFT:
832 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapRightShiftMask, pressed);
833 astrand 66 break;
834     case SCANCODE_CHAR_LCTRL:
835 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapLeftCtrlMask, pressed);
836 astrand 66 break;
837     case SCANCODE_CHAR_RCTRL:
838 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapRightCtrlMask, pressed);
839 astrand 66 break;
840     case SCANCODE_CHAR_LALT:
841 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapLeftAltMask, pressed);
842 astrand 66 break;
843     case SCANCODE_CHAR_RALT:
844 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapRightAltMask, pressed);
845 astrand 66 break;
846     case SCANCODE_CHAR_LWIN:
847 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapLeftWinMask, pressed);
848 astrand 66 break;
849     case SCANCODE_CHAR_RWIN:
850 astrand 82 MASK_CHANGE_BIT(remote_modifier_state, MapRightWinMask, pressed);
851 astrand 66 break;
852 astrand 552 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 astrand 66 }
865    
866 astrand 113 #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 astrand 66 }
876    
877     /* Send keyboard input */
878     void
879 matthewc 203 rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode)
880 astrand 66 {
881     update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));
882    
883     if (scancode & SCANCODE_EXTENDED)
884     {
885 astrand 84 DEBUG_KBD(("Sending extended scancode=0x%x, flags=0x%x\n",
886     scancode & ~SCANCODE_EXTENDED, flags));
887 astrand 66 rdp_send_input(time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,
888     scancode & ~SCANCODE_EXTENDED, 0);
889     }
890     else
891     {
892 astrand 85 DEBUG_KBD(("Sending scancode=0x%x, flags=0x%x\n", scancode, flags));
893     rdp_send_input(time, RDP_INPUT_SCANCODE, flags, scancode, 0);
894 astrand 66 }
895     }

  ViewVC Help
Powered by ViewVC 1.1.26