mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-24 02:01:18 +07:00
Set logind LockedHint on lock/unlock (#1763)
* Set logind LockedHint on lock/unlock * fixup! Set logind LockedHint on lock/unlock - use warn!() instead of error!() - extract dbus call into a separate method * fixup! Set logind LockedHint on lock/unlock - Update LockedHint in refresh_and_flush_clients * fixup! Set logind LockedHint on lock/unlock woops * fixup! Set logind LockedHint on lock/unlock - only call SetLockedHint if niri was run with `--session` * fixes --------- Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
This commit is contained in:
@@ -216,6 +216,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
display,
|
display,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
|
cli.session,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
+89
@@ -193,6 +193,9 @@ pub struct Niri {
|
|||||||
pub stop_signal: LoopSignal,
|
pub stop_signal: LoopSignal,
|
||||||
pub display_handle: DisplayHandle,
|
pub display_handle: DisplayHandle,
|
||||||
|
|
||||||
|
/// Whether niri was run with `--session`
|
||||||
|
pub is_session_instance: bool,
|
||||||
|
|
||||||
/// Name of the Wayland socket.
|
/// Name of the Wayland socket.
|
||||||
///
|
///
|
||||||
/// This is `None` when creating `Niri` without a Wayland socket.
|
/// This is `None` when creating `Niri` without a Wayland socket.
|
||||||
@@ -360,6 +363,9 @@ pub struct Niri {
|
|||||||
|
|
||||||
pub lock_state: LockState,
|
pub lock_state: LockState,
|
||||||
|
|
||||||
|
// State that we last sent to the logind LockedHint.
|
||||||
|
pub locked_hint: Option<bool>,
|
||||||
|
|
||||||
pub screenshot_ui: ScreenshotUi,
|
pub screenshot_ui: ScreenshotUi,
|
||||||
pub config_error_notification: ConfigErrorNotification,
|
pub config_error_notification: ConfigErrorNotification,
|
||||||
pub hotkey_overlay: HotkeyOverlay,
|
pub hotkey_overlay: HotkeyOverlay,
|
||||||
@@ -629,6 +635,7 @@ impl State {
|
|||||||
display: Display<State>,
|
display: Display<State>,
|
||||||
headless: bool,
|
headless: bool,
|
||||||
create_wayland_socket: bool,
|
create_wayland_socket: bool,
|
||||||
|
is_session_instance: bool,
|
||||||
) -> Result<Self, Box<dyn std::error::Error>> {
|
) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
let _span = tracy_client::span!("State::new");
|
let _span = tracy_client::span!("State::new");
|
||||||
|
|
||||||
@@ -657,6 +664,7 @@ impl State {
|
|||||||
display,
|
display,
|
||||||
&backend,
|
&backend,
|
||||||
create_wayland_socket,
|
create_wayland_socket,
|
||||||
|
is_session_instance,
|
||||||
);
|
);
|
||||||
backend.init(&mut niri);
|
backend.init(&mut niri);
|
||||||
|
|
||||||
@@ -690,6 +698,9 @@ impl State {
|
|||||||
self.niri.display_handle.flush_clients().unwrap();
|
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.
|
// Clear the time so it's fetched afresh next iteration.
|
||||||
self.niri.clock.clear();
|
self.niri.clock.clear();
|
||||||
self.niri.pointer_inactivity_timer_got_reset = false;
|
self.niri.pointer_inactivity_timer_got_reset = false;
|
||||||
@@ -2225,6 +2236,7 @@ impl Niri {
|
|||||||
display: Display<State>,
|
display: Display<State>,
|
||||||
backend: &Backend,
|
backend: &Backend,
|
||||||
create_wayland_socket: bool,
|
create_wayland_socket: bool,
|
||||||
|
is_session_instance: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let _span = tracy_client::span!("Niri::new");
|
let _span = tracy_client::span!("Niri::new");
|
||||||
|
|
||||||
@@ -2495,6 +2507,7 @@ impl Niri {
|
|||||||
stop_signal,
|
stop_signal,
|
||||||
socket_name,
|
socket_name,
|
||||||
display_handle,
|
display_handle,
|
||||||
|
is_session_instance,
|
||||||
start_time: Instant::now(),
|
start_time: Instant::now(),
|
||||||
is_at_startup: true,
|
is_at_startup: true,
|
||||||
clock: animation_clock,
|
clock: animation_clock,
|
||||||
@@ -2594,6 +2607,7 @@ impl Niri {
|
|||||||
mods_with_finger_scroll_binds,
|
mods_with_finger_scroll_binds,
|
||||||
|
|
||||||
lock_state: LockState::Unlocked,
|
lock_state: LockState::Unlocked,
|
||||||
|
locked_hint: None,
|
||||||
|
|
||||||
screenshot_ui,
|
screenshot_ui,
|
||||||
config_error_notification,
|
config_error_notification,
|
||||||
@@ -5741,6 +5755,81 @@ impl Niri {
|
|||||||
self.queue_redraw_all();
|
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) {
|
pub fn new_lock_surface(&mut self, surface: LockSurface, output: &Output) {
|
||||||
let lock = match &self.lock_state {
|
let lock = match &self.lock_state {
|
||||||
LockState::Unlocked => {
|
LockState::Unlocked => {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ impl Server {
|
|||||||
display,
|
display,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user