* feat(dock): push neighboring icons apart on magnification
* fix(dock): cap magnification expansion and disable it in taskbar mode
* fix(dock): scale pushed icon offsets to the capped magnification expansion
* fix(dock): avoid binding loop when reading expansion ratio
- caps lock, power profile, idle inhibitor and charging pulse in the island
- microphone mute and volume as a level transient
- privacy slot while mic, camera or screen share is in use
- duo battery style: arc around the network glyph with signal dots
* fix(notifications): edit rules from the menu instead of deleting them
A notification rule can set an action and Bypass DND together, but
Unmute and Block in Do Not Disturb spliced the whole rule, dropping the
other setting. They now reset only their own field, and a rule is
removed once it no longer does anything (action and urgency default,
no bypass). Mute and Allow in Do Not Disturb set their field on the
app's existing rule instead of appending one that first-match policy
would shadow.
The menu now only reads and edits enabled, exact rules on the app name
or desktop entry. It used to match any rule whose pattern equaled the
app name, including summary, body, contains and regex rules, and could
delete disabled ones.
Also adds a Copy item to the notification menu on popups and center
cards, copying the summary and body as plain text.
* fix(notifications): let mute apply alongside other rule actions
Rule actions are first-match, so a mute rule behind an app's existing
rule (e.g. No history) never applied while the menu showed Unmute.
Mute is now evaluated like Bypass DND: any matching enabled mute rule
disables the popup, and the other actions stay first-match, so No
history and Mute both apply.
* fix(notifications): skip the sound for dropped and muted notifications
The notification sound played before the check that dismisses a
notification with neither a popup nor a center entry, so dropped
notifications (transient while muted, Popup only plus Mute) still made
a sound. Play it only for notifications that are kept, and not when a
mute rule applies, like Do Not Disturb.
* feat(dock): add proximity icon magnification with customizable curves
* fix(dock): restrict proximity magnification to dock and add translator context
* feat(screenshot): snap to active popouts and modals in region mode
Allow region screenshot selector to detect and snap to visible shell
popouts and modals on hover and click or keyboard confirmation.
- PopoutManager.qml: add getActiveSurfaces() collecting visible
DankPopout and DankModal global bounding boxes
- DMSShellIPC.qml: add screenshot.getSurfaces IPC endpoint
- core: fetch snap targets from shell IPC during region screenshot init
- selector: highlight snap targets on hover with surface name and dimensions
- selector: click or Enter/Space on hovered target locks selection to surface bounds
- selector: allow hover snap over pre-selection (SelectionState.fromPreSelect)
- selector: reset selection on degenerate (1x1) click release for quick re-selection
- unit tests for display name formatting, hover detection, and render bounds
* fix(screenshot): correct snap off-by-one and drag-away cancellation
- region_input: fix drag-away snap cancellation by setting hasSelection=true
and clearing preSelect so freeform dragging renders and is not discarded
- region_input: add snapToTarget helper subtracting 1 device pixel (devPxX/Y)
from currentX/currentY to prevent inclusive coordinate off-by-one (420x580 -> 420x580)
- region_render: compute hover bounds with w = round(width * scaleX) and
x2 = x1 + w - 1 to eliminate +1 device pixel in render bounds
- region_snap_test: assert exact 420x580 bounds for both hover and snapped states
* style(screenshot): format region_snap_test.go with golangci-lint-fmt
A compositor resolves a bind's keysym on the first level of the active
layout. Layouts that put punctuation higher up therefore cannot reach it
at all: de:neo has bracketleft on layer 4 and plain de on AltGr, so
Mod+bracketleft is a bind that can never fire. The editor recorded and
stored it anyway and gave no sign that anything was wrong (#3585).
`dms keybinds keymap` now reports what the seat's xkb keymap puts on the
first level of every physical key, and the editor says so instead of
letting a dead bind through.
The keymap a compositor hands out writes its keysyms as hex, so only the
range the keymap package can name back is usable for the comparison.
That is the ASCII range, which is where the problem lives, and the
command reports the vocabulary alongside the keys so the caller can tell
"the layout cannot reach this" from "we could not name it" and stay
quiet in the second case.
* lock: lock before sleep when the command skips logind
Custom hibernate never emits PrepareForSleep, so the session stayed unlocked. Wait for the compositor lock on every sleep path, and release the delay inhibitor if that lock finished first.
* lock: release the sleep inhibitor only after lockerReady
* lock: read the sleep inhibitor under its mutex in the race test
scrollbar: interface style toggle and no scrollbars in the dash
dash: never allow scrollbars
cc: widget sheet cards, header close button and content-sized dialogs
settings: stop repeating the page title as the first card label
translations: index untitled cards by their page, not a nested row
fixes#3604fixes#3609
* powermenu: derive shortcuts and extra actions from one source
The power menu matched keys with a switch that repeated the key hints
getPowerActionData already returns, plus a second key list for release.
Look the pressed key up against the hints of the visible actions instead,
so every action with a hint gets its shortcut and the two cannot drift.
Side effects:
- Ctrl+letter no longer triggers actions. Only Ctrl+P was excluded
before, so Ctrl+R still rebooted. Ctrl combinations are navigation.
- U now triggers switch user when it is shown. Its hint already said U.
- Releasing a letter with no visible action no longer cancels a hold.
SessionService now owns the custom:N action ids as customPowerActions
and extraPowerActions, which the power menu and the launcher both use.
Actions resolve by index into that list instead of slicing the prefix.
* powermenu: add actions that reboot into a chosen efi boot entry
Settings → Power & Sleep gets a "Reboot to another OS" card that lists
the firmware's active EFI entries through efibootmgr. Each saved entry
becomes a "Reboot to <name>" action in the power menu and the launcher,
bound to 1-9 in the order it was added.
Picking one lists the entries again, and stops with a toast if the id no
longer carries the saved label. Otherwise it sets BootNext through pkexec
and reboots through SessionService, so custom reboot commands still apply.
BootEntryService reports why entries are unavailable: not booted in UEFI
mode, efibootmgr missing, or efibootmgr failing with its stderr. Saved
entries stay listed in settings whatever the status, so a synced config
on another machine can still remove them.
efibootmgr parsing and the picker's filtering live in BootEntries.js,
covered by tests/boot-entries.test.mjs.
* powermenu: ignore special keys in action shortcuts