diff -up firefox-67.0/widget/gtk/mozcontainer.cpp.mozilla-1535567 firefox-67.0/widget/gtk/mozcontainer.cpp --- firefox-67.0/widget/gtk/mozcontainer.cpp.mozilla-1535567 2019-05-14 01:08:37.000000000 +0200 +++ firefox-67.0/widget/gtk/mozcontainer.cpp 2019-05-15 15:56:19.645336209 +0200 @@ -157,6 +157,7 @@ void moz_container_init(MozContainer *co container->subsurface = nullptr; container->eglwindow = nullptr; container->frame_callback_handler = nullptr; + container->frame_callback_handler_surface_id = -1; // We can draw to x11 window any time. container->ready_to_draw = GDK_IS_X11_DISPLAY(gdk_display_get_default()); container->surface_needs_clear = true; @@ -165,6 +166,11 @@ void moz_container_init(MozContainer *co } #if defined(MOZ_WAYLAND) +void moz_container_set_initial_draw_callback( + MozContainer *container, std::function inital_draw_cb) { + container->inital_draw_cb = inital_draw_cb; +} + static wl_surface *moz_container_get_gtk_container_surface( MozContainer *container) { static auto sGdkWaylandWindowGetWlSurface = (wl_surface * (*)(GdkWindow *)) @@ -178,37 +184,61 @@ static void frame_callback_handler(void uint32_t time) { MozContainer *container = MOZ_CONTAINER(data); g_clear_pointer(&container->frame_callback_handler, wl_callback_destroy); + container->frame_callback_handler_surface_id = -1; if (!container->ready_to_draw && container->inital_draw_cb) { container->inital_draw_cb(); } container->ready_to_draw = true; } -void moz_container_set_initial_draw_callback( - MozContainer *container, std::function inital_draw_cb) { - container->inital_draw_cb = inital_draw_cb; -} - static const struct wl_callback_listener frame_listener = { frame_callback_handler}; -static gboolean moz_container_map_wayland(GtkWidget *widget, - GdkEventAny *event) { - MozContainer *container = MOZ_CONTAINER(widget); - - if (container->ready_to_draw || container->frame_callback_handler) { - return FALSE; - } - +static void moz_container_request_parent_frame_callback( + MozContainer *container) { wl_surface *gtk_container_surface = moz_container_get_gtk_container_surface(container); + int gtk_container_surface_id = + gtk_container_surface + ? wl_proxy_get_id((struct wl_proxy *)gtk_container_surface) + : -1; + + LOG( + ("%s [%p] frame_callback_handler %p " + "frame_callback_handler_surface_id %d\n", + __FUNCTION__, (void *)container, container->frame_callback_handler, + container->frame_callback_handler_surface_id)); + + if (container->frame_callback_handler && + container->frame_callback_handler_surface_id == + gtk_container_surface_id) { + return; + } + + // If there's pending frame callback, delete it. + if (container->frame_callback_handler) { + g_clear_pointer(&container->frame_callback_handler, wl_callback_destroy); + } if (gtk_container_surface) { + container->frame_callback_handler_surface_id = gtk_container_surface_id; container->frame_callback_handler = wl_surface_frame(gtk_container_surface); wl_callback_add_listener(container->frame_callback_handler, &frame_listener, container); + } else { + container->frame_callback_handler_surface_id = -1; + } +} + +static gboolean moz_container_map_wayland(GtkWidget *widget, + GdkEventAny *event) { + MozContainer *container = MOZ_CONTAINER(widget); + + if (container->ready_to_draw) { + return FALSE; } + moz_container_request_parent_frame_callback(MOZ_CONTAINER(widget)); return FALSE; } @@ -217,6 +247,7 @@ static void moz_container_unmap_wayland( g_clear_pointer(&container->subsurface, wl_subsurface_destroy); g_clear_pointer(&container->surface, wl_surface_destroy); g_clear_pointer(&container->frame_callback_handler, wl_callback_destroy); + container->frame_callback_handler_surface_id = -1; container->surface_needs_clear = true; container->ready_to_draw = false; @@ -329,6 +360,10 @@ void moz_container_realize(GtkWidget *wi : gtk_widget_get_visual(widget); window = gdk_window_new(parent, &attributes, attributes_mask); + + LOG(("moz_container_realize() [%p] GdkWindow %p\n", (void *)container, + (void *)window)); + gdk_window_set_user_data(window, widget); } else { window = parent; @@ -498,6 +533,7 @@ static void moz_container_add(GtkContain struct wl_surface *moz_container_get_wl_surface(MozContainer *container) { if (!container->surface) { if (!container->ready_to_draw) { + moz_container_request_parent_frame_callback(container); return nullptr; } GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(container)); diff -up firefox-67.0/widget/gtk/mozcontainer.h.mozilla-1535567 firefox-67.0/widget/gtk/mozcontainer.h --- firefox-67.0/widget/gtk/mozcontainer.h.mozilla-1535567 2019-05-14 01:08:37.000000000 +0200 +++ firefox-67.0/widget/gtk/mozcontainer.h 2019-05-15 15:50:59.440570372 +0200 @@ -77,6 +77,7 @@ struct _MozContainer { struct wl_subsurface *subsurface; struct wl_egl_window *eglwindow; struct wl_callback *frame_callback_handler; + int frame_callback_handler_surface_id; gboolean surface_needs_clear; gboolean ready_to_draw; std::function inital_draw_cb;