diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 1 | ||||
| -rw-r--r-- | src/niri.rs | 89 | ||||
| -rw-r--r-- | src/tests/server.rs | 1 |
3 files changed, 91 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs index d036c2a8..bdc6df46 100644 --- a/src/main.rs +++ b/src/main.rs @@ -216,6 +216,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { display, false, true, + cli.session, ) .unwrap(); diff --git a/src/niri.rs b/src/niri.rs index 9bc83302..80e97baf 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -193,6 +193,9 @@ pub struct Niri { pub stop_signal: LoopSignal, pub display_handle: DisplayHandle, + /// Whether niri was run with `--session` + pub is_session_instance: bool, + /// Name of the Wayland socket. /// /// This is `None` when creating `Niri` without a Wayland socket. @@ -360,6 +363,9 @@ pub struct Niri { pub lock_state: LockState, + // State that we last sent to the logind LockedHint. + pub locked_hint: Option<bool>, + pub screenshot_ui: ScreenshotUi, pub config_error_notification: ConfigErrorNotification, pub hotkey_overlay: HotkeyOverlay, @@ -629,6 +635,7 @@ impl State { display: Display<State>, headless: bool, create_wayland_socket: bool, + is_session_instance: bool, ) -> Result<Self, Box<dyn std::error::Error>> { let _span = tracy_client::span!("State::new"); @@ -657,6 +664,7 @@ impl State { display, &backend, create_wayland_socket, + is_session_instance, ); backend.init(&mut niri); @@ -690,6 +698,9 @@ impl State { self.niri.display_handle.flush_clients().unwrap(); } + #[cfg(feature = "dbus")] + self.niri.update_locked_hint(); + // Clear the time so it's fetched afresh next iteration. self.niri.clock.clear(); self.niri.pointer_inactivity_timer_got_reset = false; @@ -2225,6 +2236,7 @@ impl Niri { display: Display<State>, backend: &Backend, create_wayland_socket: bool, + is_session_instance: bool, ) -> Self { let _span = tracy_client::span!("Niri::new"); @@ -2495,6 +2507,7 @@ impl Niri { stop_signal, socket_name, display_handle, + is_session_instance, start_time: Instant::now(), is_at_startup: true, clock: animation_clock, @@ -2594,6 +2607,7 @@ impl Niri { mods_with_finger_scroll_binds, lock_state: LockState::Unlocked, + locked_hint: None, screenshot_ui, config_error_notification, @@ -5741,6 +5755,81 @@ impl Niri { self.queue_redraw_all(); } + #[cfg(feature = "dbus")] + fn update_locked_hint(&mut self) { + use std::sync::LazyLock; + + if !self.is_session_instance { + return; + } + + static XDG_SESSION_ID: LazyLock<Option<String>> = LazyLock::new(|| { + let id = std::env::var("XDG_SESSION_ID").ok(); + if id.is_none() { + warn!( + "env var 'XDG_SESSION_ID' is unset or invalid; logind LockedHint won't be set" + ); + } + id + }); + + let Some(session_id) = &*XDG_SESSION_ID else { + return; + }; + + fn call(session_id: &str, locked: bool) -> anyhow::Result<()> { + let conn = zbus::blocking::Connection::system() + .context("error connecting to the system bus")?; + + let message = conn + .call_method( + Some("org.freedesktop.login1"), + "/org/freedesktop/login1", + Some("org.freedesktop.login1.Manager"), + "GetSession", + &(session_id), + ) + .context("failed to call GetSession")?; + + let message_body = message.body(); + let session_path: zbus::zvariant::ObjectPath = message_body + .deserialize() + .context("failed to deserialize GetSession reply")?; + + conn.call_method( + Some("org.freedesktop.login1"), + session_path, + Some("org.freedesktop.login1.Session"), + "SetLockedHint", + &(locked), + ) + .context("failed to call SetLockedHint")?; + + Ok(()) + } + + let locked = self.is_locked(); + if self.locked_hint.is_some_and(|h| h == locked) { + return; + } + + self.locked_hint = Some(locked); + + let res = thread::Builder::new() + .name("Logind LockedHint Updater".to_owned()) + .spawn(move || { + let _span = tracy_client::span!("LockedHint"); + + if let Err(err) = call(session_id, locked) { + warn!("failed to set logind LockedHint: {err:?}"); + } + }); + + if let Err(err) = res { + warn!("error spawning a thread to set logind LockedHint: {err:?}"); + } + } + pub fn new_lock_surface(&mut self, surface: LockSurface, output: &Output) { let lock = match &self.lock_state { LockState::Unlocked => { diff --git a/src/tests/server.rs b/src/tests/server.rs index ea1f913b..40f6c1c7 100644 --- a/src/tests/server.rs +++ b/src/tests/server.rs @@ -23,6 +23,7 @@ impl Server { display, true, false, + false, ) .unwrap(); |
