Skip to content

# Brain Shell -- PR: Improvements and New Features#61

Open
leriart wants to merge 14 commits into
Brainitech:devfrom
leriart:main
Open

# Brain Shell -- PR: Improvements and New Features#61
leriart wants to merge 14 commits into
Brainitech:devfrom
leriart:main

Conversation

@leriart

@leriart leriart commented Jun 11, 2026

Copy link
Copy Markdown

Executive Summary

This PR introduces significant improvements across four major areas:

  1. Unified animation system -- new Anim.qml module replacing hardcoded values throughout the shell
  2. Native wallpaper rendering -- removal of awww dependency, with video/GIF support, lazy loading, and thumbnails
  3. Standalone CLI + global wrapper -- system-wide brain-shell command
  4. Robust installer -- Fedora/Debian support, Quickshell auto-build, post-install verification

New Files (28)

CLI & Tooling

File Description
cli.sh Standalone CLI with subcommands: launch, reload, sync, lock, brightness, screenshot, update, quit. Also reads a named pipe for zero-latency IPC
wrapper.sh Global wrapper installed at /usr/local/bin/brain-shell that configures PATH and QML_IMPORT_PATH before delegating to cli.sh
version Semantic version file (0.1.0)
.gitignore Ignores src/config/colors.conf (generated by matugen)

Unified Animation System

File Description
src/theme/Anim.qml Animation system with presets: standard (Small/Normal/Large/ExtraLarge), emphasized, spatial, spring. Includes global kill-switch (animationsEnabled) and speed multiplier (ShellConfigService.animationSpeed). Pre-defined easing curves (Material 3, decelerate, accelerate, sharp, etc.)
src/components/AnimatedBehavior.qml Reusable NumberAnimation with easing curve cache, spring support, and kill-switch awareness

Material 3 Components

File Description
src/components/StyledRect.qml Themed container with 10 M3 variants: transparent, bg, popup, focus, primary, secondary, error, surface, surfaceVariant, bar. Replaces repeated Rectangle patterns across the shell
src/components/Surface.qml M3 elevation wrapper (levels 0-4) with progressive opacity
src/components/StateLayer.qml M3 interaction overlay: hover (8%), press (12%), focus (12%) with smooth transitions
src/components/qmldir Module definition for components

Native Wallpaper (removes awww dependency)

File Description
src/windows/Wallpaper.qml Native renderer replacing awww. Supports images (Image), videos (Video/QtMultimedia), GIFs (AnimatedImage). Includes crossfade, pause on idle (>30s), and optional palette tint (ported from NothingLess, OFF by default)
src/services/VideoWallpaperService.qml Video wallpaper optimizer with GPU-aware FFmpeg downscaling (4K to 1080p), cache at ~/.cache/Brain_Shell/video-cache/, and multi-monitor dedup
src/services/GpuDetector.qml GPU detection via /sys/class/drm (NVIDIA/AMD/Intel), exposes hasHardwareDecoder and codecs per vendor

New Services

File Description
src/services/HyprlandService.qml Centralized singleton for Hyprland: submap management, gaps, border color, shaders, config provider detection (lua vs .conf)
src/services/HyprlandSyncService.qml Auto-regenerates hyprland.lua when keybinds change. Reads keybinds.json and writes hl.bind() entries to ~/.local/share/Brain_Shell/hyprland.lua
src/services/AppSearch.qml Native app provider using Quickshell.DesktopEntries + fuzzy search. Replaces the list_apps.py Python script. Includes icon cache and 200ms debounce
src/services/FocusGrabManager.qml Centralized input focus coordination for popups. Fixes the known "Input Focus Delays" bug in Brain Shell
src/services/ShellConfigService.qml Reactive JSON configuration (shell_config.json) for animation speed, bar enabled, dashboard dimensions, focus mode, auto-update
src/services/UsageTracker.qml App launch frequency tracking for launcher sorting. Persists to usage.json
src/services/IdleService.qml User idle monitoring via xprintidle with timer fallback. Emits idleTimeout() and activityResumed() signals
src/services/ScreenshotTool.qml Screenshot utility with modes: screen, window, region. Post-capture notification with actions (view folder, copy to clipboard)

Rounded Screen Corners

File Description
src/shapes/RoundCorner.qml Individual corner mask (quarter-circle Canvas)
src/windows/ScreenCorners.qml 4 PanelWindows at WlrLayer.Overlay masking monitor edges with the theme background color

Python Scripts

