load the rdp to X11 keybaord mappings from file

This commit is contained in:
Jay Sorg 2014-07-31 16:17:19 -07:00
parent d99181aa78
commit 4ef60f163d
3 changed files with 228 additions and 43 deletions

View File

@ -220,6 +220,195 @@ hex_str_to_bin(char *in, char *out, int out_len)
}
}
/*****************************************************************************/
static void APP_CC
xrdp_load_keyboard_layout(struct xrdp_client_info *client_info)
{
int fd;
int index = 0;
struct list *names = (struct list *)NULL;
struct list *items = (struct list *)NULL;
struct list *values = (struct list *)NULL;
char *item = (char *)NULL;
char *value = (char *)NULL;
char *q = (char *)NULL;
char keyboard_cfg_file[256] = { 0 };
char rdp_layout[256] = { 0 };
/* infer model/variant */
/* TODO specify different X11 keyboard models/variants */
g_memset(client_info->model, 0, sizeof(client_info->model));
g_memset(client_info->variant, 0, sizeof(client_info->variant));
g_strncpy(client_info->layout, "us", sizeof(client_info->layout) - 1);
if (client_info->keyboard_subtype == 3)
{
/* macintosh keyboard */
g_strncpy(client_info->variant, "mac", sizeof(client_info->variant) - 1);
}
else if (client_info->keyboard_subtype == 0)
{
/* default - standard subtype */
client_info->keyboard_subtype = 1;
}
g_snprintf(keyboard_cfg_file, 255, "%s/xrdp_keyboard.ini", XRDP_CFG_PATH);
DEBUG(("keyboard_cfg_file %s", keyboard_cfg_file));
fd = g_file_open(keyboard_cfg_file);
if (fd > 0)
{
int section_found = -1;
char section_rdp_layouts[256] = { 0 };
char section_layouts_map[256] = { 0 };
names = list_create();
names->auto_free = 1;
items = list_create();
items->auto_free = 1;
values = list_create();
values->auto_free = 1;
file_read_sections(fd, names);
for (index = 0; index < names->count; index++)
{
q = (char *)list_get_item(names, index);
if (g_strncasecmp("default", q, 8) != 0)
{
int i;
file_read_section(fd, q, items, values);
for (i = 0; i < items->count; i++)
{
item = (char *)list_get_item(items, i);
value = (char *)list_get_item(values, i);
if (g_strcasecmp(item, "keyboard_type") == 0)
{
int v = g_atoi(value);
if (v == client_info->keyboard_type)
{
section_found = index;
}
}
else if (g_strcasecmp(item, "keyboard_subtype") == 0)
{
int v = g_atoi(value);
if (v != client_info->keyboard_subtype &&
section_found == index)
{
section_found = -1;
break;
}
}
else if (g_strcasecmp(item, "rdp_layouts") == 0)
{
if (section_found != -1 && section_found == index)
{
g_strncpy(section_rdp_layouts, value, 255);
}
}
else if (g_strcasecmp(item, "layouts_map") == 0)
{
if (section_found != -1 && section_found == index)
{
g_strncpy(section_layouts_map, value, 255);
}
}
else if (g_strcasecmp(item, "model") == 0)
{
if (section_found != -1 && section_found == index)
{
g_memset(client_info->model, 0, sizeof(client_info->model) - 1);
g_strncpy(client_info->model, value, sizeof(client_info->model) - 1);
}
}
else if (g_strcasecmp(item, "variant") == 0)
{
if (section_found != -1 && section_found == index)
{
g_memset(client_info->variant, 0, sizeof(client_info->variant) - 1);
g_strncpy(client_info->variant, value, sizeof(client_info->variant) - 1);
}
}
else
{
/*
* mixing items from different sections will result in
* skipping over current section.
*/
DEBUG(("xrdp_load_keyboard_layout: skipping configuration item - %s, continuing to next section", item));
break;
}
}
list_clear(items);
list_clear(values);
}
}
if (section_found == -1)
{
g_memset(section_rdp_layouts, 0, sizeof(char) * 256);
g_memset(section_layouts_map, 0, sizeof(char) * 256);
// read default section
file_read_section(fd, "default", items, values);
for (index = 0; index < items->count; index++)
{
item = (char *)list_get_item(items, index);
value = (char *)list_get_item(values, index);
if (g_strcasecmp(item, "rdp_layouts") == 0)
{
g_strncpy(section_rdp_layouts, value, 255);
}
else if (g_strcasecmp(item, "layouts_map") == 0)
{
g_strncpy(section_layouts_map, value, 255);
}
}
list_clear(items);
list_clear(values);
}
// load the map
file_read_section(fd, section_rdp_layouts, items, values);
for (index = 0; index < items->count; index++)
{
int rdp_layout_id;
item = (char *)list_get_item(items, index);
value = (char *)list_get_item(values, index);
rdp_layout_id = g_htoi(value);
if (rdp_layout_id == client_info->keylayout)
{
g_strncpy(rdp_layout, item, 255);
break;
}
}
list_clear(items);
list_clear(values);
file_read_section(fd, section_layouts_map, items, values);
for (index = 0; index < items->count; index++)
{
item = (char *)list_get_item(items, index);
value = (char *)list_get_item(values, index);
if (g_strcasecmp(item, rdp_layout) == 0)
{
g_strncpy(client_info->layout, value, sizeof(client_info->layout) - 1);
break;
}
}
list_delete(names);
list_delete(items);
list_delete(values);
DEBUG(("xrdp_load_keyboard_layout: model %s variant %s layout %s",
client_info->model, client_info->variant, client_info->layout));
g_file_close(fd);
}
}
/*****************************************************************************/
struct xrdp_sec *APP_CC
xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans)
@ -1853,6 +2042,7 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self)
in_uint8s(s, 79);
in_uint32_le(s, client_info->keyboard_type);
in_uint32_le(s, client_info->keyboard_subtype);
xrdp_load_keyboard_layout(client_info);
s->p = s->data;
return 0;
}

