ReactOS 0.4.15-dev-7834-g00c4b3d
xkeymap.c File Reference
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <ctype.h>
#include <limits.h>
#include <time.h>
#include <string.h>
#include "rdesktop.h"
#include "scancodes.h"
Include dependency graph for xkeymap.c:

Go to the source code of this file.

Macros

#define KEYMAP_MASK   0xffff
 
#define KEYMAP_MAX_LINE_LENGTH   80
 

Functions

static void update_modifier_state (RDPCLIENT *This, uint8 scancode, BOOL pressed)
 
static void free_key_translation (key_translation *ptr)
 
static void add_to_keymap (RDPCLIENT *This, char *keyname, uint8 scancode, uint16 modifiers, char *mapname)
 
static void add_sequence (RDPCLIENT *This, char *rest, char *mapname)
 
BOOL xkeymap_from_locale (RDPCLIENT *This, const char *locale)
 
static charpathjoin (const char *a, const char *b)
 
FILExkeymap_open (const char *filename)
 
static BOOL xkeymap_read (RDPCLIENT *This, char *mapname)
 
void xkeymap_init (RDPCLIENT *This)
 
static void send_winkey (RDPCLIENT *This, uint32 ev_time, BOOL pressed, BOOL leftkey)
 
static void reset_winkey (RDPCLIENT *This, uint32 ev_time)
 
BOOL handle_special_keys (RDPCLIENT *This, uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed)
 
key_translation xkeymap_translate_key (RDPCLIENT *This, uint32 keysym, unsigned int keycode, unsigned int state)
 
void xkeymap_send_keys (RDPCLIENT *This, uint32 keysym, unsigned int keycode, unsigned int state, uint32 ev_time, BOOL pressed, uint8 nesting)
 
uint16 xkeymap_translate_button (unsigned int button)
 
charget_ksname (uint32 keysym)
 
static BOOL is_modifier (uint8 scancode)
 
void save_remote_modifiers (RDPCLIENT *This, uint8 scancode)
 
void restore_remote_modifiers (RDPCLIENT *This, uint32 ev_time, uint8 scancode)
 
void ensure_remote_modifiers (RDPCLIENT *This, uint32 ev_time, key_translation tr)
 
unsigned int read_keyboard_state (RDPCLIENT *This)
 
uint16 ui_get_numlock_state (RDPCLIENT *This, unsigned int state)
 
void reset_modifier_keys (RDPCLIENT *This)
 
void rdp_send_scancode (RDPCLIENT *This, uint32 time, uint16 flags, uint8 scancode)
 

Macro Definition Documentation

◆ KEYMAP_MASK

#define KEYMAP_MASK   0xffff

Definition at line 37 of file xkeymap.c.

◆ KEYMAP_MAX_LINE_LENGTH

#define KEYMAP_MAX_LINE_LENGTH   80

Definition at line 38 of file xkeymap.c.

Function Documentation

◆ add_sequence()

static void add_sequence ( RDPCLIENT This,
char rest,
char mapname 
)
static

Definition at line 83 of file xkeymap.c.

84{
85 KeySym keysym;
86 key_translation *tr, **prev_next;
87 size_t chars;
88 char keyname[KEYMAP_MAX_LINE_LENGTH];
89
90 /* Skip over whitespace after the sequence keyword */
91 chars = strspn(rest, " \t");
92 rest += chars;
93
94 /* Fetch the keysym name */
95 chars = strcspn(rest, " \t\0");
96 STRNCPY(keyname, rest, chars + 1);
97 rest += chars;
98
99 keysym = XStringToKeysym(keyname);
100 if (keysym == NoSymbol)
101 {
102 DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring line)\n", keyname, mapname));
103 return;
104 }
105
106
107 DEBUG_KBD(("Adding sequence for keysym (0x%lx, %s) -> ", keysym, keyname));
108
109 free_key_translation(This->xkeymap.keymap[keysym & KEYMAP_MASK]);
110 prev_next = &This->xkeymap.keymap[keysym & KEYMAP_MASK];
111
112 while (*rest)
113 {
114 /* Skip whitespace */
115 chars = strspn(rest, " \t");
116 rest += chars;
117
118 /* Fetch the keysym name */
119 chars = strcspn(rest, " \t\0");
120 STRNCPY(keyname, rest, chars + 1);
121 rest += chars;
122
123 keysym = XStringToKeysym(keyname);
124 if (keysym == NoSymbol)
125 {
126 DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring line)\n", keyname,
127 mapname));
128 return;
129 }
130
131 /* Allocate space for key_translation structure */
132 tr = (key_translation *) xmalloc(sizeof(key_translation));
133 memset(tr, 0, sizeof(key_translation));
134 *prev_next = tr;
135 prev_next = &tr->next;
136 tr->seq_keysym = keysym;
137
138 DEBUG_KBD(("0x%x, ", (unsigned int) keysym));
139 }
140 DEBUG_KBD(("\n"));
141}
void * xmalloc(int size)
Definition: uimain.c:747
#define STRNCPY(dst, src, n)
Definition: rdesktop.h:168
#define DEBUG_KBD(args)
Definition: rdesktop.h:135
_Check_return_ _CRTIMP size_t __cdecl strspn(_In_z_ const char *_Str, _In_z_ const char *_Control)
_Check_return_ _CRTIMP size_t __cdecl strcspn(_In_z_ const char *_Str, _In_z_ const char *_Control)
#define memset(x, y, z)
Definition: compat.h:39
uint32 seq_keysym
Definition: types.h:135
struct _key_translation * next
Definition: types.h:136
KeySym XStringToKeysym(const char *str)
Definition: x11stubs.c:1382
#define NoSymbol
Definition: x11stubs.h:10
rfbKeySym KeySym
Definition: x11stubs.h:27
#define KEYMAP_MAX_LINE_LENGTH
Definition: xkeymap.c:38
#define KEYMAP_MASK
Definition: xkeymap.c:37
static void free_key_translation(key_translation *ptr)
Definition: xkeymap.c:44

