changeset: 498019:9961a0e4d424 tag: tip parent: 498006:3fa65bda1e50 user: Martin Stransky date: Tue Oct 08 13:32:37 2019 +0200 files: widget/gtk/mozcontainer.cpp description: Bug 1587008 - [Wayland/GL] Fixed visual glitches with gl compositor during window resize, r=jhorak Recently we update egl_window size only in moz_container_size_allocate() which is leads to visible visual glitches as moz_container_size_allocate() is not called during window resize but after it. We need to update egl_window size faster which is done in configure-event callback. Differential Revision: https://phabricator.services.mozilla.com/D48526 diff --git a/widget/gtk/mozcontainer.cpp b/widget/gtk/mozcontainer.cpp --- a/widget/gtk/mozcontainer.cpp +++ b/widget/gtk/mozcontainer.cpp @@ -136,16 +136,60 @@ void moz_container_put(MozContainer* con container->children = g_list_append(container->children, child); /* we assume that the caller of this function will have already set the parent GdkWindow because we can have many anonymous children. */ gtk_widget_set_parent(child_widget, GTK_WIDGET(container)); } /* static methods */ +#if defined(MOZ_WAYLAND) +static gint moz_container_get_scale(MozContainer* container) { + static auto sGdkWindowGetScaleFactorPtr = + (gint(*)(GdkWindow*))dlsym(RTLD_DEFAULT, "gdk_window_get_scale_factor"); + + if (sGdkWindowGetScaleFactorPtr) { + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container)); + return (*sGdkWindowGetScaleFactorPtr)(window); + } + + return 1; +} + +static void moz_container_resize(MozContainer* container, int width, + int height) { + // Set correct scaled/unscaled mozcontainer offset + // especially when wl_egl is used but we don't recreate it as Gtk+ does. + if (container->subsurface) { + gint x, y; + gdk_window_get_position(gtk_widget_get_window(GTK_WIDGET(container)), &x, + &y); + wl_subsurface_set_position(container->subsurface, x, y); + } + + // Try to only resize wl_egl_window on scale factor change. + // It's a bit risky as Gtk+ recreates it at that event. + if (container->eglwindow) { + gint scale = moz_container_get_scale(container); + if (container->surface) { + wl_surface_set_buffer_scale(container->surface, scale); + } + wl_egl_window_resize(container->eglwindow, width * scale, height * scale, 0, + 0); + } +} + +static gboolean moz_container_configure_event_cb(GtkWidget* widget, + GdkEventConfigure* event) { + LOG(("moz_container_egl_window_configure_event_cb [%p] %d %d %d %d\n", + (void*)widget, event->x, event->y, event->width, event->height)); + moz_container_resize(MOZ_CONTAINER(widget), event->width, event->height); + return FALSE; +} +#endif void moz_container_class_init(MozContainerClass* klass) { /*GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); */ GtkContainerClass* container_class = GTK_CONTAINER_CLASS(klass); GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass); widget_class->map = moz_container_map; @@ -173,16 +217,21 @@ 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; container->inital_draw_cb = nullptr; + + // We need faster resize response in mozcontainer to avoid visual glitches + // during window resize. + g_signal_connect(container, "configure_event", + G_CALLBACK(moz_container_configure_event_cb), nullptr); #endif LOG(("%s [%p]\n", __FUNCTION__, (void*)container)); } #if defined(MOZ_WAYLAND) void moz_container_set_initial_draw_callback( MozContainer* container, std::function inital_draw_cb) { @@ -285,53 +334,26 @@ static void moz_container_unmap_wayland( container->frame_callback_handler_surface_id = -1; container->surface_needs_clear = true; container->ready_to_draw = false; LOGWAYLAND(("%s [%p]\n", __FUNCTION__, (void*)container)); } -static gint moz_container_get_scale(MozContainer* container) { - static auto sGdkWindowGetScaleFactorPtr = - (gint(*)(GdkWindow*))dlsym(RTLD_DEFAULT, "gdk_window_get_scale_factor"); - - if (sGdkWindowGetScaleFactorPtr) { - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container)); - return (*sGdkWindowGetScaleFactorPtr)(window); - } - - return 1; -} - void moz_container_scale_changed(MozContainer* container, GtkAllocation* aAllocation) { LOGWAYLAND(("%s [%p] surface %p eglwindow %p\n", __FUNCTION__, (void*)container, (void*)container->surface, (void*)container->eglwindow)); if (!container->surface) { return; } - - // Set correct scaled/unscaled mozcontainer offset - // especially when wl_egl is used but we don't recreate it as Gtk+ does. - gint x, y; - gdk_window_get_position(gtk_widget_get_window(GTK_WIDGET(container)), &x, &y); - wl_subsurface_set_position(container->subsurface, x, y); - - // Try to only resize wl_egl_window on scale factor change. - // It's a bit risky as Gtk+ recreates it at that event. - if (container->eglwindow) { - gint scale = moz_container_get_scale(container); - wl_surface_set_buffer_scale(container->surface, - moz_container_get_scale(container)); - wl_egl_window_resize(container->eglwindow, aAllocation->width * scale, - aAllocation->height * scale, 0, 0); - } + moz_container_resize(container, aAllocation->width, aAllocation->height); } #endif void moz_container_map(GtkWidget* widget) { MozContainer* container; GList* tmp_list; GtkWidget* tmp_child; @@ -451,26 +473,18 @@ void moz_container_size_allocate(GtkWidg allocation->y, allocation->width, allocation->height); } #if defined(MOZ_WAYLAND) // We need to position our subsurface according to GdkWindow // when offset changes (GdkWindow is maximized for instance). // see gtk-clutter-embed.c for reference. - if (container->subsurface) { - gint x, y; - gdk_window_get_position(gtk_widget_get_window(widget), &x, &y); - wl_subsurface_set_position(container->subsurface, x, y); - } - if (container->eglwindow) { - gint scale = moz_container_get_scale(container); - wl_egl_window_resize(container->eglwindow, allocation->width * scale, - allocation->height * scale, 0, 0); - } + moz_container_resize(MOZ_CONTAINER(widget), allocation->width, + allocation->height); #endif } void moz_container_remove(GtkContainer* container, GtkWidget* child_widget) { MozContainerChild* child; MozContainer* moz_container; GdkWindow* parent_window;