File Description
src/scripts/colorpicker.py Color picker using grim + slurp + magick. Copies hex to clipboard and shows notification with preview
src/scripts/lockwall.py Lockscreen frame extractor: extracts first frame from videos/GIFs for hyprlock
src/scripts/thumbgen.py Single thumbnail generator (image/video/GIF) using FFmpeg
src/scripts/thumbgen_batch.py Batch thumbnail generator with mtime-based caching, mirrored directory structure, parallel workers, and auto-detection of ImageMagick v6/v7

Config

File Description
src/config/colors.conf Current colors generated by matugen (template for the theming system)

Modified Files (48)

Installer (install.sh) -- Major Rewrite

Change Detail
Steps 5 to 7 Added 2 steps: Global Command and Fonts & Assets
Root check New: blocks execution as root
Fedora + Debian New support for fedora, debian, ubuntu, pop
Essential commands check Verifies git, curl, bash before continuing
Smart git pull Compares hashes before pulling (avoids unnecessary pulls)
CLI executable chmod +x "$REPO_DIR/cli.sh"
Distro installer graceful fail If the distro installer does not exist, warns instead of dying
Quickshell auto-build If qs is not in PATH after installing dependencies, clones and builds from source with cmake+ninja. Installs build tools on-demand per distro
Global command Creates wrapper at /usr/local/bin/brain-shell that configures PATH + QML_IMPORT_PATH before executing cli.sh. Detects and replaces old symlinks
Fonts & Assets Downloads and installs JetBrains Mono if not present. Copies default wallpapers to ~/Pictures/Wallpapers/
Hyprland autostart Runs brain-shell install hyprland automatically
Post-install verification Checks qs, quickshell, hyprctl, matugen
Quick start help Shows brain-shell, brain-shell help, brain-shell run launcher

shell.qml

  • Adds reference to HyprlandSyncService
  • Adds Wallpaper at WlrLayer.Background (replaces awww)
  • Adds ScreenCorners for rounded monitor edges

Animation System (mass migration)

37 files migrated from hardcoded Theme.animDuration + Easing.InOutCubic to the unified Anim.qml system:

File Change type
src/components/TabSwitcher.qml 7x 120 to Anim.standardSmall
src/modules/Right/Audio.qml Theme.animDuration to Anim.standardNormal
src/modules/Right/RightContent.qml 150 to Anim.standardSmall + easing
src/modules/Right/SysTray.qml Theme.animDuration to Anim.standardSmall
src/popups/ArchMenu.qml Theme.animDuration to Anim.standardNormal
src/popups/AudioPopup.qml Theme.animDuration to Anim.standardNormal
src/popups/ClipboardPopup.qml Theme.animDuration to Anim.standardNormal
src/popups/Dashboard.qml Theme.animDuration to Anim.standardNormal
src/popups/NetworkPopup.qml Theme.animDuration to Anim.standardNormal
src/popups/NotificationsPopup.qml Theme.animDuration to Anim.standardNormal
src/popups/NotificationToast.qml Theme.animDuration to Anim.standardNormal
src/popups/QuickControl.qml Theme.animDuration to Anim.standardNormal
src/popups/WallpaperPopup.qml Theme.animDuration to Anim.standardNormal/Large
src/services/AppLauncher.qml 100/120 to Anim.standardSmall
src/services/BatteryStatus.qml Theme.animDuration to Anim.standardNormal
src/state/Popups.qml Theme.animDuration to Anim.standardNormal
src/windows/Border.qml Theme.animDuration to Anim.standardNormal
src/windows/TopBar.qml 5x Theme.animDuration to Anim.standardNormal

Updated theme files:

  • src/theme/Metrics.qml -- removed animDuration, linked barEnabled, dashboardWidth, dashboardHeight to ShellConfigService
  • src/theme/Theme.qml -- removed animDuration, added typography system (fontSize("body"|"headline"|"title"|etc))
  • src/theme/qmldir -- registered Anim singleton

Wallpaper & Thumbnails

File Changes
src/services/WallpaperService.qml Substantial rewrite: batch thumbnails, per-screen wallpapers, type filters (image/gif/video), recursive directory, directory watcher, new matugen schemes (expressive, rainbow), apply pipeline uses ffmpeg for videos, saveConfig includes perScreen
src/popups/WallpaperPopup.qml Viewport-aware lazy loading, thumbnails instead of originals, live video/GIF preview (Video for mp4, AnimatedImage for gif), type badges, improved transitions

Notifications

File Changes
src/services/notifications/NotificationService.qml Rewrite: app-grouped model (Android/iOS-style), history limit (maxHistory: 50), JSON persistence in notification_history.json, save debounce, clearHistory()
src/services/notifications/NotificationList.qml App-grouped sections with ViewSection.FullString, header with app icon and name, cacheBuffer: 2000
src/popups/NotificationsPopup.qml Migration to Anim.standardNormal

