Implement scancode indexing
The mapping from scancodes to the indexes used in xrdp_keymap is not well designed and contains an implicit dependency on keycode values. This mapping is alse slightly different from the index used for the 'keys' map in the xrdp_wm structure. This commit introduces support for mapping scancodes directly to 'scancode indexes' suitable for indexing into both structures. Some renaming is also done; [MS-RDPBCGR] uses the terms scancode and keyCode interchangeably. An effort is made to use key_code for a raw value from a TS_KEYBOARD_EVENT, and scancode for a value which is produced by the scancode module.
This commit is contained in:
parent
d82a172b55
commit
c91ef80ca9
@ -326,9 +326,48 @@ const struct map_settings global_settings[] =
|
||||
// Default mapping set is "evdev"
|
||||
const struct map_settings *settings = &global_settings[SI_EVDEV];
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
scancode_to_index(unsigned short scancode)
|
||||
{
|
||||
if (scancode <= 0x7f)
|
||||
{
|
||||
return scancode;
|
||||
}
|
||||
if (scancode <= 0xff)
|
||||
{
|
||||
// 0x80 - 0xff : Invalid code
|
||||
return -1;
|
||||
}
|
||||
if (scancode <= 0x17f)
|
||||
{
|
||||
// 01x100 - 0x17f : Move bit 9 to bit 8
|
||||
return (scancode & 0x7f) | 0x80;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
unsigned short
|
||||
scancode_to_keycode(unsigned short scancode)
|
||||
scancode_from_index(int index)
|
||||
{
|
||||
index &= 0xff;
|
||||
unsigned short result;
|
||||
if (index < 0x80)
|
||||
{
|
||||
result = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (index & 0x7f) | 0x100;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
unsigned short
|
||||
scancode_to_x11_keycode(unsigned short scancode)
|
||||
{
|
||||
unsigned int min = 0;
|
||||
unsigned int max = settings->size;
|
||||
@ -419,3 +458,12 @@ scancode_get_keycode_set(void)
|
||||
{
|
||||
return settings->name;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
const char *
|
||||
scancode_get_xkb_rules(void)
|
||||
{
|
||||
// Currently supported keycods map directly to the same name for
|
||||
// the rules which use them.
|
||||
return settings->name;
|
||||
}
|
||||
|
@ -18,13 +18,32 @@
|
||||
* @file common/scancode.h
|
||||
* @brief Scancode handling
|
||||
*
|
||||
* Convert between RDP scancodes and X11 keycodes.
|
||||
* This module provides functionality for the following:-
|
||||
* 1) Mapping from TS_KEYBOARD_EVENT PDU values to an 'RDP scancode'
|
||||
* 2) Handling RDP scancodes
|
||||
* 3) Convert between RDP scancodes and X11 keycodes.
|
||||
*
|
||||
* RDP scancodes are largely the same as Windows scancodes. These are
|
||||
* indirectly documented in the Microsoft "Keyboard Scan Code Specification",
|
||||
* Rev 1.3a (March 16th 2000) and are otherwise known as "Scan code set
|
||||
* 1" scancodes. This document no longer appears to be available directly from
|
||||
* the Microsoft website.
|
||||
* The values received in TS_KEYBOARD_EVENT PDUs are largely the same as
|
||||
* Windows scancodes. These are indirectly documented in the Microsoft
|
||||
* "Keyboard Scan Code Specification", Rev 1.3a (March 16th 2000) and
|
||||
* are otherwise known as "Scan code set 1" scancodes. This document no
|
||||
* longer appears to be available directly from the Microsoft website.
|
||||
*
|
||||
* A TS_KEYBOARD_EVENT_PDU contains two important values:-
|
||||
* 1) key_code This is not unique. For example, left-shift and
|
||||
* right-shift share a key_code of 0x2a
|
||||
* 2) keyboard_flags Among other flags, contains KBDFLAGS_EXTENDED and
|
||||
* KBDFLAGS_EXTENDED1. These combine with the key_code
|
||||
* to allow a specific key to be determined.
|
||||
*
|
||||
* An 'RDP scancode' as defined by this module is a mapping of the
|
||||
* Windows key_code and keyboard_flags into a single value which
|
||||
* represents a unique key. For example:-
|
||||
* Left control : key_code=0x1d, KBDFLAGS_EXTENDED=0 scancode = 0x1d
|
||||
* Right control : key_code=0x1d, KBDFLAGS_EXTENDED=1 scancode = 0x11d
|
||||
*
|
||||
* This model of unique keys more closely maps what X11 does with its
|
||||
* own keycodes.
|
||||
*
|
||||
* X11 keycodes are the X11 equivalent of RDP scancodes. In general, these
|
||||
* are specific to an X server. In practice however, these are nowadays
|
||||
@ -39,15 +58,63 @@
|
||||
#if !defined(SCANCODE_H)
|
||||
#define SCANCODE_H
|
||||
|
||||
enum
|
||||
{
|
||||
/**
|
||||
* Maximum value returned by scancode_to_index()
|
||||
*/
|
||||
SCANCODE_MAX_INDEX = 255
|
||||
};
|
||||
|
||||
// Convert key_code and flags values received from a TS_KEYBOARD_EVENT
|
||||
// into a value suitable for use by this module
|
||||
#define SCANCODE_FROM_KBD_EVENT(key_code,keyboard_flags) \
|
||||
(((key_code) & 0x7f) | ((keyboard_flags) & 0x100))
|
||||
|
||||
// Convert a scancode used by this module back into a
|
||||
// TS_KEYBOARD_EVENT keyCode value
|
||||
#define SCANCODE_TO_KBD_EVENT_KEY_CODE(scancode) ((scancode) & 0x7f)
|
||||
|
||||
// Convert a scancode used by this module back into a
|
||||
// TS_KEYBOARD_EVENT keyboardFlags value
|
||||
#define SCANCODE_TO_KBD_EVENT_KBD_FLAGS(scancode) ((scancode) & 0x100)
|
||||
|
||||
/**
|
||||
* Looks up an RDP scancode
|
||||
* Convert a scancode to an index
|
||||
* @param scancode scancode in the range 0x00 - 0x1ff
|
||||
* @return index in the range 0..SCANCODE_MAX_INDEX (inclusive) or -1
|
||||
*
|
||||
* This function converts a 9-bit scancode into an 8-bit array index,
|
||||
* independent of the currently loaded keymap
|
||||
*
|
||||
* For scancodes in the range 0x00 - 0x7f, the index is identical to the
|
||||
* scancode. This includes scancodes for all the keys affected by
|
||||
* numlock.
|
||||
*/
|
||||
int
|
||||
scancode_to_index(unsigned short scancode);
|
||||
|
||||
/**
|
||||
* Convert an index back to a scancode.
|
||||
* @param index in the range 0..SCANCODE_MAX_INDEX
|
||||
*
|
||||
* @result scancode which is mapped to the index value
|
||||
*
|
||||
* The result is always a valid scancode, even if the index is
|
||||
* not valid.
|
||||
*/
|
||||
unsigned short
|
||||
scancode_from_index(int index);
|
||||
|
||||
/**
|
||||
* Looks up an RDP scancode and converts to an x11 keycode
|
||||
*
|
||||
* @param scancode Scancode. Extended scancodes have bit 9 set
|
||||
* (i.e. are in 0x100 - 0x1ff)
|
||||
* (i.e. are in 0x100 - 0x1ff).
|
||||
* @return keycode, or 0 for no keycode
|
||||
*/
|
||||
unsigned short
|
||||
scancode_to_keycode(unsigned short scancode);
|
||||
scancode_to_x11_keycode(unsigned short scancode);
|
||||
|
||||
/**
|
||||
* Gets the next valid scancode from the list of valid scancodes
|
||||
@ -84,4 +151,13 @@ scancode_set_keycode_set(const char *kk_set);
|
||||
const char *
|
||||
scancode_get_keycode_set(void);
|
||||
|
||||
/**
|
||||
* Gets the XKB rules set which can be used to access the currently
|
||||
* loaded keycode set
|
||||
*
|
||||
* @result "evdev", or "base"
|
||||
*/
|
||||
const char *
|
||||
scancode_get_xkb_rules(void);
|
||||
|
||||
#endif /* SCANCODE_H */
|
||||
|
@ -63,9 +63,6 @@
|
||||
#define XRDP_MAX_BITMAP_CACHE_IDX 2000
|
||||
#define XRDP_BITMAP_CACHE_ENTRIES 2048
|
||||
|
||||
#define XR_MIN_KEY_CODE 8
|
||||
#define XR_MAX_KEY_CODE 256
|
||||
|
||||
/*
|
||||
* Constants come from ITU-T Recommendations
|
||||
*/
|
||||
|
@ -279,7 +279,7 @@ output_file_section(FILE *outf,
|
||||
continue;
|
||||
}
|
||||
|
||||
e.keycode = scancode_to_keycode(scancode);
|
||||
e.keycode = scancode_to_x11_keycode(scancode);
|
||||
nbytes = XLookupString(&e, text, 255, &ks, NULL);
|
||||
if (ks == NoSymbol)
|
||||
{
|
||||
|
@ -31,7 +31,7 @@ START_TEST(test_scancode__evdev_all_values_returned)
|
||||
iter = 0;
|
||||
while ((scancode = scancode_get_next(&iter)) != 0)
|
||||
{
|
||||
unsigned short keycode = scancode_to_keycode(scancode);
|
||||
unsigned short keycode = scancode_to_x11_keycode(scancode);
|
||||
ck_assert_int_ne(keycode, 0);
|
||||
}
|
||||
}
|
||||
@ -57,7 +57,7 @@ START_TEST(test_scancode__evdev_bad_values_mapped_to_0)
|
||||
{
|
||||
if (!valid[scancode])
|
||||
{
|
||||
ck_assert_int_eq(scancode_to_keycode(scancode), 0);
|
||||
ck_assert_int_eq(scancode_to_x11_keycode(scancode), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -74,7 +74,7 @@ START_TEST(test_scancode__base_all_values_returned)
|
||||
iter = 0;
|
||||
while ((scancode = scancode_get_next(&iter)) != 0)
|
||||
{
|
||||
unsigned short keycode = scancode_to_keycode(scancode);
|
||||
unsigned short keycode = scancode_to_x11_keycode(scancode);
|
||||
ck_assert_int_ne(keycode, 0);
|
||||
}
|
||||
}
|
||||
@ -100,7 +100,7 @@ START_TEST(test_scancode__base_bad_values_mapped_to_0)
|
||||
{
|
||||
if (!valid[scancode])
|
||||
{
|
||||
ck_assert_int_eq(scancode_to_keycode(scancode), 0);
|
||||
ck_assert_int_eq(scancode_to_x11_keycode(scancode), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
134
xrdp/lang.c
134
xrdp/lang.c
@ -39,58 +39,64 @@
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_key_info *
|
||||
get_key_info_from_scan_code(int device_flags, int scan_code, int *keys,
|
||||
get_key_info_from_kbd_event(int keyboard_flags, int key_code, int *keys,
|
||||
int caps_lock, int num_lock, int scroll_lock,
|
||||
struct xrdp_keymap *keymap)
|
||||
{
|
||||
struct xrdp_key_info *rv;
|
||||
int shift;
|
||||
int altgr_scancode;
|
||||
int altgr;
|
||||
int ext;
|
||||
int index;
|
||||
|
||||
ext = device_flags & KBD_FLAG_EXT; /* 0x0100 */
|
||||
shift = keys[42] || keys[54];
|
||||
altgr = keys[56] & KBD_FLAG_EXT; /* right alt */
|
||||
altgr_scancode = SCANCODE_FROM_KBD_EVENT(56, KBD_FLAG_EXT);
|
||||
altgr = keys[scancode_to_index(altgr_scancode)]; /* right alt */
|
||||
rv = 0;
|
||||
index = INDEX_FROM_SCANCODE(scan_code, ext);
|
||||
|
||||
if (num_lock &&
|
||||
index >= XR_RDP_SCAN_MIN_NUMLOCK && index <= XR_RDP_SCAN_MAX_NUMLOCK)
|
||||
index = scancode_to_index(SCANCODE_FROM_KBD_EVENT(key_code, keyboard_flags));
|
||||
if (index >= 0)
|
||||
{
|
||||
rv = &(keymap->keys_numlock[index - XR_RDP_SCAN_MIN_NUMLOCK]);
|
||||
}
|
||||
else if (shift && caps_lock && altgr)
|
||||
{
|
||||
rv = &(keymap->keys_shiftcapslockaltgr[index]);
|
||||
}
|
||||
else if (shift && caps_lock)
|
||||
{
|
||||
rv = &(keymap->keys_shiftcapslock[index]);
|
||||
}
|
||||
else if (shift && altgr)
|
||||
{
|
||||
rv = &(keymap->keys_shiftaltgr[index]);
|
||||
}
|
||||
else if (shift)
|
||||
{
|
||||
rv = &(keymap->keys_shift[index]);
|
||||
}
|
||||
else if (caps_lock && altgr)
|
||||
{
|
||||
rv = &(keymap->keys_capslockaltgr[index]);
|
||||
}
|
||||
else if (caps_lock)
|
||||
{
|
||||
rv = &(keymap->keys_capslock[index]);
|
||||
}
|
||||
else if (altgr)
|
||||
{
|
||||
rv = &(keymap->keys_altgr[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = &(keymap->keys_noshift[index]);
|
||||
// scancode_to_index() guarantees to map numlock scancodes
|
||||
// to the same index values.
|
||||
if (num_lock &&
|
||||
index >= XR_RDP_SCAN_MIN_NUMLOCK &&
|
||||
index <= XR_RDP_SCAN_MAX_NUMLOCK)
|
||||
{
|
||||
rv = &(keymap->keys_numlock[index - XR_RDP_SCAN_MIN_NUMLOCK]);
|
||||
}
|
||||
else if (shift && caps_lock && altgr)
|
||||
{
|
||||
rv = &(keymap->keys_shiftcapslockaltgr[index]);
|
||||
}
|
||||
else if (shift && caps_lock)
|
||||
{
|
||||
rv = &(keymap->keys_shiftcapslock[index]);
|
||||
}
|
||||
else if (shift && altgr)
|
||||
{
|
||||
rv = &(keymap->keys_shiftaltgr[index]);
|
||||
}
|
||||
else if (shift)
|
||||
{
|
||||
rv = &(keymap->keys_shift[index]);
|
||||
}
|
||||
else if (caps_lock && altgr)
|
||||
{
|
||||
rv = &(keymap->keys_capslockaltgr[index]);
|
||||
}
|
||||
else if (caps_lock)
|
||||
{
|
||||
rv = &(keymap->keys_capslock[index]);
|
||||
}
|
||||
else if (altgr)
|
||||
{
|
||||
rv = &(keymap->keys_altgr[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = &(keymap->keys_noshift[index]);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -98,13 +104,13 @@ get_key_info_from_scan_code(int device_flags, int scan_code, int *keys,
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
get_keysym_from_scan_code(int device_flags, int scan_code, int *keys,
|
||||
get_keysym_from_kbd_event(int keyboard_flags, int key_code, int *keys,
|
||||
int caps_lock, int num_lock, int scroll_lock,
|
||||
struct xrdp_keymap *keymap)
|
||||
{
|
||||
struct xrdp_key_info *ki;
|
||||
|
||||
ki = get_key_info_from_scan_code(device_flags, scan_code, keys,
|
||||
ki = get_key_info_from_kbd_event(keyboard_flags, key_code, keys,
|
||||
caps_lock, num_lock, scroll_lock,
|
||||
keymap);
|
||||
|
||||
@ -118,13 +124,13 @@ get_keysym_from_scan_code(int device_flags, int scan_code, int *keys,
|
||||
|
||||
/*****************************************************************************/
|
||||
char32_t
|
||||
get_char_from_scan_code(int device_flags, int scan_code, int *keys,
|
||||
get_char_from_kbd_event(int keyboard_flags, int key_code, int *keys,
|
||||
int caps_lock, int num_lock, int scroll_lock,
|
||||
struct xrdp_keymap *keymap)
|
||||
{
|
||||
struct xrdp_key_info *ki;
|
||||
|
||||
ki = get_key_info_from_scan_code(device_flags, scan_code, keys,
|
||||
ki = get_key_info_from_kbd_event(keyboard_flags, key_code, keys,
|
||||
caps_lock, num_lock, scroll_lock,
|
||||
keymap);
|
||||
|
||||
@ -138,28 +144,29 @@ get_char_from_scan_code(int device_flags, int scan_code, int *keys,
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Tests a table key to see if it's a valid scancode
|
||||
* Converts a table key to a scancode index value
|
||||
*
|
||||
* @param key Table key
|
||||
* @param[out] scancode scancode index value (0..255) if 1 is returned
|
||||
* @return Boolean != 0 if the key is valid
|
||||
* @return index >= 0, or < 0 for an invalid key
|
||||
*/
|
||||
static int
|
||||
is_valid_scancode(const char *key, int *scancode)
|
||||
key_to_scancode_index(const char *key)
|
||||
{
|
||||
int rv = 0;
|
||||
int extended = 0;
|
||||
if ((key[0] == 'E' || key[0] == 'e') && key[1] == '0' && key[2] == '_')
|
||||
int rv = -1;
|
||||
int keyboard_flags = 0;
|
||||
if ((key[0] == 'E' || key[0] == 'e') && key[2] == '_')
|
||||
{
|
||||
extended = 1;
|
||||
key += 3;
|
||||
if (key[1] == '0')
|
||||
{
|
||||
keyboard_flags |= KBD_FLAG_EXT;
|
||||
key += 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (isxdigit(key[0]) && isxdigit(key[1]) && key[2] == '\0')
|
||||
{
|
||||
rv = 1;
|
||||
*scancode = XDIGIT_TO_VAL(key[0]) * 16 + XDIGIT_TO_VAL(key[1]);
|
||||
*scancode = INDEX_FROM_SCANCODE(*scancode, extended);
|
||||
int code = XDIGIT_TO_VAL(key[0]) * 16 + XDIGIT_TO_VAL(key[1]);
|
||||
rv = scancode_to_index(SCANCODE_FROM_KBD_EVENT(code, keyboard_flags));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@ -248,13 +255,14 @@ km_read_section(toml_table_t *tfile, const char *section_name,
|
||||
{
|
||||
const char *key;
|
||||
toml_datum_t val;
|
||||
int index;
|
||||
int scancode; // index value 0..255
|
||||
int i;
|
||||
char *p;
|
||||
const char *unicode_str;
|
||||
for (index = 0 ; (key = toml_key_in(section, index)) != NULL; ++index)
|
||||
for (i = 0 ; (key = toml_key_in(section, i)) != NULL; ++i)
|
||||
{
|
||||
if (!is_valid_scancode(key, &scancode))
|
||||
// Get a scancode index from the key if possible
|
||||
int sindex = key_to_scancode_index(key);
|
||||
if (sindex < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Can't parse value '%s' in [%s] in keymap file",
|
||||
@ -283,7 +291,7 @@ km_read_section(toml_table_t *tfile, const char *section_name,
|
||||
|
||||
/* Parse both values and add them to the keymap, logging any
|
||||
* errors */
|
||||
if (!is_valid_keysym(val.u.s, &keymap[scancode].sym))
|
||||
if (!is_valid_keysym(val.u.s, &keymap[sindex].sym))
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Can't read KeySym for [%s]:%s in keymap file",
|
||||
@ -291,7 +299,7 @@ km_read_section(toml_table_t *tfile, const char *section_name,
|
||||
}
|
||||
|
||||
if (unicode_str != NULL &&
|
||||
!is_valid_unicode_char(unicode_str, &keymap[scancode].chr))
|
||||
!is_valid_unicode_char(unicode_str, &keymap[sindex].chr))
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Can't read unicode character for [%s]:%s in keymap file",
|
||||
@ -385,7 +393,7 @@ km_load_file(const char *filename, struct xrdp_keymap *keymap)
|
||||
/* The numlock map is much smaller and offset by
|
||||
* XR_RDP_SCAN_MAX_NUMLOCK. Read the section into a temporary
|
||||
* area and copy it over */
|
||||
struct xrdp_key_info keys_numlock[256];
|
||||
struct xrdp_key_info keys_numlock[SCANCODE_MAX_INDEX + 1];
|
||||
int i;
|
||||
for (i = XR_RDP_SCAN_MIN_NUMLOCK; i <= XR_RDP_SCAN_MAX_NUMLOCK; ++i)
|
||||
{
|
||||
|
14
xrdp/xrdp.h
14
xrdp/xrdp.h
@ -147,8 +147,14 @@ int
|
||||
xrdp_wm_mouse_touch(struct xrdp_wm *self, int gesture, int param);
|
||||
int
|
||||
xrdp_wm_mouse_click(struct xrdp_wm *self, int x, int y, int but, int down);
|
||||
/**
|
||||
* Handle a TS_KEYBOARD_EVENT ([MS-RDPBCGR] 2.2.8.1.1.3.1.1.1)
|
||||
*
|
||||
* @param device_flags keyboardFlags value from PDU
|
||||
* @param key_code keyCode value from PDU
|
||||
*/
|
||||
int
|
||||
xrdp_wm_key(struct xrdp_wm *self, int device_flags, int scan_code);
|
||||
xrdp_wm_key(struct xrdp_wm *self, int keyboard_flags, int key_code);
|
||||
int
|
||||
xrdp_wm_key_sync(struct xrdp_wm *self, int device_flags, int key_flags);
|
||||
int
|
||||
@ -424,15 +430,15 @@ set_string(char **in_str, const char *in);
|
||||
|
||||
/* in lang.c */
|
||||
struct xrdp_key_info *
|
||||
get_key_info_from_scan_code(int device_flags, int scan_code, int *keys,
|
||||
get_key_info_from_kbd_event(int keyboard_flags, int key_code, int *keys,
|
||||
int caps_lock, int num_lock, int scroll_lock,
|
||||
struct xrdp_keymap *keymap);
|
||||
int
|
||||
get_keysym_from_scan_code(int device_flags, int scan_code, int *keys,
|
||||
get_keysym_from_kbd_event(int keyboard_flags, int key_code, int *keys,
|
||||
int caps_lock, int num_lock, int scroll_lock,
|
||||
struct xrdp_keymap *keymap);
|
||||
char32_t
|
||||
get_char_from_scan_code(int device_flags, int scan_code, int *keys,
|
||||
get_char_from_kbd_event(int keyboard_flags, int key_code, int *keys,
|
||||
int caps_lock, int num_lock, int scroll_lock,
|
||||
struct xrdp_keymap *keymap);
|
||||
int
|
||||
|
@ -1226,7 +1226,7 @@ xrdp_bitmap_def_proc(struct xrdp_bitmap *self, int msg,
|
||||
}
|
||||
else
|
||||
{
|
||||
char32_t c = get_char_from_scan_code
|
||||
char32_t c = get_char_from_kbd_event
|
||||
(param2, scan_code, self->wm->keys, self->wm->caps_lock,
|
||||
self->wm->num_lock, self->wm->scroll_lock,
|
||||
&(self->wm->keymap));
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "xrdp_constants.h"
|
||||
#include "fifo.h"
|
||||
#include "guid.h"
|
||||
#include "scancode.h"
|
||||
#include "xrdp_client_info.h"
|
||||
|
||||
#define MAX_NR_CHANNELS 16
|
||||
@ -452,25 +453,17 @@ struct xrdp_key_info
|
||||
char32_t chr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Keyboard description
|
||||
*
|
||||
* Each section maps an RDP scancode to a KeySym and a Unicode
|
||||
* character.
|
||||
*/
|
||||
#define INDEX_FROM_SCANCODE(scancode,extended) \
|
||||
(((scancode) & 0x7f) | ((extended) ? 0x80 : 0))
|
||||
|
||||
struct xrdp_keymap
|
||||
{
|
||||
struct xrdp_key_info keys_noshift[256];
|
||||
struct xrdp_key_info keys_shift[256];
|
||||
struct xrdp_key_info keys_altgr[256];
|
||||
struct xrdp_key_info keys_shiftaltgr[256];
|
||||
struct xrdp_key_info keys_capslock[256];
|
||||
struct xrdp_key_info keys_capslockaltgr[256];
|
||||
struct xrdp_key_info keys_shiftcapslock[256];
|
||||
struct xrdp_key_info keys_shiftcapslockaltgr[256];
|
||||
// These arrays are indexed by a return from scancode_to_index()
|
||||
struct xrdp_key_info keys_noshift[SCANCODE_MAX_INDEX + 1];
|
||||
struct xrdp_key_info keys_shift[SCANCODE_MAX_INDEX + 1];
|
||||
struct xrdp_key_info keys_altgr[SCANCODE_MAX_INDEX + 1];
|
||||
struct xrdp_key_info keys_shiftaltgr[SCANCODE_MAX_INDEX + 1];
|
||||
struct xrdp_key_info keys_capslock[SCANCODE_MAX_INDEX + 1];
|
||||
struct xrdp_key_info keys_capslockaltgr[SCANCODE_MAX_INDEX + 1];
|
||||
struct xrdp_key_info keys_shiftcapslock[SCANCODE_MAX_INDEX + 1];
|
||||
struct xrdp_key_info keys_shiftcapslockaltgr[SCANCODE_MAX_INDEX + 1];
|
||||
// NumLock is restricted to a much smaller set of keys
|
||||
struct xrdp_key_info keys_numlock[XR_RDP_SCAN_MAX_NUMLOCK -
|
||||
XR_RDP_SCAN_MIN_NUMLOCK + 1];
|
||||
@ -554,11 +547,12 @@ struct xrdp_wm
|
||||
int current_pointer;
|
||||
int mouse_x;
|
||||
int mouse_y;
|
||||
/* keyboard info */
|
||||
int keys[256]; /* key states 0 up 1 down*/
|
||||
/* keyboard info (indexed by a return from scancode_to_index()) */
|
||||
int keys[SCANCODE_MAX_INDEX + 1]; /* key states 0 up 1 down*/
|
||||
int caps_lock;
|
||||
int scroll_lock;
|
||||
int num_lock;
|
||||
|
||||
/* Unicode input */
|
||||
int last_high_surrogate_key_up;
|
||||
int last_high_surrogate_key_down;
|
||||
|
@ -1569,15 +1569,26 @@ xrdp_wm_mouse_click(struct xrdp_wm *self, int x, int y, int but, int down)
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
xrdp_wm_key(struct xrdp_wm *self, int device_flags, int scan_code)
|
||||
xrdp_wm_key(struct xrdp_wm *self, int keyboard_flags, int key_code)
|
||||
{
|
||||
int msg;
|
||||
struct xrdp_key_info *ki;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG,
|
||||
"xrdp_wm_key: RDP scancode:0x%04x, flags: 0x%04x",
|
||||
scan_code, device_flags);
|
||||
scan_code = scan_code % 128;
|
||||
"xrdp_wm_key: RDP key_code:0x%04x, keyboard_flags: 0x%04x",
|
||||
key_code, keyboard_flags);
|
||||
int scancode = SCANCODE_FROM_KBD_EVENT(key_code, keyboard_flags);
|
||||
int keyup = ((keyboard_flags & KBD_FLAG_UP) != 0);
|
||||
|
||||
int sindex = scancode_to_index(scancode);
|
||||
if (sindex < 0)
|
||||
{
|
||||
// The scancode doesn't map to an index, so we can't handle it here.
|
||||
// Log this so we can investigate
|
||||
LOG(LOG_LEVEL_WARNING, "Ignoring unusable scancode %x (%s)",
|
||||
scancode, (keyup ? "up" : "down"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (self->popup_wnd != 0)
|
||||
{
|
||||
@ -1585,24 +1596,17 @@ xrdp_wm_key(struct xrdp_wm *self, int device_flags, int scan_code)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// workaround odd shift behavior
|
||||
// see https://github.com/neutrinolabs/xrdp/issues/397
|
||||
if (scan_code == 42 && device_flags == (KBD_FLAG_UP | KBD_FLAG_EXT))
|
||||
if (keyup)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (device_flags & KBD_FLAG_UP) /* 0x8000 */
|
||||
{
|
||||
self->keys[scan_code] = 0;
|
||||
self->keys[sindex] = 0;
|
||||
msg = WM_KEYUP;
|
||||
}
|
||||
else /* key down */
|
||||
{
|
||||
self->keys[scan_code] = 1 | device_flags;
|
||||
self->keys[sindex] = 1;
|
||||
msg = WM_KEYDOWN;
|
||||
|
||||
switch (scan_code)
|
||||
switch (key_code)
|
||||
{
|
||||
case 58:
|
||||
self->caps_lock = !self->caps_lock;
|
||||
@ -1618,24 +1622,28 @@ xrdp_wm_key(struct xrdp_wm *self, int device_flags, int scan_code)
|
||||
|
||||
if (self->mm->mod != 0)
|
||||
{
|
||||
// Backend module loaded...
|
||||
if (self->mm->mod->mod_event != 0)
|
||||
{
|
||||
ki = get_key_info_from_scan_code
|
||||
(device_flags, scan_code, self->keys, self->caps_lock,
|
||||
// ..and able to take events. Check the scancode maps to
|
||||
// a real key in the currently loaded keymap
|
||||
ki = get_key_info_from_kbd_event
|
||||
(keyboard_flags, key_code, self->keys, self->caps_lock,
|
||||
self->num_lock, self->scroll_lock,
|
||||
&(self->keymap));
|
||||
|
||||
if (ki != 0)
|
||||
{
|
||||
self->mm->mod->mod_event(self->mm->mod, msg, ki->chr, ki->sym,
|
||||
scan_code, device_flags);
|
||||
key_code, keyboard_flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (self->focused_window != 0)
|
||||
{
|
||||
// Pass keypress on to a widget in the login window
|
||||
xrdp_bitmap_def_proc(self->focused_window,
|
||||
msg, scan_code, device_flags);
|
||||
msg, key_code, keyboard_flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1720,6 +1728,29 @@ get_unicode_character(struct xrdp_wm *self, int device_flags, char16_t c16)
|
||||
return c32;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Takes a scancode index and fakes a keyboard event to represent it
|
||||
* @param self module pointer
|
||||
* @param device_flags default flags to pass in for the keyboard event.
|
||||
* @param scancode index
|
||||
*
|
||||
* Some of the device_flags are overridden by the scancode derived from the
|
||||
* scancode index
|
||||
*/
|
||||
static void
|
||||
fake_kbd_event_from_scancode_index(struct xrdp_wm *self, int device_flags,
|
||||
int index)
|
||||
{
|
||||
int scancode = scancode_from_index(index);
|
||||
int key_code = SCANCODE_TO_KBD_EVENT_KEY_CODE(scancode);
|
||||
|
||||
device_flags &= ~(KBD_FLAG_EXT | KBD_FLAG_EXT1);
|
||||
device_flags |= SCANCODE_TO_KBD_EVENT_KBD_FLAGS(scancode);
|
||||
|
||||
xrdp_wm_key(self, device_flags, key_code);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t c16)
|
||||
@ -1734,40 +1765,40 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t c16)
|
||||
|
||||
// See if we can find the character in the existing keymap,
|
||||
// and if so, generate normal key event(s) for it
|
||||
for (index = XR_MIN_KEY_CODE; index < XR_MAX_KEY_CODE; index++)
|
||||
for (index = 0; index <= SCANCODE_MAX_INDEX; ++index)
|
||||
{
|
||||
if (c32 == self->keymap.keys_noshift[index].chr)
|
||||
{
|
||||
xrdp_wm_key(self, device_flags, index - XR_MIN_KEY_CODE);
|
||||
fake_kbd_event_from_scancode_index(self, device_flags, index);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (index = XR_MIN_KEY_CODE; index < XR_MAX_KEY_CODE; index++)
|
||||
for (index = 0; index <= SCANCODE_MAX_INDEX; ++index)
|
||||
{
|
||||
if (c32 == self->keymap.keys_shift[index].chr)
|
||||
{
|
||||
if (device_flags & KBD_FLAG_UP)
|
||||
{
|
||||
xrdp_wm_key(self, device_flags, index - XR_MIN_KEY_CODE);
|
||||
fake_kbd_event_from_scancode_index(self, device_flags, index);
|
||||
xrdp_wm_key(self, KBD_FLAG_UP, XR_RDP_SCAN_LSHIFT);
|
||||
}
|
||||
else
|
||||
{
|
||||
xrdp_wm_key(self, KBD_FLAG_DOWN, XR_RDP_SCAN_LSHIFT);
|
||||
xrdp_wm_key(self, device_flags, index - XR_MIN_KEY_CODE);
|
||||
fake_kbd_event_from_scancode_index(self, device_flags, index);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (index = XR_MIN_KEY_CODE; index < XR_MAX_KEY_CODE; index++)
|
||||
for (index = 0; index <= SCANCODE_MAX_INDEX; ++index)
|
||||
{
|
||||
if (c32 == self->keymap.keys_altgr[index].chr)
|
||||
{
|
||||
if (device_flags & KBD_FLAG_UP)
|
||||
{
|
||||
xrdp_wm_key(self, device_flags, index - XR_MIN_KEY_CODE);
|
||||
fake_kbd_event_from_scancode_index(self, device_flags, index);
|
||||
xrdp_wm_key(self, KBD_FLAG_UP | KBD_FLAG_EXT,
|
||||
XR_RDP_SCAN_ALT);
|
||||
}
|
||||
@ -1775,19 +1806,19 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t c16)
|
||||
{
|
||||
xrdp_wm_key(self, KBD_FLAG_DOWN | KBD_FLAG_EXT,
|
||||
XR_RDP_SCAN_ALT);
|
||||
xrdp_wm_key(self, device_flags, index - XR_MIN_KEY_CODE);
|
||||
fake_kbd_event_from_scancode_index(self, device_flags, index);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (index = XR_MIN_KEY_CODE; index < XR_MAX_KEY_CODE; index++)
|
||||
for (index = 0; index <= SCANCODE_MAX_INDEX; ++index)
|
||||
{
|
||||
if (c32 == self->keymap.keys_shiftaltgr[index].chr)
|
||||
{
|
||||
if (device_flags & KBD_FLAG_UP)
|
||||
{
|
||||
xrdp_wm_key(self, device_flags, index - XR_MIN_KEY_CODE);
|
||||
fake_kbd_event_from_scancode_index(self, device_flags, index);
|
||||
xrdp_wm_key(self, KBD_FLAG_UP | KBD_FLAG_EXT, XR_RDP_SCAN_ALT);
|
||||
xrdp_wm_key(self, KBD_FLAG_UP, XR_RDP_SCAN_LSHIFT);
|
||||
}
|
||||
@ -1796,7 +1827,7 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t c16)
|
||||
xrdp_wm_key(self, KBD_FLAG_DOWN, XR_RDP_SCAN_LSHIFT);
|
||||
xrdp_wm_key(self, KBD_FLAG_DOWN | KBD_FLAG_EXT,
|
||||
XR_RDP_SCAN_ALT);
|
||||
xrdp_wm_key(self, device_flags, index - XR_MIN_KEY_CODE);
|
||||
fake_kbd_event_from_scancode_index(self, device_flags, index);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
12
xup/xup.c
12
xup/xup.c
@ -266,6 +266,7 @@ lib_mod_event(struct mod *mod, int msg, tbus param1, tbus param2,
|
||||
int len;
|
||||
int key;
|
||||
int rv;
|
||||
int scancode;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "in lib_mod_event");
|
||||
make_stream(s);
|
||||
@ -311,15 +312,8 @@ lib_mod_event(struct mod *mod, int msg, tbus param1, tbus param2,
|
||||
/* xup doesn't need the Unicode character mapping in param1. Send
|
||||
* the X11 scancode instead, so xorgxrdp doesn't have to do this
|
||||
* work again */
|
||||
if ((param4 & KBD_FLAG_EXT) != 0)
|
||||
{
|
||||
// Extended key - set bit 9 of the scancode for the lookup
|
||||
param1 = scancode_to_keycode(param3 | 0x100);
|
||||
}
|
||||
else
|
||||
{
|
||||
param1 = scancode_to_keycode(param3);
|
||||
}
|
||||
scancode = SCANCODE_FROM_KBD_EVENT(param3, param4);
|
||||
param1 = scancode_to_x11_keycode(scancode);
|
||||
}
|
||||
|
||||
init_stream(s, 8192);
|
||||
|
Loading…
Reference in New Issue
Block a user