diff --git a/src/core/window-private.h b/src/core/window-private.h index afaa499e5..9964c8595 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -410,6 +410,9 @@ struct _MetaWindow /* if TRUE, the X server hasn't yet committed a new buffer following resize of the frame/client window */ guint resize_pending : 1; + /* if TRUE, the window frame has a redraw queued */ + guint frame_redraw_pending : 1; + /* if non-NULL, the bounds of the window frame */ cairo_region_t *frame_bounds; @@ -788,6 +791,9 @@ void meta_window_set_resize_pending (MetaWindow *window, gboolean is_resize_pending); gboolean meta_window_resize_is_pending (MetaWindow *window); +void meta_window_set_frame_redraw_pending (MetaWindow *window, + gboolean is_frame_redraw_pending); + void meta_window_grab_op_began (MetaWindow *window, MetaGrabOp op); void meta_window_grab_op_ended (MetaWindow *window, MetaGrabOp op); diff --git a/src/core/window.c b/src/core/window.c index 34f48712f..eaab29d2e 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -3730,6 +3730,9 @@ meta_window_updates_are_frozen (MetaWindow *window) if (window->sync_request_serial < window->sync_request_wait_serial) return TRUE; + if (window->frame_redraw_pending) + return TRUE; + return FALSE; } @@ -6324,6 +6327,15 @@ meta_window_resize_is_pending (MetaWindow *window) return window->resize_pending; } +void +meta_window_set_frame_redraw_pending (MetaWindow *window, + gboolean is_frame_redraw_pending) +{ + window->frame_redraw_pending = is_frame_redraw_pending; + + meta_compositor_sync_updates_frozen (window->display->compositor, window); +} + static void end_grab_op (MetaWindow *window, const ClutterEvent *event) diff --git a/src/ui/frames.c b/src/ui/frames.c index 129a9e59b..471bfa0c7 100644 --- a/src/ui/frames.c +++ b/src/ui/frames.c @@ -149,6 +149,7 @@ static void invalidate_whole_window (MetaUIFrame *frame) { gdk_window_invalidate_rect (frame->window, NULL, FALSE); + meta_window_set_frame_redraw_pending (frame->meta_window, TRUE); } static MetaStyleInfo * @@ -484,6 +485,27 @@ meta_ui_frame_attach_style (MetaUIFrame *frame) variant)); } +static void +after_paint (GdkFrameClock *frame_clock, + MetaUIFrame *frame) +{ + MetaFrames *frames = frame->frames; + MetaWindow *window = frame->meta_window; + + /* Make sure the damage is posted to the X server before + * we mark the frame redraw finished and unfreeze, so there's + * a wayland surface commit waiting for us at unfreeze time + */ + if (meta_is_wayland_compositor ()) + gdk_display_sync (gtk_widget_get_display (GTK_WIDGET (frames))); + + meta_window_set_frame_redraw_pending (window, FALSE); + + g_signal_handlers_disconnect_by_func (G_OBJECT (gdk_window_get_frame_clock (frame->window)), + G_CALLBACK (after_paint), + frame); +} + MetaUIFrame * meta_frames_manage_window (MetaFrames *frames, MetaWindow *meta_window, @@ -531,6 +553,10 @@ meta_ui_frame_unmanage (MetaUIFrame *frame) frame->xwindow, META_CURSOR_DEFAULT); + g_signal_handlers_disconnect_by_func (G_OBJECT (gdk_window_get_frame_clock (frame->window)), + G_CALLBACK (after_paint), + frame); + gdk_window_set_user_data (frame->window, NULL); g_hash_table_remove (frames->frames, &frame->xwindow); @@ -1396,6 +1422,11 @@ meta_frames_draw (GtkWidget *widget, meta_ui_frame_paint (frame, cr); cairo_region_destroy (region); + g_signal_connect (G_OBJECT (gdk_window_get_frame_clock (frame->window)), + "after-paint", + G_CALLBACK (after_paint), + frame); + return TRUE; }