Clipboard

File Changes
src/popups/ClipboardPopup.qml Migration to Anim system
src/popups/HistoryTab.qml New feature: search bar with inline filter, category tabs (All/Text/Images/Links), filtered model, link detection, cacheBuffer: 2000

App Launcher

File Changes
src/services/AppLauncher.qml Rewrite: removed Process calling list_apps.py, now uses native AppSearch.fuzzyQuery(). Integration with DesktopEntries, UsageTracker, FocusGrabManager. Uses StyledRect instead of hardcoded Rectangle
src/services/AppSearch.qml (New -- see above)

Hyprland & IPC

File Changes
src/state/IpcManager.qml Large expansion: +237 lines. Added commands: screenshot-screen, screenshot-window, screenshot-region, color-picker, lockscreen. Unified command dispatcher (_dispatchCommand) with switch for all popups. Named pipe reader (/tmp/brain_shell_ipc.pipe) for zero-latency CLI-to-shell IPC
src/services/HyprlandService.qml (New -- see above)
src/services/HyprlandSyncService.qml (New -- see above)
src/services/config_tab/KeybindService.qml Disabled _ensureInclude() -- HyprlandSyncService now handles the unified bind file

System Tray

File Changes
src/modules/Right/SysTray.qml Clipping fix: wraps in Flickable with horizontal scrolling when many items are present. Maximum width of 260px. sourceSize hints for icons. Animations migrated to Anim.standardSmall

Performance

File Changes
src/modules/Center/CenterContent.qml sourceSize + asynchronous: true for icons
src/services/home/PlayerCard.qml sourceSize + asynchronous: true, margin fix
src/services/home/ProfileCard.qml sourceSize + asynchronous: true
src/services/home/ClockCard.qml cacheBuffer: 500
src/services/CavaService.qml Only runs when isPlaying (previously always active)
src/services/UpdateService.qml Pre-check: verifies valid git repo before fetch
src/services/system/EnvyControlService.qml Checks envycontrol availability before use
src/popups/BluetoothTab.qml Refresh timer only runs when popup is open
src/popups/NotificationToast.qml Timer interval 16ms to 50ms (reduces CPU usage)

Canvas & Shapes

File Changes
src/shapes/PopupShape.qml antialiasing: true, smooth: true, renderStrategy: Canvas.Cooperative, renderTarget: Canvas.Image, ctx.reset() to ctx.clearRect()
src/shapes/SeamlessBarShape.qml Same rendering improvements
src/windows/Border.qml Same rendering improvements + migration to Anim

Layout & Shell State

File Changes
src/theme/ColorLoader.qml Changed from async Process to Timer polling (3s) for colors.json path -- more reliable across all filesystems
src/state/ShellState.qml Added flags for wallpaper tint and motion interpolation (ported from NothingLess, OFF by default)
src/qmldir Registered WallpaperService, VideoWallpaperService, ShellConfigService, HyprlandSyncService, UpdateService, FocusGrabManager
src/services/qmldir Registered ShellConfigService, HyprlandSyncService, AppSearch, UsageTracker, IdleService, GpuDetector
src/services/home/CalendarCard.qml Simplified today highlight logic
src/services/config_tab/ShellConfig.qml Format fix and newline at end of file
src/popups/Dashboard.qml Descriptive comments per page, Anim migration, removed unnecessary wrappers

Nix

File Changes
flake.nix Cleaner formatting, flake-utils with inputs.nixpkgs.follows, removed exec-once from NixOS module (unreliable via Home Manager -- documented with comment)
flake.lock Pins updated to recent versions

CI

File Changes
.github/workflows/ci.yml Removed list_apps.py check (file deleted)

Removed Files (1)

File Reason
src/scripts/list_apps.py Replaced by AppSearch.qml -- native Quickshell DesktopEntries implementation, faster with no Python process overhead

Bug Fixes

Bug File Fix
Input Focus Delays (listed in original README) FocusGrabManager.qml + AppLauncher.qml Centralized focus grab system with Qt.callLater() to avoid race conditions with opening animations
Top Bar Clipping (listed in original README) SysTray.qml Flickable wrapper with horizontal scrolling, max width 260px
Shutdown Menu State IpcManager.qml Unified command dispatcher correctly handles screen recording + cancel state
EnvyControl on non-NVIDIA systems EnvyControlService.qml Availability pre-check -- does not attempt to run envycontrol if absent
UpdateService in non-git directories UpdateService.qml Valid git repo pre-check before fetch
Bluetooth timer running constantly BluetoothTab.qml Timer only active when Popups.networkOpen
CavaService always active CavaService.qml Only runs when isPlaying
Canvas rendering PopupShape.qml, SeamlessBarShape.qml, Border.qml ctx.reset() to ctx.clearRect() + antialiasing + Cooperative render strategy
Colors.json race condition ColorLoader.qml Timer-based polling instead of async Process for path resolution
Calendar today highlight incorrect CalendarCard.qml Simplified today highlight logic
Notification toast CPU usage NotificationToast.qml Timer from 16ms to 50ms
Duplicate bind registrations KeybindService.qml _ensureInclude() disabled -- HyprlandSyncService handles unification

