|
|
776610 |
From 0d134522d83ee263cdc83ea899af59fd264bafa7 Mon Sep 17 00:00:00 2001
|
|
|
776610 |
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
|
776610 |
Date: Thu, 29 Jun 2017 12:22:47 +0800
|
|
|
776610 |
Subject: [PATCH] wayland/keyboard: Create a separate keymap shm file per
|
|
|
776610 |
resource
|
|
|
776610 |
|
|
|
776610 |
By using the shm file when sending the keymap to all clients, we
|
|
|
776610 |
effectively allows any client to change the keymap, as any client has
|
|
|
776610 |
the ability to change the content of the file. Sending a read-only file
|
|
|
776610 |
descriptor, or making the file itself read-only before unlinking, can
|
|
|
776610 |
be worked around by the client by using chmod(2) and open(2) on
|
|
|
776610 |
/proc/<pid>/<fd>.
|
|
|
776610 |
|
|
|
776610 |
Using memfd could potentially solve this issue, but as the usage of
|
|
|
776610 |
mmap with MAP_SHARED is wide spread among clients, such a change can
|
|
|
776610 |
not be introduced without causing wide spread compatibility issues.
|
|
|
776610 |
|
|
|
776610 |
So, to avoid allowing clients to interfere with each other, create a
|
|
|
776610 |
separate shm file for each wl_keyboard resource when sending the
|
|
|
776610 |
keymap. We could eventually do this per client, but in most cases,
|
|
|
776610 |
there will only be one wl_keyboard resource per client anyway.
|
|
|
776610 |
|
|
|
776610 |
https://bugzilla.gnome.org/show_bug.cgi?id=784206
|
|
|
776610 |
---
|
|
|
776610 |
src/wayland/meta-wayland-keyboard.c | 136 +++++++++++-----------------
|
|
|
776610 |
src/wayland/meta-wayland-keyboard.h | 3 +-
|
|
|
776610 |
2 files changed, 56 insertions(+), 83 deletions(-)
|
|
|
776610 |
|
|
|
776610 |
diff --git a/src/wayland/meta-wayland-keyboard.c b/src/wayland/meta-wayland-keyboard.c
|
|
|
776610 |
index 167293ca7..aca1fe411 100644
|
|
|
776610 |
--- a/src/wayland/meta-wayland-keyboard.c
|
|
|
776610 |
+++ b/src/wayland/meta-wayland-keyboard.c
|
|
|
776610 |
@@ -127,34 +127,65 @@ create_anonymous_file (off_t size,
|
|
|
776610 |
}
|
|
|
776610 |
|
|
|
776610 |
static void
|
|
|
776610 |
-inform_clients_of_new_keymap (MetaWaylandKeyboard *keyboard)
|
|
|
776610 |
+send_keymap (MetaWaylandKeyboard *keyboard,
|
|
|
776610 |
+ struct wl_resource *resource)
|
|
|
776610 |
{
|
|
|
776610 |
- struct wl_resource *keyboard_resource;
|
|
|
776610 |
+ MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
|
|
|
776610 |
+ GError *error = NULL;
|
|
|
776610 |
+ int fd;
|
|
|
776610 |
+ char *keymap_area;
|
|
|
776610 |
|
|
|
776610 |
- wl_resource_for_each (keyboard_resource, &keyboard->resource_list)
|
|
|
776610 |
+ if (!xkb_info->keymap_string)
|
|
|
776610 |
+ return;
|
|
|
776610 |
+
|
|
|
776610 |
+ fd = create_anonymous_file (xkb_info->keymap_size, &error);
|
|
|
776610 |
+ if (fd < 0)
|
|
|
776610 |
{
|
|
|
776610 |
- wl_keyboard_send_keymap (keyboard_resource,
|
|
|
776610 |
- WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
|
|
|
776610 |
- keyboard->xkb_info.keymap_fd,
|
|
|
776610 |
- keyboard->xkb_info.keymap_size);
|
|
|
776610 |
+ g_warning ("Creating a keymap file for %lu bytes failed: %s",
|
|
|
776610 |
+ (unsigned long) xkb_info->keymap_size,
|
|
|
776610 |
+ error->message);
|
|
|
776610 |
+ g_clear_error (&error);
|
|
|
776610 |
+ return;
|
|
|
776610 |
}
|
|
|
776610 |
- wl_resource_for_each (keyboard_resource, &keyboard->focus_resource_list)
|
|
|
776610 |
+
|
|
|
776610 |
+
|
|
|
776610 |
+ keymap_area = mmap (NULL, xkb_info->keymap_size,
|
|
|
776610 |
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
|
|
776610 |
+ if (keymap_area == MAP_FAILED)
|
|
|
776610 |
{
|
|
|
776610 |
- wl_keyboard_send_keymap (keyboard_resource,
|
|
|
776610 |
- WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
|
|
|
776610 |
- keyboard->xkb_info.keymap_fd,
|
|
|
776610 |
- keyboard->xkb_info.keymap_size);
|
|
|
776610 |
+ g_warning ("Failed to mmap() %lu bytes\n",
|
|
|
776610 |
+ (unsigned long) xkb_info->keymap_size);
|
|
|
776610 |
+ close (fd);
|
|
|
776610 |
+ return;
|
|
|
776610 |
}
|
|
|
776610 |
+
|
|
|
776610 |
+ strcpy (keymap_area, xkb_info->keymap_string);
|
|
|
776610 |
+
|
|
|
776610 |
+ munmap (keymap_area, xkb_info->keymap_size);
|
|
|
776610 |
+
|
|
|
776610 |
+ wl_keyboard_send_keymap (resource,
|
|
|
776610 |
+ WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
|
|
|
776610 |
+ fd,
|
|
|
776610 |
+ keyboard->xkb_info.keymap_size);
|
|
|
776610 |
+ close (fd);
|
|
|
776610 |
+}
|
|
|
776610 |
+
|
|
|
776610 |
+static void
|
|
|
776610 |
+inform_clients_of_new_keymap (MetaWaylandKeyboard *keyboard)
|
|
|
776610 |
+{
|
|
|
776610 |
+ struct wl_resource *keyboard_resource;
|
|
|
776610 |
+
|
|
|
776610 |
+ wl_resource_for_each (keyboard_resource, &keyboard->resource_list)
|
|
|
776610 |
+ send_keymap (keyboard, keyboard_resource);
|
|
|
776610 |
+ wl_resource_for_each (keyboard_resource, &keyboard->focus_resource_list)
|
|
|
776610 |
+ send_keymap (keyboard, keyboard_resource);
|
|
|
776610 |
}
|
|
|
776610 |
|
|
|
776610 |
static void
|
|
|
776610 |
meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
|
|
|
776610 |
struct xkb_keymap *keymap)
|
|
|
776610 |
{
|
|
|
776610 |
- MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
|
|
|
776610 |
- GError *error = NULL;
|
|
|
776610 |
- char *keymap_str;
|
|
|
776610 |
- size_t previous_size;
|
|
|
776610 |
+ MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
|
|
|
776610 |
|
|
|
776610 |
if (keymap == NULL)
|
|
|
776610 |
{
|
|
|
776610 |
@@ -162,60 +193,24 @@ meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
|
|
|
776610 |
return;
|
|
|
776610 |
}
|
|
|
776610 |
|
|
|
776610 |
+ g_clear_pointer (&xkb_info->keymap_string, g_free);
|
|
|
776610 |
xkb_keymap_unref (xkb_info->keymap);
|
|
|
776610 |
xkb_info->keymap = xkb_keymap_ref (keymap);
|
|
|
776610 |
|
|
|
776610 |
meta_wayland_keyboard_update_xkb_state (keyboard);
|
|
|
776610 |
|
|
|
776610 |
- keymap_str = xkb_map_get_as_string (xkb_info->keymap);
|
|
|
776610 |
- if (keymap_str == NULL)
|
|
|
776610 |
+ xkb_info->keymap_string =
|
|
|
776610 |
+ xkb_keymap_get_as_string (xkb_info->keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
|
|
|
776610 |
+ if (!xkb_info->keymap_string)
|
|
|
776610 |
{
|
|
|
776610 |
- g_warning ("failed to get string version of keymap");
|
|
|
776610 |
+ g_warning ("Failed to get string version of keymap");
|
|
|
776610 |
return;
|
|
|
776610 |
}
|
|
|
776610 |
- previous_size = xkb_info->keymap_size;
|
|
|
776610 |
- xkb_info->keymap_size = strlen (keymap_str) + 1;
|
|
|
776610 |
-
|
|
|
776610 |
- if (xkb_info->keymap_fd >= 0)
|
|
|
776610 |
- close (xkb_info->keymap_fd);
|
|
|
776610 |
-
|
|
|
776610 |
- xkb_info->keymap_fd = create_anonymous_file (xkb_info->keymap_size, &error);
|
|
|
776610 |
- if (xkb_info->keymap_fd < 0)
|
|
|
776610 |
- {
|
|
|
776610 |
- g_warning ("creating a keymap file for %lu bytes failed: %s",
|
|
|
776610 |
- (unsigned long) xkb_info->keymap_size,
|
|
|
776610 |
- error->message);
|
|
|
776610 |
- g_clear_error (&error);
|
|
|
776610 |
- goto err_keymap_str;
|
|
|
776610 |
- }
|
|
|
776610 |
-
|
|
|
776610 |
- if (xkb_info->keymap_area)
|
|
|
776610 |
- munmap (xkb_info->keymap_area, previous_size);
|
|
|
776610 |
-
|
|
|
776610 |
- xkb_info->keymap_area = mmap (NULL, xkb_info->keymap_size,
|
|
|
776610 |
- PROT_READ | PROT_WRITE,
|
|
|
776610 |
- MAP_SHARED, xkb_info->keymap_fd, 0);
|
|
|
776610 |
- if (xkb_info->keymap_area == MAP_FAILED)
|
|
|
776610 |
- {
|
|
|
776610 |
- g_warning ("failed to mmap() %lu bytes\n",
|
|
|
776610 |
- (unsigned long) xkb_info->keymap_size);
|
|
|
776610 |
- goto err_dev_zero;
|
|
|
776610 |
- }
|
|
|
776610 |
- strcpy (xkb_info->keymap_area, keymap_str);
|
|
|
776610 |
- free (keymap_str);
|
|
|
776610 |
+ xkb_info->keymap_size = strlen (xkb_info->keymap_string) + 1;
|
|
|
776610 |
|
|
|
776610 |
inform_clients_of_new_keymap (keyboard);
|
|
|
776610 |
|
|
|
776610 |
notify_modifiers (keyboard);
|
|
|
776610 |
-
|
|
|
776610 |
- return;
|
|
|
776610 |
-
|
|
|
776610 |
-err_dev_zero:
|
|
|
776610 |
- close (xkb_info->keymap_fd);
|
|
|
776610 |
- xkb_info->keymap_fd = -1;
|
|
|
776610 |
-err_keymap_str:
|
|
|
776610 |
- free (keymap_str);
|
|
|
776610 |
- return;
|
|
|
776610 |
}
|
|
|
776610 |
|
|
|
776610 |
static xkb_mod_mask_t
|
|
|
776610 |
@@ -707,28 +702,12 @@ meta_wayland_keyboard_enable (MetaWaylandKeyboard *keyboard)
|
|
|
776610 |
maybe_restore_numlock_state (keyboard);
|
|
|
776610 |
}
|
|
|
776610 |
|
|
|
776610 |
-static void
|
|
|
776610 |
-meta_wayland_xkb_info_init (MetaWaylandXkbInfo *xkb_info)
|
|
|
776610 |
-{
|
|
|
776610 |
- xkb_info->keymap_fd = -1;
|
|
|
776610 |
-}
|
|
|
776610 |
-
|
|
|
776610 |
static void
|
|
|
776610 |
meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
|
|
|
776610 |
{
|
|
|
776610 |
g_clear_pointer (&xkb_info->keymap, xkb_keymap_unref);
|
|
|
776610 |
g_clear_pointer (&xkb_info->state, xkb_state_unref);
|
|
|
776610 |
-
|
|
|
776610 |
- if (xkb_info->keymap_area)
|
|
|
776610 |
- {
|
|
|
776610 |
- munmap (xkb_info->keymap_area, xkb_info->keymap_size);
|
|
|
776610 |
- xkb_info->keymap_area = NULL;
|
|
|
776610 |
- }
|
|
|
776610 |
- if (xkb_info->keymap_fd >= 0)
|
|
|
776610 |
- {
|
|
|
776610 |
- close (xkb_info->keymap_fd);
|
|
|
776610 |
- xkb_info->keymap_fd = -1;
|
|
|
776610 |
- }
|
|
|
776610 |
+ g_clear_pointer (&xkb_info->keymap_string, g_free);
|
|
|
776610 |
}
|
|
|
776610 |
|
|
|
776610 |
void
|
|
|
776610 |
@@ -1001,10 +980,7 @@ meta_wayland_keyboard_create_new_resource (MetaWaylandKeyboard *keyboard,
|
|
|
776610 |
wl_resource_set_implementation (resource, &keyboard_interface,
|
|
|
776610 |
keyboard, unbind_resource);
|
|
|
776610 |
|
|
|
776610 |
- wl_keyboard_send_keymap (resource,
|
|
|
776610 |
- WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
|
|
|
776610 |
- keyboard->xkb_info.keymap_fd,
|
|
|
776610 |
- keyboard->xkb_info.keymap_size);
|
|
|
776610 |
+ send_keymap (keyboard, resource);
|
|
|
776610 |
|
|
|
776610 |
notify_key_repeat_for_resource (keyboard, resource);
|
|
|
776610 |
|
|
|
776610 |
@@ -1050,8 +1026,6 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard)
|
|
|
776610 |
wl_list_init (&keyboard->resource_list);
|
|
|
776610 |
wl_list_init (&keyboard->focus_resource_list);
|
|
|
776610 |
|
|
|
776610 |
- meta_wayland_xkb_info_init (&keyboard->xkb_info);
|
|
|
776610 |
-
|
|
|
776610 |
keyboard->default_grab.interface = &default_keyboard_grab_interface;
|
|
|
776610 |
keyboard->default_grab.keyboard = keyboard;
|
|
|
776610 |
keyboard->grab = &keyboard->default_grab;
|
|
|
776610 |
diff --git a/src/wayland/meta-wayland-keyboard.h b/src/wayland/meta-wayland-keyboard.h
|
|
|
776610 |
index 39f06ef17..dba9fda0c 100644
|
|
|
776610 |
--- a/src/wayland/meta-wayland-keyboard.h
|
|
|
776610 |
+++ b/src/wayland/meta-wayland-keyboard.h
|
|
|
776610 |
@@ -74,9 +74,8 @@ typedef struct
|
|
|
776610 |
{
|
|
|
776610 |
struct xkb_keymap *keymap;
|
|
|
776610 |
struct xkb_state *state;
|
|
|
776610 |
- int keymap_fd;
|
|
|
776610 |
size_t keymap_size;
|
|
|
776610 |
- char *keymap_area;
|
|
|
776610 |
+ char *keymap_string;
|
|
|
776610 |
} MetaWaylandXkbInfo;
|
|
|
776610 |
|
|
|
776610 |
struct _MetaWaylandKeyboard
|
|
|
776610 |
--
|
|
|
776610 |
2.19.0
|
|
|
776610 |
|