Referenced by xkeymap_read().

◆ add_to_keymap()

static void add_to_keymap ( RDPCLIENT This,
char keyname,
uint8  scancode,
uint16  modifiers,
char mapname 
)
static

Definition at line 57 of file xkeymap.c.

58{
59 KeySym keysym;
61
62 keysym = XStringToKeysym(keyname);
63 if (keysym == NoSymbol)
64 {
65 DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring)\n", keyname, mapname));
66 return;
67 }
68
69 DEBUG_KBD(("Adding translation, keysym=0x%x, scancode=0x%x, "
70 "modifiers=0x%x\n", (unsigned int) keysym, scancode, modifiers));
71
72 tr = (key_translation *) xmalloc(sizeof(key_translation));
73 memset(tr, 0, sizeof(key_translation));
74 tr->scancode = scancode;
75 tr->modifiers = modifiers;
76 free_key_translation(This->xkeymap.keymap[keysym & KEYMAP_MASK]);
77 This->xkeymap.keymap[keysym & KEYMAP_MASK] = tr;
78
79 return;
80}
uint16 modifiers
Definition: types.h:133
uint8 scancode
Definition: types.h:132

Referenced by xkeymap_read().

◆ ensure_remote_modifiers()

void ensure_remote_modifiers ( RDPCLIENT This,
uint32  ev_time,
key_translation  tr 
)

Definition at line 790 of file xkeymap.c.

791{
792 /* If this key is a modifier, do nothing */
793 if (is_modifier(tr.scancode))
794 return;
795
796 if (!This->numlock_sync)
797 {
798 /* NumLock */
800 != MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapNumLockMask))
801 {
802 /* The remote modifier state is not correct */
803 uint16 new_remote_state;
804
806 {
807 DEBUG_KBD(("Remote NumLock state is incorrect, activating NumLock.\n"));
808 new_remote_state = KBD_FLAG_NUMLOCK;
809 This->xkeymap.remote_modifier_state = MapNumLockMask;
810 }
811 else
812 {
813 DEBUG_KBD(("Remote NumLock state is incorrect, deactivating NumLock.\n"));
814 new_remote_state = 0;
815 This->xkeymap.remote_modifier_state = 0;
816 }
817
818 rdp_send_input(This, 0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0);
819 }
820 }
821
822
823 /* Shift. Left shift and right shift are treated as equal; either is fine. */
825 != MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapShiftMask))
826 {
827 /* The remote modifier state is not correct */
829 {
830 /* Needs left shift. Send down. */
832 }
834 {
835 /* Needs right shift. Send down. */
837 }
838 else
839 {
840 /* Should not use this modifier. Send up for shift currently pressed. */
841 if (MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapLeftShiftMask))
842 /* Left shift is down */
844 else
845 /* Right shift is down */
847 }
848 }
849
850 /* AltGr */
852 != MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapAltGrMask))
853 {
854 /* The remote modifier state is not correct */
856 {
857 /* Needs this modifier. Send down. */
859 }
860 else
861 {
862 /* Should not use this modifier. Send up. */
864 }
865 }
866
867
868}
#define RDP_KEYPRESS
Definition: constants.h:251
#define MapRightShiftMask
Definition: constants.h:363
#define KBD_FLAG_NUMLOCK
Definition: constants.h:247
#define RDP_KEYRELEASE
Definition: constants.h:252
#define MapNumLockMask
Definition: constants.h:379
#define MapAltGrMask
Definition: constants.h:369
@ RDP_INPUT_SYNCHRONIZE
Definition: constants.h:231
#define MASK_HAS_BITS(var, mask)
Definition: constants.h:388
#define MapShiftMask
Definition: constants.h:365
#define MapLeftShiftMask
Definition: constants.h:364
void rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
Definition: rdp.c:551
unsigned short uint16
Definition: types.h:30
#define SCANCODE_CHAR_RALT
Definition: scancodes.h:209
#define SCANCODE_CHAR_LSHIFT
Definition: scancodes.h:156
#define SCANCODE_CHAR_RSHIFT
Definition: scancodes.h:195
static BOOL is_modifier(uint8 scancode)
Definition: xkeymap.c:747
void rdp_send_scancode(RDPCLIENT *This, uint32 time, uint16 flags, uint8 scancode)
Definition: xkeymap.c:1001

