From 14c045b6f2f3d15996e9c4ee7a852370d341fe66 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Tue, 3 Sep 2013 14:06:32 +0100 Subject: wayland: Use the subsurface protocol to implement GtkClutterEmbed The subsurface protocol lets us "embed" one surface within another. The compositor will compose the two surfaces together to create a single window. We use it here to take the surface we get from Clutter and make that into a subsurface and then associate that subsurface with the main surface coming from GTK+. https://bugzilla.gnome.org/show_bug.cgi?id=695737 --- clutter-gtk/gtk-clutter-embed.c | 100 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/clutter-gtk/gtk-clutter-embed.c b/clutter-gtk/gtk-clutter-embed.c index 14d99bf..adb4407 100644 --- a/clutter-gtk/gtk-clutter-embed.c +++ b/clutter-gtk/gtk-clutter-embed.c @@ -46,6 +46,7 @@ #endif #include +#include #include "gtk-clutter-embed.h" #include "gtk-clutter-offscreen.h" #include "gtk-clutter-actor.h" @@ -66,6 +67,10 @@ #include #endif +#if defined(CLUTTER_WINDOWING_WAYLAND) +#include +#endif + #if defined(GDK_WINDOWING_X11) #include #endif @@ -74,6 +79,14 @@ #include #endif +#if defined(GDK_WINDOWING_WAYLAND) +#include +#endif + +#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND) +#include "subsurface-client-protocol.h" +#endif + G_DEFINE_TYPE (GtkClutterEmbed, gtk_clutter_embed, GTK_TYPE_CONTAINER); #define GTK_CLUTTER_EMBED_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_CLUTTER_TYPE_EMBED, GtkClutterEmbedPrivate)) @@ -92,6 +105,11 @@ struct _GtkClutterEmbedPrivate guint geometry_changed : 1; guint use_layout_size : 1; + +#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND) + struct wl_subcompositor *subcompositor; + struct wl_subsurface *subsurface; +#endif }; enum @@ -363,6 +381,28 @@ gtk_clutter_embed_realize (GtkWidget *widget) } #endif +#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND) + if (priv->subcompositor) + { + GdkDisplay *display; + struct wl_surface *clutter_surface, *gtk_surface; + struct wl_compositor *compositor; + + display = gdk_display_get_default (); + compositor = gdk_wayland_display_get_wl_compositor (display); + clutter_surface = wl_compositor_create_surface (compositor); + gtk_surface = gdk_wayland_window_get_wl_surface (gdk_window_get_toplevel(window)); + clutter_wayland_stage_set_wl_surface (CLUTTER_STAGE (priv->stage), + clutter_surface); + priv->subsurface = + wl_subcompositor_get_subsurface (priv->subcompositor, + clutter_surface, + gtk_surface); + wl_subsurface_set_position (priv->subsurface, allocation.x, allocation.y); + wl_subsurface_set_desync (priv->subsurface); + } +#endif + clutter_actor_realize (priv->stage); if (gtk_widget_get_visible (widget)) @@ -532,8 +572,15 @@ gtk_clutter_embed_size_allocate (GtkWidget *widget, draw before we get the ConfigureNotify response. */ clutter_x11_handle_event ((XEvent *)&xevent); } +#endif +#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND) + if (priv->subsurface) + { + wl_subsurface_set_position (priv->subsurface, allocation->x, allocation->y); + } #endif } + } static gboolean @@ -938,6 +985,40 @@ gtk_clutter_embed_class_init (GtkClutterEmbedClass *klass) g_object_class_install_property (gobject_class, PROP_USE_LAYOUT_SIZE, pspec); } + + +#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND) +static void +registry_handle_global (void *data, + struct wl_registry *registry, + uint32_t name, + const char *interface, + uint32_t version) +{ + GtkClutterEmbed *embed = data; + GtkClutterEmbedPrivate *priv = embed->priv; + + if (strcmp (interface, "wl_subcompositor") == 0) { + priv->subcompositor = wl_registry_bind (registry, + name, + &wl_subcompositor_interface, + 1); + } +} + +static void +registry_handle_global_remove (void *data, + struct wl_registry *registry, + uint32_t name) +{ +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; +#endif + static void gtk_clutter_embed_init (GtkClutterEmbed *embed) { @@ -986,6 +1067,25 @@ gtk_clutter_embed_init (GtkClutterEmbed *embed) g_signal_connect (priv->stage, "queue-relayout", G_CALLBACK (on_stage_queue_relayout), embed); + + +#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND) + { + GdkDisplay *gdk_display = gdk_display_get_default (); + if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WAYLAND) && + GDK_IS_WAYLAND_DISPLAY (gdk_display)) + { + struct wl_display *display; + struct wl_registry *registry; + + display = gdk_wayland_display_get_wl_display (gdk_display); + registry = wl_display_get_registry (display); + wl_registry_add_listener (registry, ®istry_listener, embed); + + wl_display_roundtrip (display); + } + } +#endif } /** -- cgit v1.2.1