- Gate greeter external-auth status fprint availability only on confirmed setups
- Reload dankshell-U2F/U2F-Key watchers live
Related: #2874
Port 1.5
(cherry picked from commit 3938e60ce4)
- Introduce external management of greetd PAM
- New functionality to validate and apply custom PAM service paths in lockscreen
Port 1.5
(cherry picked from commit b169fe0d77)
this makes use of the existing getFilteredScreens function to allow
users to specify which displays the lockscreen should appear on. prior
to this change, it was "all" or just one.
* feat: parallax-scroll wallpaper
Add a `Scrolling` wallpaper fill mode that translates the wallpaper crop
with the active workspace — like Android home-screen parallax, but along
niri's vertical workspace axis.
The image is scaled to cover the screen on its non-scroll axis, and the
active workspace index drives a fractional offset into the cropped
overflow along the scroll axis. Scroll position is spring-animated
CPU-side and handed to a minimal single-texture shader as a UV offset.
Per-monitor scroll position is published into SessionData so the lock
screen renders the same crop as the active workspace, keeping visual
continuity across lock/unlock.
Two implementation details worth calling out for review:
- QSG_USE_SIMPLE_ANIMATION_DRIVER=1 is exported to the spawned quickshell
process. The default animation driver advances in fixed ~16ms steps,
capping the scroll at 60Hz and desyncing it from compositor motion on
high-refresh displays; the simple driver advances by real elapsed time,
restoring native-refresh pacing. Removing it visibly regresses to 60Hz.
- The wallpaper survives wl_output rebind cycles (e.g. OLED image-cleaning
on DPMS soft-off), which otherwise leave a stuck or void background.
Recovery re-anchors the scroll target on output-lifecycle signals,
rebuilds the ShaderEffect against the current render context, and
re-attaches the wallpaper-layer surface on unlock for parallax-active
monitors — guarded against lock state so the shader gets reliable frame
hints.
* simplify bindings and gate lock screen shader in a loader
---------
Co-authored-by: bbedward <bbedward@gmail.com>
* feat(wallpaper): support configurable background color
* chore(translations): update settings search index
* revert(wallpaper): keep Pad naming instead of Center
When pam_faillock locks the account (DMS authenticates through the system PAM
stack: /etc/pam.d/login -> system-auth), the lock screen kept showing the
generic "Incorrect password - try again" even though the real cause is a
lockout, so a correct password looks rejected and only a reboot (which clears
the tmpfs /run/faillock tally) appears to help. See #2647.
The previous onMessageChanged only matched the *English* faillock strings
("The account is locked ...") and then wiped that text again on the trailing
pam_unix "Password:" prompt. On a non-English system (e.g. German) the strings
never matched, so the lockout was never surfaced at all.
Detect the notice by position rather than by text: pam emits its informational
messages within an attempt before the password prompt. Collect every non-prompt
info message and, once the prompt arrives, surface the collected lines (minus
the prompt itself) as lockMessage. If the stack short-circuits without ever
prompting (e.g. pam_faillock preauth configured as requisite), the notice is
surfaced on completion instead. This is locale-independent. A per-attempt flag
keeps the message stable across repeated locked attempts and retires it when an
attempt completes without a lockout (faillock reset / unlock_time elapsed).
Fixes#2647
When a custom lock command is configured, Lock.lock() runs the command and
returns early without engaging WlSessionLock, so IdleService.isShellLocked
never transitions true->false. That transition is the only trigger that
dismisses a completed FadeToLockWindow, so the fully-faded black overlay stays
on screen and the desktop is unusable after re-login (regression from b8f4c35,
which added the _completed guard and tied dismissal solely to isShellLocked).
Add a dedicated dismissFadeToLock signal that the custom-lock branch emits
after launching the external locker, mirroring the existing fade signal wiring,
so the overlay is handed off and torn down. The built-in WlSessionLock path is
unchanged and still dismisses on unlock.
Fixes#2595
* fix: ignore keyboard shortcuts of disabled powermenu actions
* fix typo when checking for lock shortcut
* ignore shortcuts for hidden powermenu actions in grid navigation
* ignore keyboard shortcuts of disabled actions in lock power menu
* ignore keyboard shortcuts of disabled actions in lock power menu (list navigation)
- Core user is logged in tty1 while user two is in tty3, you can now seamlessly switch bewteen them
New IPC options:
- `dms ipc call sessions list`
- `dms switch-user [target]`
- New Powermenu switch users option
Pulses the WiFi and Bluetooth status icons while a connection is in
progress (lock screen, DankBar control center button, control center
compound pill). The pulse is implemented as a reusable Widgets/DankBlink
component, and the wifi-connecting condition is centralized as
NetworkService.isWifiConnecting.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Introduces Standalone & Connected Modes
- Updated Animations & Motion effects for both modes
- Numerous QOL tweaks and updates throughout the system
- Highly inspired to the OG Caelestia Shell / @Soramanew
* feat: rewind to track start on previous when past 8 seconds
Adds MprisController.previousOrRewind() which rewinds the current track
to position 0 if more than 8 seconds in (with canSeek check), and falls
back to previous() otherwise — matching traditional media player behaviour.
All previous() call sites across Media.qml, MediaPlayerTab.qml,
MediaOverviewCard.qml, LockScreenContent.qml and DMSShellIPC.qml
are updated to use the new shared function.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: poll position in MprisController for previousOrRewind accuracy
Without a polling timer, activePlayer.position is never updated in
contexts that don't display a seekbar (e.g. the DankBar widget), causing
the position > 8 check in previousOrRewind() to always see 0 and fall
through to previous() instead of rewinding.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add a neutral `dms auth sync` command and reuse the shared auth flow from:
- Settings auth toggle auto-apply
- `dms greeter sync`
- `dms greeter install`
- greeter auth cleanup paths
- Rework lockscreen PAM so DMS builds /etc/pam.d/dankshell from the system login stack, but removes fingerprint and U2F from that password path. Keep /etc/pam.d/dankshell-u2f separate.
- Preserve custom PAM files in place to avoid adding duplicate greeter auth when the distro already provides it, and keep NixOS on the non-writing path.
- Re-add loginConfigWatcher so installs can still fall through to
/etc/pam.d instead of the bundled PAM assets
- Add login-faillock bundled PAM asset at runtime. Use it as the bundled fallback when dankshell config is absent
- Fix invalid bare property writes (u2fPending, u2fState, unlockInProgress,
state) in Pam.qml
- Improve lockscreen auth feedback
* fix: restore lock screen U2F/fingerprint auth to working state
* fix(pam): Keep SettingsData as single source of truth for auth availability
- Restores SettingsData for fingerprint/U2F, keeping lock screen and New Greeter Settings UI in sync
---------
Co-authored-by: purian23 <purian23@gmail.com>
After unlocking the screen (startup lock or wake from sleep), the desktop
showed Hyprland's background color instead of the wallpaper.
WallpaperBackground disables QML updates via updatesEnabled after a 1-second
settle timer. While WlSessionLock is active, Hyprland does not composite the
background layer, so when the lock is released it needs a fresh Wayland buffer
— but none is committed because the render loop is already paused.
The previous attempt used SessionService.sessionUnlocked, which is unreliable
for the startup lock case: DMSService is not yet connected when lock() is
called at startup, so notifyLoginctl is a no-op and the loginctl state never
transitions, meaning sessionUnlocked never fires.
Fix by tracking the shell lock state directly from Lock.qml's shouldLock via
a new IdleService.isShellLocked property. WallpaperBackground watches this and
re-enables rendering for 1 second on unlock, ensuring a fresh buffer is
committed to Wayland before the compositor resumes displaying the layer.
- Split auth capability state by lock screen and greeter
- Share detection between settings UI and lock runtime
- Broaden greeter PAM include detection across supported distros
* feat: add setting to change and hotreload locale
* fix: typo in component id
* feat: add persistent locale setting
* feat: wrap useLocale in a settings set hook, enable locale hotreload when editing settings file
* chore: update translation and settings file
* feat: enable fuzzy search in locale setting
* fix: regenerate translations with official plugins cloned
* fix: revert back to system's locale for displaying certain time formats
* feat: Add FIDO2/U2F security key support for lock screen
Adds hardware security key authentication (e.g. YubiKey) with two modes:
Alternative (OR) and Second Factor (AND). Includes settings UI, PAM
integration, availability detection, and proper state cleanup.
Also fixes persist:false properties being reset on settings file reload.
* feat: Add U2F pending timeout and Escape to cancel
Cancel U2F second factor after 30s or on Escape key press,
returning to password/fingerprint input.
* fix: U2F detection honors custom PAM override for non-default key paths