Referenced by restore_remote_modifiers(), and xkeymap_send_keys().

◆ free_key_translation()

static void free_key_translation ( key_translation ptr)
static

Definition at line 44 of file xkeymap.c.

45{
47
48 while (ptr)
49 {
50 next = ptr->next;
51 xfree(ptr);
52 ptr = next;
53 }
54}
void xfree(void *mem)
Definition: uimain.c:758
static PVOID ptr
Definition: dispmode.c:27
static unsigned __int64 next
Definition: rand_nt.c:6

Referenced by add_sequence(), and add_to_keymap().

◆ get_ksname()

char * get_ksname ( uint32  keysym)

Definition at line 734 of file xkeymap.c.

735{
736 char *ksname = NULL;
737
738 if (keysym == NoSymbol)
739 ksname = "NoSymbol";
740 else if (!(ksname = XKeysymToString(keysym)))
741 ksname = "(no name)";
742
743 return ksname;
744}
#define NULL
Definition: types.h:112
const char * XKeysymToString(KeySym keysym)
Definition: x11stubs.c:1391

Referenced by xkeymap_translate_key(), and xwin_process_events().

◆ handle_special_keys()

BOOL handle_special_keys ( RDPCLIENT This,
uint32  keysym,
unsigned int  state,
uint32  ev_time,
BOOL  pressed 
)

Definition at line 489 of file xkeymap.c.

490{
491 switch (keysym)
492 {
493 case XK_Return:
494 if ((get_key_state(This, state, XK_Alt_L) || get_key_state(This, state, XK_Alt_R))
495 && (get_key_state(This, state, XK_Control_L)
496 || get_key_state(This, state, XK_Control_R)))
497 {
498 /* Ctrl-Alt-Enter: toggle full screen */
499 if (pressed)
501 return True;
502 }
503 break;
504
505 case XK_Break:
506 /* Send Break sequence E0 46 E0 C6 */
507 if (pressed)
508 {
510 (SCANCODE_EXTENDED | 0x46));
512 (SCANCODE_EXTENDED | 0xc6));
513 }
514 /* No release sequence */
515 return True;
516 break;
517
518 case XK_Pause:
519 /* According to MS Keyboard Scan Code
520 Specification, pressing Pause should result
521 in E1 1D 45 E1 9D C5. I'm not exactly sure
522 of how this is supposed to be sent via
523 RDP. The code below seems to work, but with
524 the side effect that Left Ctrl stays
525 down. Therefore, we release it when Pause
526 is released. */
527 if (pressed)
528 {
535 }
536 else
537 {
538 /* Release Left Ctrl */
540 0x1d, 0);
541 }
542 return True;
543 break;
544
545 case XK_Meta_L: /* Windows keys */
546 case XK_Super_L:
547 case XK_Hyper_L:
548 send_winkey(This, ev_time, pressed, True);
549 return True;
550 break;
551
552 case XK_Meta_R:
553 case XK_Super_R:
554 case XK_Hyper_R:
555 send_winkey(This, ev_time, pressed, False);
556 return True;
557 break;
558
559 case XK_space:
560 /* Prevent access to the Windows system menu in single app mode */
561 if (This->win_button_size
562 && (get_key_state(This, state, XK_Alt_L) || get_key_state(This, state, XK_Alt_R)))
563 return True;
564 break;
565
566 case XK_Num_Lock:
567 /* Synchronize on key release */
568 if (This->numlock_sync && !pressed)
571
572 /* Inhibit */
573 return True;
574 break;
575 case XK_Overlay1_Enable:
576 /* Toggle SeamlessRDP */
577 if (pressed)
579 break;
580
581 }
582 return False;
583}
static int state
Definition: maze.c:121
@ RDP_INPUT_SCANCODE
Definition: constants.h:234
unsigned int read_keyboard_state(void)
Definition: uimain.c:632
void ui_seamless_toggle(void)
void xwin_toggle_fullscreen(void)
Definition: vnc.c:124
RD_BOOL get_key_state(unsigned int state, uint32 keysym)
Definition: vnc.c:146
#define False
Definition: types.h:25
#define True
Definition: types.h:24
#define SCANCODE_EXTENDED
Definition: scancodes.h:24
static void send_winkey(RDPCLIENT *This, uint32 ev_time, BOOL pressed, BOOL leftkey)
Definition: xkeymap.c:439
uint16 ui_get_numlock_state(RDPCLIENT *This, unsigned int state)
Definition: xkeymap.c:888

◆ is_modifier()

static BOOL is_modifier ( uint8  scancode)
static

