Skip to content

Releases: leriart/NothingLess

NothingLess — Release Notes v1.0.3

15 Jun 19:59

Choose a tag to compare

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

13 Jun 15:23

Choose a tag to compare

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, and videoPlayerComp each emit contentReady() when the actual media is decoded and ready to display:
    • Image.Ready for static images
    • AnimatedImage.Ready for GIFs
    • MediaPlayer.PlayingState or Loaded for 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 contentReady never fires (e.g. corrupted media file).
  • The old layer's Loader is deactivated after crossfade, freeing GPU resources (video decoder, interpolation shader, palette canvas).
  • Video readiness uses a polling Timer (60ms) since onStatusChanged is unavailable on this QtMultimedia/Quickshell Video type.
  • 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 MouseArea and 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 broken axctl config unbind-key CLI format. Replaced with axctl config keybinds-batch using the same JSON format as CompositorKeybinds.qml — guaranteed consistency.
  • When a bind had multiple keys (e.g. SUPER+C and SUPER+SHIFT+X), only the last key was actually unbound because a single Process was reused and each iteration killed the previous one. Now builds a single atomic batch.

Atomic Delete

  • deleteBind() now sends a single keybinds-batch payload that:
    1. Unbinds the deleted bind's keys
    2. 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 debounced applyKeybinds() cycle (~100ms).

Reload Binds Button

  • Now does a full clean rebuild: reloads binds.json from disk, triggers a complete unbind+rebind cycle, and syncs the persistent .conf/.lua/.toml files.
  • 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: false filter: 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-only mode, 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:

  • enableRemoveTransition and enableAddTransition are explicitly set to false before appsModel.clear(). The old approach relied on a modelRebuilding property binding, but QML bindings are lazy and weren't re-evaluated in time.
  • Added a guard: if filteredApps is empty but the model already has items, the rebuild is cancelled — prevents accidental blank lists from race conditions.
  • Transitions are re-enabled via Qt.callLater after the rebuild completes.

Notch — Launcher Push Guard

  • NotchContent.qml: when opening the launcher, the StackView now checks if LauncherView is already the current item before pushing. Prevents rapid push/pop cycles that clashed with AnimatedListView transitions.

Compositor Keybinds — Performance

  • Removed the heavy sync-hyprland.py call from every compositorProcess exit in CompositorKeybinds.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-only mode.

v1.0.1

28 May 10:26

Choose a tag to compare

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 loginlock and sleep_monitor background 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 the install.sh script.

v1.0.0

27 May 18:10

Choose a tag to compare

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 | sh

Or manually:

git clone https://github.com/Leriart/NothingLess.git ~/.local/src/nothingless
sudo ln -s ~/.local/src/nothingless/cli.sh /usr/local/bin/nothingless
nothingless

Hyprland 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