input: use ro_anonymous_file to minimize duplication of keymap files

Since version 7 clients must use MAP_PRIVATE to map the keymap fd so we
can use memfd_create in os_ro_anonymous_file_get_ref using
RO_ANONYMOUS_FILE_MAPMODE_PRIVATE, for older version we use
RO_ANONYMOUS_FILE_MAPMODE_SHARED to be compatibile with MAP_SHARED.

Signed-off-by: Sebastian Wick <sebastian@sebastianwick.net>
This commit is contained in:
Sebastian Wick 2019-11-01 02:38:45 +01:00
parent ac1b92dfea
commit abec512883
2 changed files with 34 additions and 25 deletions

View File

@ -78,6 +78,7 @@ struct weston_pointer;
struct linux_dmabuf_buffer;
struct weston_recorder;
struct weston_pointer_constraint;
struct ro_anonymous_file;
enum weston_keyboard_modifier {
MODIFIER_CTRL = (1 << 0),
@ -704,8 +705,7 @@ weston_pointer_start_drag(struct weston_pointer *pointer,
struct wl_client *client);
struct weston_xkb_info {
struct xkb_keymap *keymap;
size_t keymap_size;
char *keymap_string;
struct ro_anonymous_file *keymap_rofile;
int32_t ref_count;
xkb_mod_index_t shift_mod;
xkb_mod_index_t caps_mod;

View File

@ -2086,32 +2086,30 @@ WL_EXPORT void
weston_keyboard_send_keymap(struct weston_keyboard *kbd, struct wl_resource *resource)
{
struct weston_xkb_info *xkb_info = kbd->xkb_info;
void *area;
int fd;
size_t size;
enum ro_anonymous_file_mapmode mapmode;
fd = os_create_anonymous_file(xkb_info->keymap_size);
if (fd < 0) {
weston_log("creating a keymap file for %lu bytes failed: %s\n",
(unsigned long) xkb_info->keymap_size,
if (wl_resource_get_version(resource) < 7)
mapmode = RO_ANONYMOUS_FILE_MAPMODE_SHARED;
else
mapmode = RO_ANONYMOUS_FILE_MAPMODE_PRIVATE;
fd = os_ro_anonymous_file_get_fd(xkb_info->keymap_rofile, mapmode);
size = os_ro_anonymous_file_size(xkb_info->keymap_rofile);
if (fd == -1) {
weston_log("creating a keymap file failed: %s\n",
strerror(errno));
return;
}
area = mmap(NULL, xkb_info->keymap_size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (area == MAP_FAILED) {
weston_log("failed to mmap() %lu bytes\n",
(unsigned long) xkb_info->keymap_size);
goto err_mmap;
}
strcpy(area, xkb_info->keymap_string);
munmap(area, xkb_info->keymap_size);
wl_keyboard_send_keymap(resource,
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
fd,
xkb_info->keymap_size);
err_mmap:
close(fd);
size);
os_ro_anonymous_file_put_fd(fd);
}
static void
@ -3149,8 +3147,7 @@ weston_xkb_info_destroy(struct weston_xkb_info *xkb_info)
xkb_keymap_unref(xkb_info->keymap);
if (xkb_info->keymap_string)
free(xkb_info->keymap_string);
os_ro_anonymous_file_destroy(xkb_info->keymap_rofile);
free(xkb_info);
}
@ -3171,6 +3168,8 @@ weston_compositor_xkb_destroy(struct weston_compositor *ec)
static struct weston_xkb_info *
weston_xkb_info_create(struct xkb_keymap *keymap)
{
char *keymap_string;
size_t keymap_size;
struct weston_xkb_info *xkb_info = zalloc(sizeof *xkb_info);
if (xkb_info == NULL)
return NULL;
@ -3202,13 +3201,22 @@ weston_xkb_info_create(struct xkb_keymap *keymap)
xkb_info->scroll_led = xkb_keymap_led_get_index(xkb_info->keymap,
XKB_LED_NAME_SCROLL);
xkb_info->keymap_string = xkb_keymap_get_as_string(xkb_info->keymap,
keymap_string = xkb_keymap_get_as_string(xkb_info->keymap,
XKB_KEYMAP_FORMAT_TEXT_V1);
if (xkb_info->keymap_string == NULL) {
if (keymap_string == NULL) {
weston_log("failed to get string version of keymap\n");
goto err_keymap;
}
xkb_info->keymap_size = strlen(xkb_info->keymap_string) + 1;
keymap_size = strlen(keymap_string) + 1;
xkb_info->keymap_rofile = os_ro_anonymous_file_create(keymap_size,
keymap_string);
free(keymap_string);
if (!xkb_info->keymap_rofile) {
weston_log("failed to create anonymous file for keymap\n");
goto err_keymap;
}
return xkb_info;
@ -3441,7 +3449,8 @@ weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
wl_signal_init(&seat->destroy_signal);
wl_signal_init(&seat->updated_caps_signal);
seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 7,
seat->global = wl_global_create(ec->wl_display, &wl_seat_interface,
MIN(wl_seat_interface.version, 7),
seat, bind_seat);
seat->compositor = ec;