Definition at line 747 of file xkeymap.c.

748{
749 switch (scancode)
750 {
760 return True;
761 default:
762 break;
763 }
764 return False;
765}
#define SCANCODE_CHAR_NUMLOCK
Definition: scancodes.h:255
#define SCANCODE_CHAR_RCTRL
Definition: scancodes.h:214
#define SCANCODE_CHAR_LALT
Definition: scancodes.h:203
#define SCANCODE_CHAR_LWIN
Definition: scancodes.h:366
#define SCANCODE_CHAR_LCTRL
Definition: scancodes.h:198
#define SCANCODE_CHAR_RWIN
Definition: scancodes.h:368

Referenced by ensure_remote_modifiers(), restore_remote_modifiers(), and save_remote_modifiers().

◆ pathjoin()

static char * pathjoin ( const char a,
const char b 
)
static

Definition at line 202 of file xkeymap.c.

203{
204 char *result;
205 result = xmalloc(PATH_MAX * 2 + 1);
206
207 if (b[0] == '/')
208 {
210 }
211 else
212 {
214 strcat(result, "/");
216 }
217 return result;
218}
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
char * strncat(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:605
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
#define PATH_MAX
Definition: types.h:280
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLuint64EXT * result
Definition: glext.h:11304

Referenced by xkeymap_open().

◆ rdp_send_scancode()

void rdp_send_scancode ( RDPCLIENT This,
uint32  time,
uint16  flags,
uint8  scancode 
)

Definition at line 1001 of file xkeymap.c.

1002{
1004
1005 if (scancode & SCANCODE_EXTENDED)
1006 {
1007 DEBUG_KBD(("Sending extended scancode=0x%x, flags=0x%x\n",
1008 scancode & ~SCANCODE_EXTENDED, flags));
1010 scancode & ~SCANCODE_EXTENDED, 0);
1011 }
1012 else
1013 {
1014 DEBUG_KBD(("Sending scancode=0x%x, flags=0x%x\n", scancode, flags));
1016 }
1017}
#define KBD_FLAG_EXT
Definition: constants.h:240
GLbitfield flags
Definition: glext.h:7161
__u16 time
Definition: mkdosfs.c:8
static void update_modifier_state(RDPCLIENT *This, uint8 scancode, BOOL pressed)
Definition: xkeymap.c:940

Referenced by ensure_remote_modifiers(), handle_special_keys(), reset_modifier_keys(), reset_winkey(), send_winkey(), and xkeymap_send_keys().

◆ read_keyboard_state()

unsigned int read_keyboard_state ( RDPCLIENT This)

Definition at line 872 of file xkeymap.c.

873{
874#ifdef RDP2VNC
875 return 0;
876#else
877 unsigned int state;
878 Window wdummy;
879 int dummy;
880
881 XQueryPointer(This->display, This->wnd, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
882 return state;
883#endif
884}
Definition: window.c:28

◆ reset_modifier_keys()

void reset_modifier_keys ( RDPCLIENT This)

Definition at line 900 of file xkeymap.c.

901{
902 unsigned int state = read_keyboard_state(This);
903
904 /* reset keys */
905 uint32 ev_time;
906 ev_time = time(NULL);
907
908 if (MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapLeftShiftMask)
909 && !get_key_state(This, state, XK_Shift_L))
911
912 if (MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapRightShiftMask)
913 && !get_key_state(This, state, XK_Shift_R))
915
916 if (MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapLeftCtrlMask)
917 && !get_key_state(This, state, XK_Control_L))
919
920 if (MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapRightCtrlMask)
921 && !get_key_state(This, state, XK_Control_R))
923
924 if (MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapLeftAltMask) && !get_key_state(This, state, XK_Alt_L))
926
927 if (MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapRightAltMask) &&
928 !get_key_state(This, state, XK_Alt_R) && !get_key_state(This, state, XK_Mode_switch)
929 && !get_key_state(This, state, XK_ISO_Level3_Shift))
931
932 reset_winkey(This, ev_time);
933
934 if (This->numlock_sync)
936}
#define MapLeftCtrlMask
Definition: constants.h:372
#define MapRightCtrlMask
Definition: constants.h:371
#define MapRightAltMask
Definition: constants.h:367
#define MapLeftAltMask
Definition: constants.h:368
unsigned int uint32
Definition: types.h:32
static void reset_winkey(RDPCLIENT *This, uint32 ev_time)
Definition: xkeymap.c:477

◆ reset_winkey()

static void reset_winkey ( RDPCLIENT This,
uint32  ev_time 
)
static

Definition at line 477 of file xkeymap.c.

478{
479 if (This->use_rdp5)
480 {
481 /* For some reason, it seems to suffice to release
482 *either* the left or right winkey. */
484 }
485}

Referenced by reset_modifier_keys().

◆ restore_remote_modifiers()

void restore_remote_modifiers ( RDPCLIENT This,
uint32  ev_time,
uint8  scancode 
)

Definition at line 777 of file xkeymap.c.

