Skip to content
Open
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
27 changes: 27 additions & 0 deletions compositor/ShellClients/ExtendedBehaviorWindow.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2025 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Authored by: Leonhard Kargl <leo.kargl@proton.me>
*/

public class GreeterCompositor.ExtendedBehaviorWindow : ShellWindow {
public bool modal { get; private set; default = false; }
public bool dim { get; private set; default = false; }

public ExtendedBehaviorWindow (Meta.Window window) {
Object (window: window);
}

public void make_modal (bool dim) {
modal = true;
this.dim = dim;
}

protected override void get_window_position (Mtk.Rectangle window_rect, out int x, out int y) {
var monitor_rect = window.display.get_monitor_geometry (window.get_monitor ());

x = monitor_rect.x + (monitor_rect.width - window_rect.width) / 2;
y = monitor_rect.y + (monitor_rect.height - window_rect.height) / 2;
}
}
51 changes: 47 additions & 4 deletions compositor/ShellClients/PanelWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,33 @@ public class GreeterCompositor.PanelWindow : ShellWindow {
private int height = -1;

public PanelWindow (WindowManager wm, Meta.Window window, Pantheon.Desktop.Anchor anchor) {
Object (wm: wm, anchor: anchor, window: window, position: Position.from_anchor (anchor));
Object (wm: wm, window: window, anchor: anchor);
}

construct {
update_strut ();

window.unmanaging.connect (() => {
if (window_struts.remove (window)) {
update_struts ();
}
});

notify["anchor"].connect (() => position = Position.from_anchor (anchor));
notify["anchor"].connect (position_window);

unowned var workspace_manager = window.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);
notify["width"].connect (update_strut);
notify["height"].connect (update_strut);

var window_actor = (Meta.WindowActor) window.get_compositor_private ();

window_actor.notify["width"].connect (update_clip);
window_actor.notify["height"].connect (update_clip);
window_actor.notify["translation-y"].connect (update_clip);
notify["anchor"].connect (update_clip);
}

public Mtk.Rectangle get_custom_window_rect () {
Expand Down Expand Up @@ -103,4 +110,40 @@ public class GreeterCompositor.PanelWindow : ShellWindow {
return TOP;
}
}

protected override void get_window_position (Mtk.Rectangle window_rect, out int x, out int y) {
var monitor_rect = window.display.get_monitor_geometry (window.display.get_primary_monitor ());
switch (anchor) {
case TOP:
x = monitor_rect.x + (monitor_rect.width - window_rect.width) / 2;
y = monitor_rect.y;
break;

case BOTTOM:
x = monitor_rect.x + (monitor_rect.width - window_rect.width) / 2;
y = monitor_rect.y + monitor_rect.height - window_rect.height;
break;

default:
warning ("Unsupported anchor %s for PanelWindow", anchor.to_string ());
x = 0;
y = 0;
break;
}
}

private void update_clip () {
var monitor_geom = window.display.get_monitor_geometry (window.get_monitor ());
var window_actor = (Meta.WindowActor) window.get_compositor_private ();

var y = window_actor.y + window_actor.translation_y;

if (y + window_actor.height > monitor_geom.y + monitor_geom.height) {
window_actor.set_clip (0, 0, window_actor.width, monitor_geom.y + monitor_geom.height - y);
} else if (y < monitor_geom.y) {
window_actor.set_clip (0, monitor_geom.y - y, window_actor.width, window_actor.height);
} else {
window_actor.remove_clip ();
}
}
}
69 changes: 7 additions & 62 deletions compositor/ShellClients/PositionedWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,11 @@
* Authored by: Leonhard Kargl <leo.kargl@proton.me>
*/

