Skip to content

feat(power): add SleepListenerService to auto-lock on system suspend#2577

Open
l1a wants to merge 5 commits intonoctalia-dev:mainfrom
l1a:fix-suspend-locking
Open

feat(power): add SleepListenerService to auto-lock on system suspend#2577
l1a wants to merge 5 commits intonoctalia-dev:mainfrom
l1a:fix-suspend-locking

Conversation

@l1a
Copy link
Copy Markdown

@l1a l1a commented Apr 28, 2026

Motivation

This PR addresses an issue where Noctalia fails to auto-lock the session when the system enters sleep via external triggers (such as closing a laptop lid or running systemctl suspend).

Currently, Noctalia's locking logic is primarily tied to its internal idle timer. By introducing the SleepListenerService, the shell now eavesdrops on the org.freedesktop.login1.Manager.PrepareForSleep DBus signal, allowing it to trigger the lock screen immediately before the system suspends.

Type of Change

  • Bug fix
  • New feature

Related Issue

Testing

I have verified this change by running the modified shell from source and performing the following manual tests:

  • Tested on niri
  • Tested on Hyprland
  • Tested on sway

Manual Test Scenarios:

  1. Lid Close Test: Closing the laptop lid successfully triggers the lock screen before suspension.
  2. Manual Suspend Test: Running systemctl suspend successfully triggers the lock screen.
  3. Toggle Verification: Confirmed that the lockOnSuspend setting is respected (disabling it prevents the auto-lock).
  4. Resilience: Confirmed the dbus-monitor subprocess automatically restarts if terminated.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my code
  • No new warnings or errors
  • Documentation or comments updated (if relevant)

Additional Notes

The implementation follows the established project pattern of using Quickshell.Io to manage system utility subprocesses (consistent with BluetoothService.qml and ClipboardService.qml). It uses SplitParser to ensure real-time, line-buffered signal detection.

Copy link
Copy Markdown

@eventualbuddha eventualbuddha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a maintainer, so take the "Request Changes" review with a grain of salt. I'm just another user (CachyOS+niri+noctalia) who ran into the issue described in #2569 and went looking for a fix.

Comment thread Services/Power/SleepListenerService.qml Outdated

onExited: (code, status) => {
Logger.w("SleepListener", "dbus-monitor exited with code " + code + ". Restarting...");
if (root.running) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no running property on Singleton instances (from qmllint):

  Warning: Services/Power/SleepListenerService.qml:55:16: Member "running" not found on type "Singleton"
  [missing-property]
        if (root.running) {
                 ^^^^^^^

This conditional should just be removed and always call restartTimer.start();.

if (line.includes("boolean true")) {
if (Settings.data.general.lockOnSuspend) {
Logger.i("SleepListener", "System is preparing for sleep, triggering lock");
CompositorService.lock();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is happening as a result of dbus sending the PrepareForSleep signal, but nothing in this change actually prevents sleep until the compositor lock has taken effect. I think this service should have a systemd-inhibit --what=sleep ... process that can be stopped after the lock has happened (or lockOnSuspend is disabled).

Addresses PR noctalia-dev#2577 feedback:
- Fixed invalid property reference on Singleton in onExited.
- Implemented systemd-inhibit to prevent race conditions during suspend.
- Added verified logic to release inhibitor only after lock screen is active.
- Added comprehensive documentation for the sleep listener logic.
@l1a
Copy link
Copy Markdown
Author

l1a commented Apr 30, 2026

Cool! Thanks for the catch. I've made the updates and tested what I can. Does it work as expected in your environment?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Session does not auto-lock on system-initiated suspend (e.g. lid close)

2 participants