diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index b92302e4d..87cd28926 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -721,10 +721,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 9dc56b223..6c147afeb 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); } @@ -1291,6 +1298,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) { @@ -1299,6 +1312,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) { @@ -1496,6 +1512,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 */ @@ -1829,12 +1848,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) @@ -2328,3 +2341,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 f7228ed2b..ffbe4be04 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -343,6 +343,9 @@ struct _MetaWindow /* if TRUE, window is attached to its parent */ guint attached : 1; + /* if TRUE, we are freezing updates during a resize */ + guint updates_frozen_for_resize : 1; + /* if non-NULL, the bounds of the window frame */ cairo_region_t *frame_bounds; @@ -663,4 +666,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 aa5a006d2..1e8083954 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -4472,6 +4472,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) @@ -4972,8 +5003,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); } @@ -9159,8 +9189,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) @@ -9442,8 +9471,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,