diff --git a/src/HidableWindow.vala b/src/HidableWindow.vala new file mode 100644 index 000000000..6a61a9175 --- /dev/null +++ b/src/HidableWindow.vala @@ -0,0 +1,98 @@ +/* + * SPDX-License-Identifier: GPL-3.0-or-later + * SPDX-FileCopyrightText: 2024 elementary, Inc. (https://elementary.io) + */ + +/* Hides windows on both X11 and Wayland */ +public class Gala.HidableWindow : GLib.Object { + private const int OUT_OF_BOUNDS = 1000000; + + public Meta.Window window { get; construct; } + + /* Current window actor position or position before the window was moved out of bounds */ + public float x { get; private set; default = 0.0f; } + public float y { get; private set; default = 0.0f; } + + /* Current window position or position before it was moved out of bounds */ + private int actual_x { get; private set; default = 0; } + private int actual_y { get; private set; default = 0; } + + public HidableWindow (Meta.Window window) { + Object (window: window); + } + + construct { + var rect = window.get_frame_rect (); + actual_x = rect.x; + actual_y = rect.y; + + unowned var actor = (Meta.WindowActor) window.get_compositor_private (); + if (actor != null) { + x = actor.x; + y = actor.y; + } + + window.position_changed.connect (on_window_position_changed); + } + + private void on_window_position_changed () requires (window != null) { + var rect = window.get_frame_rect (); + + if (rect.x != OUT_OF_BOUNDS) { + actual_x = rect.x; + + Idle.add_once (() => { + return_if_fail (window != null); + unowned var actor = (Meta.WindowActor) window.get_compositor_private (); + return_if_fail (actor != null); + x = actor.x; + }); + } + + if (rect.y != OUT_OF_BOUNDS) { + actual_y = rect.y; + + Idle.add_once (() => { + return_if_fail (window != null); + unowned var actor = (Meta.WindowActor) window.get_compositor_private (); + return_if_fail (actor != null); + y = actor.y; + }); + } + } + + public void hide_window () requires (window != null) { + unowned var actor = (Meta.WindowActor) window.get_compositor_private (); + if (actor != null) { + actor.visible = false; + } + + if (!Meta.Util.is_wayland_compositor ()) { + window.move_frame (false, HidableWindow.OUT_OF_BOUNDS, HidableWindow.OUT_OF_BOUNDS); + } + } + + public void show_window () requires (window != null) { + unowned var actor = (Meta.WindowActor) window.get_compositor_private (); + if (actor != null) { + actor.visible = true; + } + + if (!Meta.Util.is_wayland_compositor ()) { + window.move_frame (false, actual_x, actual_y); + } + } + + public Mtk.Rectangle get_frame_rect () { + if (window == null) { + Mtk.Rectangle null_rect = { 0, 0, 0, 0 }; + return null_rect; + } + + var window_rect = window.get_frame_rect (); + window_rect.x = actual_x; + window_rect.y = actual_y; + + return window_rect; + } +} diff --git a/src/ShellClients/DelegateActor.vala b/src/ShellClients/DelegateActor.vala deleted file mode 100644 index bd93f9128..000000000 --- a/src/ShellClients/DelegateActor.vala +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0-or-later - * SPDX-FileCopyrightText: 2024 elementary, Inc. (https://elementary.io) - */ - -/* This class is used to workaround https://github.com/elementary/gala/issues/2101 */ -public class Gala.DelegateActor : GLib.Object { - public const int OUT_OF_BOUNDS = 1000000; - - public Meta.WindowActor actor { get; construct; } - - /* Current window actor position or position before the window was moved out of bounds */ - public float x { get; private set; default = 0.0f; } - public float y { get; private set; default = 0.0f; } - - /* Current window position or position before it was moved out of bounds */ - public int actual_x { get; private set; default = 0; } - public int actual_y { get; private set; default = 0; } - - public DelegateActor (Meta.WindowActor actor) { - Object (actor: actor); - } - - construct { - actor.meta_window.position_changed.connect ((_window) => { - var rect = _window.get_frame_rect (); - - if (rect.x != OUT_OF_BOUNDS) { - actual_x = rect.x; - Idle.add_once (() => { - x = actor.x; - }); - } - if (rect.y != OUT_OF_BOUNDS) { - actual_y = rect.y; - Idle.add_once (() => { - y = actor.y; - }); - } - }); - } -} diff --git a/src/ShellClients/PanelClone.vala b/src/ShellClients/PanelClone.vala index 15fc8d23f..c717072ed 100644 --- a/src/ShellClients/PanelClone.vala +++ b/src/ShellClients/PanelClone.vala @@ -48,8 +48,8 @@ public class Gala.PanelClone : Object { actor = (Meta.WindowActor) panel.window.get_compositor_private (); // WindowActor position and Window position aren't necessarily the same. // The clone needs the actor position - panel.delegate_actor.notify["x"].connect (update_clone_position); - panel.delegate_actor.notify["y"].connect (update_clone_position); + panel.hidable_window.notify["x"].connect (update_clone_position); + panel.hidable_window.notify["y"].connect (update_clone_position); // Actor visibility might be changed by something else e.g. workspace switch // but we want to keep it in sync with us actor.notify["visible"].connect (update_visible); @@ -80,7 +80,11 @@ public class Gala.PanelClone : Object { } private void update_visible () { - actor.visible = !panel_hidden; + if (panel_hidden) { + panel.hidable_window.hide_window (); + } else { + panel.hidable_window.show_window (); + } if (actor.visible && !wm.get_display ().get_monitor_in_fullscreen (panel.window.get_monitor ())) { // The actor has just been revealed, make sure it's at the top @@ -97,7 +101,7 @@ public class Gala.PanelClone : Object { switch (panel.anchor) { case TOP: case BOTTOM: - return panel.delegate_actor.x; + return panel.hidable_window.x; default: return 0; } @@ -106,9 +110,9 @@ public class Gala.PanelClone : Object { private float calculate_clone_y (bool hidden) { switch (panel.anchor) { case TOP: - return hidden ? panel.delegate_actor.y - actor.height : panel.delegate_actor.y; + return hidden ? panel.hidable_window.y - actor.height : panel.hidable_window.y; case BOTTOM: - return hidden ? panel.delegate_actor.y + actor.height : panel.delegate_actor.y; + return hidden ? panel.hidable_window.y + actor.height : panel.hidable_window.y; default: return 0; } @@ -127,10 +131,6 @@ public class Gala.PanelClone : Object { panel_hidden = true; - if (!Meta.Util.is_wayland_compositor ()) { - panel.window.move_frame (false, DelegateActor.OUT_OF_BOUNDS, DelegateActor.OUT_OF_BOUNDS); - } - if (panel.anchor != TOP && panel.anchor != BOTTOM) { warning ("Animated hide not supported for side yet."); return; @@ -150,10 +150,6 @@ public class Gala.PanelClone : Object { return; } - if (!Meta.Util.is_wayland_compositor ()) { - panel.window.move_frame (false, panel.delegate_actor.actual_x, panel.delegate_actor.actual_y); - } - clone.save_easing_state (); clone.set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD); clone.set_easing_duration (get_animation_duration ()); diff --git a/src/ShellClients/PanelWindow.vala b/src/ShellClients/PanelWindow.vala index 107218e11..bac1e3983 100644 --- a/src/ShellClients/PanelWindow.vala +++ b/src/ShellClients/PanelWindow.vala @@ -15,7 +15,7 @@ public class Gala.PanelWindow : Object { public Meta.Side anchor; - public DelegateActor delegate_actor; + public HidableWindow hidable_window; private PanelClone clone; private uint idle_move_id = 0; @@ -46,7 +46,7 @@ public class Gala.PanelWindow : Object { window.stick (); - delegate_actor = new DelegateActor ((Meta.WindowActor) window.get_compositor_private ()); + hidable_window = new HidableWindow (window); clone = new PanelClone (wm, this); var monitor_manager = wm.get_display ().get_context ().get_backend ().get_monitor_manager (); @@ -63,9 +63,7 @@ public class Gala.PanelWindow : Object { #else public Meta.Rectangle get_custom_window_rect () { #endif - var window_rect = window.get_frame_rect (); - window_rect.x = delegate_actor.actual_x; - window_rect.y = delegate_actor.actual_y; + var window_rect = hidable_window.get_frame_rect (); if (width > 0) { window_rect.width = width; diff --git a/src/meson.build b/src/meson.build index d8fa147aa..89bf5f571 100644 --- a/src/meson.build +++ b/src/meson.build @@ -4,6 +4,7 @@ gala_bin_sources = files( 'DaemonManager.vala', 'DesktopIntegration.vala', 'Dialogs.vala', + 'HidableWindow.vala', 'InternalUtils.vala', 'KeyboardManager.vala', 'Main.vala', @@ -41,7 +42,6 @@ gala_bin_sources = files( 'HotCorners/Barrier.vala', 'HotCorners/HotCorner.vala', 'HotCorners/HotCornerManager.vala', - 'ShellClients/DelegateActor.vala', 'ShellClients/HideTracker.vala', 'ShellClients/ManagedClient.vala', 'ShellClients/NotificationsClient.vala',