diff --git a/src/WindowStateSaver.vala b/src/WindowStateSaver.vala index 08d304c1b..0ab66e28c 100644 --- a/src/WindowStateSaver.vala +++ b/src/WindowStateSaver.vala @@ -4,6 +4,8 @@ */ public class Gala.WindowStateSaver : GLib.Object { + private const double REQUIRED_AREA_PERCENTAGE_IN_BOUNDS = 5.0; + [DBus (name = "org.freedesktop.login1.Manager")] private interface LoginManager : Object { public signal void prepare_for_sleep (bool about_to_suspend); @@ -125,7 +127,14 @@ public class Gala.WindowStateSaver : GLib.Object { } } - window.move_resize_frame (false, last_x, last_y, last_width, last_height); + // this is a fix for #2552 and #2526. + // window.move_resize_frame (false, ...) should constrain the window to the monitor bounds + // but mutter's constraint system can drop some constraints when it can't satisfy every single one of them. + // Instead we manually constrain the window based on its visible area. + if (validate_last_window_position (window.display, { last_x, last_y, last_width, last_height })) { + window.move_resize_frame (true, last_x, last_y, last_width, last_height); + } + track_window (window, app_id); return; } @@ -159,6 +168,22 @@ public class Gala.WindowStateSaver : GLib.Object { save_all_windows_state (); } + private static bool validate_last_window_position (Meta.Display display, Mtk.Rectangle position) { + var area_in_bounds = 0; + + var n_monitors = display.get_n_monitors (); + for (var i = 0; i < n_monitors; i++) { + var monitor_rect = display.get_monitor_geometry (i); + + Mtk.Rectangle intersection; + monitor_rect.intersect (position, out intersection); + + area_in_bounds += intersection.area (); + } + + return (double) area_in_bounds / position.area () * 100.0 >= REQUIRED_AREA_PERCENTAGE_IN_BOUNDS; + } + private static void track_window (Meta.Window window, string app_id) { window.unmanaging.connect (save_window_state); }