diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index 5af36d278f..5afb11c417 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -681,6 +681,13 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator, GDK_WINDOW_STATE_ICONIFIED); } + if (window_impl->toplevel && + window_impl->toplevel->frame_pending) + { + window_impl->toplevel->frame_pending = FALSE; + gdk_frame_clock_thaw (gdk_window_get_frame_clock (event->any.window)); + } + _gdk_x11_window_grab_check_unmap (window, xevent->xany.serial); } @@ -1132,6 +1139,21 @@ _gdk_wm_protocols_filter (GdkXEvent *xev, return GDK_FILTER_REMOVE; } + else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_FRAME_DRAWN")) + { + GdkWindowImplX11 *window_impl; + + window_impl = GDK_WINDOW_IMPL_X11 (event->any.window->impl); + if (window_impl->toplevel && + window_impl->toplevel->frame_pending) + { + window_impl->toplevel->frame_pending = FALSE; + gdk_frame_clock_thaw (gdk_window_get_frame_clock (event->any.window)); + } + + return GDK_FILTER_REMOVE; + } + return GDK_FILTER_CONTINUE; } diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 6b8a0e8fab..99d2f7f659 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -213,6 +213,51 @@ set_sync_counter(Display *display, XSyncSetCounter(display, counter, sync_value); } +static void +gdk_x11_window_begin_frame (GdkWindow *window) +{ + GdkWindowImplX11 *impl; + + g_return_if_fail (GDK_IS_WINDOW (window)); + + impl = GDK_WINDOW_IMPL_X11 (window->impl); + + if (!WINDOW_IS_TOPLEVEL (window) || + impl->toplevel->extended_update_counter == None) + return; + + impl->toplevel->current_counter_value += 1; + set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper), + impl->toplevel->extended_update_counter, + impl->toplevel->current_counter_value); +} + +static void +gdk_x11_window_end_frame (GdkWindow *window) +{ + GdkWindowImplX11 *impl; + + g_return_if_fail (GDK_IS_WINDOW (window)); + + impl = GDK_WINDOW_IMPL_X11 (window->impl); + + if (!WINDOW_IS_TOPLEVEL (window) || + impl->toplevel->extended_update_counter == None) + return; + + impl->toplevel->current_counter_value += 1; + set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper), + impl->toplevel->extended_update_counter, + impl->toplevel->current_counter_value); + + if (gdk_x11_screen_supports_net_wm_hint (gdk_window_get_screen (window), + gdk_atom_intern_static_string ("_NET_WM_FRAME_DRAWN"))) + { + impl->toplevel->frame_pending = TRUE; + gdk_frame_clock_freeze (gdk_window_get_frame_clock (window)); + } +} + /***************************************************** * X11 specific implementations of generic functions * *****************************************************/ @@ -616,9 +661,8 @@ ensure_sync_counter (GdkWindow *window) { GdkDisplay *display = GDK_WINDOW_DISPLAY (window); GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window); - GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl); - if (toplevel && impl->use_synchronized_configure && + if (toplevel && toplevel->update_counter == None && GDK_X11_DISPLAY (display)->use_sync) { @@ -718,6 +762,20 @@ setup_toplevel_window (GdkWindow *window, ensure_sync_counter (window); } +static void +on_frame_clock_before_paint (GdkFrameClock *clock, + GdkWindow *window) +{ + gdk_x11_window_begin_frame (window); +} + +static void +on_frame_clock_after_paint (GdkFrameClock *clock, + GdkWindow *window) +{ + gdk_x11_window_end_frame (window); +} + void _gdk_x11_display_create_window_impl (GdkDisplay *display, GdkWindow *window, @@ -878,6 +936,10 @@ _gdk_x11_display_create_window_impl (GdkDisplay *display, clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL); gdk_window_set_frame_clock (window, clock); + g_signal_connect (clock, "before-paint", + G_CALLBACK (on_frame_clock_before_paint), window); + g_signal_connect (clock, "after-paint", + G_CALLBACK (on_frame_clock_after_paint), window); } static GdkEventMask diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h index b4b737604b..c42365222c 100644 --- a/gdk/x11/gdkwindow-x11.h +++ b/gdk/x11/gdkwindow-x11.h @@ -126,6 +126,9 @@ struct _GdkToplevelX11 /* Set if the WM is presenting us as focused, i.e. with active decorations */ guint have_focused : 1; + + /* If we're expecting a response from the compositor after painting a frame */ + guint frame_pending : 1; gulong map_serial; /* Serial of last transition from unmapped */