- Read and convert external compositor rules into editable DMS rules
- Preserve niri multi-match rules and add match editor
- niri background-effect (blur/xray/noise/saturation) support
The networkd backend treated any link reporting Type=ether as a wired uplink.
Podman bridges and veth pairs report Type=ether, so they were classified as
ethernet: isWired() short-circuited on Type and never consulted looksVirtual(),
which also lacked a podman prefix.
The link map was also never pruned. Links discovered at enumeration or via
signals were kept forever, so torn-down container interfaces lingered as
routable and could win the wired-uplink slot over the real NIC -- leaving the
indicator showing WiFi while a wired connection was active and default-routed.
- isWired()/isWireless() exclude virtual interfaces before consulting Type, and
looksVirtual() now recognises podman.
- enumerateLinks() reconciles the cached map against ListLinks via syncLinks(),
pruning links that no longer appear so dead interfaces don't accumulate.
- Introduce multi-account greeter login with per-user theme previews
- Add `dms greeter sync --profile` for secondary users with or without sudo
- Add Manage greeter group membership from Settings UI → Users Tab
- Update to add DMS Action keys in Keyboard Shortcuts
- Defaulted in niri/hyprland includes file as `Alt+Space`
- New (IPC): `dms ipc call spotlight-bar toggle`
- Slight UI update to follow user radius
* networkd: classify links by Type instead of name prefix
The systemd-networkd backend decided wifi-vs-ethernet by checking
whether the interface name started with "wlan" or "wlp". Anything
else (that was not on a small virtual-prefix denylist) was treated
as wired ethernet. That misclassified two common cases:
* Nebula tunnels (kernel name like "nebula.homelab", Type=none,
Kind=tun) showed up as a wired ethernet device — DMS rendered an
"Ethernet connected" indicator whenever the overlay was up, even
with no physical NIC plugged in.
* Renamed wifi interfaces (e.g. systemd link files that rename
wlan0 to a friendlier name like "wifi") were also miscategorised
as ethernet, because they no longer matched wlan*/wlp*.
networkd already publishes the real link kind in the JSON returned
by the per-link Describe method ("ether", "wlan", "loopback",
"none"). Fetch it during enumerateLinks, cache it on linkInfo, and
classify against that. The old prefix logic is kept as a fallback
for the case where Describe ever fails to populate Type.
The package-level looksVirtual() helper replaces the unexported
isVirtualInterface method so the new classification helpers and
their tests can use it without needing a live backend.
Tests cover both the Type-based and fallback paths, including the
Nebula-shaped Type=none/tun case that motivated this change.
* networkd: cache linkType across signal ticks and unit-test Describe fallback
enumerateLinks runs on every PropertiesChanged signal under
/org/freedesktop/network1, which fires on carrier flap, DHCP renew, and
each address change. The previous version rebuilt every linkInfo from
scratch on each tick, including a synchronous Describe D-Bus round-trip
per link, despite the link Type being fixed at netlink creation. Preserve
existing entries when the D-Bus path matches, refreshing only ifindex,
and only call fetchLinkType on a genuinely new entry. A link torn down
and re-created at a different path still triggers a refetch.
Extract parseDescribeType from fetchLinkType so the JSON failure path —
malformed payload, missing Type field, wrong type for Type — can be
exercised without a live D-Bus connection. The classifier's fallback to
name-prefix heuristics already had coverage; this locks in that the seam
between Describe and the classifier surfaces an empty string on every
failure mode rather than misclassifying a link.
- Note: We do not convert your existing conf configs to lua. This update only reflects DMS defaults state
- Updated README.md to reflect changes
- Updated Keyboard shortcut support
* feat: add cycleProfile IPC command for display outputs
Adds `dms ipc outputs cycleProfile` which cycles through configured display
profiles in order, wrapping around from the last back to the first.
Useful for binding to a compositor keybind (e.g. Super+P in niri/Hyprland)
without needing an external wrapper script.
* feat: add Mod+P default keybind for cycling display profiles
Binds Super+P to `dms ipc outputs cycleProfile` in both the niri and
Hyprland default keybind configs. Mod+Shift+P is already reserved for
powering off monitors on both compositors, so Mod+P is a natural fit.
* fix: preserve pre-existing connection profiles on cancelled WiFi activation
When a pre-existing WiFi connection activation is cancelled, do not
remove the connection profile — only remove profiles for newly created
connections.
* feat: retrieve WiFi/VPN secrets from D-Bus secret service with unlock
Wireless, 802.1x, VPN, and WireGuard secrets are now looked up from
org.freedesktop.Secret before prompting the user. If the keyring is
locked, the unlock prompt is triggered via Prompt.Prompt() and the
lookup retried after the vault is unlocked.
* feat(tailscale): add Tailscale control center widget
Full-stack Tailscale integration for DMS control center:
Backend (Go):
- Event-driven manager via WatchIPNBus (no polling)
- Reconnects with exponential backoff when tailscaled unavailable
- Typed conversion from ipnstate.Status to QML-friendly IPC types
- Testable via tailscaleClient interface with mock watcher
- Manager cleanup in cleanupManagers()
- 19 unit tests
Frontend (QML):
- TailscaleService with WebSocket subscription
- TailscaleWidget with peer list, filter chips, search
- Copy-to-clipboard for IPs and DNS names
- Daemon lifecycle handling (offline/stopped states)
Dependencies:
- Add tailscale.com v1.96.1 (official local API client)
- Bump Go to 1.26.1 (required by tailscale.com)
* cleanups
---------
Co-authored-by: bbedward <bbedward@gmail.com>
Move system update flow to GO, with a CLI (convenient AIO tool) and
server integration. All lifecycle, scheduling, execution occurs on
backend side.
Run some backends via pkexec, some via terminal like paru/yay.
Incorporate flatpak as an option to update.
Add terminal override setting in GUI, in addition to $TERMINAL env
variable.
fixes#2307fixes#822fixes#1102fixes#1812fixes#1087fixes#1743
The unconditional startup scan introduced duplicate tray icons on normal boot because apps were still registering their own SNI items when the scan ran.
Use CLOCK_BOOTTIME − CLOCK_MONOTONIC to detect whether the system has ever been suspended. The startup scan now only runs when the difference exceeds 5 s, meaning at least one suspend/resume cycle has occurred.
On a fresh boot the difference is ≈ 0 and the scan is skipped entirely.
* Fix ddc brightness not applying because process exits before debounce timer runs
* Added sync.WaitGroup to DDCBackend and use it instead of loop in wait logic, added timeout in case i2c hangs.
* go fmt
---------
Co-authored-by: bbedward <bbedward@gmail.com>