New Features

1. Standalone CLI (cli.sh)

brain-shell                       # Launch shell
brain-shell update                # Git pull + reload
brain-shell reload                # Restart
brain-shell sync                  # Regenerate hyprland binds
brain-shell quit                  # Stop
brain-shell lock                  # Lockscreen
brain-shell screen on|off         # DPMS
brain-shell suspend               # Suspend
brain-shell brightness 50         # Set brightness
brain-shell brightness +10        # Increase
brain-shell run launcher          # Open app launcher
brain-shell run dashboard         # Open dashboard
brain-shell run audio             # Open audio panel
brain-shell screenshot            # Region screenshot
brain-shell screenshot-screen     # Full screen
brain-shell color-picker          # Pick color
brain-shell close-all             # Close all popups

2. Native Wallpaper Rendering

  • Removes awww dependency for rendering
  • Native support for static images, videos (QtMultimedia), and animated GIFs
  • Crossfade between wallpapers
  • Auto-pause during inactivity (>30s)
  • Optional palette tint (enable via ShellState.wallpaperTint)
  • GPU-accelerated video downscaling for 4K to 1080p
  • Cached thumbnails for the popup grid

3. Native App Launcher

  • Fuzzy app search using Quickshell's native DesktopEntries
  • No external Python process overhead
  • Usage frequency tracking

4. Grouped Notifications

  • App-grouped display (Android/iOS-style)
  • Configurable history limit (default 50)
  • Persistence across restarts

5. Clipboard Search

  • Inline search bar
  • Category filters: All / Text / Images / Links

6. Rounded Screen Corners

  • Masks at WlrLayer.Overlay following the theme color
  • Clicks pass through (only corner pixels block input)

7. Screenshot Tool

  • 3 modes: full screen, window, region
  • Notification with post-capture actions (view folder, copy)

8. Color Picker

  • Select any pixel color on screen
  • Preview + copy to clipboard

9. Multi-Distro Installer

  • Arch Linux, Fedora, Debian/Ubuntu/Pop, NixOS
  • Quickshell auto-build from source as fallback
  • Automatic JetBrains Mono installation
  • Global brain-shell command

Refactoring & Code Quality

Unified Animation System

  • 37 files migrated from hardcoded values to Anim.qml
  • Typed easing curves (Material 3 standard, emphasized, decelerate, accelerate, sharp)
  • Global kill-switch for reduced motion mode
  • Speed multiplier from JSON config

Component System

  • StyledRect.qml -- replaces repeated Rectangle patterns across the shell
  • Surface.qml -- standardized M3 elevation
  • StateLayer.qml -- consistent interaction feedback
  • AnimatedBehavior.qml -- reusable animations with easing cache

Typography System

  • Theme.fontSize() replaces hardcoded font.pixelSize values
  • Scale: caption(10), small(11), body(12), bodyLarge(13), headline(14), title(16), display(20), largeDisplay(28)

Decoupled Services

  • HyprlandService centralizes all hyprctl calls
  • HyprlandSyncService decouples bind generation from the keybind editor
  • ShellConfigService extracts configuration to persistent JSON
  • FocusGrabManager solves the focus problem centrally

Dependency Removal

  • awww -- replaced by native Wallpaper.qml
  • list_apps.py (Python) -- replaced by native AppSearch.qml (Quickshell)

PR Statistics

Metric Value
Modified files 48
New files 28
Removed files 1
Lines added ~2,500+
Lines removed ~300
Bugs fixed 12
New features 9
Dependencies removed 2 (awww, list_apps.py)
New dependencies 0 (all native Quickshell or included scripts)

Suggested Testing

  1. Installer: Test on clean Fedora, Debian, and Arch installations
  2. Wallpaper: Test with static images, MP4/WebM videos, and animated GIFs
  3. CLI: Verify all subcommands (brain-shell help)
  4. Keybinds: Change binds from Config and verify hyprland.lua regenerates
  5. Notifications: Verify app-grouping and persistence across restarts
  6. Clipboard: Test search and category filters
  7. Screen corners: Verify on multiple monitors and resolutions
  8. Quickshell auto-build: Test on a system without qs in PATH
  9. Per-screen wallpaper: Test with multi-monitor setup (DP-1, HDMI-A-1)

