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
This commit is contained in:
parent
551a57ed7f
commit
988da215c8
@ -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;
|
||||
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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user