Bug 1337369 - [Wayland] add routines to map/unmap wl_surface as overlay for MozContainer, r?jhorak draft
authorMartin Stransky <stransky@redhat.com>
Tue, 24 Oct 2017 14:34:45 +0200
changeset 685394 b743e00d60342f5d12611de499a71d0e35a8587f
parent 685393 096fdf2c5494d4931e95c9d4547bcbc2529c98e4
child 685395 b51fbda7c466f40d3f9020f4cd90e44ac069f1ad
push id85908
push userstransky@redhat.com
push dateTue, 24 Oct 2017 13:27:47 +0000
reviewersjhorak
bugs1337369
milestone58.0a1
Bug 1337369 - [Wayland] add routines to map/unmap wl_surface as overlay for MozContainer, r?jhorak MozReview-Commit-ID: Jn1fJSMlHnP
widget/gtk/mozcontainer.cpp
--- a/widget/gtk/mozcontainer.cpp
+++ b/widget/gtk/mozcontainer.cpp
@@ -213,16 +213,79 @@ moz_container_init (MozContainer *contai
           wl_registry_add_listener(registry, &registry_listener, container);
           wl_display_dispatch(display);
           wl_display_roundtrip(display);
         }
     }
 #endif
 }
 
+#if defined(MOZ_WAYLAND)
+/* We want to draw to GdkWindow owned by mContainer from Compositor thread but
+ * Gtk+ can be used in main thread only. So we create wayland wl_surface
+ * and attach it as an overlay to GdkWindow.
+ *
+ * see gtk_clutter_embed_ensure_subsurface() at gtk-clutter-embed.c
+*  for reference.
+ */
+static gboolean
+moz_container_map_surface(MozContainer *container)
+{
+    GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(container));
+    if (GDK_IS_X11_DISPLAY(display))
+        return false;
+
+    if (container->subsurface && container->surface)
+        return true;
+
+    if (!container->surface) {
+        struct wl_compositor *compositor;
+        compositor = gdk_wayland_display_get_wl_compositor(display);
+        container->surface = wl_compositor_create_surface(compositor);
+    }
+
+    if (!container->subsurface) {
+        GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
+        wl_surface* gtk_surface = gdk_wayland_window_get_wl_surface(window);
+        if (!gtk_surface) {
+          // We requested the underlying wl_surface too early when container
+          // is not realized yet. We'll try again before first rendering
+          // to mContainer.
+          return false;
+        }
+
+        container->subsurface =
+          wl_subcompositor_get_subsurface (container->subcompositor,
+                                           container->surface,
+                                           gtk_surface);
+        gint x, y;
+        gdk_window_get_position(window, &x, &y);
+        wl_subsurface_set_position(container->subsurface, x, y);
+        wl_subsurface_set_desync(container->subsurface);
+
+        // Route input to parent wl_surface owned by Gtk+ so we get input
+        // events from Gtk+.
+        GdkDisplay* display = gtk_widget_get_display(GTK_WIDGET (container));
+        wl_compositor* compositor = gdk_wayland_display_get_wl_compositor(display);
+        wl_region* region = wl_compositor_create_region(compositor);
+        wl_surface_set_input_region(container->surface, region);
+        wl_region_destroy(region);
+    }
+    return true;
+}
+
+static void
+moz_container_unmap_surface(MozContainer *container)
+{
+    g_clear_pointer(&container->subsurface, wl_subsurface_destroy);
+    g_clear_pointer(&container->surface, wl_surface_destroy);
+}
+
+#endif
+
 void
 moz_container_map (GtkWidget *widget)
 {
     MozContainer *container;
     GList *tmp_list;
     GtkWidget *tmp_child;
 
     g_return_if_fail (IS_MOZ_CONTAINER(widget));