Add support for keymaps with no Caps Lock key

The Colemak keyboard does not have a Caps Lock key:-

1) Keyboard files have a caps_lock_supported flag added to the [General]
   section. This is set to false if the keyboardlayout does not have a
   Caps Lock key.
2) The caps_lock_supported flag is parsed when reading keymap files
   for the login screen/VNC.
3) The flag is also checked when telling xorgxrdp what the scancode for
   the caps lock key is.
This commit is contained in:
matt335672
2024-11-18 15:43:33 +00:00
parent 25e5612ca3
commit cbf5f7aae8
2 changed files with 139 additions and 7 deletions
+136 -7
View File
@@ -37,6 +37,21 @@
((d) >= 'a' && (d) <= 'f') ? (d) - 'a' + 10 : \
(d) - 'A' + 10)
/*
* Struct representing the contents of a km file [General] section
*/
struct km_general
{
unsigned int version;
int caps_lock_supported;
};
const struct km_general km_general_default =
{
.version = 0,
.caps_lock_supported = 1
};
/*****************************************************************************/
struct xrdp_key_info *
get_key_info_from_kbd_event(int keyboard_flags, int key_code, int *keys,
@@ -53,6 +68,9 @@ get_key_info_from_kbd_event(int keyboard_flags, int key_code, int *keys,
rv = 0;
index = scancode_to_index(SCANCODE_FROM_KBD_EVENT(key_code, keyboard_flags));
// Don't take caps_lock into account if the keymap doesn't support it.
caps_lock = caps_lock && keymap->caps_lock_supported;
if (index >= 0)
{
// scancode_to_index() guarantees to map numlock scancodes
@@ -353,6 +371,101 @@ get_keymaps(int keylayout, struct xrdp_keymap *keymap)
return 0;
}
/*****************************************************************************/
/**
* Parses the [General] section in a keymap file
* @param tfile TOML file in memory
* @param general result (initialised to defaults)
*/
static void
parse_km_general(toml_table_t *tfile, struct km_general *general)
{
toml_table_t *section;
if (tfile != NULL && (section = toml_table_in(tfile, "General")) != NULL)
{
toml_datum_t d;
if ((d = toml_int_in(section, "version")).ok)
{
general->version = d.u.i;
}
if ((d = toml_bool_in(section, "caps_lock_supported")).ok)
{
general->caps_lock_supported = d.u.b;
}
}
}
/*****************************************************************************/
/**
* Loads the [General] section only from a TOML file
* @param filename Name of TOML file
* @param quiet Set true to not log errors
* @param[out] km_general Contents of [General] section. Defaults are provided.
* @return 0 if the operation was successful
*/
static int
km_load_file_general(const char *filename, int quiet,
struct km_general *general)
{
FILE *fp;
toml_table_t *tfile;
char errbuf[200];
int rv = 1;
*general = km_general_default;
if ((fp = fopen(filename, "r")) == NULL)
{
if (!quiet)
{
LOG(LOG_LEVEL_ERROR, "Error loading keymap file %s (%s)",
filename, g_get_strerror());
}
}
else
{
tfile = toml_parse_file(fp, errbuf, sizeof(errbuf));
fclose(fp);
if (tfile == NULL)
{
if (!quiet)
{
LOG(LOG_LEVEL_ERROR, "Error in keymap file %s - %s",
filename, errbuf);
}
}
else
{
parse_km_general(tfile, general);
rv = 0;
toml_free(tfile);
}
}
return rv;
}
/*****************************************************************************/
/**
* Boolean to test if a keylayout supports the caps_lock modifier key
* @param keylayout keyboardLayout from TS_UD_CS_CORE (see [MS-RDPBCGR])
* @return True if layout supports caps lock
*/
static int
keylayout_supports_caps_lock(int keylayout)
{
char filename[256];
struct km_general general;
g_snprintf(filename, sizeof(filename),
XRDP_CFG_PATH "/km-%08x.toml", keylayout);
(void)km_load_file_general(filename, 1, &general);
return general.caps_lock_supported;
}
/*****************************************************************************/
int
km_load_file(const char *filename, struct xrdp_keymap *keymap)
@@ -361,6 +474,7 @@ km_load_file(const char *filename, struct xrdp_keymap *keymap)
toml_table_t *tfile;
char errbuf[200];
int rv = 0;
struct km_general general = km_general_default;
if ((fp = fopen(filename, "r")) == NULL)
{
@@ -382,16 +496,23 @@ km_load_file(const char *filename, struct xrdp_keymap *keymap)
/* Clear the whole keymap */
memset(keymap, 0, sizeof(*keymap));
/* Check to see if we should expect caps lock entries */
parse_km_general(tfile, &general);
keymap->caps_lock_supported = general.caps_lock_supported;
/* read the keymap sections */
km_read_section(tfile, "noshift", keymap->keys_noshift);
km_read_section(tfile, "shift", keymap->keys_shift);
km_read_section(tfile, "altgr", keymap->keys_altgr);
km_read_section(tfile, "shiftaltgr", keymap->keys_shiftaltgr);
km_read_section(tfile, "capslock", keymap->keys_capslock);
km_read_section(tfile, "capslockaltgr", keymap->keys_capslockaltgr);
km_read_section(tfile, "shiftcapslock", keymap->keys_shiftcapslock);
km_read_section(tfile, "shiftcapslockaltgr",
keymap->keys_shiftcapslockaltgr);
if (keymap->caps_lock_supported)
{
km_read_section(tfile, "capslock", keymap->keys_capslock);
km_read_section(tfile, "capslockaltgr", keymap->keys_capslockaltgr);
km_read_section(tfile, "shiftcapslock", keymap->keys_shiftcapslock);
km_read_section(tfile, "shiftcapslockaltgr",
keymap->keys_shiftcapslockaltgr);
}
/* The numlock map is much smaller and offset by
* SCANCODE_MIX_NUMLOCK. Read the section into a temporary
@@ -657,8 +778,16 @@ xrdp_init_xkb_layout(struct xrdp_client_info *client_info)
// Initialise the rules and a few keycodes for xorgxrdp
snprintf(client_info->xkb_rules, sizeof(client_info->xkb_rules),
"%s", scancode_get_xkb_rules());
client_info->x11_keycode_caps_lock =
scancode_to_x11_keycode(SCANCODE_CAPS_KEY);
if (keylayout_supports_caps_lock(client_info->keylayout))
{
client_info->x11_keycode_caps_lock =
scancode_to_x11_keycode(SCANCODE_CAPS_KEY);
}
else
{
LOG(LOG_LEVEL_INFO, "xrdp_init_xkb_layout: caps lock is not supported");
client_info->x11_keycode_caps_lock = 0;
}
client_info->x11_keycode_num_lock =
scancode_to_x11_keycode(SCANCODE_NUMLOCK_KEY);
client_info->x11_keycode_scroll_lock =
+3
View File
@@ -462,6 +462,9 @@ struct xrdp_key_info
struct xrdp_keymap
{
// Are the caps lock maps populated?
int caps_lock_supported;
// 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];