778{
780
781 if (is_modifier(scancode))
782 return;
783
784 dummy.scancode = 0;
785 dummy.modifiers = This->xkeymap.saved_remote_modifier_state;
787}
void ensure_remote_modifiers(RDPCLIENT *This, uint32 ev_time, key_translation tr)
Definition: xkeymap.c:790

Referenced by xkeymap_send_keys().

◆ save_remote_modifiers()

void save_remote_modifiers ( RDPCLIENT This,
uint8  scancode 
)

Definition at line 768 of file xkeymap.c.

769{
770 if (is_modifier(scancode))
771 return;
772
773 This->xkeymap.saved_remote_modifier_state = This->xkeymap.remote_modifier_state;
774}

Referenced by xkeymap_send_keys().

◆ send_winkey()

static void send_winkey ( RDPCLIENT This,
uint32  ev_time,
BOOL  pressed,
BOOL  leftkey 
)
static

Definition at line 439 of file xkeymap.c.

440{
441 uint8 winkey;
442
443 if (leftkey)
444 winkey = SCANCODE_CHAR_LWIN;
445 else
446 winkey = SCANCODE_CHAR_RWIN;
447
448 if (pressed)
449 {
450 if (This->use_rdp5)
451 {
452 rdp_send_scancode(This, ev_time, RDP_KEYPRESS, winkey);
453 }
454 else
455 {
456 /* RDP4 doesn't support winkey. Fake with Ctrl-Esc */
459 }
460 }
461 else
462 {
463 /* key released */
464 if (This->use_rdp5)
465 {
466 rdp_send_scancode(This, ev_time, RDP_KEYRELEASE, winkey);
467 }
468 else
469 {
472 }
473 }
474}
unsigned char uint8
Definition: types.h:28
#define SCANCODE_CHAR_ESC
Definition: scancodes.h:313

Referenced by handle_special_keys().

◆ ui_get_numlock_state()

uint16 ui_get_numlock_state ( RDPCLIENT This,
unsigned int  state 
)

Definition at line 888 of file xkeymap.c.

889{
890 uint16 numlock_state = 0;
891
892 if (get_key_state(This, state, XK_Num_Lock))
893 numlock_state = KBD_FLAG_NUMLOCK;
894
895 return numlock_state;
896}

Referenced by handle_special_keys(), and reset_modifier_keys().

◆ update_modifier_state()

static void update_modifier_state ( RDPCLIENT This,
uint8  scancode,
BOOL  pressed 
)
static

Definition at line 940 of file xkeymap.c.

941{
942#ifdef WITH_DEBUG_KBD
943 uint16 old_modifier_state;
944
945 old_modifier_state = This->xkeymap.remote_modifier_state;
946#endif
947
948 switch (scancode)
949 {
951 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapLeftShiftMask, pressed);
952 break;
954 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapRightShiftMask, pressed);
955 break;
957 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapLeftCtrlMask, pressed);
958 break;
960 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapRightCtrlMask, pressed);
961 break;
963 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapLeftAltMask, pressed);
964 break;
966 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapRightAltMask, pressed);
967 break;
969 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapLeftWinMask, pressed);
970 break;
972 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state, MapRightWinMask, pressed);
973 break;
975 /* KeyReleases for NumLocks are sent immediately. Toggle the
976 modifier state only on Keypress */
977 if (pressed && !This->numlock_sync)
978 {
979 BOOL newNumLockState;
980 newNumLockState =
982 (This->xkeymap.remote_modifier_state, MapNumLockMask) == False);
983 MASK_CHANGE_BIT(This->xkeymap.remote_modifier_state,
984 MapNumLockMask, newNumLockState);
985 }
986 }
987
988#ifdef WITH_DEBUG_KBD
989 if (old_modifier_state != This->xkeymap.remote_modifier_state)
990 {
991 DEBUG_KBD(("Before updating modifier_state:0x%x, pressed=0x%x\n",
992 old_modifier_state, pressed));
993 DEBUG_KBD(("After updating modifier_state:0x%x\n", This->xkeymap.remote_modifier_state));
994 }
995#endif
996
997}
#define MapRightWinMask
Definition: constants.h:375
#define MapLeftWinMask
Definition: constants.h:376
#define MASK_CHANGE_BIT(var, mask, active)
Definition: constants.h:389
unsigned int BOOL
Definition: ntddk_ex.h:94

Referenced by rdp_send_scancode().

◆ xkeymap_from_locale()

BOOL xkeymap_from_locale ( RDPCLIENT This,
const char locale 
)

Definition at line 144 of file xkeymap.c.

