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

ShellClients: Allow X11 clients to use pantheon protocol via mutter hints #2002

Merged
merged 8 commits into from
Aug 8, 2024
95 changes: 94 additions & 1 deletion src/ShellClients/ShellClientsManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ public class Gala.ShellClientsManager : Object {
notifications_client = new NotificationsClient (wm.get_display ());

start_clients.begin ();

if (!Meta.Util.is_wayland_compositor ()) {
wm.get_display ().window_created.connect ((window) => {
window.notify["mutter-hints"].connect ((obj, pspec) => parse_mutter_hints ((Meta.Window) obj));
parse_mutter_hints (window);
});
}
}

private async void start_clients () {
Expand Down Expand Up @@ -98,7 +105,15 @@ public class Gala.ShellClientsManager : Object {
}
}

private void make_dock (Meta.Window window) {
public void make_dock (Meta.Window window) {
if (Meta.Util.is_wayland_compositor ()) {
make_dock_wayland (window);
} else {
make_dock_x11 (window);
}
}

private void make_dock_wayland (Meta.Window window) requires (Meta.Util.is_wayland_compositor ()) {
foreach (var client in protocol_clients) {
if (client.wayland_client.owns_window (window)) {
client.wayland_client.make_dock (window);
Expand All @@ -107,6 +122,25 @@ public class Gala.ShellClientsManager : Object {
}
}

private void make_dock_x11 (Meta.Window window) requires (!Meta.Util.is_wayland_compositor ()) {
unowned var x11_display = wm.get_display ().get_x11_display ();

#if HAS_MUTTER46
var x_window = x11_display.lookup_xwindow (window);
#else
var x_window = window.get_xwindow ();
#endif
// gtk3's gdk_x11_window_set_type_hint() is used as a reference
unowned var xdisplay = x11_display.get_xdisplay ();
var atom = xdisplay.intern_atom ("_NET_WM_WINDOW_TYPE", false);
var dock_atom = xdisplay.intern_atom ("_NET_WM_WINDOW_TYPE_DOCK", false);

// (X.Atom) 4 is XA_ATOM
// 32 is format
// 0 means replace
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) {
if (window in windows) {
windows[window].update_anchor (side);
Expand Down Expand Up @@ -156,4 +190,63 @@ public class Gala.ShellClientsManager : Object {

centered_windows[window] = new CenteredWindow (wm, window);
}

//X11 only
private void parse_mutter_hints (Meta.Window window) requires (!Meta.Util.is_wayland_compositor ()) {
if (window.mutter_hints == null) {
return;
}

var mutter_hints = window.mutter_hints.split (":");
foreach (var mutter_hint in mutter_hints) {
var split = mutter_hint.split ("=");

if (split.length != 2) {
continue;
}

var key = split[0];
var val = split[1];

switch (key) {
case "anchor":
int parsed;
if (int.try_parse (val, out parsed) && 0 <= parsed && parsed <= 15) {
set_anchor (window, parsed);
} else {
warning ("Failed to parse %s as anchor", val);
}
break;
lenemter marked this conversation as resolved.
Show resolved Hide resolved

case "hide-mode":
int parsed;
if (int.try_parse (val, out parsed) && 0 <= parsed && parsed <= 4) {
set_hide_mode (window, parsed);
} else {
warning ("Failed to parse %s as hide mode", val);
}
break;
lenemter marked this conversation as resolved.
Show resolved Hide resolved

case "size":
var split_val = val.split (",");
if (split_val.length != 2) {
break;
}
int parsed_width, parsed_height = 0; //set to 0 because vala doesn't realize height will be set too
if (int.try_parse (split_val[0], out parsed_width) && int.try_parse (split_val[1], out parsed_height)) {
set_size (window, parsed_width, parsed_height);
} else {
warning ("Failed to parse %s as width and height", val);
}
break;

case "centered":
make_centered (window);
break;

default:
break;
}
}
}
}
Loading