summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2014-09-17 19:45:06 +0200
committerBastien Nocera <hadess@hadess.net>2014-09-17 21:53:40 +0200
commit062ddb71b82a1e44c6c8c8e4d7defb61ca75674b (patch)
tree3accc5bc7ea6b31af79c88abb8fb9d062c5ce44d
parentffe677dd78c5b1e10df51ff2cc659c70587d67d7 (diff)
downloadclutter-gtk-062ddb71b82a1e44c6c8c8e4d7defb61ca75674b.tar.gz
gtk-clutter-embed: Fix hiding embed inside container
Such as the embed inside a GtkStack, as used in Cheese or Totem. With help from Matthias Clasen (positioning inside the window), and Jasper St. Pierre (Wayland API help). https://bugzilla.gnome.org/show_bug.cgi?id=736564
-rw-r--r--clutter-gtk/gtk-clutter-embed.c89
1 files changed, 77 insertions, 12 deletions
diff --git a/clutter-gtk/gtk-clutter-embed.c b/clutter-gtk/gtk-clutter-embed.c
index e2a2ee9..64cc8b6 100644
--- a/clutter-gtk/gtk-clutter-embed.c
+++ b/clutter-gtk/gtk-clutter-embed.c
@@ -104,6 +104,7 @@ struct _GtkClutterEmbedPrivate
#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND)
struct wl_subcompositor *subcompositor;
+ struct wl_surface *clutter_surface;
struct wl_subsurface *subsurface;
#endif
};
@@ -180,6 +181,10 @@ gtk_clutter_embed_dispose (GObject *gobject)
clutter_actor_destroy (priv->stage);
priv->stage = NULL;
+
+#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND)
+ g_clear_pointer (&priv->subsurface, wl_subsurface_destroy);
+#endif
}
G_OBJECT_CLASS (gtk_clutter_embed_parent_class)->dispose (gobject);
@@ -278,6 +283,39 @@ gtk_clutter_embed_draw (GtkWidget *widget, cairo_t *cr)
return GTK_WIDGET_CLASS (gtk_clutter_embed_parent_class)->draw (widget, cr);
}
+#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND)
+static void
+gtk_clutter_embed_ensure_subsurface (GtkClutterEmbed *embed)
+{
+ GtkClutterEmbedPrivate *priv;
+ GtkWidget *widget;
+ struct wl_surface *gtk_surface;
+ GtkAllocation allocation;
+ GdkWindow *window;
+ gint x, y;
+
+ widget = GTK_WIDGET (embed);
+ priv = embed->priv;
+
+ if (priv->subsurface)
+ return;
+
+ gtk_widget_get_allocation (widget, &allocation);
+ window = gtk_widget_get_window (widget);
+ gtk_surface = gdk_wayland_window_get_wl_surface (gdk_window_get_toplevel(window));
+
+ priv->subsurface =
+ wl_subcompositor_get_subsurface (priv->subcompositor,
+ priv->clutter_surface,
+ gtk_surface);
+
+ gtk_widget_translate_coordinates (widget, gtk_widget_get_toplevel (widget), 0, 0, &x, &y);
+ gdk_window_get_origin (gtk_widget_get_parent_window (widget), &x, &y);
+ wl_subsurface_set_position (priv->subsurface, x + allocation.x, y + allocation.y);
+ wl_subsurface_set_desync (priv->subsurface);
+}
+#endif
+
static void
gtk_clutter_embed_realize (GtkWidget *widget)
{
@@ -394,21 +432,13 @@ gtk_clutter_embed_realize (GtkWidget *widget)
if (priv->subcompositor)
{
GdkDisplay *display;
- struct wl_surface *clutter_surface, *gtk_surface;
struct wl_compositor *compositor;
display = gtk_widget_get_display (widget);
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));
+ priv->clutter_surface = wl_compositor_create_surface (compositor);
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);
+ priv->clutter_surface);
}
#endif
@@ -585,7 +615,11 @@ gtk_clutter_embed_size_allocate (GtkWidget *widget,
#endif
#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND)
if (priv->subsurface)
- wl_subsurface_set_position (priv->subsurface, allocation->x, allocation->y);
+ {
+ gint x, y;
+ gdk_window_get_origin (gtk_widget_get_window (widget), &x, &y);
+ wl_subsurface_set_position (priv->subsurface, x, y);
+ }
#endif
}
}
@@ -623,20 +657,50 @@ gtk_clutter_embed_unmap_event (GtkWidget *widget,
clutter_actor_unmap (priv->stage);
+#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND)
+ g_clear_pointer (&priv->subsurface, wl_subsurface_destroy);
+#endif
+
return res;
}
static void
+gtk_clutter_embed_map (GtkWidget *widget)
+{
+ GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (widget)->priv;
+
+#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND)
+ {
+ GdkDisplay *gdk_display = gtk_widget_get_display (widget);
+
+ if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WAYLAND) &&
+ GDK_IS_WAYLAND_DISPLAY (gdk_display))
+ {
+ gtk_clutter_embed_ensure_subsurface (GTK_CLUTTER_EMBED (widget));
+ }
+ }
+#endif
+
+ GTK_WIDGET_CLASS (gtk_clutter_embed_parent_class)->map (widget);
+
+ clutter_actor_map (priv->stage);
+}
+
+static void
gtk_clutter_embed_unmap (GtkWidget *widget)
{
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (widget)->priv;
+ GTK_WIDGET_CLASS (gtk_clutter_embed_parent_class)->unmap (widget);
+
/* gtk may emit an unmap signal after dispose, so it's possible we may
* have already disposed priv->stage. */
if (priv->stage != NULL)
clutter_actor_unmap (priv->stage);
- GTK_WIDGET_CLASS (gtk_clutter_embed_parent_class)->unmap (widget);
+#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND)
+ g_clear_pointer (&priv->subsurface, wl_subsurface_destroy);
+#endif
}
static gboolean
@@ -958,6 +1022,7 @@ gtk_clutter_embed_class_init (GtkClutterEmbedClass *klass)
widget_class->unrealize = gtk_clutter_embed_unrealize;
widget_class->show = gtk_clutter_embed_show;
widget_class->hide = gtk_clutter_embed_hide;
+ widget_class->map = gtk_clutter_embed_map;
widget_class->unmap = gtk_clutter_embed_unmap;
widget_class->map_event = gtk_clutter_embed_map_event;
widget_class->unmap_event = gtk_clutter_embed_unmap_event;