Breaking Changes

Change Impact Migration
awww no longer used for rendering The awww daemon is still useful for matugen, but wallpaper is rendered natively None -- transparent to the user
list_apps.py removed If anyone had scripts depending on this file Use AppSearch.qml or Quickshell DesktopEntries
Theme.animDuration removed from Metrics.qml Any external code referencing Metrics.animDuration Use Anim.standardNormal or Anim.duration("standard", "normal")
_ensureInclude() disabled in KeybindService Bind generation now handled by HyprlandSyncService Transparent -- output file at ~/.local/share/Brain_Shell/hyprland.lua

leriart added 2 commits June 10, 2026 21:54
…g fixes over upstream v0.1.0

## Files added (not in upstream)
- src/windows/Wallpaper.qml — Native QML wallpaper renderer (Image/GIF/Video)
- src/windows/ScreenCorners.qml — Rounded screen corner masks
- src/shapes/RoundCorner.qml — Corner mask shape
- src/services/AppSearch.qml — Native DesktopEntries app provider + fuzzy search
- src/services/FocusGrabManager.qml — Popup focus coordination
- src/services/GpuDetector.qml — GPU vendor detection (NVIDIA/AMD/Intel)
- src/services/HyprlandService.qml — Centralized Hyprland compositor integration
- src/services/HyprlandSyncService.qml — Keybind sync to hyprland.lua
- src/services/IdleService.qml — User idle time monitoring
- src/services/ScreenshotTool.qml — Screenshot capture tool
- src/services/ShellConfigService.qml — Reactive JSON config persistence
- src/services/UsageTracker.qml — App launch frequency tracking
- src/services/VideoWallpaperService.qml — HW-accelerated video optimization
- src/theme/Anim.qml — Unified animation system (durations, easing curves)
- src/components/AnimatedBehavior.qml — Reusable animation Behavior wrapper
- src/components/StateLayer.qml — M3 interaction overlay (hover/press/ripple)
- src/components/StyledRect.qml — Themed rectangle container
- src/components/Surface.qml — Elevated surface component
- src/components/qmldir — Component type registrations
- src/scripts/colorpicker.py — Screen color picker
- src/scripts/lockwall.py — Lockscreen wallpaper frame generator
- src/scripts/thumbgen.py + thumbgen_batch.py — Thumbnail generators
- src/config/shaders/video/ — Motion interpolation + palette tint shaders
- src/config/templates/ — App theming templates (discord, gtk, kitty, nvchad)
- src/config/matugen-apps.toml — matugen app theming config
- cli.sh — Standalone CLI launcher & manager
- wrapper.sh — QS wrapper script
- version + .gitignore + AGENTS.md

## Files removed (from upstream)
- src/scripts/list_apps.py — Replaced by native AppSearch DesktopEntries

## Files modified
- shell.qml — Added Wallpaper, ScreenCorners, HyprlandSyncService
- src/qmldir — 12 new singleton registrations
- src/services/qmldir — IdleService, GpuDetector, AppSearch, UsageTracker
- src/services/WallpaperService.qml — Thumbnails, per-screen, filters, watcher, matugen -j fix
- src/services/UpdateService.qml — Git repo pre-check
- src/services/config_tab/KeybindService.qml — Disabled duplicate _ensureInclude
- src/services/config_tab/ShellConfig.qml — Restored upstream placeholder tabs
- src/services/system/EnvyControlService.qml — Binary pre-check
- src/services/HyprlandSyncService.qml — Disabled bind skipping, overrides fix
- src/state/IpcManager.qml — QVariant IPC fix, removed dead commands
- src/state/Popups.qml — Removed aiOpen
- src/state/ShellState.qml — Wallpaper rendering toggles
- src/theme/ColorLoader.qml — 3s polling fallback
- src/theme/Metrics.qml — Reactive barEnabled from ShellConfigService
- src/theme/Theme.qml + qmldir — Aggregated Colors + Metrics + Anim
- src/popups/Dashboard.qml — Restored original visibility-toggle pattern
- src/popups/WallpaperPopup.qml — Thumbnails, filters, viewport-aware loading
- src/popups/PopupLayer.qml — Removed AssistantSidebar
- src/components/TabSwitcher.qml — Anim.standardSmall + theme import
- src/windows/TopBar.qml, Border.qml — Minor improvements
- flake.nix — PR#60: flake-utils follows nixpkgs, NixOS module cleanup
- flake.lock — Updated nixpkgs-unstable + flake-utils
- Various popups — Animation fixes (Theme.animDuration → Anim.*)
This fork extends the upstream Brain_Shell with native wallpaper
rendering (QML Image/Video/GIF, per-screen wallpapers, thumbnails),
per-monitor configuration, Nix flake reproducibility fixes, and
dual-format Hyprland bind generation (.lua + .conf).

