Bug 1464823 - [Wayland] Don't paint until we have a visible wl_surface, r=jhorak,lsalzman

It's based on a solution by Takuro Ashie <ashie@clear-code.com>

MozReview-Commit-ID: FqcdUJQJLdl

--HG--
extra : rebase_source : d4ed4d66439a3693a2f4d5e6a4037ed62969d64f
This commit is contained in:
Martin Stransky 2018-06-06 11:30:27 +02:00
Родитель 01f5681a9d
Коммит 46f6ecf022
3 изменённых файлов: 27 добавлений и 2 удалений

Просмотреть файл

@ -212,6 +212,7 @@ moz_container_init (MozContainer *container)
container->surface = nullptr;
container->subsurface = nullptr;
container->eglwindow = nullptr;
container->committed = false;
GdkDisplay *gdk_display = gtk_widget_get_display(GTK_WIDGET(container));
if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) {
@ -231,12 +232,20 @@ moz_container_init (MozContainer *container)
}
#if defined(MOZ_WAYLAND)
static void
moz_container_after_paint(GdkFrameClock *clock, MozContainer *container)
{
container->committed = true;
g_signal_handlers_disconnect_by_func(clock,
reinterpret_cast<gpointer>(moz_container_after_paint), container);
}
/* 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.
* for reference.
*/
static gboolean
moz_container_map_surface(MozContainer *container)
@ -248,6 +257,9 @@ moz_container_map_surface(MozContainer *container)
static auto sGdkWaylandWindowGetWlSurface =
(wl_surface *(*)(GdkWindow *))
dlsym(RTLD_DEFAULT, "gdk_wayland_window_get_wl_surface");
static auto sGdkWindowGetFrameClock =
(GdkFrameClock *(*)(GdkWindow *))
dlsym(RTLD_DEFAULT, "gdk_window_get_frame_clock");
GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(container));
if (GDK_IS_X11_DISPLAY(display))
@ -272,6 +284,11 @@ moz_container_map_surface(MozContainer *container)
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,
@ -298,6 +315,7 @@ 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;
}
#endif
@ -569,7 +587,7 @@ moz_container_get_wl_surface(MozContainer *container)
moz_container_map_surface(container);
}
return container->surface;
return container->committed ? container->surface : nullptr;
}
struct wl_egl_window *

Просмотреть файл

@ -73,6 +73,7 @@ struct _MozContainer
struct wl_surface *surface;
struct wl_subsurface *subsurface;
struct wl_egl_window *eglwindow;
gboolean committed;
#endif
};

Просмотреть файл

@ -2067,6 +2067,12 @@ nsWindow::OnExposeEvent(cairo_t *cr)
if (!mGdkWindow || mIsFullyObscured || !mHasMappedToplevel)
return FALSE;
#ifdef MOZ_WAYLAND
// Window does not have visible wl_surface yet.
if (!mIsX11Display && !GetWaylandSurface())
return FALSE;
#endif
nsIWidgetListener *listener = GetListener();
if (!listener)
return FALSE;