Skip to content

Commit 9f63c52

Browse files
WindowManager: cleanup maximize and unmaximize animations (#2255)
Co-authored-by: Leonhard <[email protected]>
1 parent 3d180af commit 9f63c52

File tree

2 files changed

+138
-135
lines changed

2 files changed

+138
-135
lines changed

lib/Utils.vala

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,9 +325,14 @@ namespace Gala {
325325
return null;
326326
}
327327

328-
var container = new Clutter.Actor ();
329-
container.set_size (inner_rect.width, inner_rect.height);
330-
container.content = content;
328+
var container = new Clutter.Actor () {
329+
content = content,
330+
offscreen_redirect = Clutter.OffscreenRedirect.ALWAYS,
331+
x = inner_rect.x,
332+
y = inner_rect.y,
333+
width = inner_rect.width,
334+
height = inner_rect.height
335+
};
331336

332337
return container;
333338
}

src/WindowManager.vala

Lines changed: 130 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,14 +1210,12 @@ namespace Gala {
12101210
return;
12111211
}
12121212

1213-
Meta.SizeChange? which_change_local = which_change;
1214-
which_change = null;
1215-
12161213
unowned var window = actor.get_meta_window ();
12171214
var new_rect = window.get_frame_rect ();
12181215

1219-
switch (which_change_local) {
1216+
switch (which_change) {
12201217
case Meta.SizeChange.MAXIMIZE:
1218+
case Meta.SizeChange.FULLSCREEN:
12211219
// don't animate resizing of two tiled windows with mouse drag
12221220
if (window.get_tile_match () != null && !window.maximized_horizontally) {
12231221
var old_end = old_rect_size_change.x + old_rect_size_change.width;
@@ -1228,21 +1226,18 @@ namespace Gala {
12281226
break;
12291227
}
12301228
}
1229+
12311230
maximize (actor, new_rect.x, new_rect.y, new_rect.width, new_rect.height);
12321231
break;
12331232
case Meta.SizeChange.UNMAXIMIZE:
1234-
unmaximize (actor, new_rect.x, new_rect.y, new_rect.width, new_rect.height);
1235-
break;
1236-
case Meta.SizeChange.FULLSCREEN:
1237-
maximize (actor, new_rect.x, new_rect.y, new_rect.width, new_rect.height);
1238-
break;
12391233
case Meta.SizeChange.UNFULLSCREEN:
12401234
unmaximize (actor, new_rect.x, new_rect.y, new_rect.width, new_rect.height);
12411235
break;
12421236
default:
12431237
break;
12441238
}
12451239

1240+
which_change = null;
12461241
size_change_completed (actor);
12471242
}
12481243

@@ -1317,91 +1312,94 @@ namespace Gala {
13171312
}
13181313

