Skip to content

Commit f8346f0

Browse files
wayland: Implement make_center (#1942)
Co-authored-by: Danielle Foré <[email protected]>
1 parent 060deb2 commit f8346f0

File tree

6 files changed

+119
-11
lines changed

6 files changed

+119
-11
lines changed

protocol/pantheon-desktop-shell-v1.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,21 @@
111111
Tell the shell to keep the surface above on all workspaces
112112
</description>
113113
</request>
114+
115+
<request name="make_centered">
116+
<description summary="requests to keep the surface centered">
117+
Request to keep the surface centered. This will cause keyboard focus
118+
to not be granted automatically but having to be requested via focus.
119+
</description>
120+
</request>
121+
122+
<request name="focus">
123+
<description summary="request keyboard focus">
124+
Request keyboard focus, taking it away from any other window.
125+
Keyboard focus must always be manually be requested and is
126+
- in contrast to normal windows - never automatically granted
127+
by the compositor.
128+
</description>
129+
</request>
114130
</interface>
115131
</protocol>

protocol/pantheon-desktop-shell.vapi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ namespace Pantheon.Desktop {
5656
public static Wl.Interface iface;
5757
public Destroy destroy;
5858
public SetKeepAbove set_keep_above;
59+
public MakeCentered make_centered;
60+
public Focus focus;
5961
}
6062

6163
[CCode (has_target = false, has_typedef = false)]
@@ -75,5 +77,7 @@ namespace Pantheon.Desktop {
7577
[CCode (has_target = false, has_typedef = false)]
7678
public delegate void SetKeepAbove (Wl.Client client, Wl.Resource resource);
7779
[CCode (has_target = false, has_typedef = false)]
80+
public delegate void MakeCentered (Wl.Client client, Wl.Resource resource);
81+
[CCode (has_target = false, has_typedef = false)]
7882
public delegate void Destroy (Wl.Client client, Wl.Resource resource);
7983
}

src/PantheonShell.vala

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ namespace Gala {
5555
wayland_pantheon_panel_interface = {
5656
destroy_panel_surface,
5757
set_anchor,
58-
focus,
58+
focus_panel,
5959
set_size,
6060
set_hide_mode,
6161
};
@@ -67,9 +67,13 @@ namespace Gala {
6767
wayland_pantheon_extended_behavior_interface = {
6868
destroy_extended_behavior_surface,
6969
set_keep_above,
70+
make_centered,
71+
focus_extended_behavior,
7072
};
7173

7274
PanelSurface.quark = GLib.Quark.from_string ("-gala-wayland-panel-surface-data");
75+
WidgetSurface.quark = GLib.Quark.from_string ("-gala-wayland-widget-surface-data");
76+
ExtendedBehaviorSurface.quark = GLib.Quark.from_string ("-gala-wayland-extended-behavior-surface-data");
7377

7478
shell_global = Wl.Global.create (wl_disp, ref Pantheon.Desktop.ShellInterface.iface, 1, (client, version, id) => {
7579
unowned var resource = client.create_resource (ref Pantheon.Desktop.ShellInterface.iface, (int) version, id);
@@ -260,15 +264,29 @@ namespace Gala {
260264
ShellClientsManager.get_instance ().set_anchor (window, side);
261265
}
262266

263-
internal static void focus (Wl.Client client, Wl.Resource resource) {
267+
internal static void focus_panel (Wl.Client client, Wl.Resource resource) {
264268
unowned PanelSurface? panel_surface = resource.get_user_data<PanelSurface> ();
265269
if (panel_surface.wayland_surface == null) {
266270
warning ("Window tried to focus but wayland surface is null.");
267271
return;
268272
}
269273

274+
focus (panel_surface.wayland_surface);
275+
}
276+
277+
internal static void focus_extended_behavior (Wl.Client client, Wl.Resource resource) {
278+
unowned ExtendedBehaviorSurface? extended_behavior_surface = resource.get_user_data<ExtendedBehaviorSurface> ();
279+
if (extended_behavior_surface.wayland_surface == null) {
280+
warning ("Window tried to focus but wayland surface is null.");
281+
return;
282+
}
283+
284+
focus (extended_behavior_surface.wayland_surface);
285+
}
286+
287+
internal static void focus (Object wayland_surface) {
270288
Meta.Window? window;
271-
panel_surface.wayland_surface.get ("window", out window, null);
289+
wayland_surface.get ("window", out window, null);
272290
if (window == null) {
273291
warning ("Window tried to focus but wayland surface had no associated window.");
274292
return;
@@ -326,6 +344,21 @@ namespace Gala {
326344
window.make_above ();
327345
}
328346

347+
internal static void make_centered (Wl.Client client, Wl.Resource resource) {
348+
unowned ExtendedBehaviorSurface? eb_surface = resource.get_user_data<ExtendedBehaviorSurface> ();
349+
if (eb_surface.wayland_surface == null) {
350+
return;
351+
}
352+
353+
Meta.Window? window;
354+
eb_surface.wayland_surface.get ("window", out window, null);
355+
if (window == null) {
356+
return;
357+
}
358+
359+
ShellClientsManager.get_instance ().make_centered (window);
360+
}
361+
329362
internal static void destroy_panel_surface (Wl.Client client, Wl.Resource resource) {
330363
resource.destroy ();
331364
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2024 elementary, Inc. (https://elementary.io)
3+
* SPDX-License-Identifier: GPL-3.0-or-later
4+
*
5+
* Authored by: Leonhard Kargl <[email protected]>
6+
*/
7+
8+
public class Gala.CenteredWindow : Object {
9+
public WindowManager wm { get; construct; }
10+
public Meta.Window window { get; construct; }
11+
12+
public CenteredWindow (WindowManager wm, Meta.Window window) {
13+
Object (wm: wm, window: window);
14+
}
15+
16+
construct {
17+
window.size_changed.connect (position_window);
18+
window.stick ();
19+
20+
var monitor_manager = wm.get_display ().get_context ().get_backend ().get_monitor_manager ();
21+
monitor_manager.monitors_changed.connect (() => position_window ());
22+
23+
position_window ();
24+
25+
window.shown.connect (() => window.focus (wm.get_display ().get_current_time ()));
26+
}
27+
28+
private void position_window () {
29+
var display = wm.get_display ();
30+
var monitor_geom = display.get_monitor_geometry (display.get_primary_monitor ());
31+
var window_rect = window.get_frame_rect ();
32+
33+
var x = monitor_geom.x + (monitor_geom.width - window_rect.width) / 2;
34+
var y = monitor_geom.y + (monitor_geom.height - window_rect.height) / 2;
35+
36+
Idle.add (() => {
37+
window.move_frame (false, x, y);
38+
return Source.REMOVE;
39+
});
40+
}
41+
}

src/ShellClients/ShellClientsManager.vala

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public class Gala.ShellClientsManager : Object {
2626
private ManagedClient[] protocol_clients = {};
2727

2828
private GLib.HashTable<Meta.Window, PanelWindow> windows = new GLib.HashTable<Meta.Window, PanelWindow> (null, null);
29+
private GLib.HashTable<Meta.Window, CenteredWindow> centered_windows = new GLib.HashTable<Meta.Window, CenteredWindow> (null, null);
2930

3031
private ShellClientsManager (WindowManager wm) {
3132
Object (wm: wm);
@@ -97,20 +98,22 @@ public class Gala.ShellClientsManager : Object {
9798
}
9899
}
99100

100-
public void set_anchor (Meta.Window window, Meta.Side side) {
101-
if (window in windows) {
102-
windows[window].update_anchor (side);
103-
return;
104-
}
105-
106-
#if HAS_MUTTER46
101+
private void make_dock (Meta.Window window) {
107102
foreach (var client in protocol_clients) {
108103
if (client.wayland_client.owns_window (window)) {
109104
client.wayland_client.make_dock (window);
110105
break;
111106
}
112107
}
113-
#endif
108+
}
109+
110+
public void set_anchor (Meta.Window window, Meta.Side side) {
111+
if (window in windows) {
112+
windows[window].update_anchor (side);
113+
return;
114+
}
115+
116+
make_dock (window);
114117
// TODO: Return if requested by window that's not a trusted client?
115118

116119
windows[window] = new PanelWindow (wm, window, side);
@@ -143,4 +146,14 @@ public class Gala.ShellClientsManager : Object {
143146

144147
windows[window].set_hide_mode (hide_mode);
145148
}
149+
150+
public void make_centered (Meta.Window window) {
151+
if (window in centered_windows) {
152+
return;
153+
}
154+
155+
make_dock (window);
156+
157+
centered_windows[window] = new CenteredWindow (wm, window);
158+
}
146159
}

src/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ gala_bin_sources = files(
4040
'HotCorners/Barrier.vala',
4141
'HotCorners/HotCorner.vala',
4242
'HotCorners/HotCornerManager.vala',
43+
'ShellClients/CenteredWindow.vala',
4344
'ShellClients/HideTracker.vala',
4445
'ShellClients/ManagedClient.vala',
4546
'ShellClients/NotificationsClient.vala',

0 commit comments

Comments
 (0)