Skip to content

Commit

Permalink
Use WindowPositioner for panel positions (#2109)
Browse files Browse the repository at this point in the history
Co-authored-by: Leo <lenemter@gmail.com>
Co-authored-by: Ryan Kornheisl <ryan@skarva.tech>
  • Loading branch information
3 people authored Dec 7, 2024
1 parent 58e5b42 commit 9d0e352
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 136 deletions.
20 changes: 1 addition & 19 deletions src/PantheonShell.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
24 changes: 12 additions & 12 deletions src/ShellClients/HideTracker.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

Expand Down
116 changes: 30 additions & 86 deletions src/ShellClients/PanelWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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 ();
}
Expand All @@ -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
Expand Down Expand Up @@ -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;

Expand All @@ -173,7 +101,7 @@ public class Gala.PanelWindow : Object {

Meta.Strut strut = {
rect,
anchor
side_from_anchor (anchor)
};

window_struts[window] = strut;
Expand All @@ -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;
}
}
}
32 changes: 27 additions & 5 deletions src/ShellClients/ShellClientsManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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);
Expand Down
48 changes: 34 additions & 14 deletions src/ShellClients/WindowPositioner.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit 9d0e352

Please sign in to comment.