145{
146 char *str, *ptr;
147 FILE *fp;
148
149 /* Create a working copy */
150 str = xstrdup(locale);
151
152 /* Truncate at dot and at */
153 ptr = strrchr(str, '.');
154 if (ptr)
155 *ptr = '\0';
156 ptr = strrchr(str, '@');
157 if (ptr)
158 *ptr = '\0';
159
160 /* Replace _ with - */
161 ptr = strrchr(str, '_');
162 if (ptr)
163 *ptr = '-';
164
165 /* Convert to lowercase */
166 ptr = str;
167 while (*ptr)
168 {
169 *ptr = tolower((int) *ptr);
170 ptr++;
171 }
172
173 /* Try to open this keymap (da-dk) */
174 fp = xkeymap_open(str);
175 if (fp == NULL)
176 {
177 /* Truncate at dash */
178 ptr = strrchr(str, '-');
179 if (ptr)
180 *ptr = '\0';
181
182 /* Try the short name (da) */
183 fp = xkeymap_open(str);
184 }
185
186 if (fp)
187 {
188 fclose(fp);
189 STRNCPY(This->keymapname, str, sizeof(This->keymapname));
190 xfree(str);
191 return True;
192 }
193
194 xfree(str);
195 return False;
196}
int tolower(int c)
Definition: utclib.c:902
char * xstrdup(const char *s)
Definition: uimain.c:768
Definition: _locale.h:75
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
const WCHAR * str
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
FILE * xkeymap_open(const char *filename)
Definition: xkeymap.c:222

◆ xkeymap_init()

void xkeymap_init ( RDPCLIENT This)

Definition at line 425 of file xkeymap.c.

426{
427 unsigned int max_keycode;
428
429 if (strcmp(This->keymapname, "none"))
430 {
431 if (xkeymap_read(This, This->keymapname))
432 This->xkeymap.keymap_loaded = True;
433 }
434
435 XDisplayKeycodes(This->display, &This->xkeymap.min_keycode, (int *) &max_keycode);
436}
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
void XDisplayKeycodes(Display *display, int *min_keycode, int *max_keycode)
Definition: x11stubs.c:1400
static BOOL xkeymap_read(RDPCLIENT *This, char *mapname)
Definition: xkeymap.c:260

◆ xkeymap_open()

FILE * xkeymap_open ( const char filename)

Definition at line 222 of file xkeymap.c.

223{
224 char *path1, *path2;
225 char *home;
226 FILE *fp;
227
228 /* Try ~/.rdesktop/keymaps */
229 home = getenv("HOME");
230 if (home)
231 {
232 path1 = pathjoin(home, ".rdesktop/keymaps");
234 xfree(path1);
235 fp = fopen(path2, "r");
236 xfree(path2);
237 if (fp)
238 return fp;
239 }
240
241 /* Try KEYMAP_PATH */
242 path1 = pathjoin(KEYMAP_PATH, filename);
243 fp = fopen(path1, "r");
244 xfree(path1);
245 if (fp)
246 return fp;
247
248 /* Try current directory, in case we are running from the source
249 tree */
250 path1 = pathjoin("keymaps", filename);
251 fp = fopen(path1, "r");
252 xfree(path1);
253 if (fp)
254 return fp;
255
256 return NULL;
257}
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
_Check_return_ char *__cdecl getenv(_In_z_ const char *_VarName)
const char * filename
Definition: ioapi.h:137
static const WCHAR path1[]
Definition: path.c:28
static const WCHAR path2[]
Definition: path.c:29
Definition: tftpd.h:38
static char * pathjoin(const char *a, const char *b)
Definition: xkeymap.c:202

Referenced by xkeymap_from_locale(), and xkeymap_read().

◆ xkeymap_read()

static BOOL xkeymap_read ( RDPCLIENT This,
char mapname 
)
static

Definition at line 260 of file xkeymap.c.

