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

PanelWindow/X11: Use pantheon protocol for positioning, struts, etc. #551

Merged
merged 4 commits into from
Aug 11, 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
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ gdk_wl_dep = dependency('gdk-wayland-3.0')
# GDK X11 dep is for detecting whether we're on Wayland or not ONLY, we don't actually have
# a hard X11 dependency here
gdk_x11_dep = dependency('gdk-x11-3.0')
x11_dep = dependency('x11')
gtk_dep = dependency('gtk+-3.0', version: '>=3.10')
gee_dep = dependency('gee-0.8')
granite_dep = dependency('granite', version: '>=5.4.0')
Expand Down
100 changes: 21 additions & 79 deletions src/PanelWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ public class Wingpanel.PanelWindow : Gtk.Window {
private int monitor_number;
private int monitor_width;
private int monitor_height;
private int monitor_x;
private int monitor_y;
private int panel_height;
private bool expanded = false;

Expand All @@ -43,7 +41,6 @@ public class Wingpanel.PanelWindow : Gtk.Window {
resizable: false,
skip_pager_hint: true,
skip_taskbar_hint: true,
type_hint: Gdk.WindowTypeHint.DOCK,
vexpand: false
);

Expand Down Expand Up @@ -100,19 +97,15 @@ public class Wingpanel.PanelWindow : Gtk.Window {
}

private void on_realize () {
// realize isn't called when reveal_child is false, so we set true, then
// false, then true again to animate. On wayland we are animated in by gala
// so we just want the revealer to always reveal.
if (!Utils.is_wayland ()) {
revealer.reveal_child = false;
}
update_panel_dimensions ();
Services.BackgroundManager.initialize (this.monitor_number, panel_height);
revealer.transition_type = SLIDE_DOWN;
revealer.reveal_child = true;

// We have to wrap in Idle otherwise the Meta.Window of the WaylandSurface in Gala is still null
Idle.add_once (init_wl);
if (Utils.is_wayland ()) {
// We have to wrap in Idle otherwise the Meta.Window of the WaylandSurface in Gala is still null
Idle.add_once (init_wl);
} else {
init_x ();
}
}

private void update_panel_dimensions () {
Expand All @@ -135,13 +128,6 @@ public class Wingpanel.PanelWindow : Gtk.Window {
monitor_height = monitor_dimensions.height;

this.set_size_request (monitor_width, (popover_manager.current_indicator != null ? monitor_height : -1));

monitor_x = monitor_dimensions.x;
monitor_y = monitor_dimensions.y;

move (monitor_x, monitor_y);

update_struts ();
}

private void update_visual () {
Expand All @@ -162,65 +148,6 @@ public class Wingpanel.PanelWindow : Gtk.Window {
return Gdk.EVENT_PROPAGATE;
}

private void update_struts () {
if (!this.get_realized () || panel == null) {
return;
}

/**
* https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html#NETWMSTRUT
* The _NET_WM_STRUCT_PARTICAL specification does not allow to reserve space for arbitrary rectangles
* on the screen. Instead it only allows to reserve space at the borders of screen.
* As for multi-monitor layouts the wingpanel can be at the within the screen (and not at the border)
* this makes it impossible to reserve the correct space for all possible multi-monitor layouts.
* Fortunately for up to 3 monitors there is always a possiblity to reserve the right space by also
* using the struct-left and struct-right cardinals.
*/

var display = get_display ();
var n_monitors = display.get_n_monitors ();
int screen_width = 0;
bool no_monitor_left = true;
bool no_monitor_right = true;
bool no_monitor_above = true;
for (var i = 0; i < n_monitors; i++) {
var rect = display.get_monitor (i).get_geometry ();
screen_width = int.max (screen_width, rect.x + rect.width);
if (i == monitor_number) {
continue;
}

var is_left = rect.x + rect.width <= monitor_x;
var is_right = rect.x >= monitor_x + monitor_width;
var is_above = rect.y + rect.height <= monitor_y;
var is_below = rect.y >= monitor_y + panel_height;
no_monitor_left &= !is_left || is_above || is_below;
no_monitor_right &= !is_right || is_above || is_below;
no_monitor_above &= !is_above || is_left || is_right;
}

long struts[12] = { 0 };
var scale_factor = this.get_scale_factor ();
if (no_monitor_left) {
struts [0] = (monitor_x + monitor_width) * scale_factor;
struts [4] = monitor_y * scale_factor;
struts [5] = (monitor_y + panel_height) * scale_factor - 1;
} else if (no_monitor_right) {
struts [1] = (screen_width - monitor_x) * scale_factor;
struts [6] = monitor_y * scale_factor;
struts [7] = (monitor_y + panel_height) * scale_factor - 1;
} else if (no_monitor_above) {
struts [2] = (monitor_y + panel_height) * scale_factor;
struts [8] = monitor_x * scale_factor;
struts [9] = (monitor_x + monitor_width) * scale_factor - 1;
} else {
warning ("Unable to set struts, because Wingpanel is not at the edge of the Gdk.Screen area.");
}

Gdk.property_change (this.get_window (), Gdk.Atom.intern ("_NET_WM_STRUT_PARTIAL", false),
Gdk.Atom.intern ("CARDINAL", false), 32, Gdk.PropMode.REPLACE, (uint8[])struts, 12);
}

public void set_expanded (bool expand) {
if (expand && !this.expanded) {
Services.BackgroundManager.get_default ().remember_window ();
Expand All @@ -244,6 +171,21 @@ public class Wingpanel.PanelWindow : Gtk.Window {
}
}

private void init_x () {
var display = Gdk.Display.get_default ();
if (display is Gdk.X11.Display) {
unowned var xdisplay = ((Gdk.X11.Display) display).get_xdisplay ();

var window = ((Gdk.X11.Window) get_window ()).get_xid ();

var prop = xdisplay.intern_atom ("_MUTTER_HINTS", false);

var value = "anchor=4:hide-mode=0:size=-1,%d".printf (get_allocated_height () * get_scale_factor ());

xdisplay.change_property (window, prop, X.XA_STRING, 8, 0, (uchar[]) value, value.length);
}
}

public void registry_handle_global (Wl.Registry wl_registry, uint32 name, string @interface, uint32 version) {
if (@interface == "io_elementary_pantheon_shell_v1") {
desktop_shell = wl_registry.bind<Pantheon.Desktop.Shell> (name, ref Pantheon.Desktop.Shell.iface, uint32.min (version, 1));
Expand Down
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ wingpanel_deps = [
granite_dep,
gdk_wl_dep,
gdk_x11_dep,
x11_dep,
posix_dep,
wl_client_dep,
pantheon_desktop_shell_dep
Expand Down
Loading