xwayland: Switch to the new Xwayland DDX

This commit is contained in:
Jasper St. Pierre 2014-03-20 13:12:43 -04:00
parent 43730f1660
commit be02fa1120
7 changed files with 106 additions and 74 deletions

View File

@ -133,7 +133,7 @@ AC_ARG_WITH([wayland-protocols],
AC_ARG_WITH([xwayland-path],
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
[XWAYLAND_PATH="$withval"],
[XWAYLAND_PATH="$bindir/Xorg"])
[XWAYLAND_PATH="$bindir/Xwayland"])
AM_GLIB_GNU_GETTEXT

View File

@ -41,14 +41,11 @@ mutter_built_sources = \
gtk-shell-protocol.c \
gtk-shell-server-protocol.h \
xdg-shell-protocol.c \
xdg-shell-server-protocol.h \
xserver-protocol.c \
xserver-server-protocol.h
xdg-shell-server-protocol.h
wayland_protocols = \
wayland/protocol/gtk-shell.xml \
wayland/protocol/xdg-shell.xml \
wayland/protocol/xserver.xml
wayland/protocol/xdg-shell.xml
libmutter_wayland_la_SOURCES = \
backends/meta-backend.c \
@ -214,8 +211,9 @@ libmutter_wayland_la_SOURCES = \
wayland/meta-wayland.c \
wayland/meta-wayland.h \
wayland/meta-wayland-private.h \
wayland/meta-xwayland-private.h \
wayland/meta-xwayland.c \
wayland/meta-xwayland.h \
wayland/meta-xwayland-private.h \
wayland/meta-wayland-data-device.c \
wayland/meta-wayland-data-device.h \
wayland/meta-wayland-keyboard.c \

View File

