Releases: leriart/NothingLess
NothingLess — Release Notes v1.0.3
Highlights
This release expands NothingLess with deeper monitor control and native wireless screen sharing, plus a refreshed project README that focuses on the shell's own feature set.
New Features
Wireless Screen Sharing
A new Settings section brings wireless display support directly into NothingLess. It can both receive and send screens using multiple protocols:
- AirPlay receiver via UxPlay (iOS, iPadOS, macOS).
- Miracast via miraclecast or GNOME Network Displays (Windows, Android, smart TVs).
- Chromecast sender via GNOME Network Displays.
The panel lets you choose between Receive and Send modes, pick a protocol, configure sinks, interfaces, FPS, audio/video outputs, and view live backend logs. Dependencies have been added to the Arch/Fedora installer and the Nix media package.
Fixed
- Monitor panel now keeps available refresh rates tied to the selected resolution.
- Primary monitor selection is persisted via StateService.
v1.0.2
NothingLess — Release Notes
Wallpaper Crossfade System
Before: Wallpaper transitions used a scale+opacity "pulse" animation (scale 1→1.02→1, opacity 1→0.4→1) that looked like a blink, not a fade. Video-to-video and GIF-to-GIF transitions loaded abruptly with no animation at all.
After: Two-layer crossfade architecture:
- Layer A / Layer B alternate as "current" and "next". The inactive layer loads the next wallpaper hidden (opacity 0) without destroying the current one.
- Signal-driven readiness — no more blind polling.
staticImageComponent,gifPlayerComp, andvideoPlayerCompeach emitcontentReady()when the actual media is decoded and ready to display:Image.Readyfor static imagesAnimatedImage.Readyfor GIFsMediaPlayer.PlayingStateorLoadedfor videos
- A short 80ms stabilization delay after readiness lets the GPU paint the first frame.
- Smooth crossfade: old layer fades out (380ms,
Easing.InOutCubic), new layer fades in with a subtle zoom reveal (0.97 → 1.0, 420ms,Easing.OutBack). - 3-second safety timeout forces the crossfade if
contentReadynever fires (e.g. corrupted media file). - The old layer's
Loaderis deactivated after crossfade, freeing GPU resources (video decoder, interpolation shader, palette canvas). - Video readiness uses a polling
Timer(60ms) sinceonStatusChangedis unavailable on this QtMultimedia/QuickshellVideotype. - Initial wallpaper load uses a simple fade-in (300ms) without zoom or fade-out.
Custom Keybinds — Full Rework
Enable/Disable Toggle Now Works
- The checkbox on custom bind items was visual-only — it had no
MouseAreaand clicking it opened the editor instead of toggling. Now it correctly enables/disables the bind with immediate unbind. - The main edit click area ignores clicks on the checkbox zone.
Unbind Format Fixed
unbindKeybind()was using a brokenaxctl config unbind-keyCLI format. Replaced withaxctl config keybinds-batchusing the same JSON format asCompositorKeybinds.qml— guaranteed consistency.- When a bind had multiple keys (e.g.
SUPER+CandSUPER+SHIFT+X), only the last key was actually unbound because a singleProcesswas reused and each iteration killed the previous one. Now builds a single atomic batch.
Atomic Delete
deleteBind()now sends a singlekeybinds-batchpayload that:- Unbinds the deleted bind's keys
- Rebinds all remaining enabled custom binds
- No more race condition between unbind and rebind. The compositor state is immediately consistent.
Immediate Toggle-Off
- When disabling a bind via the checkbox, the unbind happens instantly via
keybinds-batch, without waiting for the debouncedapplyKeybinds()cycle (~100ms).
Reload Binds Button
- Now does a full clean rebuild: reloads
binds.jsonfrom disk, triggers a complete unbind+rebind cycle, and syncs the persistent.conf/.lua/.tomlfiles. - Cleans up orphaned binds left over from failed deletions.
- Added
CompositorKeybinds.forceReloadBinds()for programmatic use.
Persistent Config Sync
sync-hyprland.py --binds-only: a lightweight mode that only regenerates and injects the keybinds section into.conf/.lua/.toml. Does NOT touch compositor settings, gestures, or trigger any reload.- Called only when the user explicitly changes a bind (toggle, add, delete, save) — not on every system trigger.
enabled: falsefilter:process_binds()now skips disabled binds, so they don't reappear in the persistent config files after sync.- Critical fix:
_inject_block()with an empty string was deleting blocks instead of preserving them (Python""is falsy). In--binds-onlymode, compositor and gestures blocks are now completely untouched.
Launcher — Rapid Toggle Fix
Before: Pressing SUPER repeatedly to open/close the app launcher caused the app list to go blank. The AnimatedListView add/remove transitions clashed with model clear+rebuild cycles.
After:
enableRemoveTransitionandenableAddTransitionare explicitly set tofalsebeforeappsModel.clear(). The old approach relied on amodelRebuildingproperty binding, but QML bindings are lazy and weren't re-evaluated in time.- Added a guard: if
filteredAppsis empty but the model already has items, the rebuild is cancelled — prevents accidental blank lists from race conditions. - Transitions are re-enabled via
Qt.callLaterafter the rebuild completes.
Notch — Launcher Push Guard
NotchContent.qml: when opening the launcher, theStackViewnow checks ifLauncherViewis already the current item before pushing. Prevents rapid push/pop cycles that clashed withAnimatedListViewtransitions.
Compositor Keybinds — Performance
- Removed the heavy
sync-hyprland.pycall from everycompositorProcessexit inCompositorKeybinds.qml. This was regenerating all config files (compositor + keybinds + gestures) and triggering reloads on every keybind batch, causing flickering and performance drops. - Live keybind changes are handled by
axctl keybinds-batch— persistent files are synced only on explicit user actions via the lightweight--binds-onlymode.
v1.0.1
What's New
Bug Fixes
- Workspaces UI: Fixed a critical issue where secondary monitors without explicit metadata generated negative workspace index labels (
-1,-2). The QML logic now features bulletproof math and cross-references global workspace states to correctly position the active workspace indicator (white dot) even when monitor metadata is incomplete. - IdleService: Resolved a zombie process leak across shell reloads. Orphaned
loginlockandsleep_monitorbackground scripts are now proactively cleared before starting new ones.
Improvements
- Native integration of the new lightning-fast C daemon (
axctl.c) right out of the box in theinstall.shscript.
v1.0.0
NothingLess v1.0.0
First release of NothingLess — a fork of Ambxst with massive changes across all areas of the codebase.
What's New
Video wallpapers with QtMultimedia + FFmpeg
Replaces mpvpaper. Runs in-process with VA-API hardware acceleration, no external processes. Configurable OpenGL/Vulkan backend with threaded render loop.
Free Layout
Windows-style floating desktop: floating windows, edge snap, show desktop, Smart Resize Anchors. Switchable from the dashboard alongside Dwindle, Master, and Scrolling.
Dynamic Island
Notifications and metrics embedded in the bar in "dynamic" mode. The notch merges with the bar, showing a compact pill with clock, media, and metrics.
Task tray
Full system tray with icon show/hide and context menus.
M3 Animation System
Complete animation system with 3 profiles: Material 3 (default), Windows Classic, macOS. Replaces the global Config.animDuration with M3 easing curves across 200+ files. Each profile defines durations and easings per motion type (standard, emphasized, spatial, decelerate, accelerate).
Expanded compositor configuration
From ~25 to 100+ properties:
| Category | New Properties |
|---|---|
| Opacity & Dim | activeOpacity, inactiveOpacity, fullscreenOpacity, dimInactive, dimStrength, dimAround, dimSpecial |
| Resize | resizeOnBorder, extendBorderGrabArea, hoverIconOnBorder, roundingPower |
| Snap assistant | snapEnabled, snapWindowGap, snapMonitorGap, snapBorderOverlap, snapRespectGaps |
| Input: Keyboard | kbLayout, kbVariant, kbOptions, numlockByDefault, repeatRate, repeatDelay |
| Input: Mouse | mouseSensitivity, mouseAccelProfile, followMouse, mouseNaturalScroll, mouseScrollFactor, mouseLeftHanded, mouseRefocus, floatSwitchOverrideFocus |
| Input: Touchpad | 8 properties |
| Cursor | 8 properties |
| Gestures | 10 swipe properties |
| Layouts | 10 dwindle, 8 master, 6 scrolling |
| XWayland | 3 properties |
| Misc | renderBackend, animateManualResizes, animateMouseWindowdragging, etc. |
Monitor configuration panel
Full GUI for monitor setup: drag-and-drop arrangement, resolution, refresh rate, scale, transform. Backed by monitors_writer.py with live hyprctl reload.
Config sync
sync-hyprland-conf.py reads compositor.json and binds.json, generating native hyprland.conf and hyprland.lua with 0.53+ syntax. Also syncs axctl.toml for daemon consistency.
Expanded CLI
From 9 to 20+ commands: reload, quit, screen on|off, suspend, VolumeUp/Down/Mute, MicMute, Caffeine, Gamemode, Nightlight, run <module>. Install now supports --lua and --conf.
4 new presets
| Preset | Files | Style |
|---|---|---|
| Dot Matrix | 8 | Dot-matrix aesthetic |
| Nothing | 10 | Monochrome + red accents, Ndot font |
| Pure Monochrome | 8 | Pure monochrome |
| Minimal | 2 | Minimal theme |
New Services
| Service | Description |
|---|---|
IpcPool.qml |
IPC coalescer (50ms) — prevents compositor overload |
MonitorsWriter.qml |
QML backend for monitor configuration |
PerMonitorConfig.qml |
Per-monitor bar, notch, dock positioning |
WlrToplevelMapper.qml |
hyprctl → WlrToplevel bridge for ScreencopyView |
DeepSeekApiStrategy.qml |
DeepSeek AI provider |
BatteryAlertService.qml |
Low battery notifications, auto power save |
Calculator.qml |
Integrated calculator (libqalculate) |
MusicRecognizer.qml |
Music recognition (SongRec/Shazam) |
ScreenTranslation.qml |
Screen translation (translate-shell) |
New Scripts
| Script | Purpose |
|---|---|
sync-hyprland-conf.py |
Sync config to hyprland.conf/lua + axctl.toml |
monitors_writer.py |
Monitor config backend with live reload |
nothing-fps |
MangoHud FPS monitoring tool |
apply-config.sh |
Apply compositor config |
mangohud-patch/build-mangohud.sh |
Build patched MangoHud from source |
toggle-metrics.sh |
Toggle notch metrics overlay |
nothingless-resize |
Window resize tool |
bluetooth_helper.py |
Bluetooth pairing helper |
fps_monitor.py |
Real-time FPS monitor |
fps_preload.c |
C preloader for FPS hooking |
gsr-fps.sh |
GPU Screen Recorder FPS script |
Performance
- Video wallpapers: mpv → QtMultimedia + FFmpeg (in-process, hardware accelerated)
- Offscreen layer: conditional — only rendered when content is visible
- IpcPool: 50ms IPC coalescing prevents compositor flooding
- Adjacent monitor detection: bar hover region adjusts when a monitor is adjacent
- Show/hide delays: 200ms show, 800ms hide (was 1000ms)
Installation
curl -sL https://github.com/Leriart/NothingLess/raw/main/install.sh | shOr manually:
git clone https://github.com/Leriart/NothingLess.git ~/.local/src/nothingless
sudo ln -s ~/.local/src/nothingless/cli.sh /usr/local/bin/nothingless
nothinglessHyprland integration
nothingless install hyprland # Auto-detect
nothingless install hyprland --conf # Config file mode (default)
nothingless install hyprland --lua # Lua mode (Hyprland >= 0.48)
nothingless remove hyprland # Remove config