Skip to content

Commit

Permalink
Unify keyboard layout change code
Browse files Browse the repository at this point in the history
The keyboard layout is set when the keyboard is initialised and when
a client connects.

When the X server is started and the keyboard is initialised,
client layout info is unavailable. Therefore, a default layout
is set. Subsequent calls are made when a client connects to the X
server. These calls set the client layout for the currently connected
RDP client.

The amount of time which may elapse between the X server starting and
the first RDP client connecting may be considerable - a session could
be started without a client using xrdp-sesrun. Or, it may be only a
second or so, if the X server is started by a connection to xrdp.

The two codepaths for setting the layout are separate. The initialisation
codepath appears to be deficient in that the layout is not also set
on inputInfo.keyboard. This seems to cause problems where X11 clients
can end up loading the wrong layout where an RDP client has not yet
connected. See (for example):-

neutrinolabs/xrdp#1721

This is pretty rare, but when it happens is difficult to debug.

This commit unifies the codepaths so that the same code is always used
when the layout changes.
  • Loading branch information
matt335672 committed Aug 12, 2024
1 parent 24b4d1e commit a0c3fd3
Showing 1 changed file with 67 additions and 54 deletions.
121 changes: 67 additions & 54 deletions xrdpkeyb/rdpKeyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ xrdp keyboard module
#define LLOGLN(_level, _args) \
do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0)

/* A few hard-coded evdev keycodes (see g_evdev_str) */
#define CAPS_LOCK_KEY_CODE 66
#define NUM_LOCK_KEY_CODE 77
#define SCROLL_LOCK_KEY_CODE 78

static char g_evdev_str[] = "evdev";
static char g_pc104_str[] = "pc104";
static char g_us_str[] = "us";
Expand Down Expand Up @@ -393,7 +398,6 @@ static int
rdpkeybControl(DeviceIntPtr device, int what)
{
DevicePtr pDev;
XkbRMLVOSet set;
rdpPtr dev;

LLOGLN(0, ("rdpkeybControl: what %d", what));
Expand All @@ -402,16 +406,9 @@ rdpkeybControl(DeviceIntPtr device, int what)
switch (what)
{
case DEVICE_INIT:
memset(&set, 0, sizeof(set));
set.rules = g_evdev_str;
set.model = g_pc104_str;
set.layout = g_us_str;
set.variant = g_empty_str;
set.options = g_empty_str;
InitKeyboardDeviceStruct(device, &set, rdpkeybBell,
rdpkeybChangeKeyboardControl);
dev = rdpGetDevFromScreen(NULL);
dev->keyboard.device = device;
rdpLoadLayout(&(dev->keyboard), NULL);
rdpRegisterInputCallback(0, rdpInputKeyboard);
break;
case DEVICE_ON:
Expand Down Expand Up @@ -517,29 +514,35 @@ rdpkeybUnplug(pointer p)
static int
reload_xkb(DeviceIntPtr keyboard, XkbRMLVOSet *set)
{
XkbSrvInfoPtr xkbi;
XkbDescPtr xkb;
KeySymsPtr keySyms;
KeyCode first_key;
CARD8 num_keys;
DeviceIntPtr pDev;

/* free some stuff so we can call InitKeyboardDeviceStruct again */
xkbi = keyboard->key->xkbInfo;
xkb = xkbi->desc;
XkbFreeKeyboard(xkb, 0, TRUE);
free(xkbi);
keyboard->key->xkbInfo = NULL;
free(keyboard->kbdfeed);
keyboard->kbdfeed = NULL;
free(keyboard->key);
keyboard->key = NULL;
if (keyboard->key != NULL)
{
XkbSrvInfoPtr xkbi = keyboard->key->xkbInfo;
if (xkbi != NULL)
{
XkbDescPtr xkb = xkbi->desc;
if (xkb != NULL)
{
XkbFreeKeyboard(xkb, 0, TRUE);
}
free(xkbi);
}
free(keyboard->kbdfeed);
keyboard->kbdfeed = NULL;
free(keyboard->key);
keyboard->key = NULL;
}

/* init keyboard and reload the map */
if (!InitKeyboardDeviceStruct(keyboard, set, rdpkeybBell,
rdpkeybChangeKeyboardControl))
{
LLOGLN(0, ("rdpLoadLayout: InitKeyboardDeviceStruct failed"));
LLOGLN(0, ("reload_xkb: InitKeyboardDeviceStruct failed"));
return 1;
}

Expand Down Expand Up @@ -573,48 +576,58 @@ reload_xkb(DeviceIntPtr keyboard, XkbRMLVOSet *set)
static int
rdpLoadLayout(rdpKeyboard *keyboard, struct xrdp_client_info *client_info)
{
XkbRMLVOSet set;

int keylayout = client_info->keylayout;

LLOGLN(0, ("rdpLoadLayout: keylayout 0x%8.8x variant %s display %s",
keylayout, client_info->variant, display));
memset(&set, 0, sizeof(set));
set.rules = g_evdev_str;

set.model = g_pc104_str;
set.layout = g_us_str;
set.variant = g_empty_str;
set.options = g_empty_str;

if (strlen(client_info->model) > 0)
// Load default layout parameters
XkbRMLVOSet set =
{
set.model = client_info->model;
}
if (strlen(client_info->variant) > 0)
.rules = g_evdev_str,
.model = g_pc104_str,
.layout = g_us_str,
.variant = g_empty_str,
.options = g_empty_str
};

if (client_info != NULL)
{
set.variant = client_info->variant;
}
if (strlen(client_info->layout) > 0)
{
set.layout = client_info->layout;
}
if (strlen(client_info->options) > 0)
{
set.options = client_info->options;
if (strlen(client_info->model) > 0)
{
set.model = client_info->model;
}
if (strlen(client_info->variant) > 0)
{
set.variant = client_info->variant;
}
if (strlen(client_info->layout) > 0)
{
set.layout = client_info->layout;
}
if (strlen(client_info->options) > 0)
{
set.options = client_info->options;
}
if (strlen(client_info->xkb_rules) > 0)
{
set.rules = client_info->xkb_rules;
}

/* X11 keycodes needed to sync the keyboard */
keyboard->x11_keycode_caps_lock = client_info->x11_keycode_caps_lock;
keyboard->x11_keycode_num_lock = client_info->x11_keycode_num_lock;
keyboard->x11_keycode_scroll_lock = client_info->x11_keycode_scroll_lock;
}
if (strlen(client_info->xkb_rules) > 0)
else
{
set.rules = client_info->xkb_rules;
keyboard->x11_keycode_caps_lock = CAPS_LOCK_KEY_CODE;
keyboard->x11_keycode_num_lock = NUM_LOCK_KEY_CODE;
keyboard->x11_keycode_scroll_lock = SCROLL_LOCK_KEY_CODE;
}

LLOGLN(0, ("rdpLoadLayout: rules=\"%s\" model=\"%s\" variant=\"%s\""
"layout=\"%s\" options=\"%s\"",
set.rules, set.model, set.variant, set.layout, set.options));

reload_xkb(keyboard->device, &set);
reload_xkb(inputInfo.keyboard, &set);

/* Copy X11 keycodes needed to sync the keyboard */
keyboard->x11_keycode_caps_lock = client_info->x11_keycode_caps_lock;
keyboard->x11_keycode_num_lock = client_info->x11_keycode_num_lock;
keyboard->x11_keycode_scroll_lock = client_info->x11_keycode_scroll_lock;
return 0;
}

Expand Down

0 comments on commit a0c3fd3

Please sign in to comment.