@ -39,6 +39,7 @@
#include "x11/window-x11.h"
#include "x11/xprops.h"
#include "wayland/meta-xwayland.h"
#include "wayland/meta-wayland-private.h"
#include "meta-surface-actor-wayland.h"
@ -1536,7 +1537,12 @@ handle_other_xevent (MetaDisplay *display,
case ClientMessage:
if (window)
{
if (!frame_was_receiver)
if (event->xclient.message_type == display->atom_WL_SURFACE_ID)
{
guint32 surface_id = event->xclient.data.l[0];
meta_xwayland_handle_wl_surface_id (window, surface_id);
}
else if (!frame_was_receiver)
meta_window_x11_client_message (window, event);
}
else

View File

@ -81,6 +81,7 @@ item(ATOM_PAIR)
item(BACKLIGHT)
item(_XKB_RULES_NAMES)
item(hotplug_mode_update)
item(WL_SURFACE_ID)
/* Oddities: These are used, and we need atoms for them,
* but when we need all _NET_WM hints (i.e. when we're making

View File

@ -23,6 +23,7 @@
#include "config.h"
#include "meta-xwayland.h"
#include "meta-xwayland-private.h"
#include <glib.h>
@ -36,9 +37,6 @@
#include <sys/wait.h>
#include <stdlib.h>
#include "meta-window-actor-private.h"
#include "xserver-server-protocol.h"
static void
associate_window_with_surface (MetaWindow *window,
MetaWaylandSurface *surface)
@ -58,53 +56,63 @@ associate_window_with_surface (MetaWindow *window,
meta_compositor_window_surface_changed (display->compositor, window);
}
static void
xserver_set_window_id (struct wl_client *client,
struct wl_resource *compositor_resource,
struct wl_resource *surface_resource,
guint32 xid)
static gboolean
associate_window_with_surface_id (MetaXWaylandManager *manager,
MetaWindow *window,
guint32 surface_id)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaDisplay *display = meta_get_display ();
MetaWindow *window;
struct wl_resource *resource;
window = meta_display_lookup_x_window (display, xid);
if (!window)
return;
associate_window_with_surface (window, surface);
resource = wl_client_get_object (manager->client, surface_id);
if (resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
associate_window_with_surface (window, surface);
return TRUE;
}
else
return FALSE;
}
static const struct xserver_interface xserver_implementation = {
xserver_set_window_id
};
typedef struct {
MetaXWaylandManager *manager;
MetaWindow *window;
guint32 surface_id;
} AssociateWindowWithSurfaceOp;
static void
bind_xserver (struct wl_client *client,
void *data,
guint32 version,
guint32 id)
static gboolean
associate_window_with_surface_idle (gpointer user_data)
{
MetaXWaylandManager *manager = data;
AssociateWindowWithSurfaceOp *op = user_data;
if (!associate_window_with_surface_id (op->manager, op->window, op->surface_id))
{
/* Not here? Oh well... nothing we can do */
g_warning ("Unknown surface ID %d (from window %s)", op->surface_id, op->window->desc);
}
g_free (op);
/* If it's a different client than the xserver we launched,
* just freeze up... */
if (client != manager->client)
return;
return G_SOURCE_REMOVE;
}
manager->xserver_resource = wl_resource_create (client, &xserver_interface,
MIN (META_XSERVER_VERSION, version), id);
wl_resource_set_implementation (manager->xserver_resource,
&xserver_implementation, manager, NULL);
void
meta_xwayland_handle_wl_surface_id (MetaWindow *window,
guint32 surface_id)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaXWaylandManager *manager = &compositor->xwayland_manager;
xserver_send_listen_socket (manager->xserver_resource, manager->abstract_fd);
xserver_send_listen_socket (manager->xserver_resource, manager->unix_fd);
/* Make sure xwayland will recieve the above sockets in a finite
* time before unblocking the initialization mainloop since we are
* then going to immediately try and connect to those as the window
* manager. */
wl_client_flush (client);
if (!associate_window_with_surface_id (manager, window, surface_id))
{
/* No surface ID yet... it should arrive after the next
* iteration through the loop, so queue an idle and see
* what happens.
*/
AssociateWindowWithSurfaceOp *op = g_new0 (AssociateWindowWithSurfaceOp, 1);
op->manager = manager;
op->window = window;
op->surface_id = surface_id;
g_idle_add (associate_window_with_surface_idle, op);
}
}
static char *
@ -363,10 +371,6 @@ meta_xwayland_start (MetaXWaylandManager *manager,
if (!choose_xdisplay (manager))
return FALSE;
wl_global_create (wl_display, &xserver_interface,
META_XSERVER_VERSION,
manager, bind_xserver);
/* We want xwayland to be a wayland client so we make a socketpair to setup a
* wayland protocol connection. */
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sp) < 0)
@ -379,7 +383,7 @@ meta_xwayland_start (MetaXWaylandManager *manager,
manager->pid = fork ();
if (manager->pid == 0)
{
char socket_fd[8];
char socket_fd[8], unix_fd[8], abstract_fd[8];
/* We passed SOCK_CLOEXEC, so dup the FD so it isn't
* closed on exec.. */
@ -387,6 +391,12 @@ meta_xwayland_start (MetaXWaylandManager *manager,
snprintf (socket_fd, sizeof (socket_fd), "%d", fd);
setenv ("WAYLAND_SOCKET", socket_fd, TRUE);
fd = dup (manager->abstract_fd);
snprintf (abstract_fd, sizeof (abstract_fd), "%d", fd);
fd = dup (manager->unix_fd);
snprintf (unix_fd, sizeof (unix_fd), "%d", fd);
/* xwayland, please. */
if (getenv ("XWAYLAND_STFU"))
{
@ -403,10 +413,10 @@ meta_xwayland_start (MetaXWaylandManager *manager,
if (execl (XWAYLAND_PATH, XWAYLAND_PATH,
manager->display_name,
"-wayland",
"-rootless",
"-noreset",
"-nolisten", "all",
"-listen", abstract_fd,
"-listen", unix_fd,
NULL) < 0)
{
g_error ("Failed to spawn XWayland: %m");

View File

@ -0,0 +1,35 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef META_XWAYLAND_H
#define META_XWAYLAND_H
#include <glib.h>
#include <meta/types.h>
void
meta_xwayland_handle_wl_surface_id (MetaWindow *window,
guint32 surface_id);
#endif /* META_XWAYLAND_H */

View File

@ -1,18 +0,0 @@
<protocol name="xserver">
<interface name="xserver" version="1">
<request name="set_window_id">
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="id" type="uint"/>
</request>
<event name="client">
<arg name="fd" type="fd"/>
</event>
<event name="listen_socket">
<arg name="fd" type="fd"/>
</event>
</interface>
</protocol>