/[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 951 - (hide annotations)
Tue Aug 2 18:07:56 2005 UTC (18 years, 10 months ago) by astrand
File MIME type: text/plain
File size: 21146 byte(s)
Free mem before assigning new objects to keymap.

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

  ViewVC Help
Powered by ViewVC 1.1.26