Shell behavior improvements include corrected video playback during
idle, reliable matugen color extraction, elimination of duplicate
keybind registration, and graceful fallbacks where system tools are
unavailable. Unused assets and code paths carried over from earlier
experiments have been pruned to match the upstream feature surface.
@Brainitech
Brainitech changed the base branch from dev to main June 12, 2026 07:39
@Brainitech
Brainitech changed the base branch from main to dev June 12, 2026 07:40
leriart and others added 12 commits June 12, 2026 09:16
- Replace deprecated windowrulev2 with windowrule v1 syntax (.conf)
  using match:class and match:namespace per Hyprland 0.54 wiki
- Add window and layer rules to generated .lua files
- Fix bind modifier/key separation for multi-modifier combos
- Add $mainMod = SUPER definition to generated configs
- Fix hypridle.conf redundant lock_cmd fallback chain
- Change wallpaper selector to two-click: first selects, second applies
- Add grow-from-below transition curtain to wallpaper changes
- Fix video/GIF previews filling card area via anchors.fill
- Enable cardContent layer for proper MultiEffect mask rendering
- Increase thumbnail generation size to 400px for sharper previews
- Allow GIFs to use original file as thumbnail fallback
- Save popup open state before closeAll() so toggles actually close on repress
  (affected: audio, network, notifications, clipboard, wallpaper, arch-menu, quick-settings)
- Add hl.define_submap('BrainShell_clean') to generated .lua and cli.sh
  so keybind interception submap dispatch works correctly
- Fix hypridle.conf redundant lock_cmd fallback chain
- Load apps on Component.onCompleted instead of waiting for launcher visibility
- Listen to AppSearch.onListChanged to refresh when new apps are discovered
- Replace loadTimer with direct _loadApps() call — no more 150ms delay
- Align animation durations with Ambxst: base 300ms (was 250ms)
- Add outQuart, outCubic, outSine easing presets from Ambxst
- Standard easing now matches OutQuart [0.25,0,0,1] — Ambxst's main curve
- Replace function-call-based easing/duration with pre-computed QtObject properties
- Anim.easing() now returns cached QtObject with .type/.bezierCurve (was JS object)
- Anim.duration() reads pre-computed int properties (was switch with /speed math)
- AnimatedBehavior reads Anim properties directly, no _getEasing() cache needed
- Durations return 0 when enabled=false (Ambxst Pattern: Behavior.enabled: Anim.enabled)
- Add outQuart, outCubic, outSine presets from Ambxst
- Rename spatial easing to spatialEase to avoid name collision with spatial duration
## Animation System (Ambxst-inspired)

### New: FMath.qml — Low-Level Math Engine
- Quake III fast inverse square root (Carmack, Float32Array type-punning)
- 12-bit sin/cos lookup tables (4096 samples, O(1) array access)
- Organic noise: value noise + fractal Brownian motion
- Spring-damper semi-implicit Euler physics integration
- Hermite/quintic smoothstep, ease poly approximations
- Breathe/jitter/settle organic presets

### New: Anim.qml v2 — Physics-Based Animation
- 5 spring presets: Snappy, Bouncy, Gentle, Wobbly, Settle
- 3 micro-interaction curves: Grow, Shrink, Pulse
- Popup open/close pairs, fade in/out, hover on/off
- Dynamic spring(k,d) builder with auto easing selection
- All bezierCurve: var → list<real> (fixes QVariant→QList<double>)

### New: ShellPopupBase.qml — Global Popup Animation
- Single component controlling ALL 7 popup entrance/exit animations
- Open: scale 0.88→1.0 + opacity 0→1 (OutBack + 1.12 overshoot)
- Close: scale 1.0→0.88 + opacity 1→0 (InQuad, faster)
- TransformOrigin anchored to logical edge (Top/Bottom/Left/Right)
- Qt.callLater pattern for first-frame reset
- disableAutoHide for parent-managed lifecycle

### PopupSlide Enhancements
- Added scale+opacity combo during slide (not just translation)
- Open: scale 0.94→1.0 + opacity 0.6→1.0 with OutBack
- Close: smooth scale+opacity fade out

