Files
DankMaterialShell/core
Mario Mohar 887509548b fix(theme): take sun times from the local calendar day, not the UTC one (#3237)
* fix(theme): take sun times from the local calendar day, not the UTC one

CalculateSunTimesWithTwilight read its reference day off date.UTC(). The
event seconds it computes are local mean solar time and lonOffset converts
them to UTC, so the instant of a local day's sunrise lands on the previous
UTC day east of Greenwich and a local sunset on the next one west of it.
Whenever the local and UTC calendars disagree, the function therefore
returned a neighbouring day's times.

Everything around it already works in local calendar days: the polar
branches of CalculateSunTimes build their day from date.Year/Month/Day,
thememode's startOfNextDay uses next.Location(), and the gamma scheduler
keys its calcDay cache on now.Location(). Only the reference day inside
the calculation disagreed.

Effect at UTC+8 (Kunming, 25.04N 102.72E): between local sunrise and 08:00
local, computeLocationSchedule got yesterday's sunrise and sunset, both
already past, fell through to the next-day branch and got today's sunrise,
also past. It reported dark with nextTransition in the past, which
schedulerLoop clamps to a one-second wait, so it re-evaluated every second
until 08:00 local and then flipped to light on its own. West of UTC the
mirror image: at UTC-7 the mode went dark from 17:00 local, when the UTC
date rolls over, until the real sunset.

The same SunTimes drive the gamma/night-light scheduler, so night light
shifted by a day the same way.

Fix: derive the reference day from date's own calendar day, keeping
dayStart anchored at UTC midnight so the lonOffset arithmetic is
unchanged, and take the orbit angle from the same day. Callers whose date
is already in UTC are unaffected.

Tests: suncalc_refday_test.go covers the reference day east and west of
UTC, stability across UTC midnight, and that UTC callers do not move.
manager_location_test.go is new to the thememode package and covers
computeLocationSchedule at both offsets, including that nextTransition is
never in the past.

* fix(theme): pick the reference day from the solar day, not the civil one

Taking the reference day straight off the caller's calendar day is right
for nearly every zone, but not for one shifted a full day away from its
own meridian. Apia, Kiritimati, Tongatapu and the Chathams all sit on
west longitudes while keeping a UTC+12:45..+14 offset, so their mean
solar time and their civil time are a day apart. Every sun event landed
on the following local day there, and the location schedule reported
dark around the clock.

Anchor on the caller's local noon and convert that to mean solar time to
pick the reference day. For every other zone this resolves to the same
date as before, so Kunming, Los Angeles and London are unchanged to the
second. dateOrbitAngle now takes the same reference day, so declination
and the equation of time no longer belong to a different day than the
events computed from them.

Covered at both levels: three antimeridian zones in the suncalc test,
and two cases in the location schedule test for the symptom itself.
Both fail without this change.
2026-08-31 13:26:39 -04:00
..
2025-11-12 23:12:31 -05:00

DMS Backend & CLI

Go-based backend for DankMaterialShell providing system integration, IPC, and installation tools.

See root README for project overview and installation.

Components

dms CLI Command-line interface and daemon for shell management and system control.

dankinstall Distribution-aware installer for deploying DMS and compositor configurations on Arch, Fedora, Debian, Ubuntu, openSUSE, Gentoo, and Void. Supports both an interactive TUI and a headless (unattended) mode via CLI flags.

System Integration

Wayland Protocols (Client)

All Wayland protocols are consumed as a client - connecting to the compositor.

Protocol Purpose
wlr-gamma-control-unstable-v1 Night mode color temperature control
wlr-screencopy-unstable-v1 Screen capture for color picker/screenshot
wlr-layer-shell-unstable-v1 Overlay surfaces for color picker UI/screenshot
wlr-output-management-unstable-v1 Display configuration
wlr-output-power-management-unstable-v1 DPMS on/off CLI
wp-viewporter Fractional scaling support (color picker/screenshot UIs)
keyboard-shortcuts-inhibit-unstable-v1 Inhibit compositor shortcuts during color picker/screenshot
ext-data-control-v1 Clipboard history and persistence
ext-workspace-v1 Workspace integration
dwl-ipc-unstable-v2 dwl/MangoWC IPC for tags, outputs, etc.

DBus Interfaces

Client (consuming external services):

Interface Purpose
org.bluez Bluetooth management with pairing agent
org.freedesktop.NetworkManager Network management
net.connman.iwd iwd Wi-Fi backend
org.freedesktop.network1 systemd-networkd integration
org.freedesktop.login1 Session control, sleep inhibitors, brightness
org.freedesktop.Accounts User account information
org.freedesktop.portal.Desktop Desktop appearance settings (color scheme)
CUPS via IPP + D-Bus Printer management with job notifications

Server (implementing interfaces):

Interface Purpose
org.freedesktop.ScreenSaver Screensaver inhibit for video playback

Custom IPC via unix socket (JSON API) for shell communication.

Hardware Control

Subsystem Method Purpose
DDC/CI I2C direct External monitor brightness
Backlight logind or sysfs Internal display brightness
evdev /dev/input/event* Keyboard state (caps lock LED)
udev netlink monitor Backlight device updates (for OSD)

Plugin System

  • Plugin registry integration
  • Plugin lifecycle management
  • Settings persistence

CLI Commands

  • dms run [-d] - Start shell (optionally as daemon)
  • dms restart / dms kill - Manage running processes
  • dms ipc <command> - Send IPC commands (toggle launcher, notifications, etc.)
  • dms plugins [install|browse|search|lock|restore] - Plugin management and portable exact-revision lockfiles
  • dms brightness [list|set] - Control display/monitor brightness
  • dms color pick - Native color picker (see below)
  • dms update - Update DMS and dependencies (disabled in distro packages)
  • dms greeter - Deprecated; forwards to the standalone dms-greeter binary

Color Picker

Native Wayland color picker with magnifier, no external dependencies. Supports HiDPI and fractional scaling.

dms color pick              # Pick color, output hex
dms color pick --rgb        # Output as RGB (255 128 64)
dms color pick --hsv        # Output as HSV (24 75% 100%)
dms color pick --json       # Output all formats as JSON
dms color pick -a           # Auto-copy to clipboard

The on-screen preview displays the selected format. JSON output includes hex, RGB, HSL, HSV, and CMYK values.

Building

Requires Go 1.25+

Development build:

make              # Build dms CLI
make dankinstall  # Build installer
make test         # Run tests

Distribution build:

make dist         # Build without update features

Produces bin/dms-linux-amd64 and bin/dms-linux-arm64

Installation:

sudo make install  # Install to /usr/local/bin/dms

Development

Setup pre-commit hooks:

git config core.hooksPath .githooks

This runs gofmt, golangci-lint, tests, and builds before each commit when core/ files are staged.

Regenerating Wayland Protocol Bindings:

Protocol XML files live in internal/proto/xml/. Bindings are generated with the dankgo go-wayland-scanner:

go run github.com/AvengeMedia/dankgo/cmd/go-wayland-scanner@latest \
  -i internal/proto/xml/wlr-gamma-control-unstable-v1.xml \
  -pkg wlr_gamma_control -o internal/proto/wlr_gamma_control/gamma_control.go

Module Structure:

  • cmd/ - Binary entrypoints (dms, dankinstall)
  • internal/distros/ - Distribution-specific installation logic
  • internal/proto/ - Wayland protocol bindings
  • pkg/ - Shared packages

Installation via dankinstall

Interactive (TUI):

curl -fsSL https://install.danklinux.com | sh

Headless (unattended):

Headless mode requires cached credentials or a passwordless rule for your privilege escalation tool (sudo, doas, or run0). With sudo, run sudo -v first:

sudo -v && curl -fsSL https://install.danklinux.com | sh -s -- -c niri -t ghostty -y
sudo -v && curl -fsSL https://install.danklinux.com | sh -s -- -c hyprland -t kitty --dms-greeter -y
sudo -v && curl -fsSL https://install.danklinux.com | sh -s -- -c niri -t ghostty --git-deps niri,quickshell --all-features -y
Flag Short Description
--compositor <niri|hyprland|mango> -c Compositor/WM to install (required for headless)
--term <ghostty|kitty|alacritty> -t Terminal emulator (required for headless)
--privesc <sudo|doas|run0> Privilege escalation tool (default: autodetect)
--git Install the git version of every dependency that has one
--git-deps <name,...> Install the git version of specific dependencies (e.g. niri,quickshell)
--all-features Enable all optional dependencies (dms-greeter, danksearch, dankcalendar)
--dms-greeter Install dms-greeter
--danksearch Install danksearch and enable its user indexing service
--dankcalendar Install dankcalendar
--include-deps <name,...> Enable optional dependencies (e.g. dms-greeter)
--exclude-deps <name,...> Skip specific dependencies
--replace-configs <name,...> Replace specific configuration files (mutually exclusive with --replace-configs-all)
--replace-configs-all Replace all configuration files (mutually exclusive with --replace-configs)
--yes -y Required for headless mode - confirms installation without interactive prompts

Headless mode requires --yes to proceed; without it, the installer exits with an error. Configuration files are not replaced by default unless --replace-configs or --replace-configs-all is specified. Optional packages (dms-greeter, danksearch, dankcalendar) are disabled by default; enable them with their dedicated flags, --include-deps, or --all-features.

When no flags are provided, dankinstall launches the interactive TUI.

Headless mode validation rules

Headless mode activates when --compositor or --term is provided.

  • Both --compositor and --term are required; providing only one results in an error.
  • Headless-only flags (--privesc, --git, --git-deps, --all-features, --include-deps, --exclude-deps, --replace-configs, --replace-configs-all, --yes, --danksearch, --dankcalendar, --dms-greeter) are rejected in TUI mode.
  • Positional arguments are not accepted.

Log file location

dankinstall writes logs to /tmp by default. Set the DANKINSTALL_LOG_DIR environment variable to override the log directory.

Supported Distributions

Arch, Fedora, Debian, Ubuntu, openSUSE, Gentoo, Void (and derivatives)

Arch Linux Uses pacman for system packages, builds AUR packages via makepkg, no AUR helper dependency.

Fedora

Uses COPR repositories (avengemedia/danklinux, avengemedia/dms).

Ubuntu Requires PPA support. Most packages built from source (slow first install).

Debian Debian 13+ (Trixie), testing, and sid. Stable quickshell from Debian (trixie-backports on 13). Other companions via OBS.

openSUSE Most packages available in standard repos. Minimal building required.

Gentoo Uses Portage with GURU overlay. Automatically configures USE flags. Variable success depending on system configuration.

Void Linux Uses XBPS with the DMS and DankLinux self-hosted repositories.

See installer output for distribution-specific details during installation.