* fix: temporary Lua dispatcher compat for workspace dispatchers
* fix(resizer): add Lua dispatcher compat for window resize/move/float/center
* feat(theme): write current.lua for Hyprland Lua config, current.conf for hyprlang
* fix: align gen_lua format with #111
* refactor address review feedback
refactor(hypr,theme): address review feedback
- cache is_lua_config result to avoid redundant socket calls
- remove is_lua_config wrapper, rename _is_lua_config to is_lua_config
- move hypr import to top of theme.py
- use single line syntax in apply_hypr and apply_colours
* restore original specialws behavior and some formatting
* theme: allow overriding Qt icon theme via cli.json
Papirus colors XDG special folders (Downloads, Pictures, Music, etc.)
differently from regular ones - they end up a different color while
everything else stays neutral. With themes like breeze-dark, all folder
icons share the same style, so everything looks consistent.
Add optional `iconTheme` field to the `theme` section of cli.json.
When set, it replaces the Papirus icon theme in the generated qtengine
config with the specified theme.
Example usage in cli.json:
"theme": { "iconTheme": "breeze-dark" }
* theme: allow overriding Qt and GTK icon theme via cli.json
Some folders in Dolphin end up with Papirus-style icons while others
use the default theme icons, resulting in two different icon styles
mixed together in the same view. Dolphin's default folder icons take
their color directly from the active color scheme, so they always match
the theme exactly - Papirus has a fixed, limited palette and does not
always match.
Add optional iconThemeDark and iconThemeLight fields to the theme
section of cli.json. When set, they override the Papirus icon theme in
both the generated qtengine config and the GTK dconf setting. A generic
iconTheme field is also supported as a fallback for both modes.
Example usage in cli.json:
"theme": { "iconThemeDark": "breeze-dark", "iconThemeLight": "breeze" }
---------
Co-authored-by: Foxlike Creature <safonovkirill113@gmail.com>
* theme: add live theming for chromium-based browsers
Writes the surface colour as an RGB triplet to chromium.theme and
applies it as a managed browser policy for chromium, brave, and
google-chrome-stable using the --refresh-platform-policy flag
(introduced in Chrome 142+).
Also fixes write_file to set 0644 permissions so browser processes
can read the policy files.
* feat: use sudo tee not chmod
* chore: update readme
---------
Co-authored-by: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>
- Add Zed theme template (zed.json) with full Material You syntax
highlighting, UI colors, and terminal ANSI palette
- Apply theme via file overwrite instead of restarting Zed, so
Zed's file watcher picks up changes automatically
- Resolve symlinks in apply_zed() only before writing, since
Zed's file watcher does not detect changes through symlinks
(other themed apps that rely on symlinks are unaffected)
LSP was screaming at me so I decided to just address it to get it off my
screen.
+ Fixed the type hints
:= Modified and added type hints for certain functions and variables in
most of the files in the utils/ folder (and some in the subcommands/
folder) for clarity and so pyright's type checker wouldn't cry.
:+ To resolve certain type issues, I had to add a bit more tiny
additional code such as, additional checks if a variable is None, a tiny
class in utils/material/generator.py to resolve the constructor usage
mismatch between what the DynamicScheme accepts and what the code
actually passes, and etc.
- Renamed certain functions and variables for clarity and also for some
to not collide with pre-existing definitions from well-known library
imports.
+ PIL has reorganized their code a bit, so the code is made to reflect
their new definitions.
= Reorganized the single import statement for "colourfulness" in
utils/wallpaper.py to be close to the top.
(I think that's it)
Side Effects?:
Everything should work the same as no logic change was done whatsover
(unless we consider the added if statements for type checking as a logic
change). I've tested it, everything seems to be in urdir.
* feat: add GIF files support as wallpaper (not animated tho)
* tweak: simplifying variable use
* fix: git is good but damn it's annoying
* fix
---------
Co-authored-by: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>
* feat: GTK app theming system
- Implemented custom.css import for user-managed app themes
- process_app_themes() to dynamically update colors in imported CSS files
- Inline comment markers for color replacement (e.g, /* accent-color */)
- Papirus icon color syncing with weighted hue/saturation algorithm
This allows users to create modular app themes that automatically update when the scheme/wallpaper changes
Example usage:
.app .element { color: #24BD5C; /* accent-color */ }
.app .element:hover { background: rgba(36, 189, 92, 0.15); /* accent-color with 15% opacity */ }
* feat: atomic theme changes with locking and mode-specific CSS
- Implemented locking to prevent concurrent theme changes
- Added mode-light/mode-dark CSS markers for dynamic property reordering
- Made terminal writes and Papirus sync non-blocking to prevent hangs
- Only save scheme.json after successful theme application
Fixes race conditions during rapid theme switching and ensures Shell and GTK apps scheme stay in sync.
* theme: added to color mapping for custom theming, new schemes
* theme: quick fixes, cleanup
* theme: include thunar.css as template, with new theming system
* theme: modified GTK theming approach
- Dropped comment targeted theming in favor for existing {{ }} replacement
- [app].css.template file created for customization, bypassing built in default if present
- Handling *.template for added templates to be parsed and added to import
* theme: fixes for thunar.css
* theme: remove .template file use
* theme: path button color adjustment, non-active hover
* fixes & cleanup
* thunar css fixes
* more css fixes
* format
* fix tab vert spacing
---------
Co-authored-by: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>
* theme: apply_user_templates accepts mode.
* Some themes like those in NvChad require a mode to be supplied to
work. Added a minimal change that makes apply_user_templates accept a
mode parameter and replaces any {{ mode }} placeholder in a file with
the actual mode.
* theme: mode replace integrated with gen_replace_dynamic
+ Moved the {{ mode }} replacement logic to the gen_replace_dynamic
function.
* refactor: adjusted comment
* feat: add wallpaper post-hook for dynamic theming
Adds support for running custom shell commands after wallpaper changes
via the `wallpaper.postHook` config option in `~/.config/caelestia/cli.json`.
The wallpaper path is made available to the hook via the $WALLPAPER_PATH
environment variable. This enables integration with tools like `matugen`
or `pywal` for dynamic theming based on wallpaper colors.
The hook runs after apply_colours() in set_wallpaper(), ensuring it
executes for all wallpaper change methods (UI, IPC, and direct CLI).
* Replaced comment in example config with no-op command
* fix(recording): Fix wf-recorder audio flag and improve process monitoring
- Fix incorrect audio flag format for wf-recorder(Invalid whitespace)
Changed from `-a <device>` to `--audio=<device>` as per wf-recorder docs:
"Specify device like this: -a<device> or --audio=<device>"
- Add fallback to IDLE audio sources
Audio sources are typically in IDLE state when no media is playing.
Now falls back to IDLE sources if no RUNNING sources are found,
ensuring audio capture works when recording starts during silence
but media plays later.
- Improve process startup monitoring
The 0.1s sleep was insufficient for reliable process detection on NVIDIA systems.
Process would start and immediately die ~90% of the time when triggered via keybinds.
Now shows immediate UI feedback then monitors for 3 seconds to ensure
stable process startup while maintaining responsive user experience.
* check returncode + timeout 3s -> 1s + format
---------
Co-authored-by: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>
Previously, the start() function always invoked 'wl-screenrec' regardless of detected GPU, which prevented recording on systems with NVIDIA GPUswhen 'wf-recorder' is available.
This change updates start() to launch the recorder stored in
self.recorder, ensuring the correct recorder is used based on GPU detection.
* resizer: add window resizer daemon command
Implements a continuous window resizer daemon that automatically resizes
windows based on configurable rules. Features include:
- Listens to Hyprland socket events for real-time window detection
- Supports multiple match types: initial_title, title_contains, title_exact
- Configurable via CLI config file with fallback to sensible defaults
- Rate limiting to prevent excessive resize operations
- Window actions: float, center, and custom dimensions
- Integration with existing CLI structure
Usage: caelestia resizer --daemon
* refactor: replace pip daemon with integrated resizer functionality
## Summary
- Remove standalone pip daemon and integrate its functionality into the resizer
- Add regex matching, config support, and active mode to resizer
- Implement clean 'caelestia resizer pip' command for quick PiP operations
- Update keybinds to use new unified resizer command
## Why Replace the Old PiP Method?
### 1. Code Duplication
The old pip daemon duplicated window management logic that already existed in the resizer:
- Both daemons listened to Hyprland socket events
- Both had similar window detection and manipulation code
- Both needed rate limiting and error handling
### 2. Limited Functionality
The old pip daemon was restricted:
- Only worked with regex pattern matching for 'Picture in Picture' titles
- No configuration support for custom rules
- No way to apply PiP to arbitrary windows
- No integration with other window actions
### 3. Maintenance Overhead
Having two separate daemons created maintenance issues:
- Two different codebases to maintain and debug
- Potential conflicts when both daemons run simultaneously
- Inconsistent error handling and logging approaches
### 4. Review Feedback Implementation
The PR review specifically requested this consolidation:
- "This can actually probably replace the pip daemon entirely"
- "consider adding a regex match mode and pip action, then add that to the default rules"
## New Integrated Approach Benefits
### 1. Unified Window Management
- Single daemon handles all window operations (resize, float, center, pip)
- Consistent configuration format using camelCase
- Shared error handling and rate limiting
### 2. Enhanced PiP Functionality
- Works with any window title pattern (regex, contains, exact)
- Configurable through CLI config file
- Active mode: `caelestia resizer pip` for quick PiP on current window
- Better error messages and user guidance
### 3. Future-Proof Architecture
- Easy to add new window actions (e.g., minimize, maximize, workspace move)
- Extensible pattern matching (could add class-based matching)
- Single place to implement new Hyprland features
### 4. Improved User Experience
- Simpler command structure: `caelestia resizer pip` vs complex arguments
- Better error messages when windows aren't floating
- Consistent CLI interface across all window operations
## Implementation Details
- Added pip action to WindowRule system
- Integrated original pip calculation with minimum size constraints
- Added type safety improvements throughout
- Maintained backward compatibility for existing users
- Updated keybind: `bind = $kbWindowPip, exec, caelestia resizer pip`
* fix: unpack dispatch_commands list in hypr.batch call
- Fix 'sequence item 0: expected str instance, list found' error
- hypr.batch() expects individual string arguments, not a list
- Use *dispatch_commands to unpack the list properly
* fix: handle Hyprland event format with triple > separators
- Fix window ID parsing for events with >>> instead of >>
- Add .lstrip('>') to remove any leading > characters
- Support both >> and >>> formats for compatibility
- Fixes 'Invalid window ID format: >555ee935ba30' errors
* resizer: implement active mode for all matching windows
Active mode now searches through all open windows and applies the rule to
any that match the specified pattern, rather than just checking if the
currently active window matches. This allows for batch operations on
multiple windows with the same pattern.
Special case: using pattern "active" will still target only the currently
active window, allowing users to apply rules to just the focused window
when needed.
This addresses the latest review feedback requesting that active mode work
on any open window that matches the given pattern.
* parser: better resizer help
* completions: add for resizer
---------
Co-authored-by: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>
* templates: add nvtop, htop, and cava support
* Triggers htop and cava theme reloads
Sends a USR2 signal to htop and cava after their themes are applied. This prompts the applications to reload their configuration files, ensuring new themes are visible instantly without requiring a manual restart.