mirror of https://github.com/neutrinolabs/xrdp
load the rdp to X11 keybaord mappings from file
This commit is contained in:
parent
d99181aa78
commit
4ef60f163d
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue