diff --git a/src/ShellClients/CenteredWindow.vala b/src/ShellClients/CenteredWindow.vala deleted file mode 100644 index 6099c68d1..000000000 --- a/src/ShellClients/CenteredWindow.vala +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2024 elementary, Inc. (https://elementary.io) - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Authored by: Leonhard Kargl - */ - -public class Gala.CenteredWindow : Object { - public WindowManager wm { get; construct; } - public Meta.Window window { get; construct; } - - private uint idle_move_id = 0; - - public CenteredWindow (WindowManager wm, Meta.Window window) { - Object (wm: wm, window: window); - } - - construct { - window.size_changed.connect (position_window); - window.stick (); - - var monitor_manager = wm.get_display ().get_context ().get_backend ().get_monitor_manager (); - monitor_manager.monitors_changed.connect (() => position_window ()); - - position_window (); - - window.shown.connect (() => window.focus (wm.get_display ().get_current_time ())); - - window.unmanaging.connect (() => { - if (idle_move_id != 0) { - Source.remove (idle_move_id); - } - }); - } - - private void position_window () { - var display = wm.get_display (); - var monitor_geom = display.get_monitor_geometry (display.get_primary_monitor ()); - var window_rect = window.get_frame_rect (); - - var x = monitor_geom.x + (monitor_geom.width - window_rect.width) / 2; - var y = monitor_geom.y + (monitor_geom.height - window_rect.height) / 2; - - if (idle_move_id != 0) { - Source.remove (idle_move_id); - } - - idle_move_id = Idle.add (() => { - window.move_frame (false, x, y); - - idle_move_id = 0; - return Source.REMOVE; - }); - } -} diff --git a/src/ShellClients/ShellClientsManager.vala b/src/ShellClients/ShellClientsManager.vala index ad15ca9e8..05a765fc3 100644 --- a/src/ShellClients/ShellClientsManager.vala +++ b/src/ShellClients/ShellClientsManager.vala @@ -25,8 +25,8 @@ public class Gala.ShellClientsManager : Object { private NotificationsClient notifications_client; private ManagedClient[] protocol_clients = {}; - private GLib.HashTable windows = new GLib.HashTable (null, null); - private GLib.HashTable centered_windows = new GLib.HashTable (null, null); + private GLib.HashTable panel_windows = new GLib.HashTable (null, null); + private GLib.HashTable positioned_windows = new GLib.HashTable (null, null); private ShellClientsManager (WindowManager wm) { Object (wm: wm); @@ -144,18 +144,18 @@ public class Gala.ShellClientsManager : Object { } public void set_anchor (Meta.Window window, Meta.Side side) { - if (window in windows) { - windows[window].update_anchor (side); + if (window in panel_windows) { + panel_windows[window].update_anchor (side); return; } make_dock (window); // TODO: Return if requested by window that's not a trusted client? - windows[window] = new PanelWindow (wm, window, side); + panel_windows[window] = new PanelWindow (wm, window, side); // connect_after so we make sure the PanelWindow can destroy its barriers and struts - window.unmanaging.connect_after (() => windows.remove (window)); + window.unmanaging.connect_after ((_window) => panel_windows.remove (_window)); } /** @@ -166,37 +166,38 @@ public class Gala.ShellClientsManager : Object { * TODO: Maybe use for strut only? */ public void set_size (Meta.Window window, int width, int height) { - if (!(window in windows)) { + if (!(window in panel_windows)) { warning ("Set anchor for window before size."); return; } - windows[window].set_size (width, height); + panel_windows[window].set_size (width, height); } public void set_hide_mode (Meta.Window window, Pantheon.Desktop.HideMode hide_mode) { - if (!(window in windows)) { + if (!(window in panel_windows)) { warning ("Set anchor for window before hide mode."); return; } - windows[window].set_hide_mode (hide_mode); + panel_windows[window].set_hide_mode (hide_mode); } - public void make_centered (Meta.Window window) { - if (window in centered_windows) { - return; - } + public void make_centered (Meta.Window window) requires (!is_itself_positioned (window)) { + positioned_windows[window] = new WindowPositioner (wm, window, CENTER); - centered_windows[window] = new CenteredWindow (wm, window); + // connect_after so we make sure that any queued move is unqueued + window.unmanaging.connect_after ((_window) => positioned_windows.remove (_window)); + } - window.unmanaging.connect_after (() => centered_windows.remove (window)); + private bool is_itself_positioned (Meta.Window window) { + return (window in positioned_windows) || (window in panel_windows); } public bool is_positioned_window (Meta.Window window) { - bool positioned = (window in centered_windows) || (window in windows); + bool positioned = is_itself_positioned (window); window.foreach_ancestor ((ancestor) => { - if (ancestor in centered_windows || ancestor in windows) { + if (is_itself_positioned (ancestor)) { positioned = true; } diff --git a/src/ShellClients/WindowPositioner.vala b/src/ShellClients/WindowPositioner.vala new file mode 100644 index 000000000..3966d359e --- /dev/null +++ b/src/ShellClients/WindowPositioner.vala @@ -0,0 +1,60 @@ +/* + * Copyright 2024 elementary, Inc. (https://elementary.io) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Authored by: Leonhard Kargl + */ + +public class Gala.WindowPositioner : Object { + public enum Position { + CENTER + } + + public Meta.Window window { get; construct; } + public WindowManager wm { get; construct; } + public Position position { get; private set; } + public Variant? position_data { get; private set; } + + public WindowPositioner (WindowManager wm, Meta.Window window, Position position, Variant? position_data = null) { + Object (wm: wm, window: window, position: position, position_data: position_data); + } + + construct { + window.stick (); + + window.size_changed.connect (position_window); + window.position_changed.connect (position_window); + window.shown.connect (position_window); + + unowned var monitor_manager = wm.get_display ().get_context ().get_backend ().get_monitor_manager (); + monitor_manager.monitors_changed.connect (position_window); + monitor_manager.monitors_changed_internal.connect (position_window); + } + + /** + * This may only be called after the window was shown. + */ + public void update_position (Position new_position, Variant? new_position_data = null) { + position = new_position; + position_data = new_position_data; + + position_window (); + } + + private void position_window () { + int x = 0, y = 0; + + switch (position) { + case CENTER: + unowned var display = wm.get_display (); + var monitor_geom = display.get_monitor_geometry (display.get_primary_monitor ()); + var window_rect = window.get_frame_rect (); + + x = monitor_geom.x + (monitor_geom.width - window_rect.width) / 2; + y = monitor_geom.y + (monitor_geom.height - window_rect.height) / 2; + break; + } + + window.move_frame (false, x, y); + } +} diff --git a/src/meson.build b/src/meson.build index e2e61807b..7e6488fd1 100644 --- a/src/meson.build +++ b/src/meson.build @@ -41,13 +41,13 @@ gala_bin_sources = files( 'HotCorners/Barrier.vala', 'HotCorners/HotCorner.vala', 'HotCorners/HotCornerManager.vala', - 'ShellClients/CenteredWindow.vala', 'ShellClients/HideTracker.vala', 'ShellClients/ManagedClient.vala', 'ShellClients/NotificationsClient.vala', 'ShellClients/PanelClone.vala', 'ShellClients/PanelWindow.vala', 'ShellClients/ShellClientsManager.vala', + 'ShellClients/WindowPositioner.vala', 'Widgets/DwellClickTimer.vala', 'Widgets/IconGroup.vala', 'Widgets/IconGroupContainer.vala',