Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use WindowPositioner for panel positions #2109

Merged
merged 13 commits into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
lenemter marked this conversation as resolved.
Show resolved Hide resolved
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; }
lenemter marked this conversation as resolved.
Show resolved Hide resolved

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
Loading