[mutter] wayland/keyboard: Use MetaAnonymousFile to share keymap files



commit 988da215c8e66c20240b0a23a19fcf8e405e64d6
Author: Jonas Dreßler <verdre v0yd nl>
Date:   Fri Jan 17 23:54:31 2020 +0100

    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 <sebastian sebastianwick net>
    
    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 | 103 +++++++++++-------------------------
 src/wayland/meta-wayland-keyboard.h |   4 +-
 2 files changed, 33 insertions(+), 74 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 <errno.h>
-#include <fcntl.h>
 #include <glib.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/mman.h>
 #include <unistd.h>
 
 #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;
-
-  if (!xkb_info->keymap_string)
-    return;
+  size_t size;
+  MetaAnonymousFileMapmode mapmode;
 
-  fd = create_anonymous_file (xkb_info->keymap_size, &error);
-  if (fd < 0)
-    {
-      g_warning ("Creating a keymap file for %lu bytes failed: %s",
-                 (unsigned long) xkb_info->keymap_size,
-                 error->message);
-      g_clear_error (&error);
-      return;
-    }
+  if (wl_resource_get_version (resource) < 7)
+    mapmode = META_ANONYMOUS_FILE_MAPMODE_SHARED;
+  else
+    mapmode = META_ANONYMOUS_FILE_MAPMODE_PRIVATE;
 
+  fd = meta_anonymous_file_open_fd (xkb_info->keymap_rofile, mapmode);
+  size = meta_anonymous_file_size (xkb_info->keymap_rofile);
 
-  keymap_area = mmap (NULL, xkb_info->keymap_size,
-                      PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-  if (keymap_area == MAP_FAILED)
+  if (fd == -1)
     {
-      g_warning ("Failed to mmap() %lu bytes\n",
-                 (unsigned long) xkb_info->keymap_size);
-      close (fd);
+      g_warning ("Creating a keymap file failed: %s", strerror (errno));
       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 <xkbcommon/xkbcommon.h>
 
 #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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]