261{
262 FILE *fp;
264 unsigned int line_num = 0;
265 unsigned int line_length = 0;
266 char *keyname, *p;
267 char *line_rest;
268 uint8 scancode;
269 uint16 modifiers;
270
271 fp = xkeymap_open(mapname);
272 if (fp == NULL)
273 {
274 error("Failed to open keymap %s\n", mapname);
275 return False;
276 }
277
278 /* FIXME: More tolerant on white space */
279 while (fgets(line, sizeof(line), fp) != NULL)
280 {
281 line_num++;
282
283 /* Replace the \n with \0 */
284 p = strchr(line, '\n');
285 if (p != NULL)
286 *p = 0;
287
288 line_length = strlen(line);
289
290 /* Completely empty line */
291 if (strspn(line, " \t\n\r\f\v") == line_length)
292 {
293 continue;
294 }
295
296 /* Include */
297 if (str_startswith(line, "include "))
298 {
299 if (!xkeymap_read(This, line + sizeof("include ") - 1))
300 return False;
301 continue;
302 }
303
304 /* map */
305 if (str_startswith(line, "map "))
306 {
307 This->keylayout = strtoul(line + sizeof("map ") - 1, NULL, 16);
308 DEBUG_KBD(("Keylayout 0x%x\n", This->keylayout));
309 continue;
310 }
311
312 /* compose */
313 if (str_startswith(line, "enable_compose"))
314 {
315 DEBUG_KBD(("Enabling compose handling\n"));
316 This->enable_compose = True;
317 continue;
318 }
319
320 /* sequence */
321 if (str_startswith(line, "sequence"))
322 {
323 add_sequence(This, line + sizeof("sequence") - 1, mapname);
324 continue;
325 }
326
327 /* keyboard_type */
328 if (str_startswith(line, "keyboard_type "))
329 {
330 This->keyboard_type = strtol(line + sizeof("keyboard_type ") - 1, NULL, 16);
331 DEBUG_KBD(("keyboard_type 0x%x\n", This->keyboard_type));
332 continue;
333 }
334
335 /* keyboard_subtype */
336 if (str_startswith(line, "keyboard_subtype "))
337 {
338 This->keyboard_subtype =
339 strtol(line + sizeof("keyboard_subtype ") - 1, NULL, 16);
340 DEBUG_KBD(("keyboard_subtype 0x%x\n", This->keyboard_subtype));
341 continue;
342 }
343
344 /* keyboard_functionkeys */
345 if (str_startswith(line, "keyboard_functionkeys "))
346 {
347 This->keyboard_functionkeys =
348 strtol(line + sizeof("keyboard_functionkeys ") - 1, NULL, 16);
349 DEBUG_KBD(("keyboard_functionkeys 0x%x\n", This->keyboard_functionkeys));
350 continue;
351 }
352
353 /* Comment */
354 if (line[0] == '#')
355 {
356 continue;
357 }
358
359 /* Normal line */
360 keyname = line;
361 p = strchr(line, ' ');
362 if (p == NULL)
363 {
364 error("Bad line %d in keymap %s\n", line_num, mapname);
365 continue;
366 }
367 else
368 {
369 *p = 0;
370 }
371
372 /* scancode */
373 p++;
374 scancode = strtol(p, &line_rest, 16);
375
376 /* flags */
377 /* FIXME: Should allow case-insensitive flag names.
378 Fix by using lex+yacc... */
379 modifiers = 0;
380 if (strstr(line_rest, "altgr"))
381 {
382 MASK_ADD_BITS(modifiers, MapAltGrMask);
383 }
384
385 if (strstr(line_rest, "shift"))
386 {
388 }
389
390 if (strstr(line_rest, "numlock"))
391 {
392 MASK_ADD_BITS(modifiers, MapNumLockMask);
393 }
394
395 if (strstr(line_rest, "localstate"))
396 {
398 }
399
400 if (strstr(line_rest, "inhibit"))
401 {
402 MASK_ADD_BITS(modifiers, MapInhibitMask);
403 }
404
405 add_to_keymap(This, keyname, scancode, modifiers, mapname);
406
407 if (strstr(line_rest, "addupper"))
408 {
409 /* Automatically add uppercase key, with same modifiers
410 plus shift */
411 for (p = keyname; *p; p++)
412 *p = toupper((int) *p);
414 add_to_keymap(This, keyname, scancode, modifiers, mapname);
415 }
416 }
417
418 fclose(fp);
419 return True;
420}
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int toupper(int c)
Definition: utclib.c:881
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define MapLocalStateMask
Definition: constants.h:382
#define MapInhibitMask
Definition: constants.h:384
#define MASK_ADD_BITS(var, mask)
Definition: constants.h:386
RD_BOOL str_startswith(const char *s, const char *prefix)
Definition: rdesktop.c:1235
GLfloat GLfloat p
Definition: glext.h:8902
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
_Check_return_ long __cdecl strtol(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix)
#define error(str)
Definition: mkdosfs.c:1605
Definition: parser.c:49
static void add_sequence(RDPCLIENT *This, char *rest, char *mapname)
Definition: xkeymap.c:83
static void add_to_keymap(RDPCLIENT *This, char *keyname, uint8 scancode, uint16 modifiers, char *mapname)
Definition: xkeymap.c:57

Referenced by xkeymap_init(), and xkeymap_read().

◆ xkeymap_send_keys()

void xkeymap_send_keys ( RDPCLIENT This,
uint32  keysym,
unsigned int  keycode,
unsigned int  state,
uint32  ev_time,
BOOL  pressed,
uint8  nesting 
)

Definition at line 664 of file xkeymap.c.

