[mutter/wip/wayland] Start to integrate wayland client support into core
- From: Robert Bragg <rbragg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/wayland] Start to integrate wayland client support into core
- Date: Wed, 25 Jan 2012 14:36:51 +0000 (UTC)
commit b8a06aeae159650288b60b03b2920451a982abbd
Author: Robert Bragg <robert linux intel com>
Date: Mon Jan 23 15:34:43 2012 +0000
Start to integrate wayland client support into core
Instead of wayland clients being handled in a totally side-band way,
this patch enables us to create a MetaWindow for client wayland surfaces
as well as corresponding MetaWindowActors and MetaShapeTexture actors.
src/compositor/meta-shaped-texture.c | 13 ++-
src/compositor/meta-shaped-texture.h | 6 +-
src/compositor/meta-window-actor.c | 26 +++++--
src/core/window-private.h | 24 ++++++
src/core/window.c | 149 ++++++++++++++++++++++++++--------
src/wayland/meta-wayland-private.h | 9 ++-
src/wayland/meta-wayland.c | 100 ++++++++++++++++-------
7 files changed, 249 insertions(+), 78 deletions(-)
---
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index f17312c..ab12eba 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -704,16 +704,14 @@ meta_shaped_texture_queue_damage_redraw (ClutterWaylandSurface *surface,
#endif /* HAVE_WAYLAND */
ClutterActor *
-meta_shaped_texture_new (Window xwindow)
+meta_shaped_texture_new_with_surface (MetaWaylandSurface *surface)
{
- MetaWaylandSurface *surface = meta_wayland_lookup_surface_for_xid (xwindow);
-
if (surface)
{
ClutterWaylandSurface *wayland_surface;
ClutterActor *actor =
g_object_new (META_TYPE_SHAPED_TEXTURE,
- "surface", surface->wayland_surface, NULL);
+ "surface", &surface->wayland_surface, NULL);
/* XXX: This is a bit messy but meta-wayland.c wants a reference
* to the corresponding surface actor so that it can pass on
@@ -736,6 +734,13 @@ meta_shaped_texture_new (Window xwindow)
return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
}
+ClutterActor *
+meta_shaped_texture_new_with_xwindow (Window xwindow)
+{
+ MetaWaylandSurface *surface = meta_wayland_lookup_surface_for_xid (xwindow);
+ return meta_shaped_texture_new_with_surface (surface);
+}
+
void
meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
gboolean create_mipmaps)
diff --git a/src/compositor/meta-shaped-texture.h b/src/compositor/meta-shaped-texture.h
index 3152154..ed8a8c0 100644
--- a/src/compositor/meta-shaped-texture.h
+++ b/src/compositor/meta-shaped-texture.h
@@ -33,6 +33,7 @@
#ifdef HAVE_WAYLAND
#include <wayland-server.h>
+#include "meta-wayland-private.h"
#endif
G_BEGIN_DECLS
@@ -62,7 +63,10 @@ struct _MetaShapedTexture
GType meta_shaped_texture_get_type (void) G_GNUC_CONST;
-ClutterActor *meta_shaped_texture_new (Window xwindow);
+ClutterActor *meta_shaped_texture_new_with_xwindow (Window xwindow);
+#ifdef HAVE_WAYLAND
+ClutterActor *meta_shaped_texture_new_with_surface (MetaWaylandSurface *surface);
+#endif
void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
gboolean create_mipmaps);
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 1c615f7..7c2b46a 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -376,7 +376,10 @@ meta_window_actor_constructed (GObject *object)
if (!priv->actor)
{
- priv->actor = meta_shaped_texture_new (xwindow);
+ if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
+ priv->actor = meta_shaped_texture_new_with_xwindow (xwindow);
+ else
+ priv->actor = meta_shaped_texture_new_with_surface (window->surface);
clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->actor);
@@ -1576,13 +1579,22 @@ meta_window_actor_new (MetaWindow *window)
MetaFrame *frame;
Window top_window;
- frame = meta_window_get_frame (window);
- if (frame)
- top_window = meta_frame_get_xwindow (frame);
- else
- top_window = meta_window_get_xwindow (window);
+ if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
+ {
+ frame = meta_window_get_frame (window);
+ if (frame)
+ top_window = meta_frame_get_xwindow (frame);
+ else
+ top_window = meta_window_get_xwindow (window);
- meta_verbose ("add window: Meta %p, xwin 0x%x\n", window, (guint)top_window);
+ meta_verbose ("add window: Meta %p, xwin 0x%x\n", window, (guint)top_window);
+ }
+ else
+ {
+ meta_verbose ("add window: Meta %p, wayland surface %p\n",
+ window, window->surface);
+ top_window = None;
+ }
self = g_object_new (META_TYPE_WINDOW_ACTOR,
"meta-window", window,
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 6d23086..4c1d62a 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -44,6 +44,17 @@
#include <X11/Xutil.h>
#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
+#ifdef HAVE_WAYLAND
+#include "meta-wayland-private.h"
+#endif
+
+/* XXX: We should find a nicer approach to deal with the
+ * circular dependency we have with the current headers
+ * (meta-wayland-private.h which typedefs MetaWaylandSurface
+ * also includes window-private.h) */
+#ifndef HAVE_META_WAYLAND_SURFACE_TYPE
+typedef struct _MetaWaylandSurface MetaWaylandSurface;
+#endif
typedef struct _MetaWindowQueue MetaWindowQueue;
@@ -62,6 +73,11 @@ typedef enum {
#define NUMBER_OF_QUEUES 3
+typedef enum {
+ META_WINDOW_CLIENT_TYPE_WAYLAND,
+ META_WINDOW_CLIENT_TYPE_X11
+} MetaWindowClientType;
+
struct _MetaWindow
{
GObject parent_instance;
@@ -70,6 +86,10 @@ struct _MetaWindow
MetaScreen *screen;
const MetaMonitorInfo *monitor;
MetaWorkspace *workspace;
+#ifdef HAVE_WAYLAND
+ MetaWindowClientType client_type;
+ MetaWaylandSurface *surface;
+#endif
Window xwindow;
/* may be NULL! not all windows get decorated */
MetaFrame *frame;
@@ -454,6 +474,10 @@ MetaWindow* meta_window_new_with_attrs (MetaDisplay *display,
gboolean must_be_viewable,
MetaCompEffect effect,
XWindowAttributes *attrs);
+MetaWindow *meta_window_new_for_wayland (MetaDisplay *display,
+ int width,
+ int height,
+ MetaWaylandSurface *surface);
void meta_window_unmanage (MetaWindow *window,
guint32 timestamp);
void meta_window_calc_showing (MetaWindow *window);
diff --git a/src/core/window.c b/src/core/window.c
index 74594fa..4e94e9b 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -749,12 +749,14 @@ meta_window_should_attach_to_parent (MetaWindow *window)
}
}
-MetaWindow*
-meta_window_new_with_attrs (MetaDisplay *display,
- Window xwindow,
- gboolean must_be_viewable,
- MetaCompEffect effect,
- XWindowAttributes *attrs)
+static MetaWindow*
+meta_window_new_full (MetaDisplay *display,
+ MetaWindowClientType client_type,
+ MetaWaylandSurface *surface,
+ Window xwindow,
+ gboolean must_be_viewable,
+ MetaCompEffect effect,
+ XWindowAttributes *attrs)
{
MetaWindow *window;
GSList *tmp;
@@ -770,7 +772,8 @@ meta_window_new_with_attrs (MetaDisplay *display,
meta_verbose ("Attempting to manage 0x%lx\n", xwindow);
- if (meta_display_xwindow_is_a_no_focus_window (display, xwindow))
+ if (client_type == META_WINDOW_CLIENT_TYPE_X11 &&
+ meta_display_xwindow_is_a_no_focus_window (display, xwindow))
{
meta_verbose ("Not managing no_focus_window 0x%lx\n",
xwindow);
@@ -861,34 +864,40 @@ meta_window_new_with_attrs (MetaDisplay *display,
meta_error_trap_push_with_return (display);
- /*
- * XAddToSaveSet can only be called on windows created by a different client.
- * with Mutter we want to be able to create manageable windows from within
- * the process (such as a dummy desktop window), so we do not want this
- * call failing to prevent the window from being managed -- wrap it in its
- * own error trap (we use the _with_return() version here to ensure that
- * XSync() is done on the pop, otherwise the error will not get caught).
- */
- meta_error_trap_push_with_return (display);
- XAddToSaveSet (display->xdisplay, xwindow);
- meta_error_trap_pop_with_return (display);
-
- event_mask =
- PropertyChangeMask | EnterWindowMask | LeaveWindowMask |
- FocusChangeMask | ColormapChangeMask;
- if (attrs->override_redirect)
- event_mask |= StructureNotifyMask;
-
- /* If the window is from this client (a menu, say) we need to augment
- * the event mask, not replace it. For windows from other clients,
- * attrs->your_event_mask will be empty at this point.
- */
- XSelectInput (display->xdisplay, xwindow, attrs->your_event_mask | event_mask);
+ if (client_type == META_WINDOW_CLIENT_TYPE_X11)
+ {
+ /*
+ * XAddToSaveSet can only be called on windows created by a different
+ * client. with Mutter we want to be able to create manageable windows
+ * from within the process (such as a dummy desktop window), so we do not
+ * want this call failing to prevent the window from being managed --
+ * wrap it in its own error trap (we use the _with_return() version here
+ * to ensure that XSync() is done on the pop, otherwise the error will
+ * not get caught).
+ */
+ meta_error_trap_push_with_return (display);
+ XAddToSaveSet (display->xdisplay, xwindow);
+ meta_error_trap_pop_with_return (display);
+
+ event_mask =
+ PropertyChangeMask | EnterWindowMask | LeaveWindowMask |
+ FocusChangeMask | ColormapChangeMask;
+ if (attrs->override_redirect)
+ event_mask |= StructureNotifyMask;
+
+ /* If the window is from this client (a menu, say) we need to augment the
+ * event mask, not replace it. For windows from other clients,
+ * attrs->your_event_mask will be empty at this point.
+ */
+ XSelectInput (display->xdisplay, xwindow,
+ attrs->your_event_mask | event_mask);
+ }
has_shape = FALSE;
has_input_shape = FALSE;
#ifdef HAVE_SHAPE
- if (META_DISPLAY_HAS_SHAPE (display))
+ if (META_DISPLAY_HAS_SHAPE (display) &&
+ client_type == META_WINDOW_CLIENT_TYPE_X11)
{
int x_bounding, y_bounding, x_clip, y_clip;
unsigned w_bounding, h_bounding, w_clip, h_clip;
@@ -967,6 +976,10 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->dialog_pid = -1;
+#ifdef HAVE_WAYLAND
+ window->client_type = client_type;
+ window->surface = surface;
+#endif
window->xwindow = xwindow;
/* this is in window->screen->display, but that's too annoying to
@@ -1093,7 +1106,11 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->mwm_has_move_func = TRUE;
window->mwm_has_resize_func = TRUE;
- window->decorated = TRUE;
+ if (client_type == META_WINDOW_CLIENT_TYPE_X11)
+ window->decorated = TRUE;
+ else
+ window->decorated = FALSE;
+
window->has_close_func = TRUE;
window->has_minimize_func = TRUE;
window->has_maximize_func = TRUE;
@@ -1159,7 +1176,8 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->has_resize_func = FALSE;
}
- meta_display_register_x_window (display, &window->xwindow, window);
+ if (client_type == META_WINDOW_CLIENT_TYPE_X11)
+ meta_display_register_x_window (display, &window->xwindow, window);
/* Assign this #MetaWindow a sequence number which can be used
* for sorting.
@@ -1174,7 +1192,8 @@ meta_window_new_with_attrs (MetaDisplay *display,
meta_window_load_initial_properties (window);
- if (!window->override_redirect)
+ if (!window->override_redirect &&
+ client_type == META_WINDOW_CLIENT_TYPE_X11)
{
update_sm_hints (window); /* must come after transient_for */
@@ -1461,6 +1480,68 @@ meta_window_new_with_attrs (MetaDisplay *display,
return window;
}
+#ifdef HAVE_WAYLAND
+MetaWindow *
+meta_window_new_for_wayland (MetaDisplay *display,
+ int width,
+ int height,
+ MetaWaylandSurface *surface)
+{
+ XWindowAttributes attrs;
+ MetaScreen *scr = display->screens->data;
+ MetaWindow *window;
+
+ attrs.x = 0;
+ attrs.y = 0;
+ attrs.width = width;
+ attrs.height = height;
+ attrs.border_width = 0;
+ attrs.depth = 24;
+ attrs.visual = NULL;
+ attrs.root = scr->xroot;
+ attrs.class = InputOutput;
+ attrs.bit_gravity = NorthWestGravity;
+ attrs.win_gravity = NorthWestGravity;
+ attrs.backing_store = 0;
+ attrs.backing_planes = ~0;
+ attrs.backing_pixel = 0;
+ attrs.save_under = 0;
+ attrs.colormap = 0;
+ attrs.map_installed = 1;
+ attrs.map_state = IsViewable;
+ attrs.all_event_masks = ~0;
+ attrs.your_event_mask = 0;
+ attrs.do_not_propagate_mask = 0;
+ attrs.override_redirect = 0;
+ attrs.screen = scr->xscreen;
+
+ window = meta_window_new_full (display,
+ META_WINDOW_CLIENT_TYPE_WAYLAND,
+ surface,
+ None,
+ TRUE,
+ META_COMP_EFFECT_NONE,
+ &attrs);
+ return window;
+}
+#endif
+
+MetaWindow*
+meta_window_new_with_attrs (MetaDisplay *display,
+ Window xwindow,
+ gboolean must_be_viewable,
+ MetaCompEffect effect,
+ XWindowAttributes *attrs)
+{
+ return meta_window_new_full (display,
+ META_WINDOW_CLIENT_TYPE_X11,
+ NULL,
+ xwindow,
+ must_be_viewable,
+ effect,
+ attrs);
+}
+
/* This function should only be called from the end of meta_window_new_with_attrs () */
static void
meta_window_apply_session_info (MetaWindow *window,
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index 840e1ab..24576b8 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -38,7 +38,7 @@ typedef struct
struct wl_listener buffer_destroy_listener;
} MetaWaylandBuffer;
-typedef struct
+struct _MetaWaylandSurface
{
struct wl_surface wayland_surface;
MetaWaylandCompositor *compositor;
@@ -46,10 +46,15 @@ typedef struct
int x;
int y;
MetaWaylandBuffer *buffer;
+ MetaWindow *window;
ClutterActor *actor;
gboolean has_shell_surface;
struct wl_listener surface_destroy_listener;
-} MetaWaylandSurface;
+};
+
+#ifndef HAVE_META_WAYLAND_SURFACE_TYPE
+typedef struct _MetaWaylandSurface MetaWaylandSurface;
+#endif
typedef struct
{
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 1cbaaa9..00cb5f3 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -239,7 +239,7 @@ meta_wayland_surface_attach_buffer (struct wl_client *wayland_client,
struct wl_buffer *wayland_buffer = wayland_buffer_resource->data;
MetaWaylandBuffer *buffer = wayland_buffer->user_data;
MetaWaylandSurface *surface = wayland_surface_resource->data;
- MetaWaylandCompositor *compositor = surface->compositor;
+ //MetaWaylandCompositor *compositor = surface->compositor;
ClutterWaylandSurface *surface_actor;
/* XXX: in the case where we are reattaching the same buffer we can
@@ -262,18 +262,6 @@ meta_wayland_surface_attach_buffer (struct wl_client *wayland_client,
buffer->surfaces_attached_to = g_list_prepend (buffer->surfaces_attached_to,
surface);
- /* NB: Surfaces from xwayland are dealt with via MetaShapedTexture
- * actors */
- if (wayland_client != compositor->xwayland_client)
- {
- if (!surface->actor)
- {
- surface->actor = clutter_wayland_surface_new (&surface->wayland_surface);
- clutter_container_add_actor (CLUTTER_CONTAINER (compositor->stage),
- surface->actor);
- }
- }
-
/* XXX: Its a bit messy but even though xwayland surfaces are
* handled separately we still set surface->actor to the
* MetaShapedTexture actor thats created for a MetaWindowActor.
@@ -390,28 +378,37 @@ meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
}
static void
+surface_actor_destroyed_cb (void *user_data,
+ GObject *old_object)
+{
+ MetaWaylandSurface *surface = user_data;
+
+ surface->actor = NULL;
+ surface->window = NULL;
+}
+
+static void
meta_wayland_surface_free (MetaWaylandSurface *surface)
{
MetaWaylandCompositor *compositor = surface->compositor;
compositor->surfaces = g_list_remove (compositor->surfaces, surface);
meta_wayland_surface_detach_buffer (surface);
- /* XXX: This is a bit messy, but we only own surface->actor if
- * its a ClutterWaylandSurface. Surfaces that correspond to X
- * applications will have MetaShapedTexture actors and those are
- * owned by a MetaWindowActor.
- *
- * TODO: find a neater way of separating things.
- */
- if (surface->actor && CLUTTER_WAYLAND_IS_SURFACE (surface->actor))
+ if (surface->actor)
+ g_object_weak_unref (G_OBJECT (surface->actor),
+ surface_actor_destroyed_cb,
+ surface);
+
+ /* NB: If the surface corresponds to an X window then we will be
+ * sure to free the MetaWindow according to some X event. */
+ if (surface->window &&
+ surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
{
- clutter_actor_destroy (surface->actor);
+ MetaDisplay *display = meta_get_display ();
+ guint32 timestamp = meta_display_get_current_time_roundtrip (display);
+ meta_window_unmanage (surface->window, timestamp);
}
- if (surface->actor)
- g_object_remove_weak_pointer (G_OBJECT (surface->actor),
- (void **)&surface->actor);
-
g_slice_free (MetaWaylandSurface, surface);
meta_wayland_compositor_repick (compositor);
@@ -588,6 +585,46 @@ static void
shell_surface_set_toplevel (struct wl_client *client,
struct wl_resource *resource)
{
+ MetaWaylandCompositor *compositor = &_meta_wayland_compositor;
+ MetaWaylandShellSurface *shell_surface = resource->data;
+ MetaWaylandSurface *surface = shell_surface->surface;
+ MetaDisplay *display = meta_get_display ();
+
+ /* NB: Surfaces from xwayland become managed based on X events. */
+ if (client == compositor->xwayland_client)
+ return;
+
+ if (!surface->window)
+ {
+ int width, height;
+
+ if (surface->buffer && surface->buffer->wayland_buffer)
+ {
+ struct wl_buffer *buffer = surface->buffer->wayland_buffer;
+ width = buffer->width;
+ height = buffer->width;
+ }
+ else
+ {
+ width = 0;
+ height = 0;
+ }
+
+ surface->window =
+ meta_window_new_for_wayland (display, width, height, surface);
+
+ /* The new MetaWindow should always result in us creating a corresponding
+ * MetaWindowActor which will be immediately associated with the given
+ * surface... */
+ g_assert (surface->actor);
+
+ /* If the MetaWindow becomes unmanaged (surface->actor will be freed in
+ * this case) we need to make sure to clear our ->actor and ->window
+ * pointers. */
+ g_object_weak_ref (G_OBJECT (surface->actor),
+ surface_actor_destroyed_cb,
+ surface);
+ }
}
static void
@@ -999,12 +1036,15 @@ xserver_set_window_id (struct wl_client *client,
surface->buffer->wayland_buffer,
NULL);
+ surface->window = window;
surface->actor = surface_actor;
- /* If the MetaWindow becomes unmanaged (surface->actor will be freed
- * in this case) we need to make sure to clear our pointer. */
- g_object_add_weak_pointer (G_OBJECT (surface->actor),
- (void **)&surface->actor);
+ /* If the MetaWindow becomes unmanaged (surface->actor will be freed in
+ * this case) we need to make sure to clear our ->actor and ->window
+ * pointers in this case. */
+ g_object_weak_ref (G_OBJECT (surface->actor),
+ surface_actor_destroyed_cb,
+ surface);
#if 0
if (window->visible_to_compositor)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]