mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-26 13:41:07 +00:00
wayland: Make subsurface desynchronized after first parent surface frame
Initially the subsurface will be in synchronized mode and we will leave it like this until the first time the parent surface has been committed. The reason for this is because the subsurface position will be applied as part of the parent surface state, and we need to synchronize the initial position with the initial frame, so that we don't accidentally draw the subsurface at the default position (0, 0) which would happen in desynchronized mode if the subsurface content is committed before the next parent surface commit. https://bugzilla.gnome.org/show_bug.cgi?id=754839
This commit is contained in:
parent
07a574dddd
commit
7c4c8b90f0
@ -37,6 +37,14 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
enum {
|
||||
COMMITTED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
#define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \
|
||||
(GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
|
||||
GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
|
||||
@ -431,6 +439,8 @@ on_frame_clock_after_paint (GdkFrameClock *clock,
|
||||
wl_surface_commit (impl->surface);
|
||||
if (_gdk_wayland_is_shm_surface (impl->cairo_surface))
|
||||
_gdk_wayland_shm_surface_set_busy (impl->cairo_surface);
|
||||
|
||||
g_signal_emit (impl, signals[COMMITTED], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -859,6 +869,19 @@ static const struct wl_surface_listener surface_listener = {
|
||||
surface_leave
|
||||
};
|
||||
|
||||
static void
|
||||
on_parent_surface_committed (GdkWindowImplWayland *parent_impl,
|
||||
GdkWindow *window)
|
||||
{
|
||||
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (parent_impl,
|
||||
(gpointer) on_parent_surface_committed,
|
||||
window);
|
||||
|
||||
wl_subsurface_set_desync (impl->subsurface);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_window_create_subsurface (GdkWindow *window)
|
||||
{
|
||||
@ -886,7 +909,14 @@ gdk_wayland_window_create_subsurface (GdkWindow *window)
|
||||
wl_subcompositor_get_subsurface (display_wayland->subcompositor,
|
||||
impl->surface, parent_impl->surface);
|
||||
wl_subsurface_set_position (impl->subsurface, window->x, window->y);
|
||||
wl_subsurface_set_desync (impl->subsurface);
|
||||
|
||||
/* In order to synchronize the initial position with the initial frame
|
||||
* content, wait with making the subsurface desynchronized until after
|
||||
* the parent was committed.
|
||||
*/
|
||||
g_signal_connect_object (parent_impl, "committed",
|
||||
G_CALLBACK (on_parent_surface_committed),
|
||||
window, 0);
|
||||
gdk_window_request_transient_parent_commit (window);
|
||||
}
|
||||
}
|
||||
@ -1294,6 +1324,23 @@ gdk_wayland_window_show (GdkWindow *window,
|
||||
gdk_wayland_window_attach_image (window);
|
||||
}
|
||||
|
||||
static void
|
||||
unmap_subsurface (GdkWindow *window)
|
||||
{
|
||||
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
|
||||
GdkWindowImplWayland *parent_impl;
|
||||
|
||||
g_return_if_fail (impl->subsurface);
|
||||
g_return_if_fail (impl->transient_for);
|
||||
|
||||
parent_impl = GDK_WINDOW_IMPL_WAYLAND (impl->transient_for->impl);
|
||||
wl_subsurface_destroy (impl->subsurface);
|
||||
g_signal_handlers_disconnect_by_func (parent_impl,
|
||||
(gpointer) on_parent_surface_committed,
|
||||
window);
|
||||
impl->subsurface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_window_hide_surface (GdkWindow *window)
|
||||
{
|
||||
@ -1338,10 +1385,7 @@ gdk_wayland_window_hide_surface (GdkWindow *window)
|
||||
}
|
||||
|
||||
if (impl->subsurface)
|
||||
{
|
||||
wl_subsurface_destroy (impl->subsurface);
|
||||
impl->subsurface = NULL;
|
||||
}
|
||||
unmap_subsurface (window);
|
||||
|
||||
if (impl->awaiting_frame)
|
||||
{
|
||||
@ -1793,24 +1837,18 @@ static void
|
||||
gdk_wayland_window_set_transient_for (GdkWindow *window,
|
||||
GdkWindow *parent)
|
||||
{
|
||||
GdkWindowImplWayland *impl;
|
||||
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
|
||||
|
||||
if (impl->subsurface)
|
||||
unmap_subsurface (window);
|
||||
|
||||
impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
|
||||
impl->transient_for = parent;
|
||||
|
||||
gdk_wayland_window_sync_parent (window);
|
||||
|
||||
if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_SUBSURFACE)
|
||||
{
|
||||
if (impl->subsurface)
|
||||
{
|
||||
wl_subsurface_destroy (impl->subsurface);
|
||||
impl->subsurface = NULL;
|
||||
}
|
||||
|
||||
if (parent && gdk_window_is_visible (window))
|
||||
gdk_wayland_window_create_subsurface (window);
|
||||
}
|
||||
if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_SUBSURFACE &&
|
||||
parent && gdk_window_is_visible (window))
|
||||
gdk_wayland_window_create_subsurface (window);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2392,6 +2430,13 @@ _gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass)
|
||||
impl_class->show_window_menu = gdk_wayland_window_show_window_menu;
|
||||
impl_class->create_gl_context = gdk_wayland_window_create_gl_context;
|
||||
impl_class->invalidate_for_new_frame = gdk_wayland_window_invalidate_for_new_frame;
|
||||
|
||||
signals[COMMITTED] = g_signal_new ("committed",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user