From 8b57ecebdaff4958114a6d103e13a6100221f5db Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Mon, 13 Jun 2011 17:53:23 -0400 Subject: [PATCH] Implement freezing of updates during resize Replace the unused meta_compositor_set_updates() with a reversed-meaning meta_compositor_set_updates_frozen(), and use it to implement freezing application window updates during interactive resizing. This avoids drawing new areas of the window with blank content before the application has a chance to repaint. https://bugzilla.gnome.org/show_bug.cgi?id=685463 --- src/compositor/compositor.c | 14 +++++-- src/compositor/meta-window-actor-private.h | 2 + src/compositor/meta-window-actor.c | 45 ++++++++++++++++++---- src/core/window-private.h | 5 +++ src/core/window.c | 40 ++++++++++++++++--- src/meta/compositor.h | 4 +- 6 files changed, 92 insertions(+), 18 deletions(-) diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index 105464fca..3c4972d83 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -716,10 +716,18 @@ meta_compositor_remove_window (MetaCompositor *compositor, } void -meta_compositor_set_updates (MetaCompositor *compositor, - MetaWindow *window, - gboolean updates) +meta_compositor_set_updates_frozen (MetaCompositor *compositor, + MetaWindow *window, + gboolean updates_frozen) { + MetaWindowActor *window_actor; + + DEBUG_TRACE ("meta_compositor_set_updates_frozen\n"); + window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window)); + if (!window_actor) + return; + + meta_window_actor_set_updates_frozen (window_actor, updates_frozen); } static gboolean diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h index 97e314049..0d653ec6c 100644 --- a/src/compositor/meta-window-actor-private.h +++ b/src/compositor/meta-window-actor-private.h @@ -45,6 +45,8 @@ void meta_window_actor_update_shape (MetaWindowActor *self); void meta_window_actor_update_opacity (MetaWindowActor *self); void meta_window_actor_mapped (MetaWindowActor *self); void meta_window_actor_unmapped (MetaWindowActor *self); +void meta_window_actor_set_updates_frozen (MetaWindowActor *self, + gboolean updates_frozen); cairo_region_t *meta_window_actor_get_obscured_region (MetaWindowActor *self); diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 180cfdc56..4f6ccba73 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -111,6 +111,7 @@ struct _MetaWindowActorPrivate guint recompute_focused_shadow : 1; guint recompute_unfocused_shadow : 1; guint size_changed : 1; + guint updates_frozen : 1; guint needs_destroy : 1; @@ -925,10 +926,16 @@ meta_window_actor_thaw (MetaWindowActor *self) if (self->priv->freeze_count) return; + /* We ignore moves and resizes on frozen windows */ + meta_window_actor_sync_actor_position (self); + + /* We do this now since we might be going right back into the + * frozen state */ + meta_window_actor_pre_paint (self); + /* Since we ignore damage events while a window is frozen for certain effects * we may need to issue an update_area() covering the whole pixmap if we * don't know what real damage has happened. */ - if (self->priv->needs_damage_all) meta_window_actor_damage_all (self); } @@ -1279,6 +1286,12 @@ meta_window_actor_destroy (MetaWindowActor *self) clutter_actor_destroy (CLUTTER_ACTOR (self)); } +static gboolean +is_frozen (MetaWindowActor *self) +{ + return self->priv->freeze_count ? TRUE : FALSE; +} + void meta_window_actor_sync_actor_position (MetaWindowActor *self) { @@ -1287,6 +1300,9 @@ meta_window_actor_sync_actor_position (MetaWindowActor *self) meta_window_get_input_rect (priv->window, &window_rect); + if (is_frozen (self)) + return; + if (priv->last_width != window_rect.width || priv->last_height != window_rect.height) { @@ -1483,6 +1499,9 @@ meta_window_actor_new (MetaWindow *window) if (priv->mapped) meta_window_actor_queue_create_pixmap (self); + meta_window_actor_set_updates_frozen (self, + meta_window_updates_are_frozen (priv->window)); + meta_window_actor_sync_actor_position (self); /* Hang our compositor window state off the MetaWindow for fast retrieval */ @@ -1872,12 +1891,6 @@ check_needs_shadow (MetaWindowActor *self) meta_shadow_unref (old_shadow); } -static gboolean -is_frozen (MetaWindowActor *self) -{ - return self->priv->freeze_count ? TRUE : FALSE; -} - void meta_window_actor_process_damage (MetaWindowActor *self, XDamageNotifyEvent *event) @@ -2329,3 +2342,21 @@ meta_window_actor_update_opacity (MetaWindowActor *self) self->priv->opacity = opacity; clutter_actor_set_opacity (self->priv->actor, opacity); } + +void +meta_window_actor_set_updates_frozen (MetaWindowActor *self, + gboolean updates_frozen) +{ + MetaWindowActorPrivate *priv = self->priv; + + updates_frozen = updates_frozen != FALSE; + + if (priv->updates_frozen != updates_frozen) + { + priv->updates_frozen = updates_frozen; + if (updates_frozen) + meta_window_actor_freeze (self); + else + meta_window_actor_thaw (self); + } +} diff --git a/src/core/window-private.h b/src/core/window-private.h index 9b7987d06..9059f6f87 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -336,6 +336,9 @@ struct _MetaWindow /* if non-NULL, the bounds of the window frame */ cairo_region_t *frame_bounds; + /* if TRUE, we are freezing updates during a resize */ + guint updates_frozen_for_resize : 1; + /* Note: can be NULL */ GSList *struts; @@ -655,4 +658,6 @@ gboolean meta_window_can_tile_side_by_side (MetaWindow *window); void meta_window_compute_tile_match (MetaWindow *window); +gboolean meta_window_updates_are_frozen (MetaWindow *window); + #endif diff --git a/src/core/window.c b/src/core/window.c index 83255e06d..f190c745e 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -4466,6 +4466,37 @@ send_sync_request (MetaWindow *window) } #endif +/** + * meta_window_updates_are_frozen: + * @window: a #MetaWindow + * + * Gets whether the compositor should be updating the window contents; + * window content updates may be frozen at client request by setting + * an odd value in the extended _NET_WM_SYNC_REQUEST_COUNTER counter r + * by the window manager during a resize operation while waiting for + * the client to redraw. + * + * Return value: %TRUE if updates are currently frozen + */ +gboolean +meta_window_updates_are_frozen (MetaWindow *window) +{ + return window->updates_frozen_for_resize; +} + +static void +meta_window_set_updates_frozen_for_resize (MetaWindow *window, + gboolean updates_frozen) +{ + if (updates_frozen != window->updates_frozen_for_resize) + { + window->updates_frozen_for_resize = updates_frozen; + if (window->display->compositor) + meta_compositor_set_updates_frozen (window->display->compositor, window, + meta_window_updates_are_frozen (window)); + } +} + static gboolean maybe_move_attached_dialog (MetaWindow *window, void *data) @@ -4966,8 +4997,7 @@ meta_window_move_resize_internal (MetaWindow *window, window->sync_request_time.tv_sec == 0) { /* turn off updating */ - if (window->display->compositor) - meta_compositor_set_updates (window->display->compositor, window, FALSE); + meta_window_set_updates_frozen_for_resize (window, TRUE); send_sync_request (window); } @@ -9097,8 +9127,7 @@ update_resize (MetaWindow *window, } /* If we get here, it means the client should have redrawn itself */ - if (window->display->compositor) - meta_compositor_set_updates (window->display->compositor, window, TRUE); + meta_window_set_updates_frozen_for_resize (window, FALSE); /* Remove any scheduled compensation events */ if (window->display->grab_resize_timeout_id) @@ -9380,8 +9409,7 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, xev->root_x, xev->root_y, TRUE); - if (window->display->compositor) - meta_compositor_set_updates (window->display->compositor, window, TRUE); + meta_window_set_updates_frozen_for_resize (window, FALSE); /* If a tiled window has been dragged free with a * mouse resize without snapping back to the tiled diff --git a/src/meta/compositor.h b/src/meta/compositor.h index 8ccd46d2c..e36f30b05 100644 --- a/src/meta/compositor.h +++ b/src/meta/compositor.h @@ -153,9 +153,9 @@ void meta_compositor_window_unmapped (MetaCompositor *compositor, MetaWindow *window); void meta_compositor_sync_window_geometry (MetaCompositor *compositor, MetaWindow *window); -void meta_compositor_set_updates (MetaCompositor *compositor, +void meta_compositor_set_updates_frozen (MetaCompositor *compositor, MetaWindow *window, - gboolean updates); + gboolean updates_frozen); void meta_compositor_sync_stack (MetaCompositor *compositor, MetaScreen *screen,