13191314
private void maximize (Meta.WindowActor actor, int ex, int ey, int ew, int eh) {
1320-
if (!AnimationsSettings.get_enable_animations ()) {
1321-
return;
1322-
}
1323-
1324-
var duration = AnimationDuration.SNAP;
1325-
1326-
kill_window_effects (actor);
13271315

13281316
unowned var window = actor.get_meta_window ();
13291317
if (window.maximized_horizontally && behavior_settings.get_boolean ("move-maximized-workspace")
13301318
|| window.fullscreen && behavior_settings.get_boolean ("move-fullscreened-workspace")) {
13311319
move_window_to_next_ws (window);
13321320
}
13331321

1334-
if (window.window_type == Meta.WindowType.NORMAL) {
1335-
if (latest_window_snapshot == null) {
1336-
return;
1337-
}
1322+
kill_window_effects (actor);
13381323

1339-
maximizing.add (actor);
1340-
latest_window_snapshot.set_position (old_rect_size_change.x, old_rect_size_change.y);
1341-
1342-
ui_group.add_child (latest_window_snapshot);
1343-
1344-
// FIMXE that's a hacky part. There is a short moment right after maximized_completed
1345-
// where the texture is screwed up and shows things it's not supposed to show,
1346-
// resulting in flashing. Waiting here transparently shortly fixes that issue. There
1347-
// appears to be no signal that would inform when that moment happens.
1348-
// We can't spend arbitrary amounts of time transparent since the overlay fades away,
1349-
// about a third has proven to be a solid time. So this fix will only apply for
1350-
// durations >= FLASH_PREVENT_TIMEOUT*3
1351-
const int FLASH_PREVENT_TIMEOUT = 80;
1352-
var delay = 0;
1353-
if (FLASH_PREVENT_TIMEOUT <= duration / 3) {
1354-
actor.opacity = 0;
1355-
delay = FLASH_PREVENT_TIMEOUT;
1356-
Timeout.add (FLASH_PREVENT_TIMEOUT, () => {
1357-
actor.opacity = 255;
1358-
return false;
1359-
});
1360-
}
1324+
if (!AnimationsSettings.get_enable_animations () ||
1325+
latest_window_snapshot == null ||
1326+
window.window_type != Meta.WindowType.NORMAL) {
1327+
return;
1328+
}
13611329

1362-
var scale_x = (double) ew / old_rect_size_change.width;
1363-
var scale_y = (double) eh / old_rect_size_change.height;
1364-
1365-
latest_window_snapshot.save_easing_state ();
1366-
latest_window_snapshot.set_easing_mode (Clutter.AnimationMode.EASE_IN_OUT_QUAD);
1367-
latest_window_snapshot.set_easing_duration (duration);
1368-
latest_window_snapshot.set_position (ex, ey);
1369-
latest_window_snapshot.set_scale (scale_x, scale_y);
1370-
1371-
// the opacity animation is special, since we have to wait for the
1372-
// FLASH_PREVENT_TIMEOUT to be done before we can safely fade away
1373-
latest_window_snapshot.save_easing_state ();
1374-
latest_window_snapshot.set_easing_delay (delay);
1375-
latest_window_snapshot.set_easing_duration (duration - delay);
1376-
latest_window_snapshot.opacity = 0;
1377-
latest_window_snapshot.restore_easing_state ();
1378-
1379-
ulong maximize_old_handler_id = 0UL;
1380-
maximize_old_handler_id = latest_window_snapshot.transitions_completed.connect ((snapshot) => {
1381-
snapshot.disconnect (maximize_old_handler_id);
1382-
snapshot.destroy ();
1383-
actor.set_translation (0.0f, 0.0f, 0.0f);
1330+
var duration = AnimationDuration.SNAP;
1331+
1332+
maximizing.add (actor);
1333+
latest_window_snapshot.set_position (old_rect_size_change.x, old_rect_size_change.y);
1334+
1335+
ui_group.add_child (latest_window_snapshot);
1336+
1337+
// FIMXE that's a hacky part. There is a short moment right after maximized_completed
1338+
// where the texture is screwed up and shows things it's not supposed to show,
1339+
// resulting in flashing. Waiting here transparently shortly fixes that issue. There
1340+
// appears to be no signal that would inform when that moment happens.
1341+
// We can't spend arbitrary amounts of time transparent since the overlay fades away,
1342+
// about a third has proven to be a solid time. So this fix will only apply for
1343+
// durations >= FLASH_PREVENT_TIMEOUT*3
1344+
const int FLASH_PREVENT_TIMEOUT = 80;
1345+
var delay = 0;
1346+
if (FLASH_PREVENT_TIMEOUT <= duration / 3) {
1347+
actor.opacity = 0;
1348+
delay = FLASH_PREVENT_TIMEOUT;
1349+
Timeout.add (FLASH_PREVENT_TIMEOUT, () => {
1350+
actor.opacity = 255;
1351+
return false;
13841352
});
1353+
}
13851354

1386-
latest_window_snapshot = null;
1355+
var scale_x = (double) ew / old_rect_size_change.width;
1356+
var scale_y = (double) eh / old_rect_size_change.height;
13871357

1388-
actor.set_pivot_point (0.0f, 0.0f);
1389-
actor.set_translation (old_rect_size_change.x - ex, old_rect_size_change.y - ey, 0.0f);
1390-
actor.set_scale (1.0f / scale_x, 1.0f / scale_y);
1358+
latest_window_snapshot.save_easing_state ();
1359+
latest_window_snapshot.set_easing_mode (Clutter.AnimationMode.EASE_IN_OUT_QUAD);
1360+
latest_window_snapshot.set_easing_duration (duration);
1361+
latest_window_snapshot.set_position (ex, ey);
1362+
latest_window_snapshot.set_scale (scale_x, scale_y);
1363+
latest_window_snapshot.restore_easing_state ();
1364+
1365+
// the opacity animation is special, since we have to wait for the
1366+
// FLASH_PREVENT_TIMEOUT to be done before we can safely fade away
1367+
latest_window_snapshot.save_easing_state ();
1368+
latest_window_snapshot.set_easing_delay (delay);
1369+
latest_window_snapshot.set_easing_duration (duration - delay);
1370+
latest_window_snapshot.opacity = 0;
1371+
latest_window_snapshot.restore_easing_state ();
1372+
1373+
ulong maximize_old_handler_id = 0;
1374+
maximize_old_handler_id = latest_window_snapshot.transition_stopped.connect ((snapshot, name, is_finished) => {
1375+
snapshot.disconnect (maximize_old_handler_id);
13911376

1392-
actor.save_easing_state ();
1393-
actor.set_easing_mode (Clutter.AnimationMode.EASE_IN_OUT_QUAD);
1394-
actor.set_easing_duration (duration);
1395-
actor.set_scale (1.0f, 1.0f);
13961377
actor.set_translation (0.0f, 0.0f, 0.0f);
1397-
actor.restore_easing_state ();
13981378

1399-
ulong handler_id = 0UL;
1400-
handler_id = actor.transitions_completed.connect (() => {
1401-
actor.disconnect (handler_id);
1402-
maximizing.remove (actor);
1403-
});
1404-
}
1379+
unowned var parent = snapshot.get_parent ();
1380+
if (parent != null) {
1381+
parent.remove_child (snapshot);
1382+
}
1383+
});
1384+
1385+
latest_window_snapshot = null;
1386+
1387+
actor.set_pivot_point (0.0f, 0.0f);
1388+
actor.set_translation (old_rect_size_change.x - ex, old_rect_size_change.y - ey, 0.0f);
1389+
actor.set_scale (1.0f / scale_x, 1.0f / scale_y);
1390+
1391+
actor.save_easing_state ();
1392+
actor.set_easing_mode (Clutter.AnimationMode.EASE_IN_OUT_QUAD);
1393+
actor.set_easing_duration (duration);
1394+
actor.set_scale (1.0f, 1.0f);
1395+
actor.set_translation (0.0f, 0.0f, 0.0f);
1396+
actor.restore_easing_state ();
1397+
1398+
ulong handler_id = 0UL;
1399+
handler_id = actor.transitions_completed.connect (() => {
1400+
actor.disconnect (handler_id);
1401+
maximizing.remove (actor);
1402+
});
14051403
}
14061404

14071405
public override void unminimize (Meta.WindowActor actor) {
@@ -1693,76 +1691,76 @@ namespace Gala {
16931691
}
16941692

16951693
private void unmaximize (Meta.WindowActor actor, int ex, int ey, int ew, int eh) {
1696-
if (!AnimationsSettings.get_enable_animations ()) {
1694+
unowned var window = actor.get_meta_window ();
1695+
move_window_to_old_ws (window);
1696+
1697+
kill_window_effects (actor);
1698+
1699+
if (!AnimationsSettings.get_enable_animations () ||
1700+
latest_window_snapshot == null ||
1701+
window.window_type != Meta.WindowType.NORMAL) {
16971702
return;
16981703
}
16991704

17001705
var duration = AnimationDuration.SNAP;
17011706

1702-
kill_window_effects (actor);
1703-
unowned var window = actor.get_meta_window ();
1704-
1705-
move_window_to_old_ws (window);
1706-
1707-
if (window.window_type == Meta.WindowType.NORMAL) {
1708-
float offset_x, offset_y;
1709-
var unmaximized_window_geometry = WindowListener.get_default ().get_unmaximized_state_geometry (window);
1707+
float offset_x, offset_y;
1708+
var unmaximized_window_geometry = WindowListener.get_default ().get_unmaximized_state_geometry (window);
17101709

1711-
if (unmaximized_window_geometry != null) {
1712-
offset_x = unmaximized_window_geometry.outer.x - unmaximized_window_geometry.inner.x;
1713-
offset_y = unmaximized_window_geometry.outer.y - unmaximized_window_geometry.inner.y;
1714-
} else {
1715-
offset_x = 0;
1716-
offset_y = 0;
1717-
}
1710+
if (unmaximized_window_geometry != null) {
1711+
offset_x = unmaximized_window_geometry.outer.x - unmaximized_window_geometry.inner.x;
1712+
offset_y = unmaximized_window_geometry.outer.y - unmaximized_window_geometry.inner.y;
1713+
} else {
1714+
offset_x = 0;
1715+
offset_y = 0;
1716+
}
17181717

1719-
if (latest_window_snapshot == null) {
1720-
return;
1721-
}
1718+
unmaximizing.add (actor);
17221719

1723-
unmaximizing.add (actor);
1720+
latest_window_snapshot.set_position (old_rect_size_change.x, old_rect_size_change.y);
17241721

1725-
latest_window_snapshot.set_position (old_rect_size_change.x, old_rect_size_change.y);
1722+
ui_group.add_child (latest_window_snapshot);
17261723

1727-
ui_group.add_child (latest_window_snapshot);
1724+
var scale_x = (float) ew / old_rect_size_change.width;
1725+
var scale_y = (float) eh / old_rect_size_change.height;
17281726

1729-
var scale_x = (float) ew / old_rect_size_change.width;
1730-
var scale_y = (float) eh / old_rect_size_change.height;
1727+
latest_window_snapshot.save_easing_state ();
1728+
latest_window_snapshot.set_easing_mode (Clutter.AnimationMode.EASE_IN_OUT_QUAD);
1729+
latest_window_snapshot.set_easing_duration (duration);
1730+
latest_window_snapshot.set_position (ex, ey);
1731+
latest_window_snapshot.set_scale (scale_x, scale_y);
1732+
latest_window_snapshot.opacity = 0U;
1733+
latest_window_snapshot.restore_easing_state ();
17311734

1732-
latest_window_snapshot.save_easing_state ();
1733-
latest_window_snapshot.set_easing_mode (Clutter.AnimationMode.EASE_IN_OUT_QUAD);
1734-
latest_window_snapshot.set_easing_duration (duration);
1735-
latest_window_snapshot.set_position (ex, ey);
1736-
latest_window_snapshot.set_scale (scale_x, scale_y);
1737-
latest_window_snapshot.opacity = 0U;
1738-
latest_window_snapshot.restore_easing_state ();
1735+
ulong unmaximize_old_handler_id = 0;
1736+
unmaximize_old_handler_id = latest_window_snapshot.transition_stopped.connect ((snapshot, name, is_finished) => {
1737+
snapshot.disconnect (unmaximize_old_handler_id);
17391738

1740-
ulong unmaximize_old_handler_id = 0UL;
1741-
unmaximize_old_handler_id = latest_window_snapshot.transitions_completed.connect ((snapshot) => {
1742-
snapshot.disconnect (unmaximize_old_handler_id);
1743-
snapshot.destroy ();
1744-
});
1739+
unowned var parent = snapshot.get_parent ();
1740+
if (parent != null) {
1741+
parent.remove_child (snapshot);
1742+
}
1743+
});
17451744

1746-
latest_window_snapshot = null;
1745+
latest_window_snapshot = null;
17471746

1748-
actor.set_pivot_point (0.0f, 0.0f);
1749-
actor.set_position (ex, ey);
1750-
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);
1751-
actor.set_scale (1.0f / scale_x, 1.0f / scale_y);
1747+
actor.set_pivot_point (0.0f, 0.0f);
1748+
actor.set_position (ex, ey);
1749+
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);
1750+
actor.set_scale (1.0f / scale_x, 1.0f / scale_y);
17521751

1753-
actor.save_easing_state ();
1754-
actor.set_easing_mode (Clutter.AnimationMode.EASE_IN_OUT_QUAD);
1755-
actor.set_easing_duration (duration);
1756-
actor.set_scale (1.0f, 1.0f);
1757-
actor.set_translation (0.0f, 0.0f, 0.0f);
1758-
actor.restore_easing_state ();
1752+
actor.save_easing_state ();
1753+
actor.set_easing_mode (Clutter.AnimationMode.EASE_IN_OUT_QUAD);
1754+
actor.set_easing_duration (duration);
1755+
actor.set_scale (1.0f, 1.0f);
1756+
actor.set_translation (0.0f, 0.0f, 0.0f);
1757+
actor.restore_easing_state ();
17591758

1760-
ulong handler_id = 0UL;
1761-
handler_id = actor.transitions_completed.connect (() => {
1762-
actor.disconnect (handler_id);
1763-
unmaximizing.remove (actor);
1764-
});
1765-
}
1759+
ulong handler_id = 0UL;
1760+
handler_id = actor.transitions_completed.connect (() => {
1761+
actor.disconnect (handler_id);
1762+
unmaximizing.remove (actor);
1763+
});
17661764
}
17671765

17681766
private void move_window_to_next_ws (Meta.Window window) {

0 commit comments

Comments
 (0)