From 988da215c8e66c20240b0a23a19fcf8e405e64d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= Date: Fri, 17 Jan 2020 23:54:31 +0100 Subject: [PATCH] wayland/keyboard: Use MetaAnonymousFile to share keymap files Since protocol version 7 clients must use MAP_PRIVATE to map the keymap fd, that means we can use memfd_create() to create the fd by using meta_anonymous_file_open_fd() with META_ANONYMOUS_FILE_MAPMODE_PRIVATE, for older versions we use META_ANONYMOUS_FILE_MAPMODE_SHARED to be compatibile with MAP_SHARED. Pretty much all of this code was written for Weston by Sebastian Wick, see https://gitlab.freedesktop.org/wayland/weston/merge_requests/240. Co-authored-by: Sebastian Wick Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1734 https://gitlab.gnome.org/GNOME/mutter/merge_requests/1012 --- src/wayland/meta-wayland-keyboard.c | 105 +++++++++------------------- src/wayland/meta-wayland-keyboard.h | 4 +- 2 files changed, 34 insertions(+), 75 deletions(-) diff --git a/src/wayland/meta-wayland-keyboard.c b/src/wayland/meta-wayland-keyboard.c index 6b6c1f778..cc569faf7 100644 --- a/src/wayland/meta-wayland-keyboard.c +++ b/src/wayland/meta-wayland-keyboard.c @@ -48,15 +48,14 @@ #include "config.h" #include -#include #include #include #include -#include #include #include "backends/meta-backend-private.h" #include "core/display-private.h" +#include "core/meta-anonymous-file.h" #include "wayland/meta-wayland-private.h" #ifdef HAVE_NATIVE_BACKEND @@ -79,86 +78,34 @@ unbind_resource (struct wl_resource *resource) wl_list_remove (wl_resource_get_link (resource)); } -static int -create_anonymous_file (off_t size, - GError **error) -{ - static const char template[] = "mutter-shared-XXXXXX"; - char *path; - int fd, flags; - - fd = g_file_open_tmp (template, &path, error); - - if (fd == -1) - return -1; - - unlink (path); - g_free (path); - - flags = fcntl (fd, F_GETFD); - if (flags == -1) - goto err; - - if (fcntl (fd, F_SETFD, flags | FD_CLOEXEC) == -1) - goto err; - - if (ftruncate (fd, size) < 0) - goto err; - - return fd; - - err: - g_set_error_literal (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), - strerror (errno)); - close (fd); - - return -1; -} - static void send_keymap (MetaWaylandKeyboard *keyboard, struct wl_resource *resource) { MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info; - GError *error = NULL; int fd; - char *keymap_area; + size_t size; + MetaAnonymousFileMapmode mapmode; - if (!xkb_info->keymap_string) - return; + if (wl_resource_get_version (resource) < 7) + mapmode = META_ANONYMOUS_FILE_MAPMODE_SHARED; + else + mapmode = META_ANONYMOUS_FILE_MAPMODE_PRIVATE; - fd = create_anonymous_file (xkb_info->keymap_size, &error); - if (fd < 0) + fd = meta_anonymous_file_open_fd (xkb_info->keymap_rofile, mapmode); + size = meta_anonymous_file_size (xkb_info->keymap_rofile); + + if (fd == -1) { - g_warning ("Creating a keymap file for %lu bytes failed: %s", - (unsigned long) xkb_info->keymap_size, - error->message); - g_clear_error (&error); + g_warning ("Creating a keymap file failed: %s", strerror (errno)); return; } - - keymap_area = mmap (NULL, xkb_info->keymap_size, - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (keymap_area == MAP_FAILED) - { - g_warning ("Failed to mmap() %lu bytes\n", - (unsigned long) xkb_info->keymap_size); - close (fd); - return; - } - - strcpy (keymap_area, xkb_info->keymap_string); - - munmap (keymap_area, xkb_info->keymap_size); - wl_keyboard_send_keymap (resource, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, - fd, - keyboard->xkb_info.keymap_size); - close (fd); + fd, size); + + meta_anonymous_file_close_fd (fd); } static void @@ -177,6 +124,8 @@ meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard, struct xkb_keymap *keymap) { MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info; + char *keymap_string; + size_t keymap_size; if (keymap == NULL) { @@ -184,20 +133,30 @@ meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard, return; } - g_clear_pointer (&xkb_info->keymap_string, g_free); xkb_keymap_unref (xkb_info->keymap); xkb_info->keymap = xkb_keymap_ref (keymap); meta_wayland_keyboard_update_xkb_state (keyboard); - xkb_info->keymap_string = + keymap_string = xkb_keymap_get_as_string (xkb_info->keymap, XKB_KEYMAP_FORMAT_TEXT_V1); - if (!xkb_info->keymap_string) + if (!keymap_string) { g_warning ("Failed to get string version of keymap"); return; } - xkb_info->keymap_size = strlen (xkb_info->keymap_string) + 1; + keymap_size = strlen (keymap_string) + 1; + + xkb_info->keymap_rofile = + meta_anonymous_file_new (keymap_size, (const uint8_t *) keymap_string); + + free (keymap_string); + + if (!xkb_info->keymap_rofile) + { + g_warning ("Failed to create anonymous file for keymap"); + return; + } inform_clients_of_new_keymap (keyboard); @@ -590,7 +549,7 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info) { g_clear_pointer (&xkb_info->keymap, xkb_keymap_unref); g_clear_pointer (&xkb_info->state, xkb_state_unref); - g_clear_pointer (&xkb_info->keymap_string, g_free); + meta_anonymous_file_free (xkb_info->keymap_rofile); } void diff --git a/src/wayland/meta-wayland-keyboard.h b/src/wayland/meta-wayland-keyboard.h index 1dd3b12ba..ac57d7677 100644 --- a/src/wayland/meta-wayland-keyboard.h +++ b/src/wayland/meta-wayland-keyboard.h @@ -49,6 +49,7 @@ #include #include "clutter/clutter.h" +#include "core/meta-anonymous-file.h" #include "wayland/meta-wayland-types.h" #define META_TYPE_WAYLAND_KEYBOARD (meta_wayland_keyboard_get_type ()) @@ -74,8 +75,7 @@ typedef struct { struct xkb_keymap *keymap; struct xkb_state *state; - size_t keymap_size; - char *keymap_string; + MetaAnonymousFile *keymap_rofile; } MetaWaylandXkbInfo; struct _MetaWaylandKeyboard