public class GreeterCompositor.PositionedWindow : Object {
public enum Position {
TOP,
BOTTOM,
CENTER,
FULLSCREEN;

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 abstract class GreeterCompositor.PositionedWindow : Object {
public Meta.Window window { get; construct; }
/**
* 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; }

private ulong position_changed_id;

public PositionedWindow (Meta.Window window, Position position, Variant? position_data = null) {
Object (window: window, position: position, position_data: position_data);
}

construct {
window.stick ();

Expand All @@ -46,47 +20,18 @@ public class GreeterCompositor.PositionedWindow : Object {
unowned var monitor_manager = window.display.get_context ().get_backend ().get_monitor_manager ();
monitor_manager.monitors_changed.connect (position_window);
monitor_manager.monitors_changed_internal.connect (position_window);

notify["position"].connect (position_window);
notify["position-data"].connect (position_window);
}

private void position_window () {
int x = 0, y = 0;
protected void position_window () {
var window_rect = window.get_frame_rect ();
int width = window_rect.width, height = window_rect.height;
unowned var display = window.display;

switch (position) {
case CENTER:
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) / 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;

case FULLSCREEN:
var monitor_geom = display.get_monitor_geometry (display.get_primary_monitor ());
x = monitor_geom.x;
y = monitor_geom.y;
width = monitor_geom.width;
height = monitor_geom.height;
break;
}
int x = 0, y = 0;
get_window_position (window_rect, out x, out y);

SignalHandler.block (window, position_changed_id);
window.move_resize_frame (false, x, y, width, height);
window.move_frame (false, x, y);
SignalHandler.unblock (window, position_changed_id);
}

protected abstract void get_window_position (Mtk.Rectangle window_rect, out int x, out int y);
}
9 changes: 3 additions & 6 deletions compositor/ShellClients/ShellClientsManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,13 @@ public class GreeterCompositor.ShellClientsManager : Object {
return instance;
}

public Clutter.Actor? actor { get { return wm.stage; } }

public WindowManager wm { get; construct; }

private NotificationsClient notifications_client;
private ManagedClient[] protocol_clients = {};

private GLib.HashTable<Meta.Window, PanelWindow> panel_windows = new GLib.HashTable<Meta.Window, PanelWindow> (null, null);
private GLib.HashTable<Meta.Window, ShellWindow> positioned_windows = new GLib.HashTable<Meta.Window, ShellWindow> (null, null);
private GLib.HashTable<Meta.Window, ExtendedBehaviorWindow> positioned_windows = new GLib.HashTable<Meta.Window, ExtendedBehaviorWindow> (null, null);

private ShellClientsManager (WindowManager wm) {
Object (wm: wm);
Expand Down Expand Up @@ -95,7 +93,6 @@ public class GreeterCompositor.ShellClientsManager : Object {
}
#endif


public void make_desktop (Meta.Window window) {
#if HAS_MUTTER49
window.set_type (Meta.WindowType.DESKTOP);
Expand Down Expand Up @@ -176,14 +173,14 @@ public class GreeterCompositor.ShellClientsManager : Object {
public void init_greeter (Meta.Window window) {
make_desktop (window);

positioned_windows[window] = new ShellWindow (window, FULLSCREEN);
positioned_windows[window] = new ExtendedBehaviorWindow (window);

// connect_after so we make sure that any queued move is unqueued
window.unmanaging.connect_after ((_window) => positioned_windows.remove (_window));
}

public void make_centered (Meta.Window window) requires (!is_itself_shell_window (window)) {
positioned_windows[window] = new ShellWindow (window, CENTER);
positioned_windows[window] = new ExtendedBehaviorWindow (window);

// connect_after so we make sure that any queued move is unqueued
window.unmanaging.connect_after ((_window) => positioned_windows.remove (_window));
Expand Down
36 changes: 1 addition & 35 deletions compositor/ShellClients/ShellWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,6 @@
* Authored by: Leonhard Kargl <leo.kargl@proton.me>
*/

public class GreeterCompositor.ShellWindow : PositionedWindow {
public Clutter.Actor? actor { get { return window_actor; } }
public abstract class GreeterCompositor.ShellWindow : PositionedWindow {

private Meta.WindowActor window_actor;

public ShellWindow (Meta.Window window, Position position, Variant? position_data = null) {
base (window, position, position_data);
}

construct {
window_actor = (Meta.WindowActor) window.get_compositor_private ();

window_actor.notify["width"].connect (update_clip);
window_actor.notify["height"].connect (update_clip);
window_actor.notify["translation-y"].connect (update_clip);
notify["position"].connect (update_clip);
}

private void update_clip () {
if (position != TOP && position != BOTTOM) {
window_actor.remove_clip ();
return;
}

var monitor_geom = window.display.get_monitor_geometry (window.get_monitor ());

var y = window_actor.y + window_actor.translation_y;

if (y + window_actor.height > monitor_geom.y + monitor_geom.height) {
window_actor.set_clip (0, 0, window_actor.width, monitor_geom.y + monitor_geom.height - y);
} else if (y < monitor_geom.y) {
window_actor.set_clip (0, monitor_geom.y - y, window_actor.width, window_actor.height);
} else {
window_actor.remove_clip ();
}
}
}
1 change: 1 addition & 0 deletions compositor/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ compositor_files = files(
'Background/SystemBackground.vala',
'PantheonShell.vala',
'ShellClients/CenteredWindow.vala',
'ShellClients/ExtendedBehaviorWindow.vala',
'ShellClients/ManagedClient.vala',
'ShellClients/NotificationsClient.vala',
'ShellClients/PanelWindow.vala',
Expand Down
Loading