Bug 1444437 - [Wayland] Don't map mozcontainer subsurface until parent surface is commited, r?ashie draft
authorMartin Stransky <stransky@redhat.com>
Thu, 28 Jun 2018 13:37:31 +0200
changeset 813056 7dc09bb0f57c3397f68c424b2a4e781e89069517
parent 810007 15c95df467be553beb39f2e8102c206639e05fde
push id114749
push userstransky@redhat.com
push dateMon, 02 Jul 2018 09:57:40 +0000
reviewersashie
bugs1444437
milestone62.0a1
Bug 1444437 - [Wayland] Don't map mozcontainer subsurface until parent surface is commited, r?ashie MozReview-Commit-ID: 4qoyGH8VCAU
widget/gtk/mozcontainer.cpp
widget/gtk/mozcontainer.h
--- a/widget/gtk/mozcontainer.cpp
+++ b/widget/gtk/mozcontainer.cpp
@@ -207,17 +207,17 @@ moz_container_init (MozContainer *contai
     gtk_widget_set_redraw_on_allocate(GTK_WIDGET(container), FALSE);
 
 #if defined(MOZ_WAYLAND)
     {
       container->subcompositor = nullptr;
       container->surface = nullptr;
       container->subsurface = nullptr;
       container->eglwindow = nullptr;
-      container->committed = false;
+      container->parent_surface_committed = false;
 
       GdkDisplay *gdk_display = gtk_widget_get_display(GTK_WIDGET(container));
       if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) {
           // Available as of GTK 3.8+
           static auto sGdkWaylandDisplayGetWlDisplay =
               (wl_display *(*)(GdkDisplay *))
               dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display");
 
@@ -228,21 +228,22 @@ moz_container_init (MozContainer *contai
           wl_display_roundtrip(display);
         }
     }
 #endif
 }
 
 #if defined(MOZ_WAYLAND)
 static void
-moz_container_after_paint(GdkFrameClock *clock, MozContainer *container)
+moz_container_commited_handler(GdkFrameClock *clock, MozContainer *container)
 {
-    container->committed = true;
-    g_signal_handlers_disconnect_by_func(clock,
-         reinterpret_cast<gpointer>(moz_container_after_paint), container);
+    container->parent_surface_committed = true;
+    g_signal_handler_disconnect(clock,
+                                container->parent_surface_committed_handler);
+    container->parent_surface_committed_handler = 0;
 }
 
 /* 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.
@@ -263,37 +264,44 @@ moz_container_map_surface(MozContainer *
 
     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->parent_surface_committed) {
+        if (!container->parent_surface_committed_handler) {
+            GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
+            GdkFrameClock *clock = sGdkWindowGetFrameClock(window);
+            container->parent_surface_committed_handler =
+                g_signal_connect_after(clock, "after-paint",
+                                       G_CALLBACK(moz_container_commited_handler),
+                                       container);
+        }
+        return false;
+    }
+
     if (!container->surface) {
         struct wl_compositor *compositor;
         compositor = sGdkWaylandDisplayGetWlCompositor(display);
         container->surface = wl_compositor_create_surface(compositor);
     }
 
     if (!container->subsurface) {
         GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
         wl_surface* gtk_surface = sGdkWaylandWindowGetWlSurface(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;
         }
 
-        GdkFrameClock *clock = sGdkWindowGetFrameClock(window);
-        g_signal_connect_after(clock, "after-paint",
-                               G_CALLBACK(moz_container_after_paint),
-                               container);
-
         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);
@@ -310,17 +318,29 @@ moz_container_map_surface(MozContainer *
 }
 
 static void
 moz_container_unmap_surface(MozContainer *container)
 {
     g_clear_pointer(&container->eglwindow, wl_egl_window_destroy);
     g_clear_pointer(&container->subsurface, wl_subsurface_destroy);
     g_clear_pointer(&container->surface, wl_surface_destroy);
-    container->committed = false;
+
+    if (container->parent_surface_committed_handler) {
+        static auto sGdkWindowGetFrameClock =
+            (GdkFrameClock *(*)(GdkWindow *))
+            dlsym(RTLD_DEFAULT, "gdk_window_get_frame_clock");
+        GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
+        GdkFrameClock *clock = sGdkWindowGetFrameClock(window);
+
+        g_signal_handler_disconnect(clock,
+                                    container->parent_surface_committed_handler);
+        container->parent_surface_committed_handler = 0;
+    }
+    container->parent_surface_committed = false;
 }
 
 #endif
 
 void
 moz_container_map (GtkWidget *widget)
 {
     MozContainer *container;
@@ -582,17 +602,17 @@ moz_container_get_wl_surface(MozContaine
     if (!container->subsurface || !container->surface) {
         GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
         if (!gdk_window_is_visible(window))
             return nullptr;
 
         moz_container_map_surface(container);
     }
 
-    return container->committed ? container->surface : nullptr;
+    return container->surface;
 }
 
 struct wl_egl_window *
 moz_container_get_wl_egl_window(MozContainer *container)
 {
     if (!container->eglwindow) {
         struct wl_surface *wlsurf = moz_container_get_wl_surface(container);
         if (!wlsurf)
--- a/widget/gtk/mozcontainer.h
+++ b/widget/gtk/mozcontainer.h
@@ -68,17 +68,18 @@ struct _MozContainer
     GtkContainer   container;
     GList         *children;
 
 #ifdef MOZ_WAYLAND
     struct wl_subcompositor *subcompositor;
     struct wl_surface       *surface;
     struct wl_subsurface    *subsurface;
     struct wl_egl_window    *eglwindow;
-    gboolean                 committed;
+    gboolean                 parent_surface_committed;
+    gulong                   parent_surface_committed_handler;
 #endif
 };
 
 struct _MozContainerClass
 {
     GtkContainerClass parent_class;
 };