Skip to content

Commit

Permalink
Rework our libxfce4windowing use to be thread-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
fossfreedom committed Feb 17, 2025
1 parent b2194af commit e53d335
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 14 deletions.
8 changes: 8 additions & 0 deletions src/daemon/endsession.vala
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ namespace Budgie {
this.cancel_clicked();
return Gdk.EVENT_STOP;
});

GtkLayerShell.init_for_window(this);
GtkLayerShell.set_layer(this, GtkLayerShell.Layer.TOP);
GtkLayerShell.set_anchor(this, GtkLayerShell.Edge.LEFT, false);
GtkLayerShell.set_anchor(this, GtkLayerShell.Edge.TOP, false);
GtkLayerShell.set_keyboard_mode(this, GtkLayerShell.KeyboardMode.ON_DEMAND);
}

public void Open(uint type, uint timestamp, uint open_length, ObjectPath[] inhibiters) throws DBusError, IOError {
Expand Down Expand Up @@ -175,6 +181,8 @@ namespace Budgie {
/* Update the label */
this.label_end_title.set_text(title);

GtkLayerShell.set_monitor(this, new WaylandClient().gdk_monitor);

if (main_show != null) {
/* We have a specific type.. */
for (int i = 0; i < all_widgets.length; i++) {
Expand Down
54 changes: 47 additions & 7 deletions src/daemon/manager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,49 @@
*/

namespace Budgie {

/*
The underlying WaylandClient does not appear to be fully thread-safe and either
repeated calls very quickly, or calls within the same process where the
reference was not release will result in mutex-locks causing the daemon to spin
indefinitely.
Our use in the daemon is limited so we can initialise variable we use within
a singleton to make things thread-safe.
*/
[SingleInstance]
public class WaylandClient : GLib.Object {
private unowned libxfce4windowing.Monitor? primary_monitor=null;

public bool is_initialised() { return primary_monitor != null; }
public unowned Gdk.Monitor gdk_monitor {get; private set; }
public Gdk.Rectangle monitor_res { get; private set; }

public WaylandClient() {
if (primary_monitor != null) return;
libxfce4windowing.Screen.get_default().monitors_changed.connect(on_monitors_changed);
on_monitors_changed();
}

void on_monitors_changed() {
int loop = 0;

/* it can take a short-time after first call for the underlying wayland client
to return a reference, so lets loop until we get a reference ... but
don't try indefinitely
*/
Timeout.add(200, ()=> {
primary_monitor = libxfce4windowing.Screen.get_default().get_primary_monitor();
if (primary_monitor != null || loop++ > 10) {
monitor_res = primary_monitor.get_logical_geometry();
gdk_monitor = primary_monitor.get_gdk_monitor();
return false;
}

return true;
});
}
}
/**
* Main lifecycle management, handle all the various session and GTK+ bits
*/
Expand All @@ -18,8 +61,10 @@ namespace Budgie {
/* Keep track of our SessionManager */
private LibSession.SessionClient? sclient;

// define a reference to WaylandClient once for this process
private WaylandClient wayland_client = new WaylandClient();

/* On Screen Display */
public static unowned libxfce4windowing.Monitor? primary_monitor { get; private set; }
Budgie.OSDManager? osd;
Budgie.OSDKeys? osdkeys;
Budgie.Notifications.Server? notifications;
Expand All @@ -38,9 +83,6 @@ namespace Budgie {
* Construct a new ServiceManager and initialiase appropriately
*/
public ServiceManager(bool replace) {
libxfce4windowing.Screen.get_default().monitors_changed.connect(on_monitors_changed);
on_monitors_changed();

theme_manager = new Budgie.ThemeManager();
status_notifier = new Budgie.StatusNotifier.FreedesktopWatcher();
register_with_session.begin((o, res) => {
Expand All @@ -56,6 +98,7 @@ namespace Budgie {

notifications = new Budgie.Notifications.Server();
notifications.setup_dbus(replace);

background = new Budgie.Background();

try {
Expand All @@ -74,9 +117,6 @@ namespace Budgie {
nightlight = new NightLightManager();
}

void on_monitors_changed() {
primary_monitor = libxfce4windowing.Screen.get_default().get_primary_monitor();
}
/**
* Attempt registration with the Session Manager
*/
Expand Down
8 changes: 4 additions & 4 deletions src/daemon/notifications/dbus.vala
Original file line number Diff line number Diff line change
Expand Up @@ -359,9 +359,9 @@
* Configures the location of a notification popup and makes it visible on the screen.
*/
private void configure_window(Popup? popup) {
var primary_monitor = ServiceManager.primary_monitor;
if (primary_monitor == null) return;
Gdk.Rectangle mon_rect = primary_monitor.get_workarea();
if (!new WaylandClient().is_initialised()) return;

Gdk.Rectangle mon_rect = new WaylandClient().monitor_res;

GtkLayerShell.init_for_window(popup);
GtkLayerShell.set_layer(popup, GtkLayerShell.Layer.TOP);
Expand All @@ -376,7 +376,7 @@

/* determine the y position for the latest notification */
calculate_position(mon_rect.y);
GtkLayerShell.set_monitor(popup, primary_monitor.get_gdk_monitor());
GtkLayerShell.set_monitor(popup, new WaylandClient().gdk_monitor);
var pos = (NotificationPosition) this.panel_settings.get_enum("notification-position");
int edge_a, edge_b;

Expand Down
6 changes: 3 additions & 3 deletions src/daemon/osd.vala
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,12 @@ namespace Budgie {
resizable = false;
skip_pager_hint = true;
skip_taskbar_hint = true;

GtkLayerShell.init_for_window(this);
GtkLayerShell.set_layer(this, GtkLayerShell.Layer.TOP);
GtkLayerShell.set_margin(this, GtkLayerShell.Edge.BOTTOM, 80);
GtkLayerShell.set_anchor(this, GtkLayerShell.Edge.BOTTOM, true);

set_decorated(false);
stick();

Expand All @@ -153,9 +155,7 @@ namespace Budgie {
* Move the OSD into the correct position
*/
public void move_osd() {
var primary_monitor = ServiceManager.primary_monitor;
if (primary_monitor == null) return;
GtkLayerShell.set_monitor(this, primary_monitor.get_gdk_monitor());
GtkLayerShell.set_monitor(this, new WaylandClient().gdk_monitor);
}
}

Expand Down

0 comments on commit e53d335

Please sign in to comment.