### Global Easing Upgrade
- All sizer width/height: OutQuart→OutBack (organic overshoot)
- All 9 popup sizers animate with unified OutBack feel
- Notch cWidth syncs with dashboard sizer (same OutBack easing)
- TabSwitcher tabs scale 1.04x on hover with OutBack
- IconBtn: scale 1.08x hover / 0.92x press with OutBack

## IPC & Keybind System

### Pipe Reader Optimization
- Old: while true; cat pipe; done (fork per keypress)
- New: while IFS= read -r line; done < pipe (persistent, zero fork)
- Latency: ~50ms→~1ms per keypress

### Missing Command Handlers
- Added _toggleNetwork() helper + cases: wifi-toggle, bt-toggle, vpn-toggle, hotspot-toggle
- All 4 network tab toggles now work via keybinds

### HyprlandSyncService
- Debounce: 1000ms→150ms, initTimer: 3000ms→500ms
- Auto-reload after sync (200ms delay for file write)
- Direct Connections{target: KeybindService} (no 5s timer)
- saveAndReload() only saves (sync handles reload, no race)

## Dashboard Fixes

### Black Gap Elimination
- clip:false + flareHeight: Theme.notchHeight (40px)
- PopupShape flare extends into notch area (was clipped at y=0)
- Dashboard appears to grow FROM inside the notch

### First-Click Dead Zone
- Reverted wantsFocus timer pattern (15ms delay broke interaction)
- Direct keyboardFocus binding: no timing hole

### QFont::setPointSize(0) Warnings
- Sizer close states: height 0→1px (invisible, but prevents font calc at 0)
- Applied to ClipboardPopup, NetworkPopup, WallpaperPopup

## Video Wallpaper

### VP9→H.264 Transcoding (Intel GPU)
- VP9 has no VAAPI decode on Intel → every frame was CPU-decoded
- VideoWallpaperService always outputs H.264 MP4 cache
- needsTranscode() API checks source codec
- Wallpaper.qml blocks original VP9 playback during cache generation
- Preview in WallpaperPopup uses cached H.264, not original VP9
- ffmpeg: -hwaccel none (suppresses VAAPI/Vulkan error spam)

### Grow-From-Below Transition (creator's vision)
- Theme.background curtain covers old wallpaper
- Shrinks upward revealing new wallpaper from bottom
- OutQuart easing, works with all media types

### Two-Click Wallpaper Behavior (creator's vision)
- First click: select/preview
- Second click: apply and close

## Performance

### Adaptive System Timers
- Dashboard open: normal speed (1-2s polling)
- Dashboard closed: reduced (5-8s polling)
- CpuService, MemService, NetService, CpuFreqService, ThermalService, GpuService

### Battery Desktop Detection
- visible: bat.ready && bat.isLaptopBattery
- Auto-hides on desktop, collapses spacing in bar
- implicitWidth/Height → 0 when invisible

### Desktop Bar Gap
- rNotchMinWidth: 200→160 (matches content without battery)

## Fixes
- PopupSlide: added missing import '../theme' (Anim reference)
- qmldir load order: FMath→Anim→Theme→Colors→Metrics (dependency chain)
- NotificationsPopup: duplicate id fix (ShellPopupBase + NotificationList)
- Theme.animDuration added as single tuning point (280ms)
- WallpaperPopup: preview video uses cached H.264 path
- Various brace/id corrections after batch shellpopupbase application
- Fix pipe reader dying after first message by wrapping read loop in
  infinite while-true so it reopens the FIFO on EOF instead of exiting
- Fix send_ipc to use qs ipc as primary (more reliable) and fall back
  to the named pipe only when qs is unavailable
- Align target names across HyprlandSyncService, IpcManager, and CLI:
  bt-toggle -> bluetooth-toggle
  notifications-toggle -> notification-toggle
- Give each audio tab its own CLI command (audioOut-toggle,
  audioIn-toggle, audioMix-toggle) so the correct tab opens instead
  of all three binds opening the output tab
- Add missing IPC_MAP entries for bluetooth-toggle, notification-toggle,
  and the three audio tab targets
…ding

- Replace grow-from-below curtain transition with proper snapshot crossfade:
  ShaderEffectSource freezes the old wallpaper frame, then crossfades it
  out (opacity 1→0 over 500ms) while the new wallpaper loads underneath.
  Works seamlessly across all media types (static, GIF, video).

- Fix animated video wallpapers sometimes not loading: the Video source
  binding now falls back to the original path while waiting for the
  transcoded cache instead of returning an empty source. The
  _waitingForCache flag is properly set/cleared during cache resolution.

- Add content-ready detection so crossfade waits for the new wallpaper
  to finish loading (Image.Ready / AnimatedImage.Ready / Video Loaded)
  before starting the transition. A 2s timeout ensures the transition
  completes even if content detection misses the event.

- Remove unused curtain transition code.
…rmats

Two root causes fixed:

1. Race condition in snapshot crossfade: Qt.callLater could execute
   _performSwap before the ShaderEffectSource finished capturing the
   old frame. Now uses a 50ms frame-delay Timer to guarantee the
   snapshot is rendered before the wallpaper swap underneath.

2. Stale content-ready detection: the readonly _contentReady binding
   would return true from the PREVIOUS media type's status (e.g.
   videoPlayer still Playing when switching to an image). Replaced
   with explicit Connections on each media element's onStatusChanged
   that check _expectedPath matches the current type before signaling
   ready. Added _resetMediaState() to clear sources of unused media
   elements so their status resets to Null/Loading.

Also: crossfade in-progress transitions now queue the incoming path
instead of dropping it, ensuring rapid wallpaper changes don't leave
a stale snapshot visible.
Replace the three separate always-present media elements (Image,
AnimatedImage, Video) that caused stale-state bugs when switching
between formats with a Loader-based architecture:

- wallImageContainer holds the current wallpaper path as 'source'
- wallImageLoader picks the right component (staticImageComponent
  for images, videoComponent for GIFs/videos) based on file type
- On type change the Loader destroys the old component and creates
  a fresh one — no stale bindings, no source-clearing races
- Binding + Connections keep sourceFile synced to the loaded item
- Scale+opacity pulse transition on wallpaper change (from NothingLess)
- GIF and video share the videoComponent wrapper which delegates to
  gifPlayerComp or videoPlayerComp sub-loaders
- Idle-based pause/resume preserved for animated content
- VideoWallpaperService cache support preserved
…views

- Replace pulse animation with proper two-layer crossfade system
  (layerA/layerB alternate, old fades out while new fades in with
  subtle zoom reveal via Easing.OutBack)

- Signal-driven readiness detection instead of blind polling:
  staticImageComponent, gifPlayerComp, and videoPlayerComp each
  emit contentReady() when the actual media is decoded and ready
  to display (Image.Ready, AnimatedImage.Ready, or Video Loaded/
  Buffered). A 2.5s safety timeout forces the crossfade if the
  signal never fires.

- Fix video-to-video and gif-to-gif transitions that previously
  loaded abruptly — the crossfade now waits for the inner Video/
  AnimatedImage element to be truly ready before animating.

- Use polling Timer (60ms) for Video readiness since onStatusChanged
  is unavailable on this QtMultimedia/Quickshell Video type.

- WallpaperPopup: remove live Video/AnimatedImage preview decoders
  (heavy GPU cost). All preview cards now use static JPEG thumbnails
  only, sourceSize reduced 512→256, cardContent set to opacity:0
  (single render via MultiEffect mask), removed redundant background
  Rectangle and QtMultimedia import.

- WallpaperPopup: fix rounded-corner mask edges — maskThresholdMin
  0.5→0.4, maskSpreadAtMin 1.0→0.0 for crisp corners matching the
  border frame (radius 10).

- Thumbnail generation: --size 400→256, JPEG quality 85→80, add
  -strip to remove metadata for smaller file sizes.
…and rendering optimizations

- feat(wallpaper): instant wallpaper apply with background color extraction
- feat(wallpaper): two-layer crossfade transitions with GPU-optimized caching
- feat(wallpaper): deterministic thumbnail paths using proxy directory structure
- feat(wallpaper): subfolder scanning, directory auto-refresh, and fallback wallpapers
- feat(wallpaper): lockscreen frame generation for video/GIF wallpapers
- perf(shell): add UseQApplication, NativeTextRendering, DropExpensiveFonts pragmas
- perf(render): GPU caching on Speedometer Canvas
- perf(theme): remove redundant 3s ColorLoader poll timer
- refactor(wallpaper): simplify WallpaperPopup card delegate and PopupLayer imports
- perf(ipc): reduce pipe check from 1s to 30s fallback after startup
- perf(services): tie QuickSettings/QuickControl polls to dashboard visibility
- perf(services): slow system poll intervals to 30-60s when dashboard closed
- perf(network): reduce status poll to 30s when popup closed
- fix(video): restore sync getEffectivePath, remove broken async callback queue
- fix(installer): remove awww from AUR deps and hyprland autostart blocks
- fix(installer): remove duplicate hyprland config block handled by cli.sh
- style(anim): replace OutBack with OutCubic across all popup and bar animations
- perf(render): GPU caching and pixel rounding on SeamlessBar, Border, RoundCorner
- perf(render): GPU caching on ClockCard timer canvas
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant