Fix window maximize and unmaximize animations (#1557)

This commit is contained in:
Leo 2023-02-22 03:57:33 +09:00 committed by GitHub
parent 6ab08256e0
commit d0abb9c0e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 47 deletions

View File

@ -30,6 +30,8 @@
<issue url="https://github.com/elementary/gala/issues/1482">Duplicate "Plus" workspaces</issue>
<issue url="https://github.com/elementary/gala/issues/1203">Artifact around non native apps in the overview mode</issue>
<issue url="https://github.com/elementary/gala/issues/1505">"Not responding" dialog and not responding app close after inactivity</issue>
<issue url="https://github.com/elementary/gala/issues/1185">Unmaximize effect not working with mutter >= 3.38</issue>
<issue url="https://github.com/elementary/gala/issues/1536">Several (un-)maximize animations are not played</issue>
</issues>
</release>

View File

@ -271,7 +271,7 @@ namespace Gala {
/**
* Creates an actor showing the current contents of the given WindowActor.
*
* @param actor The actor from which to create a shnapshot
* @param actor The actor from which to create a snapshot
* @param inner_rect The inner (actually visible) rectangle of the window
* @param outer_rect The outer (input region) rectangle of the window
*
@ -279,36 +279,20 @@ namespace Gala {
*/
public static Clutter.Actor? get_window_actor_snapshot (
Meta.WindowActor actor,
Meta.Rectangle inner_rect,
Meta.Rectangle outer_rect
Meta.Rectangle inner_rect
) {
var texture = actor.get_texture () as Meta.ShapedTexture;
Clutter.Content content;
if (texture == null)
try {
content = actor.paint_to_content (inner_rect);
} catch (Error e) {
warning ("Could not create window snapshot: %s", e.message);
return null;
var surface = texture.get_image ({
inner_rect.x - outer_rect.x,
inner_rect.y - outer_rect.y,
inner_rect.width,
inner_rect.height
});
if (surface == null)
return null;
var canvas = new Clutter.Canvas ();
var handler = canvas.draw.connect ((cr) => {
cr.set_source_surface (surface, 0, 0);
cr.paint ();
return false;
});
canvas.set_size (inner_rect.width, inner_rect.height);
SignalHandler.disconnect (canvas, handler);
}
var container = new Clutter.Actor ();
container.set_size (inner_rect.width, inner_rect.height);
container.content = canvas;
container.content = content;
return container;
}

View File

@ -104,6 +104,7 @@ namespace Gala {
private GLib.HashTable<Meta.Window, int> ws_assoc = new GLib.HashTable<Meta.Window, int> (direct_hash, direct_equal);
private Meta.SizeChange? which_change = null;
private Meta.Rectangle old_rect_size_change;
private Clutter.Actor latest_window_snapshot;
private GLib.Settings animations_settings;
private GLib.Settings behavior_settings;
@ -1062,6 +1063,8 @@ namespace Gala {
public override void size_change (Meta.WindowActor actor, Meta.SizeChange which_change_local, Meta.Rectangle old_frame_rect, Meta.Rectangle old_buffer_rect) {
which_change = which_change_local;
old_rect_size_change = old_frame_rect;
latest_window_snapshot = Utils.get_window_actor_snapshot (actor, old_frame_rect);
}
// size_changed gets called after frame_rect has updated
@ -1193,7 +1196,7 @@ namespace Gala {
var old_inner_rect = window_geometry != null ? window_geometry.inner : fallback;
var old_outer_rect = window_geometry != null ? window_geometry.outer : fallback;
var old_actor = Utils.get_window_actor_snapshot (actor, old_inner_rect, old_outer_rect);
var old_actor = Utils.get_window_actor_snapshot (actor, old_inner_rect);
if (old_actor == null) {
return;
}
@ -1586,41 +1589,40 @@ namespace Gala {
offset_height = 0;
}
Meta.Rectangle old_rect = { (int) actor.x, (int) actor.y, (int) actor.width, (int) actor.height };
var old_actor = Utils.get_window_actor_snapshot (actor, old_rect, old_rect);
if (old_actor == null) {
if (latest_window_snapshot == null) {
return;
}
unmaximizing.add (actor);
old_actor.set_position (old_rect.x, old_rect.y);
// FIXME: Gtk windows don't want to go out of bounds of screen when unmaximizing, so place them manually
// This is OS 7 (Mutter 42) specific, this was not needed in OS 6
window.move_frame (true, ex, ey);
ui_group.add_child (old_actor);
latest_window_snapshot.set_position (old_rect_size_change.x, old_rect_size_change.y);
var scale_x = (float) ew / old_rect.width;
var scale_y = (float) eh / old_rect.height;
ui_group.add_child (latest_window_snapshot);
old_actor.save_easing_state ();
old_actor.set_easing_mode (Clutter.AnimationMode.EASE_IN_OUT_QUAD);
old_actor.set_easing_duration (duration);
old_actor.set_position (ex, ey);
old_actor.set_scale (scale_x, scale_y);
old_actor.opacity = 0U;
old_actor.restore_easing_state ();
var scale_x = (float) ew / old_rect_size_change.width;
var scale_y = (float) eh / old_rect_size_change.height;
latest_window_snapshot.save_easing_state ();
latest_window_snapshot.set_easing_mode (Clutter.AnimationMode.EASE_IN_OUT_QUAD);
latest_window_snapshot.set_easing_duration (duration);
latest_window_snapshot.set_position (ex, ey);
latest_window_snapshot.set_scale (scale_x, scale_y);
latest_window_snapshot.opacity = 0U;
latest_window_snapshot.restore_easing_state ();
ulong unmaximize_old_handler_id = 0UL;
unmaximize_old_handler_id = old_actor.transitions_completed.connect (() => {
old_actor.disconnect (unmaximize_old_handler_id);
old_actor.destroy ();
unmaximize_old_handler_id = latest_window_snapshot.transitions_completed.connect (() => {
latest_window_snapshot.disconnect (unmaximize_old_handler_id);
latest_window_snapshot.destroy ();
});
var maximized_x = actor.x;
var maximized_y = actor.y;
actor.set_pivot_point (0.0f, 0.0f);
actor.set_position (ex, ey);
actor.set_translation (-ex + offset_x * (1.0f / scale_x - 1.0f) + maximized_x, -ey + offset_y * (1.0f / scale_y - 1.0f) + maximized_y, 0.0f);
actor.set_translation (-ex + offset_x * (1.0f / scale_x - 1.0f) + old_rect_size_change.x, -ey + offset_y * (1.0f / scale_y - 1.0f) + old_rect_size_change.y, 0.0f);
actor.set_scale (1.0f / scale_x, 1.0f / scale_y);
actor.save_easing_state ();