diff --git a/src/PantheonShell.vala b/src/PantheonShell.vala index 1e0f173ff..0dabcb683 100644 --- a/src/PantheonShell.vala +++ b/src/PantheonShell.vala @@ -243,25 +243,7 @@ namespace Gala { return; } - Meta.Side side = TOP; - switch (anchor) { - case TOP: - break; - - case BOTTOM: - side = BOTTOM; - break; - - case LEFT: - side = LEFT; - break; - - case RIGHT: - side = RIGHT; - break; - } - - ShellClientsManager.get_instance ().set_anchor (window, side); + ShellClientsManager.get_instance ().set_anchor (window, anchor); } internal static void focus_panel (Wl.Client client, Wl.Resource resource) { diff --git a/src/ShellClients/HideTracker.vala b/src/ShellClients/HideTracker.vala index 35ed7a0d4..ee6f9cd26 100644 --- a/src/ShellClients/HideTracker.vala +++ b/src/ShellClients/HideTracker.vala @@ -16,17 +16,7 @@ public class Gala.HideTracker : Object { public Meta.Display display { get; construct; } public unowned PanelWindow panel { get; construct; } - private Pantheon.Desktop.HideMode _hide_mode = NEVER; - public Pantheon.Desktop.HideMode hide_mode { - get { - return _hide_mode; - } - set { - _hide_mode = value; - - setup_barrier (); - } - } + public Pantheon.Desktop.HideMode hide_mode { get; set; } private Clutter.PanAction pan_action; @@ -97,6 +87,16 @@ public class Gala.HideTracker : Object { pan_action.pan.connect (on_pan); display.get_stage ().add_action_full ("panel-swipe-gesture", CAPTURE, pan_action); + + panel.notify["anchor"].connect (setup_barrier); + + var monitor_manager = display.get_context ().get_backend ().get_monitor_manager (); + monitor_manager.monitors_changed.connect (() => { + setup_barrier (); //Make sure barriers are still on the primary monitor + schedule_update (); + }); + + setup_barrier (); } #if !HAS_MUTTER45 @@ -171,7 +171,7 @@ public class Gala.HideTracker : Object { continue; } - if (!panel.get_custom_window_rect ().overlap (window.get_frame_rect ())) { + if (!panel.window.get_frame_rect ().overlap (window.get_frame_rect ())) { continue; } diff --git a/src/ShellClients/PanelWindow.vala b/src/ShellClients/PanelWindow.vala index 5351cbe5a..7e29bd656 100644 --- a/src/ShellClients/PanelWindow.vala +++ b/src/ShellClients/PanelWindow.vala @@ -10,34 +10,21 @@ public class Gala.PanelWindow : Object { public WindowManager wm { get; construct; } public Meta.Window window { get; construct; } + public Pantheon.Desktop.Anchor anchor { get; construct set; } - public bool hidden { get; private set; default = false; } - - public Meta.Side anchor; + private WindowPositioner window_positioner; private PanelClone clone; - private uint idle_move_id = 0; - private int width = -1; private int height = -1; - public PanelWindow (WindowManager wm, Meta.Window window, Meta.Side anchor) { - Object (wm: wm, window: window); - - // Meta.Side seems to be currently not supported as GLib.Object property ...? - // At least it always crashed for me with some paramspec, g_type_fundamental backtrace - this.anchor = anchor; + public PanelWindow (WindowManager wm, Meta.Window window, Pantheon.Desktop.Anchor anchor) { + Object (wm: wm, window: window, anchor: anchor); } construct { - window.size_changed.connect (position_window); - window.unmanaging.connect (() => { - if (idle_move_id != 0) { - Source.remove (idle_move_id); - } - if (window_struts.remove (window)) { update_struts (); } @@ -47,13 +34,18 @@ public class Gala.PanelWindow : Object { clone = new PanelClone (wm, this); - var monitor_manager = wm.get_display ().get_context ().get_backend ().get_monitor_manager (); - monitor_manager.monitors_changed.connect (() => update_anchor (anchor)); - monitor_manager.monitors_changed_internal.connect (() => update_anchor (anchor)); + unowned var display = wm.get_display (); - var workspace_manager = wm.get_display ().get_workspace_manager (); + unowned var workspace_manager = display.get_workspace_manager (); workspace_manager.workspace_added.connect (update_strut); workspace_manager.workspace_removed.connect (update_strut); + + window.size_changed.connect (update_strut); + window.position_changed.connect (update_strut); + + window_positioner = new WindowPositioner (display, window, WindowPositioner.Position.from_anchor (anchor)); + + notify["anchor"].connect (() => window_positioner.position = WindowPositioner.Position.from_anchor (anchor)); } #if HAS_MUTTER45 @@ -83,73 +75,9 @@ public class Gala.PanelWindow : Object { this.width = width; this.height = height; - position_window (); - set_hide_mode (clone.hide_mode); // Resetup barriers etc. - } - - public void update_anchor (Meta.Side anchor) { - this.anchor = anchor; - - position_window (); - set_hide_mode (clone.hide_mode); // Resetup barriers etc. - } - - 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 (); - - switch (anchor) { - case TOP: - position_window_top (monitor_geom, window_rect); - break; - - case BOTTOM: - position_window_bottom (monitor_geom, window_rect); - break; - - default: - warning ("Side not supported yet"); - break; - } - update_strut (); } -#if HAS_MUTTER45 - private void position_window_top (Mtk.Rectangle monitor_geom, Mtk.Rectangle window_rect) { -#else - private void position_window_top (Meta.Rectangle monitor_geom, Meta.Rectangle window_rect) { -#endif - var x = monitor_geom.x + (monitor_geom.width - window_rect.width) / 2; - - move_window_idle (x, monitor_geom.y); - } - -#if HAS_MUTTER45 - private void position_window_bottom (Mtk.Rectangle monitor_geom, Mtk.Rectangle window_rect) { -#else - private void position_window_bottom (Meta.Rectangle monitor_geom, Meta.Rectangle window_rect) { -#endif - var x = monitor_geom.x + (monitor_geom.width - window_rect.width) / 2; - var y = monitor_geom.y + monitor_geom.height - window_rect.height; - - move_window_idle (x, y); - } - - private void move_window_idle (int x, int y) { - 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; - }); - } - public void set_hide_mode (Pantheon.Desktop.HideMode hide_mode) { clone.hide_mode = hide_mode; @@ -173,7 +101,7 @@ public class Gala.PanelWindow : Object { Meta.Strut strut = { rect, - anchor + side_from_anchor (anchor) }; window_struts[window] = strut; @@ -199,4 +127,20 @@ public class Gala.PanelWindow : Object { update_struts (); } } + + private Meta.Side side_from_anchor (Pantheon.Desktop.Anchor anchor) { + switch (anchor) { + case BOTTOM: + return BOTTOM; + + case LEFT: + return LEFT; + + case RIGHT: + return RIGHT; + + default: + return TOP; + } + } } diff --git a/src/ShellClients/ShellClientsManager.vala b/src/ShellClients/ShellClientsManager.vala index 757b1f08f..dfaa8b0ff 100644 --- a/src/ShellClients/ShellClientsManager.vala +++ b/src/ShellClients/ShellClientsManager.vala @@ -143,16 +143,16 @@ public class Gala.ShellClientsManager : Object { xdisplay.change_property (x_window, atom, (X.Atom) 4, 32, 0, (uchar[]) dock_atom, 1); } - public void set_anchor (Meta.Window window, Meta.Side side) { + public void set_anchor (Meta.Window window, Pantheon.Desktop.Anchor anchor) { if (window in panel_windows) { - panel_windows[window].update_anchor (side); + panel_windows[window].anchor = anchor; return; } make_dock (window); // TODO: Return if requested by window that's not a trusted client? - panel_windows[window] = new PanelWindow (wm, window, side); + panel_windows[window] = new PanelWindow (wm, window, anchor); // connect_after so we make sure the PanelWindow can destroy its barriers and struts window.unmanaging.connect_after ((_window) => panel_windows.remove (_window)); @@ -226,8 +226,30 @@ public class Gala.ShellClientsManager : Object { switch (key) { case "anchor": - int parsed; // Will be used as Meta.Side which is a 4 value bitfield so check bounds for that - if (int.try_parse (val, out parsed) && 0 <= parsed && parsed <= 15) { + int meta_side_parsed; // Will be used as Meta.Side which is a 4 value bitfield so check bounds for that + if (int.try_parse (val, out meta_side_parsed) && 0 <= meta_side_parsed && meta_side_parsed <= 15) { + //FIXME: Next major release change dock and wingpanel calls to get rid of this + Pantheon.Desktop.Anchor parsed = TOP; + switch ((Meta.Side) meta_side_parsed) { + case BOTTOM: + parsed = BOTTOM; + break; + + case LEFT: + parsed = LEFT; + break; + + case RIGHT: + parsed = RIGHT; + break; + + default: + break; + } + + set_anchor (window, parsed); + // We need to set a second time because the intention is to call this before the window is shown which it is on wayland + // but on X the window was already shown when we get here so we have to call again to instantly apply it. set_anchor (window, parsed); } else { warning ("Failed to parse %s as anchor", val); diff --git a/src/ShellClients/WindowPositioner.vala b/src/ShellClients/WindowPositioner.vala index 62b7928d7..daf838f14 100644 --- a/src/ShellClients/WindowPositioner.vala +++ b/src/ShellClients/WindowPositioner.vala @@ -7,13 +7,28 @@ public class Gala.WindowPositioner : Object { public enum Position { - CENTER + TOP, + BOTTOM, + CENTER; + + public static Position from_anchor (Pantheon.Desktop.Anchor anchor) { + if (anchor > 1) { + warning ("Position %s not supported yet", anchor.to_string ()); + return CENTER; + } + + return (Position) anchor; + } } public Meta.Display display { get; construct; } public Meta.Window window { get; construct; } - public Position position { get; private set; } - public Variant? position_data { get; private set; } + /** + * This may only be set after the window was shown. + * The initial position should only be given in the constructor. + */ + public Position position { get; construct set; } + public Variant? position_data { get; construct set; } public WindowPositioner (Meta.Display display, Meta.Window window, Position position, Variant? position_data = null) { Object (display: display, window: window, position: position, position_data: position_data); @@ -29,29 +44,34 @@ public class Gala.WindowPositioner : Object { unowned var monitor_manager = 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 (); + notify["position"].connect (position_window); + notify["position-data"].connect (position_window); } private void position_window () { int x = 0, y = 0; + var window_rect = window.get_frame_rect (); + switch (position) { case CENTER: 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; + + case TOP: + var monitor_geom = display.get_monitor_geometry (display.get_primary_monitor ()); + x = monitor_geom.x + (monitor_geom.width - window_rect.width) / 2; + y = monitor_geom.y; + break; + + case BOTTOM: + var monitor_geom = display.get_monitor_geometry (display.get_primary_monitor ()); + x = monitor_geom.x + (monitor_geom.width - window_rect.width) / 2; + y = monitor_geom.y + monitor_geom.height - window_rect.height; + break; } window.move_frame (false, x, y);