View File

@ -282,7 +282,7 @@ rdpChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
/******************************************************************************/
int
rdpLoadLayout(int keylayout)
rdpLoadLayout(struct xrdp_client_info *client_info)
{
XkbRMLVOSet set;
XkbSrvInfoPtr xkbi;
@ -292,8 +292,10 @@ rdpLoadLayout(int keylayout)
KeyCode first_key;
CARD8 num_keys;
LLOGLN(0, ("rdpLoadLayout: keylayout 0x%8.8x display %s",
keylayout, display));
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));
if (g_use_evdev)
{
@ -303,42 +305,26 @@ rdpLoadLayout(int keylayout)
{
set.rules = "base";
}
set.model = "pc104";
set.layout = "us";
switch (keylayout)
{
case 0x00000407: /* German */
set.layout = "de";
break;
case 0x00000409: /* US */
set.layout = "us";
break;
case 0x0000040C: /* French */
set.layout = "fr";
break;
case 0x00000410: /* Italian */
set.layout = "it";
break;
case 0x00000416: /* Portuguese (Brazilian ABNT) */
set.model = "abnt2";
set.layout = "br";
break;
case 0x00000419: /* Russian */
set.layout = "ru";
break;
case 0x0000041D: /* Swedish */
set.layout = "se";
break;
case 0x00000816: /* Portuguese */
set.layout = "pt";
break;
default:
LLOGLN(0, ("rdpLoadLayout: unknown keylayout 0x%8.8x", keylayout));
break;
}
set.variant = "";
set.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;
}
retry:
/* free some stuff so we can call InitKeyboardDeviceStruct again */
xkbi = g_keyboard->key->xkbInfo;
xkb = xkbi->desc;
@ -355,21 +341,30 @@ rdpLoadLayout(int keylayout)
rdpChangeKeyboardControl))
{
LLOGLN(0, ("rdpLoadLayout: InitKeyboardDeviceStruct failed"));
return 1;
}
/* notify the X11 clients eg. X_ChangeKeyboardMapping */
keySyms = XkbGetCoreMap(g_keyboard);
first_key = keySyms->minKeyCode;
num_keys = (keySyms->maxKeyCode - keySyms->minKeyCode) + 1;
XkbApplyMappingChange(g_keyboard, keySyms, first_key, num_keys,
NULL, serverClient);
for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
if (keySyms)
{
if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key)
first_key = keySyms->minKeyCode;
num_keys = (keySyms->maxKeyCode - keySyms->minKeyCode) + 1;
XkbApplyMappingChange(g_keyboard, keySyms, first_key, num_keys,
NULL, serverClient);
for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
{
XkbApplyMappingChange(pDev, keySyms, first_key, num_keys,
NULL, serverClient);
if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key)
{
XkbApplyMappingChange(pDev, keySyms, first_key, num_keys,
NULL, serverClient);
}
}
} else
{
/* sometimes, variant doesn't support all layouts */
set.variant = "";
goto retry;
}
return 0;

View File

@ -1117,7 +1117,7 @@ rdpup_process_msg(struct stream *s)
g_do_multimon = 0;
}
rdpLoadLayout(g_rdpScreen.client_info.keylayout);
rdpLoadLayout(&(g_rdpScreen.client_info));
}
else if (msg_type == 105)