666{
667 key_translation tr, *ptr;
668 tr = xkeymap_translate_key(This, keysym, keycode, state);
669
670 if (tr.seq_keysym == 0)
671 {
672 /* Scancode translation */
673 if (tr.scancode == 0)
674 return;
675
676 if (pressed)
677 {
679 ensure_remote_modifiers(This, ev_time, tr);
682 }
683 else
684 {
686 }
687 return;
688 }
689
690 /* Sequence, only on key down */
691 if (pressed)
692 {
693 ptr = &tr;
694 do
695 {
696 DEBUG_KBD(("Handling sequence element, keysym=0x%x\n",
697 (unsigned int) ptr->seq_keysym));
698
699 if (nesting++ > 32)
700 {
701 error("Sequence nesting too deep\n");
702 return;
703 }
704
705 xkeymap_send_keys(This, ptr->seq_keysym, keycode, state, ev_time, True, nesting);
706 xkeymap_send_keys(This, ptr->seq_keysym, keycode, state, ev_time, False, nesting);
707 ptr = ptr->next;
708 }
709 while (ptr);
710 }
711}
void restore_remote_modifiers(RDPCLIENT *This, uint32 ev_time, uint8 scancode)
Definition: xkeymap.c:777
void save_remote_modifiers(RDPCLIENT *This, uint8 scancode)
Definition: xkeymap.c:768
key_translation xkeymap_translate_key(RDPCLIENT *This, uint32 keysym, unsigned int keycode, unsigned int state)
Definition: xkeymap.c:587
void xkeymap_send_keys(RDPCLIENT *This, uint32 keysym, unsigned int keycode, unsigned int state, uint32 ev_time, BOOL pressed, uint8 nesting)
Definition: xkeymap.c:664

Referenced by xkeymap_send_keys().

◆ xkeymap_translate_button()

uint16 xkeymap_translate_button ( unsigned int  button)

Definition at line 714 of file xkeymap.c.

715{
716 switch (button)
717 {
718 case Button1: /* left */
719 return MOUSE_FLAG_BUTTON1;
720 case Button2: /* middle */
721 return MOUSE_FLAG_BUTTON3;
722 case Button3: /* right */
723 return MOUSE_FLAG_BUTTON2;
724 case Button4: /* wheel up */
725 return MOUSE_FLAG_BUTTON4;
726 case Button5: /* wheel down */
727 return MOUSE_FLAG_BUTTON5;
728 }
729
730 return 0;
731}
#define MOUSE_FLAG_BUTTON5
Definition: constants.h:259
#define MOUSE_FLAG_BUTTON1
Definition: constants.h:255
#define MOUSE_FLAG_BUTTON2
Definition: constants.h:256
#define MOUSE_FLAG_BUTTON4
Definition: constants.h:258
#define MOUSE_FLAG_BUTTON3
Definition: constants.h:257
DWORD button
Definition: button.c:166
#define Button1
Definition: x11stubs.h:19
#define Button3
Definition: x11stubs.h:21
#define Button2
Definition: x11stubs.h:20
#define Button5
Definition: x11stubs.h:23
#define Button4
Definition: x11stubs.h:22

Referenced by handle_button_event().

◆ xkeymap_translate_key()

key_translation xkeymap_translate_key ( RDPCLIENT This,
uint32  keysym,
unsigned int  keycode,
unsigned int  state 
)

Definition at line 587 of file xkeymap.c.

588{
589 key_translation tr = { 0, 0, 0, 0 };
591
592 ptr = This->xkeymap.keymap[keysym & KEYMAP_MASK];
593 if (ptr)
594 {
595 tr = *ptr;
596 if (tr.seq_keysym == 0) /* Normal scancode translation */
597 {
599 {
600 DEBUG_KBD(("Inhibiting key\n"));
601 tr.scancode = 0;
602 return tr;
603 }
604
606 {
607 /* The modifiers to send for this key should be obtained
608 from the local state. Currently, only shift is implemented. */
610 {
612 }
613 }
614
615 /* Windows interprets CapsLock+Ctrl+key
616 differently from Shift+Ctrl+key. Since we
617 are simulating CapsLock with Shifts, things
618 like Ctrl+f with CapsLock on breaks. To
619 solve this, we are releasing Shift if Ctrl
620 is on, but only if Shift isn't physically pressed. */
622 && MASK_HAS_BITS(This->xkeymap.remote_modifier_state, MapCtrlMask)
624 {
625 DEBUG_KBD(("Non-physical Shift + Ctrl pressed, releasing Shift\n"));
627 }
628
629 DEBUG_KBD(("Found scancode translation, scancode=0x%x, modifiers=0x%x\n",
630 tr.scancode, tr.modifiers));
631 }
632 }
633 else
634 {
635 if (This->xkeymap.keymap_loaded)
636 warning("No translation for (keysym 0x%lx, %s)\n", keysym,
637 get_ksname(keysym));
638
639 /* not in keymap, try to interpret the raw scancode */
640 if (((int) keycode >= This->xkeymap.min_keycode) && (keycode <= 0x60))
641 {
642 tr.scancode = keycode - This->xkeymap.min_keycode;
643
644 /* The modifiers to send for this key should be
645 obtained from the local state. Currently, only
646 shift is implemented. */
648 {
650 }
651
652 DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));
653 }
654 else
655 {
656 DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));
657 }
658 }
659
660 return tr;
661}
#define MapCtrlMask
Definition: constants.h:373
#define MASK_REMOVE_BITS(var, mask)
Definition: constants.h:387
#define warning(s)
Definition: debug.h:83
#define ShiftMask
Definition: x11stubs.h:11
char * get_ksname(uint32 keysym)
Definition: xkeymap.c:734

Referenced by xkeymap_send_keys().