gardesk/garbg / 9c44705

Browse files

fix: refresh DISPLAY from systemd env on X11 reconnect

When the X session restarts, DISPLAY can change (e.g. :0 -> :1).
The daemon kept the stale value, preventing X11 reconnection.
Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
9c4470527c5fb7faafaa1cfd9ee99f4906c6e510
Parents
f89cf77
Tree
8b54751

1 changed file

StatusFile+-
M garbg/src/daemon/state.rs 41 0
garbg/src/daemon/state.rsmodified
@@ -224,7 +224,12 @@ impl Daemon {
224224
     }
225225
 
226226
     /// Attempt to establish/re-establish X11 connection
227
+    ///
228
+    /// On reconnection, refreshes `DISPLAY` from the systemd user environment
229
+    /// since the X display number may change across session restarts (e.g. `:0` -> `:1`).
227230
     fn try_connect_x11(&mut self) -> bool {
231
+        Self::refresh_display_env();
232
+
228233
         match Connection::new() {
229234
             Ok(conn) => {
230235
                 let (width, height) = conn.screen_dimensions();
@@ -239,6 +244,42 @@ impl Daemon {
239244
         }
240245
     }
241246
 
247
+    /// Refresh DISPLAY (and XAUTHORITY) from the systemd user manager environment.
248
+    ///
249
+    /// When the X session restarts, the display number can change (e.g. `:0` -> `:1`).
250
+    /// systemd's user manager gets updated via `systemctl --user import-environment`,
251
+    /// but a long-running daemon keeps the stale value in its own process environment.
252
+    fn refresh_display_env() {
253
+        let output = match std::process::Command::new("systemctl")
254
+            .args(["--user", "show-environment"])
255
+            .output()
256
+        {
257
+            Ok(o) if o.status.success() => o,
258
+            _ => return,
259
+        };
260
+
261
+        let env_str = match std::str::from_utf8(&output.stdout) {
262
+            Ok(s) => s,
263
+            Err(_) => return,
264
+        };
265
+
266
+        for line in env_str.lines() {
267
+            if let Some(val) = line.strip_prefix("DISPLAY=") {
268
+                let current = std::env::var("DISPLAY").unwrap_or_default();
269
+                if current != val {
270
+                    tracing::info!("DISPLAY changed: {} -> {}", current, val);
271
+                    std::env::set_var("DISPLAY", val);
272
+                }
273
+            } else if let Some(val) = line.strip_prefix("XAUTHORITY=") {
274
+                let current = std::env::var("XAUTHORITY").unwrap_or_default();
275
+                if current != val {
276
+                    tracing::info!("XAUTHORITY changed: {} -> {}", current, val);
277
+                    std::env::set_var("XAUTHORITY", val);
278
+                }
279
+            }
280
+        }
281
+    }
282
+
242283
     /// Check if X11 connection is alive
243284
     fn x11_is_alive(&self) -> bool {
244285
         self.conn.as_ref().map(|c| c.is_alive()).unwrap_or(false)