neiam-device
Branding packages for neiam devices, published as .deb and .rpm
through the same pipeline as ppl.
| Package | Installs to |
|---|---|
neiam-branding |
nothing; depends on all of the below |
plymouth-theme-neiam |
/usr/share/plymouth/themes/neiam/ |
sddm-theme-neiam |
/usr/share/sddm/themes/neiam/ |
plasma-wallpaper-neiam |
/usr/share/wallpapers/neiam/ (desktop and lock screen) |
plasma-wallpaper-neiam-moire |
/usr/share/plasma/wallpapers/org.neiam.moire/ (animated; desktop and lock screen) |
plasma-splash-neiam |
/usr/share/plasma/look-and-feel/org.neiam.desktop/ (splash after login) |
Both are architecture-independent (all / noarch).
Images
Every background is rendered per resolution rather than scaled from one master, and each theme picks the render that best fits the screen (matching aspect ratio first, then least scaling, preferring to shrink):
plymouth/theme/background-<W>x<H>.png
sddm/theme/backgrounds/<W>x<H>.png
wallpaper/theme/contents/images/<W>x<H>.png
at 1280x800, 1366x768, 1920x1080, 1920x1200, 2560x1440, 2560x1600 and 3840x2160.
The files committed now are stand-ins: solid #651d1d with a #fef3c7
moire fading out into it. Blender renders replace them by overwriting
the file at the same path; nothing else needs to change.
tools/standins.py # write any missing stand-ins (needs numpy, Pillow)
tools/standins.py --force # rewrite them all
tools/standins.py --check # every image present at its size? (CI runs this)
The Plasma splash has no images of its own: it shows the installed wallpaper package’s, so login hands off to a desktop using that wallpaper without a visible change.
Adding or dropping a resolution means editing four lists together:
RESOLUTIONS in tools/standins.py, the bg_* table in
plymouth/theme/neiam.script, backgrounds in
sddm/theme/theme.conf, and backgrounds in
splash/theme/contents/splash/Splash.qml. Plasma finds the
wallpaper’s sizes by itself.
The Plymouth theme is copied into the initramfs, so every render there adds to its size.
Animated wallpaper
plasma-wallpaper-neiam-moire is a Plasma wallpaper plugin (“neiam
moire” under Wallpaper type, for the desktop or the lock screen)
that draws its patterns live: the moire, a halftone field, both,
bokeh (soft out-of-focus discs drifting upward and fading in and out
as they rise, 4 to 64 of them, each its own shade from the primary
towards the accent and from muted to vivid), or a starfield (sparse
stars, mostly faint and a few bright, each twinkling at its own rate). It can also fade back and
forth between any two of those every few minutes. Effects, each a checkbox and usable with any pattern: a glint, a band of light sweeping across the rings and dots
every minute and a half; breathing, the pattern slowly swelling and
easing; a few large defocused discs drifting past in front now and
then, like a light close to the lens; film grain; and dither (on by
default), which keeps the slow dark gradients from banding on 8-bit
displays.
Everything drifts slowly and never visibly repeats.
Its colours come from the waxx themes (dark, light, her, afterdark,
forest, sky, clays, stones, blueprint): the ground is base-100
fading to base-300, the moire accent, the halftone primary. It
can hold one theme and pattern, or follow the time of day through
night, sunrise, day and sunset, each phase with its own theme and
pattern (by default a starfield at night, bokeh at sunrise, moire and
halftone by day, moire at sunset), either by clock times or by the real
sun at a latitude and longitude. Between phases both blend by the sun’s
elevation: the patterns crossfade, and the colours turn the hue so the
transitions pass through the purples of a real twilight rather than
grey.
A checkbox writes “NEIAM” in the bottom right corner, in the theme’s
accent colour, in B612 Mono Bold at 12% of the screen height, with
sliders for its opacity and for a soft glow around it; the package pulls
in the font (fonts-b612 / firstyear-b612-fonts).
Settings trade smoothness for power: frame rate (30 by default) and speed, where 0 holds a still frame and costs nothing after drawing it.
moire/shaders/field.frag shader source
moire/theme/contents/ui/field.frag.qsb compiled; run tools/shaders.sh after editing
moire/theme/contents/ui/themes.js generated; tools/themes.py ../waxx/assets/css/app.css
moire/theme/contents/ui/schedule.js sun position and theme blending
moire/theme/contents/ui/Field.qml the picture, without Plasma
Field.qml is plain QtQuick, so it can be rendered outside Plasma.
Offscreen rendering needs the GPU path, or the shader is skipped:
QT_QUICK_BACKEND=rhi QSG_RHI_BACKEND=opengl QT_QPA_PLATFORM=offscreen qml6 ...
Android
droid/ is the animated wallpaper as an Android live wallpaper, with
the same patterns, effects, themes, time-of-day schedule and wordmark.
Its launcher entry is the settings screen, which also sets it as the
wallpaper and can fill in the location for following the sun.
It draws the same picture as the desktop because it runs the same
shader: the app packages moire/shaders/field.frag unchanged and
adapts its Qt header to OpenGL ES 3.0 at load time, and
tools/themes.py writes the palette for both. The motion and schedule
are Kotlin ports of Field.qml and schedule.js; keep them in step.
It draws only while visible, at the configured frame rate, and reports
its colours to Android for Material You.
cd droid && ./gradlew :app:testDebugUnitTest :app:assembleDebug
The icon is generated by tools/icons.py: the adaptive icon’s vector,
PNGs at every density (F-Droid reads the icon from the APK and cannot
render adaptive icons), and a 512 px store icon under droid/fastlane.
CI (.github/workflows/android.yml) builds it in a container
(droid/Dockerfile, context the repository root), signs it and
publishes it to the forge’s F-Droid repository, as Ova does. It needs
the ANDROID_KEYSTORE and ANDROID_KEYSTORE_PASS secrets and skips
without them; the workflow says how to make the keystore.
Enabling
Installing a package does not switch to its theme:
# Plymouth (rebuilds the initramfs)
sudo plymouth-set-default-theme -R neiam # Fedora / openSUSE
sudo update-alternatives --set default.plymouth \
/usr/share/plymouth/themes/neiam/neiam.plymouth \
&& sudo update-initramfs -u # Debian / Ubuntu
# SDDM
printf '[Theme]\nCurrent=neiam\n' | sudo tee /etc/sddm.conf.d/neiam.conf
Per user, in System Settings: the wallpaper under Wallpaper and
Screen Locking → Appearance (as the “Image” type for the stills, or
“neiam moire” for the animated one), the splash under Splash Screen
(or plasma-apply-wallpaperimage /usr/share/wallpapers/neiam and
kwriteconfig6 --file ksplashrc --group KSplash --key Theme org.neiam.desktop).
KDE’s settings show sddm/theme/preview.png and
splash/theme/contents/previews/*.png; re-render them after changing
the themes or their art:
QT_QPA_PLATFORM=offscreen qml6 tools/sddm-preview.qml
QT_QPA_PLATFORM=offscreen qml6 tools/splash-preview.qml
Try the login screen and splash without switching to them:
sddm-greeter-qt6 --test-mode --theme sddm/theme
ksplashqml --test --window splash/theme
Building
The packages are data-only cargo crates so that cargo-deb and
cargo-generate-rpm apply as they do for ppl:
cargo deb -p plymouth-theme-neiam --no-build --no-strip
cargo deb -p sddm-theme-neiam --no-build --no-strip
cargo deb -p plasma-wallpaper-neiam --no-build --no-strip
cargo deb -p plasma-wallpaper-neiam-moire --no-build --no-strip
cargo deb -p plasma-splash-neiam --no-build --no-strip
cargo deb -p neiam-branding --no-build --no-strip
tools/deb-fixup.sh target/debian/*.deb
cargo generate-rpm -p plymouth -a noarch
cargo generate-rpm -p sddm -a noarch
cargo generate-rpm -p wallpaper -a noarch
cargo generate-rpm -p moire -a noarch
cargo generate-rpm -p splash -a noarch
cargo generate-rpm -p branding -a noarch
cargo-deb can’t mark a package Architecture: all and writes an
empty Depends: for packages with nothing to link, so
tools/deb-fixup.sh corrects the control file afterwards.
CI (.github/workflows/package.yml) does the above on every push,
stamping +dev.<timestamp> onto branch builds and publishing to the
forge’s deb and rpm registries. Releases use ./release.sh as in ppl:
a v* tag publishes the bare version.