aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--CHANGELOG.md217
-rw-r--r--README.md11
-rw-r--r--config/fastfetch/config-compact.jsonc105
-rw-r--r--config/fastfetch/config.jsonc256
-rw-r--r--config/ghostty/config1
-rw-r--r--config/hypr/.luarc.json9
-rw-r--r--config/hypr/Monitor_Profiles/HDMI-A-1-HighRefreshRate.conf11
-rw-r--r--config/hypr/Monitor_Profiles/HDMI-A-1-HighRefreshRate.lua15
-rw-r--r--config/hypr/Monitor_Profiles/README9
-rw-r--r--config/hypr/Monitor_Profiles/Virtual-1-1920x1080.conf11
-rw-r--r--config/hypr/Monitor_Profiles/Virtual-1-1920x1080.lua15
-rw-r--r--config/hypr/Monitor_Profiles/Virtual-1-2560x1080.conf11
-rw-r--r--config/hypr/Monitor_Profiles/Virtual-1-2560x1080.lua15
-rw-r--r--config/hypr/Monitor_Profiles/default.lua32
-rw-r--r--config/hypr/Monitor_Profiles/eDP-1-disable.conf4
-rw-r--r--config/hypr/Monitor_Profiles/eDP-1-disable.lua13
-rw-r--r--config/hypr/UserConfigs/01-UserDefaults.conf7
-rw-r--r--config/hypr/UserConfigs/ENVariables.conf2
-rw-r--r--config/hypr/UserConfigs/LayerRules.conf14
-rw-r--r--config/hypr/UserConfigs/UserDecorations.conf6
-rw-r--r--config/hypr/UserConfigs/UserKeybinds.conf16
-rw-r--r--config/hypr/UserConfigs/WindowRules.conf7
-rw-r--r--config/hypr/UserConfigs/monitors.lua18
-rw-r--r--config/hypr/UserConfigs/user_decorations.lua106
-rw-r--r--config/hypr/UserConfigs/user_keybinds.lua40
-rwxr-xr-xconfig/hypr/UserScripts/WallpaperAutoChange.sh13
-rwxr-xr-xconfig/hypr/UserScripts/WallpaperEffects.sh42
-rwxr-xr-xconfig/hypr/UserScripts/WallpaperRandom.sh15
-rwxr-xr-xconfig/hypr/UserScripts/WallpaperSelect.sh21
-rwxr-xr-xconfig/hypr/UserScripts/WeatherWrap.sh6
-rw-r--r--config/hypr/configs/ENVariables.conf4
-rw-r--r--config/hypr/configs/Keybinds.conf298
-rw-r--r--config/hypr/configs/LayerRules.conf26
-rw-r--r--config/hypr/configs/Startup_Apps.conf14
-rw-r--r--config/hypr/configs/Startup_Apps.disable1
-rw-r--r--config/hypr/configs/SystemSettings.conf28
-rw-r--r--config/hypr/configs/WindowRules-config-v3.conf470
-rw-r--r--config/hypr/configs/WindowRules-pre-53.conf234
-rw-r--r--config/hypr/configs/WindowRules.conf151
-rw-r--r--config/hypr/hl.meta.lua1252
-rw-r--r--config/hypr/hyprland.conf6
-rw-r--r--config/hypr/hyprland.lua.disable25
-rw-r--r--config/hypr/hyprlock-1080p.conf182
-rw-r--r--config/hypr/hyprlock-2k.conf72
-rw-r--r--config/hypr/hyprlock.conf182
-rwxr-xr-xconfig/hypr/initial-boot.sh55
-rw-r--r--config/hypr/lua/animations.lua33
-rw-r--r--config/hypr/lua/decorations.lua64
-rw-r--r--config/hypr/lua/env.lua37
-rw-r--r--config/hypr/lua/keybind_helpers.lua355
-rw-r--r--config/hypr/lua/keybinds.lua648
-rw-r--r--config/hypr/lua/laptop-lid.lua22
-rw-r--r--config/hypr/lua/laptops.lua14
-rw-r--r--config/hypr/lua/layer_rules.lua88
-rw-r--r--config/hypr/lua/monitors.lua46
-rw-r--r--config/hypr/lua/screenshot-region.lua13
-rw-r--r--config/hypr/lua/settings.lua179
-rw-r--r--config/hypr/lua/startup.lua71
-rw-r--r--config/hypr/lua/user_decorations_helper.lua28
-rw-r--r--config/hypr/lua/user_defaults.lua33
-rw-r--r--config/hypr/lua/user_keybinds_helper.lua217
-rw-r--r--config/hypr/lua/user_layer_rules_helper.lua16
-rw-r--r--config/hypr/lua/user_overrides.lua156
-rw-r--r--config/hypr/lua/user_startup_helper.lua34
-rw-r--r--config/hypr/lua/user_window_rules_helper.lua16
-rw-r--r--config/hypr/lua/window_rules.lua1110
-rw-r--r--config/hypr/lua/workspaces.lua12
-rwxr-xr-xconfig/hypr/scripts/ChangeLayout.sh120
-rwxr-xr-xconfig/hypr/scripts/DisableWaybarService.sh265
-rwxr-xr-xconfig/hypr/scripts/Dropterminal.sh630
-rwxr-xr-xconfig/hypr/scripts/ExternalBrightness.sh304
-rwxr-xr-xconfig/hypr/scripts/Float-all-Windows.sh25
-rwxr-xr-xconfig/hypr/scripts/GameMode.sh96
-rwxr-xr-xconfig/hypr/scripts/Ghostty_themes.sh120
-rwxr-xr-xconfig/hypr/scripts/HyprLayoutModule.sh131
-rwxr-xr-xconfig/hypr/scripts/JavaManager.sh245
-rwxr-xr-xconfig/hypr/scripts/KeyBinds.sh39
-rwxr-xr-xconfig/hypr/scripts/KeybindsLayoutInit.sh7
-rwxr-xr-xconfig/hypr/scripts/Kitty_themes.sh67
-rwxr-xr-xconfig/hypr/scripts/Kool_Quick_Settings.sh158
-rwxr-xr-xconfig/hypr/scripts/Logout.sh180
-rwxr-xr-xconfig/hypr/scripts/LuaAutoReload.sh47
-rwxr-xr-xconfig/hypr/scripts/LuaCycleWindow.sh73
-rwxr-xr-xconfig/hypr/scripts/LuaFocusWorkspaceRelative.sh44
-rwxr-xr-xconfig/hypr/scripts/LuaFullscreenMaximized.sh11
-rwxr-xr-xconfig/hypr/scripts/LuaMoveWindowDirectional.sh51
-rwxr-xr-xconfig/hypr/scripts/LuaMoveWindowWorkspaceRelative.sh51
-rwxr-xr-xconfig/hypr/scripts/LuaSwapWindow.sh56
-rwxr-xr-xconfig/hypr/scripts/MonitorProfiles.sh53
-rwxr-xr-xconfig/hypr/scripts/OverviewToggle.sh17
-rwxr-xr-xconfig/hypr/scripts/Polkit-Diag.sh102
-rwxr-xr-xconfig/hypr/scripts/PortalHyprland.sh21
-rwxr-xr-xconfig/hypr/scripts/Refresh.sh39
-rwxr-xr-xconfig/hypr/scripts/ResizeActive.sh21
-rwxr-xr-xconfig/hypr/scripts/Tak0-Autodispatch.sh69
-rwxr-xr-xconfig/hypr/scripts/Tak0-Per-Window-Switch.sh105
-rwxr-xr-xconfig/hypr/scripts/ThemeChanger.sh156
-rwxr-xr-xconfig/hypr/scripts/Toggle-Active-Window-Audio.sh19
-rwxr-xr-xconfig/hypr/scripts/WallpaperCmd.sh91
-rwxr-xr-xconfig/hypr/scripts/WallpaperDaemon.sh10
-rwxr-xr-xconfig/hypr/scripts/WallustConfig.sh46
-rwxr-xr-xconfig/hypr/scripts/WallustSwww.sh158
-rwxr-xr-xconfig/hypr/scripts/WaybarStartup.sh88
-rwxr-xr-xconfig/hypr/scripts/keybinds_parser.py270
-rwxr-xr-xconfig/hypr/scripts/update_WindowRules.sh14
-rw-r--r--config/hypr/v2.3.235
-rw-r--r--config/hypr/v2.3.240
-rw-r--r--config/kitty/kitty.conf2
-rw-r--r--config/rofi/0-shared-fonts.rasi4
-rw-r--r--config/rofi/config.rasi12
-rw-r--r--config/rofi/dwm-config-horiz.rasi1
-rw-r--r--config/rofi/dwm-config-vert.rasi1
-rw-r--r--config/rofi/themes/KooL_dwm.rasi1
-rwxr-xr-xconfig/swaync/config.json2
-rw-r--r--config/wallust/templates/colors-cava4
-rw-r--r--config/wallust/templates/colors-ghostty.conf2
-rw-r--r--config/wallust/wallust-kitty-v4.toml13
-rw-r--r--config/wallust/wallust-v4.toml53
-rw-r--r--config/waybar/Modules12
-rw-r--r--config/waybar/ModulesCustom17
-rw-r--r--config/waybar/configs/BOT-&-Left-SouthWest3
-rw-r--r--config/waybar/configs/BOT-&-Right-SouthEast3
-rw-r--r--config/waybar/configs/BOT-Camellia3
-rw-r--r--config/waybar/configs/BOT-Chrysanthemum3
-rw-r--r--config/waybar/configs/BOT-Default4
-rw-r--r--config/waybar/configs/BOT-Default-Laptop4
-rw-r--r--config/waybar/configs/BOT-Gardenia3
-rw-r--r--config/waybar/configs/BOT-Peony3
-rw-r--r--config/waybar/configs/BOT-Simple3
-rw-r--r--config/waybar/configs/BOT-Sleek3
-rw-r--r--config/waybar/configs/LEFT-WestWing3
-rw-r--r--config/waybar/configs/LEFT-WestWing-v23
-rw-r--r--config/waybar/configs/RIGHT-EastWing3
-rw-r--r--config/waybar/configs/RIGHT-EastWing-v23
-rw-r--r--config/waybar/configs/TOP-&-BOT-SummitSplit3
-rw-r--r--config/waybar/configs/TOP-&-BOT-SummitSplit-glass3
-rw-r--r--config/waybar/configs/TOP-&-BOT-SummitSplit-v23
-rw-r--r--config/waybar/configs/TOP-&-BOT-SummitSplit-v33
-rw-r--r--config/waybar/configs/TOP-&-Left-NorthWest3
-rw-r--r--config/waybar/configs/TOP-&-Right-NorthEast3
-rw-r--r--config/waybar/configs/TOP-0-Ja-03
-rw-r--r--config/waybar/configs/TOP-Arrow3
-rw-r--r--config/waybar/configs/TOP-Camellia3
-rw-r--r--config/waybar/configs/TOP-Chrysanthemum3
-rw-r--r--config/waybar/configs/TOP-Default2
-rw-r--r--config/waybar/configs/TOP-Default-Laptop2
-rw-r--r--config/waybar/configs/TOP-Default-Laptop-glass2
-rw-r--r--config/waybar/configs/TOP-Default-Laptop-old-v13
-rw-r--r--config/waybar/configs/TOP-Default-Laptop-old-v23
-rw-r--r--config/waybar/configs/TOP-Default-Laptop-old-v33
-rw-r--r--config/waybar/configs/TOP-Default-Laptop-old-v43
-rw-r--r--config/waybar/configs/TOP-Default-Laptop-old-v52
-rw-r--r--config/waybar/configs/TOP-Default-old-v13
-rw-r--r--config/waybar/configs/TOP-Default-old-v23
-rw-r--r--config/waybar/configs/TOP-Default-old-v33
-rw-r--r--config/waybar/configs/TOP-Default-old-v43
-rw-r--r--config/waybar/configs/TOP-Everforest3
-rw-r--r--config/waybar/configs/TOP-Everforest-glass3
-rw-r--r--config/waybar/configs/TOP-Gardenia3
-rw-r--r--config/waybar/configs/TOP-Minimal-Long3
-rw-r--r--config/waybar/configs/TOP-Minimal-Short3
-rw-r--r--config/waybar/configs/TOP-Peony3
-rw-r--r--config/waybar/configs/TOP-Simple3
-rw-r--r--config/waybar/configs/TOP-Simpliest3
-rw-r--r--config/waybar/configs/TOP-Sleek3
-rw-r--r--config/waybar/configs/TOP-ddubs-simple-bar1
-rw-r--r--config/waybar/configs/[TOP & BOT] SummitSplit v33
-rw-r--r--config/waybar/style/0-VERTICAL-Catpuccin-Mocha.css25
-rw-r--r--config/waybar/style/0-VERTICAL-Golden-Noir.css27
-rw-r--r--config/waybar/style/0-VERTICAL-Oglo-Chicklets.css27
-rw-r--r--config/waybar/style/Black-&-White-Monochrome.css27
-rw-r--r--config/waybar/style/Catppuccin-Frappe.css27
-rw-r--r--config/waybar/style/Catppuccin-Latte.css25
-rw-r--r--config/waybar/style/Catppuccin-Mocha.css27
-rw-r--r--config/waybar/style/Colored-Chroma-Glow.css25
-rw-r--r--config/waybar/style/Colored-Translucent.css25
-rw-r--r--config/waybar/style/Colorful-Aurora-Blossom.css25
-rw-r--r--config/waybar/style/Colorful-Aurora.css27
-rw-r--r--config/waybar/style/Colorful-Oglo-Chicklets.css25
-rw-r--r--config/waybar/style/Colorful-Rainbow-Spectrum.css25
-rw-r--r--config/waybar/style/Colorful-stolen-style.css25
-rw-r--r--config/waybar/style/Crystal-Clear-Glass.css25
-rw-r--r--config/waybar/style/Dark-Golden-Eclipse.css24
-rw-r--r--config/waybar/style/Dark-Golden-Noir.css27
-rw-r--r--config/waybar/style/Dark-Half-Moon.css27
-rw-r--r--config/waybar/style/Dark-Latte-Wallust-combined-v2.css25
-rw-r--r--config/waybar/style/Dark-Latte-Wallust-combined.css25
-rw-r--r--config/waybar/style/Dark-Purpl.css27
-rw-r--r--config/waybar/style/Dark-Wallust-Obsidian-Edge.css27
-rw-r--r--config/waybar/style/Extra-Arrow.css25
-rw-r--r--config/waybar/style/Extra-Crimson.css27
-rw-r--r--config/waybar/style/Extra-EverForest.css27
-rw-r--r--config/waybar/style/Extra-ML4W-starter.css24
-rw-r--r--config/waybar/style/Extra-Mauve.css25
-rw-r--r--config/waybar/style/Extra-Modern-Combined-Transparent.css83
-rw-r--r--config/waybar/style/Extra-Modern-Combined.css59
-rw-r--r--config/waybar/style/Extra-Neon-Circuit.css110
-rw-r--r--config/waybar/style/Extra-Prismatic-Glow.css27
-rw-r--r--config/waybar/style/Extra-Rose-Pine.css25
-rw-r--r--config/waybar/style/Extra-Simple-Pink.css27
-rw-r--r--config/waybar/style/Light-Monochrome-Contrast.css25
-rw-r--r--config/waybar/style/Light-Obsidian-Glow.css27
-rw-r--r--config/waybar/style/ML4W-Glass-3d.css25
-rw-r--r--config/waybar/style/ML4W-Glass.css25
-rw-r--r--config/waybar/style/ML4W/glass.css24
-rw-r--r--config/waybar/style/Rainbow-RGB-Bordered.css27
-rw-r--r--config/waybar/style/Retro-Simple-Style.css27
-rw-r--r--config/waybar/style/Transparent-Crystal-Clear.css27
-rw-r--r--config/waybar/style/VERTICAL-Catpuccin-Mocha.css25
-rw-r--r--config/waybar/style/Wallust-Bordered-Chroma-Fusion-Edge.css23
-rw-r--r--config/waybar/style/Wallust-Bordered-Chroma-Simple.css25
-rw-r--r--config/waybar/style/Wallust-Box-type.css62
-rw-r--r--config/waybar/style/Wallust-Chroma-Edge.css39
-rw-r--r--config/waybar/style/Wallust-Chroma-Fusion.css40
-rw-r--r--config/waybar/style/Wallust-Chroma-Tally-V2.css25
-rw-r--r--config/waybar/style/Wallust-Chroma-Tally.css25
-rw-r--r--config/waybar/style/Wallust-Colored.css27
-rw-r--r--config/waybar/style/Wallust-ML4W-modern-mixed.css27
-rw-r--r--config/waybar/style/Wallust-ML4W-modern.css27
-rw-r--r--config/waybar/style/Wallust-Simple.css27
-rw-r--r--config/waybar/style/Wallust-Transparent-Crystal-Clear.css27
-rw-r--r--config/waybar/style/catppuccin-themes/frappe.css24
-rw-r--r--config/waybar/style/catppuccin-themes/latte.css24
-rw-r--r--config/waybar/style/catppuccin-themes/mocha.css23
-rw-r--r--config/waybar/style/catppuccin-themes/rgbmocha.css24
-rw-r--r--config/wezterm/wezterm.lua7
-rw-r--r--config/wlogout/layout2
-rw-r--r--config/yazi/flavors/catppuccin-macchiato.yazi/flavor.toml1204
-rw-r--r--config/yazi/init.lua168
-rw-r--r--config/yazi/keymap.toml99
-rw-r--r--config/yazi/package.toml37
-rw-r--r--config/yazi/plugins/compress.yazi/LICENSE21
-rw-r--r--config/yazi/plugins/compress.yazi/README.md152
-rw-r--r--config/yazi/plugins/compress.yazi/main.lua577
-rw-r--r--config/yazi/plugins/full-border.yazi/LICENSE21
-rw-r--r--config/yazi/plugins/full-border.yazi/README.md32
-rw-r--r--config/yazi/plugins/full-border.yazi/main.lua53
-rw-r--r--config/yazi/plugins/git.yazi/LICENSE21
-rw-r--r--config/yazi/plugins/git.yazi/README.md89
-rw-r--r--config/yazi/plugins/git.yazi/main.lua259
-rw-r--r--config/yazi/plugins/git.yazi/types.lua12
-rw-r--r--config/yazi/plugins/smart-filter.yazi/LICENSE21
-rw-r--r--config/yazi/plugins/smart-filter.yazi/README.md28
-rw-r--r--config/yazi/plugins/smart-filter.yazi/main.lua50
-rw-r--r--config/yazi/plugins/yatline-githead.yazi/LICENSE22
-rw-r--r--config/yazi/plugins/yatline-githead.yazi/README.md213
-rw-r--r--config/yazi/plugins/yatline-githead.yazi/main.lua569
-rw-r--r--config/yazi/plugins/yatline.yazi/LICENSE23
-rw-r--r--config/yazi/plugins/yatline.yazi/README.md23
-rw-r--r--config/yazi/plugins/yatline.yazi/main.lua1464
-rw-r--r--config/yazi/theme.toml3
-rw-r--r--config/yazi/yazi.toml88
-rwxr-xr-xcopy.sh7
-rw-r--r--docs/HOWTO-fix-ventoy-GUI.md1
-rwxr-xr-xscripts/fix-systemsettings-lua.sh229
-rw-r--r--scripts/lib_apps.sh66
-rw-r--r--scripts/lib_copy.sh116
-rwxr-xr-xscripts/migrate-hypr-to-lua.sh2212
-rwxr-xr-xwallpapers/3d-door.jpgbin0 -> 644427 bytes
-rw-r--r--wallpapers/Catppuccin-pond-bridge.jpgbin0 -> 963904 bytes
-rw-r--r--wallpapers/a_black_sand_beach_with_waves_and_clouds_above.jpgbin0 -> 1401572 bytes
-rw-r--r--wallpapers/a_group_of_wooden_posts_in_water.jpgbin0 -> 2503065 bytes
-rwxr-xr-xwallpapers/astralbed.pngbin0 -> 2693000 bytes
264 files changed, 18806 insertions, 2320 deletions
diff --git a/.gitignore b/.gitignore
index f85a9570..619fc948 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,3 +41,6 @@ htmlcov/
.vscode/
*.swp
*.swo
+
+# Copy-Logs
+Copy-Logs/
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7dbe95a8..9624a3a8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,216 @@
## v2.3.24
-- Created new development branch
+## Fixed:
+
+- `awww` default didn't work for wide screen monitors
+ - Default is to `resize --crop`
+ - Made wallpaper scripts monitor determinsitic
+ - Just overriding default won't work for non ultrawide screens
+ - Also add UserConfig override variabe to force default if needed
+ - Thanks to **CateDesu** for finding issue & correct parameters
+ - Found some corner cases and fixed them
+- After LUA migration
+ - Logout issues:
+ - logout stopped working
+ - Long delay 20s+ for logout when using SDDM
+ - Duplicate keybinds
+ - layout persistance code failed
+- `cava` colors reloaded dynamically with wallpaper change
+- Updated `initial-boot.sh` to set `prefer-dark `
+ - This will set flatpak apps to dark
+ - PortalHyprland now also has the ubuntu portal code
+- Added script `scripts/DisableWaybarService.sh`
+ - Some OS's / distros add a `waybar.service` to manage waybar
+ - This breaks theming and waybar restarts
+- `scripts/lib_copy.sh` wasn't preserving `UserConfigs` dir
+- Bad import path in `.config/waybar/style/ML4W/glass.css` file
+- Migration script didn't properly create the `system_settings.lua` file
+- Logout is NixOS.
+ - Added fallback if hyprshutdown not installed or fails
+ - Fixed pathing issues where not all logout options used`Logout.sh`
+- Removed sleep statments from startup to trim login time
+- Network icon on waybar invisible
+ - Changed the CSS files it's better but should revisit it
+- NixOS waybar issues:
+ - User waybar service enabled
+ - `install.sh` checks for and disables on install
+ - `Refresh.sh` now supports systemctl service as well
+ - On NixOS waybar startup is wrapped `Refresh.sh` handles that also
+- Parser for `UserConfigs` mistook border size 1 as as true/false value
+- `UserConfigs/user_decorations.lua` was not being imported correctly
+- My custom keybinds were included in defaults by mistake
+ - Removed from both .lua and .conf files
+- Theme by wallpaper and global theme
+ - Neither were updating waybar nor border colors
+ - Adjusted colors on style sheet `Wallust-Chrome-Fustion.css`
+ - Current workspace showed as single color blob
+- Migrate-hypr-to-lua to lua script
+ - Wasn't properly handling variables list `$scriptDir`
+- Sourcing of `UserConfig/user_keybinds.lua`
+- Duplicate import of keybinds
+ - was reading `lua/keybinds.lua` and `UserConfigs/configs`
+ - Udpated `Kool_Quick_Settings.sh`
+ - Only reads `configs` and `UserConfigs` dirs
+- MonitorProfile for `eDP-1-disable.lua` incorrect
+ - Changed to `disable = true`
+- `copy.sh`
+ - Didn't handle `hyprland.lua` properly
+ - Re-copied `*.conf` files when LUA enabled
+ - `monitors.lua` not copied to `UserConfigs` dir
+ - `MonitorProfiles.sh` wasn't set up for LUA configuration
+- `scrpts/migrate-hypr-to-lua.sh`
+ - It didn't convert `monitors.conf` nor `workspaces.conf`
+ - Impropved summary to show converted and what's left native
+ - I.e. `hyprlock.conf` and `hypridle.conf` still use `.conf`
+- `DropDownterminal`
+ - Created `silent-mode` for startup
+ - It now goes directly to specialworkspace
+ - Adding lua support broke legacy hyprlang
+ - Part Dos: Fixed the fix to work in lua workflow
+ - Part Tres: `DropDownterminal.sh` exited on hide not persisted
+- logout keybinding and logout from menu not working in LUA config
+- logic issue in migration script
+- Updated description for logout/exit keybinding
+ - It only said `exit` if you search for `logout` nothing is returned
+- Improved migration process to properly backup and move the .lua files
+ - `/.config/hypr/lua` are the pristine source files
+ - Migration script will convert the .conf files to .lua
+ - Them move the system configs to `.config/hypr/configs`
+ - Then move thhe user configs to `.config/hypr/UserConfigs`
+ - Preserving user changes on subsquent updates
+- `JavaManger.sh` field width cut off JDK version
+- `Tak0-Autodispatch.sh`
+ - Reworked code to support LUA config
+- `Tak0-Per-Window-Switch.sh`
+ - Had syntax error
+ - Added support for both Hyprlang and LUA configs
+- Incorrect XDGDATA dirs for flatpak
+- `Gamemode.sh`
+ - It supports both HYPRLANG and LUA configs
+- `Float-all-windows.sh`
+ - It works with HYPRLANG and LUA
+- `MonitorProfiles.sh` script to work with LUA or HYPRLANG
+ - Added additional profiles also
+ - Virtual-1 1920x1080
+ - Virtual-1 2560x1080
+ - HDMI-A-1 High Refresh Rate
+ - eDP-1 disable
+- Legacy import of `UserKeybinds.conf`
+- `Toggle-Active-Windown-Audio` script to work with LUA workflow
+- `layerrules` made menus look terrible
+- `OverviewToggle.sh` handling of quickshell vs. ags
+
+## Updated:
+
+- OpenSuse is not longer supported
+- Updated lua defaults to disable hyprland wallpaper at start
+- `ENVariables.conf` and `env.lua`
+- migration script to make/keep proper Window Rule names
+- LUA function to handle lid switch to enable/disable laptop display
+- Thank you `@star` on `TheBlackDons` Discord Server
+- keybind description for `hyprsunset` to include `hyprsunset`
+ - Makes it easier to find in keybind search tool
+- `ExternalBrightness.sh`
+ - Taken from code modified by `@RAH-iĐ905`
+ - Discovers montiors, and LUA compatible
+
+## Added:
+
+- `yazi` config to `copy.sh`
+- Waybar widget for layouts
+ - Shows current layout
+ - `D` for `dwindle`
+ - `S` for `scrolling`
+ - `M` for `Monocole` (Capital M)
+ - `m` for `master` (lowercase m in a circle)
+ - Click on icon brings up menu to select layout
+- Created helper lua modules for `UserConfigs` lua files
+ - `user_keybinds_helper.lua`
+ - `user_startup_helper.lua`
+ - `user_window_rules.lua`
+ - `user_layer_rules.lua`
+ - `user_decorations.lua`
+ - The removes the basic setup user lua files
+ - The generated `user_keybinds.lua` now only has the bindings config
+ - Removing all the setup code, functions, makes editing easier
+ - Also any updates to the user keybind code is done outside of `UserConfigs`
+ - `UserConfigs` dir is preserved on updates
+- `SUPERCTRL + G` for ghostty theme selector
+- Kitty theme selector to `Kool_Quick_Settings` to match entry for ghostty
+- `.luarc.jsonc` and `hl.meta.lua` (Thank you @Tony,btw) for the latter
+- This will get rid of `function not defined` errors in Editor LSP's that support LUA
+- And provide fuction info as well with properly configured editors
+- support for `$VISUAL` editor
+- Setting the env variable to your GUI editor will override `$EDITOR`
+- You can use `neovide`, `code/codium`. `geany`, `emacs` etc
+- Providing a richer environment, and faster.
+- Created a `keybind_helpers.lua` file
+ - Moved all the helper functions which should need to be edited
+ - This cleans up the `keybinds.lua` file to be more user friendly, easier editing
+- Edited `keybinds.lua` to make it easier to understand and edit
+ - Added a clear “User-editable bindings” header block.
+ - Grouped bindings with section labels:
+ - Application launchers and utility scripts
+ - Window/session controls
+ - Layout and tiling controls
+ - Audio/media/hardware keys
+ - Screenshot bindings
+ - Window resize/move/swap/grouping
+ - Workspace navigation/assignment
+ - Mouse drag/resize bindings
+- `Javamanger.sh`
+ - Manage Java runtime instances
+ - 1st pass, only tested for Arch
+ - Added code for other distros, needs testing
+- helper script `logout.sh` to call `hyprshutdown`
+ - Added pkill `waybar`, `awww-daemon`, and `swww-daemon` before `hyprshutdown`
+- menu option for `LayerRules` in Quick settings menu
+
+## Removed:
+
+- "-config-v3.conf" files for
+ - `WindowRules.conf/lua`
+ - `LayerRules.conf/lua`
+ - They are no longer needed
+- Hard-coded rofi terminal overrides in theme configs
+ - `themes/KooL_dwm.rasi`
+ - `dwm-config-horiz.rasi`
+ - `dwm-config-vert.rasi`
+- Thanks to [@TeaJhay](https://github.com/TeaJhay) for finding this
+
+## Misc:
+
+- Started planning changes to Wallust code to support v4.0
+- `wallust v4.0.0` isn't backward compatible
+- There seem to be more options but the color palletes are worse IMO
+- Suggest current users ping wallust to v3.5.2
+
+## Lua migration related:
+
+- Improved move/resize and window swapping using native calls
+ - Thanks to `TheAhumMaitra`
+ - His LUA code is better than mine
+ - I will probably be "borrowing" more ;)
+ - https://github.com/TheAhumMaitra/Aurora
+ - https://github.com/TheAhumMaitra
+- Moved layer rules to own file `LayerRules.conf`
+ - Added additional rules from `TheAhumMaitra`
+ - Updated LUA config accordingly
+- Began Migration process to LUA
+ - Created `scripts/migrate-hypr-to-lua.sh`
+ - Script converts `configs` and `UserConfigs` to LUA
+ - Backs them up in local directories
+ - Allows a revert option to restore hyprlang config files
+- Making `Kool_Quick_Settings.sh` script LUA/HYPRLANG aware
+- Broke out the `hypr/configs` and `hypr/UserConfig` LUA files
+- Added project header to all .LUA files
+- Migration script will add that to the converted .conf files as well
+- Updated keybinds parser to support LUA
+- Fixed resize by keybind, SUPERSHIFT= + Arrow keys
+- Then modified that script to support mouse resize
+ - SUPER + Left Mouse to move
+ - SUPER + Right Mouse to resize
## v2.3.23
@@ -70,8 +279,6 @@
v2.3.22
-## v2.3.22
-
- Fixed: Kitty font issue
- Thank you `@JasonNero` for the fix
- Enabled `touch on tablet` in `hypr/configs/SystemSettings.conf`
@@ -107,10 +314,6 @@ v2.3.22
- Replaced with a script `Float-All-Windows.sh` in `Keybinds.conf` file
- Fixed Package name for `waybar-weather`
- Added `scrolling` layout
-- Fixed all float toggle
- - Old command drepreciated
- - Replaced with a script `Float-All-Windows.sh` in `Keybinds.conf` file
-- Fixed Package name for `waybar-weather`
- Added `monocle` layout
- Experimenting with some additional layerrules
- Improving wallpaper based theming
diff --git a/README.md b/README.md
index 9b3588b7..8e7ba281 100644
--- a/README.md
+++ b/README.md
@@ -61,8 +61,6 @@ Automated Hyprland Scripts for Distro of choice which will pull this dotfiles if
- [Arch-Linux](https://github.com/LinuxBeginnings/Arch-Hyprland)
-- [OpenSUSE(Tumbleweed)](https://github.com/LinuxBeginnings/OpenSuse-Hyprland)
-
- [Fedora-Linux (43/44//Rawhide)](https://github.com/LinuxBeginnings/Fedora-Hyprland)
- [Debian-Linux (Trixie,Testing,SID)](https://github.com/LinuxBeginnings/Debian-Hyprland)
@@ -71,7 +69,10 @@ Automated Hyprland Scripts for Distro of choice which will pull this dotfiles if
- [Ubuntu 24.04 LTS](https://github.com/LinuxBeginnings/Ubuntu-Hyprland/tree/24.04)
- [Ubuntu 26.04 LTS](https://github.com/LinuxBeginnings/Ubuntu-Hyprland/tree/26.04)
+
- No longer supported
+
+ - [OpenSUSE(Tumbleweed)](https://github.com/LinuxBeginnings/OpenSuse-Hyprland)
- [Ubuntu 24.10 (deprecated)](https://github.com/LinuxBeginnings/Ubuntu-Hyprland/tree/24.10)
- [Ubuntu 25.04 (deprecated)](https://github.com/LinuxBeginnings/Ubuntu-Hyprland/tree/25.04)
- [Ubuntu 25.10 (deprecated )](https://github.com/LinuxBeginnings/Ubuntu-Hyprland/tree/25.10)
@@ -159,7 +160,12 @@ chmod +x copy.sh
### ✍️ Contributing
- If you have improvements on the dotfiles or configuration, feel free to submit a PR for improvement.
+ - Pull Requests (PRs) must be submitted against the `development` branch!
+ - Those submitted against the `main` branch will be closed
+ - The `main` branch is only for fully tested code
+ - Your change might work fine for your distro but not for the others we support
- I always welcome improvements as I am also just learning just like you guys!
+
- Click [`HERE`](https://github.com/LinuxBeginnings/Hyprland-Dots/blob/main/CONTRIBUTING.md) for a guide how to contribute
> Thanks to all who have contributed code, or support on the Discord server. Your efforts are greatly appreciated
@@ -176,6 +182,7 @@ chmod +x copy.sh
- a Star on my Github repos would be nice 🌟
- Subscribe to my Youtube Channel [YouTube](https://www.youtube.com/@LinuxBeginnings)
+ > Note: Videos coming soon to the YouTube channel!
## 🫰 Thank you for the stars 🩷
diff --git a/config/fastfetch/config-compact.jsonc b/config/fastfetch/config-compact.jsonc
index fa0ed3f7..77c695f6 100644
--- a/config/fastfetch/config-compact.jsonc
+++ b/config/fastfetch/config-compact.jsonc
@@ -5,62 +5,55 @@
*
*/
{
- "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
- "logo": {
- // "type": "auto",
- // x."source": "~/.config/fastfetch/logo.png",
- // "height": 10,
- "padding": {
- "top": 3,
- "right": 2
- },
- "type": "small"
+ "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
+ "logo": {
+ // "type": "auto",
+ // x."source": "~/.config/fastfetch/logo.png",
+ // "height": 10,
+ "padding": {
+ "top": 3,
+ "right": 2,
},
- "display": {
- "separator": " "
+ "type": "small",
+ },
+ "display": {
+ "separator": " ",
+ },
+ "modules": [
+ "break",
+ "break",
+ "break",
+ "break",
+ {
+ "type": "os",
+ "key": " ",
+ "keyColor": "31",
},
- "modules": [
- "break",
- "break",
- "break",
- "break",
- {
- "type": "os",
- "key": " ",
- "keyColor": "31"
- },
- {
- "type": "kernel",
- "key": " ",
- "keyColor": "32"
- },
- {
- "type": "shell",
- "key": " ",
- "keyColor": "34"
- },
- {
- "type": "terminal",
- "key": " ",
- "keyColor": "35"
- },
- {
- "type": "wm",
- "key": " ",
- "keyColor": "36"
- },
- {
- "type": "uptime",
- "key": " ",
- "keyColor": "31"
- },
- {
- "type": "command",
- "key": " ",
- "keyColor": "36",
- "shell": "/bin/bash",
- "text": "echo \"KoolDots: v$DOTS_VERSION\""
- },
- "break"
- ]
+ {
+ "type": "kernel",
+ "key": " ",
+ "keyColor": "32",
+ },
+ {
+ "type": "shell",
+ "key": " ",
+ "keyColor": "34",
+ },
+ {
+ "type": "terminal",
+ "key": " ",
+ "keyColor": "35",
+ },
+ {
+ "type": "wm",
+ "key": " ",
+ "keyColor": "36",
+ },
+ {
+ "type": "uptime",
+ "key": " ",
+ "keyColor": "31",
+ },
+ "break",
+ ],
}
diff --git a/config/fastfetch/config.jsonc b/config/fastfetch/config.jsonc
index 252becd4..4dc4c597 100644
--- a/config/fastfetch/config.jsonc
+++ b/config/fastfetch/config.jsonc
@@ -1,131 +1,131 @@
{
- "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
- "logo": {
- // "type": "kitty",
- // "source": "~/.config/fastfetch/ubuntu.png",
- // "height": 10,
- // "width": 20,
- "type": "small",
- "padding": {
- "top": 3,
- "left": 1
- }
+ "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
+ "logo": {
+ // "type": "kitty",
+ // "source": "~/.config/fastfetch/ubuntu.png",
+ // "height": 10,
+ // "width": 20,
+ "type": "small",
+ "padding": {
+ "top": 3,
+ "left": 1,
},
- "modules": [
- "break",
- {
- "type": "custom",
- "format": "\u001b[90m┌──────────────────────Hardware──────────────────────┐"
- },
- {
- "type": "host",
- "key": " PC",
- "keyColor": "green"
- },
- {
- "type": "cpu",
- "key": "│ ├",
- "keyColor": "green"
- },
- {
- "type": "gpu",
- "key": "│ ├󰍛",
- "keyColor": "green"
- },
- {
- "type": "memory",
- "key": "│ ├󰍛",
- "keyColor": "green"
- },
- {
- "type": "disk",
- "key": "└ └",
- "keyColor": "green"
- },
- {
- "type": "custom",
- "format": "\u001b[90m└────────────────────────────────────────────────────┘"
- },
- "break",
- {
- "type": "custom",
- "format": "\u001b[90m┌──────────────────────Software──────────────────────┐"
- },
- {
- "type": "os",
- "key": " OS",
- "keyColor": "yellow"
- },
- {
- "type": "kernel",
- "key": "│ ├",
- "keyColor": "yellow"
- },
- {
- "type": "bios",
- "key": "│ ├",
- "keyColor": "yellow"
- },
- {
- "type": "packages",
- "key": "│ ├󰏖",
- "keyColor": "yellow"
- },
- {
- "type": "shell",
- "key": "└ └",
- "keyColor": "yellow"
- },
- {
- "type": "wm",
- "key": " WM",
- "keyColor": "blue"
- },
- {
- "type": "lm",
- "key": "│ ├",
- "keyColor": "blue"
- },
- {
- "type": "wmtheme",
- "key": "│ ├󰉼",
- "keyColor": "blue"
- },
- {
- "type": "terminal",
- "key": "└ └",
- "keyColor": "blue"
- },
- {
- "type": "custom",
- "format": "\u001b[90m└────────────────────────────────────────────────────┘"
- },
- "break",
- {
- "type": "custom",
- "format": "\u001b[90m┌─────────────────Uptime / Age / DT──────────────────┐"
- },
- {
- "type": "command",
- "key": " OS Age ",
- "keyColor": "magenta",
- "text": "birth_install=$(stat -c %W /); current=$(date +%s); time_progression=$((current - birth_install)); days_difference=$((time_progression / 86400)); echo $days_difference days"
- },
- {
- "type": "uptime",
- "key": " Uptime ",
- "keyColor": "magenta"
- },
- {
- "type": "command",
- "key": " KoolDots Ver ",
- "text": "echo v${DOTS_VERSION}",
- "keyColor": "magenta"
- },
- {
- "type": "custom",
- "format": "\u001b[90m└────────────────────────────────────────────────────┘"
- },
- "break"
- ]
+ },
+ "modules": [
+ "break",
+ {
+ "type": "custom",
+ "format": "\u001b[90m┌──────────────────────Hardware────────────────────────────┐",
+ },
+ {
+ "type": "host",
+ "key": " PC",
+ "keyColor": "green",
+ },
+ {
+ "type": "cpu",
+ "key": "│ ├",
+ "keyColor": "green",
+ },
+ {
+ "type": "gpu",
+ "key": "│ ├󰍛",
+ "keyColor": "green",
+ },
+ {
+ "type": "memory",
+ "key": "│ ├󰍛",
+ "keyColor": "green",
+ },
+ {
+ "type": "disk",
+ "key": "└ └",
+ "keyColor": "green",
+ },
+ {
+ "type": "custom",
+ "format": "\u001b[90m└──────────────────────────────────────────────────────────┘",
+ },
+ "break",
+ {
+ "type": "custom",
+ "format": "\u001b[90m┌──────────────────────Software──────────────────────┐",
+ },
+ {
+ "type": "os",
+ "key": " OS",
+ "keyColor": "yellow",
+ },
+ {
+ "type": "kernel",
+ "key": "│ ├",
+ "keyColor": "yellow",
+ },
+ {
+ "type": "bios",
+ "key": "│ ├",
+ "keyColor": "yellow",
+ },
+ {
+ "type": "packages",
+ "key": "│ ├󰏖",
+ "keyColor": "yellow",
+ },
+ {
+ "type": "shell",
+ "key": "└ └",
+ "keyColor": "yellow",
+ },
+ {
+ "type": "wm",
+ "key": " WM",
+ "keyColor": "blue",
+ },
+ {
+ "type": "lm",
+ "key": "│ ├",
+ "keyColor": "blue",
+ },
+ {
+ "type": "wmtheme",
+ "key": "│ ├󰉼",
+ "keyColor": "blue",
+ },
+ {
+ "type": "terminal",
+ "key": "└ └",
+ "keyColor": "blue",
+ },
+ {
+ "type": "custom",
+ "format": "\u001b[90m└────────────────────────────────────────────────────┘",
+ },
+ "break",
+ {
+ "type": "custom",
+ "format": "\u001b[90m┌─────────────────Uptime / Age / DT──────────────────┐",
+ },
+ {
+ "type": "command",
+ "key": " OS Age ",
+ "keyColor": "magenta",
+ "text": "birth_install=$(stat -c %W /); current=$(date +%s); time_progression=$((current - birth_install)); days_difference=$((time_progression / 86400)); echo $days_difference days",
+ },
+ {
+ "type": "uptime",
+ "key": " Uptime ",
+ "keyColor": "magenta",
+ },
+ {
+ "type": "command",
+ "key": " KoolDots Ver ",
+ "text": "echo v${DOTS_VERSION}",
+ "keyColor": "magenta",
+ },
+ {
+ "type": "custom",
+ "format": "\u001b[90m└────────────────────────────────────────────────────┘",
+ },
+ "break",
+ ],
}
diff --git a/config/ghostty/config b/config/ghostty/config
index fb539f6b..cce2bc93 100644
--- a/config/ghostty/config
+++ b/config/ghostty/config
@@ -1,5 +1,6 @@
# pkill -SIGUSR2 ghostty
theme = "Catppuccin Mocha"
+#config-file = ~/.config/ghostty/wallust.conf
#theme = Aura
#theme = Aardvark Blue
#theme = GruvboxDarkHard
diff --git a/config/hypr/.luarc.json b/config/hypr/.luarc.json
new file mode 100644
index 00000000..e01b5803
--- /dev/null
+++ b/config/hypr/.luarc.json
@@ -0,0 +1,9 @@
+{
+ "diagnostics.globals": [
+ "hl"
+ ],
+ "workspace.checkThirdParty": false,
+ "workspace.library": [
+ "${HOME}/.config/hypr"
+ ]
+}
diff --git a/config/hypr/Monitor_Profiles/HDMI-A-1-HighRefreshRate.conf b/config/hypr/Monitor_Profiles/HDMI-A-1-HighRefreshRate.conf
new file mode 100644
index 00000000..11f7db56
--- /dev/null
+++ b/config/hypr/Monitor_Profiles/HDMI-A-1-HighRefreshRate.conf
@@ -0,0 +1,11 @@
+# /* ---- 💫 https://github.com/LinuxBeginnings 💫 ---- */ #
+# default Monitor config
+
+# Monitor Configuration
+# See Hyprland wiki for more details
+# https://wiki.hyprland.org/Configuring/Monitors/
+# Configure your Display resolution, offset, scale and Monitors here, use `hyprctl monitors` to get the info.
+
+monitor = HDMI-A-1, highrr,auto,1
+
+
diff --git a/config/hypr/Monitor_Profiles/HDMI-A-1-HighRefreshRate.lua b/config/hypr/Monitor_Profiles/HDMI-A-1-HighRefreshRate.lua
new file mode 100644
index 00000000..dddb042a
--- /dev/null
+++ b/config/hypr/Monitor_Profiles/HDMI-A-1-HighRefreshRate.lua
@@ -0,0 +1,15 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- HDMI-A-1 High Refresh Rate profile
+
+hl.monitor({
+ output = "HDMI-A-1",
+ mode = "highrr",
+ position = "auto",
+ scale = "1",
+})
diff --git a/config/hypr/Monitor_Profiles/README b/config/hypr/Monitor_Profiles/README
index 86075d77..478f2601 100644
--- a/config/hypr/Monitor_Profiles/README
+++ b/config/hypr/Monitor_Profiles/README
@@ -3,11 +3,14 @@
# Create a unique file name i.e. Mirror, or Office, Scale, etc etc
# tip: You can easily create a profile using nwg-displays
-# after creating a profile using nwg-displays, copy the ~/.config/hypr/monitors.conf file to this directory with a unique file name
+# after creating a profile using nwg-displays:
+# - Hyprlang workflow: copy ~/.config/hypr/monitors.conf here as <name>.conf
+# - Lua workflow: copy ~/.config/hypr/UserConfigs/monitors.lua here as <name>.lua
# suggest not to call it default
-
-# Note, after selecting Profiles wanted via Rofi (SUPER SHIFT E), previous content of ~/.config/hypr/monitors.conf will be backed up and named as Previous_Profile.conf
+# Note, after selecting Profiles wanted via Rofi (SUPER SHIFT E):
+# - Hyprlang workflow writes ~/.config/hypr/monitors.conf
+# - Lua workflow writes ~/.config/hypr/UserConfigs/monitors.lua
# Monitor profile should be loaded automatically once selected by KooL Rofi Settings ROfi Menu, unless you disabled the auto-reload function on Hyprland settings.
# However, if it does not load, kindly log out and re-login. This seem apparent if you are using a Virtual Environment.
diff --git a/config/hypr/Monitor_Profiles/Virtual-1-1920x1080.conf b/config/hypr/Monitor_Profiles/Virtual-1-1920x1080.conf
new file mode 100644
index 00000000..d06f1e62
--- /dev/null
+++ b/config/hypr/Monitor_Profiles/Virtual-1-1920x1080.conf
@@ -0,0 +1,11 @@
+# /* ---- 💫 https://github.com/LinuxBeginnings 💫 ---- */ #
+# default Monitor config
+
+# Monitor Configuration
+# See Hyprland wiki for more details
+# https://wiki.hyprland.org/Configuring/Monitors/
+# Configure your Display resolution, offset, scale and Monitors here, use `hyprctl monitors` to get the info.
+
+# Monitors
+monitor = Virtual-1, 1920x1080@60,auto,1
+
diff --git a/config/hypr/Monitor_Profiles/Virtual-1-1920x1080.lua b/config/hypr/Monitor_Profiles/Virtual-1-1920x1080.lua
new file mode 100644
index 00000000..2360d12e
--- /dev/null
+++ b/config/hypr/Monitor_Profiles/Virtual-1-1920x1080.lua
@@ -0,0 +1,15 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- Virtual-1 1920x1080 profile
+
+hl.monitor({
+ output = "Virtual-1",
+ mode = "1920x1080@60",
+ position = "auto",
+ scale = "1",
+})
diff --git a/config/hypr/Monitor_Profiles/Virtual-1-2560x1080.conf b/config/hypr/Monitor_Profiles/Virtual-1-2560x1080.conf
new file mode 100644
index 00000000..1120e741
--- /dev/null
+++ b/config/hypr/Monitor_Profiles/Virtual-1-2560x1080.conf
@@ -0,0 +1,11 @@
+# /* ---- 💫 https://github.com/LinuxBeginnings 💫 ---- */ #
+# default Monitor config
+
+# Monitor Configuration
+# See Hyprland wiki for more details
+# https://wiki.hyprland.org/Configuring/Monitors/
+# Configure your Display resolution, offset, scale and Monitors here, use `hyprctl monitors` to get the info.
+
+# Monitors
+monitor = Virtual-1, 2560x1080@60,auto,1
+
diff --git a/config/hypr/Monitor_Profiles/Virtual-1-2560x1080.lua b/config/hypr/Monitor_Profiles/Virtual-1-2560x1080.lua
new file mode 100644
index 00000000..4fbdbb38
--- /dev/null
+++ b/config/hypr/Monitor_Profiles/Virtual-1-2560x1080.lua
@@ -0,0 +1,15 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- Virtual-1 2560x1080 profile
+
+hl.monitor({
+ output = "Virtual-1",
+ mode = "2560x1080@60",
+ position = "auto",
+ scale = "1",
+})
diff --git a/config/hypr/Monitor_Profiles/default.lua b/config/hypr/Monitor_Profiles/default.lua
new file mode 100644
index 00000000..5ae297c4
--- /dev/null
+++ b/config/hypr/Monitor_Profiles/default.lua
@@ -0,0 +1,32 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- default Monitor config
+-- Monitor Configuration
+-- See Hyprland wiki for more details
+-- https://wiki.hyprland.org/Configuring/Monitors/
+
+hl.monitor({
+ output = "",
+ mode = "preferred",
+ position = "auto",
+ scale = "1",
+})
+
+hl.monitor({
+ output = "",
+ mode = "highrr",
+ position = "auto",
+ scale = "1",
+})
+
+hl.monitor({
+ output = "",
+ mode = "highres",
+ position = "auto",
+ scale = "1",
+})
diff --git a/config/hypr/Monitor_Profiles/eDP-1-disable.conf b/config/hypr/Monitor_Profiles/eDP-1-disable.conf
new file mode 100644
index 00000000..ac8a306f
--- /dev/null
+++ b/config/hypr/Monitor_Profiles/eDP-1-disable.conf
@@ -0,0 +1,4 @@
+# /* ---- 💫 https://github.com/LinuxBeginnings 💫 ---- */ #
+# Disable eDP-1 (laptop panel)
+
+monitor = eDP-1,disable
diff --git a/config/hypr/Monitor_Profiles/eDP-1-disable.lua b/config/hypr/Monitor_Profiles/eDP-1-disable.lua
new file mode 100644
index 00000000..c07673e2
--- /dev/null
+++ b/config/hypr/Monitor_Profiles/eDP-1-disable.lua
@@ -0,0 +1,13 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- Disable eDP-1 (laptop panel)
+
+hl.monitor({
+ output = "eDP-1",
+ disabled = true,
+})
diff --git a/config/hypr/UserConfigs/01-UserDefaults.conf b/config/hypr/UserConfigs/01-UserDefaults.conf
index dd5f299a..2dc537df 100644
--- a/config/hypr/UserConfigs/01-UserDefaults.conf
+++ b/config/hypr/UserConfigs/01-UserDefaults.conf
@@ -9,15 +9,18 @@
# Set your default editor here uncomment and reboot to take effect.
# NOTE, this will be automatically uncommented if you select neovim or vim to your default editor
-#env = EDITOR,vim #default editor
+env = EDITOR,nvim #default editor
# Define preferred text editor for the KooL Quick Settings Menu (SUPER SHIFT E)
# script will take the default EDITOR and nano as fallback
$edit=${EDITOR:-nano}
+# Optional visual editor for Quick Settings (GUI or TTY command)
+$visual=${VISUAL:-}
# These two are for UserKeybinds.conf & Waybar Modules
$term = kitty # Terminal
$files = thunar # File Manager
# Default Search Engine for ROFI Search (SUPER S)
-$Search_Engine = "https://www.google.com/search?q={}" \ No newline at end of file
+$Search_Engine = "https://www.google.com/search?q={}"
+env = VISUAL,nvim #default visual editor for quick settings (optional)
diff --git a/config/hypr/UserConfigs/ENVariables.conf b/config/hypr/UserConfigs/ENVariables.conf
index e2b3498a..c9c229ed 100644
--- a/config/hypr/UserConfigs/ENVariables.conf
+++ b/config/hypr/UserConfigs/ENVariables.conf
@@ -54,3 +54,5 @@
# env = AQ_MGPU_NO_EXPLICIT,1 # Disables explicit syncing on mgpu buffers
# env = AQ_NO_MODIFIERS,1 # Disables modifiers for DRM buffers
+
+
diff --git a/config/hypr/UserConfigs/LayerRules.conf b/config/hypr/UserConfigs/LayerRules.conf
new file mode 100644
index 00000000..6ca3c180
--- /dev/null
+++ b/config/hypr/UserConfigs/LayerRules.conf
@@ -0,0 +1,14 @@
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# For layerrules
+# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
+
+# This file is used to add or overwrite layer rules
+# This file will not be modified during dotfiles updates
+
+# Example:
+# layerrule = blur on, ignore_alpha 0, match:namespace rofi
diff --git a/config/hypr/UserConfigs/UserDecorations.conf b/config/hypr/UserConfigs/UserDecorations.conf
index d962092f..e7e30651 100644
--- a/config/hypr/UserConfigs/UserDecorations.conf
+++ b/config/hypr/UserConfigs/UserDecorations.conf
@@ -14,9 +14,9 @@
source = $HOME/.config/hypr/wallust/wallust-hyprland.conf
general {
- border_size = 2
- gaps_in = 2
- gaps_out = 4
+ border_size = 1
+ gaps_in = 4
+ gaps_out = 6
col.active_border = $color12
col.inactive_border = $color10
diff --git a/config/hypr/UserConfigs/UserKeybinds.conf b/config/hypr/UserConfigs/UserKeybinds.conf
index cc19ff78..38407eec 100644
--- a/config/hypr/UserConfigs/UserKeybinds.conf
+++ b/config/hypr/UserConfigs/UserKeybinds.conf
@@ -1,15 +1,11 @@
-# ==================================================
-# KoolDots (2026)
-# Project URL: https://github.com/LinuxBeginnings
-# License: GNU GPLv3
-# SPDX-License-Identifier: GPL-3.0-or-later
-# ==================================================
+# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ #
# This is where you put your own keybinds. Be Mindful to check as well ~/.config/hypr/configs/Keybinds.conf to avoid conflict
# if you think I should replace the Pre-defined Keybinds in ~/.config/hypr/configs/Keybinds.conf , submit an issue or let me know in DC and present me a valid reason as to why, such as conflicting with global shortcuts, etc etc
# See https://wiki.hyprland.org/Configuring/Keywords/ for more settings and variables
# See also Laptops.conf for laptops keybinds
+# /* ---- ✴️ Variables ✴️ ---- */ #
$mainMod = SUPER
$scriptsDir = $HOME/.config/hypr/scripts
$UserScripts = $HOME/.config/hypr/UserScripts
@@ -33,10 +29,14 @@ $UserConfigs = $HOME/.config/hypr/UserConfigs
# E.g.
# bindd = $mainMod, Z, My z app, exec APPNAME
+##############
+# Rebinds #
+##############
-
-
+##############
+# unbinds #
+##############
diff --git a/config/hypr/UserConfigs/WindowRules.conf b/config/hypr/UserConfigs/WindowRules.conf
index b6d65135..7ec0fd08 100644
--- a/config/hypr/UserConfigs/WindowRules.conf
+++ b/config/hypr/UserConfigs/WindowRules.conf
@@ -4,15 +4,12 @@
# License: GNU GPLv3
# SPDX-License-Identifier: GPL-3.0-or-later
# ==================================================
-# For window rules and layerrules
+# For window rules
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
# This file is used to add or overwrite window rules
# This file will not be modified during dotfiles updates
-# Optional Layer rules
-# To Resolve blurred corners in rofi Uncomment
-# layerrule = blur on, ignore_alpha 0, match:namespace rofi
-
+# Layer rules now belong in UserConfigs/LayerRules.conf
diff --git a/config/hypr/UserConfigs/monitors.lua b/config/hypr/UserConfigs/monitors.lua
new file mode 100644
index 00000000..544380ed
--- /dev/null
+++ b/config/hypr/UserConfigs/monitors.lua
@@ -0,0 +1,18 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- User monitor overrides for Lua workflow.
+-- MonitorProfiles.sh writes selected Lua monitor profiles into this file.
+-- Keep custom hl.monitor(...) entries here so upgrades preserve them.
+
+-- Example:
+-- hl.monitor({
+-- output = "eDP-1",
+-- mode = "preferred",
+-- position = "auto",
+-- scale = "1",
+-- })
diff --git a/config/hypr/UserConfigs/user_decorations.lua b/config/hypr/UserConfigs/user_decorations.lua
new file mode 100644
index 00000000..6b34666e
--- /dev/null
+++ b/config/hypr/UserConfigs/user_decorations.lua
@@ -0,0 +1,106 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- User decorations overrides (auto-generated).
+-- This file is intentionally split from other user overrides.
+-- Add only user-specific Lua overrides here.
+-- Example:
+-- hl.config({ general = { gaps_in = 4, gaps_out = 8 } })
+
+-- Source reference from UserDecorations.conf (hyprlang):
+-- source = $HOME/.config/hypr/wallust/wallust-hyprland.conf
+-- general {
+-- border_size = 2
+-- gaps_in = 2
+-- gaps_out = 4
+-- col.active_border = $color12
+-- col.inactive_border = $color10
+-- }
+-- decoration {
+-- rounding = 10
+-- active_opacity = 1.0
+-- inactive_opacity = 0.9
+-- fullscreen_opacity = 1.0
+-- dim_inactive = true
+-- dim_strength = 0.1
+-- dim_special = 0.8
+-- shadow {
+-- enabled = true
+-- range = 3
+-- render_power = 1
+-- color = $color12
+-- color_inactive = $color10
+-- }
+-- blur {
+-- enabled = true
+-- size = 6
+-- passes = 3
+-- new_optimizations = true
+-- xray = true
+-- ignore_opacity = true
+-- special = true
+-- popups = true
+-- }
+-- }
+-- group {
+-- col.border_active = $color15
+-- groupbar {
+-- col.active = $color0
+-- }
+-- }
+
+local function read_wallust_colors(path)
+ local colors = {}
+ local handle = io.open(path, "r")
+ if not handle then
+ return colors
+ end
+ for line in handle:lines() do
+ local key, hex = line:match("^%$([%w_]+)%s*=%s*rgb%(([0-9A-Fa-f]+)%)")
+ if key and hex then
+ colors[key] = "rgb(" .. hex .. ")"
+ end
+ end
+ handle:close()
+ return colors
+end
+
+local wallust_path = (os.getenv("HOME") or "") .. "/.config/hypr/wallust/wallust-hyprland.conf"
+local colors = read_wallust_colors(wallust_path)
+
+if next(colors) then
+ hl.config({
+ general = {
+ col = {
+ active_border = colors.color12 or "rgba(8db4ffff)",
+ inactive_border = colors.color10 or "rgba(5f6578ff)",
+ },
+ },
+ })
+
+ hl.config({
+ decoration = {
+ shadow = {
+ color = colors.color12 or "rgba(8db4ffff)",
+ color_inactive = colors.color10 or "rgba(5f6578ff)",
+ },
+ },
+ })
+
+ hl.config({
+ group = {
+ col = {
+ border_active = colors.color15 or "rgba(ffffffff)",
+ },
+ groupbar = {
+ col = {
+ active = colors.color0 or "rgba(0f111aff)",
+ },
+ },
+ },
+ })
+end
diff --git a/config/hypr/UserConfigs/user_keybinds.lua b/config/hypr/UserConfigs/user_keybinds.lua
new file mode 100644
index 00000000..91872105
--- /dev/null
+++ b/config/hypr/UserConfigs/user_keybinds.lua
@@ -0,0 +1,40 @@
+-- User keybind overrides (auto-generated).
+-- Add keybinds with bind("MODS", "KEY", fn, opts).
+-- Example:
+-- bind("SUPER", "Z", exec_cmd("ghostty"), { description = "Launch ghostty" })
+-- Helper functions live in ~/.config/hypr/lua/user_keybinds_helper.lua so they can be updated separately.
+local user_keybinds_helper = nil
+do
+ local source = (debug.getinfo(1, "S") or {}).source or ""
+ local source_path = source:match("^@(.+)$")
+ local source_dir = source_path and source_path:match("^(.*)/[^/]+$") or nil
+ local home = os.getenv("HOME") or ""
+ local candidate_paths = {
+ source_dir and (source_dir .. "/../lua/user_keybinds_helper.lua") or nil,
+ home ~= "" and (home .. "/.config/hypr/lua/user_keybinds_helper.lua") or nil,
+ home ~= "" and (home .. "/.config/hypr/user_keybinds_helper.lua") or nil,
+ }
+
+ local tried_paths = {}
+ for _, helper_path in ipairs(candidate_paths) do
+ if helper_path then
+ table.insert(tried_paths, helper_path)
+ local f = io.open(helper_path, "r")
+ if f then
+ f:close()
+ local loaded_ok, loaded_helpers = pcall(dofile, helper_path)
+ if loaded_ok and type(loaded_helpers) == "table" and loaded_helpers.bind then
+ user_keybinds_helper = loaded_helpers
+ break
+ end
+ end
+ end
+ end
+
+ if not user_keybinds_helper then
+ error("Failed to load user_keybinds_helper.lua from: " .. table.concat(tried_paths, ", "))
+ end
+end
+local exec_cmd = user_keybinds_helper.exec_cmd
+local bind = user_keybinds_helper.bind
+
diff --git a/config/hypr/UserScripts/WallpaperAutoChange.sh b/config/hypr/UserScripts/WallpaperAutoChange.sh
index faec6335..5cee2a1e 100755
--- a/config/hypr/UserScripts/WallpaperAutoChange.sh
+++ b/config/hypr/UserScripts/WallpaperAutoChange.sh
@@ -13,13 +13,11 @@
# NOTE: this script uses bash (not POSIX shell) for the RANDOM variable
wallust_refresh=$HOME/.config/hypr/scripts/RefreshNoWaybar.sh
+SCRIPTSDIR="$HOME/.config/hypr/scripts"
+# shellcheck source=/dev/null
+. "$SCRIPTSDIR/WallpaperCmd.sh"
focused_monitor=$(hyprctl monitors | awk '/^Monitor/{name=$2} /focused: yes/{print name}')
-if command -v awww >/dev/null 2>&1; then
- WWW="awww"
-else
- WWW="swww"
-fi
if [[ $# -lt 1 ]] || [[ ! -d $1 ]]; then
echo "Usage:
@@ -41,12 +39,13 @@ while true; do
done \
| sort -n | cut -d':' -f2- \
| while read -r img; do
- $WWW img -o $focused_monitor "$img"
+ resize_mode="$(wallpaper_resize_mode "$img" "$focused_monitor")"
+ "$WWW_CMD" img -o "$focused_monitor" --resize "$resize_mode" "$img"
# Regenerate colors from the exact image path to avoid cache races
$HOME/.config/hypr/scripts/WallustSwww.sh "$img"
# Refresh UI components that depend on wallust output
$wallust_refresh
sleep $INTERVAL
-
+
done
done
diff --git a/config/hypr/UserScripts/WallpaperEffects.sh b/config/hypr/UserScripts/WallpaperEffects.sh
index e1c8fe83..297c77fa 100755
--- a/config/hypr/UserScripts/WallpaperEffects.sh
+++ b/config/hypr/UserScripts/WallpaperEffects.sh
@@ -12,13 +12,10 @@ terminal=kitty
wallpaper_current="$HOME/.config/hypr/wallpaper_effects/.wallpaper_current"
wallpaper_output="$HOME/.config/hypr/wallpaper_effects/.wallpaper_modified"
SCRIPTSDIR="$HOME/.config/hypr/scripts"
+# shellcheck source=/dev/null
+. "$SCRIPTSDIR/WallpaperCmd.sh"
focused_monitor=$(hyprctl monitors -j | jq -r '.[] | select(.focused) | .name')
rofi_theme="$HOME/.config/rofi/config-wallpaper-effect.rasi"
-if command -v awww >/dev/null 2>&1; then
- WWW="awww"
-else
- WWW="swww"
-fi
# Directory for swaync
iDIR="$HOME/.config/swaync/images"
@@ -29,10 +26,10 @@ FPS=60
TYPE="wipe"
DURATION=2
BEZIER=".43,1.19,1,.4"
-if [[ "$WWW" == "swww" || "$WWW" == "awww" ]]; then
- SWWW_PARAMS="--transition-fps $FPS --transition-type $TYPE --transition-duration $DURATION --transition-bezier $BEZIER"
+if [[ "$WWW_CMD" == "swww" || "$WWW_CMD" == "awww" ]]; then
+ SWWW_PARAMS=(--transition-fps "$FPS" --transition-type "$TYPE" --transition-duration "$DURATION" --transition-bezier "$BEZIER")
else
- SWWW_PARAMS=""
+ SWWW_PARAMS=()
fi
# Define ImageMagick effects
@@ -59,12 +56,15 @@ declare -A effects=(
# Function to apply no effects
no-effects() {
- $WWW img -o "$focused_monitor" "$wallpaper_current" $SWWW_PARAMS &&
- wait $!
- wallust run "$wallpaper_current" -s &&
- wait $!
+ local resize_mode
+ resize_mode="$(wallpaper_resize_mode "$wallpaper_current" "$focused_monitor")"
+ "$WWW_CMD" img -o "$focused_monitor" --resize "$resize_mode" "$wallpaper_current" "${SWWW_PARAMS[@]}" || return 1
+ if ! "$SCRIPTSDIR/WallustSwww.sh" "$wallpaper_current"; then
+ notify-send -u critical -i "$iDIR/error.png" "Wallust failed" "Wallpaper theme not refreshed"
+ return 1
+ fi
# Refresh rofi, waybar, wallust palettes
- sleep 2
+ sleep 0.5
"$SCRIPTSDIR/Refresh.sh"
notify-send -u low -i "$iDIR/ja.png" "No wallpaper" "effects applied"
@@ -90,19 +90,21 @@ main() {
# Apply selected effect
notify-send -u normal -i "$iDIR/ja.png" "Applying:" "$choice effects"
eval "${effects[$choice]}"
-
+
# intial kill process
for pid in swaybg mpvpaper; do
killall -SIGUSR1 "$pid"
done
sleep 1
- $WWW img -o "$focused_monitor" "$wallpaper_output" $SWWW_PARAMS &
-
- sleep 2
-
- wallust run "$wallpaper_output" -s &
- sleep 1
+ local resize_mode
+ resize_mode="$(wallpaper_resize_mode "$wallpaper_output" "$focused_monitor")"
+ "$WWW_CMD" img -o "$focused_monitor" --resize "$resize_mode" "$wallpaper_output" "${SWWW_PARAMS[@]}"
+ sleep 0.5
+ if ! "$SCRIPTSDIR/WallustSwww.sh" "$wallpaper_output"; then
+ notify-send -u critical -i "$iDIR/error.png" "Wallust failed" "Wallpaper theme not refreshed"
+ return 1
+ fi
# Refresh rofi, waybar, wallust palettes
"${SCRIPTSDIR}/Refresh.sh"
notify-send -u low -i "$iDIR/ja.png" "$choice" "effects applied"
diff --git a/config/hypr/UserScripts/WallpaperRandom.sh b/config/hypr/UserScripts/WallpaperRandom.sh
index 70f051f7..aae80426 100755
--- a/config/hypr/UserScripts/WallpaperRandom.sh
+++ b/config/hypr/UserScripts/WallpaperRandom.sh
@@ -25,20 +25,23 @@ TYPE="random"
DURATION=1
BEZIER=".43,1.19,1,.4"
if [[ "$WWW_CMD" == "swww" || "$WWW_CMD" == "awww" ]]; then
- SWWW_PARAMS="--transition-fps $FPS --transition-type $TYPE --transition-duration $DURATION --transition-bezier $BEZIER"
+ SWWW_PARAMS=(--transition-fps "$FPS" --transition-type "$TYPE" --transition-duration "$DURATION" --transition-bezier "$BEZIER")
else
- SWWW_PARAMS=""
+ SWWW_PARAMS=()
fi
if ! "$WWW_CMD" query >/dev/null 2>&1; then
"$WWW_DAEMON" "${WWW_DAEMON_ARGS[@]}" &
fi
-
-"$WWW_CMD" img -o "$focused_monitor" "$RANDOMPICS" $SWWW_PARAMS
+resize_mode="$(wallpaper_resize_mode "$RANDOMPICS" "$focused_monitor")"
+"$WWW_CMD" img -o "$focused_monitor" --resize "$resize_mode" "$RANDOMPICS" "${SWWW_PARAMS[@]}"
wait $!
-"$SCRIPTSDIR/WallustSwww.sh" "$RANDOMPICS" &&
+if ! "$SCRIPTSDIR/WallustSwww.sh" "$RANDOMPICS"; then
+ notify-send -u critical "Wallust failed" "Wallpaper theme not refreshed"
+ exit 1
+fi
wait $!
-sleep 2
+sleep 0.5
"$SCRIPTSDIR/Refresh.sh"
diff --git a/config/hypr/UserScripts/WallpaperSelect.sh b/config/hypr/UserScripts/WallpaperSelect.sh
index 31c7969a..2e5ecd86 100755
--- a/config/hypr/UserScripts/WallpaperSelect.sh
+++ b/config/hypr/UserScripts/WallpaperSelect.sh
@@ -27,9 +27,9 @@ TYPE="any"
DURATION=2
BEZIER=".43,1.19,1,.4"
if [[ "$WWW_CMD" == "swww" || "$WWW_CMD" == "awww" ]]; then
- SWWW_PARAMS="--transition-fps $FPS --transition-type $TYPE --transition-duration $DURATION --transition-bezier $BEZIER"
+ SWWW_PARAMS=(--transition-fps "$FPS" --transition-type "$TYPE" --transition-duration "$DURATION" --transition-bezier "$BEZIER")
else
- SWWW_PARAMS=""
+ SWWW_PARAMS=()
fi
@@ -173,11 +173,13 @@ apply_image_wallpaper() {
"$WWW_CMD" query >/dev/null 2>&1 && break
sleep 0.1
done
- "$WWW_CMD" img -o "$focused_monitor" "$image_path" $SWWW_PARAMS || {
+ local resize_mode
+ resize_mode="$(wallpaper_resize_mode "$image_path" "$focused_monitor")"
+ "$WWW_CMD" img -o "$focused_monitor" --resize "$resize_mode" "$image_path" "${SWWW_PARAMS[@]}" || {
sleep 0.2
- "$WWW_CMD" img -o "$focused_monitor" "$image_path" $SWWW_PARAMS
+ "$WWW_CMD" img -o "$focused_monitor" --resize "$resize_mode" "$image_path" "${SWWW_PARAMS[@]}"
}
- "$WWW_CMD" img -o "$focused_monitor" "$image_path" $SWWW_PARAMS
+ "$WWW_CMD" img -o "$focused_monitor" --resize "$resize_mode" "$image_path" "${SWWW_PARAMS[@]}"
# Persist per-monitor wallpaper selection
mkdir -p "$(dirname "$per_monitor_wallpaper_current")" "$(dirname "$per_monitor_wallpaper_link")"
@@ -185,10 +187,13 @@ apply_image_wallpaper() {
cp -f "$image_path" "$per_monitor_wallpaper_current" || true
# Run additional scripts (pass the image path to avoid cache race conditions)
- "$SCRIPTSDIR/WallustSwww.sh" "$image_path"
- sleep 2
+ if ! "$SCRIPTSDIR/WallustSwww.sh" "$image_path"; then
+ notify-send -i "$iDIR/error.png" "Wallust failed" "Wallpaper theme not refreshed"
+ return 1
+ fi
+ sleep 0.5
"$SCRIPTSDIR/Refresh.sh"
- sleep 1
+ sleep 0.3
}
diff --git a/config/hypr/UserScripts/WeatherWrap.sh b/config/hypr/UserScripts/WeatherWrap.sh
index a95bbd51..d2952d76 100755
--- a/config/hypr/UserScripts/WeatherWrap.sh
+++ b/config/hypr/UserScripts/WeatherWrap.sh
@@ -17,15 +17,15 @@ check_network() {
if ping -c1 -W1 8.8.8.8 >/dev/null 2>&1; then
return 0
fi
-
+
if ping -c1 -W1 1.1.1.1 >/dev/null 2>&1; then
return 0
fi
-
+
if curl -s --connect-timeout 2 "https://ipinfo.io" >/dev/null 2>&1; then
return 0
fi
-
+
return 1
}
diff --git a/config/hypr/configs/ENVariables.conf b/config/hypr/configs/ENVariables.conf
index 0226d053..b134b60d 100644
--- a/config/hypr/configs/ENVariables.conf
+++ b/config/hypr/configs/ENVariables.conf
@@ -10,7 +10,7 @@
# environment-variables
# Current Version of KoolDots:
-env = DOTS_VERSION,2.3.23
+env = DOTS_VERSION,2.3.24
### Toolkit Backend Variables ###
env = GDK_BACKEND,wayland,x11,*
@@ -22,6 +22,8 @@ env = CLUTTER_BACKEND,wayland
#env = SDL_VIDEODRIVER,wayland
### XDG Specifications ###
+# Trying to fix flatpak not being seen in rofi this fix below errors
+#env = XDG_DATA_DIRS,/usr/local/share:/usr/share:$XDG_DATA_DIRS:/var/lib/flatpak/exports/share:/home/$USER/.local/share/flatpak/exports/share
env = XDG_CURRENT_DESKTOP,Hyprland
env = XDG_SESSION_DESKTOP,Hyprland
env = XDG_SESSION_TYPE,wayland
diff --git a/config/hypr/configs/Keybinds.conf b/config/hypr/configs/Keybinds.conf
index bbc93b25..82693694 100644
--- a/config/hypr/configs/Keybinds.conf
+++ b/config/hypr/configs/Keybinds.conf
@@ -18,172 +18,174 @@ source= $UserConfigs/01-UserDefaults.conf
#### STANDARD ####
# Common shortcuts
#bindr = $mainMod, $mainMod_L, exec, pkill rofi || rofi -show drun -modi drun,filebrowser,run,window # Super Key to Launch rofi menu
-bindd = $mainMod, D, app launcher, exec, pkill rofi || true && rofi -show drun -modi drun,filebrowser,run,window
-bindd = $mainMod, B, open default browser, exec, xdg-open "https://"
-bindd = $mainMod, A, desktop overview, exec, $scriptsDir/OverviewToggle.sh # toggles quickshell or ags overview (tries QS first, falls back to AGS)
-#bindd = $mainMod, A, ags overview, exec, pkill rofi || true && ags -t 'overview' # desktop overview (if installed)
+bindd = $mainMod, D, App launcher, exec, pkill rofi || true && rofi -show drun -modi drun,filebrowser,run,window
+bindd = $mainMod, B, Open default browser, exec, xdg-open "https://"
+bindd = $mainMod, A, Desktop overview, exec, $scriptsDir/OverviewToggle.sh # toggles quickshell or ags overview (tries QS first, falls back to AGS)
+#bindd = $mainMod, A, Ags overview, exec, pkill rofi || true && ags -t 'overview' # desktop overview (if installed)
#bindd = $mainMod, A, Quickshell overview, global, quickshell:overviewToggle # desktop overview (if installed)
bindd = $mainMod, Return, Open terminal, exec, $term
-bindd = $mainMod, E, file manager, exec, $files
+bindd = $mainMod, E, File manager, exec, $files
bindd = $mainMod, C, SSH session manager, exec, $scriptsDir/rofi-ssh-menu.sh
# FEATURES / EXTRAS
bindd = $mainMod, T, Global theme switcher using Wallust, exec, $scriptsDir/ThemeChanger.sh #Global theme switcher
-bindd = $mainMod, H, help / cheat sheet, exec, $scriptsDir/KeyHints.sh
-bindd = $mainMod ALT, R, refresh bar and menus, exec, $scriptsDir/Refresh.sh
-bindd = $mainMod ALT, E, emoji menu, exec, $scriptsDir/RofiEmoji.sh
-bindd = $mainMod, S, web search, exec, $scriptsDir/RofiSearch.sh
-bindd = $mainMod CTRL, S, window switcher, exec, rofi -show window
-bindd = $mainMod ALT, O, toggle blur, exec, $scriptsDir/ChangeBlur.sh
-bindd = $mainMod SHIFT, G, toggle game mode, exec, $scriptsDir/GameMode.sh
-bindd = $mainMod ALT, L, toggle layouts, exec, $scriptsDir/ChangeLayout.sh toggle
-bindd = $mainMod ALT, V, clipboard manager, exec, $scriptsDir/ClipManager.sh
-bindd = $mainMod CTRL, R, rofi theme selector, exec, $scriptsDir/RofiThemeSelector.sh
-bindd = $mainMod CTRL SHIFT, R, rofi theme selector (modified), exec, pkill rofi || true && $scriptsDir/RofiThemeSelector-modified.sh
+bindd = $mainMod, H, Help / cheat sheet, exec, $scriptsDir/KeyHints.sh
+bindd = $mainMod ALT, R, Refresh bar and menus, exec, $scriptsDir/Refresh.sh
+bindd = $mainMod ALT, E, Emoji menu, exec, $scriptsDir/RofiEmoji.sh
+bindd = $mainMod, S, Web search, exec, $scriptsDir/RofiSearch.sh
+bindd = $mainMod CTRL, S, Window switcher, exec, rofi -show window
+bindd = $mainMod ALT, O, Toggle blur, exec, $scriptsDir/ChangeBlur.sh
+bindd = $mainMod SHIFT, G, Toggle game mode, exec, $scriptsDir/GameMode.sh
+bindd = $mainMod ALT, L, Toggle layouts, exec, $scriptsDir/ChangeLayout.sh toggle
+bindd = $mainMod ALT, V, Clipboard manager, exec, $scriptsDir/ClipManager.sh
+bindd = $mainMod CTRL, R, Rofi theme selector, exec, $scriptsDir/RofiThemeSelector.sh
+bindd = $mainMod CTRL SHIFT, R, Rofi theme selector (modified), exec, pkill rofi || true && $scriptsDir/RofiThemeSelector-modified.sh
bindd = $mainMod CTRL, K, Kitty theme selector, exec, $scriptsDir/Kitty_themes.sh
+bindd = $mainMod CTRL, G, Ghostty theme selector, exec, $scriptsDir/Ghostty_themes.sh
bindd = $mainMod SHIFT, B, Set static Rainbow Border, exec, $UserScripts/RainbowBorders-low-cpu.sh --run-once
bindd = $mainMod SHIFT, H, Toggle Mute/Unmute for Active-Window, exec, $scriptsDir/Toggle-Active-Window-Audio.sh
bindd = ALT SHIFT, S, Hyprshot Screen Capture, exec, $scriptsDir/hyprshot.sh -m region -o $HOME/Pictures/Screenshots
-bindd = $mainMod SHIFT, F, fullscreen, fullscreen
-bindd = $mainMod CTRL, F, maximize window, fullscreen, 1
+bindd = $mainMod SHIFT, F, Fullscreen, fullscreen
+bindd = $mainMod CTRL, F, Maximize window, fullscreen, 1
bindd = $mainMod, SPACE, Float current window, togglefloating,
bindd = $mainMod ALT, SPACE, Float all windows, exec, $scriptsDir/Float-all-Windows.sh
-bindd = $mainMod SHIFT, Return, DropDown terminal, exec, $scriptsDir/Dropterminal.sh $term
+# NOTE: Dropterminal is currently certified only with kitty. Not all terminals behave correctly as a dropdown.
+bindd = $mainMod SHIFT, Return, DropDown terminal, exec, $scriptsDir/Dropterminal.sh kitty
# Desktop zooming or magnifier
-bindd = $mainMod ALT, mouse_down, zoom in, exec, hyprctl keyword cursor:zoom_factor "$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {factor = $2; if (factor < 1) {factor = 1}; print factor * 2.0}')"
-bindd = $mainMod ALT, mouse_up, zoom out, exec, hyprctl keyword cursor:zoom_factor "$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {factor = $2; if (factor < 1) {factor = 1}; print factor / 2.0}')"
+bindd = $mainMod ALT, mouse_down, Zoom in, exec, hyprctl keyword cursor:zoom_factor "$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {factor = $2; if (factor < 1) {factor = 1}; print factor * 2.0}')"
+bindd = $mainMod ALT, mouse_up, Zoom out, exec, hyprctl keyword cursor:zoom_factor "$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {factor = $2; if (factor < 1) {factor = 1}; print factor / 2.0}')"
# Waybar / Bar related
-bindd = $mainMod CTRL ALT, B, toggle waybar on/off, exec, pkill -SIGUSR1 waybar
-bindd = $mainMod CTRL, B, waybar styles menu, exec, $scriptsDir/WaybarStyles.sh
-bindd = $mainMod ALT, B, waybar layout menu, exec, $scriptsDir/WaybarLayout.sh
+bindd = $mainMod CTRL ALT, B, Toggle waybar on/off, exec, pkill -SIGUSR1 waybar
+bindd = $mainMod CTRL, B, Waybar styles menu, exec, $scriptsDir/WaybarStyles.sh
+bindd = $mainMod ALT, B, Waybar layout menu, exec, $scriptsDir/WaybarLayout.sh
# Night light toggle (Hyprsunset)
-bindd = $mainMod, N, toggle night light, exec, $scriptsDir/Hyprsunset.sh toggle
+bindd = $mainMod, N, Toggle Hyprsunset - night light, exec, $scriptsDir/Hyprsunset.sh toggle
# FEATURES / EXTRAS (UserScripts)
-bindd = $mainMod SHIFT, M, online music, exec, $UserScripts/RofiBeats.sh
-bindd = $mainMod, W, select wallpaper, exec, $UserScripts/WallpaperSelect.sh
-bindd = $mainMod SHIFT, W, wallpaper effects, exec, $UserScripts/WallpaperEffects.sh
-bindd = CTRL ALT, W, random wallpaper, exec, $UserScripts/WallpaperRandom.sh
-bindd = $mainMod CTRL, O, toggle active window opacity, setprop, active opaque toggle
-bindd = $mainMod SHIFT, K, search keybinds, exec, $scriptsDir/KeyBinds.sh
-bindd = $mainMod SHIFT, A, animations menu, exec, $scriptsDir/Animations.sh
-bindd = $mainMod SHIFT, O, change oh-my-zsh theme, exec, $UserScripts/ZshChangeTheme.sh
-bindlnd = ALT_L, SHIFT_L, switch keyboard layout globally, exec, $scriptsDir/KeyboardLayout.sh switch
-bindlnd = SHIFT_L, ALT_L, switch keyboard layout per-window, exec, $scriptsDir/Tak0-Per-Window-Switch.sh
-bindd = $mainMod ALT, C, calculator, exec, $UserScripts/RofiCalc.sh
+bindd = $mainMod SHIFT, M, Online music, exec, $UserScripts/RofiBeats.sh
+bindd = $mainMod, W, Select Wallpaper, exec, $UserScripts/WallpaperSelect.sh
+bindd = $mainMod SHIFT, W, Wallpaper effects, exec, $UserScripts/WallpaperEffects.sh
+bindd = CTRL ALT, W, Random wallpaper, exec, $UserScripts/WallpaperRandom.sh
+bindd = $mainMod CTRL, O, Toggle active window opacity, setprop, active opaque toggle
+bindd = $mainMod SHIFT, K, Search keybinds, exec, $scriptsDir/KeyBinds.sh
+bindd = $mainMod SHIFT, A, Animations menu, exec, $scriptsDir/Animations.sh
+bindd = $mainMod SHIFT, O, Change ZSH (oh-my-zsh) theme, exec, $UserScripts/ZshChangeTheme.sh
+bindlnd = ALT_L, SHIFT_L, Switch keyboard layout globally, exec, $scriptsDir/KeyboardLayout.sh switch
+bindlnd = SHIFT_L, ALT_L, Switch keyboard layout per-window, exec, $scriptsDir/Tak0-Per-Window-Switch.sh
+bindd = $mainMod ALT, C, Calculator, exec, $UserScripts/RofiCalc.sh
# Move current workspaces to monitors (left right up or down)
-bindd = $mainMod CTRL, F9, move workspace to left monitor, movecurrentworkspacetomonitor, l
-bindd = $mainMod CTRL, F10, move workspace to right monitor, movecurrentworkspacetomonitor, r
-bindd = $mainMod CTRL, F11, move workspace to up monitor, movecurrentworkspacetomonitor, u
-bindd = $mainMod CTRL, F12, move workspace to down monitor, movecurrentworkspacetomonitor, d
+bindd = $mainMod CTRL, F9, Move workspace to left monitor, movecurrentworkspacetomonitor, l
+bindd = $mainMod CTRL, F10, Move workspace to right monitor, movecurrentworkspacetomonitor, r
+bindd = $mainMod CTRL, F11, Move workspace to up monitor, movecurrentworkspacetomonitor, u
+bindd = $mainMod CTRL, F12, Move workspace to down monitor, movecurrentworkspacetomonitor, d
#### SYSTEM ####
-bindd = CTRL ALT, Delete, exit Hyprland, exec, hyprctl dispatch exit 0
-bindd = $mainMod, Q, close active window, killactive,
+bindd = CTRL ALT,Delete, Exit Hyprland, exec, $scriptsDir/Logout.sh
+bindd = $mainMod, Q, Close active window, killactive,
bindd = $mainMod SHIFT, Q, Terminate active process, exec, $scriptsDir/KillActiveProcess.sh
-bindd = CTRL ALT, L, lock screen, exec, $scriptsDir/LockScreen.sh
-bindd = CTRL ALT, P, powermenu, exec, $scriptsDir/Wlogout.sh
-bindd = $mainMod SHIFT, N, notification panel, exec, swaync-client -t -sw
+bindd = CTRL ALT, L, Lock screen, exec, $scriptsDir/LockScreen.sh
+bindd = CTRL ALT, P, Powermenu, exec, $scriptsDir/Wlogout.sh
+bindd = $mainMod SHIFT, N, Notification panel, exec, swaync-client -t -sw
bindd = $mainMod SHIFT, E, Quick settings menu, exec, $scriptsDir/Kool_Quick_Settings.sh
# Master Layout
-bindd = $mainMod CTRL, D, remove master, layoutmsg, removemaster
-bindd = $mainMod, I, add master, layoutmsg, addmaster
+bindd = $mainMod CTRL, D, Remove master, layoutmsg, removemaster
+bindd = $mainMod, I, Add master, layoutmsg, addmaster
# j/k cycle windows globally
-bindd = $mainMod, j, cycle next, layoutmsg, cyclenext
-bindd = $mainMod, k, cycle previous, layoutmsg, cycleprev
-bindd = $mainMod CTRL, Return, swap with master, layoutmsg, swapwithmaster
+bindd = $mainMod, j, Cycle next, cyclenext
+bindd = $mainMod, k, Cycle previous, cyclenext, prev
+bindd = $mainMod CTRL, Return, Swap with master, layoutmsg, swapwithmaster
# Dwindle Layout
-bindd = $mainMod SHIFT, I, toggle split (dwindle), layoutmsg, togglesplit
-bindd = $mainMod, P, toggle pseudo (dwindle), pseudo,
+bindd = $mainMod SHIFT, I, Toggle split (dwindle), layoutmsg, togglesplit
+bindd = $mainMod, P, Toggle pseudo (dwindle), pseudo,
# Works on either layout (Master or Dwindle)
-bindd = $mainMod, M, set split ratio 0.3, exec, hyprctl dispatch splitratio 0.3
+bindd = $mainMod, M, Set split ratio 0.3, exec, hyprctl dispatch splitratio 0.3
# layout aware keybinds
exec-once = $scriptsDir/ChangeLayout.sh init
# Direct layout binds
-bindd = $mainMod ALT, 1, layout dwindle, exec, $scriptsDir/ChangeLayout.sh dwindle
-bindd = $mainMod ALT, 2, layout master, exec, $scriptsDir/ChangeLayout.sh master
-bindd = $mainMod ALT, 3, layout scrolling, exec, $scriptsDir/ChangeLayout.sh scrolling
-bindd = $mainMod ALT, 4, layout monocle, exec, $scriptsDir/ChangeLayout.sh monocle
+bindd = $mainMod ALT, 1, Layout dwindle, exec, $scriptsDir/ChangeLayout.sh dwindle
+bindd = $mainMod ALT, 2, Layout master, exec, $scriptsDir/ChangeLayout.sh master
+bindd = $mainMod ALT, 3, Layout scrolling, exec, $scriptsDir/ChangeLayout.sh scrolling
+bindd = $mainMod ALT, 4, Layout monocle, exec, $scriptsDir/ChangeLayout.sh monocle
# Scrolling Layout
-bindd = $mainMod SHIFT, period, move to right column, layoutmsg, move +col
-bindd = $mainMod SHIFT, comma, move to left column, layoutmsg, move -col
-bindd = $mainMod ALT, comma, swap columns left, layoutmsg, swapcol l
-bindd = $mainMod ALT, period, swap columns right, layoutmsg, swapcol r
+bindd = $mainMod SHIFT, period, Move to right column, layoutmsg, move +col
+bindd = $mainMod SHIFT, comma, Move to left column, layoutmsg, move -col
+bindd = $mainMod ALT, comma, Swap columns left, layoutmsg, swapcol l
+bindd = $mainMod ALT, period, Swap columns right, layoutmsg, swapcol r
# Set layout to Horizontal (Standard "Tape" style)
bindd = $mainMod ALT, H, Horizonal scroll right,exec, hyprctl keyword scrolling:direction right
# Set layout to Vertical (Stacked "Column" style)
bindd = $mainMod ALT, V, Vertical Scroll down,exec, hyprctl keyword scrolling:direction down
# Create a toggle bind (e.g., Mod + Shift + S)
-bindd = $mainMod ALT, S, toggle scrolling V/H, exec, bash -c '[[ $(hyprctl getoption scrolling:direction -j | jq -r ".str") == "right" ]] && hyprctl keyword scrolling:direction down || hyprctl keyword scrolling:direction right'
+bindd = $mainMod ALT, S, Toggle scrolling V/H, exec, bash -c '[[ $(hyprctl getoption scrolling:direction -j | jq -r ".str") == "right" ]] && hyprctl keyword scrolling:direction down || hyprctl keyword scrolling:direction right'
# Cycle windows; if floating bring to top
-bindd = ALT, tab, cycle next window, cyclenext
-bindd = ALT, tab, bring active to top, bringactivetotop
+bindd = ALT, Tab, Cycle next window, cyclenext
+bindd = ALT, Tab, Bring active to top, bringactivetotop
# Special Keys / Hot Keys
-bindeld = , xf86audioraisevolume, volume up, exec, $scriptsDir/Volume.sh --inc
-bindeld = , xf86audiolowervolume, volume down, exec, $scriptsDir/Volume.sh --dec
-bindeld = ALT, xf86audioraisevolume, volume up precise, exec, $scriptsDir/Volume.sh --inc-precise
-bindeld = ALT, xf86audiolowervolume, volume down precise, exec, $scriptsDir/Volume.sh --dec-precise
-bindld = , xf86AudioMicMute, toggle mic mute, exec, $scriptsDir/Volume.sh --toggle-mic
-bindld = , xf86audiomute, toggle mute, exec, $scriptsDir/Volume.sh --toggle
-bindld = , xf86Sleep, sleep, exec, systemctl suspend
-bindld = , xf86Rfkill, airplane mode, exec, $scriptsDir/AirplaneMode.sh
+bindeld = , xf86audioraisevolume, Volume up, exec, $scriptsDir/Volume.sh --inc
+bindeld = , xf86audiolowervolume, Volume down, exec, $scriptsDir/Volume.sh --dec
+bindeld = ALT, xf86audioraisevolume, Volume up precise, exec, $scriptsDir/Volume.sh --inc-precise
+bindeld = ALT, xf86audiolowervolume, Volume down precise, exec, $scriptsDir/Volume.sh --dec-precise
+bindld = , xf86AudioMicMute, Toggle mic mute, exec, $scriptsDir/Volume.sh --toggle-mic
+bindld = , xf86audiomute, Toggle mute, exec, $scriptsDir/Volume.sh --toggle
+bindld = , xf86Sleep, Sleep, exec, systemctl suspend
+bindld = , xf86Rfkill, Airplane mode, exec, $scriptsDir/AirplaneMode.sh
# media controls using keyboards
-bindld = , xf86AudioPlayPause, play/pause, exec, $scriptsDir/MediaCtrl.sh --pause
-bindld = , xf86AudioPause, pause, exec, $scriptsDir/MediaCtrl.sh --pause
-bindld = , xf86AudioPlay, play, exec, $scriptsDir/MediaCtrl.sh --pause
-bindld = , xf86AudioNext, next track, exec, $scriptsDir/MediaCtrl.sh --nxt
-bindld = , xf86AudioPrev, previous track, exec, $scriptsDir/MediaCtrl.sh --prv
-bindld = , xf86audiostop, stop, exec, $scriptsDir/MediaCtrl.sh --stop
+bindld = , xf86AudioPlayPause, Play/pause, exec, $scriptsDir/MediaCtrl.sh --pause
+bindld = , xf86AudioPause, Pause, exec, $scriptsDir/MediaCtrl.sh --pause
+bindld = , xf86AudioPlay, Play, exec, $scriptsDir/MediaCtrl.sh --pause
+bindld = , xf86AudioNext, Next track, exec, $scriptsDir/MediaCtrl.sh --nxt
+bindld = , xf86AudioPrev, Previous track, exec, $scriptsDir/MediaCtrl.sh --prv
+bindld = , xf86audiostop, Stop, exec, $scriptsDir/MediaCtrl.sh --stop
# Screenshot keybindings NOTE: You may need to press Fn key as well
-bindd = $mainMod, Print, screenshot now, exec, $scriptsDir/ScreenShot.sh --now
-bindd = $mainMod SHIFT, Print, screenshot (area), exec, $scriptsDir/ScreenShot.sh --area
-bindd = $mainMod CTRL, Print, screenshot in 5s, exec, $scriptsDir/ScreenShot.sh --in5
-bindd = $mainMod CTRL SHIFT, Print, screenshot in 10s, exec, $scriptsDir/ScreenShot.sh --in10
-bindd = ALT, Print, screenshot active window, exec, $scriptsDir/ScreenShot.sh --active
+bindd = $mainMod, Print, Screenshot now, exec, $scriptsDir/ScreenShot.sh --now
+bindd = $mainMod SHIFT, Print, Screenshot (area), exec, $scriptsDir/ScreenShot.sh --area
+bindd = $mainMod CTRL, Print, Screenshot in 5s, exec, $scriptsDir/ScreenShot.sh --in5
+bindd = $mainMod CTRL SHIFT, Print, Screenshot in 10s, exec, $scriptsDir/ScreenShot.sh --in10
+bindd = ALT, Print, Screenshot active window, exec, $scriptsDir/ScreenShot.sh --active
# screenshot with swappy (another screenshot tool)
-bindd = $mainMod SHIFT, S, screenshot (swappy), exec, $scriptsDir/ScreenShot.sh --swappy
+bindd = $mainMod SHIFT, S, Screenshot (swappy), exec, $scriptsDir/ScreenShot.sh --swappy
# Resize windows
-binded = $mainMod SHIFT, left, resize left (-50), resizeactive, -50 0
-binded = $mainMod SHIFT, right, resize right (+50), resizeactive, 50 0
-binded = $mainMod SHIFT, up, resize up (-50), resizeactive, 0 -50
-binded = $mainMod SHIFT, down, resize down (+50), resizeactive, 0 50
+binded = $mainMod SHIFT, left, Resize left (-50), resizeactive, -50 0
+binded = $mainMod SHIFT, right, Resize right (+50), resizeactive, 50 0
+binded = $mainMod SHIFT, up, Resize up (-50), resizeactive, 0 -50
+binded = $mainMod SHIFT, down, Resize down (+50), resizeactive, 0 50
# Move windows
-bindd = $mainMod CTRL, left, move window left, movewindow, l
-bindd = $mainMod CTRL, right, move window right, movewindow, r
-bindd = $mainMod CTRL, up, move window up, movewindow, u
-bindd = $mainMod CTRL, down, move window down, movewindow, d
+bindd = $mainMod CTRL, left, Move window left, movewindow, l
+bindd = $mainMod CTRL, right, Move window right, movewindow, r
+bindd = $mainMod CTRL, up, Move window up, movewindow, u
+bindd = $mainMod CTRL, down, Move window down, movewindow, d
# Swap windows
-bindd = $mainMod ALT, left, swap window left, swapwindow, l
-bindd = $mainMod ALT, right, swap window right, swapwindow, r
-bindd = $mainMod ALT, up, swap window up, swapwindow, u
-bindd = $mainMod ALT, down, swap window down, swapwindow, d
+bindd = $mainMod ALT, left, Swap window left, swapwindow, l
+bindd = $mainMod ALT, right, Swap window right, swapwindow, r
+bindd = $mainMod ALT, up, Swap window up, swapwindow, u
+bindd = $mainMod ALT, down, Swap window down, swapwindow, d
# group
-bindd = $mainMod, G, toggle group, togglegroup
+bindd = $mainMod, G, Toggle group, togglegroup
# Navigate within a group
bindd = $mainMod, Tab, Change Group Forward, changegroupactive, f
-bindd = $mainMod CTRL, tab, change active in group, changegroupactive
+bindd = $mainMod CTRL, tab, Change active in group, changegroupactive
bindd = $mainMod SHIFT, Tab, Change Group Back, changegroupactive, b
# Move window into/out of group
@@ -193,71 +195,71 @@ bindd = $mainMod CTRL, H, Move active out of group, moveoutofgroup # Move active
# Try to dynamically move in grouped window and when ungrouped
# Not working for me DW 11/26/25 PR: https://github.com/LinuxBeginnings/Hyprland-Dots/pull/872
-#bindd = $mainMod, right, focus right, exec, bash -c 'if hyprctl activewindow -j | jq -e "((.grouped | type) == \"boolean\") or (.address == (.grouped[-1] // empty))" >/dev/null 2>&1; then hyprctl dispatch movefocus r; else hyprctl dispatch changegroupactive f; fi'
-#bindd = $mainMod, left, focus left, exec, bash -c 'if hyprctl activewindow -j | jq -e "((.grouped | type) == \"boolean\") or (.address == (.grouped[0] // empty))" >/dev/null 2>&1; then hyprctl dispatch movefocus l; else hyprctl dispatch changegroupactive b; fi'
+#bindd = $mainMod, right, Focus right, exec, bash -c 'if hyprctl activewindow -j | jq -e "((.grouped | type) == \"boolean\") or (.address == (.grouped[-1] // empty))" >/dev/null 2>&1; then hyprctl dispatch movefocus r; else hyprctl dispatch changegroupactive f; fi'
+#bindd = $mainMod, left, Focus left, exec, bash -c 'if hyprctl activewindow -j | jq -e "((.grouped | type) == \"boolean\") or (.address == (.grouped[0] // empty))" >/dev/null 2>&1; then hyprctl dispatch movefocus l; else hyprctl dispatch changegroupactive b; fi'
# Move focus with mainMod + arrow keys
-bindd = $mainMod, left, focus left, movefocus, l
-bindd = $mainMod, right, focus right, movefocus, r
-bindd = $mainMod, up, focus up, movefocus, u
-bindd = $mainMod, down, focus down, movefocus, d
+bindd = $mainMod, left, Focus left, movefocus, l
+bindd = $mainMod, right, Focus right, movefocus, r
+bindd = $mainMod, up, Focus up, movefocus, u
+bindd = $mainMod, down, Focus down, movefocus, d
# Workspaces related
-bindd = $mainMod, tab, next workspace, workspace, m+1
-bindd = $mainMod SHIFT, tab, previous workspace, workspace, m-1
+bindd = $mainMod, tab, Next workspace, workspace, m+1
+bindd = $mainMod SHIFT, tab, Previous workspace, workspace, m-1
# Special workspace
-bindd = $mainMod SHIFT, U, move to special workspace, movetoworkspace, special
-bindd = $mainMod, U, toggle special workspace, togglespecialworkspace,
+bindd = $mainMod SHIFT, U, Move to special workspace, movetoworkspace, special
+bindd = $mainMod, U, Toggle special workspace, togglespecialworkspace,
# The following mappings use the key codes to better support various keyboard layouts
# 1 is code:10, 2 is code 11, etc
# Switch workspaces with mainMod + [0-9]
-bindd = $mainMod, code:10, workspace 1, workspace, 1 # NOTE: code:10 = key 1
-bindd = $mainMod, code:11, workspace 2, workspace, 2 # NOTE: code:11 = key 2
-bindd = $mainMod, code:12, workspace 3, workspace, 3 # NOTE: code:12 = key 3
-bindd = $mainMod, code:13, workspace 4, workspace, 4 # NOTE: code:13 = key 4
-bindd = $mainMod, code:14, workspace 5, workspace, 5 # NOTE: code:14 = key 5
-bindd = $mainMod, code:15, workspace 6, workspace, 6 # NOTE: code:15 = key 6
-bindd = $mainMod, code:16, workspace 7, workspace, 7 # NOTE: code:16 = key 7
-bindd = $mainMod, code:17, workspace 8, workspace, 8 # NOTE: code:17 = key 8
-bindd = $mainMod, code:18, workspace 9, workspace, 9 # NOTE: code:18 = key 9
-bindd = $mainMod, code:19, workspace 10, workspace, 10 # NOTE: code:19 = key 0
+bindd = $mainMod, code:10, Workspace 1, workspace, 1 # NOTE: code:10 = key 1
+bindd = $mainMod, code:11, Workspace 2, workspace, 2 # NOTE: code:11 = key 2
+bindd = $mainMod, code:12, Workspace 3, workspace, 3 # NOTE: code:12 = key 3
+bindd = $mainMod, code:13, Workspace 4, workspace, 4 # NOTE: code:13 = key 4
+bindd = $mainMod, code:14, Workspace 5, workspace, 5 # NOTE: code:14 = key 5
+bindd = $mainMod, code:15, Workspace 6, workspace, 6 # NOTE: code:15 = key 6
+bindd = $mainMod, code:16, Workspace 7, workspace, 7 # NOTE: code:16 = key 7
+bindd = $mainMod, code:17, Workspace 8, workspace, 8 # NOTE: code:17 = key 8
+bindd = $mainMod, code:18, Workspace 9, workspace, 9 # NOTE: code:18 = key 9
+bindd = $mainMod, code:19, Workspace 10, workspace, 10 # NOTE: code:19 = key 0
# Move active window and follow to workspace mainMod + SHIFT [0-9]
-bindd = $mainMod SHIFT, code:10, move to workspace 1, movetoworkspace, 1 # NOTE: code:10 = key 1
-bindd = $mainMod SHIFT, code:11, move to workspace 2, movetoworkspace, 2 # NOTE: code:11 = key 2
-bindd = $mainMod SHIFT, code:12, move to workspace 3, movetoworkspace, 3 # NOTE: code:12 = key 3
-bindd = $mainMod SHIFT, code:13, move to workspace 4, movetoworkspace, 4 # NOTE: code:13 = key 4
-bindd = $mainMod SHIFT, code:14, move to workspace 5, movetoworkspace, 5 # NOTE: code:14 = key 5
-bindd = $mainMod SHIFT, code:15, move to workspace 6, movetoworkspace, 6 # NOTE: code:15 = key 6
-bindd = $mainMod SHIFT, code:16, move to workspace 7, movetoworkspace, 7 # NOTE: code:16 = key 7
-bindd = $mainMod SHIFT, code:17, move to workspace 8, movetoworkspace, 8 # NOTE: code:17 = key 8
-bindd = $mainMod SHIFT, code:18, move to workspace 9, movetoworkspace, 9 # NOTE: code:18 = key 9
-bindd = $mainMod SHIFT, code:19, move to workspace 10, movetoworkspace, 10 # NOTE: code:19 = key 0
-bindd = $mainMod SHIFT, bracketleft, move to previous workspace, movetoworkspace, -1 # brackets [
-bindd = $mainMod SHIFT, bracketright, move to next workspace, movetoworkspace, +1 # brackets ]
+bindd = $mainMod SHIFT, code:10, Move to workspace 1, movetoworkspace, 1 # NOTE: code:10 = key 1
+bindd = $mainMod SHIFT, code:11, Move to workspace 2, movetoworkspace, 2 # NOTE: code:11 = key 2
+bindd = $mainMod SHIFT, code:12, Move to workspace 3, movetoworkspace, 3 # NOTE: code:12 = key 3
+bindd = $mainMod SHIFT, code:13, Move to workspace 4, movetoworkspace, 4 # NOTE: code:13 = key 4
+bindd = $mainMod SHIFT, code:14, Move to workspace 5, movetoworkspace, 5 # NOTE: code:14 = key 5
+bindd = $mainMod SHIFT, code:15, Move to workspace 6, movetoworkspace, 6 # NOTE: code:15 = key 6
+bindd = $mainMod SHIFT, code:16, Move to workspace 7, movetoworkspace, 7 # NOTE: code:16 = key 7
+bindd = $mainMod SHIFT, code:17, Move to workspace 8, movetoworkspace, 8 # NOTE: code:17 = key 8
+bindd = $mainMod SHIFT, code:18, Move to workspace 9, movetoworkspace, 9 # NOTE: code:18 = key 9
+bindd = $mainMod SHIFT, code:19, Move to workspace 10, movetoworkspace, 10 # NOTE: code:19 = key 0
+bindd = $mainMod SHIFT, bracketleft, Move to previous workspace, movetoworkspace, -1 # brackets [
+bindd = $mainMod SHIFT, bracketright, Move to next workspace, movetoworkspace, +1 # brackets ]
# Move active window to a workspace silently mainMod + CTRL [0-9]
-bindd = $mainMod CTRL, code:10, move silently to workspace 1, movetoworkspacesilent, 1 # NOTE: code:10 = key 1
-bindd = $mainMod CTRL, code:11, move silently to workspace 2, movetoworkspacesilent, 2 # NOTE: code:11 = key 2
-bindd = $mainMod CTRL, code:12, move silently to workspace 3, movetoworkspacesilent, 3 # NOTE: code:12 = key 3
-bindd = $mainMod CTRL, code:13, move silently to workspace 4, movetoworkspacesilent, 4 # NOTE: code:13 = key 4
-bindd = $mainMod CTRL, code:14, move silently to workspace 5, movetoworkspacesilent, 5 # NOTE: code:14 = key 5
-bindd = $mainMod CTRL, code:15, move silently to workspace 6, movetoworkspacesilent, 6 # NOTE: code:15 = key 6
-bindd = $mainMod CTRL, code:16, move silently to workspace 7, movetoworkspacesilent, 7 # NOTE: code:16 = key 7
-bindd = $mainMod CTRL, code:17, move silently to workspace 8, movetoworkspacesilent, 8 # NOTE: code:17 = key 8
-bindd = $mainMod CTRL, code:18, move silently to workspace 9, movetoworkspacesilent, 9 # NOTE: code:18 = key 9
-bindd = $mainMod CTRL, code:19, move silently to workspace 10, movetoworkspacesilent, 10 # NOTE: code:19 = key 0
-bindd = $mainMod CTRL, bracketleft, move silently to previous workspace, movetoworkspacesilent, -1 # brackets [
-bindd = $mainMod CTRL, bracketright, move silently to next workspace, movetoworkspacesilent, +1 # brackets ]
+bindd = $mainMod CTRL, code:10, Move silently to workspace 1, movetoworkspacesilent, 1 # NOTE: code:10 = key 1
+bindd = $mainMod CTRL, code:11, Move silently to workspace 2, movetoworkspacesilent, 2 # NOTE: code:11 = key 2
+bindd = $mainMod CTRL, code:12, Move silently to workspace 3, movetoworkspacesilent, 3 # NOTE: code:12 = key 3
+bindd = $mainMod CTRL, code:13, Move silently to workspace 4, movetoworkspacesilent, 4 # NOTE: code:13 = key 4
+bindd = $mainMod CTRL, code:14, Move silently to workspace 5, movetoworkspacesilent, 5 # NOTE: code:14 = key 5
+bindd = $mainMod CTRL, code:15, Move silently to workspace 6, movetoworkspacesilent, 6 # NOTE: code:15 = key 6
+bindd = $mainMod CTRL, code:16, Move silently to workspace 7, movetoworkspacesilent, 7 # NOTE: code:16 = key 7
+bindd = $mainMod CTRL, code:17, Move silently to workspace 8, movetoworkspacesilent, 8 # NOTE: code:17 = key 8
+bindd = $mainMod CTRL, code:18, Move silently to workspace 9, movetoworkspacesilent, 9 # NOTE: code:18 = key 9
+bindd = $mainMod CTRL, code:19, Move silently to workspace 10, movetoworkspacesilent, 10 # NOTE: code:19 = key 0
+bindd = $mainMod CTRL, bracketleft, Move silently to previous workspace, movetoworkspacesilent, -1 # brackets [
+bindd = $mainMod CTRL, bracketright, Move silently to next workspace, movetoworkspacesilent, +1 # brackets ]
# Scroll through existing workspaces with mainMod + scroll
-bindd = $mainMod, mouse_down, next workspace, workspace, e+1
-bindd = $mainMod, mouse_up, previous workspace, workspace, e-1
-bindd = $mainMod, period, next workspace, workspace, e+1
-bindd = $mainMod, comma, previous workspace, workspace, e-1
+bindd = $mainMod, mouse_down, Next workspace, workspace, e+1
+bindd = $mainMod, mouse_up, Previous workspace, workspace, e-1
+bindd = $mainMod, period, Next workspace, workspace, e+1
+bindd = $mainMod, comma, Previous workspace, workspace, e-1
# Move/resize windows with mainMod + LMB/RMB and dragging
-bindmd = $mainMod, mouse:272, move window, movewindow # NOTE: mouse:272 = left click
-bindmd = $mainMod, mouse:273, resize window, resizewindow # NOTE: mouse:272 = right click
+bindmd = $mainMod, mouse:272, Move window, movewindow # NOTE: mouse:272 = left click
+bindmd = $mainMod, mouse:273, Resize window, resizewindow # NOTE: mouse:272 = right click
diff --git a/config/hypr/configs/LayerRules.conf b/config/hypr/configs/LayerRules.conf
new file mode 100644
index 00000000..a5b1ea0f
--- /dev/null
+++ b/config/hypr/configs/LayerRules.conf
@@ -0,0 +1,26 @@
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# Vendor defaults for layerrules
+# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
+
+# LAYER RULES
+layerrule = match:namespace rofi, blur on, ignore_alpha 0, animation slide
+layerrule = match:namespace notifications, blur on, ignore_alpha 0, animation slide
+layerrule = match:namespace quickshell:overview, blur on, ignore_alpha 0.5
+layerrule = match:namespace wallpaper, blur on, ignore_alpha 0
+
+# swaync + helper overlays
+layerrule = match:namespace swaync-control-center, blur on, ignore_alpha 0
+layerrule = match:namespace swaync-notification-window, blur on, ignore_alpha 0
+layerrule = match:namespace com.aurora.keybinds_help, blur on, ignore_alpha 0
+layerrule = match:namespace logout_dialog, blur on, ignore_alpha 0
+
+# Optional Layer rules
+# To Resolve blurred corners in rofi Add to User config
+# SUPER SHIFT + E Edit User Layer Rules
+#layerrule = blur on, ignore_alpha 0, match:namespace rofi
+#layerrule = blur on, match:namespace waybar
diff --git a/config/hypr/configs/Startup_Apps.conf b/config/hypr/configs/Startup_Apps.conf
index a27a12b9..bf8b3b4b 100644
--- a/config/hypr/configs/Startup_Apps.conf
+++ b/config/hypr/configs/Startup_Apps.conf
@@ -13,7 +13,7 @@ $livewallpaper=""
$wallDIR = $HOME/Pictures/wallpapers # change path manually here if needed
### wallpaper stuff ###
-exec-once = $scriptsDir/WallpaperDaemon.sh
+exec-once = sh -c 'sleep 2; $HOME/.config/hypr/scripts/WallpaperDaemon.sh'
#exec-once = mpvpaper '*' -o "load-scripts=no no-audio --loop" $livewallpaper
# wallpaper random
#exec-once = $SwwwRandom $wallDIR # random wallpaper switcher every 30 minutes
@@ -21,19 +21,21 @@ exec-once = $scriptsDir/WallpaperDaemon.sh
### Startup ###
exec-once = dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
exec-once = systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
-exec-once = $HOME/.config/hypr/scripts/Dropterminal.sh "kitty --class kitty-dropterm" &
exec-once = $scriptsDir/Polkit.sh
-exec-once = nm-applet --indicator
+exec-once = nm-applet
exec-once = nm-tray # For ubuntu
exec-once = swaync
#exec-once = ags
#exec-once = blueman-applet
#exec-once = rog-control-center
-exec-once = $scriptsDir/PortalHyprlandUbuntu.sh
-exec-once = waybar
+exec-once = $scriptsDir/PortalHyprland.sh
+exec-once = sh $scriptsDir/WaybarStartup.sh
exec-once = qs -c overview # Quickshell Overview
exec-once = hypridle
+exec-once = $scriptsDir/LuaAutoReload.sh
exec-once = $scriptsDir/Hyprsunset.sh init
+# NOTE: Dropterminal is currently certified only with kitty. Not all terminals behave correctly as a dropdown.
+exec-once = $scriptsDir/Dropterminal.sh --startup kitty
# Clipboard manager
exec-once = wl-paste --type text --watch cliphist store
@@ -52,3 +54,5 @@ exec-once = wl-paste --type image --watch cliphist store
# xdg-desktop-portal-hyprland (should be auto starting. However, you can force to start)
#exec-once = $scriptsDir/PortalHyprland.sh
+exec-once = blueman-applet
+exec-once = $scriptsDir/KeybindsLayoutInit.sh
diff --git a/config/hypr/configs/Startup_Apps.disable b/config/hypr/configs/Startup_Apps.disable
new file mode 100644
index 00000000..3b2a5bd4
--- /dev/null
+++ b/config/hypr/configs/Startup_Apps.disable
@@ -0,0 +1 @@
+$scriptsDir/Polkit.sh
diff --git a/config/hypr/configs/SystemSettings.conf b/config/hypr/configs/SystemSettings.conf
index 6621ffe2..8e64a78a 100644
--- a/config/hypr/configs/SystemSettings.conf
+++ b/config/hypr/configs/SystemSettings.conf
@@ -5,7 +5,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# ==================================================
# Default settings
-# This is where you put your own settings as this will not be touched during update
+# This is where you put your own settings as this will not be touched during update
# if the upgrade.sh is used.
# refer to Hyprland wiki for more info https://wiki.hyprland.org/Configuring/Variables/
@@ -14,9 +14,10 @@
$scriptsDir = $HOME/.config/hypr/scripts
dwindle {
- preserve_split = true
- smart_resizing = true
- use_active_for_splits = true
+ #pseudotile = false # Not supported 0.55+
+ preserve_split = true
+ smart_resizing = true
+ use_active_for_splits = true
smart_split = false
default_split_ratio = 1.0
split_bias = 0
@@ -73,18 +74,18 @@ input {
touchpad {
disable_while_typing = true
- natural_scroll = true
+ natural_scroll = true
clickfinger_behavior = false
middle_button_emulation = false
tap-to-click = true
drag_lock = false
}
-
+
# below for devices with touchdevice ie. touchscreen
touchdevice {
enabled = true
}
-
+
# below is for table see link above for proper variables
tablet {
transform = 0
@@ -106,15 +107,18 @@ gestures {
gesture = 3, horizontal, workspace
gesture = 3, up, dispatcher, exec, hyprctl keyword cursor:zoom_factor "$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {factor = $2; if (factor < 1) {factor = 1}; print factor * 1.5}')"
- gesture = 3, down, dispatcher, exec, hyprctl keyword cursor:zoom_factor "$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {factor = $2; if (factor < 1) {factor = 1}; print factor / 1.5}')"
- gesture = 4, up, dispatcher, exec, $scriptsDir/OverviewToggle.sh
+ gesture = 3, down, dispatcher, exec, hyprctl keyword cursor:zoom_factor "$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {factor = $2; if (factor < 1) {factor = 1}; print factor / 1.5}')"
+ gesture = 4, up, dispatcher, exec, $scriptsDir/OverviewToggle.sh
gesture = 4, down, float
}
misc {
disable_hyprland_logo = true
disable_splash_rendering = true
- vrr = 2
+ force_default_wallpaper = false
+ # vfr = true # Not supported past v0.54.3
+ vrr = 0 # Disabling by default causes MPV to black screen when maximixes
+ #vrr = 0,disabled, 1, alweays on, 2, only on when fullscreen
mouse_move_enables_dpms = true
enable_swallow = off
swallow_regex = ^(kitty)$
@@ -156,12 +160,12 @@ cursor {
no_hardware_cursors = 2 # change to 1 if want to disable
enable_hyprcursor = true
warp_on_change_workspace = 2
- no_warps = true
+ no_warps = true
no_break_fs_vrr = false
min_refresh_rate = 24
hotspot_padding = 1
inactive_timeout = 0
- default_monitor =
+ default_monitor =
zoom_factor = 1.0
zoom_rigid = false
zoom_detached_camera = true
diff --git a/config/hypr/configs/WindowRules-config-v3.conf b/config/hypr/configs/WindowRules-config-v3.conf
deleted file mode 100644
index aab7d005..00000000
--- a/config/hypr/configs/WindowRules-config-v3.conf
+++ /dev/null
@@ -1,470 +0,0 @@
-# ==================================================
-# KoolDots (2026)
-# Project URL: https://github.com/LinuxBeginnings
-# License: GNU GPLv3
-# SPDX-License-Identifier: GPL-3.0-or-later
-# ==================================================
-# Vendor defaults for window rules and layerrules
-# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
-
-# NOTES: This is only for Hyprland >= 0.53
-
-# Some samples on hwo to start apps on specific workspaces
-# windowrule = match:tag email*, workspace 1
-# windowrule = match:tag browser*, workspace 2
-# windowrule = match:tag projects*, workspace 3
-# windowrule = match:tag screenshare*, workspace 4 silent
-# windowrule = match:tag gamestore*, workspace 5
-# windowrule = match:class ^(virt-manager)$, workspace 6 silent
-# windowrule = match:class ^(.virt-manager-wrapped)$, workspace 6 silent
-# windowrule = match:tag im*, workspace 7
-# windowrule = match:class obsidian, workspace 8
-# windowrule = match:tag games*, workspace 8
-# windowrule = match:tag multimedia*, workspace 9 silent
-
-# TAGS - add apps under appropriate tag to use the same settings
-# browser tags
-windowrule = match:class ^([Ff]irefox|org.mozilla.firefox|[Ff]irefox-esr|[Ff]irefox-bin)$, tag +browser
-windowrule = match:class ^([Gg]oogle-chrome(-beta|-dev|-unstable)?)$, tag +browser
-windowrule = match:class ^(chrome-.+-Default)$, tag +browser
-windowrule = match:class ^([Cc]hromium)$, tag +browser
-windowrule = match:class ^([Mm]icrosoft-edge(-stable|-beta|-dev|-unstable))$, tag +browser
-windowrule = match:class ^([Bb]rave-browser(-beta|-dev|-unstable)?)$, tag +browser
-windowrule = match:class ^([Tt]horium-browser|[Cc]achy-browser)$, tag +browser
-windowrule = match:class ^(zen-alpha|zen)$, tag +browser
-
-# notif tags
-windowrule = match:class ^(swaync-control-center|swaync-notification-window|swaync-client|class)$, tag +notif
-
-# KooL settings tag
-windowrule = match:title ^(KooL Quick Cheat Sheet)$, tag +KooL_Cheat
-windowrule = match:title ^(KooL Hyprland Settings)$, tag +KooL_Settings
-windowrule = match:class ^(nwg-displays|nwg-look)$, tag +KooL-Settings
-
-# terminal tags
-windowrule = match:class ^(ghostty|wezterm|Alacritty|kitty|kitty-dropterm)$, tag +terminal
-
-# email tags
-windowrule = match:class ^([Tt]hunderbird|org.mozilla.Thunderbird)$, tag +email
-windowrule = match:class ^(eu.betterbird.Betterbird)$, tag +email
-windowrule = match:class ^(org.gnome.Evolution)$, tag +email
-
-# project tags
-windowrule = match:class ^(codium|codium-url-handler|VSCodium)$, tag +projects
-windowrule = match:class ^(VSCode|code|code-url-handler)$, tag +projects
-windowrule = match:class ^(jetbrains-.+)$, tag +projects
-windowrule = match:class ^(dev.zed.Zed|antigravity)$, tag +projects
-
-# screenshare tags
-windowrule = match:class ^(com.obsproject.Studio)$, tag +screenshare
-
-# IM tags
-windowrule = match:class ^([Dd]iscord|[Ww]ebCord|[Vv]esktop)$, tag +im
-windowrule = match:class ^([Ff]erdium)$, tag +im
-windowrule = match:class ^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$, tag +im
-windowrule = match:class ^(org.telegram.desktop|io.github.tdesktop_x64.TDesktop)$, tag +im
-windowrule = match:class ^(teams-for-linux)$, tag +im
-windowrule = match:class ^(im.riot.Riot|Element)$, tag +im
-
-# game tags
-windowrule = match:class ^(gamescope)$, tag +games
-windowrule = match:class ^(steam_app_\\d+)$, tag +games
-windowrule = match:xdg_tag ^(proton-game)$, tag +games
-
-# gamestore tags
-windowrule = match:class ^([Ss]team)$, tag +gamestore
-windowrule = match:title ^([Ll]utris)$, tag +gamestore
-windowrule = match:class ^(com.heroicgameslauncher.hgl)$, tag +gamestore
-
-# file-manager tags
-windowrule = match:class ^([Tt]hunar|org.gnome.Nautilus|[Pp]cmanfm-qt)$, tag +file-manager
-windowrule = match:class ^(app.drey.Warp)$, tag +file-manager
-
-# wallpaper tags
-windowrule = match:class ^([Ww]aytrogen)$, tag +wallpaper
-
-# multimedia tags
-windowrule = match:class ^([Aa]udacious)$, tag +multimedia
-
-# multimedia-video tags
-windowrule = match:class ^([Mm]pv|vlc)$, tag +multimedia_video
-
-# settings tags
-windowrule = match:title ^(ROG Control)$, tag +settings
-windowrule = match:class ^(wihotspot(-gui)?)$, tag +settings
-windowrule = match:class ^([Bb]aobab|org.gnome.[Bb]aobab)$, tag +settings
-windowrule = match:class ^(gnome-disks|wihotspot(-gui)?)$, tag +settings
-windowrule = match:title (Kvantum Manager), tag +settings
-windowrule = match:class ^(file-roller|org.gnome.FileRoller)$, tag +settings
-windowrule = match:class ^(nm-applet|nm-connection-editor|blueman-manager)$, tag +settings
-windowrule = match:class ^(pavucontrol|org.pulseaudio.pavucontrol|com.saivert.pwvucontrol)$, tag +settings
-windowrule = match:class ^(qt5ct|qt6ct)$, tag +settings
-windowrule = match:class (xdg-desktop-portal-gtk), tag +settings
-windowrule = match:class ^(org.kde.polkit-kde-authentication-agent-1)$, tag +settings
-windowrule = match:class ^([Rr]ofi)$, tag +settings
-windowrule = match:class ^(btrfs-assistant)$, tag +settings
-windowrule = match:class ^(timeshift-gtk)$, tag +settings
-
-# viewer tags
-windowrule = match:class ^(gnome-system-monitor|org.gnome.SystemMonitor|io.missioncenter.MissionCenter)$, tag +viewer
-windowrule = match:class ^(evince)$, tag +viewer
-windowrule = match:class ^(eog|org.gnome.Loupe)$, tag +viewer
-
-# Some special override rules
-windowrule = match:tag multimedia, no_blur on
-windowrule = match:tag multimedia, opacity 1.0
-
-# FLOAT
-windowrule = match:class ([Zz]oom|onedriver|onedriver-launcher), float on
-windowrule = match:class ^(mpv|com.github.rafostar.Clapper)$, float on
-windowrule = match:class ^([Qq]alculate-gtk)$, float on
-
-# float popups and dialogue
-windowrule = match:title ^(Authentication Required)$, float on, center on
-windowrule = match:class ^(xfce-polkit|mate-polkit|polkit-mate-authentication-agent-1)$, match:title ^(Authentication required|Authentication Required)$, float on, center on, size (monitor_w*0.35) (monitor_h*0.35)
-windowrule = match:class (codium|codium-url-handler|VSCodium), match:title negative:(.*codium.*|.*VSCodium.*), float on
-windowrule = match:class ^(com.heroicgameslauncher.hgl)$, match:title negative:(Heroic Games Launcher), float on
-windowrule = match:class ^([Ss]team)$, match:title negative:^([Ss]team)$, float on
-windowrule = match:title ^(Add Folder to Workspace)$, float on, size (monitor_w*0.7) (monitor_h*0.6), center on
-windowrule = match:title ^(Save As)$, float on, size (monitor_w*0.7) (monitor_h*0.6), center on
-windowrule = match:initial_title (Open Files), float on, size (monitor_w*0.7) (monitor_h*0.6)
-windowrule = match:title ^(SDDM Background)$, float on, center on, size (monitor_w*0.16) (monitor_h*0.12)
-windowrule = match:class ^(yad)$, float on, center on, size (monitor_w*0.2) (monitor_h*0.2)
-windowrule = match:class ^(hyprland-donate-screen)$, float on, center on
-
-# SIZE
-
-# POSITION
-windowrule = match:title ^(ROG Control)$, center on
-windowrule = match:title ^(Keybindings)$, center on
-windowrule = match:class ^(pavucontrol|org.pulseaudio.pavucontrol|com.saivert.pwvucontrol)$, center on
-windowrule = match:class ^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$, center on
-windowrule = match:class ^(nm-connection-editor)$, center on
-windowrule = match:class ^(nm-applet)$, match:title ^(Wi-Fi Network Authentication Required)$, center on
-
-# windowrule to avoid idle for fullscreen apps
-windowrule = match:fullscreen true, idle_inhibit fullscreen
-windowrule = idle_inhibit fullscreen, match:fullscreen 1
-windowrule = idle_inhibit fullscreen, match:class .*
-windowrule = idle_inhibit fullscreen, match:title .*
-
-# OPACITY
-windowrule = match:tag browser, opacity 0.99 0.8
-windowrule = match:tag projects, opacity 0.9 0.8
-windowrule = match:tag im, opacity 0.94 0.86
-windowrule = match:tag multimedia, opacity 0.94 0.86
-windowrule = match:tag file-manager, opacity 0.9 0.8
-windowrule = match:tag terminal, opacity 0.9 0.7
-windowrule = match:class ^(gedit|org.gnome.TextEditor|mousepad)$, opacity 0.8 0.7
-windowrule = match:class ^(deluge)$, opacity 0.9 0.8
-windowrule = match:class ^(seahorse)$, opacity 0.9 0.8
-
-# BLUR & FULLSCREEN
-
-# This not gonna take the focus to the window that appears
-# when hovering over some of the parts of the IntelliJ Products
-windowrule = match:class ^(jetbrains-.*)$, no_initial_focus on
-windowrule = match:title ^(wind.*)$, no_initial_focus on
-
-# LAYER RULES
-layerrule = match:namespace rofi, blur on
-layerrule = match:namespace notifications, blur on
-layerrule = match:namespace quickshell:overview, blur on
-layerrule = match:namespace quickshell:overview, ignore_alpha 0.5
-
-#
-layerrule = blur on, match:namespace wallpaper
-layerrule = animation slide, match:namespace rofi
-layerrule = animation slide, match:namespace notifications
-
-# Optional Layer rules
-# To Resolve blurred corners in rofi Add to User config
-# SUPER SHIFT + E Edit User Window Rules
-#layerrule = blur on, ignore_alpha 0, match:namespace rofi
-#layerrule = blur on, match:namespace waybar
-
-
-windowrule {
- name = Picture-in-Picture
- match:title = ^[Pp]icture-in-[Pp]icture$
- float = on
- move = 72% 7%
- opacity = 0.95 0.75
- pin = on
- keep_aspect_ratio = on
- size = (monitor_w*0.3) (monitor_h*0.3)
-}
-
-# Named rule for CachyOS Kernel Manager
-windowrule {
- name = CachyOS Kernel Manager
- match:class = ^(org.cachyos.KernelManager)$
- match:title = ^(CachyOS Kernel Manager)$
- match:initial_class = ^(org.cachyos.KernelManager)$
- match:initial_title = ^(CachyOS Kernel Manager)$
- float = on
- center = on
- size = (monitor_w*0.6) (monitor_h*0.6)
-}
-
-# Named rule for Mainline Kernels
-windowrule {
- name = Mainline Kernels
- match:class = ^(mainline-gtk)$
- match:title = ^(Mainline Kernels)$
- match:initial_class = ^(mainline-gtk)$
- match:initial_title = ^(Mainline Kernels)$
- float = on
- center = on
- size = (monitor_w*0.45) (monitor_h*0.55)
-}
-
-# Named rule for Kwallet
-windowrule {
- name = Kwallet
- match:class = ^(org.kde.kwalletmanager)$
- match:title = ^(Wallet Manager)$
- match:initial_class = ^(org.kde.kwalletmanager)$
- match:initial_title = ^(Wallet Manager)$
- float = on
- center = on
- size = (monitor_w*0.6) (monitor_h*0.6)
-}
-# Named rule for NVIDIA Settings
-windowrule {
- name = NVIDIA Settings
- match:class = ^(nvidia-settings)$
- match:title = ^(NVIDIA Settings)$
- match:initial_class = ^(nvidia-settings)$
- match:initial_title = ^(NVIDIA Settings)$
- float = on
- center = on
- size = (monitor_w*0.6) (monitor_h*0.6)
-}
-# Named rule for CachyOS Package Installer
-windowrule {
- name = CachyOS Package Installer
- match:class = ^(org.cachyos.cachyos-pi)$
- match:title = ^(CachyOS Package Installer)$
- match:initial_class = ^(org.cachyos.cachyos-pi)$
- match:initial_title = ^(CachyOS Package Installer)$
- float = on
- center = on
- size = (monitor_w*0.6) (monitor_h*0.6)
-}
-# Named rule for Shelly
-windowrule {
- name = Shelly
- match:class = ^(com.shellyorg.shelly)$
- match:title = ^(Shelly)$
- match:initial_class = ^(com.shellyorg.shelly)$
- match:initial_title = ^(Shelly)$
- float = on
- center = on
- size = (monitor_w*0.6) (monitor_h*0.6)
-}
-
-# Named rule for CachyOS Hello
-windowrule {
- name = CachyOS Hello
- match:class = ^(CachyOSHello)$
- match:title = ^(CachyOS Hello)$
- match:initial_class = ^(CachyOSHello)$
- match:initial_title = ^(CachyOS Hello)$
- float = on
- center = on
- size = (monitor_w*0.6) (monitor_h*0.6)
-}
-
-# Named rule for Cache Cleaner - Octopi
-windowrule {
- name = Cache Cleaner - Octopi
- match:class = ^(octopi-cachecleaner)$
- match:title = ^(Cache Cleaner - Octopi)$
- match:initial_class = ^(octopi-cachecleaner)$
- match:initial_title = ^(Cache Cleaner - Octopi)$
- float = on
- center = on
- size = (monitor_w*0.6) (monitor_h*0.6)
-}
-
-# Named rule for Octopi Package Manager
-windowrule {
- name = Octopi Package Manager
- match:class = ^(octopi)$
- match:title = ^(Octopi)$
- match:initial_class = ^(octopi)$
- match:initial_title = ^(Octopi)$
- float = on
- center = on
- size = (monitor_w*0.6) (monitor_h*0.6)
-}
-
-# Named rule for Repository Editor - Octopi
-windowrule {
- name = Repository Editor - Octopi
- match:class = ^(octopi-repoeditor)$
- match:title = ^(Repository Editor - Octopi)$
- match:initial_class = ^(octopi-repoeditor)$
- match:initial_title = ^(Repository Editor - Octop)$
- float = on
- center = on
- size = (monitor_w*0.6) (monitor_h*0.6)
-}
-
-# Named rule for KooL Cheat (tag)
-windowrule {
- name = KooL Cheat (tag)
- match:tag = KooL_Cheat
- float = on
- center = on
- size = (monitor_w*0.65) (monitor_h*0.9)
-}
-
-# Named rule for Wallpaper (tag)
-windowrule {
- name = Wallpaper (tag)
- match:tag = wallpaper
- float = on
- center = on
- size = (monitor_w*0.7) (monitor_h*0.7)
- opacity = 0.9 0.7
-}
-
-# Named rule for Settings (tag)
-windowrule {
- name = Settings (tag)
- match:tag = settings
- float = on
- center = on
- size = (monitor_w*0.7) (monitor_h*0.7)
- opacity = 0.8 0.7
-}
-
-# Named rule for Viewer (tag)
-windowrule {
- name = Viewer (tag)
- match:tag = viewer
- float = on
- center = on
- opacity = 0.82 0.75
-}
-
-# Named rule for KooL Settings (tag)
-windowrule {
- name = KooL Settings (tag)
- match:tag = KooL-Settings
- float = on
- center = on
-}
-
-# Named rule for Multimedia Video (tag)
-windowrule {
- name = Multimedia Video (tag)
- match:tag = multimedia_video
- no_blur = on
- opacity = 1.0
-}
-
-# Named rule for Games (tag)
-windowrule {
- name = Games (tag)
- match:tag = games
- no_blur = on
- fullscreen = 0
-}
-
-# Named rule for Ferdium
-windowrule {
- name = Ferdium
- match:class = ^([Ff]erdium)$
- float = on
- center = on
- size = (monitor_w*0.6) (monitor_h*0.7)
-}
-
-# Named rule for Calculators
-windowrule {
- name = Calculators
- match:class = (org.gnome.Calculator|qalculate-gtk)
- float = on
- center = on
- size = (monitor_w*0.55) (monitor_h*0.45)
-}
-
-# Named rule for Thunar Dialogs
-windowrule {
- name = Thunar Dialogs
- match:class = ([Tt]hunar)
- match:title = negative:(.*[Tt]hunar.*)
- float = on
- center = on
-}
-
-# Named rule for Bitwarden
-windowrule {
- name = Bitwarden
- match:class = ^(Bitwarden)$
- match:title = ^(Bitwarden)$
- match:initial_class = ^(Bitwarden)$
- match:initial_title = ^(Bitwarden)$
- float = on
- center = on
- size = (monitor_w*0.6) (monitor_h*0.6)
-}
-# Named rule for hyprpwcenter audio control panel
-windowrule {
- name = hyprland audio panel
- match:class = ^(hyprpwcenter)$
- match:initial_class = ^(hyprpwcenter)$
- float = on
- center = on
- size = (monitor_w*0.6) (monitor_h*0.6)
-}
-# Named rule for Garida Assistant
-windowrule {
- name = Garuda Assistant
- match:class = ^(garuda-assistant)$
- match:title = ^(Garuda Assistant)$
- match:initial_class = ^(garuda-assistant)$
- match:initial_title = ^(Garuda Assistant)$
- float = on
- center = on
- size = (monitor_w*0.6) (monitor_h*0.6)
-}
-
-# Named rule for HyprMod HL config GUI
-windowrule {
- name = HyprMod GUI
- match:class = ^(com.github.hyprmod)$
- match:title = ^(HyprMod)$
- match:initial_class = ^(com.github.hyprmod)$
- match:initial_title = ^(HyprMod)$
- float = on
- center = on
- size = (monitor_w*0.7) (monitor_h*0.75)
-}
-# Named rule for easy effects
-windowrule {
- name = EasyEffects
- match:class = ^(com.github.wwmm.easyeffects)$
- match:title = ^(Easy Effects)$
- match:initial_class = ^(com.github.wwmm.easyeffects)$
- match:initial_title = ^(Easy Effects)$
- float = on
- center = on
- size = (monitor_w*0.6) (monitor_h*0.65)
-}
-# Named rule for Mousam weather GUI
-windowrule {
- name = Mousam Weather
- match:class = ^(io.github.amit9838.mousam)$
- match:title = ^(Mousam)$
- match:initial_class = ^(io.github.amit9838.mousam)$
- match:initial_title = ^(Mousam)$
- float = on
- center = on
- size = (monitor_w*0.7) (monitor_h*0.75)
-}
-
-
diff --git a/config/hypr/configs/WindowRules-pre-53.conf b/config/hypr/configs/WindowRules-pre-53.conf
deleted file mode 100644
index fc74f600..00000000
--- a/config/hypr/configs/WindowRules-pre-53.conf
+++ /dev/null
@@ -1,234 +0,0 @@
-# ==================================================
-# KoolDots (2026)
-# Project URL: https://github.com/LinuxBeginnings
-# License: GNU GPLv3
-# SPDX-License-Identifier: GPL-3.0-or-later
-# ==================================================
-# Vendor defaults for window rules and layerrules
-# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
-
-# NOTES: This is only for Hyprland > 0.48
-
-# windowrule - tags - add apps under appropriate tag to use the same settings
-# browser tags
-windowrule = tag +browser, class:^([Ff]irefox|org.mozilla.firefox|[Ff]irefox-esr|[Ff]irefox-bin)$
-windowrule = tag +browser, class:^([Gg]oogle-chrome(-beta|-dev|-unstable)?)$
-windowrule = tag +browser, class:^(chrome-.+-Default)$ # Chrome PWAs
-windowrule = tag +browser, class:^([Cc]hromium)$
-windowrule = tag +browser, class:^([Mm]icrosoft-edge(-stable|-beta|-dev|-unstable))$
-windowrule = tag +browser, class:^(Brave-browser(-beta|-dev|-unstable)?)$
-windowrule = tag +browser, class:^([Tt]horium-browser|[Cc]achy-browser)$
-windowrule = tag +browser, class:^(zen-alpha|zen)$
-
-# notif tags
-windowrule = tag +notif, class:^(swaync-control-center|swaync-notification-window|swaync-client|class)$
-
-# KooL settings tag
-windowrule = tag +KooL_Cheat, title:^(KooL Quick Cheat Sheet)$
-windowrule = tag +KooL_Settings, title:^(KooL Hyprland Settings)$
-windowrule = tag +KooL-Settings, class:^(nwg-displays|nwg-look)$
-
-# terminal tags
-windowrule = tag +terminal, class:^(Alacritty|kitty|kitty-dropterm)$
-
-# email tags
-windowrule = tag +email, class:^([Tt]hunderbird|org.gnome.Evolution)$
-windowrule = tag +email, class:^(eu.betterbird.Betterbird)$
-
-# project tags
-windowrule = tag +projects, class:^(codium|codium-url-handler|VSCodium)$
-windowrule = tag +projects, class:^(VSCode|code|code-url-handler)$
-windowrule = tag +projects, class:^(jetbrains-.+)$ # JetBrains IDEs
-
-# screenshare tags
-windowrule = tag +screenshare, class:^(com.obsproject.Studio)$
-
-# IM tags
-windowrule = tag +im, class:^([Dd]iscord|[Ww]ebCord|[Vv]esktop)$
-windowrule = tag +im, class:^([Ff]erdium)$
-windowrule = tag +im, class:^([Ww]hatsapp-for-linux)$
-windowrule = tag +im, class:^(ZapZap|com.rtosta.zapzap)$
-windowrule = tag +im, class:^(org.telegram.desktop|io.github.tdesktop_x64.TDesktop)$
-windowrule = tag +im, class:^(teams-for-linux)$
-windowrule = tag +im, class:^(im.riot.Riot|Element)$ # Element Matrix client
-
-# game tags
-windowrule = tag +games, class:^(gamescope)$
-windowrule = tag +games, class:^(steam_app_\d+)$
-
-# gamestore tags
-windowrule = tag +gamestore, class:^([Ss]team)$
-windowrule = tag +gamestore, title:^([Ll]utris)$
-windowrule = tag +gamestore, class:^(com.heroicgameslauncher.hgl)$
-
-# file-manager tags
-windowrule = tag +file-manager, class:^([Tt]hunar|org.gnome.Nautilus|[Pp]cmanfm-qt)$
-windowrule = tag +file-manager, class:^(app.drey.Warp)$
-
-# wallpaper tags
-windowrule = tag +wallpaper, class:^([Ww]aytrogen)$
-
-# multimedia tags
-windowrule = tag +multimedia, class:^([Aa]udacious)$
-
-# multimedia-video tags
-windowrule = tag +multimedia_video, class:^([Mm]pv|vlc)$
-
-# settings tags
-windowrule = tag +settings, title:^(ROG Control)$
-windowrule = tag +settings, class:^(wihotspot(-gui)?)$ # wifi hotspot
-windowrule = tag +settings, class:^([Bb]aobab|org.gnome.[Bb]aobab)$ # Disk usage analyzer
-windowrule = tag +settings, class:^(gnome-disks|wihotspot(-gui)?)$
-windowrule = tag +settings, title:(Kvantum Manager)
-windowrule = tag +settings, class:^(file-roller|org.gnome.FileRoller)$ # archive manager
-windowrule = tag +settings, class:^(nm-applet|nm-connection-editor|blueman-manager)$
-windowrule = tag +settings, class:^(pavucontrol|org.pulseaudio.pavucontrol|com.saivert.pwvucontrol)$
-windowrule = tag +settings, class:^(qt5ct|qt6ct|[Yy]ad)$
-windowrule = tag +settings, class:(xdg-desktop-portal-gtk)
-windowrule = tag +settings, class:^(org.kde.polkit-kde-authentication-agent-1)$
-windowrule = tag +settings, class:^([Rr]ofi)$
-
-# viewer tags
-windowrule = tag +viewer, class:^(gnome-system-monitor|org.gnome.SystemMonitor|io.missioncenter.MissionCenter)$ # system monitor
-windowrule = tag +viewer, class:^(evince)$ # document viewer
-windowrule = tag +viewer, class:^(eog|org.gnome.Loupe)$ # image viewer
-
-# Some special override rules
-windowrule = noblur, tag:multimedia_video*
-windowrule = opacity 1.0, tag:multimedia_video*
-
-# POSITION
-# windowrule = center,floating:1 # warning, it cause even the menu to float and center.
-windowrule = center, tag:KooL_Cheat*
-windowrule = center, class:([Tt]hunar), title:negative:(.*[Tt]hunar.*)
-windowrule = center, title:^(ROG Control)$
-windowrule = center, tag:KooL-Settings*
-windowrule = center, title:^(Keybindings)$
-windowrule = center, class:^(pavucontrol|org.pulseaudio.pavucontrol|com.saivert.pwvucontrol)$
-windowrule = center, class:^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$
-windowrule = center, class:^([Ff]erdium)$
-windowrule = move 72% 7%,title:^(Picture-in-Picture)$
-#windowrule = move 72% 7%,title:^(Firefox)$
-
-# windowrule to avoid idle for fullscreen apps
-#windowrule = idleinhibit fullscreen, class:^(*)$
-#windowrule = idleinhibit fullscreen, title:^(*)$
-windowrule = idleinhibit fullscreen, fullscreen:1
-
-# windowrule move to workspace
-#windowrule = workspace 1, tag:email*
-#windowrule = workspace 2, tag:browser*
-#windowrule = workspace 3, class:^([Tt]hunar)$
-#windowrule = workspace 3, tag:projects*
-#windowrule = workspace 5, tag:gamestore*
-#windowrule = workspace 7, tag:im*
-#windowrule = workspace 8, tag:games*
-
-# windowrule move to workspace (silent)
-#windowrule = workspace 4 silent, tag:screenshare*
-#windowrule = workspace 6 silent, class:^(virt-manager)$
-#windowrule = workspace 6 silent, class:^(.virt-manager-wrapped)$
-#windowrule = workspace 9 silent, tag:multimedia*
-#
-# FLOAT
-windowrule = float, tag:KooL_Cheat*
-windowrule = float, tag:wallpaper*
-windowrule = float, tag:settings*
-windowrule = float, tag:viewer*
-windowrule = float, tag:KooL-Settings*
-windowrule = float, class:([Zz]oom|onedriver|onedriver-launcher)$
-windowrule = float, class:(org.gnome.Calculator), title:(Calculator)
-windowrule = float, class:^(mpv|com.github.rafostar.Clapper)$
-windowrule = float, class:^([Qq]alculate-gtk)$
-#windowrule = float, class:^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$
-windowrule = float, class:^([Ff]erdium)$
-windowrule = float, title:^(Picture-in-Picture)$
-#windowrule = float, title:^(Firefox)$
-
-# windowrule - ######### float popups and dialogue #######
-windowrule = float, title:^(Authentication Required)$
-windowrule = center, title:^(Authentication Required)$
-windowrule = float, class:(codium|codium-url-handler|VSCodium), title:negative:(.*codium.*|.*VSCodium.*)
-windowrule = float, class:^(com.heroicgameslauncher.hgl)$, title:negative:(Heroic Games Launcher)
-windowrule = float, class:^([Ss]team)$, title:negative:^([Ss]team)$
-windowrule = float, class:([Tt]hunar), title:negative:(.*[Tt]hunar.*)
-
-windowrule = float, title:^(Add Folder to Workspace)$
-windowrule = size 70% 60%, title:^(Add Folder to Workspace)$
-windowrule = center, title:^(Add Folder to Workspace)$
-
-windowrule = float, title:^(Save As)$
-windowrule = size 70% 60%, title:^(Save As)$
-windowrule = center, title:^(Save As)$
-
-windowrule = float, initialTitle:(Open Files)
-windowrule = size 70% 60%, initialTitle:(Open Files)
-
-windowrule = float, title:^(SDDM Background)$ #KooL's Dots YAD for setting SDDM background
-windowrule = center, title:^(SDDM Background)$ #KooL's Dots YAD for setting SDDM background
-windowrule = size 16% 12%, title:^(SDDM Background)$ #KooL's Dots YAD for setting SDDM background
-# END of float popups and dialogue #######
-
-# OPACITY
-windowrule = opacity 0.99 0.8, tag:browser*
-windowrule = opacity 0.9 0.8, tag:projects*
-windowrule = opacity 0.94 0.86, tag:im*
-windowrule = opacity 0.94 0.86, tag:multimedia*
-windowrule = opacity 0.9 0.8, tag:file-manager*
-windowrule = opacity 0.9 0.7, tag:terminal*
-windowrule = opacity 0.8 0.7, tag:settings*
-windowrule = opacity 0.82 0.75, tag:viewer*
-windowrule = opacity 0.9 0.7, tag:wallpaper*
-windowrule = opacity 0.8 0.7, class:^(gedit|org.gnome.TextEditor|mousepad)$
-windowrule = opacity 0.9 0.8, class:^(deluge)$
-windowrule = opacity 0.9 0.8, class:^(seahorse)$ # gnome-keyring gui
-windowrule = opacity 0.95 0.75, title:^(Picture-in-Picture)$
-
-# SIZE
-windowrule = size 65% 90%, tag:KooL_Cheat*
-windowrule = size 70% 70%, tag:wallpaper*
-windowrule = size 70% 70%, tag:settings*
-windowrule = size 60% 70%, class:^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$
-windowrule = size 60% 70%, class:^([Ff]erdium)$
-
-#windowrule = size 25% 25%, title:^(Picture-in-Picture)$
-#windowrule = size 25% 25%, title:^(Firefox)$
-
-# PINNING
-windowrule = pin, title:^(Picture-in-Picture)$
-#windowrule = pin,title:^(Firefox)$
-
-# windowrule - extras
-windowrule = keepaspectratio, title:^(Picture-in-Picture)$
-
-# BLUR & FULLSCREEN
-windowrule = noblur, tag:games*
-windowrule = fullscreen, tag:games*
-
-
-#This not gonna take the focus to the window that appears when hovering over some of the parts of the IntelliJ Products
-windowrule = noinitialfocus, class:^(jetbrains-*)
-windowrule = noinitialfocus, title:^(wind.*)$
-
-#windowrule = bordercolor rgb(EE4B55) rgb(880808), fullscreen:1
-#windowrule = bordercolor rgb(282737) rgb(1E1D2D), floating:1
-#windowrule = opacity 0.8 0.8, pinned:1
-
-# LAYER RULES
-layerrule = blur, rofi
-layerrule = ignorezero, rofi
-layerrule = blur, notifications
-layerrule = ignorezero, notifications
-layerrule = blur, quickshell:overview
-layerrule = ignorezero, quickshell:overview
-layerrule = ignorealpha 0.5, quickshell:overview
-
-#layerrule = ignorealpha 0.5, tag:notif*
-
-#layerrule = ignorezero, class:^([Rr]ofi)$
-#layerrule = blur, class:^([Rr]ofi)$
-#layerrule = unset,class:^([Rr]ofi)$
-#layerrule = ignorezero, <rofi>
-
-#layerrule = ignorezero, overview
-#layerrule = blur, overview
diff --git a/config/hypr/configs/WindowRules.conf b/config/hypr/configs/WindowRules.conf
index 7082d64c..8aa9186c 100644
--- a/config/hypr/configs/WindowRules.conf
+++ b/config/hypr/configs/WindowRules.conf
@@ -4,12 +4,12 @@
# License: GNU GPLv3
# SPDX-License-Identifier: GPL-3.0-or-later
# ==================================================
-# Vendor defaults for window rules and layerrules
+# Vendor defaults for window rules
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
# NOTES: This is only for Hyprland >= 0.53
-# Some samples on hwo to start apps on specific workspaces
+# Some samples on hwo to start apps on specific workspaces
# windowrule = match:tag email*, workspace 1
# windowrule = match:tag browser*, workspace 2
# windowrule = match:tag projects*, workspace 3
@@ -24,165 +24,241 @@
# TAGS - add apps under appropriate tag to use the same settings
# browser tags
+# name: tag-browser-firefox
windowrule = match:class ^([Ff]irefox|org.mozilla.firefox|[Ff]irefox-esr|[Ff]irefox-bin)$, tag +browser
+# name: tag-browser-google-chrome
windowrule = match:class ^([Gg]oogle-chrome(-beta|-dev|-unstable)?)$, tag +browser
+# name: tag-browser-chrome-default-profile
windowrule = match:class ^(chrome-.+-Default)$, tag +browser
+# name: tag-browser-chromium
windowrule = match:class ^([Cc]hromium)$, tag +browser
+# name: tag-browser-microsoft-edge
windowrule = match:class ^([Mm]icrosoft-edge(-stable|-beta|-dev|-unstable))$, tag +browser
+# name: tag-browser-brave
windowrule = match:class ^([Bb]rave-browser(-beta|-dev|-unstable)?)$, tag +browser
+# name: tag-browser-thorium-cachy
windowrule = match:class ^([Tt]horium-browser|[Cc]achy-browser)$, tag +browser
+# name: tag-browser-zen
windowrule = match:class ^(zen-alpha|zen)$, tag +browser
# notif tags
+# name: tag-notifications-swaync
windowrule = match:class ^(swaync-control-center|swaync-notification-window|swaync-client|class)$, tag +notif
# KooL settings tag
+# name: tag-kool-cheat-sheet
windowrule = match:title ^(KooL Quick Cheat Sheet)$, tag +KooL_Cheat
+# name: tag-kool-hyprland-settings
windowrule = match:title ^(KooL Hyprland Settings)$, tag +KooL_Settings
+# name: tag-kool-settings-nwg-tools
windowrule = match:class ^(nwg-displays|nwg-look)$, tag +KooL-Settings
# terminal tags
+# name: tag-terminal-emulators
windowrule = match:class ^(ghostty|wezterm|Alacritty|kitty|kitty-dropterm)$, tag +terminal
# email tags
+# name: tag-email-thunderbird
windowrule = match:class ^([Tt]hunderbird|org.mozilla.Thunderbird)$, tag +email
+# name: tag-email-betterbird
windowrule = match:class ^(eu.betterbird.Betterbird)$, tag +email
+# name: tag-email-evolution
windowrule = match:class ^(org.gnome.Evolution)$, tag +email
# project tags
+# name: tag-projects-vscodium
windowrule = match:class ^(codium|codium-url-handler|VSCodium)$, tag +projects
+# name: tag-projects-vscode
windowrule = match:class ^(VSCode|code|code-url-handler)$, tag +projects
+# name: tag-projects-jetbrains
windowrule = match:class ^(jetbrains-.+)$, tag +projects
+# name: tag-projects-zed
windowrule = match:class ^(dev.zed.Zed|antigravity)$, tag +projects
# screenshare tags
+# name: tag-screenshare-obs
windowrule = match:class ^(com.obsproject.Studio)$, tag +screenshare
+windowrule = match:class ^(com.obsproject.Studio)$, workspace 10 silent
# IM tags
+# name: tag-im-discord-family
windowrule = match:class ^([Dd]iscord|[Ww]ebCord|[Vv]esktop)$, tag +im
+# name: tag-im-ferdium
windowrule = match:class ^([Ff]erdium)$, tag +im
+# name: tag-im-whatsapp
windowrule = match:class ^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$, tag +im
+# name: tag-im-telegram
windowrule = match:class ^(org.telegram.desktop|io.github.tdesktop_x64.TDesktop)$, tag +im
+# name: tag-im-teams
windowrule = match:class ^(teams-for-linux)$, tag +im
+# name: tag-im-element
windowrule = match:class ^(im.riot.Riot|Element)$, tag +im
# game tags
+# name: tag-games-gamescope
windowrule = match:class ^(gamescope)$, tag +games
+# name: tag-games-steam-app
windowrule = match:class ^(steam_app_\\d+)$, tag +games
+# name: tag-games-proton
windowrule = match:xdg_tag ^(proton-game)$, tag +games
# gamestore tags
+# name: tag-gamestore-steam
windowrule = match:class ^([Ss]team)$, tag +gamestore
+# name: tag-gamestore-lutris
windowrule = match:title ^([Ll]utris)$, tag +gamestore
+# name: tag-gamestore-heroic
windowrule = match:class ^(com.heroicgameslauncher.hgl)$, tag +gamestore
# file-manager tags
+# name: tag-file-manager-common
windowrule = match:class ^([Tt]hunar|org.gnome.Nautilus|[Pp]cmanfm-qt)$, tag +file-manager
+# name: tag-file-manager-warp
windowrule = match:class ^(app.drey.Warp)$, tag +file-manager
# wallpaper tags
+# name: tag-wallpaper-waytrogen
windowrule = match:class ^([Ww]aytrogen)$, tag +wallpaper
# multimedia tags
+# name: tag-multimedia-audacious
windowrule = match:class ^([Aa]udacious)$, tag +multimedia
# multimedia-video tags
+# name: tag-multimedia-video-players
windowrule = match:class ^([Mm]pv|vlc)$, tag +multimedia_video
# settings tags
+# name: tag-settings-rog-control
windowrule = match:title ^(ROG Control)$, tag +settings
+# name: tag-settings-wihotspot
windowrule = match:class ^(wihotspot(-gui)?)$, tag +settings
+# name: tag-settings-baobab
windowrule = match:class ^([Bb]aobab|org.gnome.[Bb]aobab)$, tag +settings
+# name: tag-settings-disks-and-hotspot
windowrule = match:class ^(gnome-disks|wihotspot(-gui)?)$, tag +settings
+# name: tag-settings-kvantum
windowrule = match:title (Kvantum Manager), tag +settings
+# name: tag-settings-file-roller
windowrule = match:class ^(file-roller|org.gnome.FileRoller)$, tag +settings
+# name: tag-settings-network-blueman
windowrule = match:class ^(nm-applet|nm-connection-editor|blueman-manager)$, tag +settings
+# name: tag-settings-pavucontrol
windowrule = match:class ^(pavucontrol|org.pulseaudio.pavucontrol|com.saivert.pwvucontrol)$, tag +settings
+# name: tag-settings-qtct
windowrule = match:class ^(qt5ct|qt6ct)$, tag +settings
+# name: tag-settings-xdg-portal-gtk
windowrule = match:class (xdg-desktop-portal-gtk), tag +settings
+# name: tag-settings-polkit-kde
windowrule = match:class ^(org.kde.polkit-kde-authentication-agent-1)$, tag +settings
+# name: tag-settings-rofi
windowrule = match:class ^([Rr]ofi)$, tag +settings
+# name: tag-settings-btrfs-assistant
windowrule = match:class ^(btrfs-assistant)$, tag +settings
+# name: tag-settings-timeshift
windowrule = match:class ^(timeshift-gtk)$, tag +settings
# viewer tags
+# name: tag-viewer-system-monitor
windowrule = match:class ^(gnome-system-monitor|org.gnome.SystemMonitor|io.missioncenter.MissionCenter)$, tag +viewer
+# name: tag-viewer-evince
windowrule = match:class ^(evince)$, tag +viewer
+# name: tag-viewer-image-viewers
windowrule = match:class ^(eog|org.gnome.Loupe)$, tag +viewer
# Some special override rules
+# name: multimedia-disable-blur
windowrule = match:tag multimedia, no_blur on
+# name: multimedia-force-opacity
windowrule = match:tag multimedia, opacity 1.0
# FLOAT
+# name: float-zoom-onedriver
windowrule = match:class ([Zz]oom|onedriver|onedriver-launcher), float on
+# name: float-video-players
windowrule = match:class ^(mpv|com.github.rafostar.Clapper)$, float on
+# name: float-qalculate
windowrule = match:class ^([Qq]alculate-gtk)$, float on
# float popups and dialogue
+# name: float-center-auth-required-title
windowrule = match:title ^(Authentication Required)$, float on, center on
+# name: float-center-polkit-auth-dialog
windowrule = match:class ^(xfce-polkit|mate-polkit|polkit-mate-authentication-agent-1)$, match:title ^(Authentication required|Authentication Required)$, float on, center on, size (monitor_w*0.35) (monitor_h*0.35)
+# name: float-vscodium-secondary-window
windowrule = match:class (codium|codium-url-handler|VSCodium), match:title negative:(.*codium.*|.*VSCodium.*), float on
+# name: float-heroic-secondary-window
windowrule = match:class ^(com.heroicgameslauncher.hgl)$, match:title negative:(Heroic Games Launcher), float on
+# name: float-steam-secondary-window
windowrule = match:class ^([Ss]team)$, match:title negative:^([Ss]team)$, float on
+# name: float-center-add-folder-dialog
windowrule = match:title ^(Add Folder to Workspace)$, float on, size (monitor_w*0.7) (monitor_h*0.6), center on
+# name: float-center-save-as-dialog
windowrule = match:title ^(Save As)$, float on, size (monitor_w*0.7) (monitor_h*0.6), center on
+# name: float-open-files-dialog
windowrule = match:initial_title (Open Files), float on, size (monitor_w*0.7) (monitor_h*0.6)
+# name: float-center-sddm-background
windowrule = match:title ^(SDDM Background)$, float on, center on, size (monitor_w*0.16) (monitor_h*0.12)
+# name: float-center-yad-dialog
windowrule = match:class ^(yad)$, float on, center on, size (monitor_w*0.2) (monitor_h*0.2)
+# name: float-center-hyprland-donate
windowrule = match:class ^(hyprland-donate-screen)$, float on, center on
# SIZE
# POSITION
+# name: center-rog-control
windowrule = match:title ^(ROG Control)$, center on
+# name: center-keybindings
windowrule = match:title ^(Keybindings)$, center on
+# name: center-pavucontrol
windowrule = match:class ^(pavucontrol|org.pulseaudio.pavucontrol|com.saivert.pwvucontrol)$, center on
+# name: center-whatsapp
windowrule = match:class ^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$, center on
+# name: center-network-editor
windowrule = match:class ^(nm-connection-editor)$, center on
+# name: center-nm-auth-dialog
windowrule = match:class ^(nm-applet)$, match:title ^(Wi-Fi Network Authentication Required)$, center on
# windowrule to avoid idle for fullscreen apps
+# name: idle-inhibit-fullscreen-bool
windowrule = match:fullscreen true, idle_inhibit fullscreen
+# name: idle-inhibit-fullscreen-int
windowrule = idle_inhibit fullscreen, match:fullscreen 1
+# name: idle-inhibit-any-class
windowrule = idle_inhibit fullscreen, match:class .*
+# name: idle-inhibit-any-title
windowrule = idle_inhibit fullscreen, match:title .*
# OPACITY
+# name: opacity-browser-tag
windowrule = match:tag browser, opacity 0.99 0.8
+# name: opacity-projects-tag
windowrule = match:tag projects, opacity 0.9 0.8
+# name: opacity-im-tag
windowrule = match:tag im, opacity 0.94 0.86
+# name: opacity-multimedia-tag
windowrule = match:tag multimedia, opacity 0.94 0.86
+# name: opacity-file-manager-tag
windowrule = match:tag file-manager, opacity 0.9 0.8
+# name: opacity-terminal-tag
windowrule = match:tag terminal, opacity 0.9 0.7
+# name: opacity-text-editors
windowrule = match:class ^(gedit|org.gnome.TextEditor|mousepad)$, opacity 0.8 0.7
+# name: opacity-deluge
windowrule = match:class ^(deluge)$, opacity 0.9 0.8
+# name: opacity-seahorse
windowrule = match:class ^(seahorse)$, opacity 0.9 0.8
# BLUR & FULLSCREEN
-# This not gonna take the focus to the window that appears
+# This not gonna take the focus to the window that appears
# when hovering over some of the parts of the IntelliJ Products
+# name: no-initial-focus-jetbrains
windowrule = match:class ^(jetbrains-.*)$, no_initial_focus on
+# name: no-initial-focus-wind-title
windowrule = match:title ^(wind.*)$, no_initial_focus on
-# LAYER RULES
-layerrule = match:namespace rofi, blur on
-layerrule = match:namespace notifications, blur on
-layerrule = match:namespace quickshell:overview, blur on
-layerrule = match:namespace quickshell:overview, ignore_alpha 0.5
-
-#
-layerrule = blur on, match:namespace wallpaper
-layerrule = animation slide, match:namespace rofi
-layerrule = animation slide, match:namespace notifications
-
-# Optional Layer rules
-# To Resolve blurred corners in rofi Add to User config
-# SUPER SHIFT + E Edit User Window Rules
-#layerrule = blur on, ignore_alpha 0, match:namespace rofi
-#layerrule = blur on, match:namespace waybar
-
windowrule {
name = Picture-in-Picture
@@ -219,7 +295,7 @@ windowrule {
size = (monitor_w*0.45) (monitor_h*0.55)
}
-# Named rule for Kwallet
+# Named rule for Kwallet
windowrule {
name = Kwallet
match:class = ^(org.kde.kwalletmanager)$
@@ -412,18 +488,22 @@ windowrule {
center = on
size = (monitor_w*0.6) (monitor_h*0.6)
}
+
# Named rule for hyprpwcenter audio control panel
windowrule {
name = hyprland audio panel
match:class = ^(hyprpwcenter)$
+ match:title = ^(Pipewire Control Center)$
match:initial_class = ^(hyprpwcenter)$
+ match:initial_title = ^(Pipewire Control Center)$
float = on
center = on
size = (monitor_w*0.6) (monitor_h*0.6)
}
-# Named rule for Garida Assistant
+
+# Named rule for Garuda Assistant
windowrule {
- name = Garuda Assistant
+ name = Garuda Assistant
match:class = ^(garuda-assistant)$
match:title = ^(Garuda Assistant)$
match:initial_class = ^(garuda-assistant)$
@@ -433,9 +513,9 @@ windowrule {
size = (monitor_w*0.6) (monitor_h*0.6)
}
-# Named rule for HyprMod HL config GUI
+# Named rule for HyprMod HL config GUI
windowrule {
- name = HyprMod GUI
+ name = HyprMod GUI
match:class = ^(com.github.hyprmod)$
match:title = ^(HyprMod)$
match:initial_class = ^(com.github.hyprmod)$
@@ -444,9 +524,10 @@ windowrule {
center = on
size = (monitor_w*0.7) (monitor_h*0.75)
}
-# Named rule for easy effects
+
+# Named rule for EasyEffects
windowrule {
- name = EasyEffects
+ name = EasyEffects
match:class = ^(com.github.wwmm.easyeffects)$
match:title = ^(Easy Effects)$
match:initial_class = ^(com.github.wwmm.easyeffects)$
@@ -456,9 +537,19 @@ windowrule {
size = (monitor_w*0.6) (monitor_h*0.65)
}
-# Named rule for Mousam weather GUI
+# Named rule for Megasync
windowrule {
- name = Mousam Weather
+ name = Megasync
+ match:class = ^(nz\.co\.mega\.megasync)$
+ match:initial_class = ^(nz\.co\.mega\.megasync)$
+ float = on
+ center = on
+ size = (monitor_w*0.1) (monitor_h*0.3)
+}
+
+# Named rule for Mousam weather GUI
+windowrule {
+ name = Mousam Weather
match:class = ^(io.github.amit9838.mousam)$
match:title = ^(Mousam)$
match:initial_class = ^(io.github.amit9838.mousam)$
@@ -467,5 +558,3 @@ windowrule {
center = on
size = (monitor_w*0.7) (monitor_h*0.75)
}
-
-
diff --git a/config/hypr/hl.meta.lua b/config/hypr/hl.meta.lua
new file mode 100644
index 00000000..76fc923b
--- /dev/null
+++ b/config/hypr/hl.meta.lua
@@ -0,0 +1,1252 @@
+-- This file is autogenerated. Do not edit by hand.
+-- Generator: scripts/generateLuaStubs.py
+---@meta
+
+---@alias HL.EventName
+---| "config.reloaded"
+---| "hyprland.shutdown"
+---| "hyprland.start"
+---| "keybinds.submap"
+---| "layer.closed"
+---| "layer.opened"
+---| "monitor.added"
+---| "monitor.focused"
+---| "monitor.layout_changed"
+---| "monitor.removed"
+---| "screenshare.state"
+---| "window.active"
+---| "window.class"
+---| "window.close"
+---| "window.destroy"
+---| "window.fullscreen"
+---| "window.kill"
+---| "window.move_to_workspace"
+---| "window.open"
+---| "window.open_early"
+---| "window.pin"
+---| "window.title"
+---| "window.update_rules"
+---| "window.urgent"
+---| "workspace.active"
+---| "workspace.created"
+---| "workspace.move_to_monitor"
+---| "workspace.removed"
+
+---@alias HL.ConfigKey
+---| "animations.enabled"
+---| "animations.workspace_wraparound"
+---| "binds.allow_pin_fullscreen"
+---| "binds.allow_workspace_cycles"
+---| "binds.disable_keybind_grabbing"
+---| "binds.drag_threshold"
+---| "binds.focus_preferred_method"
+---| "binds.hide_special_on_workspace_change"
+---| "binds.ignore_group_lock"
+---| "binds.movefocus_cycles_fullscreen"
+---| "binds.movefocus_cycles_groupfirst"
+---| "binds.pass_mouse_when_bound"
+---| "binds.scroll_event_delay"
+---| "binds.window_direction_monitor_fallback"
+---| "binds.workspace_back_and_forth"
+---| "binds.workspace_center_on"
+---| "cursor.default_monitor"
+---| "cursor.enable_hyprcursor"
+---| "cursor.hide_on_key_press"
+---| "cursor.hide_on_tablet"
+---| "cursor.hide_on_touch"
+---| "cursor.hotspot_padding"
+---| "cursor.inactive_timeout"
+---| "cursor.invisible"
+---| "cursor.min_refresh_rate"
+---| "cursor.no_break_fs_vrr"
+---| "cursor.no_hardware_cursors"
+---| "cursor.no_warps"
+---| "cursor.persistent_warps"
+---| "cursor.sync_gsettings_theme"
+---| "cursor.use_cpu_buffer"
+---| "cursor.warp_back_after_non_mouse_input"
+---| "cursor.warp_on_change_workspace"
+---| "cursor.warp_on_toggle_special"
+---| "cursor.zoom_detached_camera"
+---| "cursor.zoom_disable_aa"
+---| "cursor.zoom_factor"
+---| "cursor.zoom_rigid"
+---| "debug.colored_stdout_logs"
+---| "debug.damage_blink"
+---| "debug.damage_tracking"
+---| "debug.disable_logs"
+---| "debug.disable_scale_checks"
+---| "debug.disable_time"
+---| "debug.ds_handle_same_buffer"
+---| "debug.ds_handle_same_buffer_fifo"
+---| "debug.enable_stdout_logs"
+---| "debug.error_limit"
+---| "debug.error_position"
+---| "debug.fifo_pending_workaround"
+---| "debug.full_cm_proto"
+---| "debug.gl_debugging"
+---| "debug.invalidate_fp16"
+---| "debug.log_damage"
+---| "debug.manual_crash"
+---| "debug.overlay"
+---| "debug.pass"
+---| "debug.render_solitary_wo_damage"
+---| "debug.suppress_errors"
+---| "debug.vfr"
+---| "decoration.active_opacity"
+---| "decoration.blur.brightness"
+---| "decoration.blur.contrast"
+---| "decoration.blur.enabled"
+---| "decoration.blur.ignore_opacity"
+---| "decoration.blur.input_methods"
+---| "decoration.blur.input_methods_ignorealpha"
+---| "decoration.blur.new_optimizations"
+---| "decoration.blur.noise"
+---| "decoration.blur.passes"
+---| "decoration.blur.popups"
+---| "decoration.blur.popups_ignorealpha"
+---| "decoration.blur.size"
+---| "decoration.blur.special"
+---| "decoration.blur.vibrancy"
+---| "decoration.blur.vibrancy_darkness"
+---| "decoration.blur.xray"
+---| "decoration.border_part_of_window"
+---| "decoration.dim_around"
+---| "decoration.dim_inactive"
+---| "decoration.dim_modal"
+---| "decoration.dim_special"
+---| "decoration.dim_strength"
+---| "decoration.fullscreen_opacity"
+---| "decoration.glow.color"
+---| "decoration.glow.color_inactive"
+---| "decoration.glow.enabled"
+---| "decoration.glow.range"
+---| "decoration.glow.render_power"
+---| "decoration.inactive_opacity"
+---| "decoration.rounding"
+---| "decoration.rounding_power"
+---| "decoration.screen_shader"
+---| "decoration.shadow.color"
+---| "decoration.shadow.color_inactive"
+---| "decoration.shadow.enabled"
+---| "decoration.shadow.offset"
+---| "decoration.shadow.range"
+---| "decoration.shadow.render_power"
+---| "decoration.shadow.scale"
+---| "decoration.shadow.sharp"
+---| "dwindle.default_split_ratio"
+---| "dwindle.force_split"
+---| "dwindle.permanent_direction_override"
+---| "dwindle.precise_mouse_move"
+---| "dwindle.preserve_split"
+---| "dwindle.smart_resizing"
+---| "dwindle.smart_split"
+---| "dwindle.special_scale_factor"
+---| "dwindle.split_bias"
+---| "dwindle.split_width_multiplier"
+---| "dwindle.use_active_for_splits"
+---| "ecosystem.enforce_permissions"
+---| "ecosystem.no_donation_nag"
+---| "ecosystem.no_update_news"
+---| "experimental.wp_cm_1_2"
+---| "general.allow_tearing"
+---| "general.border_size"
+---| "general.col.active_border"
+---| "general.col.inactive_border"
+---| "general.col.nogroup_border"
+---| "general.col.nogroup_border_active"
+---| "general.extend_border_grab_area"
+---| "general.float_gaps"
+---| "general.gaps_in"
+---| "general.gaps_out"
+---| "general.gaps_workspaces"
+---| "general.hover_icon_on_border"
+---| "general.layout"
+---| "general.locale"
+---| "general.modal_parent_blocking"
+---| "general.no_focus_fallback"
+---| "general.resize_corner"
+---| "general.resize_on_border"
+---| "general.snap.border_overlap"
+---| "general.snap.enabled"
+---| "general.snap.monitor_gap"
+---| "general.snap.respect_gaps"
+---| "general.snap.window_gap"
+---| "gestures.close_max_timeout"
+---| "gestures.scrolling.move_snap_cursor"
+---| "gestures.scrolling.move_snap_to_grid"
+---| "gestures.workspace_swipe_cancel_ratio"
+---| "gestures.workspace_swipe_create_new"
+---| "gestures.workspace_swipe_direction_lock"
+---| "gestures.workspace_swipe_direction_lock_threshold"
+---| "gestures.workspace_swipe_distance"
+---| "gestures.workspace_swipe_forever"
+---| "gestures.workspace_swipe_invert"
+---| "gestures.workspace_swipe_min_speed_to_force"
+---| "gestures.workspace_swipe_touch"
+---| "gestures.workspace_swipe_touch_invert"
+---| "gestures.workspace_swipe_use_r"
+---| "group.auto_group"
+---| "group.col.border_active"
+---| "group.col.border_inactive"
+---| "group.col.border_locked_active"
+---| "group.col.border_locked_inactive"
+---| "group.drag_into_group"
+---| "group.focus_removed_window"
+---| "group.group_on_movetoworkspace"
+---| "group.groupbar.blur"
+---| "group.groupbar.col.active"
+---| "group.groupbar.col.inactive"
+---| "group.groupbar.col.locked_active"
+---| "group.groupbar.col.locked_inactive"
+---| "group.groupbar.enabled"
+---| "group.groupbar.font_family"
+---| "group.groupbar.font_size"
+---| "group.groupbar.font_weight_active"
+---| "group.groupbar.font_weight_inactive"
+---| "group.groupbar.gaps_in"
+---| "group.groupbar.gaps_out"
+---| "group.groupbar.gradient_round_only_edges"
+---| "group.groupbar.gradient_rounding"
+---| "group.groupbar.gradient_rounding_power"
+---| "group.groupbar.gradients"
+---| "group.groupbar.height"
+---| "group.groupbar.indicator_gap"
+---| "group.groupbar.indicator_height"
+---| "group.groupbar.keep_upper_gap"
+---| "group.groupbar.middle_click_close"
+---| "group.groupbar.priority"
+---| "group.groupbar.render_titles"
+---| "group.groupbar.round_only_edges"
+---| "group.groupbar.rounding"
+---| "group.groupbar.rounding_power"
+---| "group.groupbar.scrolling"
+---| "group.groupbar.stacked"
+---| "group.groupbar.text_color"
+---| "group.groupbar.text_color_inactive"
+---| "group.groupbar.text_color_locked_active"
+---| "group.groupbar.text_color_locked_inactive"
+---| "group.groupbar.text_offset"
+---| "group.groupbar.text_padding"
+---| "group.insert_after_current"
+---| "group.merge_floated_into_tiled_on_groupbar"
+---| "group.merge_groups_on_drag"
+---| "group.merge_groups_on_groupbar"
+---| "input.accel_profile"
+---| "input.emulate_discrete_scroll"
+---| "input.float_switch_override_focus"
+---| "input.focus_on_close"
+---| "input.follow_mouse"
+---| "input.follow_mouse_shrink"
+---| "input.follow_mouse_threshold"
+---| "input.force_no_accel"
+---| "input.kb_file"
+---| "input.kb_layout"
+---| "input.kb_model"
+---| "input.kb_options"
+---| "input.kb_rules"
+---| "input.kb_variant"
+---| "input.left_handed"
+---| "input.mouse_refocus"
+---| "input.natural_scroll"
+---| "input.numlock_by_default"
+---| "input.off_window_axis_events"
+---| "input.repeat_delay"
+---| "input.repeat_rate"
+---| "input.resolve_binds_by_sym"
+---| "input.rotation"
+---| "input.scroll_button"
+---| "input.scroll_button_lock"
+---| "input.scroll_factor"
+---| "input.scroll_method"
+---| "input.scroll_points"
+---| "input.sensitivity"
+---| "input.special_fallthrough"
+---| "input.tablet.absolute_region_position"
+---| "input.tablet.active_area_position"
+---| "input.tablet.active_area_size"
+---| "input.tablet.left_handed"
+---| "input.tablet.output"
+---| "input.tablet.region_position"
+---| "input.tablet.region_size"
+---| "input.tablet.relative_input"
+---| "input.tablet.transform"
+---| "input.touchdevice.enabled"
+---| "input.touchdevice.output"
+---| "input.touchdevice.transform"
+---| "input.touchpad.clickfinger_behavior"
+---| "input.touchpad.disable_while_typing"
+---| "input.touchpad.drag_3fg"
+---| "input.touchpad.drag_lock"
+---| "input.touchpad.flip_x"
+---| "input.touchpad.flip_y"
+---| "input.touchpad.middle_button_emulation"
+---| "input.touchpad.natural_scroll"
+---| "input.touchpad.scroll_factor"
+---| "input.touchpad.tap_and_drag"
+---| "input.touchpad.tap_button_map"
+---| "input.touchpad.tap_to_click"
+---| "input.virtualkeyboard.release_pressed_on_close"
+---| "input.virtualkeyboard.share_states"
+---| "layout.single_window_aspect_ratio"
+---| "layout.single_window_aspect_ratio_tolerance"
+---| "master.allow_small_split"
+---| "master.always_keep_position"
+---| "master.center_ignores_reserved"
+---| "master.center_master_fallback"
+---| "master.drop_at_cursor"
+---| "master.focus_master_on_close"
+---| "master.mfact"
+---| "master.new_on_active"
+---| "master.new_on_top"
+---| "master.new_status"
+---| "master.orientation"
+---| "master.slave_count_for_center_master"
+---| "master.smart_resizing"
+---| "master.special_scale_factor"
+---| "misc.allow_session_lock_restore"
+---| "misc.always_follow_on_dnd"
+---| "misc.animate_manual_resizes"
+---| "misc.animate_mouse_windowdragging"
+---| "misc.anr_missed_pings"
+---| "misc.background_color"
+---| "misc.close_special_on_empty"
+---| "misc.col.splash"
+---| "misc.disable_autoreload"
+---| "misc.disable_hyprland_guiutils_check"
+---| "misc.disable_hyprland_logo"
+---| "misc.disable_scale_notification"
+---| "misc.disable_splash_rendering"
+---| "misc.disable_watchdog_warning"
+---| "misc.disable_xdg_env_checks"
+---| "misc.enable_anr_dialog"
+---| "misc.enable_swallow"
+---| "misc.exit_window_retains_fullscreen"
+---| "misc.focus_on_activate"
+---| "misc.font_family"
+---| "misc.force_default_wallpaper"
+---| "misc.initial_workspace_tracking"
+---| "misc.key_press_enables_dpms"
+---| "misc.layers_hog_keyboard_focus"
+---| "misc.lockdead_screen_delay"
+---| "misc.middle_click_paste"
+---| "misc.mouse_move_enables_dpms"
+---| "misc.mouse_move_focuses_monitor"
+---| "misc.name_vk_after_proc"
+---| "misc.on_focus_under_fullscreen"
+---| "misc.render_unfocused_fps"
+---| "misc.screencopy_force_8b"
+---| "misc.session_lock_xray"
+---| "misc.size_limits_tiled"
+---| "misc.splash_font_family"
+---| "misc.swallow_exception_regex"
+---| "misc.swallow_regex"
+---| "misc.vrr"
+---| "opengl.nvidia_anti_flicker"
+---| "quirks.prefer_hdr"
+---| "quirks.skip_non_kms_dmabuf_formats"
+---| "render.cm_auto_hdr"
+---| "render.cm_enabled"
+---| "render.cm_sdr_eotf"
+---| "render.commit_timing_enabled"
+---| "render.ctm_animation"
+---| "render.direct_scanout"
+---| "render.expand_undersized_textures"
+---| "render.fp16_sdr_tf"
+---| "render.icc_vcgt_enabled"
+---| "render.keep_unmodified_copy"
+---| "render.new_render_scheduling"
+---| "render.non_shader_cm"
+---| "render.non_shader_cm_interop"
+---| "render.send_content_type"
+---| "render.use_fp16"
+---| "render.use_shader_blur_blend"
+---| "render.xp_mode"
+---| "scrolling.column_width"
+---| "scrolling.direction"
+---| "scrolling.explicit_column_widths"
+---| "scrolling.focus_fit_method"
+---| "scrolling.follow_focus"
+---| "scrolling.follow_min_visible"
+---| "scrolling.fullscreen_on_one_column"
+---| "scrolling.wrap_focus"
+---| "scrolling.wrap_swapcol"
+---| "xwayland.create_abstract_socket"
+---| "xwayland.enabled"
+---| "xwayland.force_zero_scaling"
+---| "xwayland.use_nearest_neighbor"
+
+---@alias HL.MonitorSelector string|integer|HL.Monitor
+---@alias HL.WorkspaceSelector string|integer|HL.Workspace
+---@alias HL.WindowSelector string|integer|HL.Window
+---@alias HL.Vec2Like HL.Vec2|{x:number, y:number}|{number, number}|string
+---@alias HL.CssGap integer|{top?:integer, right?:integer, bottom?:integer, left?:integer}
+---@alias HL.Gradient string|{colors:string[], angle?:number}
+
+---@class HL.Dispatcher
+local __HL_Dispatcher = {}
+
+---@class HL.Vec2
+---@field x number
+---@field y number
+local __HL_Vec2 = {}
+
+---@class HL.Box
+---@field x number
+---@field y number
+---@field w number
+---@field h number
+local __HL_Box = {}
+
+---@class HL.LayoutTarget
+---@field index integer
+---@field window HL.Window|nil
+---@field box HL.Box
+---@field place fun(self: HL.LayoutTarget, box: HL.Box): nil
+---@field set_box fun(self: HL.LayoutTarget, box: HL.Box): nil
+local __HL_LayoutTarget = {}
+
+---@class HL.LayoutContext
+---@field area HL.Box
+---@field targets HL.LayoutTarget[]
+---@field grid_cell fun(self: HL.LayoutContext, i: integer, cols: integer, rows?: integer): HL.Box
+---@field column fun(self: HL.LayoutContext, i: integer, n: integer): HL.Box
+---@field row fun(self: HL.LayoutContext, i: integer, n: integer): HL.Box
+---@field split fun(self: HL.LayoutContext, box: HL.Box, side: 'left'|'right'|'top'|'bottom'|'up'|'down', ratio: number): HL.Box
+local __HL_LayoutContext = {}
+
+---@class HL.LayoutProvider
+---@field recalculate fun(ctx: HL.LayoutContext): nil
+---@field layout_msg? fun(ctx: HL.LayoutContext, msg: string): boolean|string|nil
+local __HL_LayoutProvider = {}
+
+---@class HL.BindOptions
+---@field repeating? boolean
+---@field locked? boolean
+---@field release? boolean
+---@field non_consuming? boolean
+---@field transparent? boolean
+---@field ignore_mods? boolean
+---@field dont_inhibit? boolean
+---@field long_press? boolean
+---@field submap_universal? boolean
+---@field click? boolean
+---@field drag? boolean
+---@field description? string
+---@field desc? string
+---@field device? {inclusive?: boolean, list?: string[]}
+local __HL_BindOptions = {}
+
+---@class HL.TimerOptions
+---@field timeout integer
+---@field type "repeat"|"oneshot"
+local __HL_TimerOptions = {}
+
+---@class HL.GestureSpec
+---@field fingers integer
+---@field direction string
+---@field action string
+---@field mods? string
+---@field scale? number
+---@field mode? string
+---@field zoom_level? number
+---@field workspace_name? string
+---@field disable_inhibit? boolean
+local __HL_GestureSpec = {}
+
+---@class HL.PermissionSpec
+---@field binary string
+---@field type string
+---@field mode string
+local __HL_PermissionSpec = {}
+
+---@class HL.NotificationOptions
+---@field color? string
+---@field timeout? number
+---@field icon? integer|string
+---@field font_size? number
+local __HL_NotificationOptions = {}
+
+---@class HL.LayerQueryFilter
+---@field monitor? HL.MonitorSelector
+---@field namespace? string
+local __HL_LayerQueryFilter = {}
+
+---@class HL.WindowQueryFilter
+---@field class? string
+---@field floating? boolean
+---@field mapped? boolean
+---@field monitor? HL.MonitorSelector
+---@field tag? string
+---@field title? string
+---@field workspace? HL.WorkspaceSelector
+local __HL_WindowQueryFilter = {}
+
+---@class HL.DeviceSpec
+---@field absolute_region_position? boolean
+---@field accel_profile? string
+---@field active_area_position? HL.Vec2Like
+---@field active_area_size? HL.Vec2Like
+---@field clickfinger_behavior? boolean
+---@field disable_while_typing? boolean
+---@field drag_3fg? integer|boolean
+---@field drag_lock? integer|boolean
+---@field enabled? boolean
+---@field flip_x? boolean
+---@field flip_y? boolean
+---@field kb_file? string
+---@field kb_layout? string
+---@field kb_model? string
+---@field kb_options? string
+---@field kb_rules? string
+---@field kb_variant? string
+---@field keybinds? boolean
+---@field left_handed? boolean
+---@field middle_button_emulation? boolean
+---@field name string
+---@field natural_scroll? boolean
+---@field numlock_by_default? boolean
+---@field output? string
+---@field region_position? HL.Vec2Like
+---@field region_size? HL.Vec2Like
+---@field relative_input? boolean
+---@field release_pressed_on_close? boolean
+---@field repeat_delay? integer|boolean
+---@field repeat_rate? integer|boolean
+---@field resolve_binds_by_sym? boolean
+---@field rotation? integer|boolean
+---@field scroll_button? integer|boolean
+---@field scroll_button_lock? boolean
+---@field scroll_factor? number|boolean
+---@field scroll_method? string
+---@field scroll_points? string
+---@field sensitivity? number|boolean
+---@field share_states? integer|boolean
+---@field tags? string
+---@field tap_and_drag? boolean
+---@field tap_button_map? string
+---@field tap_to_click? boolean
+---@field transform? integer|boolean
+local __HL_DeviceSpec = {}
+
+---@class HL.LayerRuleSpec
+---@field above_lock? integer|boolean
+---@field animation? string
+---@field blur? boolean
+---@field blur_popups? boolean
+---@field dim_around? boolean
+---@field enabled? boolean
+---@field ignore_alpha? number|boolean
+---@field match? table<string, string|boolean>
+---@field name? string
+---@field no_anim? boolean
+---@field no_screen_share? boolean
+---@field order? integer|boolean
+---@field xray? boolean
+local __HL_LayerRuleSpec = {}
+
+---@class HL.MonitorSpec
+---@field bitdepth? integer|boolean
+---@field cm? string
+---@field disabled? boolean
+---@field icc? string
+---@field max_avg_luminance? integer|boolean
+---@field max_luminance? integer|boolean
+---@field min_luminance? number|boolean
+---@field mirror? string
+---@field mode? string
+---@field output string
+---@field position? string
+---@field reserved? integer|HL.CssGap
+---@field reserved_area? integer|HL.CssGap
+---@field scale? string|number
+---@field sdr_eotf? string
+---@field sdr_max_luminance? integer|boolean
+---@field sdr_min_luminance? number|boolean
+---@field sdrbrightness? number|boolean
+---@field sdrsaturation? number|boolean
+---@field supports_hdr? integer|boolean
+---@field supports_wide_color? integer|boolean
+---@field transform? integer|boolean
+---@field vrr? integer|boolean
+local __HL_MonitorSpec = {}
+
+---@class HL.WindowRuleSpec
+---@field enabled? boolean
+---@field match? table<string, string|number|boolean>
+---@field name? string
+local __HL_WindowRuleSpec = {}
+
+---@class HL.WorkspaceRuleSpec
+---@field animation? string
+---@field border_size? integer|boolean
+---@field decorate? boolean
+---@field default? boolean
+---@field default_name? string
+---@field enabled? boolean
+---@field float_gaps? integer|HL.CssGap
+---@field gaps_in? integer|HL.CssGap
+---@field gaps_out? integer|HL.CssGap
+---@field layout? string
+---@field layout_opts? table<string, string|number|boolean>
+---@field monitor? string
+---@field no_border? boolean
+---@field no_rounding? boolean
+---@field no_shadow? boolean
+---@field on_created_empty? string
+---@field persistent? boolean
+---@field workspace string
+local __HL_WorkspaceRuleSpec = {}
+
+---@class HL.EventSubscription
+---@field is_active fun(self: HL.EventSubscription, ...): any
+---@field remove fun(self: HL.EventSubscription, ...): any
+local __HL_EventSubscription = {}
+
+---@class HL.Group
+---@field current HL.Window|nil
+---@field current_index integer
+---@field denied boolean
+---@field locked boolean
+---@field members HL.Window|table|nil
+---@field size integer
+local __HL_Group = {}
+
+---@class HL.Keybind
+---@field is_enabled fun(self: HL.Keybind, ...): any
+---@field remove fun(self: HL.Keybind, ...): any
+---@field set_enabled fun(self: HL.Keybind, ...): any
+---@field unbind fun(self: HL.Keybind, ...): any
+---@field arg string
+---@field auto_consuming boolean
+---@field catchall boolean
+---@field click boolean
+---@field description any
+---@field device_inclusive boolean
+---@field devices nil
+---@field display_key string
+---@field dont_inhibit boolean
+---@field drag boolean
+---@field enabled boolean
+---@field handler string
+---@field has_description boolean
+---@field ignore_mods boolean
+---@field key string
+---@field keycode integer
+---@field locked boolean
+---@field long_press boolean
+---@field modmask integer
+---@field mouse boolean
+---@field non_consuming boolean
+---@field release boolean
+---@field repeating boolean
+---@field submap string
+---@field submap_universal boolean
+---@field transparent boolean
+local __HL_Keybind = {}
+
+---@class HL.LayerRule
+---@field is_enabled fun(self: HL.LayerRule, ...): any
+---@field set_enabled fun(self: HL.LayerRule, ...): any
+local __HL_LayerRule = {}
+
+---@class HL.LayerSurface
+---@field above_fullscreen boolean|nil
+---@field address string
+---@field h integer
+---@field interactivity integer
+---@field layer integer
+---@field mapped boolean
+---@field monitor HL.Monitor|nil
+---@field namespace string
+---@field pid integer
+---@field w integer
+---@field x integer
+---@field y integer
+local __HL_LayerSurface = {}
+
+---@class HL.Monitor
+---@field active_special_workspace HL.Workspace|nil
+---@field active_workspace HL.Workspace|nil
+---@field description string
+---@field dpms_status boolean
+---@field focused boolean|nil
+---@field height integer
+---@field id integer
+---@field is_mirror boolean
+---@field mirrors HL.Monitor|table
+---@field name string
+---@field position integer|table
+---@field refresh_rate number
+---@field scale number
+---@field size integer|table
+---@field transform integer
+---@field vrr_active boolean
+---@field width integer
+---@field x integer
+---@field y integer
+local __HL_Monitor = {}
+
+---@class HL.Notification
+---@field dismiss fun(self: HL.Notification, ...): any
+---@field get_color fun(self: HL.Notification, ...): any
+---@field get_elapsed fun(self: HL.Notification, ...): any
+---@field get_elapsed_since_creation fun(self: HL.Notification, ...): any
+---@field get_font_size fun(self: HL.Notification, ...): any
+---@field get_icon fun(self: HL.Notification, ...): any
+---@field get_text fun(self: HL.Notification, ...): any
+---@field get_timeout fun(self: HL.Notification, ...): any
+---@field is_alive fun(self: HL.Notification, ...): any
+---@field is_paused fun(self: HL.Notification, ...): any
+---@field pause fun(self: HL.Notification, ...): any
+---@field resume fun(self: HL.Notification, ...): any
+---@field set_color fun(self: HL.Notification, ...): any
+---@field set_font_size fun(self: HL.Notification, ...): any
+---@field set_icon fun(self: HL.Notification, ...): any
+---@field set_paused fun(self: HL.Notification, ...): any
+---@field set_text fun(self: HL.Notification, ...): any
+---@field set_timeout fun(self: HL.Notification, ...): any
+local __HL_Notification = {}
+
+---@class HL.Timer
+---@field is_enabled fun(self: HL.Timer, ...): any
+---@field set_enabled fun(self: HL.Timer, ...): any
+---@field set_timeout fun(self: HL.Timer, ...): any
+local __HL_Timer = {}
+
+---@class HL.Window
+---@field accepts_input boolean
+---@field active boolean|nil
+---@field address string
+---@field at integer|table
+---@field class string
+---@field content_type string
+---@field floating boolean
+---@field focus_history_id integer
+---@field fullscreen integer
+---@field fullscreen_client integer
+---@field group HL.Group|nil
+---@field hidden boolean
+---@field inhibiting_idle boolean
+---@field initial_class string
+---@field initial_title string
+---@field layout HL.Window|boolean|integer|number|string|table|nil
+---@field mapped boolean
+---@field monitor HL.Monitor|nil
+---@field over_fullscreen boolean
+---@field pid integer
+---@field pinned boolean
+---@field size integer|table
+---@field stable_id integer
+---@field swallowing HL.Window|nil
+---@field tags string|table
+---@field title string
+---@field visible boolean
+---@field workspace HL.Workspace|nil
+---@field xdg_description string|nil
+---@field xdg_tag string|nil
+---@field xwayland boolean
+local __HL_Window = {}
+
+---@class HL.WindowRule
+---@field is_enabled fun(self: HL.WindowRule, ...): any
+---@field set_enabled fun(self: HL.WindowRule, ...): any
+local __HL_WindowRule = {}
+
+---@class HL.Workspace
+---@field get_groups fun(self: HL.Workspace, ...): any
+---@field get_windows fun(self: HL.Workspace, ...): any
+---@field active boolean
+---@field config_name string
+---@field fullscreen_mode integer
+---@field fullscreen_window HL.Window|nil
+---@field groups integer|nil
+---@field has_fullscreen boolean
+---@field has_urgent boolean
+---@field id integer
+---@field is_empty boolean
+---@field is_persistent boolean
+---@field last_window HL.Window|nil
+---@field monitor HL.Monitor|nil
+---@field name string
+---@field special boolean
+---@field tiled_layout string
+---@field visible boolean
+---@field windows integer
+local __HL_Workspace = {}
+
+---@class HL.API
+---@field animation fun(...): any
+---@field bind fun(keys: string, dispatcher: HL.Dispatcher|function, opts?: HL.BindOptions): HL.Keybind
+---@field config fun(config: table): nil
+---@field curve fun(...): any
+---@field define_submap fun(name: string, reset_or_fn: string|function, fn?: function): nil
+---@field device fun(spec: HL.DeviceSpec): nil
+---@field dispatch fun(dispatcher: HL.Dispatcher|function): any
+---@field env fun(...): any
+---@field exec_cmd fun(cmd: string, rules?: table<string, string|number|boolean>): nil
+---@field gesture fun(spec: HL.GestureSpec): nil
+---@field get_active_monitor fun(): HL.Monitor|nil
+---@field get_active_special_workspace fun(monitor?: HL.MonitorSelector): HL.Workspace|nil
+---@field get_active_window fun(): HL.Window|nil
+---@field get_active_workspace fun(monitor?: HL.MonitorSelector): HL.Workspace|nil
+---@field get_config fun(key: HL.ConfigKey|string): any, string?
+---@field get_current_submap fun(): string
+---@field get_cursor_pos fun(): HL.Vec2|nil
+---@field get_last_window fun(): HL.Window|nil
+---@field get_last_workspace fun(monitor?: HL.MonitorSelector): HL.Workspace|nil
+---@field get_layers fun(filters?: HL.LayerQueryFilter): HL.LayerSurface[]
+---@field get_monitor fun(selector: HL.MonitorSelector): HL.Monitor|nil
+---@field get_monitor_at fun(x: number|HL.Vec2, y?: number): HL.Monitor|nil
+---@field get_monitor_at_cursor fun(): HL.Monitor|nil
+---@field get_monitors fun(): HL.Monitor[]
+---@field get_urgent_window fun(): HL.Window|nil
+---@field get_window fun(selector: HL.WindowSelector): HL.Window|nil
+---@field get_windows fun(filters?: HL.WindowQueryFilter): HL.Window[]
+---@field get_workspace fun(selector: HL.WorkspaceSelector): HL.Workspace|nil
+---@field get_workspace_windows fun(workspace: HL.WorkspaceSelector): HL.Window[]
+---@field get_workspaces fun(): HL.Workspace[]
+---@field layer_rule fun(spec: HL.LayerRuleSpec): HL.LayerRule
+---@field monitor fun(spec: HL.MonitorSpec): nil
+---@field on fun(event: HL.EventName, cb: fun(...)): HL.EventSubscription
+---@field permission fun(spec: HL.PermissionSpec): nil
+---@field timer fun(callback: function, opts: HL.TimerOptions): HL.Timer
+---@field unbind fun(...): any
+---@field version fun(...): any
+---@field window_rule fun(spec: HL.WindowRuleSpec): HL.WindowRule
+---@field workspace_rule fun(spec: HL.WorkspaceRuleSpec): nil
+---@field dsp HL.DspNamespace
+---@field layout HL.LayoutNamespace
+---@field notification HL.NotificationNamespace
+---@field plugin HL.PluginNamespace
+local __HL_API = {}
+
+---@class HL.DspNamespace
+---@field dpms fun(...): HL.Dispatcher
+---@field event fun(...): HL.Dispatcher
+---@field exec_cmd fun(...): HL.Dispatcher
+---@field exec_raw fun(...): HL.Dispatcher
+---@field exit fun(...): HL.Dispatcher
+---@field focus fun(...): HL.Dispatcher
+---@field force_idle fun(...): HL.Dispatcher
+---@field force_renderer_reload fun(...): HL.Dispatcher
+---@field global fun(...): HL.Dispatcher
+---@field layout fun(...): HL.Dispatcher
+---@field no_op fun(...): HL.Dispatcher
+---@field pass fun(...): HL.Dispatcher
+---@field send_key_state fun(...): HL.Dispatcher
+---@field send_shortcut fun(...): HL.Dispatcher
+---@field submap fun(...): HL.Dispatcher
+---@field cursor HL.DspCursorNamespace
+---@field group HL.DspGroupNamespace
+---@field window HL.DspWindowNamespace
+---@field workspace HL.DspWorkspaceNamespace
+local __HL_DspNamespace = {}
+
+---@class HL.DspCursorNamespace
+---@field move fun(...): HL.Dispatcher
+---@field move_to_corner fun(...): HL.Dispatcher
+local __HL_DspCursorNamespace = {}
+
+---@class HL.DspGroupNamespace
+---@field active fun(...): HL.Dispatcher
+---@field lock fun(...): HL.Dispatcher
+---@field lock_active fun(...): HL.Dispatcher
+---@field move_window fun(...): HL.Dispatcher
+---@field next fun(...): HL.Dispatcher
+---@field prev fun(...): HL.Dispatcher
+---@field toggle fun(...): HL.Dispatcher
+local __HL_DspGroupNamespace = {}
+
+---@class HL.DspWindowNamespace
+---@field alter_zorder fun(...): HL.Dispatcher
+---@field bring_to_top fun(...): HL.Dispatcher
+---@field center fun(...): HL.Dispatcher
+---@field clear_tags fun(...): HL.Dispatcher
+---@field close fun(...): HL.Dispatcher
+---@field cycle_next fun(...): HL.Dispatcher
+---@field deny_from_group fun(...): HL.Dispatcher
+---@field drag fun(...): HL.Dispatcher
+---@field float fun(...): HL.Dispatcher
+---@field fullscreen fun(...): HL.Dispatcher
+---@field fullscreen_state fun(...): HL.Dispatcher
+---@field kill fun(...): HL.Dispatcher
+---@field move fun(...): HL.Dispatcher
+---@field pin fun(...): HL.Dispatcher
+---@field pseudo fun(...): HL.Dispatcher
+---@field resize fun(...): HL.Dispatcher
+---@field set_prop fun(...): HL.Dispatcher
+---@field signal fun(...): HL.Dispatcher
+---@field swap fun(...): HL.Dispatcher
+---@field tag fun(...): HL.Dispatcher
+---@field toggle_swallow fun(...): HL.Dispatcher
+local __HL_DspWindowNamespace = {}
+
+---@class HL.DspWorkspaceNamespace
+---@field move fun(...): HL.Dispatcher
+---@field rename fun(...): HL.Dispatcher
+---@field swap_monitors fun(...): HL.Dispatcher
+---@field toggle_special fun(...): HL.Dispatcher
+local __HL_DspWorkspaceNamespace = {}
+
+---@class HL.LayoutNamespace
+---@field register fun(name: string, provider: HL.LayoutProvider): nil
+local __HL_LayoutNamespace = {}
+
+---@class HL.NotificationNamespace
+---@field create fun(opts?: HL.NotificationOptions): HL.Notification
+---@field get fun(): HL.Notification[]
+local __HL_NotificationNamespace = {}
+
+---@class HL.PluginNamespace
+---@field load fun(...): any
+---@field [string] any
+local __HL_PluginNamespace = {}
+
+---@type HL.API
+hl = {}
+
+---@class HL.ConfigValueTypes
+---@field ['animations.enabled'] boolean
+---@field ['animations.workspace_wraparound'] boolean
+---@field ['binds.allow_pin_fullscreen'] boolean
+---@field ['binds.allow_workspace_cycles'] boolean
+---@field ['binds.disable_keybind_grabbing'] boolean
+---@field ['binds.drag_threshold'] integer|boolean
+---@field ['binds.focus_preferred_method'] integer|boolean
+---@field ['binds.hide_special_on_workspace_change'] boolean
+---@field ['binds.ignore_group_lock'] boolean
+---@field ['binds.movefocus_cycles_fullscreen'] boolean
+---@field ['binds.movefocus_cycles_groupfirst'] boolean
+---@field ['binds.pass_mouse_when_bound'] boolean
+---@field ['binds.scroll_event_delay'] integer|boolean
+---@field ['binds.window_direction_monitor_fallback'] boolean
+---@field ['binds.workspace_back_and_forth'] boolean
+---@field ['binds.workspace_center_on'] integer|boolean
+---@field ['cursor.default_monitor'] string
+---@field ['cursor.enable_hyprcursor'] boolean
+---@field ['cursor.hide_on_key_press'] boolean
+---@field ['cursor.hide_on_tablet'] boolean
+---@field ['cursor.hide_on_touch'] boolean
+---@field ['cursor.hotspot_padding'] integer|boolean
+---@field ['cursor.inactive_timeout'] number|boolean
+---@field ['cursor.invisible'] boolean
+---@field ['cursor.min_refresh_rate'] integer|boolean
+---@field ['cursor.no_break_fs_vrr'] integer|boolean
+---@field ['cursor.no_hardware_cursors'] integer|boolean
+---@field ['cursor.no_warps'] boolean
+---@field ['cursor.persistent_warps'] boolean
+---@field ['cursor.sync_gsettings_theme'] boolean
+---@field ['cursor.use_cpu_buffer'] integer|boolean
+---@field ['cursor.warp_back_after_non_mouse_input'] boolean
+---@field ['cursor.warp_on_change_workspace'] integer|boolean
+---@field ['cursor.warp_on_toggle_special'] integer|boolean
+---@field ['cursor.zoom_detached_camera'] boolean
+---@field ['cursor.zoom_disable_aa'] boolean
+---@field ['cursor.zoom_factor'] number|boolean
+---@field ['cursor.zoom_rigid'] boolean
+---@field ['debug.colored_stdout_logs'] boolean
+---@field ['debug.damage_blink'] boolean
+---@field ['debug.damage_tracking'] integer|boolean
+---@field ['debug.disable_logs'] boolean
+---@field ['debug.disable_scale_checks'] boolean
+---@field ['debug.disable_time'] boolean
+---@field ['debug.ds_handle_same_buffer'] boolean
+---@field ['debug.ds_handle_same_buffer_fifo'] boolean
+---@field ['debug.enable_stdout_logs'] boolean
+---@field ['debug.error_limit'] integer|boolean
+---@field ['debug.error_position'] integer|boolean
+---@field ['debug.fifo_pending_workaround'] boolean
+---@field ['debug.full_cm_proto'] boolean
+---@field ['debug.gl_debugging'] boolean
+---@field ['debug.invalidate_fp16'] integer|boolean
+---@field ['debug.log_damage'] boolean
+---@field ['debug.manual_crash'] integer|boolean
+---@field ['debug.overlay'] boolean
+---@field ['debug.pass'] boolean
+---@field ['debug.render_solitary_wo_damage'] boolean
+---@field ['debug.suppress_errors'] boolean
+---@field ['debug.vfr'] boolean
+---@field ['decoration.active_opacity'] number|boolean
+---@field ['decoration.blur.brightness'] number|boolean
+---@field ['decoration.blur.contrast'] number|boolean
+---@field ['decoration.blur.enabled'] boolean
+---@field ['decoration.blur.ignore_opacity'] boolean
+---@field ['decoration.blur.input_methods'] boolean
+---@field ['decoration.blur.input_methods_ignorealpha'] number|boolean
+---@field ['decoration.blur.new_optimizations'] boolean
+---@field ['decoration.blur.noise'] number|boolean
+---@field ['decoration.blur.passes'] integer|boolean
+---@field ['decoration.blur.popups'] boolean
+---@field ['decoration.blur.popups_ignorealpha'] number|boolean
+---@field ['decoration.blur.size'] integer|boolean
+---@field ['decoration.blur.special'] boolean
+---@field ['decoration.blur.vibrancy'] number|boolean
+---@field ['decoration.blur.vibrancy_darkness'] number|boolean
+---@field ['decoration.blur.xray'] boolean
+---@field ['decoration.border_part_of_window'] boolean
+---@field ['decoration.dim_around'] number|boolean
+---@field ['decoration.dim_inactive'] boolean
+---@field ['decoration.dim_modal'] boolean
+---@field ['decoration.dim_special'] number|boolean
+---@field ['decoration.dim_strength'] number|boolean
+---@field ['decoration.fullscreen_opacity'] number|boolean
+---@field ['decoration.glow.color'] string
+---@field ['decoration.glow.color_inactive'] string
+---@field ['decoration.glow.enabled'] boolean
+---@field ['decoration.glow.range'] integer|boolean
+---@field ['decoration.glow.render_power'] integer|boolean
+---@field ['decoration.inactive_opacity'] number|boolean
+---@field ['decoration.rounding'] integer|boolean
+---@field ['decoration.rounding_power'] number|boolean
+---@field ['decoration.screen_shader'] string
+---@field ['decoration.shadow.color'] string
+---@field ['decoration.shadow.color_inactive'] string
+---@field ['decoration.shadow.enabled'] boolean
+---@field ['decoration.shadow.offset'] HL.Vec2Like
+---@field ['decoration.shadow.range'] integer|boolean
+---@field ['decoration.shadow.render_power'] integer|boolean
+---@field ['decoration.shadow.scale'] number|boolean
+---@field ['decoration.shadow.sharp'] boolean
+---@field ['dwindle.default_split_ratio'] number|boolean
+---@field ['dwindle.force_split'] integer|boolean
+---@field ['dwindle.permanent_direction_override'] boolean
+---@field ['dwindle.precise_mouse_move'] boolean
+---@field ['dwindle.preserve_split'] boolean
+---@field ['dwindle.smart_resizing'] boolean
+---@field ['dwindle.smart_split'] boolean
+---@field ['dwindle.special_scale_factor'] number|boolean
+---@field ['dwindle.split_bias'] integer|boolean
+---@field ['dwindle.split_width_multiplier'] number|boolean
+---@field ['dwindle.use_active_for_splits'] boolean
+---@field ['ecosystem.enforce_permissions'] boolean
+---@field ['ecosystem.no_donation_nag'] boolean
+---@field ['ecosystem.no_update_news'] boolean
+---@field ['experimental.wp_cm_1_2'] boolean
+---@field ['general.allow_tearing'] boolean
+---@field ['general.border_size'] integer|boolean
+---@field ['general.col.active_border'] string|HL.Gradient
+---@field ['general.col.inactive_border'] string|HL.Gradient
+---@field ['general.col.nogroup_border'] string|HL.Gradient
+---@field ['general.col.nogroup_border_active'] string|HL.Gradient
+---@field ['general.extend_border_grab_area'] integer|boolean
+---@field ['general.float_gaps'] integer|HL.CssGap
+---@field ['general.gaps_in'] integer|HL.CssGap
+---@field ['general.gaps_out'] integer|HL.CssGap
+---@field ['general.gaps_workspaces'] integer|boolean
+---@field ['general.hover_icon_on_border'] boolean
+---@field ['general.layout'] string
+---@field ['general.locale'] string
+---@field ['general.modal_parent_blocking'] boolean
+---@field ['general.no_focus_fallback'] boolean
+---@field ['general.resize_corner'] integer|boolean
+---@field ['general.resize_on_border'] boolean
+---@field ['general.snap.border_overlap'] boolean
+---@field ['general.snap.enabled'] boolean
+---@field ['general.snap.monitor_gap'] integer|boolean
+---@field ['general.snap.respect_gaps'] boolean
+---@field ['general.snap.window_gap'] integer|boolean
+---@field ['gestures.close_max_timeout'] integer|boolean
+---@field ['gestures.scrolling.move_snap_cursor'] boolean
+---@field ['gestures.scrolling.move_snap_to_grid'] boolean
+---@field ['gestures.workspace_swipe_cancel_ratio'] number|boolean
+---@field ['gestures.workspace_swipe_create_new'] boolean
+---@field ['gestures.workspace_swipe_direction_lock'] boolean
+---@field ['gestures.workspace_swipe_direction_lock_threshold'] integer|boolean
+---@field ['gestures.workspace_swipe_distance'] integer|boolean
+---@field ['gestures.workspace_swipe_forever'] boolean
+---@field ['gestures.workspace_swipe_invert'] boolean
+---@field ['gestures.workspace_swipe_min_speed_to_force'] integer|boolean
+---@field ['gestures.workspace_swipe_touch'] boolean
+---@field ['gestures.workspace_swipe_touch_invert'] boolean
+---@field ['gestures.workspace_swipe_use_r'] boolean
+---@field ['group.auto_group'] boolean
+---@field ['group.col.border_active'] string|HL.Gradient
+---@field ['group.col.border_inactive'] string|HL.Gradient
+---@field ['group.col.border_locked_active'] string|HL.Gradient
+---@field ['group.col.border_locked_inactive'] string|HL.Gradient
+---@field ['group.drag_into_group'] integer|boolean
+---@field ['group.focus_removed_window'] boolean
+---@field ['group.group_on_movetoworkspace'] boolean
+---@field ['group.groupbar.blur'] boolean
+---@field ['group.groupbar.col.active'] string|HL.Gradient
+---@field ['group.groupbar.col.inactive'] string|HL.Gradient
+---@field ['group.groupbar.col.locked_active'] string|HL.Gradient
+---@field ['group.groupbar.col.locked_inactive'] string|HL.Gradient
+---@field ['group.groupbar.enabled'] boolean
+---@field ['group.groupbar.font_family'] string
+---@field ['group.groupbar.font_size'] integer|boolean
+---@field ['group.groupbar.font_weight_active'] integer|string
+---@field ['group.groupbar.font_weight_inactive'] integer|string
+---@field ['group.groupbar.gaps_in'] integer|boolean
+---@field ['group.groupbar.gaps_out'] integer|boolean
+---@field ['group.groupbar.gradient_round_only_edges'] boolean
+---@field ['group.groupbar.gradient_rounding'] integer|boolean
+---@field ['group.groupbar.gradient_rounding_power'] number|boolean
+---@field ['group.groupbar.gradients'] boolean
+---@field ['group.groupbar.height'] integer|boolean
+---@field ['group.groupbar.indicator_gap'] integer|boolean
+---@field ['group.groupbar.indicator_height'] integer|boolean
+---@field ['group.groupbar.keep_upper_gap'] boolean
+---@field ['group.groupbar.middle_click_close'] boolean
+---@field ['group.groupbar.priority'] integer|boolean
+---@field ['group.groupbar.render_titles'] boolean
+---@field ['group.groupbar.round_only_edges'] boolean
+---@field ['group.groupbar.rounding'] integer|boolean
+---@field ['group.groupbar.rounding_power'] number|boolean
+---@field ['group.groupbar.scrolling'] boolean
+---@field ['group.groupbar.stacked'] boolean
+---@field ['group.groupbar.text_color'] string
+---@field ['group.groupbar.text_color_inactive'] string
+---@field ['group.groupbar.text_color_locked_active'] string
+---@field ['group.groupbar.text_color_locked_inactive'] string
+---@field ['group.groupbar.text_offset'] integer|boolean
+---@field ['group.groupbar.text_padding'] integer|boolean
+---@field ['group.insert_after_current'] boolean
+---@field ['group.merge_floated_into_tiled_on_groupbar'] boolean
+---@field ['group.merge_groups_on_drag'] boolean
+---@field ['group.merge_groups_on_groupbar'] boolean
+---@field ['input.accel_profile'] string
+---@field ['input.emulate_discrete_scroll'] integer|boolean
+---@field ['input.float_switch_override_focus'] integer|boolean
+---@field ['input.focus_on_close'] integer|boolean
+---@field ['input.follow_mouse'] integer|boolean
+---@field ['input.follow_mouse_shrink'] integer|boolean
+---@field ['input.follow_mouse_threshold'] number|boolean
+---@field ['input.force_no_accel'] boolean
+---@field ['input.kb_file'] string
+---@field ['input.kb_layout'] string
+---@field ['input.kb_model'] string
+---@field ['input.kb_options'] string
+---@field ['input.kb_rules'] string
+---@field ['input.kb_variant'] string
+---@field ['input.left_handed'] boolean
+---@field ['input.mouse_refocus'] boolean
+---@field ['input.natural_scroll'] boolean
+---@field ['input.numlock_by_default'] boolean
+---@field ['input.off_window_axis_events'] integer|boolean
+---@field ['input.repeat_delay'] integer|boolean
+---@field ['input.repeat_rate'] integer|boolean
+---@field ['input.resolve_binds_by_sym'] boolean
+---@field ['input.rotation'] integer|boolean
+---@field ['input.scroll_button'] integer|boolean
+---@field ['input.scroll_button_lock'] boolean
+---@field ['input.scroll_factor'] number|boolean
+---@field ['input.scroll_method'] string
+---@field ['input.scroll_points'] string
+---@field ['input.sensitivity'] number|boolean
+---@field ['input.special_fallthrough'] boolean
+---@field ['input.tablet.absolute_region_position'] boolean
+---@field ['input.tablet.active_area_position'] HL.Vec2Like
+---@field ['input.tablet.active_area_size'] HL.Vec2Like
+---@field ['input.tablet.left_handed'] boolean
+---@field ['input.tablet.output'] string
+---@field ['input.tablet.region_position'] HL.Vec2Like
+---@field ['input.tablet.region_size'] HL.Vec2Like
+---@field ['input.tablet.relative_input'] boolean
+---@field ['input.tablet.transform'] integer|boolean
+---@field ['input.touchdevice.enabled'] boolean
+---@field ['input.touchdevice.output'] string
+---@field ['input.touchdevice.transform'] integer|boolean
+---@field ['input.touchpad.clickfinger_behavior'] boolean
+---@field ['input.touchpad.disable_while_typing'] boolean
+---@field ['input.touchpad.drag_3fg'] integer|boolean
+---@field ['input.touchpad.drag_lock'] integer|boolean
+---@field ['input.touchpad.flip_x'] boolean
+---@field ['input.touchpad.flip_y'] boolean
+---@field ['input.touchpad.middle_button_emulation'] boolean
+---@field ['input.touchpad.natural_scroll'] boolean
+---@field ['input.touchpad.scroll_factor'] number|boolean
+---@field ['input.touchpad.tap_and_drag'] boolean
+---@field ['input.touchpad.tap_button_map'] string
+---@field ['input.touchpad.tap_to_click'] boolean
+---@field ['input.virtualkeyboard.release_pressed_on_close'] boolean
+---@field ['input.virtualkeyboard.share_states'] integer|boolean
+---@field ['layout.single_window_aspect_ratio'] HL.Vec2Like
+---@field ['layout.single_window_aspect_ratio_tolerance'] number|boolean
+---@field ['master.allow_small_split'] boolean
+---@field ['master.always_keep_position'] boolean
+---@field ['master.center_ignores_reserved'] boolean
+---@field ['master.center_master_fallback'] string
+---@field ['master.drop_at_cursor'] boolean
+---@field ['master.focus_master_on_close'] boolean
+---@field ['master.mfact'] number|boolean
+---@field ['master.new_on_active'] string
+---@field ['master.new_on_top'] boolean
+---@field ['master.new_status'] string
+---@field ['master.orientation'] string
+---@field ['master.slave_count_for_center_master'] integer|boolean
+---@field ['master.smart_resizing'] boolean
+---@field ['master.special_scale_factor'] number|boolean
+---@field ['misc.allow_session_lock_restore'] boolean
+---@field ['misc.always_follow_on_dnd'] boolean
+---@field ['misc.animate_manual_resizes'] boolean
+---@field ['misc.animate_mouse_windowdragging'] boolean
+---@field ['misc.anr_missed_pings'] integer|boolean
+---@field ['misc.background_color'] string
+---@field ['misc.close_special_on_empty'] boolean
+---@field ['misc.col.splash'] string
+---@field ['misc.disable_autoreload'] boolean
+---@field ['misc.disable_hyprland_guiutils_check'] boolean
+---@field ['misc.disable_hyprland_logo'] boolean
+---@field ['misc.disable_scale_notification'] boolean
+---@field ['misc.disable_splash_rendering'] boolean
+---@field ['misc.disable_watchdog_warning'] boolean
+---@field ['misc.disable_xdg_env_checks'] boolean
+---@field ['misc.enable_anr_dialog'] boolean
+---@field ['misc.enable_swallow'] boolean
+---@field ['misc.exit_window_retains_fullscreen'] boolean
+---@field ['misc.focus_on_activate'] boolean
+---@field ['misc.font_family'] string
+---@field ['misc.force_default_wallpaper'] integer|boolean
+---@field ['misc.initial_workspace_tracking'] integer|boolean
+---@field ['misc.key_press_enables_dpms'] boolean
+---@field ['misc.layers_hog_keyboard_focus'] boolean
+---@field ['misc.lockdead_screen_delay'] integer|boolean
+---@field ['misc.middle_click_paste'] boolean
+---@field ['misc.mouse_move_enables_dpms'] boolean
+---@field ['misc.mouse_move_focuses_monitor'] boolean
+---@field ['misc.name_vk_after_proc'] boolean
+---@field ['misc.on_focus_under_fullscreen'] integer|boolean
+---@field ['misc.render_unfocused_fps'] integer|boolean
+---@field ['misc.screencopy_force_8b'] boolean
+---@field ['misc.session_lock_xray'] boolean
+---@field ['misc.size_limits_tiled'] boolean
+---@field ['misc.splash_font_family'] string
+---@field ['misc.swallow_exception_regex'] string
+---@field ['misc.swallow_regex'] string
+---@field ['misc.vrr'] integer|boolean
+---@field ['opengl.nvidia_anti_flicker'] boolean
+---@field ['quirks.prefer_hdr'] integer|boolean
+---@field ['quirks.skip_non_kms_dmabuf_formats'] boolean
+---@field ['render.cm_auto_hdr'] integer|boolean
+---@field ['render.cm_enabled'] boolean
+---@field ['render.cm_sdr_eotf'] string
+---@field ['render.commit_timing_enabled'] boolean
+---@field ['render.ctm_animation'] integer|boolean
+---@field ['render.direct_scanout'] integer|boolean
+---@field ['render.expand_undersized_textures'] boolean
+---@field ['render.fp16_sdr_tf'] integer|boolean
+---@field ['render.icc_vcgt_enabled'] boolean
+---@field ['render.keep_unmodified_copy'] integer|boolean
+---@field ['render.new_render_scheduling'] boolean
+---@field ['render.non_shader_cm'] integer|boolean
+---@field ['render.non_shader_cm_interop'] integer|boolean
+---@field ['render.send_content_type'] boolean
+---@field ['render.use_fp16'] integer|boolean
+---@field ['render.use_shader_blur_blend'] boolean
+---@field ['render.xp_mode'] boolean
+---@field ['scrolling.column_width'] number|boolean
+---@field ['scrolling.direction'] string
+---@field ['scrolling.explicit_column_widths'] string
+---@field ['scrolling.focus_fit_method'] integer|boolean
+---@field ['scrolling.follow_focus'] boolean
+---@field ['scrolling.follow_min_visible'] number|boolean
+---@field ['scrolling.fullscreen_on_one_column'] boolean
+---@field ['scrolling.wrap_focus'] boolean
+---@field ['scrolling.wrap_swapcol'] boolean
+---@field ['xwayland.create_abstract_socket'] boolean
+---@field ['xwayland.enabled'] boolean
+---@field ['xwayland.force_zero_scaling'] boolean
+---@field ['xwayland.use_nearest_neighbor'] boolean
+local __HL_ConfigValueTypes = {}
diff --git a/config/hypr/hyprland.conf b/config/hypr/hyprland.conf
index 26701470..43ad22f3 100644
--- a/config/hypr/hyprland.conf
+++ b/config/hypr/hyprland.conf
@@ -26,8 +26,10 @@ source= $UserConfigs/Laptops.conf
source= $UserConfigs/LaptopDisplay.conf
# Load defaults, then user additions
-source= $configs/WindowRules.conf # Window Rules and Layer Rules (defaults)
-source= $UserConfigs/WindowRules.conf # Window Rules and Layer Rules (user)
+source= $configs/WindowRules.conf # Window Rules (defaults)
+source= $UserConfigs/WindowRules.conf # Window Rules (user)
+source= $configs/LayerRules.conf # Layer Rules (defaults)
+source= $UserConfigs/LayerRules.conf # Layer Rules (user)
source= $configs/SystemSettings.conf # Default config for hypr
diff --git a/config/hypr/hyprland.lua.disable b/config/hypr/hyprland.lua.disable
new file mode 100644
index 00000000..920976ba
--- /dev/null
+++ b/config/hypr/hyprland.lua.disable
@@ -0,0 +1,25 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- KoolDots Hyprland Lua config entrypoint.
+-- Mirrors hyprland.conf include order for features currently supported by Lua config.
+local configHome = os.getenv("XDG_CONFIG_HOME") or (os.getenv("HOME") .. "/.config")
+local hyprDir = configHome .. "/hypr"
+
+local function load_module(name)
+ dofile(hyprDir .. "/lua/" .. name .. ".lua")
+end
+
+-- In Lua workflow, runtime config is loaded from split files under:
+-- ~/.config/hypr/configs/system_*.lua
+-- ~/.config/hypr/UserConfigs/user_*.lua
+-- via lua/user_overrides.lua. Base lua/*.lua modules are templates and should
+-- not also be loaded directly here, or bindings/settings can be duplicated.
+load_module("user_defaults")
+load_module("user_overrides")
+load_module("monitors")
+load_module("workspaces")
diff --git a/config/hypr/hyprlock-1080p.conf b/config/hypr/hyprlock-1080p.conf
deleted file mode 100644
index b0a0279c..00000000
--- a/config/hypr/hyprlock-1080p.conf
+++ /dev/null
@@ -1,182 +0,0 @@
-# /* ---- 💫 https://github.com/LinuxBeginnings 💫 ---- */ #
-# Hyprlock config for < 1080p monitor resolutions
-# Original config submitted by https://github.com/SherLock707
-
-# Sourcing colors generated by wallust
-source = $HOME/.config/hypr/wallust/wallust-hyprland.conf
-$Scripts = $HOME/.config/hypr/scripts
-
-general {
- fractional_scaling = 2
- immediate_render = true
-}
-
-background {
- monitor =
- # NOTE: use only 1 path
- #path = screenshot # screenshot of your desktop
- #path = $HOME/.config/hypr/wallpaper_effects/.wallpaper_modified # by wallpaper effects
- path = $HOME/.config/hypr/wallpaper_effects/.wallpaper_current # current wallpaper
-
- color = rgb(0,0,0) # color will be rendered initially until path is available
-
- # all these options are taken from hyprland, see https://wiki.hyprland.org/Configuring/Variables/#blur for explanations
- blur_size = 3
- blur_passes = 2 # 0 disables blurring
- noise = 0.0117
- contrast = 1.3000 # Vibrant!!!
- brightness = 0.8000
- vibrancy = 0.2100
- vibrancy_darkness = 0.0
-}
-
-
-# Date
-label {
- monitor =
- text = cmd[update:18000000] echo "<b> "$(date +'%A, %-d %B')" </b>"
- color = $color13
- font_size = 48
- font_family = Victor Mono Bold Italic
- position = 0, -60
- halign = center
- valign = center
-}
-
-# Hour-Time
-label {
- monitor =
-# text = cmd[update:1000] echo "$(date +"%H")"
- text = cmd[update:1000] echo "$(date +"%I:%M %p")" #AM/PM
- #color = rgba(255, 185, 0, .8)
- color = $color8
- font_size = 130
- font_family = JetBrainsMono Nerd Font ExtraBold
- position = 0, -250
- halign = center
- valign = top
-}
-
-# Minute-Time
-# label {
-# monitor =
-# text = cmd[update:1000] echo "$(date +"%M")"
-# #color = rgba(15, 10, 222, .8)
-# color = $color12
-# font_size = 150
-# font_family = JetBrainsMono Nerd Font ExtraBold
-# position = 0, -340
-# halign = center
- # valign = top
-# }
-
-# Seconds-Time
-# label {
-# monitor =
-## text = cmd[update:1000] echo "$(date +"%S")"
-# text = cmd[update:1000] echo "$(date +"%S %p")" #AM/PM
-# color = $color11
-# font_size = 32
-# font_family = JetBrainsMono Nerd Font ExtraBold
-# position = 0, -350
-# halign = center
-# valign = top
-# }
-
-# Put a picture of choice here. Default is the current wallpaper
-# image {
-# monitor =
-# path = $HOME/.config/hypr/wallpaper_effects/.wallpaper_current
-# size = 160
-# rounding = -1
-# border_size = 0
-# border_color = $color11
-# rotate = 0
-# reload_time = -1
-# position = 0, 280
-# halign = center
-# valign = bottom
-# }
-
-# USER
-label {
- monitor =
- text =  $USER
- color = $color9
- font_size = 36
- font_family = Victor Mono Bold Oblique
- position = 0, 275
- halign = center
- valign = bottom
-}
-
-# INPUT FIELD
-input-field {
- monitor =
- size = 230, 70
- outline_thickness = 2
- dots_size = 0.2 # Scale of input-field height, 0.2 - 0.8
- dots_spacing = 0.2 # Scale of dots' absolute size, 0.0 - 1.0
- dots_center = true
- outer_color = $color8
- inner_color = rgba(255, 255, 255, 0.1)
- capslock_color = rgb(255,255,255)
- font_color = $color13
- fade_on_empty = false
- font_family = Victor Mono Bold Oblique
- placeholder_text = <i><span foreground="##ffffff99">🔒 Type Password</span></i>
- hide_input = false
- position = 0, 100
- halign = center
- valign = bottom
-}
-
-# Keyboard LAYOUT
-label {
- monitor =
- text = $LAYOUT
- color = $color8
- font_size = 14
- font_family = Victor Mono Bold Oblique
- position = 0, 70
- halign = center
- valign = bottom
-}
-
-# uptime
-label {
- monitor =
- text = cmd[update:60000] echo "<b> "$(uptime -p || $Scripts/UptimeNixOS.sh)" </b>"
- color = $color8
- font_size = 24
- font_family = Victor Mono Bold Oblique
- position = 0, 0
- halign = right
- valign = bottom
-}
-
-# battery information
-label {
- monitor =
- text = cmd[update:1000] echo "<b> "$($Scripts/Battery.sh)" </b>"
- color = $color8
- font_size = 16
- font_family = Victor Mono Bold Oblique
- position = 0, 30
- halign = right
- valign = bottom
-}
-
-# weather edit the scripts for locations
-# weather scripts are located in ~/.config/hypr/UserScripts Weather.sh and/or Weather.py
-# see https://github.com/LinuxBeginnings/Hyprland-Dots/wiki/TIPS#%EF%B8%8F-weather-app-related-for-waybar-and-hyprlock
-label {
- monitor =
- text = cmd[update:3600000] [ -f "$HOME/.cache/.weather_cache" ] && cat "$HOME/.cache/.weather_cache"
- color = $color8
- font_size = 14
- font_family = Victor Mono Bold Oblique
- position = 50, 0
- halign = left
- valign = bottom
-}
diff --git a/config/hypr/hyprlock-2k.conf b/config/hypr/hyprlock-2k.conf
index 8c357d90..08fa8539 100644
--- a/config/hypr/hyprlock-2k.conf
+++ b/config/hypr/hyprlock-2k.conf
@@ -1,5 +1,5 @@
# /* ---- 💫 https://github.com/LinuxBeginnings 💫 ---- */ #
-# Hyprlock config for => 2k monitor resolutions
+# Hyprlock config for < 1080p monitor resolutions
# Original config submitted by https://github.com/SherLock707
# Sourcing colors generated by wallust
@@ -17,7 +17,7 @@ background {
#path = screenshot # screenshot of your desktop
#path = $HOME/.config/hypr/wallpaper_effects/.wallpaper_modified # by wallpaper effects
path = $HOME/.config/hypr/wallpaper_effects/.wallpaper_current # current wallpaper
-
+
color = rgb(0,0,0) # color will be rendered initially until path is available
# all these options are taken from hyprland, see https://wiki.hyprland.org/Configuring/Variables/#blur for explanations
@@ -36,64 +36,64 @@ label {
monitor =
text = cmd[update:18000000] echo "<b> "$(date +'%A, %-d %B')" </b>"
color = $color13
- font_size = 64
+ font_size = 48
font_family = Victor Mono Bold Italic
- position = 0, -20
+ position = 0, -60
halign = center
valign = center
}
-# Hour-Time (single horizontal time like 1080p variant)
+# Hour-Time
label {
monitor =
-# text = cmd[update:1000] echo "$(date +"%H:%M")" # 24h option
- text = cmd[update:1000] echo "$(date +"%I:%M %p")" # AM/PM
+# text = cmd[update:1000] echo "$(date +"%H")"
+ text = cmd[update:1000] echo "$(date +"%I:%M %p")" #AM/PM
#color = rgba(255, 185, 0, .8)
color = $color8
- font_size = 173
- font_family = JetBrainsMono Nerd Font ExtraBold
- position = 0, -133
+ font_size = 130
+ font_family = JetBrainsMono Nerd Font ExtraBold
+ position = 0, -250
halign = center
valign = top
}
-# Minute-Time (disabled; kept for reference)
+# Minute-Time
# label {
# monitor =
# text = cmd[update:1000] echo "$(date +"%M")"
# #color = rgba(15, 10, 222, .8)
# color = $color12
-# font_size = 240
+# font_size = 150
# font_family = JetBrainsMono Nerd Font ExtraBold
-# position = 0, -450
+# position = 0, -340
# halign = center
-# valign = top
+ # valign = top
# }
-# Seconds-Time (disabled; kept for reference)
+# Seconds-Time
# label {
-# monitor =
-# text = cmd[update:1000] echo "$(date +"%S")"
-# # text = cmd[update:1000] echo "$(date +"%S %p")" #AM/PM
-# color = $color11
-# font_size = 50
-# font_family = JetBrainsMono Nerd Font ExtraBold
-# position = 0, -450
-# halign = center
-# valign = top
+# monitor =
+## text = cmd[update:1000] echo "$(date +"%S")"
+ text = cmd[update:1000] echo "$(date +"%S %p")" #AM/PM
+# color = $color11
+# font_size = 32
+# font_family = JetBrainsMono Nerd Font ExtraBold
+# position = 0, -350
+# halign = center
+# valign = top
# }
# Put a picture of choice here. Default is the current wallpaper
# image {
# monitor =
-# #path = $HOME/.config/hypr/wallpaper_effects/.wallpaper_current
+# path = $HOME/.config/hypr/wallpaper_effects/.wallpaper_current
# size = 160
# rounding = -1
# border_size = 0
# border_color = $color11
# rotate = 0
# reload_time = -1
-# position = 0, 400
+# position = 0, 280
# halign = center
# valign = bottom
# }
@@ -103,9 +103,9 @@ label {
monitor =
text =  $USER
color = $color9
- font_size = 48
+ font_size = 36
font_family = Victor Mono Bold Oblique
- position = 0, 300
+ position = 0, 275
halign = center
valign = bottom
}
@@ -113,7 +113,7 @@ label {
# INPUT FIELD
input-field {
monitor =
- size = 306, 93
+ size = 230, 70
outline_thickness = 2
dots_size = 0.2 # Scale of input-field height, 0.2 - 0.8
dots_spacing = 0.2 # Scale of dots' absolute size, 0.0 - 1.0
@@ -136,9 +136,9 @@ label {
monitor =
text = $LAYOUT
color = $color8
- font_size = 19
+ font_size = 14
font_family = Victor Mono Bold Oblique
- position = 0, 53
+ position = 0, 70
halign = center
valign = bottom
}
@@ -148,7 +148,7 @@ label {
monitor =
text = cmd[update:60000] echo "<b> "$(uptime -p || $Scripts/UptimeNixOS.sh)" </b>"
color = $color8
- font_size = 32
+ font_size = 24
font_family = Victor Mono Bold Oblique
position = 0, 0
halign = right
@@ -160,9 +160,9 @@ label {
monitor =
text = cmd[update:1000] echo "<b> "$($Scripts/Battery.sh)" </b>"
color = $color8
- font_size = 21
+ font_size = 16
font_family = Victor Mono Bold Oblique
- position = 0, 40
+ position = 0, 30
halign = right
valign = bottom
}
@@ -172,9 +172,9 @@ label {
# see https://github.com/LinuxBeginnings/Hyprland-Dots/wiki/TIPS#%EF%B8%8F-weather-app-related-for-waybar-and-hyprlock
label {
monitor =
- text = cmd[update:3600000] [ -f "$HOME/.cache/.weather_cache" ] && cat "$HOME/.cache/.weather_cache"
+ text = cmd[update:3600000] [ -f "$HOME/.cache/.weather_cache" ] && cat "$HOME/.cache/.weather_cache"
color = $color8
- font_size = 19
+ font_size = 14
font_family = Victor Mono Bold Oblique
position = 50, 0
halign = left
diff --git a/config/hypr/hyprlock.conf b/config/hypr/hyprlock.conf
deleted file mode 100644
index 8c357d90..00000000
--- a/config/hypr/hyprlock.conf
+++ /dev/null
@@ -1,182 +0,0 @@
-# /* ---- 💫 https://github.com/LinuxBeginnings 💫 ---- */ #
-# Hyprlock config for => 2k monitor resolutions
-# Original config submitted by https://github.com/SherLock707
-
-# Sourcing colors generated by wallust
-source = $HOME/.config/hypr/wallust/wallust-hyprland.conf
-$Scripts = $HOME/.config/hypr/scripts
-
-general {
- fractional_scaling = 2
- immediate_render = true
-}
-
-background {
- monitor =
- # NOTE: use only 1 path
- #path = screenshot # screenshot of your desktop
- #path = $HOME/.config/hypr/wallpaper_effects/.wallpaper_modified # by wallpaper effects
- path = $HOME/.config/hypr/wallpaper_effects/.wallpaper_current # current wallpaper
-
- color = rgb(0,0,0) # color will be rendered initially until path is available
-
- # all these options are taken from hyprland, see https://wiki.hyprland.org/Configuring/Variables/#blur for explanations
- blur_size = 3
- blur_passes = 2 # 0 disables blurring
- noise = 0.0117
- contrast = 1.3000 # Vibrant!!!
- brightness = 0.8000
- vibrancy = 0.2100
- vibrancy_darkness = 0.0
-}
-
-
-# Date
-label {
- monitor =
- text = cmd[update:18000000] echo "<b> "$(date +'%A, %-d %B')" </b>"
- color = $color13
- font_size = 64
- font_family = Victor Mono Bold Italic
- position = 0, -20
- halign = center
- valign = center
-}
-
-# Hour-Time (single horizontal time like 1080p variant)
-label {
- monitor =
-# text = cmd[update:1000] echo "$(date +"%H:%M")" # 24h option
- text = cmd[update:1000] echo "$(date +"%I:%M %p")" # AM/PM
- #color = rgba(255, 185, 0, .8)
- color = $color8
- font_size = 173
- font_family = JetBrainsMono Nerd Font ExtraBold
- position = 0, -133
- halign = center
- valign = top
-}
-
-# Minute-Time (disabled; kept for reference)
-# label {
-# monitor =
-# text = cmd[update:1000] echo "$(date +"%M")"
-# #color = rgba(15, 10, 222, .8)
-# color = $color12
-# font_size = 240
-# font_family = JetBrainsMono Nerd Font ExtraBold
-# position = 0, -450
-# halign = center
-# valign = top
-# }
-
-# Seconds-Time (disabled; kept for reference)
-# label {
-# monitor =
-# text = cmd[update:1000] echo "$(date +"%S")"
-# # text = cmd[update:1000] echo "$(date +"%S %p")" #AM/PM
-# color = $color11
-# font_size = 50
-# font_family = JetBrainsMono Nerd Font ExtraBold
-# position = 0, -450
-# halign = center
-# valign = top
-# }
-
-# Put a picture of choice here. Default is the current wallpaper
-# image {
-# monitor =
-# #path = $HOME/.config/hypr/wallpaper_effects/.wallpaper_current
-# size = 160
-# rounding = -1
-# border_size = 0
-# border_color = $color11
-# rotate = 0
-# reload_time = -1
-# position = 0, 400
-# halign = center
-# valign = bottom
-# }
-
-# USER
-label {
- monitor =
- text =  $USER
- color = $color9
- font_size = 48
- font_family = Victor Mono Bold Oblique
- position = 0, 300
- halign = center
- valign = bottom
-}
-
-# INPUT FIELD
-input-field {
- monitor =
- size = 306, 93
- outline_thickness = 2
- dots_size = 0.2 # Scale of input-field height, 0.2 - 0.8
- dots_spacing = 0.2 # Scale of dots' absolute size, 0.0 - 1.0
- dots_center = true
- outer_color = $color8
- inner_color = rgba(255, 255, 255, 0.1)
- capslock_color = rgb(255,255,255)
- font_color = $color13
- fade_on_empty = false
- font_family = Victor Mono Bold Oblique
- placeholder_text = <i><span foreground="##ffffff99">🔒 Type Password</span></i>
- hide_input = false
- position = 0, 100
- halign = center
- valign = bottom
-}
-
-# Keyboard LAYOUT
-label {
- monitor =
- text = $LAYOUT
- color = $color8
- font_size = 19
- font_family = Victor Mono Bold Oblique
- position = 0, 53
- halign = center
- valign = bottom
-}
-
-# uptime
-label {
- monitor =
- text = cmd[update:60000] echo "<b> "$(uptime -p || $Scripts/UptimeNixOS.sh)" </b>"
- color = $color8
- font_size = 32
- font_family = Victor Mono Bold Oblique
- position = 0, 0
- halign = right
- valign = bottom
-}
-
-# battery information
-label {
- monitor =
- text = cmd[update:1000] echo "<b> "$($Scripts/Battery.sh)" </b>"
- color = $color8
- font_size = 21
- font_family = Victor Mono Bold Oblique
- position = 0, 40
- halign = right
- valign = bottom
-}
-
-# weather edit the scripts for locations
-# weather scripts are located in ~/.config/hypr/UserScripts Weather.sh and/or Weather.py
-# see https://github.com/LinuxBeginnings/Hyprland-Dots/wiki/TIPS#%EF%B8%8F-weather-app-related-for-waybar-and-hyprlock
-label {
- monitor =
- text = cmd[update:3600000] [ -f "$HOME/.cache/.weather_cache" ] && cat "$HOME/.cache/.weather_cache"
- color = $color8
- font_size = 19
- font_family = Victor Mono Bold Oblique
- position = 50, 0
- halign = left
- valign = bottom
-}
diff --git a/config/hypr/initial-boot.sh b/config/hypr/initial-boot.sh
index 8ccda640..b45c31aa 100755
--- a/config/hypr/initial-boot.sh
+++ b/config/hypr/initial-boot.sh
@@ -16,6 +16,32 @@ color_scheme="prefer-dark"
gtk_theme="Flat-Remix-GTK-Blue-Dark"
icon_theme="Flat-Remix-Blue-Dark"
cursor_theme="Bibata-Modern-Ice"
+wallust_args=()
+# shellcheck source=/dev/null
+if [ -f "$scriptsDir/WallustConfig.sh" ]; then
+ . "$scriptsDir/WallustConfig.sh"
+fi
+
+set_interface_pref_with_retry() {
+ local key="$1"
+ local value="$2"
+ local expected="$3"
+ local current=""
+ local attempt=0
+ local max_attempts=6
+
+ while [ "$attempt" -lt "$max_attempts" ]; do
+ gsettings set org.gnome.desktop.interface "$key" "$value" > /dev/null 2>&1 || true
+ current="$(gsettings get org.gnome.desktop.interface "$key" 2>/dev/null || true)"
+ if [ "$current" = "$expected" ]; then
+ return 0
+ fi
+ attempt=$((attempt + 1))
+ sleep 0.25
+ done
+
+ return 1
+}
if command -v awww >/dev/null 2>&1; then
WWW="awww"
@@ -29,28 +55,27 @@ effect="--transition-bezier .43,1.19,1,.4 --transition-fps 30 --transition-type
# Check if a marker file exists.
if [ ! -f "$HOME/.config/hypr/.initial_startup_done" ]; then
- sleep 1
+ # Apply appearance preferences early and synchronously to avoid startup races
+ # where Flatpak/libadwaita apps can default to light mode.
+ set_interface_pref_with_retry color-scheme "'$color_scheme'" "'$color_scheme'" || true
+ set_interface_pref_with_retry gtk-theme "'$gtk_theme'" "'$gtk_theme'" || true
+ set_interface_pref_with_retry icon-theme "'$icon_theme'" "'$icon_theme'" || true
+ set_interface_pref_with_retry cursor-theme "'$cursor_theme'" "'$cursor_theme'" || true
+ gsettings set org.gnome.desktop.interface cursor-size 24 > /dev/null 2>&1 || true
# Initialize wallust and wallpaper
if [ -f "$wallpaper" ]; then
- wallust run -s $wallpaper > /dev/null
+ wallust "${wallust_args[@]}" run -s "$wallpaper" > /dev/null
$WWW query || $DAEMON && $swww $wallpaper $effect
"$scriptsDir/WallustSwww.sh" > /dev/null 2>&1 &
fi
-
- # initiate GTK dark mode and apply icon and cursor theme
- gsettings set org.gnome.desktop.interface color-scheme $color_scheme > /dev/null 2>&1 &
- gsettings set org.gnome.desktop.interface gtk-theme $gtk_theme > /dev/null 2>&1 &
- gsettings set org.gnome.desktop.interface icon-theme $icon_theme > /dev/null 2>&1 &
- gsettings set org.gnome.desktop.interface cursor-theme $cursor_theme > /dev/null 2>&1 &
- gsettings set org.gnome.desktop.interface cursor-size 24 > /dev/null 2>&1 &
# NIXOS initiate GTK dark mode and apply icon and cursor theme
- if [ -n "$(grep -i nixos < /etc/os-release)" ]; then
- gsettings set org.gnome.desktop.interface color-scheme "'$color_scheme'" > /dev/null 2>&1 &
- dconf write /org/gnome/desktop/interface/gtk-theme "'$gtk_theme'" > /dev/null 2>&1 &
- dconf write /org/gnome/desktop/interface/icon-theme "'$icon_theme'" > /dev/null 2>&1 &
- dconf write /org/gnome/desktop/interface/cursor-theme "'$cursor_theme'" > /dev/null 2>&1 &
- dconf write /org/gnome/desktop/interface/cursor-size "24" > /dev/null 2>&1 &
+ if grep -qi nixos /etc/os-release; then
+ dconf write /org/gnome/desktop/interface/color-scheme "'$color_scheme'" > /dev/null 2>&1 || true
+ dconf write /org/gnome/desktop/interface/gtk-theme "'$gtk_theme'" > /dev/null 2>&1 || true
+ dconf write /org/gnome/desktop/interface/icon-theme "'$icon_theme'" > /dev/null 2>&1 || true
+ dconf write /org/gnome/desktop/interface/cursor-theme "'$cursor_theme'" > /dev/null 2>&1 || true
+ dconf write /org/gnome/desktop/interface/cursor-size "24" > /dev/null 2>&1 || true
fi
# initiate kvantum theme
diff --git a/config/hypr/lua/animations.lua b/config/hypr/lua/animations.lua
new file mode 100644
index 00000000..9ba7d709
--- /dev/null
+++ b/config/hypr/lua/animations.lua
@@ -0,0 +1,33 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- Converted from config/hypr/UserConfigs/UserAnimations.conf.
+
+hl.config({
+ animations = {
+ enabled = true,
+ },
+})
+
+hl.curve("wind", { type = "bezier", points = { { 0.05, 0.9 }, { 0.1, 1.05 } } })
+hl.curve("winIn", { type = "bezier", points = { { 0.1, 1.1 }, { 0.1, 1.1 } } })
+hl.curve("winOut", { type = "bezier", points = { { 0.3, -0.3 }, { 0, 1 } } })
+hl.curve("liner", { type = "bezier", points = { { 1, 1 }, { 1, 1 } } })
+hl.curve("overshot", { type = "bezier", points = { { 0.05, 0.9 }, { 0.1, 1.05 } } })
+hl.curve("smoothOut", { type = "bezier", points = { { 0.5, 0 }, { 0.99, 0.99 } } })
+hl.curve("smoothIn", { type = "bezier", points = { { 0.5, -0.5 }, { 0.68, 1.5 } } })
+
+hl.animation({ leaf = "windows", enabled = true, speed = 6, bezier = "wind", style = "slide" })
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 5, bezier = "winIn", style = "slide" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 3, bezier = "smoothOut", style = "slide" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 5, bezier = "wind", style = "slide" })
+hl.animation({ leaf = "border", enabled = true, speed = 1, bezier = "liner" })
+hl.animation({ leaf = "borderangle", enabled = true, speed = 100, bezier = "liner", style = "loop" })
+hl.animation({ leaf = "fade", enabled = true, speed = 3, bezier = "smoothOut" })
+hl.animation({ leaf = "workspaces", enabled = true, speed = 5, bezier = "overshot" })
+hl.animation({ leaf = "workspacesIn", enabled = true, speed = 5, bezier = "winIn", style = "slide" })
+hl.animation({ leaf = "workspacesOut", enabled = true, speed = 5, bezier = "winOut", style = "slide" })
diff --git a/config/hypr/lua/decorations.lua b/config/hypr/lua/decorations.lua
new file mode 100644
index 00000000..1fe25fd7
--- /dev/null
+++ b/config/hypr/lua/decorations.lua
@@ -0,0 +1,64 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- Converted from config/hypr/UserConfigs/UserDecorations.conf.
+-- NOTE: wallust-hyprland.conf is hyprlang-sourced in the original config.
+-- Lua parity for importing that file is still evolving; using static color fallbacks here.
+
+hl.config({
+ general = {
+ border_size = 2,
+ gaps_in = 2,
+ gaps_out = 4,
+ col = {
+ active_border = "rgba(8db4ffff)",
+ inactive_border = "rgba(5f6578ff)",
+ },
+ },
+})
+
+hl.config({
+ decoration = {
+ rounding = 10,
+ active_opacity = 1.0,
+ inactive_opacity = 0.9,
+ fullscreen_opacity = 1.0,
+ dim_inactive = true,
+ dim_strength = 0.1,
+ dim_special = 0.8,
+ shadow = {
+ enabled = true,
+ range = 3,
+ render_power = 1,
+ color = "rgba(8db4ffff)",
+ color_inactive = "rgba(5f6578ff)",
+ },
+ blur = {
+ enabled = true,
+ size = 6,
+ passes = 3,
+ new_optimizations = true,
+ xray = true,
+ ignore_opacity = true,
+ special = true,
+ popups = true,
+ },
+ },
+})
+
+hl.config({
+ group = {
+ col = {
+ border_active = "rgba(ffffffff)",
+ },
+ groupbar = {
+ col = {
+ active = "rgba(0f111aff)",
+ },
+ },
+ },
+})
diff --git a/config/hypr/lua/env.lua b/config/hypr/lua/env.lua
new file mode 100644
index 00000000..f4e6c9e6
--- /dev/null
+++ b/config/hypr/lua/env.lua
@@ -0,0 +1,37 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- Converted from:
+-- - config/hypr/configs/ENVariables.conf
+-- - config/hypr/UserConfigs/ENVariables.conf (active values only)
+
+hl.env("DOTS_VERSION", "2.3.23")
+hl.env("GDK_BACKEND", "wayland,x11,*")
+hl.env("QT_QPA_PLATFORM", "wayland;xcb")
+hl.env("CLUTTER_BACKEND", "wayland")
+hl.env("XDG_CURRENT_DESKTOP", "Hyprland")
+hl.env("XDG_SESSION_DESKTOP", "Hyprland")
+hl.env("XDG_SESSION_TYPE", "wayland")
+hl.env("QT_AUTO_SCREEN_SCALE_FACTOR", "1")
+hl.env("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1")
+hl.env("QT_QPA_PLATFORMTHEME", "qt6ct")
+hl.env("QT_STYLE_OVERRIDE", "kvantum")
+hl.env("QT_QUICK_CONTROLS_STYLE", "org.hyprland.style")
+hl.env("GDK_SCALE", "1")
+hl.env("QT_SCALE_FACTOR", "1")
+hl.env("MOZ_ENABLE_WAYLAND", "1")
+hl.env("ELECTRON_OZONE_PLATFORM_HINT", "auto")
+
+-- Fix for missing mime-info database error
+local current_data_dirs = os.getenv("XDG_DATA_DIRS") or ""
+if not current_data_dirs:find("/usr/share") then
+ local new_data_dirs = "/usr/local/share:/usr/share"
+ if current_data_dirs ~= "" then
+ new_data_dirs = new_data_dirs .. ":" .. current_data_dirs
+ end
+ hl.env("XDG_DATA_DIRS", new_data_dirs)
+end
diff --git a/config/hypr/lua/keybind_helpers.lua b/config/hypr/lua/keybind_helpers.lua
new file mode 100644
index 00000000..92dc952b
--- /dev/null
+++ b/config/hypr/lua/keybind_helpers.lua
@@ -0,0 +1,355 @@
+local M = {}
+
+local function trim(value)
+ return (value or ""):gsub("^%s+", ""):gsub("%s+$", "")
+end
+local dsp = hl.dsp or hl
+local window_api = (dsp and dsp.window) or hl.window or {}
+local workspace_api = (dsp and dsp.workspace) or {}
+local group_api = (dsp and dsp.group) or {}
+
+local function exec_cmd(cmd)
+ if dsp and dsp.exec_cmd then
+ return dsp.exec_cmd(cmd)
+ end
+ return function()
+ hl.exec_cmd(cmd)
+ end
+end
+
+local function shell_quote(value)
+ return "'" .. tostring(value):gsub("'", "'\\''") .. "'"
+end
+
+local function raw_dispatch_cmd(command)
+ if dsp and dsp.exec_raw then
+ return dsp.exec_raw(tostring(command))
+ end
+ local expression = "hl.dsp.exec_raw(" .. string.format("%q", tostring(command)) .. ")"
+ return exec_cmd("hyprctl dispatch " .. shell_quote(expression))
+end
+
+local function workspace_dispatch(value)
+ if dsp and dsp.focus then
+ return function()
+ hl.dispatch(dsp.focus({ workspace = value }))
+ end
+ end
+ return raw_dispatch_cmd("workspace " .. tostring(value))
+end
+
+local known_dispatchers = {
+ bringactivetotop = true,
+ changegroupactive = true,
+ cyclenext = true,
+ fullscreen = true,
+ killactive = true,
+ layoutmsg = true,
+ movefocus = true,
+ moveintogroup = true,
+ moveoutofgroup = true,
+ movecurrentworkspacetomonitor = true,
+ movetoworkspace = true,
+ movetoworkspacesilent = true,
+ movewindow = true,
+ pseudo = true,
+ resizeactive = true,
+ setprop = true,
+ swapwindow = true,
+ togglegroup = true,
+ togglefloating = true,
+ togglespecialworkspace = true,
+ workspace = true,
+}
+
+local function direction(value)
+ local directions = {
+ l = "left",
+ r = "right",
+ u = "up",
+ d = "down",
+ left = "left",
+ right = "right",
+ up = "up",
+ down = "down",
+ }
+ return directions[trim(value)] or trim(value)
+end
+
+local function workspace_value(value)
+ value = trim(value)
+ return tonumber(value) or value
+end
+
+local function dispatch_factory_safely(factory)
+ pcall(function()
+ local dispatcher = factory()
+ if dispatcher then
+ hl.dispatch(dispatcher)
+ end
+ end)
+end
+
+local function dispatch(name, args)
+ name = trim(name)
+ args = trim(args)
+
+ if args:match("^exec%s*,") then
+ return exec_cmd(trim(args:gsub("^exec%s*,", "", 1)))
+ end
+
+ if name == "exec" then
+ return exec_cmd(args)
+ end
+
+ if known_dispatchers[args] and not known_dispatchers[name] then
+ if args == "movewindow" and window_api.drag then
+ return window_api.drag()
+ end
+ if args == "resizewindow" and window_api.resize then
+ return window_api.resize()
+ end
+ return raw_dispatch_cmd(args)
+ end
+
+ if name == "killactive" and window_api.close then
+ return window_api.close()
+ end
+ if name == "togglefloating" and window_api.float then
+ return window_api.float({ action = "toggle" })
+ end
+ if name == "fullscreen" and window_api.fullscreen then
+ if args == "1" then
+ return window_api.fullscreen({ mode = "maximized" })
+ end
+ return window_api.fullscreen({ mode = "fullscreen" })
+ end
+ if name == "pseudo" and window_api.pseudo then
+ return window_api.pseudo()
+ end
+ if name == "workspace" then
+ return workspace_dispatch(workspace_value(args))
+ end
+ if name == "movetoworkspace" then
+ if window_api.move then
+ return function()
+ hl.dispatch(window_api.move({ workspace = workspace_value(args) }))
+ end
+ end
+ return raw_dispatch_cmd("movetoworkspace " .. args)
+ end
+ if name == "movetoworkspacesilent" then
+ if window_api.move then
+ return function()
+ hl.dispatch(window_api.move({ workspace = workspace_value(args), follow = false }))
+ end
+ end
+ return raw_dispatch_cmd("movetoworkspacesilent " .. args)
+ end
+ if name == "resizeactive" then
+ return raw_dispatch_cmd("resizeactive " .. args)
+ end
+ if name == "movecurrentworkspacetomonitor" then
+ return raw_dispatch_cmd("movecurrentworkspacetomonitor " .. args)
+ end
+ if name == "movefocus" then
+ if dsp and dsp.focus then
+ return function()
+ dispatch_factory_safely(function()
+ return dsp.focus({ direction = direction(args) })
+ end)
+ end
+ end
+ return raw_dispatch_cmd("movefocus " .. args)
+ end
+ if name == "movewindow" then
+ if window_api.move then
+ return function()
+ dispatch_factory_safely(function()
+ return window_api.move({ direction = direction(args) })
+ end)
+ end
+ end
+ return raw_dispatch_cmd("movewindow " .. args)
+ end
+ if name == "swapwindow" then
+ local swap_direction = trim(args)
+ if swap_direction == "" then
+ return nil
+ end
+ return exec_cmd("$HOME/.config/hypr/scripts/LuaSwapWindow.sh " .. swap_direction)
+ end
+ if name == "togglegroup" and group_api.toggle then
+ return group_api.toggle()
+ end
+ if name == "changegroupactive" and group_api.next and group_api.prev then
+ if args == "b" or args == "prev" or args == "-1" then
+ return group_api.prev()
+ end
+ return group_api.next()
+ end
+ if name == "moveintogroup" and window_api.move then
+ return window_api.move({ into_group = direction(args) })
+ end
+ if name == "moveoutofgroup" and window_api.move then
+ return window_api.move({ out_of_group = true })
+ end
+ if name == "layoutmsg" and dsp and dsp.layout then
+ return dsp.layout(args)
+ end
+ if name == "bringactivetotop" and window_api.bring_to_top then
+ return window_api.bring_to_top()
+ end
+ if name == "setprop" and window_api.set_prop then
+ local prop, value = args:match("^(%S+)%s+(.+)$")
+ if prop and value then
+ return window_api.set_prop({ prop = prop, value = value })
+ end
+ end
+
+ if args ~= "" then
+ return raw_dispatch_cmd(name .. " " .. args)
+ end
+ return raw_dispatch_cmd(name)
+end
+
+local function chord(mods, key)
+ mods = trim(mods):gsub("%s+", " + ")
+ key = trim(key)
+ key = key:gsub("^xf86", "XF86")
+ local key_aliases = {
+ XF86AudioPlayPause = "XF86AudioPlay",
+ XF86audiolowervolume = "XF86AudioLowerVolume",
+ XF86audiomute = "XF86AudioMute",
+ XF86audioraisevolume = "XF86AudioRaiseVolume",
+ XF86audiostop = "XF86AudioStop",
+ }
+ key = key_aliases[key] or key
+ local shifted_number_keys = {
+ ["code:10"] = "exclam",
+ ["code:11"] = "at",
+ ["code:12"] = "numbersign",
+ ["code:13"] = "dollar",
+ ["code:14"] = "percent",
+ ["code:15"] = "asciicircum",
+ ["code:16"] = "ampersand",
+ ["code:17"] = "asterisk",
+ ["code:18"] = "parenleft",
+ ["code:19"] = "parenright",
+ }
+ local number_keys = {
+ ["code:10"] = "1",
+ ["code:11"] = "2",
+ ["code:12"] = "3",
+ ["code:13"] = "4",
+ ["code:14"] = "5",
+ ["code:15"] = "6",
+ ["code:16"] = "7",
+ ["code:17"] = "8",
+ ["code:18"] = "9",
+ ["code:19"] = "0",
+ }
+ if mods:match("SHIFT") and shifted_number_keys[key] then
+ key = shifted_number_keys[key]
+ else
+ key = number_keys[key] or key
+ end
+ if mods == "" then
+ return key
+ end
+ return mods .. " + " .. key
+end
+
+local function bind(mods, key, fn, opts)
+ if opts then
+ hl.bind(chord(mods, key), fn, opts)
+ else
+ hl.bind(chord(mods, key), fn)
+ end
+ if mods:match("SHIFT") then
+ local number_key = ({
+ ["code:10"] = "1",
+ ["code:11"] = "2",
+ ["code:12"] = "3",
+ ["code:13"] = "4",
+ ["code:14"] = "5",
+ ["code:15"] = "6",
+ ["code:16"] = "7",
+ ["code:17"] = "8",
+ ["code:18"] = "9",
+ ["code:19"] = "0",
+ })[key]
+ if number_key then
+ if opts then
+ hl.bind(chord(mods, number_key), fn, opts)
+ else
+ hl.bind(chord(mods, number_key), fn)
+ end
+ end
+ end
+end
+
+local function unbind_chord(key_chord)
+ if hl.unbind then
+ pcall(hl.unbind, key_chord)
+ end
+end
+
+local function bindm(mods, key, dispatcher, description)
+ local action = nil
+ if dispatcher == "movewindow" and window_api.drag then
+ action = window_api.drag()
+ elseif dispatcher == "resizewindow" then
+ if window_api.resize then
+ action = window_api.resize()
+ else
+ action = raw_dispatch_cmd("resizewindow")
+ end
+ else
+ action = raw_dispatch_cmd(dispatcher)
+ end
+ bind(mods, key, action, { description = description, mouse = true })
+end
+
+local keys_to_unbind = {
+ "SUPER + V",
+ "SUPER + W",
+ "SUPER + P",
+ "SUPER + N",
+ "SUPER + T",
+ "SUPER + X",
+ "SUPER + CTRL + S",
+ "SUPER + G",
+ "SUPER + ALT + S",
+ "SUPER + F",
+ "SUPER + ALT + F",
+ "SUPER + CTRL + F",
+ "SUPER + CTRL + A",
+ "SUPER + CTRL + B",
+ "SUPER + CTRL + W",
+ "SUPER + CTRL + T",
+ "ALT + TAB",
+ "SUPER + mouse_down",
+ "SUPER + mouse_up",
+ "SUPER + SLASH",
+ "SUPER + code:61",
+ "SUPER + ALT + code:61",
+}
+
+local function unbind_default_keys()
+ for _, key in ipairs(keys_to_unbind) do
+ unbind_chord(key)
+ end
+end
+
+M.window_api = window_api
+M.workspace_api = workspace_api
+M.group_api = group_api
+M.exec_cmd = exec_cmd
+M.raw_dispatch_cmd = raw_dispatch_cmd
+M.dispatch = dispatch
+M.bind = bind
+M.bindm = bindm
+M.unbind_default_keys = unbind_default_keys
+
+return M
diff --git a/config/hypr/lua/keybinds.lua b/config/hypr/lua/keybinds.lua
new file mode 100644
index 00000000..6bf71e47
--- /dev/null
+++ b/config/hypr/lua/keybinds.lua
@@ -0,0 +1,648 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- Auto-generated from Keybinds.conf/UserKeybinds.conf for Lua testing
+-- Helper internals live in keybind_helpers.lua so this file stays focused on bindings you may edit.
+-- To add a binding, copy an existing bind(...) line and change:
+-- 1) modifiers (e.g. "SUPER SHIFT")
+-- 2) key (e.g. "Return", "code:10", "mouse_down")
+-- 3) action (exec_cmd(...) or dispatch(...))
+-- 4) description text
+local keybind_helpers = nil
+do
+ local source = (debug.getinfo(1, "S") or {}).source or ""
+ local source_path = source:match("^@(.+)$")
+ local source_dir = source_path and source_path:match("^(.*)/[^/]+$") or nil
+ local home = os.getenv("HOME") or ""
+ local candidate_paths = {
+ source_dir and (source_dir .. "/keybind_helpers.lua") or nil,
+ home ~= "" and (home .. "/.config/hypr/lua/keybind_helpers.lua") or nil,
+ home ~= "" and (home .. "/.config/hypr/keybind_helpers.lua") or nil,
+ }
+
+ local tried_paths = {}
+ for _, helper_path in ipairs(candidate_paths) do
+ if helper_path then
+ table.insert(tried_paths, helper_path)
+ local f = io.open(helper_path, "r")
+ if f then
+ f:close()
+ local loaded_ok, loaded_helpers = pcall(dofile, helper_path)
+ if loaded_ok and type(loaded_helpers) == "table" and loaded_helpers.unbind_default_keys then
+ keybind_helpers = loaded_helpers
+ break
+ end
+ end
+ end
+ end
+
+ if not keybind_helpers then
+ error("Failed to load keybind_helpers.lua from: " .. table.concat(tried_paths, ", "))
+ end
+end
+local window_api = keybind_helpers.window_api
+local exec_cmd = keybind_helpers.exec_cmd
+local raw_dispatch_cmd = keybind_helpers.raw_dispatch_cmd
+local dispatch = keybind_helpers.dispatch
+local bind = keybind_helpers.bind
+local bindm = keybind_helpers.bindm
+
+-- Mass unbind defaults before rebuilding the Lua keymap.
+keybind_helpers.unbind_default_keys()
+
+-- ==================================================
+-- User-editable bindings
+-- ==================================================
+-- Section: Application launchers and utility scripts
+local app_binds = {
+ { "SUPER", "D", "pkill rofi || true && rofi -show drun -modi drun,filebrowser,run,window", "app launcher" },
+ { "SUPER", "B", 'xdg-open "https://"', "open default browser" },
+ { "SUPER", "A", "$HOME/.config/hypr/scripts/OverviewToggle.sh", "desktop overview" },
+ { "SUPER", "Return", "kitty", "Open terminal" },
+ { "SUPER", "E", "thunar", "file manager" },
+ { "SUPER", "C", "$HOME/.config/hypr/scripts/rofi-ssh-menu.sh", "SSH session manager" },
+ { "SUPER", "T", "$HOME/.config/hypr/scripts/ThemeChanger.sh", "Global theme switcher using Wallust" },
+ { "SUPER", "H", "$HOME/.config/hypr/scripts/KeyHints.sh", "help / cheat sheet" },
+ { "SUPER ALT", "R", "$HOME/.config/hypr/scripts/Refresh.sh", "refresh bar and menus" },
+ { "SUPER ALT", "E", "$HOME/.config/hypr/scripts/RofiEmoji.sh", "emoji menu" },
+ { "SUPER", "S", "$HOME/.config/hypr/scripts/RofiSearch.sh", "web search" },
+ { "SUPER CTRL", "S", "rofi -show window", "window switcher" },
+ { "SUPER ALT", "O", "$HOME/.config/hypr/scripts/ChangeBlur.sh", "toggle blur" },
+ { "SUPER SHIFT", "G", "$HOME/.config/hypr/scripts/GameMode.sh", "toggle game mode" },
+ { "SUPER ALT", "L", "$HOME/.config/hypr/scripts/ChangeLayout.sh toggle", "toggle layouts" },
+ { "SUPER ALT", "V", "$HOME/.config/hypr/scripts/ClipManager.sh", "clipboard manager" },
+ { "SUPER CTRL", "R", "$HOME/.config/hypr/scripts/RofiThemeSelector.sh", "rofi theme selector" },
+ {
+ "SUPER CTRL SHIFT",
+ "R",
+ "pkill rofi || true && $HOME/.config/hypr/scripts/RofiThemeSelector-modified.sh",
+ "rofi theme selector (modified)",
+ },
+ { "SUPER CTRL", "K", "$HOME/.config/hypr/scripts/Kitty_themes.sh", "Kitty theme selector" },
+ { "SUPER CTRL", "G", "$HOME/.config/hypr/scripts/Ghostty_themes.sh", "Ghostty theme selector" },
+ {
+ "SUPER SHIFT",
+ "B",
+ "$HOME/.config/hypr/UserScripts/RainbowBorders-low-cpu.sh --run-once",
+ "Set static Rainbow Border",
+ },
+ {
+ "SUPER SHIFT",
+ "H",
+ "$HOME/.config/hypr/scripts/Toggle-Active-Window-Audio.sh",
+ "Toggle Mute/Unmute for Active-Window",
+ },
+ {
+ "ALT SHIFT",
+ "S",
+ "$HOME/.config/hypr/scripts/hyprshot.sh -m region -o $HOME/Pictures/Screenshots",
+ "Hyprshot Screen Capture",
+ },
+ { "SUPER ALT", "SPACE", "$HOME/.config/hypr/scripts/Float-all-Windows.sh", "Float all windows" },
+ -- NOTE: Dropterminal is currently certified only with kitty. Not all terminals behave correctly as a dropdown.
+ { "SUPER SHIFT", "Return", "$HOME/.config/hypr/scripts/Dropterminal.sh kitty", "DropDown terminal" },
+ {
+ "SUPER ALT",
+ "mouse_down",
+ "hyprctl keyword cursor:zoom_factor \"$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {factor = $2; if (factor < 1) {factor = 1}; print factor * 2.0}')\"",
+ "zoom in",
+ },
+ {
+ "SUPER ALT",
+ "mouse_up",
+ "hyprctl keyword cursor:zoom_factor \"$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {factor = $2; if (factor < 1) {factor = 1}; print factor / 2.0}')\"",
+ "zoom out",
+ },
+ { "SUPER CTRL ALT", "B", "pkill -SIGUSR1 waybar", "toggle waybar on/off" },
+ { "SUPER CTRL", "B", "$HOME/.config/hypr/scripts/WaybarStyles.sh", "waybar styles menu" },
+ { "SUPER ALT", "B", "$HOME/.config/hypr/scripts/WaybarLayout.sh", "waybar layout menu" },
+ { "SUPER", "N", "$HOME/.config/hypr/scripts/Hyprsunset.sh toggle", "Toggle Hyprsunset - night light" },
+ { "SUPER SHIFT", "M", "$HOME/.config/hypr/UserScripts/RofiBeats.sh", "online music" },
+ { "SUPER", "W", "$HOME/.config/hypr/UserScripts/WallpaperSelect.sh", "select wallpaper" },
+ { "SUPER SHIFT", "W", "$HOME/.config/hypr/UserScripts/WallpaperEffects.sh", "wallpaper effects" },
+ { "CTRL ALT", "W", "$HOME/.config/hypr/UserScripts/WallpaperRandom.sh", "random wallpaper" },
+ { "SUPER SHIFT", "K", "$HOME/.config/hypr/scripts/KeyBinds.sh", "search keybinds" },
+ { "SUPER SHIFT", "A", "$HOME/.config/hypr/scripts/Animations.sh", "animations menu" },
+ { "SUPER SHIFT", "O", "$HOME/.config/hypr/UserScripts/ZshChangeTheme.sh", "change oh-my-zsh theme" },
+ { "SUPER ALT", "C", "$HOME/.config/hypr/UserScripts/RofiCalc.sh", "calculator" },
+}
+for _, app in ipairs(app_binds) do
+ bind(app[1], app[2], exec_cmd(app[3]), { description = app[4] })
+end
+--
+--
+-- These are examples of how to bind to a TUI/CLI apps
+-- The specific keybinds are just examples
+-- Do not user as-is as it will break exisitng keybinds
+--
+--
+-- TUI Apps Configuration (commented options from LUA-files/hyprland-key-bindings-example.lua).
+-- local terminal = "uwsm-app -- " .. (os.getenv("TERMINAL") or "")
+-- local browser = "omarchy-launch-browser"
+-- local tui_apps = {
+-- { "CTRL + ALT + O", "opencode", "a opencode", "OpenCode" },
+-- { "CTRL + ALT + SHIFT + A", "cline", "-e cline", "OpenCode" },
+-- { "CTRL + ALT + B", "btop", "-e btop", "Task Manager" },
+-- { "CTRL + ALT + SHIFT + B", "bluetui", "-e bluetui", "BlueTUI" },
+-- { "CTRL + ALT + E", "spf", "-e spf", "SuperFile Manager" },
+-- { "CTRL + ALT + L", "lazygit", "-e lazygit", "LazyGit" },
+-- { "CTRL + ALT + N", "nvtop", "-e nvtop", "Nvtop" },
+-- { "CTRL + ALT + SHIFT + N", "ncdu", "-e ncdu", "Ncdu" },
+-- { "CTRL + ALT + W", "impala", "-e impala", "Impala Wi-Fi" },
+-- { "CTRL + ALT + P", "pacseek", "-e pacseek", "PacSeek" },
+-- { "CTRL + ALT + SHIFT + P", "pacsea", "-e pacsea", "PacSea" },
+-- { "CTRL + ALT + R", "fzf-uninstall", "-e ~/.config/hypr/fzfpurge", "Fzf Uninstaller" },
+-- { "CTRL + ALT + V", "wiremix", "-e wiremix", "WireMix Volume" },
+-- { "CTRL + ALT + SHIFT + H", "htop", "-e htop", "Htop" },
+-- }
+-- for _, app in ipairs(tui_apps) do
+-- hl.bind(app[1], hl.dsp.exec_cmd(terminal .. " --title=" .. app[2] .. " " .. app[3]), { description = app[4] })
+-- end
+
+--
+--
+-- These are examples of how to bind webpages
+-- The specific keybinds are just examples
+-- Do not user as-is as it will break exisitng keybinds
+--
+--
+-- Web Apps Configuration (commented options from LUA-files/hyprland-key-bindings-example.lua).
+-- local web_apps = {
+-- { "SUPER + A", "https://gemini.google.com", "Gemini AI" },
+-- { "SUPER + Y", "https://youtube.com", "YouTube" },
+-- { "SUPER + T", "https://tiktok.com", "TikTok" },
+-- { "SUPER + X", "https://x.com", "X.com" },
+-- { "SUPER + U", "http://10.24.1.1", "Unifi" },
+-- { "SUPER + I", "https://instagram.com", "Instagram" },
+-- { "SUPER + P", "https://mail.proton.me", "Proton Mail" },
+-- }
+-- for _, web in ipairs(web_apps) do
+-- hl.bind(web[1], hl.dsp.exec_cmd([[omarchy-launch-webapp "]] .. web[2] .. [["]]), { description = web[3] })
+-- end
+
+-- Manual example actions not currently active in this config.
+-- hl.bind("SUPER + F", hl.dsp.window.fullscreen({ mode = "fullscreen" }), { description = "Fullscreen Window" })
+-- hl.bind("ALT + SPACE", hl.dsp.window.float({ action = "toggle" }), { description = "Toggle floating" })
+-- hl.bind("CTRL + ALT + return", hl.dsp.exec_cmd("uwsm-app -- kitty"), { description = "Kitty terminal" })
+-- hl.bind(
+-- "CTRL + ALT + SHIFT + return",
+-- hl.dsp.exec_cmd([[uwsm-app -- xdg-terminal-exec --dir="$(omarchy-cmd-terminal-cwd)" tmux new]]),
+-- { description = "Tmux" }
+-- )
+
+-- Section: Window/session controls
+bind("SUPER SHIFT", "F", dispatch("fullscreen", ""), { description = "fullscreen" })
+bind("SUPER CTRL", "F", dispatch("fullscreen", "1"), { description = "maximize window" })
+bind("SUPER", "SPACE", dispatch("togglefloating", ""), { description = "Float current window" })
+bind("SUPER CTRL", "O", dispatch("setprop", "active opaque toggle"), { description = "toggle active window opacity" })
+bind(
+ "ALT_L",
+ "SHIFT_L",
+ dispatch("switch keyboard layout globally", "exec, $HOME/.config/hypr/scripts/KeyboardLayout.sh switch"),
+ { locked = true, description = "switch keyboard layout globally" }
+)
+bind(
+ "SHIFT_L",
+ "ALT_L",
+ dispatch("switch keyboard layout per-window", "exec, $HOME/.config/hypr/scripts/Tak0-Per-Window-Switch.sh"),
+ { locked = true, description = "switch keyboard layout per-window" }
+)
+bind(
+ "SUPER CTRL",
+ "F9",
+ dispatch("movecurrentworkspacetomonitor", "l"),
+ { description = "move workspace to left monitor" }
+)
+bind(
+ "SUPER CTRL",
+ "F10",
+ dispatch("movecurrentworkspacetomonitor", "r"),
+ { description = "move workspace to right monitor" }
+)
+bind(
+ "SUPER CTRL",
+ "F11",
+ dispatch("movecurrentworkspacetomonitor", "u"),
+ { description = "move workspace to up monitor" }
+)
+bind(
+ "SUPER CTRL",
+ "F12",
+ dispatch("movecurrentworkspacetomonitor", "d"),
+ { description = "move workspace to down monitor" }
+)
+bind("CTRL ALT", "Delete", exec_cmd("$HOME/.config/hypr/scripts/Logout.sh"), { description = "exit Hyprland" })
+bind("SUPER", "Q", dispatch("killactive", ""), { description = "close active window" })
+bind(
+ "SUPER SHIFT",
+ "Q",
+ exec_cmd("$HOME/.config/hypr/scripts/KillActiveProcess.sh"),
+ { description = "Terminate active process" }
+)
+bind("CTRL ALT", "L", exec_cmd("$HOME/.config/hypr/scripts/LockScreen.sh"), { description = "lock screen" })
+bind("CTRL ALT", "P", exec_cmd("$HOME/.config/hypr/scripts/Wlogout.sh"), { description = "powermenu" })
+bind("SUPER SHIFT", "N", exec_cmd("swaync-client -t -sw"), { description = "notification panel" })
+bind(
+ "SUPER SHIFT",
+ "E",
+ exec_cmd("$HOME/.config/hypr/scripts/Kool_Quick_Settings.sh"),
+ { description = "Quick settings menu" }
+)
+
+-- Section: Layout and tiling controls
+bind("SUPER CTRL", "D", dispatch("layoutmsg", "removemaster"), { description = "remove master" })
+bind("SUPER", "I", dispatch("layoutmsg", "addmaster"), { description = "add master" })
+bind("SUPER", "j", exec_cmd("$HOME/.config/hypr/scripts/LuaCycleWindow.sh next"), { description = "cycle next" })
+bind(
+ "SUPER",
+ "k",
+ exec_cmd("$HOME/.config/hypr/scripts/LuaCycleWindow.sh previous"),
+ { description = "cycle previous" }
+)
+bind("SUPER CTRL", "Return", dispatch("layoutmsg", "swapwithmaster"), { description = "swap with master" })
+bind("SUPER SHIFT", "I", dispatch("layoutmsg", "togglesplit"), { description = "toggle split (dwindle)" })
+bind("SUPER", "P", dispatch("pseudo", ""), { description = "toggle pseudo (dwindle)" })
+bind("SUPER", "M", raw_dispatch_cmd("splitratio 0.3"), { description = "set split ratio 0.3" })
+bind(
+ "SUPER ALT",
+ "1",
+ exec_cmd("$HOME/.config/hypr/scripts/ChangeLayout.sh dwindle"),
+ { description = "layout dwindle" }
+)
+bind("SUPER ALT", "2", exec_cmd("$HOME/.config/hypr/scripts/ChangeLayout.sh master"), { description = "layout master" })
+bind(
+ "SUPER ALT",
+ "3",
+ exec_cmd("$HOME/.config/hypr/scripts/ChangeLayout.sh scrolling"),
+ { description = "layout scrolling" }
+)
+bind(
+ "SUPER ALT",
+ "4",
+ exec_cmd("$HOME/.config/hypr/scripts/ChangeLayout.sh monocle"),
+ { description = "layout monocle" }
+)
+bind("SUPER SHIFT", "period", dispatch("layoutmsg", "move +col"), { description = "move to right column" })
+bind("SUPER SHIFT", "comma", dispatch("layoutmsg", "move -col"), { description = "move to left column" })
+bind("SUPER ALT", "comma", dispatch("layoutmsg", "swapcol l"), { description = "swap columns left" })
+bind("SUPER ALT", "period", dispatch("layoutmsg", "swapcol r"), { description = "swap columns right" })
+bind(
+ "SUPER ALT",
+ "H",
+ exec_cmd("hyprctl keyword scrolling:direction right"),
+ { description = "Horizonal scroll right" }
+)
+bind("SUPER ALT", "V", exec_cmd("hyprctl keyword scrolling:direction down"), { description = "Vertical Scroll down" })
+bind(
+ "SUPER ALT",
+ "S",
+ exec_cmd(
+ 'bash -c \'[[ $(hyprctl getoption scrolling:direction -j | jq -r ".str") == "right" ]] && hyprctl keyword scrolling:direction down || hyprctl keyword scrolling:direction right\''
+ ),
+ { description = "toggle scrolling V/H" }
+)
+bind("ALT", "Tab", exec_cmd("$HOME/.config/hypr/scripts/LuaCycleWindow.sh next"), { description = "cycle next window" })
+
+-- Section: Audio, media, and hardware keys
+bind(
+ "",
+ "xf86audioraisevolume",
+ dispatch("volume up", "exec, $HOME/.config/hypr/scripts/Volume.sh --inc"),
+ { description = "volume up" }
+)
+bind(
+ "",
+ "xf86audiolowervolume",
+ dispatch("volume down", "exec, $HOME/.config/hypr/scripts/Volume.sh --dec"),
+ { description = "volume down" }
+)
+bind(
+ "ALT",
+ "xf86audioraisevolume",
+ dispatch("volume up precise", "exec, $HOME/.config/hypr/scripts/Volume.sh --inc-precise"),
+ { description = "volume up precise" }
+)
+bind(
+ "ALT",
+ "xf86audiolowervolume",
+ dispatch("volume down precise", "exec, $HOME/.config/hypr/scripts/Volume.sh --dec-precise"),
+ { description = "volume down precise" }
+)
+bind(
+ "",
+ "xf86AudioMicMute",
+ dispatch("toggle mic mute", "exec, $HOME/.config/hypr/scripts/Volume.sh --toggle-mic"),
+ { locked = true, description = "toggle mic mute" }
+)
+bind(
+ "",
+ "xf86audiomute",
+ dispatch("toggle mute", "exec, $HOME/.config/hypr/scripts/Volume.sh --toggle"),
+ { locked = true, description = "toggle mute" }
+)
+bind("", "xf86Sleep", dispatch("sleep", "exec, systemctl suspend"), { locked = true, description = "sleep" })
+bind(
+ "",
+ "xf86Rfkill",
+ dispatch("airplane mode", "exec, $HOME/.config/hypr/scripts/AirplaneMode.sh"),
+ { locked = true, description = "airplane mode" }
+)
+bind(
+ "",
+ "xf86AudioPlayPause",
+ dispatch("play/pause", "exec, $HOME/.config/hypr/scripts/MediaCtrl.sh --pause"),
+ { locked = true, description = "play/pause" }
+)
+bind(
+ "",
+ "xf86AudioPause",
+ dispatch("pause", "exec, $HOME/.config/hypr/scripts/MediaCtrl.sh --pause"),
+ { locked = true, description = "pause" }
+)
+bind(
+ "",
+ "xf86AudioPlay",
+ dispatch("play", "exec, $HOME/.config/hypr/scripts/MediaCtrl.sh --pause"),
+ { locked = true, description = "play" }
+)
+bind(
+ "",
+ "xf86AudioNext",
+ dispatch("next track", "exec, $HOME/.config/hypr/scripts/MediaCtrl.sh --nxt"),
+ { locked = true, description = "next track" }
+)
+bind(
+ "",
+ "xf86AudioPrev",
+ dispatch("previous track", "exec, $HOME/.config/hypr/scripts/MediaCtrl.sh --prv"),
+ { locked = true, description = "previous track" }
+)
+bind(
+ "",
+ "xf86audiostop",
+ dispatch("stop", "exec, $HOME/.config/hypr/scripts/MediaCtrl.sh --stop"),
+ { locked = true, description = "stop" }
+)
+
+-- Section: Screenshot bindings
+bind("SUPER", "Print", exec_cmd("$HOME/.config/hypr/scripts/ScreenShot.sh --now"), { description = "screenshot now" })
+bind(
+ "SUPER SHIFT",
+ "Print",
+ exec_cmd("$HOME/.config/hypr/scripts/ScreenShot.sh --area"),
+ { description = "screenshot (area)" }
+)
+bind(
+ "SUPER CTRL",
+ "Print",
+ exec_cmd("$HOME/.config/hypr/scripts/ScreenShot.sh --in5"),
+ { description = "screenshot in 5s" }
+)
+bind(
+ "SUPER CTRL SHIFT",
+ "Print",
+ exec_cmd("$HOME/.config/hypr/scripts/ScreenShot.sh --in10"),
+ { description = "screenshot in 10s" }
+)
+bind(
+ "ALT",
+ "Print",
+ exec_cmd("$HOME/.config/hypr/scripts/ScreenShot.sh --active"),
+ { description = "screenshot active window" }
+)
+bind(
+ "SUPER SHIFT",
+ "S",
+ exec_cmd("$HOME/.config/hypr/scripts/ScreenShot.sh --swappy"),
+ { description = "screenshot (swappy)" }
+)
+-- Keep legacy script-based resize bindings commented for quick rollback during Lua API migration.
+-- These call ResizeActive.sh and are preserved in case native hl.dsp/hl.window resize behavior regresses.
+-- bind(
+-- "SUPER SHIFT",
+-- "left",
+-- exec_cmd("bash $HOME/.config/hypr/scripts/ResizeActive.sh -50 0"),
+-- { description = "resize left (-50)" }
+-- )
+-- bind(
+-- "SUPER SHIFT",
+-- "right",
+-- exec_cmd("bash $HOME/.config/hypr/scripts/ResizeActive.sh 50 0"),
+-- { description = "resize right (+50)" }
+-- )
+-- bind(
+-- "SUPER SHIFT",
+-- "up",
+-- exec_cmd("bash $HOME/.config/hypr/scripts/ResizeActive.sh 0 -50"),
+-- { description = "resize up (-50)" }
+-- )
+-- bind(
+-- "SUPER SHIFT",
+-- "down",
+-- exec_cmd("bash $HOME/.config/hypr/scripts/ResizeActive.sh 0 50"),
+-- { description = "resize down (+50)" }
+-- )
+bind(
+ "SUPER SHIFT",
+ "left",
+ dispatch("resizeactive", "-50 0"),
+ { description = "resize left (-50)" }
+)
+bind(
+ "SUPER SHIFT",
+ "right",
+ dispatch("resizeactive", "50 0"),
+ { description = "resize right (+50)" }
+)
+bind("SUPER SHIFT", "up", dispatch("resizeactive", "0 -50"), { description = "resize up (-50)" })
+bind(
+ "SUPER SHIFT",
+ "down",
+ dispatch("resizeactive", "0 50"),
+ { description = "resize down (+50)" }
+)
+-- Keep legacy directional move script binds commented for rollback during Lua API migration.
+-- Native movewindow dispatch below replaces LuaMoveWindowDirectional.sh usage.
+-- bind(
+-- "SUPER CTRL",
+-- "left",
+-- exec_cmd("$HOME/.config/hypr/scripts/LuaMoveWindowDirectional.sh left"),
+-- { description = "move window left" }
+-- )
+-- bind(
+-- "SUPER CTRL",
+-- "right",
+-- exec_cmd("$HOME/.config/hypr/scripts/LuaMoveWindowDirectional.sh right"),
+-- { description = "move window right" }
+-- )
+
+-- Section: Window resize, move, swap, and grouping
+bind("SUPER CTRL", "left", dispatch("movewindow", "l"), { description = "move window left" })
+bind("SUPER CTRL", "right", dispatch("movewindow", "r"), { description = "move window right" })
+bind("SUPER CTRL", "up", dispatch("movewindow", "u"), { description = "move window up" })
+bind("SUPER CTRL", "down", dispatch("movewindow", "d"), { description = "move window down" })
+bind(
+ "SUPER ALT",
+ "left",
+ exec_cmd("$HOME/.config/hypr/scripts/LuaSwapWindow.sh l"),
+ { description = "swap window left" }
+)
+bind(
+ "SUPER ALT",
+ "right",
+ exec_cmd("$HOME/.config/hypr/scripts/LuaSwapWindow.sh r"),
+ { description = "swap window right" }
+)
+bind("SUPER ALT", "up", exec_cmd("$HOME/.config/hypr/scripts/LuaSwapWindow.sh u"), { description = "swap window up" })
+bind(
+ "SUPER ALT",
+ "down",
+ exec_cmd("$HOME/.config/hypr/scripts/LuaSwapWindow.sh d"),
+ { description = "swap window down" }
+)
+bind("SUPER", "G", dispatch("togglegroup", ""), { description = "toggle group" })
+bind("SUPER", "Tab", dispatch("changegroupactive", "f"), { description = "Change Group Forward" })
+bind("SUPER CTRL", "tab", dispatch("changegroupactive", ""), { description = "change active in group" })
+bind("SUPER SHIFT", "Tab", dispatch("changegroupactive", "b"), { description = "Change Group Back" })
+bind("SUPER CTRL", "K", dispatch("moveintogroup", "l"), { description = "Move left into group" })
+bind("SUPER CTRL", "L", dispatch("moveintogroup", "r"), { description = "Move Right into group" })
+bind("SUPER CTRL", "H", dispatch("moveoutofgroup", ""), { description = "Move active out of group" })
+bind("SUPER", "left", dispatch("movefocus", "l"), { description = "focus left" })
+bind("SUPER", "right", dispatch("movefocus", "r"), { description = "focus right" })
+bind("SUPER", "up", dispatch("movefocus", "u"), { description = "focus up" })
+bind("SUPER", "down", dispatch("movefocus", "d"), { description = "focus down" })
+
+-- Section: Workspace navigation and assignment
+-- Keep legacy relative workspace focus script binds commented for rollback during Lua API migration.
+-- Native workspace dispatch below replaces LuaFocusWorkspaceRelative.sh usage.
+-- bind(
+-- "SUPER",
+-- "tab",
+-- exec_cmd("$HOME/.config/hypr/scripts/LuaFocusWorkspaceRelative.sh next"),
+-- { description = "next workspace" }
+-- )
+-- bind(
+-- "SUPER SHIFT",
+-- "tab",
+-- exec_cmd("$HOME/.config/hypr/scripts/LuaFocusWorkspaceRelative.sh previous"),
+-- { description = "previous workspace" }
+-- )
+bind("SUPER", "tab", dispatch("workspace", "e+1"), { description = "next workspace" })
+bind("SUPER SHIFT", "tab", dispatch("workspace", "e-1"), { description = "previous workspace" })
+bind("SUPER SHIFT", "U", dispatch("movetoworkspace", "special"), { description = "move to special workspace" })
+bind("SUPER", "U", dispatch("togglespecialworkspace", ""), { description = "toggle special workspace" })
+bind("SUPER", "code:10", dispatch("workspace", "1"), { description = "workspace 1" })
+bind("SUPER", "code:11", dispatch("workspace", "2"), { description = "workspace 2" })
+bind("SUPER", "code:12", dispatch("workspace", "3"), { description = "workspace 3" })
+bind("SUPER", "code:13", dispatch("workspace", "4"), { description = "workspace 4" })
+bind("SUPER", "code:14", dispatch("workspace", "5"), { description = "workspace 5" })
+bind("SUPER", "code:15", dispatch("workspace", "6"), { description = "workspace 6" })
+bind("SUPER", "code:16", dispatch("workspace", "7"), { description = "workspace 7" })
+bind("SUPER", "code:17", dispatch("workspace", "8"), { description = "workspace 8" })
+bind("SUPER", "code:18", dispatch("workspace", "9"), { description = "workspace 9" })
+bind("SUPER", "code:19", dispatch("workspace", "10"), { description = "workspace 10" })
+bind("SUPER SHIFT", "code:10", dispatch("movetoworkspace", "1"), { description = "move to workspace 1" })
+bind("SUPER SHIFT", "code:11", dispatch("movetoworkspace", "2"), { description = "move to workspace 2" })
+bind("SUPER SHIFT", "code:12", dispatch("movetoworkspace", "3"), { description = "move to workspace 3" })
+bind("SUPER SHIFT", "code:13", dispatch("movetoworkspace", "4"), { description = "move to workspace 4" })
+bind("SUPER SHIFT", "code:14", dispatch("movetoworkspace", "5"), { description = "move to workspace 5" })
+bind("SUPER SHIFT", "code:15", dispatch("movetoworkspace", "6"), { description = "move to workspace 6" })
+bind("SUPER SHIFT", "code:16", dispatch("movetoworkspace", "7"), { description = "move to workspace 7" })
+bind("SUPER SHIFT", "code:17", dispatch("movetoworkspace", "8"), { description = "move to workspace 8" })
+bind("SUPER SHIFT", "code:18", dispatch("movetoworkspace", "9"), { description = "move to workspace 9" })
+bind("SUPER SHIFT", "code:19", dispatch("movetoworkspace", "10"), { description = "move to workspace 10" })
+-- Keep legacy relative move-to-workspace script binds commented for rollback during Lua API migration.
+-- Native movetoworkspace dispatch below replaces LuaMoveWindowWorkspaceRelative.sh usage.
+-- bind(
+-- "SUPER SHIFT",
+-- "bracketleft",
+-- exec_cmd("$HOME/.config/hypr/scripts/LuaMoveWindowWorkspaceRelative.sh previous"),
+-- { description = "move to previous workspace" }
+-- )
+-- bind(
+-- "SUPER SHIFT",
+-- "bracketright",
+-- exec_cmd("$HOME/.config/hypr/scripts/LuaMoveWindowWorkspaceRelative.sh next"),
+-- { description = "move to next workspace" }
+-- )
+bind("SUPER SHIFT", "bracketleft", dispatch("movetoworkspace", "-1"), { description = "move to previous workspace" })
+bind("SUPER SHIFT", "bracketright", dispatch("movetoworkspace", "+1"), { description = "move to next workspace" })
+bind("SUPER CTRL", "code:10", dispatch("movetoworkspacesilent", "1"), { description = "move silently to workspace 1" })
+bind("SUPER CTRL", "code:11", dispatch("movetoworkspacesilent", "2"), { description = "move silently to workspace 2" })
+bind("SUPER CTRL", "code:12", dispatch("movetoworkspacesilent", "3"), { description = "move silently to workspace 3" })
+bind("SUPER CTRL", "code:13", dispatch("movetoworkspacesilent", "4"), { description = "move silently to workspace 4" })
+bind("SUPER CTRL", "code:14", dispatch("movetoworkspacesilent", "5"), { description = "move silently to workspace 5" })
+bind("SUPER CTRL", "code:15", dispatch("movetoworkspacesilent", "6"), { description = "move silently to workspace 6" })
+bind("SUPER CTRL", "code:16", dispatch("movetoworkspacesilent", "7"), { description = "move silently to workspace 7" })
+bind("SUPER CTRL", "code:17", dispatch("movetoworkspacesilent", "8"), { description = "move silently to workspace 8" })
+bind("SUPER CTRL", "code:18", dispatch("movetoworkspacesilent", "9"), { description = "move silently to workspace 9" })
+bind(
+ "SUPER CTRL",
+ "code:19",
+ dispatch("movetoworkspacesilent", "10"),
+ { description = "move silently to workspace 10" }
+)
+-- Keep legacy silent relative move-to-workspace script binds commented for rollback during Lua API migration.
+-- Native movetoworkspacesilent dispatch below replaces LuaMoveWindowWorkspaceRelative.sh usage.
+-- bind(
+-- "SUPER CTRL",
+-- "bracketleft",
+-- exec_cmd("$HOME/.config/hypr/scripts/LuaMoveWindowWorkspaceRelative.sh previous"),
+-- { description = "move silently to previous workspace" }
+-- )
+-- bind(
+-- "SUPER CTRL",
+-- "bracketright",
+-- exec_cmd("$HOME/.config/hypr/scripts/LuaMoveWindowWorkspaceRelative.sh next"),
+-- { description = "move silently to next workspace" }
+-- )
+bind(
+ "SUPER CTRL",
+ "bracketleft",
+ dispatch("movetoworkspacesilent", "-1"),
+ { description = "move silently to previous workspace" }
+)
+bind(
+ "SUPER CTRL",
+ "bracketright",
+ dispatch("movetoworkspacesilent", "+1"),
+ { description = "move silently to next workspace" }
+)
+-- Keep legacy scroll/period/comma workspace focus script binds commented for rollback during Lua API migration.
+-- Native workspace dispatch below replaces LuaFocusWorkspaceRelative.sh usage.
+-- bind(
+-- "SUPER",
+-- "mouse_down",
+-- exec_cmd("$HOME/.config/hypr/scripts/LuaFocusWorkspaceRelative.sh next"),
+-- { description = "next workspace" }
+-- )
+-- bind(
+-- "SUPER",
+-- "mouse_up",
+-- exec_cmd("$HOME/.config/hypr/scripts/LuaFocusWorkspaceRelative.sh previous"),
+-- { description = "previous workspace" }
+-- )
+-- bind(
+-- "SUPER",
+-- "period",
+-- exec_cmd("$HOME/.config/hypr/scripts/LuaFocusWorkspaceRelative.sh next"),
+-- { description = "next workspace" }
+-- )
+-- bind(
+-- "SUPER",
+-- "comma",
+-- exec_cmd("$HOME/.config/hypr/scripts/LuaFocusWorkspaceRelative.sh previous"),
+-- { description = "previous workspace" }
+-- )
+bind("SUPER", "mouse_down", dispatch("workspace", "e+1"), { description = "next workspace" })
+bind("SUPER", "mouse_up", dispatch("workspace", "e-1"), { description = "previous workspace" })
+bind("SUPER", "period", dispatch("workspace", "e+1"), { description = "next workspace" })
+bind("SUPER", "comma", dispatch("workspace", "e-1"), { description = "previous workspace" })
+
+-- Section: Mouse drag/resize bindings
+bindm("SUPER", "mouse:272", "movewindow", "move window")
+bindm("SUPER", "mouse:273", "resizewindow", "resize window")
diff --git a/config/hypr/lua/laptop-lid.lua b/config/hypr/lua/laptop-lid.lua
new file mode 100644
index 00000000..5792791f
--- /dev/null
+++ b/config/hypr/lua/laptop-lid.lua
@@ -0,0 +1,22 @@
+-- # ==================================================
+-- # KoolDots (2026)
+-- # Project URL: https://github.com/LinuxBeginnings
+-- # License: GNU GPLv3
+-- # SPDX-License-Identifier: GPL-3.0-or-later
+-- # ==================================================
+--
+-- Sample code to handle disbling eDP-1 when lid closed
+-- Code written by @star on TheBlacDon's discord server
+-- Thank you
+--
+-- Lid close: remove laptop panel from layout
+hl.bind("switch:on:Lid Switch", function()
+ -- hl.dispatch(hl.dsp.dpms({ action = "disable", monitor = "eDP-1" }))
+ hl.monitor({ output = "eDP-1", disabled = true })
+end)
+
+-- Lid open: restore laptop panel
+hl.bind("switch:off:Lid Switch", function()
+ -- hl.dispatch(hl.dsp.dpms({ action = "enable", monitor = "eDP-1" }))
+ hl.monitor({ output = "eDP-1", disabled = false })
+end)
diff --git a/config/hypr/lua/laptops.lua b/config/hypr/lua/laptops.lua
new file mode 100644
index 00000000..7da9bdc2
--- /dev/null
+++ b/config/hypr/lua/laptops.lua
@@ -0,0 +1,14 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- Converted from:
+-- - config/hypr/configs/Laptops.conf
+-- - config/hypr/UserConfigs/Laptops.conf
+-- - config/hypr/UserConfigs/LaptopDisplay.conf
+--
+-- No active laptop rules are currently enabled in the source files.
+-- Add hl.bind(...) and/or hl.monitor(...) entries here when enabling laptop-lid logic.
diff --git a/config/hypr/lua/layer_rules.lua b/config/hypr/lua/layer_rules.lua
new file mode 100644
index 00000000..c40c3256
--- /dev/null
+++ b/config/hypr/lua/layer_rules.lua
@@ -0,0 +1,88 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+-- Auto-generated from config/hypr/configs/LayerRules.conf for Lua testing.
+-- Edit the source LayerRules.conf and regenerate this file when vendor rules change.
+
+local function apply_layer_rule(rule)
+ if hl.layer_rule then
+ hl.layer_rule(rule)
+ end
+end
+
+apply_layer_rule({
+ name = "layerrule-001",
+ match = {
+ namespace = "rofi",
+ },
+ blur = true,
+ ignore_alpha = 0,
+ animation = "slide",
+})
+
+apply_layer_rule({
+ name = "layerrule-002",
+ match = {
+ namespace = "notifications",
+ },
+ blur = true,
+ ignore_alpha = 0,
+ animation = "slide",
+})
+
+apply_layer_rule({
+ name = "layerrule-003",
+ match = {
+ namespace = "quickshell:overview",
+ },
+ blur = true,
+ ignore_alpha = 0.5,
+})
+
+apply_layer_rule({
+ name = "layerrule-004",
+ match = {
+ namespace = "wallpaper",
+ },
+ blur = true,
+ ignore_alpha = 0,
+})
+
+apply_layer_rule({
+ name = "layerrule-005",
+ match = {
+ namespace = "swaync-control-center",
+ },
+ blur = true,
+ ignore_alpha = 0,
+})
+
+apply_layer_rule({
+ name = "layerrule-006",
+ match = {
+ namespace = "swaync-notification-window",
+ },
+ blur = true,
+ ignore_alpha = 0,
+})
+
+apply_layer_rule({
+ name = "layerrule-007",
+ match = {
+ namespace = "com.aurora.keybinds_help",
+ },
+ blur = true,
+ ignore_alpha = 0,
+})
+
+apply_layer_rule({
+ name = "layerrule-008",
+ match = {
+ namespace = "logout_dialog",
+ },
+ blur = true,
+ ignore_alpha = 0,
+})
diff --git a/config/hypr/lua/monitors.lua b/config/hypr/lua/monitors.lua
new file mode 100644
index 00000000..c04735d7
--- /dev/null
+++ b/config/hypr/lua/monitors.lua
@@ -0,0 +1,46 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- Converted from config/hypr/monitors.conf (active monitor entries only).
+
+hl.monitor({
+ output = "",
+ mode = "preferred",
+ position = "auto",
+ scale = "1",
+})
+
+hl.monitor({
+ output = "",
+ mode = "highrr",
+ position = "auto",
+ scale = "1",
+})
+
+hl.monitor({
+ output = "",
+ mode = "highres",
+ position = "auto",
+ scale = "1",
+})
+
+hl.monitor({
+ output = "Virtual-1",
+ mode = "1920x1080@60",
+ position = "auto",
+ scale = "1",
+})
+
+-- Load user monitor overrides from UserConfigs when present.
+do
+ local configHome = os.getenv("XDG_CONFIG_HOME") or ((os.getenv("HOME") or "") .. "/.config")
+ local userMonitors = configHome .. "/hypr/UserConfigs/monitors.lua"
+ local ok, err = pcall(dofile, userMonitors)
+ if not ok and err and tostring(err):find("No such file or directory", 1, true) == nil then
+ print("[WARN] Unable to load user monitor overrides from " .. userMonitors .. ": " .. tostring(err))
+ end
+end
diff --git a/config/hypr/lua/screenshot-region.lua b/config/hypr/lua/screenshot-region.lua
new file mode 100644
index 00000000..6ba83bff
--- /dev/null
+++ b/config/hypr/lua/screenshot-region.lua
@@ -0,0 +1,13 @@
+-- Found on Hyprland discord
+-- Possible replacement for screenshot.sh
+
+function screenshot(file_prefix, region)
+ local file = "$HOME/Pictures/Screenshots/"
+ .. file_prefix
+ .. os.date("-%Y-%m-%d_%Hh-%Mm-%Ss_" .. math.random(100000) .. ".png")
+ local grim = 'grim -g "' .. region .. '" ' .. file
+ local message = " && notify-send Screenshot saved"
+ local copy = " && wl-copy < " .. file
+
+ hl.dispatch(hl.dsp.exec_cmd(grim .. message .. copy))
+end
diff --git a/config/hypr/lua/settings.lua b/config/hypr/lua/settings.lua
new file mode 100644
index 00000000..78ae61e2
--- /dev/null
+++ b/config/hypr/lua/settings.lua
@@ -0,0 +1,179 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- Converted from:
+-- - config/hypr/configs/SystemSettings.conf
+-- - config/hypr/UserConfigs/UserSettings.conf (currently empty)
+
+local scriptsDir = "$HOME/.config/hypr/scripts"
+
+hl.config({
+ dwindle = {
+ preserve_split = true,
+ smart_resizing = true,
+ use_active_for_splits = true,
+ smart_split = false,
+ default_split_ratio = 1.0,
+ split_bias = 0,
+ precise_mouse_move = false,
+ special_scale_factor = 0.8,
+ },
+})
+
+hl.config({
+ master = {
+ new_status = "slave",
+ new_on_top = false,
+ new_on_active = "none",
+ orientation = "left",
+ mfact = 0.55,
+ slave_count_for_center_master = 2,
+ center_master_fallback = "left",
+ smart_resizing = true,
+ drop_at_cursor = true,
+ always_keep_position = false,
+ },
+})
+
+hl.config({
+ scrolling = {
+ column_width = 0.80,
+ fullscreen_on_one_column = true,
+ direction = "right",
+ follow_focus = true,
+ },
+})
+
+hl.config({
+ general = {
+ resize_on_border = true,
+ layout = "dwindle",
+ },
+})
+
+hl.config({
+ input = {
+ kb_layout = "us",
+ kb_variant = "",
+ kb_model = "",
+ kb_options = "",
+ kb_rules = "",
+ repeat_rate = 50,
+ repeat_delay = 300,
+ sensitivity = 0,
+ numlock_by_default = true,
+ left_handed = false,
+ follow_mouse = 1,
+ float_switch_override_focus = false,
+ touchpad = {
+ disable_while_typing = true,
+ natural_scroll = true,
+ clickfinger_behavior = false,
+ middle_button_emulation = false,
+ tap_to_click = true,
+ drag_lock = false,
+ },
+ touchdevice = {
+ enabled = true,
+ },
+ tablet = {
+ transform = 0,
+ left_handed = 0,
+ },
+ },
+})
+
+hl.config({
+ gestures = {
+ workspace_swipe_distance = 300,
+ workspace_swipe_touch = false,
+ workspace_swipe_invert = true,
+ workspace_swipe_min_speed_to_force = 30,
+ workspace_swipe_cancel_ratio = 0.5,
+ workspace_swipe_create_new = true,
+ workspace_swipe_direction_lock = true,
+ workspace_swipe_forever = false,
+ workspace_swipe_use_r = false,
+ close_max_timeout = 100,
+ },
+})
+
+hl.gesture({
+ fingers = 3,
+ direction = "horizontal",
+ action = "workspace",
+})
+
+-- Complex dispatcher gestures from SystemSettings.conf are pending explicit Lua API parity:
+-- gesture = 3, up, dispatcher, exec, hyprctl keyword cursor:zoom_factor ...
+-- gesture = 3, down, dispatcher, exec, hyprctl keyword cursor:zoom_factor ...
+-- gesture = 4, up, dispatcher, exec, $scriptsDir/OverviewToggle.sh
+-- gesture = 4, down, float
+
+hl.config({
+ misc = {
+ force_default_wallpaper = 0,
+ disable_hyprland_logo = true,
+ disable_splash_rendering = true,
+ -- Setting vrr 0, issues with MPV/VLC at fullscreen
+ -- vrr 0, disable, vrr 1, always on, vrr 2, on at full screen
+ vrr = 0,
+ mouse_move_enables_dpms = true,
+ enable_swallow = false,
+ swallow_regex = "^(kitty)$",
+ focus_on_activate = false,
+ initial_workspace_tracking = 0,
+ middle_click_paste = false,
+ enable_anr_dialog = true,
+ anr_missed_pings = 15,
+ allow_session_lock_restore = true,
+ on_focus_under_fullscreen = 1,
+ },
+})
+
+hl.config({
+ binds = {
+ workspace_back_and_forth = true,
+ allow_workspace_cycles = true,
+ pass_mouse_when_bound = false,
+ },
+})
+
+hl.config({
+ xwayland = {
+ enabled = true,
+ force_zero_scaling = true,
+ },
+})
+
+hl.config({
+ render = {
+ direct_scanout = 0,
+ },
+})
+
+hl.config({
+ cursor = {
+ sync_gsettings_theme = true,
+ no_hardware_cursors = 2,
+ enable_hyprcursor = true,
+ warp_on_change_workspace = 2,
+ no_warps = true,
+ no_break_fs_vrr = false,
+ min_refresh_rate = 24,
+ hotspot_padding = 1,
+ inactive_timeout = 0,
+ default_monitor = "",
+ zoom_factor = 1.0,
+ zoom_rigid = false,
+ zoom_detached_camera = true,
+ hide_on_key_press = true,
+ hide_on_touch = false,
+ hide_on_tablet = false,
+ use_cpu_buffer = false,
+ },
+})
diff --git a/config/hypr/lua/startup.lua b/config/hypr/lua/startup.lua
new file mode 100644
index 00000000..6c189113
--- /dev/null
+++ b/config/hypr/lua/startup.lua
@@ -0,0 +1,71 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- Converted from:
+-- - config/hypr/configs/Startup_Apps.conf
+-- - config/hypr/UserConfigs/Startup_Apps.conf
+
+local scriptsDir = "$HOME/.config/hypr/scripts"
+local userScripts = "$HOME/.config/hypr/UserScripts"
+local wallDir = "$HOME/Pictures/wallpapers"
+local session = os.getenv("HYPRLAND_INSTANCE_SIGNATURE") or "default"
+local function shell_quote(value)
+ return "'" .. tostring(value):gsub("'", "'\\''") .. "'"
+end
+local function exec_once(cmd)
+ -- Why this wrapper exists:
+ -- 1) Enforce once-per-Hypr-session startup behavior using marker files.
+ -- 2) Avoid startup race conditions by waiting for Wayland/Hypr sockets.
+ -- 3) Capture per-command logs to simplify troubleshooting in user setups.
+
+ local key = cmd:gsub("[^%w_.-]", "_"):sub(1, 80)
+ local marker = "/tmp/hypr-lua-exec-once-" .. session .. "-" .. key
+ local log = "/tmp/hypr-lua-startup-" .. key .. ".log"
+ local readiness = "runtime=${XDG_RUNTIME_DIR:-/run/user/$(id -u)}; export XDG_RUNTIME_DIR=\"$runtime\"; for _ in $(seq 1 200); do if [ -n \"$WAYLAND_DISPLAY\" ] && [ -S \"$runtime/$WAYLAND_DISPLAY\" ]; then break; fi; for sock in \"$runtime\"/wayland-[0-9]*; do [ -S \"$sock\" ] || continue; case \"$(basename \"$sock\")\" in *awww*) continue ;; esac; export WAYLAND_DISPLAY=\"$(basename \"$sock\")\"; break 2; done; sleep 0.1; done; if [ -n \"$HYPRLAND_INSTANCE_SIGNATURE\" ]; then hypr_sock=\"$runtime/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket.sock\"; for _ in $(seq 1 200); do [ -S \"$hypr_sock\" ] && break; sleep 0.1; done; fi"
+ local inner = readiness .. "; " .. cmd
+ local script = "[ -e " .. shell_quote(marker) .. " ] || { touch " .. shell_quote(marker) .. " && sh -lc " .. shell_quote(inner) .. " >>" .. shell_quote(log) .. " 2>&1 & }"
+ os.execute("sh -lc " .. shell_quote(script))
+end
+-- Prefer lifecycle-hook orchestration for clarity while keeping exec_once
+-- reliability semantics for real-world startup behavior.
+local startup_commands = {
+ scriptsDir .. "/WallpaperDaemon.sh",
+ "$HOME/.config/hypr/initial-boot.sh",
+ "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP",
+ "systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP",
+ scriptsDir .. "/Polkit.sh",
+ "nm-applet",
+ "nm-tray",
+ "swaync",
+ scriptsDir .. "/PortalHyprland.sh",
+ "sh " .. scriptsDir .. "/WaybarStartup.sh",
+ "qs -c overview",
+ "hypridle",
+ scriptsDir .. "/Hyprsunset.sh init",
+ -- NOTE: Dropterminal is currently certified only with kitty. Not all terminals behave correctly as a dropdown.
+ scriptsDir .. "/Dropterminal.sh --startup kitty",
+ "wl-paste --type text --watch cliphist store",
+ "wl-paste --type image --watch cliphist store",
+}
+
+local function run_startup_commands()
+ for _, cmd in ipairs(startup_commands) do
+ exec_once(cmd)
+ end
+end
+
+if hl and hl.on then
+ hl.on("hyprland.start", run_startup_commands)
+else
+ -- Compatibility fallback for older/limited runtimes without hl.on.
+ run_startup_commands()
+end
+
+-- Optional startup examples retained from the original config:
+-- exec_once("mpvpaper '*' -o \"load-scripts=no no-audio --loop\" \"\"")
+-- exec_once(userScripts .. "/WallpaperAutoChange.sh " .. wallDir)
+-- exec_once(userScripts .. "/RainbowBorders.sh")
diff --git a/config/hypr/lua/user_decorations_helper.lua b/config/hypr/lua/user_decorations_helper.lua
new file mode 100644
index 00000000..f5e39ea8
--- /dev/null
+++ b/config/hypr/lua/user_decorations_helper.lua
@@ -0,0 +1,28 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+local function load_wallust_colors(path)
+ local colors = {}
+ local handle = io.open(path, "r")
+ if not handle then
+ return colors
+ end
+
+ for line in handle:lines() do
+ local name, hex = line:match("^%s*%$([%w_]+)%s*=%s*rgb%(([0-9A-Fa-f]+)%)")
+ if name and hex and hex ~= "" then
+ colors[string.lower(name)] = "rgb(" .. string.upper(hex) .. ")"
+ end
+ end
+
+ handle:close()
+ return colors
+end
+
+return {
+ load_wallust_colors = load_wallust_colors,
+}
diff --git a/config/hypr/lua/user_defaults.lua b/config/hypr/lua/user_defaults.lua
new file mode 100644
index 00000000..fb7bb0df
--- /dev/null
+++ b/config/hypr/lua/user_defaults.lua
@@ -0,0 +1,33 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- Converted from config/hypr/UserConfigs/01-UserDefaults.conf (active values only).
+
+KOOLDOTS_DEFAULTS = KOOLDOTS_DEFAULTS or {}
+local editor = os.getenv("EDITOR")
+if editor == nil or editor == "" then
+ editor = "nano"
+end
+local visual = os.getenv("VISUAL")
+if visual == nil then
+ visual = ""
+end
+KOOLDOTS_DEFAULTS.edit = editor
+KOOLDOTS_DEFAULTS.visual = visual
+KOOLDOTS_DEFAULTS.term = "kitty"
+KOOLDOTS_DEFAULTS.files = "thunar"
+KOOLDOTS_DEFAULTS.search_engine = "https://www.google.com/search?q={}"
+
+-- Optional user overrides live outside the pristine lua/ source tree.
+do
+ local configHome = os.getenv("XDG_CONFIG_HOME") or ((os.getenv("HOME") or "") .. "/.config")
+ local userDefaults = configHome .. "/hypr/UserConfigs/user_defaults.lua"
+ local ok, err = pcall(dofile, userDefaults)
+ if not ok and err and tostring(err):find("No such file or directory", 1, true) == nil then
+ print("[WARN] Unable to load user defaults file " .. userDefaults .. ": " .. tostring(err))
+ end
+end
diff --git a/config/hypr/lua/user_keybinds_helper.lua b/config/hypr/lua/user_keybinds_helper.lua
new file mode 100644
index 00000000..f9d4aa0c
--- /dev/null
+++ b/config/hypr/lua/user_keybinds_helper.lua
@@ -0,0 +1,217 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+local dsp = hl.dsp or hl
+
+local function exec_cmd(cmd)
+ if dsp and dsp.exec_cmd then
+ return dsp.exec_cmd(cmd)
+ end
+ return function() hl.exec_cmd(cmd) end
+end
+
+local function shell_quote(value)
+ return "'" .. tostring(value):gsub("'", "'\\''") .. "'"
+end
+
+local function raw_dispatch_cmd(command)
+ if dsp and dsp.exec_raw then
+ return dsp.exec_raw(tostring(command))
+ end
+ local expression = "hl.dsp.exec_raw(" .. string.format("%q", tostring(command)) .. ")"
+ return exec_cmd("hyprctl dispatch " .. shell_quote(expression))
+end
+
+local function trim(value)
+ return (value or ""):gsub("^%s+", ""):gsub("%s+$", "")
+end
+
+local function chord(mods, key)
+ mods = trim(mods):gsub("%s+", " + ")
+ key = trim(key)
+ if mods == "" then
+ return key
+ end
+ return mods .. " + " .. key
+end
+
+local function key_variants(key, mods)
+ key = trim(key):gsub("^xf86", "XF86")
+ local key_aliases = {
+ XF86AudioPlayPause = "XF86AudioPlay",
+ XF86audiolowervolume = "XF86AudioLowerVolume",
+ XF86audiomute = "XF86AudioMute",
+ XF86audioraisevolume = "XF86AudioRaiseVolume",
+ XF86audiostop = "XF86AudioStop",
+ }
+ key = key_aliases[key] or key
+ local shifted_number_keys = {
+ ["code:10"] = "exclam",
+ ["code:11"] = "at",
+ ["code:12"] = "numbersign",
+ ["code:13"] = "dollar",
+ ["code:14"] = "percent",
+ ["code:15"] = "asciicircum",
+ ["code:16"] = "ampersand",
+ ["code:17"] = "asterisk",
+ ["code:18"] = "parenleft",
+ ["code:19"] = "parenright",
+ }
+ local number_keys = {
+ ["code:10"] = "1",
+ ["code:11"] = "2",
+ ["code:12"] = "3",
+ ["code:13"] = "4",
+ ["code:14"] = "5",
+ ["code:15"] = "6",
+ ["code:16"] = "7",
+ ["code:17"] = "8",
+ ["code:18"] = "9",
+ ["code:19"] = "0",
+ }
+ if mods and mods:match("SHIFT") and shifted_number_keys[key] then
+ local number_key = number_keys[key]
+ if number_key then
+ return { shifted_number_keys[key], number_key }
+ end
+ return { shifted_number_keys[key] }
+ end
+ if number_keys[key] then
+ return { number_keys[key] }
+ end
+ return { key }
+end
+
+local function workspace_value(value)
+ value = trim(value)
+ return tonumber(value) or value
+end
+
+local function direction(value)
+ local directions = {
+ l = "left",
+ r = "right",
+ u = "up",
+ d = "down",
+ left = "left",
+ right = "right",
+ up = "up",
+ down = "down",
+ }
+ return directions[trim(value)] or trim(value)
+end
+
+local function dispatch_factory_safely(factory)
+ pcall(function()
+ local dispatcher = factory()
+ if dispatcher then
+ hl.dispatch(dispatcher)
+ end
+ end)
+end
+
+local function dispatch(name, args)
+ local window_api = (dsp and dsp.window) or hl.window or {}
+ name = trim(name)
+ args = trim(args)
+
+ if args:match("^exec%s*,") then
+ return exec_cmd(trim(args:gsub("^exec%s*,", "", 1)))
+ end
+ if name == "exec" then
+ return exec_cmd(args)
+ end
+ if name == "killactive" and window_api.close then
+ return window_api.close()
+ end
+ if name == "fullscreen" and window_api.fullscreen then
+ if args == "1" then
+ return window_api.fullscreen({ mode = "maximized" })
+ end
+ return window_api.fullscreen({ mode = "fullscreen" })
+ end
+ if name == "movefocus" and dsp and dsp.focus then
+ return function()
+ dispatch_factory_safely(function()
+ return dsp.focus({ direction = direction(args) })
+ end)
+ end
+ end
+ if name == "movewindow" and window_api.move then
+ return function()
+ dispatch_factory_safely(function()
+ return window_api.move({ direction = direction(args) })
+ end)
+ end
+ end
+ if name == "workspace" and dsp and dsp.focus then
+ return function() hl.dispatch(dsp.focus({ workspace = workspace_value(args) })) end
+ end
+ if name == "movetoworkspace" and window_api.move then
+ return function() hl.dispatch(window_api.move({ workspace = workspace_value(args) })) end
+ end
+ if name == "movetoworkspacesilent" and window_api.move then
+ return function() hl.dispatch(window_api.move({ workspace = workspace_value(args), follow = false })) end
+ end
+ if name == "togglefloating" and window_api.float then
+ return function() hl.dispatch(window_api.float({ action = "toggle" })) end
+ end
+ if name == "resizewindow" and window_api.resize then
+ return window_api.resize()
+ end
+ if name == "resizeactive" then
+ return raw_dispatch_cmd("resizeactive " .. args)
+ end
+ if args ~= "" then
+ return raw_dispatch_cmd(name .. " " .. args)
+ end
+ return raw_dispatch_cmd(name)
+end
+
+local function bind(mods, key, fn, opts)
+ local seen = {}
+ for _, key_variant in ipairs(key_variants(key, mods)) do
+ local key_chord = chord(mods, key_variant)
+ if not seen[key_chord] then
+ seen[key_chord] = true
+ if opts then
+ hl.bind(key_chord, fn, opts)
+ else
+ hl.bind(key_chord, fn)
+ end
+ end
+ end
+end
+
+local function unbind(mods, key)
+ if hl.unbind then
+ local seen = {}
+ for _, key_variant in ipairs(key_variants(key, mods)) do
+ local key_chord = chord(mods, key_variant)
+ if not seen[key_chord] then
+ seen[key_chord] = true
+ -- Hyprland Lua APIs vary by build: some accept unbind("MOD + KEY"),
+ -- others unbind("MOD", "KEY"), and some no-op one form silently.
+ -- Call both forms to make unbind behavior deterministic.
+ pcall(hl.unbind, key_chord)
+ pcall(hl.unbind, mods, key_variant)
+ end
+ end
+ end
+end
+
+return {
+ exec_cmd = exec_cmd,
+ trim = trim,
+ chord = chord,
+ key_variants = key_variants,
+ workspace_value = workspace_value,
+ raw_dispatch_cmd = raw_dispatch_cmd,
+ dispatch = dispatch,
+ bind = bind,
+ unbind = unbind,
+}
diff --git a/config/hypr/lua/user_layer_rules_helper.lua b/config/hypr/lua/user_layer_rules_helper.lua
new file mode 100644
index 00000000..d54b97c6
--- /dev/null
+++ b/config/hypr/lua/user_layer_rules_helper.lua
@@ -0,0 +1,16 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+local function apply_layer_rule(rule)
+ if hl.layer_rule then
+ hl.layer_rule(rule)
+ end
+end
+
+return {
+ apply_layer_rule = apply_layer_rule,
+}
diff --git a/config/hypr/lua/user_overrides.lua b/config/hypr/lua/user_overrides.lua
new file mode 100644
index 00000000..42502315
--- /dev/null
+++ b/config/hypr/lua/user_overrides.lua
@@ -0,0 +1,156 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- Loads split system/user-editable Lua override files.
+-- System files are loaded from ~/.config/hypr/configs (with UserConfigs fallback for legacy setups).
+local configHome = os.getenv("XDG_CONFIG_HOME") or ((os.getenv("HOME") or "") .. "/.config")
+local hyprDir = configHome .. "/hypr"
+local systemDir = hyprDir .. "/configs"
+local userDir = configHome .. "/hypr/UserConfigs"
+
+local function load_optional(path)
+ local ok, err = pcall(dofile, path)
+ if ok then
+ return true
+ end
+ if err and tostring(err):find("No such file or directory", 1, true) == nil then
+ print("[WARN] Unable to load user override file " .. path .. ": " .. tostring(err))
+ end
+ return false
+end
+local loaded_user_split = false
+
+local system_files = {
+ "system_env.lua",
+ "system_startup.lua",
+ "system_window_rules.lua",
+ "system_layer_rules.lua",
+ "system_keybinds.lua",
+ "system_settings.lua",
+ "system_laptops.lua",
+}
+for _, file in ipairs(system_files) do
+ local primary = systemDir .. "/" .. file
+ local legacy = userDir .. "/" .. file
+ if not load_optional(primary) then
+ load_optional(legacy)
+ end
+end
+
+local user_files = {
+ "user_env.lua",
+ "user_startup.lua",
+ "user_window_rules.lua",
+ "user_layer_rules.lua",
+ "user_keybinds.lua",
+ "user_settings.lua",
+ "user_decorations.lua",
+ "user_animations.lua",
+ "user_laptops.lua",
+}
+for _, file in ipairs(user_files) do
+ local path = userDir .. "/" .. file
+ if load_optional(path) then
+ loaded_user_split = true
+ end
+end
+if not loaded_user_split then
+ load_optional(userDir .. "/user_overrides.lua") -- legacy single-file support
+end
+
+-- Legacy compatibility: import UserKeybinds.conf when user_keybinds.lua is missing.
+do
+ local userKeybindsLua = userDir .. "/user_keybinds.lua"
+ local legacyUserKeybinds = userDir .. "/UserKeybinds.conf"
+
+ local hasUserLua = io.open(userKeybindsLua, "r")
+ if hasUserLua then
+ hasUserLua:close()
+ else
+ local legacy = io.open(legacyUserKeybinds, "r")
+ if legacy then
+ local function trim(value)
+ return (value or ""):gsub("^%s+", ""):gsub("%s+$", "")
+ end
+ local function strip_inline_comment(value)
+ return trim((value or ""):gsub("%s+#.*$", ""))
+ end
+ local function load_vars_from_file(path, vars)
+ local handle = io.open(path, "r")
+ if not handle then
+ return
+ end
+ for raw in handle:lines() do
+ local line = trim(raw)
+ if line ~= "" and not line:match("^#") then
+ local name, val = line:match("^%$([%w_]+)%s*=%s*(.+)$")
+ if name and val then
+ vars[name] = strip_inline_comment(val)
+ end
+ end
+ end
+ handle:close()
+ end
+ local vars = {}
+ local raw_lines = {}
+ local configDir = configHome .. "/hypr/configs"
+ local defaultsFile = userDir .. "/01-UserDefaults.conf"
+ local keybindsFile = configDir .. "/Keybinds.conf"
+ local systemSettingsFile = configDir .. "/SystemSettings.conf"
+
+ load_vars_from_file(systemSettingsFile, vars)
+ load_vars_from_file(keybindsFile, vars)
+ load_vars_from_file(defaultsFile, vars)
+
+ for line in legacy:lines() do
+ table.insert(raw_lines, line)
+ local trimmed = trim(line)
+ if trimmed ~= "" and not trimmed:match("^#") then
+ local var_name, var_value = trimmed:match("^%$([%w_]+)%s*=%s*(.+)$")
+ if var_name and var_value then
+ vars[var_name] = strip_inline_comment(var_value)
+ end
+ end
+ end
+ legacy:close()
+
+ local function expand_vars(value)
+ value = tostring(value or "")
+ for _ = 1, 8 do
+ local changed = false
+ value = value:gsub("%$([%w_]+)", function(name)
+ local replacement = vars[name]
+ if replacement ~= nil then
+ changed = true
+ return replacement
+ end
+ return "$" .. name
+ end)
+ if not changed then
+ break
+ end
+ end
+ return value
+ end
+
+ for _, line in ipairs(raw_lines) do
+ local trimmed = trim(line)
+ if trimmed ~= "" and not trimmed:match("^#") then
+ local keyword, value = trimmed:match("^([%w_]+)%s*=%s*(.+)$")
+ if keyword and value and (keyword:match("^bind") or keyword == "unbind") then
+ local expanded = expand_vars(value)
+ local cmd = "hyprctl keyword " .. keyword .. " " .. string.format("%q", expanded)
+ local ok = os.execute(cmd)
+ if not ok then
+ print("[WARN] Failed to apply legacy keybind via: " .. cmd)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/config/hypr/lua/user_startup_helper.lua b/config/hypr/lua/user_startup_helper.lua
new file mode 100644
index 00000000..2cc050b9
--- /dev/null
+++ b/config/hypr/lua/user_startup_helper.lua
@@ -0,0 +1,34 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+local function shell_quote(value)
+ return "'" .. tostring(value):gsub("'", "'\\''") .. "'"
+end
+
+local function exec_once(cmd, opts)
+ -- Why this wrapper exists:
+ -- 1) Enforce once-per-Hypr-session startup behavior using marker files.
+ -- 2) Avoid startup race conditions by waiting for Wayland/Hypr sockets.
+ -- 3) Capture per-command logs to simplify troubleshooting in user setups.
+
+ opts = opts or {}
+ local session = opts.session or os.getenv("HYPRLAND_INSTANCE_SIGNATURE") or "default"
+ local marker_prefix = opts.marker_prefix or "/tmp/hypr-lua-user-exec-once-"
+ local log_prefix = opts.log_prefix or "/tmp/hypr-lua-user-startup-"
+
+ local key = cmd:gsub("[^%w_.-]", "_"):sub(1, 80)
+ local marker = marker_prefix .. session .. "-" .. key
+ local log = log_prefix .. key .. ".log"
+ local readiness = [[runtime=${XDG_RUNTIME_DIR:-/run/user/$(id -u)}; export XDG_RUNTIME_DIR="$runtime"; for _ in $(seq 1 200); do if [ -n "$WAYLAND_DISPLAY" ] && [ -S "$runtime/$WAYLAND_DISPLAY" ]; then break; fi; for sock in "$runtime"/wayland-[0-9]*; do [ -S "$sock" ] || continue; case "$(basename "$sock")" in *awww*) continue ;; esac; export WAYLAND_DISPLAY="$(basename "$sock")"; break 2; done; sleep 0.1; done; if [ -n "$HYPRLAND_INSTANCE_SIGNATURE" ]; then hypr_sock="$runtime/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket.sock"; for _ in $(seq 1 200); do [ -S "$hypr_sock" ] && break; sleep 0.1; done; fi]]
+ local inner = readiness .. "; " .. cmd
+ local script = "[ -e " .. shell_quote(marker) .. " ] || { touch " .. shell_quote(marker) .. " && sh -lc " .. shell_quote(inner) .. " >>" .. shell_quote(log) .. " 2>&1 & }"
+ os.execute("sh -lc " .. shell_quote(script))
+end
+
+return {
+ exec_once = exec_once,
+}
diff --git a/config/hypr/lua/user_window_rules_helper.lua b/config/hypr/lua/user_window_rules_helper.lua
new file mode 100644
index 00000000..5ef17ef6
--- /dev/null
+++ b/config/hypr/lua/user_window_rules_helper.lua
@@ -0,0 +1,16 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+local function apply_window_rule(rule)
+ if hl.window_rule then
+ hl.window_rule(rule)
+ end
+end
+
+return {
+ apply_window_rule = apply_window_rule,
+}
diff --git a/config/hypr/lua/window_rules.lua b/config/hypr/lua/window_rules.lua
new file mode 100644
index 00000000..1a43acd3
--- /dev/null
+++ b/config/hypr/lua/window_rules.lua
@@ -0,0 +1,1110 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- Auto-generated from config/hypr/configs/WindowRules.conf for Lua testing.
+-- Edit the source WindowRules.conf and regenerate this file when vendor rules change.
+
+local function apply_window_rule(rule)
+ if hl.window_rule then
+ hl.window_rule(rule)
+ end
+end
+
+
+apply_window_rule({
+ name = "tag-browser-firefox",
+ match = {
+ class = "^([Ff]irefox|org.mozilla.firefox|[Ff]irefox-esr|[Ff]irefox-bin)$",
+ },
+ tag = "+browser",
+})
+
+apply_window_rule({
+ name = "tag-browser-google-chrome",
+ match = {
+ class = "^([Gg]oogle-chrome(-beta|-dev|-unstable)?)$",
+ },
+ tag = "+browser",
+})
+
+apply_window_rule({
+ name = "tag-browser-chrome-default-profile",
+ match = {
+ class = "^(chrome-.+-Default)$",
+ },
+ tag = "+browser",
+})
+
+apply_window_rule({
+ name = "tag-browser-chromium",
+ match = {
+ class = "^([Cc]hromium)$",
+ },
+ tag = "+browser",
+})
+
+apply_window_rule({
+ name = "tag-browser-microsoft-edge",
+ match = {
+ class = "^([Mm]icrosoft-edge(-stable|-beta|-dev|-unstable))$",
+ },
+ tag = "+browser",
+})
+
+apply_window_rule({
+ name = "tag-browser-brave",
+ match = {
+ class = "^([Bb]rave-browser(-beta|-dev|-unstable)?)$",
+ },
+ tag = "+browser",
+})
+
+apply_window_rule({
+ name = "tag-browser-thorium-cachy",
+ match = {
+ class = "^([Tt]horium-browser|[Cc]achy-browser)$",
+ },
+ tag = "+browser",
+})
+
+apply_window_rule({
+ name = "tag-browser-zen",
+ match = {
+ class = "^(zen-alpha|zen)$",
+ },
+ tag = "+browser",
+})
+
+apply_window_rule({
+ name = "tag-notifications-swaync",
+ match = {
+ class = "^(swaync-control-center|swaync-notification-window|swaync-client|class)$",
+ },
+ tag = "+notif",
+})
+
+apply_window_rule({
+ name = "tag-kool-cheat-sheet",
+ match = {
+ title = "^(KooL Quick Cheat Sheet)$",
+ },
+ tag = "+KooL_Cheat",
+})
+
+apply_window_rule({
+ name = "tag-kool-hyprland-settings",
+ match = {
+ title = "^(KooL Hyprland Settings)$",
+ },
+ tag = "+KooL_Settings",
+})
+
+apply_window_rule({
+ name = "tag-kool-settings-nwg-tools",
+ match = {
+ class = "^(nwg-displays|nwg-look)$",
+ },
+ tag = "+KooL-Settings",
+})
+
+apply_window_rule({
+ name = "tag-terminal-emulators",
+ match = {
+ class = "^(ghostty|wezterm|Alacritty|kitty|kitty-dropterm)$",
+ },
+ tag = "+terminal",
+})
+
+apply_window_rule({
+ name = "tag-email-thunderbird",
+ match = {
+ class = "^([Tt]hunderbird|org.mozilla.Thunderbird)$",
+ },
+ tag = "+email",
+})
+
+apply_window_rule({
+ name = "tag-email-betterbird",
+ match = {
+ class = "^(eu.betterbird.Betterbird)$",
+ },
+ tag = "+email",
+})
+
+apply_window_rule({
+ name = "tag-email-evolution",
+ match = {
+ class = "^(org.gnome.Evolution)$",
+ },
+ tag = "+email",
+})
+
+apply_window_rule({
+ name = "tag-projects-vscodium",
+ match = {
+ class = "^(codium|codium-url-handler|VSCodium)$",
+ },
+ tag = "+projects",
+})
+
+apply_window_rule({
+ name = "tag-projects-vscode",
+ match = {
+ class = "^(VSCode|code|code-url-handler)$",
+ },
+ tag = "+projects",
+})
+
+apply_window_rule({
+ name = "tag-projects-jetbrains",
+ match = {
+ class = "^(jetbrains-.+)$",
+ },
+ tag = "+projects",
+})
+
+apply_window_rule({
+ name = "tag-projects-zed",
+ match = {
+ class = "^(dev.zed.Zed|antigravity)$",
+ },
+ tag = "+projects",
+})
+
+apply_window_rule({
+ name = "tag-screenshare-obs",
+ match = {
+ class = "^(com.obsproject.Studio)$",
+ },
+ tag = "+screenshare",
+})
+
+apply_window_rule({
+ name = "tag-im-discord-family",
+ match = {
+ class = "^([Dd]iscord|[Ww]ebCord|[Vv]esktop)$",
+ },
+ tag = "+im",
+})
+
+apply_window_rule({
+ name = "tag-im-ferdium",
+ match = {
+ class = "^([Ff]erdium)$",
+ },
+ tag = "+im",
+})
+
+apply_window_rule({
+ name = "tag-im-whatsapp",
+ match = {
+ class = "^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$",
+ },
+ tag = "+im",
+})
+
+apply_window_rule({
+ name = "tag-im-telegram",
+ match = {
+ class = "^(org.telegram.desktop|io.github.tdesktop_x64.TDesktop)$",
+ },
+ tag = "+im",
+})
+
+apply_window_rule({
+ name = "tag-im-teams",
+ match = {
+ class = "^(teams-for-linux)$",
+ },
+ tag = "+im",
+})
+
+apply_window_rule({
+ name = "tag-im-element",
+ match = {
+ class = "^(im.riot.Riot|Element)$",
+ },
+ tag = "+im",
+})
+
+apply_window_rule({
+ name = "tag-games-gamescope",
+ match = {
+ class = "^(gamescope)$",
+ },
+ tag = "+games",
+})
+
+apply_window_rule({
+ name = "tag-games-steam-app",
+ match = {
+ class = "^(steam_app_\\\\d+)$",
+ },
+ tag = "+games",
+})
+
+apply_window_rule({
+ name = "tag-games-proton",
+ match = {
+ xdg_tag = "^(proton-game)$",
+ },
+ tag = "+games",
+})
+
+apply_window_rule({
+ name = "tag-gamestore-steam",
+ match = {
+ class = "^([Ss]team)$",
+ },
+ tag = "+gamestore",
+})
+
+apply_window_rule({
+ name = "tag-gamestore-lutris",
+ match = {
+ title = "^([Ll]utris)$",
+ },
+ tag = "+gamestore",
+})
+
+apply_window_rule({
+ name = "tag-gamestore-heroic",
+ match = {
+ class = "^(com.heroicgameslauncher.hgl)$",
+ },
+ tag = "+gamestore",
+})
+
+apply_window_rule({
+ name = "tag-file-manager-common",
+ match = {
+ class = "^([Tt]hunar|org.gnome.Nautilus|[Pp]cmanfm-qt)$",
+ },
+ tag = "+file-manager",
+})
+
+apply_window_rule({
+ name = "tag-file-manager-warp",
+ match = {
+ class = "^(app.drey.Warp)$",
+ },
+ tag = "+file-manager",
+})
+
+apply_window_rule({
+ name = "tag-wallpaper-waytrogen",
+ match = {
+ class = "^([Ww]aytrogen)$",
+ },
+ tag = "+wallpaper",
+})
+
+apply_window_rule({
+ name = "tag-multimedia-audacious",
+ match = {
+ class = "^([Aa]udacious)$",
+ },
+ tag = "+multimedia",
+})
+
+apply_window_rule({
+ name = "tag-multimedia-video-players",
+ match = {
+ class = "^([Mm]pv|vlc)$",
+ },
+ tag = "+multimedia_video",
+})
+
+apply_window_rule({
+ name = "tag-settings-rog-control",
+ match = {
+ title = "^(ROG Control)$",
+ },
+ tag = "+settings",
+})
+
+apply_window_rule({
+ name = "tag-settings-wihotspot",
+ match = {
+ class = "^(wihotspot(-gui)?)$",
+ },
+ tag = "+settings",
+})
+
+apply_window_rule({
+ name = "tag-settings-baobab",
+ match = {
+ class = "^([Bb]aobab|org.gnome.[Bb]aobab)$",
+ },
+ tag = "+settings",
+})
+
+apply_window_rule({
+ name = "tag-settings-disks-and-hotspot",
+ match = {
+ class = "^(gnome-disks|wihotspot(-gui)?)$",
+ },
+ tag = "+settings",
+})
+
+apply_window_rule({
+ name = "tag-settings-kvantum",
+ match = {
+ title = "(Kvantum Manager)",
+ },
+ tag = "+settings",
+})
+
+apply_window_rule({
+ name = "tag-settings-file-roller",
+ match = {
+ class = "^(file-roller|org.gnome.FileRoller)$",
+ },
+ tag = "+settings",
+})
+
+apply_window_rule({
+ name = "tag-settings-network-blueman",
+ match = {
+ class = "^(nm-applet|nm-connection-editor|blueman-manager)$",
+ },
+ tag = "+settings",
+})
+
+apply_window_rule({
+ name = "tag-settings-pavucontrol",
+ match = {
+ class = "^(pavucontrol|org.pulseaudio.pavucontrol|com.saivert.pwvucontrol)$",
+ },
+ tag = "+settings",
+})
+
+apply_window_rule({
+ name = "tag-settings-qtct",
+ match = {
+ class = "^(qt5ct|qt6ct)$",
+ },
+ tag = "+settings",
+})
+
+apply_window_rule({
+ name = "tag-settings-xdg-portal-gtk",
+ match = {
+ class = "(xdg-desktop-portal-gtk)",
+ },
+ tag = "+settings",
+})
+
+apply_window_rule({
+ name = "tag-settings-polkit-kde",
+ match = {
+ class = "^(org.kde.polkit-kde-authentication-agent-1)$",
+ },
+ tag = "+settings",
+})
+
+apply_window_rule({
+ name = "tag-settings-rofi",
+ match = {
+ class = "^([Rr]ofi)$",
+ },
+ tag = "+settings",
+})
+
+apply_window_rule({
+ name = "tag-settings-btrfs-assistant",
+ match = {
+ class = "^(btrfs-assistant)$",
+ },
+ tag = "+settings",
+})
+
+apply_window_rule({
+ name = "tag-settings-timeshift",
+ match = {
+ class = "^(timeshift-gtk)$",
+ },
+ tag = "+settings",
+})
+
+apply_window_rule({
+ name = "tag-viewer-system-monitor",
+ match = {
+ class = "^(gnome-system-monitor|org.gnome.SystemMonitor|io.missioncenter.MissionCenter)$",
+ },
+ tag = "+viewer",
+})
+
+apply_window_rule({
+ name = "tag-viewer-evince",
+ match = {
+ class = "^(evince)$",
+ },
+ tag = "+viewer",
+})
+
+apply_window_rule({
+ name = "tag-viewer-image-viewers",
+ match = {
+ class = "^(eog|org.gnome.Loupe)$",
+ },
+ tag = "+viewer",
+})
+
+apply_window_rule({
+ name = "multimedia-disable-blur",
+ match = {
+ tag = "multimedia",
+ },
+ no_blur = true,
+})
+
+apply_window_rule({
+ name = "multimedia-force-opacity",
+ match = {
+ tag = "multimedia",
+ },
+ opacity = 1.0,
+})
+
+apply_window_rule({
+ name = "float-zoom-onedriver",
+ match = {
+ class = "([Zz]oom|onedriver|onedriver-launcher)",
+ },
+ float = true,
+})
+
+apply_window_rule({
+ name = "float-video-players",
+ match = {
+ class = "^(mpv|com.github.rafostar.Clapper)$",
+ },
+ float = true,
+})
+
+apply_window_rule({
+ name = "float-qalculate",
+ match = {
+ class = "^([Qq]alculate-gtk)$",
+ },
+ float = true,
+})
+
+apply_window_rule({
+ name = "float-center-auth-required-title",
+ match = {
+ title = "^(Authentication Required)$",
+ },
+ float = true,
+ center = true,
+})
+
+apply_window_rule({
+ name = "float-center-polkit-auth-dialog",
+ match = {
+ class = "^(xfce-polkit|mate-polkit|polkit-mate-authentication-agent-1)$",
+ title = "^(Authentication required|Authentication Required)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.35) (monitor_h*0.35)",
+})
+
+apply_window_rule({
+ name = "float-vscodium-secondary-window",
+ match = {
+ class = "(codium|codium-url-handler|VSCodium)",
+ title = "negative:(.*codium.*|.*VSCodium.*)",
+ },
+ float = true,
+})
+
+apply_window_rule({
+ name = "float-heroic-secondary-window",
+ match = {
+ class = "^(com.heroicgameslauncher.hgl)$",
+ title = "negative:(Heroic Games Launcher)",
+ },
+ float = true,
+})
+
+apply_window_rule({
+ name = "float-steam-secondary-window",
+ match = {
+ class = "^([Ss]team)$",
+ title = "negative:^([Ss]team)$",
+ },
+ float = true,
+})
+
+apply_window_rule({
+ name = "float-center-add-folder-dialog",
+ match = {
+ title = "^(Add Folder to Workspace)$",
+ },
+ float = true,
+ size = "(monitor_w*0.7) (monitor_h*0.6)",
+ center = true,
+})
+
+apply_window_rule({
+ name = "float-center-save-as-dialog",
+ match = {
+ title = "^(Save As)$",
+ },
+ float = true,
+ size = "(monitor_w*0.7) (monitor_h*0.6)",
+ center = true,
+})
+
+apply_window_rule({
+ name = "float-open-files-dialog",
+ match = {
+ initial_title = "(Open Files)",
+ },
+ float = true,
+ size = "(monitor_w*0.7) (monitor_h*0.6)",
+})
+
+apply_window_rule({
+ name = "float-center-sddm-background",
+ match = {
+ title = "^(SDDM Background)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.16) (monitor_h*0.12)",
+})
+
+apply_window_rule({
+ name = "float-center-yad-dialog",
+ match = {
+ class = "^(yad)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.2) (monitor_h*0.2)",
+})
+
+apply_window_rule({
+ name = "float-center-hyprland-donate",
+ match = {
+ class = "^(hyprland-donate-screen)$",
+ },
+ float = true,
+ center = true,
+})
+
+apply_window_rule({
+ name = "center-rog-control",
+ match = {
+ title = "^(ROG Control)$",
+ },
+ center = true,
+})
+
+apply_window_rule({
+ name = "center-keybindings",
+ match = {
+ title = "^(Keybindings)$",
+ },
+ center = true,
+})
+
+apply_window_rule({
+ name = "center-pavucontrol",
+ match = {
+ class = "^(pavucontrol|org.pulseaudio.pavucontrol|com.saivert.pwvucontrol)$",
+ },
+ center = true,
+})
+
+apply_window_rule({
+ name = "center-whatsapp",
+ match = {
+ class = "^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$",
+ },
+ center = true,
+})
+
+apply_window_rule({
+ name = "center-network-editor",
+ match = {
+ class = "^(nm-connection-editor)$",
+ },
+ center = true,
+})
+
+apply_window_rule({
+ name = "center-nm-auth-dialog",
+ match = {
+ class = "^(nm-applet)$",
+ title = "^(Wi-Fi Network Authentication Required)$",
+ },
+ center = true,
+})
+
+apply_window_rule({
+ name = "idle-inhibit-fullscreen-bool",
+ match = {
+ fullscreen = true,
+ },
+ idle_inhibit = "fullscreen",
+})
+
+apply_window_rule({
+ name = "idle-inhibit-fullscreen-int",
+ match = {
+ fullscreen = 1,
+ },
+ idle_inhibit = "fullscreen",
+})
+
+apply_window_rule({
+ name = "idle-inhibit-any-class",
+ match = {
+ class = ".*",
+ },
+ idle_inhibit = "fullscreen",
+})
+
+apply_window_rule({
+ name = "idle-inhibit-any-title",
+ match = {
+ title = ".*",
+ },
+ idle_inhibit = "fullscreen",
+})
+
+apply_window_rule({
+ name = "opacity-browser-tag",
+ match = {
+ tag = "browser",
+ },
+ opacity = "0.99 0.8",
+})
+
+apply_window_rule({
+ name = "opacity-projects-tag",
+ match = {
+ tag = "projects",
+ },
+ opacity = "0.9 0.8",
+})
+
+apply_window_rule({
+ name = "opacity-im-tag",
+ match = {
+ tag = "im",
+ },
+ opacity = "0.94 0.86",
+})
+
+apply_window_rule({
+ name = "opacity-multimedia-tag",
+ match = {
+ tag = "multimedia",
+ },
+ opacity = "0.94 0.86",
+})
+
+apply_window_rule({
+ name = "opacity-file-manager-tag",
+ match = {
+ tag = "file-manager",
+ },
+ opacity = "0.9 0.8",
+})
+
+apply_window_rule({
+ name = "opacity-terminal-tag",
+ match = {
+ tag = "terminal",
+ },
+ opacity = "0.9 0.7",
+})
+
+apply_window_rule({
+ name = "opacity-text-editors",
+ match = {
+ class = "^(gedit|org.gnome.TextEditor|mousepad)$",
+ },
+ opacity = "0.8 0.7",
+})
+
+apply_window_rule({
+ name = "opacity-deluge",
+ match = {
+ class = "^(deluge)$",
+ },
+ opacity = "0.9 0.8",
+})
+
+apply_window_rule({
+ name = "opacity-seahorse",
+ match = {
+ class = "^(seahorse)$",
+ },
+ opacity = "0.9 0.8",
+})
+
+apply_window_rule({
+ name = "no-initial-focus-jetbrains",
+ match = {
+ class = "^(jetbrains-.*)$",
+ },
+ no_initial_focus = true,
+})
+
+apply_window_rule({
+ name = "no-initial-focus-wind-title",
+ match = {
+ title = "^(wind.*)$",
+ },
+ no_initial_focus = true,
+})
+
+
+apply_window_rule({
+ name = "Picture-in-Picture",
+ match = {
+ title = "^[Pp]icture-in-[Pp]icture$",
+ },
+ float = true,
+ move = "72% 7%",
+ opacity = "0.95 0.75",
+ pin = true,
+ keep_aspect_ratio = true,
+ size = "(monitor_w*0.3) (monitor_h*0.3)",
+})
+
+apply_window_rule({
+ name = "CachyOS Kernel Manager",
+ match = {
+ class = "^(org.cachyos.KernelManager)$",
+ title = "^(CachyOS Kernel Manager)$",
+ initial_class = "^(org.cachyos.KernelManager)$",
+ initial_title = "^(CachyOS Kernel Manager)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.6) (monitor_h*0.6)",
+})
+
+apply_window_rule({
+ name = "Mainline Kernels",
+ match = {
+ class = "^(mainline-gtk)$",
+ title = "^(Mainline Kernels)$",
+ initial_class = "^(mainline-gtk)$",
+ initial_title = "^(Mainline Kernels)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.45) (monitor_h*0.55)",
+})
+
+apply_window_rule({
+ name = "Kwallet",
+ match = {
+ class = "^(org.kde.kwalletmanager)$",
+ title = "^(Wallet Manager)$",
+ initial_class = "^(org.kde.kwalletmanager)$",
+ initial_title = "^(Wallet Manager)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.6) (monitor_h*0.6)",
+})
+
+apply_window_rule({
+ name = "NVIDIA Settings",
+ match = {
+ class = "^(nvidia-settings)$",
+ title = "^(NVIDIA Settings)$",
+ initial_class = "^(nvidia-settings)$",
+ initial_title = "^(NVIDIA Settings)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.6) (monitor_h*0.6)",
+})
+
+apply_window_rule({
+ name = "CachyOS Package Installer",
+ match = {
+ class = "^(org.cachyos.cachyos-pi)$",
+ title = "^(CachyOS Package Installer)$",
+ initial_class = "^(org.cachyos.cachyos-pi)$",
+ initial_title = "^(CachyOS Package Installer)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.6) (monitor_h*0.6)",
+})
+
+apply_window_rule({
+ name = "Shelly",
+ match = {
+ class = "^(com.shellyorg.shelly)$",
+ title = "^(Shelly)$",
+ initial_class = "^(com.shellyorg.shelly)$",
+ initial_title = "^(Shelly)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.6) (monitor_h*0.6)",
+})
+
+apply_window_rule({
+ name = "CachyOS Hello",
+ match = {
+ class = "^(CachyOSHello)$",
+ title = "^(CachyOS Hello)$",
+ initial_class = "^(CachyOSHello)$",
+ initial_title = "^(CachyOS Hello)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.6) (monitor_h*0.6)",
+})
+
+apply_window_rule({
+ name = "Cache Cleaner - Octopi",
+ match = {
+ class = "^(octopi-cachecleaner)$",
+ title = "^(Cache Cleaner - Octopi)$",
+ initial_class = "^(octopi-cachecleaner)$",
+ initial_title = "^(Cache Cleaner - Octopi)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.6) (monitor_h*0.6)",
+})
+
+apply_window_rule({
+ name = "Octopi Package Manager",
+ match = {
+ class = "^(octopi)$",
+ title = "^(Octopi)$",
+ initial_class = "^(octopi)$",
+ initial_title = "^(Octopi)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.6) (monitor_h*0.6)",
+})
+
+apply_window_rule({
+ name = "Repository Editor - Octopi",
+ match = {
+ class = "^(octopi-repoeditor)$",
+ title = "^(Repository Editor - Octopi)$",
+ initial_class = "^(octopi-repoeditor)$",
+ initial_title = "^(Repository Editor - Octop)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.6) (monitor_h*0.6)",
+})
+
+apply_window_rule({
+ name = "KooL Cheat (tag)",
+ match = {
+ tag = "KooL_Cheat",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.65) (monitor_h*0.9)",
+})
+
+apply_window_rule({
+ name = "Wallpaper (tag)",
+ match = {
+ tag = "wallpaper",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.7) (monitor_h*0.7)",
+ opacity = "0.9 0.7",
+})
+
+apply_window_rule({
+ name = "Settings (tag)",
+ match = {
+ tag = "settings",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.7) (monitor_h*0.7)",
+ opacity = "0.8 0.7",
+})
+
+apply_window_rule({
+ name = "Viewer (tag)",
+ match = {
+ tag = "viewer",
+ },
+ float = true,
+ center = true,
+ opacity = "0.82 0.75",
+})
+
+apply_window_rule({
+ name = "KooL Settings (tag)",
+ match = {
+ tag = "KooL-Settings",
+ },
+ float = true,
+ center = true,
+})
+
+apply_window_rule({
+ name = "Multimedia Video (tag)",
+ match = {
+ tag = "multimedia_video",
+ },
+ no_blur = true,
+ opacity = 1.0,
+})
+
+apply_window_rule({
+ name = "Games (tag)",
+ match = {
+ tag = "games",
+ },
+ no_blur = true,
+ fullscreen = 0,
+})
+
+apply_window_rule({
+ name = "Ferdium",
+ match = {
+ class = "^([Ff]erdium)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.6) (monitor_h*0.7)",
+})
+
+apply_window_rule({
+ name = "Calculators",
+ match = {
+ class = "(org.gnome.Calculator|qalculate-gtk)",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.55) (monitor_h*0.45)",
+})
+
+apply_window_rule({
+ name = "Thunar Dialogs",
+ match = {
+ class = "([Tt]hunar)",
+ title = "negative:(.*[Tt]hunar.*)",
+ },
+ float = true,
+ center = true,
+})
+
+apply_window_rule({
+ name = "Bitwarden",
+ match = {
+ class = "^(Bitwarden)$",
+ title = "^(Bitwarden)$",
+ initial_class = "^(Bitwarden)$",
+ initial_title = "^(Bitwarden)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.6) (monitor_h*0.6)",
+})
+
+apply_window_rule({
+ name = "hyprland audio panel",
+ match = {
+ class = "^(hyprpwcenter)$",
+ title = "^(Pipewire Control Center)$",
+ initial_class = "^(hyprpwcenter)$",
+ initial_title = "^(Pipewire Control Center)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.6) (monitor_h*0.6)",
+})
+
+apply_window_rule({
+ name = "Garuda Assistant",
+ match = {
+ class = "^(garuda-assistant)$",
+ title = "^(Garuda Assistant)$",
+ initial_class = "^(garuda-assistant)$",
+ initial_title = "^(Garuda Assistant)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.6) (monitor_h*0.6)",
+})
+
+apply_window_rule({
+ name = "HyprMod GUI",
+ match = {
+ class = "^(com.github.hyprmod)$",
+ title = "^(HyprMod)$",
+ initial_class = "^(com.github.hyprmod)$",
+ initial_title = "^(HyprMod)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.7) (monitor_h*0.75)",
+})
+
+apply_window_rule({
+ name = "EasyEffects",
+ match = {
+ class = "^(com.github.wwmm.easyeffects)$",
+ title = "^(Easy Effects)$",
+ initial_class = "^(com.github.wwmm.easyeffects)$",
+ initial_title = "^(Easy Effects)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.6) (monitor_h*0.65)",
+})
+apply_window_rule({
+ name = "Megasync",
+ match = {
+ class = "^(nz\\.co\\.mega\\.megasync)$",
+ initial_class = "^(nz\\.co\\.mega\\.megasync)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.1) (monitor_h*0.2)",
+})
+
+apply_window_rule({
+ name = "Mousam Weather",
+ match = {
+ class = "^(io.github.amit9838.mousam)$",
+ title = "^(Mousam)$",
+ initial_class = "^(io.github.amit9838.mousam)$",
+ initial_title = "^(Mousam)$",
+ },
+ float = true,
+ center = true,
+ size = "(monitor_w*0.7) (monitor_h*0.75)",
+})
+
+-- Lua-only rule: keep the dropterminal positioned when toggled by keybind.
+apply_window_rule({
+ name = "dropterminal",
+ match = {
+ class = "kitty-dropterm",
+ },
+ float = true,
+})
diff --git a/config/hypr/lua/workspaces.lua b/config/hypr/lua/workspaces.lua
new file mode 100644
index 00000000..287326ca
--- /dev/null
+++ b/config/hypr/lua/workspaces.lua
@@ -0,0 +1,12 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
+-- Converted from config/hypr/workspaces.conf.
+-- No active workspace rules are currently enabled in the source file.
+
+-- Example:
+-- hl.workspace_rule({ workspace = "1", monitor = "eDP-1" })
diff --git a/config/hypr/scripts/ChangeLayout.sh b/config/hypr/scripts/ChangeLayout.sh
index f9f6b52b..3c81bcbe 100755
--- a/config/hypr/scripts/ChangeLayout.sh
+++ b/config/hypr/scripts/ChangeLayout.sh
@@ -10,11 +10,31 @@
notif="$HOME/.config/swaync/images/ja.png"
layouts=(master dwindle scrolling monocle)
+quiet_mode=0
get_layout() {
hyprctl -j getoption general:layout | jq -r '.str'
}
+set_hypr_layout() {
+ local target="$1"
+ local output
+
+ output="$(hyprctl keyword general:layout "$target" 2>&1)"
+ if grep -q "keyword can't work with non-legacy parsers" <<<"$output"; then
+ output="$(hyprctl eval "hl.config({ general = { layout = \"${target}\" } })" 2>&1)"
+ fi
+
+ if ! grep -q "^ok$" <<<"$output"; then
+ echo "$output" >&2
+ return 1
+ fi
+}
+
+hypr_keyword() {
+ hyprctl keyword "$@" >/dev/null 2>&1 || true
+}
+
next_layout() {
local current="$1"
local i
@@ -30,66 +50,78 @@ next_layout() {
set_layout() {
local target="$1"
- hyprctl keyword general:layout "$target"
- hyprctl keyword unbind SUPER,j
- hyprctl keyword unbind SUPER,k
- hyprctl keyword unbind SUPER,left
- hyprctl keyword unbind SUPER,right
- hyprctl keyword unbind SUPER,up
- hyprctl keyword unbind SUPER,down
- hyprctl keyword unbind SUPER,O
+ if ! set_hypr_layout "$target"; then
+ if [[ "$quiet_mode" -eq 0 ]]; then
+ notify-send -e -u critical -i "$notif" " Layout switch failed: $target"
+ fi
+ return 1
+ fi
+
+ hypr_keyword unbind SUPER,j
+ hypr_keyword unbind SUPER,k
+ hypr_keyword bind SUPER,j,cyclenext
+ hypr_keyword bind SUPER,k,cyclenext,prev
+ hypr_keyword unbind SUPER,left
+ hypr_keyword unbind SUPER,right
+ hypr_keyword unbind SUPER,up
+ hypr_keyword unbind SUPER,down
+ hypr_keyword unbind SUPER,O
case "$target" in
"dwindle")
- hyprctl keyword bind SUPER,j,cyclenext
- hyprctl keyword bind SUPER,k,cyclenext,prev
- hyprctl keyword bind SUPER,left,cyclenext,prev
- hyprctl keyword bind SUPER,up,cyclenext,prev
- hyprctl keyword bind SUPER,right,cyclenext
- hyprctl keyword bind SUPER,down,cyclenext
- hyprctl keyword bind SUPER,O,layoutmsg,togglesplit
- notify-send -e -u low -i "$notif" " Dwindle Layout"
+ hypr_keyword bind SUPER,left,cyclenext,prev
+ hypr_keyword bind SUPER,up,cyclenext,prev
+ hypr_keyword bind SUPER,right,cyclenext
+ hypr_keyword bind SUPER,down,cyclenext
+ hypr_keyword bind SUPER,O,layoutmsg,togglesplit
;;
"scrolling")
- hyprctl keyword bind SUPER,j,cyclenext
- hyprctl keyword bind SUPER,k,cyclenext,prev
- hyprctl keyword bind SUPER,left,cyclenext,prev
- hyprctl keyword bind SUPER,up,cyclenext,prev
- hyprctl keyword bind SUPER,right,cyclenext
- hyprctl keyword bind SUPER,down,cyclenext
- notify-send -e -u low -i "$notif" " Scrolling Layout"
+ hypr_keyword bind SUPER,left,cyclenext,prev
+ hypr_keyword bind SUPER,up,cyclenext,prev
+ hypr_keyword bind SUPER,right,cyclenext
+ hypr_keyword bind SUPER,down,cyclenext
;;
"monocle")
- hyprctl keyword bind SUPER,j,layoutmsg,cyclenext
- hyprctl keyword bind SUPER,k,layoutmsg,cycleprev
- hyprctl keyword bind SUPER,left,layoutmsg,cycleprev
- hyprctl keyword bind SUPER,up,layoutmsg,cycleprev
- hyprctl keyword bind SUPER,right,layoutmsg,cyclenext
- hyprctl keyword bind SUPER,down,layoutmsg,cyclenext
- notify-send -e -u low -i "$notif" " Monocle Layout"
+ hypr_keyword bind SUPER,left,layoutmsg,cycleprev
+ hypr_keyword bind SUPER,up,layoutmsg,cycleprev
+ hypr_keyword bind SUPER,right,layoutmsg,cyclenext
+ hypr_keyword bind SUPER,down,layoutmsg,cyclenext
;;
"master")
- hyprctl keyword bind SUPER,j,layoutmsg,cyclenext
- hyprctl keyword bind SUPER,k,layoutmsg,cycleprev
- hyprctl keyword bind SUPER,left,movefocus,l
- hyprctl keyword bind SUPER,right,movefocus,r
- hyprctl keyword bind SUPER,up,movefocus,u
- hyprctl keyword bind SUPER,down,movefocus,d
- notify-send -e -u low -i "$notif" " Master Layout"
+ hypr_keyword bind SUPER,left,movefocus,l
+ hypr_keyword bind SUPER,right,movefocus,r
+ hypr_keyword bind SUPER,up,movefocus,u
+ hypr_keyword bind SUPER,down,movefocus,d
;;
*)
- hyprctl keyword bind SUPER,j,layoutmsg,cyclenext
- hyprctl keyword bind SUPER,k,layoutmsg,cycleprev
- hyprctl keyword bind SUPER,left,movefocus,l
- hyprctl keyword bind SUPER,right,movefocus,r
- hyprctl keyword bind SUPER,up,movefocus,u
- hyprctl keyword bind SUPER,down,movefocus,d
+ hypr_keyword bind SUPER,left,movefocus,l
+ hypr_keyword bind SUPER,right,movefocus,r
+ hypr_keyword bind SUPER,up,movefocus,u
+ hypr_keyword bind SUPER,down,movefocus,d
echo "Unknown layout: $target" >&2
return 1
;;
esac
+
+ local actual
+ actual="$(get_layout)"
+ if [[ "$actual" == "$target" ]]; then
+ if [[ "$quiet_mode" -eq 0 ]]; then
+ notify-send -e -u low -i "$notif" " ${actual^} Layout"
+ fi
+ else
+ if [[ "$quiet_mode" -eq 0 ]]; then
+ notify-send -e -u critical -i "$notif" " Layout switch failed: still ${actual}"
+ fi
+ return 1
+ fi
}
+if [[ "${1:-}" == "--quiet" || "${1:-}" == "--no-notify" ]]; then
+ quiet_mode=1
+ shift
+fi
+
current="$(get_layout)"
arg="${1:-toggle}"
@@ -104,7 +136,7 @@ master|dwindle|scrolling|monocle)
set_layout "$arg"
;;
*)
- echo "Usage: $(basename "$0") [toggle|next|init|master|dwindle|scrolling|monocle]" >&2
+ echo "Usage: $(basename "$0") [--quiet|--no-notify] [toggle|next|init|master|dwindle|scrolling|monocle]" >&2
exit 1
;;
esac
diff --git a/config/hypr/scripts/DisableWaybarService.sh b/config/hypr/scripts/DisableWaybarService.sh
new file mode 100755
index 00000000..7750fe4a
--- /dev/null
+++ b/config/hypr/scripts/DisableWaybarService.sh
@@ -0,0 +1,265 @@
+#!/usr/bin/env bash
+set -u
+set -o pipefail
+
+SERVICE_NAME="waybar.service"
+ACTION=""
+DRY_RUN=false
+OPERATION_RESULT="not-run"
+
+RED="\033[0;31m"
+GREEN="\033[0;32m"
+YELLOW="\033[1;33m"
+BLUE="\033[0;34m"
+NC="\033[0m"
+
+ICON_OK="✅"
+ICON_WARN="⚠️"
+ICON_ERR="❌"
+ICON_INFO="ℹ️"
+
+usage() {
+ cat <<EOF
+Usage: $(basename "$0") [OPTIONS]
+
+Disable --user ${SERVICE_NAME} (default action), revert it, or check status.
+
+Options:
+ -h, --help Show this help message and exit
+ -r, --revert Revert by enabling + starting --user ${SERVICE_NAME}
+ -d, --dry-run Print actions without changing anything
+ -s, --status Show current status of --user ${SERVICE_NAME}
+EOF
+}
+
+info() {
+ printf "${BLUE}${ICON_INFO} %s${NC}\n" "$1"
+}
+
+ok() {
+ printf "${GREEN}${ICON_OK} %s${NC}\n" "$1"
+}
+
+warn() {
+ printf "${YELLOW}${ICON_WARN} %s${NC}\n" "$1"
+}
+
+error() {
+ printf "${RED}${ICON_ERR} %s${NC}\n" "$1" >&2
+}
+
+fail() {
+ error "$1"
+ exit 1
+}
+
+format_command() {
+ printf "%q " "$@"
+}
+
+run_cmd() {
+ if $DRY_RUN; then
+ info "[dry-run] $(format_command "$@")"
+ return 0
+ fi
+ "$@"
+}
+
+set_action() {
+ local new_action="$1"
+ if [[ -n "$ACTION" && "$ACTION" != "$new_action" ]]; then
+ fail "Conflicting options: cannot combine '${ACTION}' with '${new_action}'."
+ fi
+ ACTION="$new_action"
+}
+
+require_systemctl() {
+ command -v systemctl >/dev/null 2>&1 || fail "systemctl is required but was not found."
+}
+
+require_user_manager() {
+ if ! systemctl --user show-environment >/dev/null 2>&1; then
+ fail "Cannot contact systemd user manager. Ensure your user systemd session is running."
+ fi
+}
+
+service_load_state() {
+ systemctl --user show --property=LoadState --value "${SERVICE_NAME}" 2>/dev/null || true
+}
+
+service_exists() {
+ local load_state
+ load_state="$(service_load_state)"
+ [[ -n "${load_state}" && "${load_state}" != "not-found" ]]
+}
+
+require_service_exists() {
+ if ! service_exists; then
+ fail "--user ${SERVICE_NAME} was not found. Exiting."
+ fi
+}
+
+get_enabled_state() {
+ local state
+ state="$(systemctl --user is-enabled "${SERVICE_NAME}" 2>/dev/null || true)"
+ [[ -n "${state}" ]] || state="unknown"
+ printf "%s" "${state}"
+}
+
+get_active_state() {
+ local state
+ state="$(systemctl --user is-active "${SERVICE_NAME}" 2>/dev/null || true)"
+ [[ -n "${state}" ]] || state="unknown"
+ printf "%s" "${state}"
+}
+
+print_state_line() {
+ local label="$1"
+ local state="$2"
+ local color="${BLUE}"
+ local icon="${ICON_INFO}"
+
+ case "${state}" in
+ loaded|enabled|active)
+ color="${GREEN}"
+ icon="${ICON_OK}"
+ ;;
+ activating|deactivating|reloading|inactive|disabled|static|indirect|masked)
+ color="${YELLOW}"
+ icon="${ICON_WARN}"
+ ;;
+ failed|not-found|unknown)
+ color="${RED}"
+ icon="${ICON_ERR}"
+ ;;
+ esac
+
+ printf " %-9s: %b%s %s%b\n" "${label}" "${color}" "${icon}" "${state}" "${NC}"
+}
+
+print_report() {
+ local load_state enabled_state active_state dry_run_state result_color result_icon result_text
+
+ load_state="$(service_load_state)"
+ [[ -n "${load_state}" ]] || load_state="unknown"
+ enabled_state="$(get_enabled_state)"
+ active_state="$(get_active_state)"
+ dry_run_state="no"
+ $DRY_RUN && dry_run_state="yes"
+
+ case "${OPERATION_RESULT}" in
+ success)
+ result_color="${GREEN}"
+ result_icon="${ICON_OK}"
+ result_text="success"
+ ;;
+ dry-run)
+ result_color="${YELLOW}"
+ result_icon="${ICON_WARN}"
+ result_text="dry-run"
+ ;;
+ failed)
+ result_color="${RED}"
+ result_icon="${ICON_ERR}"
+ result_text="failed"
+ ;;
+ *)
+ result_color="${BLUE}"
+ result_icon="${ICON_INFO}"
+ result_text="not-run"
+ ;;
+ esac
+
+ printf "\n${BLUE}${ICON_INFO} Report for --user %s${NC}\n" "${SERVICE_NAME}"
+ print_state_line "LoadState" "${load_state}"
+ print_state_line "Enabled" "${enabled_state}"
+ print_state_line "Active" "${active_state}"
+ printf " %-9s: %s\n" "Dry-run" "${dry_run_state}"
+ printf " %-9s: %b%s %s%b\n" "Result" "${result_color}" "${result_icon}" "${result_text}" "${NC}"
+}
+
+perform_disable() {
+ info "Disabling and stopping --user ${SERVICE_NAME}..."
+ if run_cmd systemctl --user disable --now "${SERVICE_NAME}"; then
+ if $DRY_RUN; then
+ OPERATION_RESULT="dry-run"
+ warn "Dry-run complete. No changes were made."
+ else
+ OPERATION_RESULT="success"
+ ok "Disabled and stopped --user ${SERVICE_NAME}."
+ fi
+ return 0
+ fi
+
+ OPERATION_RESULT="failed"
+ error "Failed to disable --user ${SERVICE_NAME}."
+ return 1
+}
+
+perform_revert() {
+ info "Reverting --user ${SERVICE_NAME} (unmask + enable + start)..."
+ if ! run_cmd systemctl --user unmask "${SERVICE_NAME}"; then
+ OPERATION_RESULT="failed"
+ error "Failed to unmask --user ${SERVICE_NAME}."
+ return 1
+ fi
+ if ! run_cmd systemctl --user enable --now "${SERVICE_NAME}"; then
+ OPERATION_RESULT="failed"
+ error "Failed to enable/start --user ${SERVICE_NAME}."
+ return 1
+ fi
+
+ if $DRY_RUN; then
+ OPERATION_RESULT="dry-run"
+ warn "Dry-run complete. No changes were made."
+ else
+ OPERATION_RESULT="success"
+ ok "Reverted successfully. --user ${SERVICE_NAME} is enabled and started."
+ fi
+ return 0
+}
+
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ -r|--revert)
+ set_action "revert"
+ ;;
+ -d|--dry-run)
+ DRY_RUN=true
+ ;;
+ -s|--status)
+ set_action "status"
+ ;;
+ *)
+ fail "Unknown option: $1 (use -h or --help)"
+ ;;
+ esac
+ shift
+done
+
+[[ -n "${ACTION}" ]] || ACTION="disable"
+
+require_systemctl
+require_user_manager
+require_service_exists
+
+exit_code=0
+case "${ACTION}" in
+ disable)
+ perform_disable || exit_code=1
+ ;;
+ revert)
+ perform_revert || exit_code=1
+ ;;
+ status)
+ OPERATION_RESULT="success"
+ info "Status requested for --user ${SERVICE_NAME}."
+ ;;
+esac
+
+print_report
+exit "${exit_code}" \ No newline at end of file
diff --git a/config/hypr/scripts/Dropterminal.sh b/config/hypr/scripts/Dropterminal.sh
index 81c0f157..21349d4a 100755
--- a/config/hypr/scripts/Dropterminal.sh
+++ b/config/hypr/scripts/Dropterminal.sh
@@ -24,6 +24,106 @@ LOCK_FILE="/tmp/dropdown_terminal_lock"
LAST_TOGGLE_FILE="/tmp/dropdown_terminal_last_toggle"
MIN_TOGGLE_INTERVAL_MS=250
DROPDOWN_KITTY_CLASS="kitty-dropterm"
+CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
+HYPR_DIR="$CONFIG_HOME/hypr"
+LUA_ENTRY="$HYPR_DIR/hyprland.lua"
+LEGACY_LUA_ENTRY="$CONFIG_HOME/hyprland.lua"
+
+if [[ -f "$LUA_ENTRY" || -f "$LEGACY_LUA_ENTRY" ]]; then
+ HYPR_CONFIG_MODE="lua"
+else
+ HYPR_CONFIG_MODE="conf"
+fi
+lua_escape() {
+ local value="$1"
+ value=${value//\\/\\\\}
+ value=${value//\"/\\\"}
+ value=${value//$'\n'/\\n}
+ printf '%s' "$value"
+}
+
+
+hypr_dispatch() {
+ local dispatcher="$1"
+ shift
+ local payload="$*"
+ if [[ "$HYPR_CONFIG_MODE" == "lua" ]]; then
+ local command="$dispatcher"
+ if [ -n "$payload" ]; then
+ command="$dispatcher $payload"
+ fi
+ local escaped
+ escaped="$(lua_escape "$command")"
+ hyprctl dispatch "hl.dsp.exec_raw(\"$escaped\")"
+ else
+ hyprctl dispatch "$dispatcher" "$payload"
+ fi
+}
+
+hypr_exec_cmd() {
+ local command="$*"
+ if [[ "$HYPR_CONFIG_MODE" == "lua" ]]; then
+ local escaped
+ escaped="$(lua_escape "$command")"
+ hyprctl dispatch "hl.dsp.exec_cmd(\"$escaped\")"
+ else
+ hyprctl dispatch exec "$command"
+ fi
+}
+
+lua_workspace_expr() {
+ local workspace="$1"
+ if [[ "$workspace" =~ ^-?[0-9]+$ ]]; then
+ printf '%s' "$workspace"
+ else
+ local escaped
+ escaped="$(lua_escape "$workspace")"
+ printf '"%s"' "$escaped"
+ fi
+}
+
+focus_window() {
+ local addr="$1"
+ if [[ "$HYPR_CONFIG_MODE" == "lua" ]]; then
+ local selector escaped
+ selector="address:$addr"
+ escaped="$(lua_escape "$selector")"
+ hyprctl dispatch "hl.dsp.focus({ window = \"$escaped\" })"
+ else
+ hypr_dispatch focuswindow "address:$addr"
+ fi
+}
+
+set_window_floating() {
+ local addr="$1"
+ if [[ "$HYPR_CONFIG_MODE" == "lua" ]]; then
+ hyprctl dispatch "hl.dsp.window.float({ window = 'address:$addr', action = 'on' })"
+ else
+ hypr_dispatch setfloating "address:$addr"
+ fi
+}
+
+resize_window_exact() {
+ local addr="$1"
+ local width="$2"
+ local height="$3"
+ if [[ "$HYPR_CONFIG_MODE" == "lua" ]]; then
+ hyprctl dispatch "hl.dsp.window.resize({ window = 'address:$addr', x = $width, y = $height, exact = true })"
+ else
+ hypr_dispatch resizewindowpixel "exact $width $height,address:$addr"
+ fi
+}
+
+move_window_exact() {
+ local addr="$1"
+ local x="$2"
+ local y="$3"
+ if [[ "$HYPR_CONFIG_MODE" == "lua" ]]; then
+ hyprctl dispatch "hl.dsp.window.move({ window = 'address:$addr', x = $x, y = $y, exact = true })"
+ else
+ hypr_dispatch movewindowpixel "exact $x $y,address:$addr"
+ fi
+}
# Dropdown size and position configuration (percentages)
WIDTH_PERCENT=65 # Width as percentage of screen width
@@ -31,19 +131,42 @@ HEIGHT_PERCENT=65 # Height as percentage of screen height
Y_PERCENT=10 # Y position as percentage from top (X is auto-centered)
# Animation settings
-ANIMATION_DURATION=100 # milliseconds
-SLIDE_STEPS=5
-SLIDE_DELAY=5 # milliseconds between steps
+ANIMATION_DURATION=220 # total animation time in milliseconds
+SLIDE_STEPS=12
+SLIDE_DELAY=$((ANIMATION_DURATION / SLIDE_STEPS))
+if [ "$SLIDE_DELAY" -lt 8 ]; then
+ SLIDE_DELAY=8
+fi
# Parse arguments
-if [ "$1" = "-d" ]; then
- DEBUG=true
- shift
-fi
+STARTUP_MODE=false
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -d | --debug)
+ DEBUG=true
+ shift
+ ;;
+ --startup | --init)
+ STARTUP_MODE=true
+ shift
+ ;;
+ -h | --help)
+ echo "Usage: $0 [-d|--debug] [--startup|--init] <terminal_command>"
+ echo "Examples:"
+ echo " $0 kitty"
+ echo " $0 --startup kitty"
+ echo " $0 -d \"kitty -e zsh\""
+ exit 0
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
-TERMINAL_CMD="$1"
+TERMINAL_CMD="$*"
if [[ "$TERMINAL_CMD" == kitty* ]] && [[ "$TERMINAL_CMD" != *"--class"* ]] && [[ "$TERMINAL_CMD" != *"--name"* ]] && [[ "$TERMINAL_CMD" != *"--app-id"* ]]; then
- TERMINAL_CMD="$TERMINAL_CMD --class $DROPDOWN_KITTY_CLASS"
+ TERMINAL_CMD="$TERMINAL_CMD --class $DROPDOWN_KITTY_CLASS --app-id $DROPDOWN_KITTY_CLASS"
fi
# Ensure only one instance runs at a time (prevents overlapping animations)
@@ -51,25 +174,27 @@ exec 9>"$LOCK_FILE"
flock -n 9 || exit 0
# Debounce rapid toggles
-now_ms=""
-if date +%s%3N >/dev/null 2>&1; then
- now_ms=$(date +%s%3N)
-else
- now_ms=$(( $(date +%s) * 1000 ))
-fi
-if [ -f "$LAST_TOGGLE_FILE" ]; then
- last_ms=$(cat "$LAST_TOGGLE_FILE" 2>/dev/null || echo 0)
- if [ -n "$last_ms" ] && [ "$last_ms" -ge 0 ] 2>/dev/null; then
- delta_ms=$((now_ms - last_ms))
- if [ "$delta_ms" -lt "$MIN_TOGGLE_INTERVAL_MS" ] 2>/dev/null; then
- if [ "$DEBUG" = true ]; then
- echo "Toggle debounced (${delta_ms}ms < ${MIN_TOGGLE_INTERVAL_MS}ms)" >&2
+if [ "$STARTUP_MODE" != true ]; then
+ now_ms=""
+ if date +%s%3N >/dev/null 2>&1; then
+ now_ms=$(date +%s%3N)
+ else
+ now_ms=$(( $(date +%s) * 1000 ))
+ fi
+ if [ -f "$LAST_TOGGLE_FILE" ]; then
+ last_ms=$(cat "$LAST_TOGGLE_FILE" 2>/dev/null || echo 0)
+ if [ -n "$last_ms" ] && [ "$last_ms" -ge 0 ] 2>/dev/null; then
+ delta_ms=$((now_ms - last_ms))
+ if [ "$delta_ms" -lt "$MIN_TOGGLE_INTERVAL_MS" ] 2>/dev/null; then
+ if [ "$DEBUG" = true ]; then
+ echo "Toggle debounced (${delta_ms}ms < ${MIN_TOGGLE_INTERVAL_MS}ms)" >&2
+ fi
+ exit 0
fi
- exit 0
fi
fi
+ echo "$now_ms" >"$LAST_TOGGLE_FILE"
fi
-echo "$now_ms" >"$LAST_TOGGLE_FILE"
# Debug echo function
debug_echo() {
@@ -103,10 +228,11 @@ resolve_terminal_address() {
# Validate input
if [ -z "$TERMINAL_CMD" ]; then
- echo "Missing terminal command. Usage: $0 [-d] <terminal_command>"
+ echo "Missing terminal command. Usage: $0 [-d|--debug] [--startup|--init] <terminal_command>"
echo "Examples:"
- echo " $0 foot"
- echo " $0 -d foot (with debug output)"
+ echo " $0 kitty"
+ echo " $0 --startup kitty"
+ echo " $0 -d kitty (with debug output)"
echo " $0 'kitty -e zsh'"
echo " $0 'alacritty --working-directory /home/user'"
echo ""
@@ -127,14 +253,57 @@ get_window_geometry() {
# Function to check if window is currently hidden off-screen
window_is_hidden() {
local addr="$1"
- local y
- y=$(hyprctl clients -j 2>/dev/null | jq -r --arg ADDR "$addr" '.[] | select(.address == $ADDR) | .at[1]' 2>/dev/null)
- if [[ "$y" =~ ^-?[0-9]+$ ]] && [ "$y" -lt 0 ]; then
+ local geometry y height monitor_id monitor_y
+ geometry=$(hyprctl clients -j 2>/dev/null | jq -r --arg ADDR "$addr" '.[] | select(.address == $ADDR) | "\(.at[1]) \(.size[1]) \(.monitor)"' 2>/dev/null)
+ y=$(echo "$geometry" | awk '{print $1}')
+ height=$(echo "$geometry" | awk '{print $2}')
+ monitor_id=$(echo "$geometry" | awk '{print $3}')
+
+ if ! [[ "$y" =~ ^-?[0-9]+$ && "$height" =~ ^[0-9]+$ ]]; then
+ return 1
+ fi
+
+ if [[ "$monitor_id" =~ ^-?[0-9]+$ ]]; then
+ monitor_y=$(hyprctl monitors -j 2>/dev/null | jq -r --argjson MID "$monitor_id" '.[] | select(.id == $MID) | .y' 2>/dev/null | head -1)
+ fi
+ if ! [[ "$monitor_y" =~ ^-?[0-9]+$ ]]; then
+ monitor_y=0
+ fi
+
+ if [ $((y + height)) -le "$monitor_y" ]; then
return 0
fi
return 1
}
+get_window_monitor_top() {
+ local addr="$1"
+ local monitor_id monitor_y
+ monitor_id=$(hyprctl clients -j 2>/dev/null | jq -r --arg ADDR "$addr" '.[] | select(.address == $ADDR) | .monitor' 2>/dev/null | head -1)
+ if [[ "$monitor_id" =~ ^-?[0-9]+$ ]]; then
+ monitor_y=$(hyprctl monitors -j 2>/dev/null | jq -r --argjson MID "$monitor_id" '.[] | select(.id == $MID) | .y' 2>/dev/null | head -1)
+ if [[ "$monitor_y" =~ ^-?[0-9]+$ ]]; then
+ echo "$monitor_y"
+ return 0
+ fi
+ fi
+ echo 0
+}
+
+get_hidden_y_for_window() {
+ local addr="$1"
+ local height="$2"
+ local monitor_top
+ if ! [[ "$height" =~ ^[0-9]+$ ]]; then
+ height=702
+ fi
+ monitor_top=$(get_window_monitor_top "$addr")
+ if ! [[ "$monitor_top" =~ ^-?[0-9]+$ ]]; then
+ monitor_top=0
+ fi
+ echo $((monitor_top - height - 80))
+}
+
# State helpers
get_hidden_state() {
if [ -f "$STATE_FILE" ]; then
@@ -146,6 +315,15 @@ set_hidden_state() {
echo "$1" >"$STATE_FILE"
}
+sleep_ms() {
+ local ms="$1"
+ if command -v awk >/dev/null 2>&1; then
+ sleep "$(awk -v value="$ms" 'BEGIN { printf "%.3f", value / 1000 }')"
+ else
+ sleep 0.01
+ fi
+}
+
# Function to animate window slide down (show)
animate_slide_down() {
local addr="$1"
@@ -153,28 +331,28 @@ animate_slide_down() {
local target_y="$3"
local width="$4"
local height="$5"
+ local start_y="$6"
debug_echo "Animating slide down for window $addr to position $target_x,$target_y"
- # Start position (above screen)
- local start_y=$((target_y - height - 50))
-
- # Calculate step size
- local step_y=$(((target_y - start_y) / SLIDE_STEPS))
+ if ! [[ "$start_y" =~ ^-?[0-9]+$ ]]; then
+ start_y=$((target_y - height - 50))
+ fi
+ local total_delta=$((target_y - start_y))
# Move window to start position instantly (off-screen)
- hyprctl dispatch movewindowpixel "exact $target_x $start_y,address:$addr" >/dev/null 2>&1
- sleep 0.05
+ move_window_exact "$addr" "$target_x" "$start_y" >/dev/null 2>&1 || return 1
+ sleep_ms "$SLIDE_DELAY"
# Animate slide down
for i in $(seq 1 $SLIDE_STEPS); do
- local current_y=$((start_y + (step_y * i)))
- hyprctl dispatch movewindowpixel "exact $target_x $current_y,address:$addr" >/dev/null 2>&1
- sleep 0.03
+ local current_y=$((start_y + (total_delta * i / SLIDE_STEPS)))
+ move_window_exact "$addr" "$target_x" "$current_y" >/dev/null 2>&1 || return 1
+ sleep_ms "$SLIDE_DELAY"
done
# Ensure final position is exact
- hyprctl dispatch movewindowpixel "exact $target_x $target_y,address:$addr" >/dev/null 2>&1
+ move_window_exact "$addr" "$target_x" "$target_y" >/dev/null 2>&1
}
# Function to animate window slide up (hide)
@@ -184,21 +362,22 @@ animate_slide_up() {
local start_y="$3"
local width="$4"
local height="$5"
+ local end_y="$6"
debug_echo "Animating slide up for window $addr from position $start_x,$start_y"
- # End position (above screen)
- local end_y=$((start_y - height - 50))
-
- # Calculate step size
- local step_y=$(((start_y - end_y) / SLIDE_STEPS))
+ if ! [[ "$end_y" =~ ^-?[0-9]+$ ]]; then
+ end_y=$((start_y - height - 50))
+ fi
+ local total_delta=$((start_y - end_y))
# Animate slide up
for i in $(seq 1 $SLIDE_STEPS); do
- local current_y=$((start_y - (step_y * i)))
- hyprctl dispatch movewindowpixel "exact $start_x $current_y,address:$addr" >/dev/null 2>&1
- sleep 0.03
+ local current_y=$((start_y - (total_delta * i / SLIDE_STEPS)))
+ move_window_exact "$addr" "$start_x" "$current_y" >/dev/null 2>&1 || return 1
+ sleep_ms "$SLIDE_DELAY"
done
+ move_window_exact "$addr" "$start_x" "$end_y" >/dev/null 2>&1
debug_echo "Slide up animation completed"
}
@@ -312,8 +491,9 @@ calculate_dropdown_position() {
echo "$final_x $final_y $width $height $mon_name"
}
-# Get the current workspace
-CURRENT_WS=$(hyprctl activeworkspace -j | jq -r '.id')
+get_current_workspace() {
+ hyprctl activeworkspace -j 2>/dev/null | jq -r '.id // empty'
+}
# Function to get stored terminal address
get_terminal_address() {
@@ -325,7 +505,7 @@ get_terminal_address() {
# Try to find an existing dropdown terminal by class (kitty only)
find_terminal_by_class() {
hyprctl clients -j 2>/dev/null | jq -r --arg CLASS "$DROPDOWN_KITTY_CLASS" \
- '.[] | select(.class == $CLASS) | .address' | head -1
+ '.[] | select((.class == $CLASS) or (.initialClass == $CLASS)) | .address' | head -1
}
# Function to get stored monitor name
@@ -356,29 +536,197 @@ window_exists() {
}
-# Function to check if window is pinned
-window_is_pinned() {
+window_workspace_name() {
local addr="$1"
- if [ -n "$addr" ]; then
- hyprctl clients -j 2>/dev/null | jq -e --arg ADDR "$addr" '.[] | select(.address == $ADDR) | .pinned == true' >/dev/null 2>&1
+ hyprctl clients -j 2>/dev/null | jq -r --arg ADDR "$addr" '.[] | select(.address == $ADDR) | .workspace.name // empty'
+}
+
+window_is_on_special_workspace() {
+ local addr="$1"
+ local workspace_name
+ workspace_name=$(window_workspace_name "$addr")
+ [ "$workspace_name" = "$SPECIAL_WS" ] || [ "$workspace_name" = "$SPECIAL_NAME" ]
+}
+
+workspace_matches_target() {
+ local target_ws="$1"
+ local current_ws="$2"
+ if [ "$target_ws" = "$SPECIAL_WS" ] || [ "$target_ws" = "$SPECIAL_NAME" ]; then
+ [ "$current_ws" = "$SPECIAL_WS" ] || [ "$current_ws" = "$SPECIAL_NAME" ]
else
+ [ "$current_ws" = "$target_ws" ]
+ fi
+}
+
+move_window_to_workspace_silent() {
+ local target_ws="$1"
+ local addr="$2"
+ local post_ws=""
+
+ if [[ "$HYPR_CONFIG_MODE" == "lua" ]]; then
+ local ws_expr
+ ws_expr=$(lua_workspace_expr "$target_ws")
+ hyprctl dispatch "hl.dsp.window.move({ window = 'address:$addr', workspace = $ws_expr, follow = false })" >/dev/null 2>&1 || return 1
+ sleep 0.03
+ post_ws=$(window_workspace_name "$addr")
+ workspace_matches_target "$target_ws" "$post_ws"
+ return $?
+ fi
+
+ # Preferred syntax on newer Hyprland builds (target a specific window by selector).
+ if hypr_dispatch movetoworkspacesilent "$target_ws,address:$addr" >/dev/null 2>&1; then
+ sleep 0.03
+ post_ws=$(window_workspace_name "$addr")
+ if workspace_matches_target "$target_ws" "$post_ws"; then
+ return 0
+ fi
+ fi
+
+ # Compatibility fallback for builds where selector syntax is ignored.
+ hypr_dispatch focuswindow "address:$addr" >/dev/null 2>&1 || return 1
+ hypr_dispatch movetoworkspacesilent "$target_ws" >/dev/null 2>&1 || return 1
+ sleep 0.03
+ post_ws=$(window_workspace_name "$addr")
+ workspace_matches_target "$target_ws" "$post_ws"
+}
+
+infer_hidden_state() {
+ local addr="$1"
+ if window_is_hidden "$addr"; then
+ echo "hidden"
+ elif window_is_on_special_workspace "$addr"; then
+ echo "hidden"
+ else
+ echo "shown"
+ fi
+}
+
+apply_dropdown_layout() {
+ local addr="$1"
+ local pos_info
+ pos_info=$(calculate_dropdown_position)
+ if [ $? -ne 0 ]; then
+ debug_echo "Warning: Failed to calculate dropdown position, layout update skipped"
return 1
fi
+
+ local target_x=$(echo "$pos_info" | cut -d' ' -f1)
+ local target_y=$(echo "$pos_info" | cut -d' ' -f2)
+ local width=$(echo "$pos_info" | cut -d' ' -f3)
+ local height=$(echo "$pos_info" | cut -d' ' -f4)
+ set_window_floating "$addr" >/dev/null 2>&1
+ resize_window_exact "$addr" "$width" "$height" >/dev/null 2>&1
+ move_window_exact "$addr" "$target_x" "$target_y" >/dev/null 2>&1
+ return 0
}
-# Ensure pin state without toggling unexpectedly
-ensure_pinned() {
+show_terminal() {
local addr="$1"
- if ! window_is_pinned "$addr"; then
- hyprctl dispatch pin "address:$addr" >/dev/null 2>&1
+ local current_ws
+ local pos_info target_x target_y width height hidden_y
+ current_ws=$(get_current_workspace)
+ if ! [[ "$current_ws" =~ ^-?[0-9]+$ ]]; then
+ current_ws=1
+ fi
+ pos_info=$(calculate_dropdown_position)
+ if [ $? -ne 0 ] || [ -z "$pos_info" ]; then
+ debug_echo "Failed to calculate dropdown position for show; falling back to direct layout"
+ move_window_to_workspace_silent "$current_ws" "$addr" >/dev/null 2>&1 || debug_echo "Failed to move dropdown terminal to workspace $current_ws"
+ apply_dropdown_layout "$addr" || debug_echo "Dropdown layout update returned non-zero"
+ focus_window "$addr" >/dev/null 2>&1 || true
+ set_hidden_state "shown"
+ debug_echo "Dropdown terminal shown"
+ return 0
+ fi
+
+ target_x=$(echo "$pos_info" | cut -d' ' -f1)
+ target_y=$(echo "$pos_info" | cut -d' ' -f2)
+ width=$(echo "$pos_info" | cut -d' ' -f3)
+ height=$(echo "$pos_info" | cut -d' ' -f4)
+ hidden_y=$(get_hidden_y_for_window "$addr" "$height")
+ if window_is_on_special_workspace "$addr"; then
+ move_window_to_workspace_silent "$current_ws" "$addr" >/dev/null 2>&1 || debug_echo "Failed to move dropdown terminal to workspace $current_ws"
+ fi
+ set_window_floating "$addr" >/dev/null 2>&1 || true
+ resize_window_exact "$addr" "$width" "$height" >/dev/null 2>&1 || true
+ animate_slide_down "$addr" "$target_x" "$target_y" "$width" "$height" "$hidden_y" || move_window_exact "$addr" "$target_x" "$target_y" >/dev/null 2>&1
+ focus_window "$addr" >/dev/null 2>&1 || true
+ set_hidden_state "shown"
+ debug_echo "Dropdown terminal shown"
+ return 0
+}
+
+hide_terminal() {
+ local addr="$1"
+ local geometry start_x start_y width height hidden_y
+ if window_is_hidden "$addr" || window_is_on_special_workspace "$addr"; then
+ set_hidden_state "hidden"
+ debug_echo "Dropdown terminal already hidden"
+ return 0
+ fi
+
+ geometry=$(get_window_geometry "$addr")
+ if [ -n "$geometry" ]; then
+ start_x=$(echo "$geometry" | awk '{print $1}')
+ start_y=$(echo "$geometry" | awk '{print $2}')
+ width=$(echo "$geometry" | awk '{print $3}')
+ height=$(echo "$geometry" | awk '{print $4}')
+ else
+ local pos_info
+ pos_info=$(calculate_dropdown_position)
+ start_x=$(echo "$pos_info" | cut -d' ' -f1)
+ start_y=$(echo "$pos_info" | cut -d' ' -f2)
+ width=$(echo "$pos_info" | cut -d' ' -f3)
+ height=$(echo "$pos_info" | cut -d' ' -f4)
+ fi
+
+ if ! [[ "$height" =~ ^[0-9]+$ ]]; then
+ height=702
+ fi
+ hidden_y=$(get_hidden_y_for_window "$addr" "$height")
+ if ! [[ "$start_x" =~ ^-?[0-9]+$ && "$start_y" =~ ^-?[0-9]+$ ]]; then
+ debug_echo "Missing geometry for slide-up animation; moving off-screen directly"
+ move_window_exact "$addr" "$start_x" "$hidden_y" >/dev/null 2>&1 || true
+ else
+ animate_slide_up "$addr" "$start_x" "$start_y" "$width" "$height" "$hidden_y" || true
+ fi
+
+ if ! window_is_hidden "$addr"; then
+ debug_echo "Dropdown not off-screen after slide; trying direct off-screen move"
+ move_window_exact "$addr" "$start_x" "$hidden_y" >/dev/null 2>&1 || true
+ fi
+ if ! window_is_hidden "$addr"; then
+ debug_echo "Off-screen hide failed, falling back to $SPECIAL_WS"
+ if ! move_window_to_workspace_silent "$SPECIAL_WS" "$addr"; then
+ debug_echo "Failed to move dropdown terminal to $SPECIAL_WS"
+ return 1
+ fi
fi
+ set_hidden_state "hidden"
+ debug_echo "Dropdown terminal hidden"
+ return 0
}
-ensure_unpinned() {
+hide_terminal_silent() {
local addr="$1"
- if window_is_pinned "$addr"; then
- hyprctl dispatch pin "address:$addr" >/dev/null 2>&1
+ local geometry start_x height hidden_y
+ geometry=$(get_window_geometry "$addr")
+ if [ -n "$geometry" ]; then
+ start_x=$(echo "$geometry" | awk '{print $1}')
+ height=$(echo "$geometry" | awk '{print $4}')
fi
+ if ! [[ "$height" =~ ^[0-9]+$ ]]; then
+ height=702
+ fi
+ hidden_y=$(get_hidden_y_for_window "$addr" "$height")
+ if ! [[ "$start_x" =~ ^-?[0-9]+$ ]]; then
+ start_x=0
+ fi
+ move_window_exact "$addr" "$start_x" "$hidden_y" >/dev/null 2>&1 || true
+ move_window_to_workspace_silent "$SPECIAL_WS" "$addr" >/dev/null 2>&1 || true
+ set_hidden_state "hidden"
+ debug_echo "Dropdown terminal hidden (silent)"
+ return 0
}
# Function to spawn terminal and capture its address
@@ -403,45 +751,48 @@ spawn_terminal() {
local windows_before=$(hyprctl clients -j)
local count_before=$(echo "$windows_before" | jq 'length')
- # Launch terminal directly in special workspace to avoid visible spawn
- hyprctl dispatch exec "[float; size $width $height; workspace special:scratchpad silent] $TERMINAL_CMD"
-
- # Wait for window to appear
- sleep 0.1
-
- # Get windows after spawning
- local windows_after=$(hyprctl clients -j)
- local count_after=$(echo "$windows_after" | jq 'length')
+ # Launch terminal with pre-applied workspace/geometry hints to avoid visible zigzag.
+ local launch_cmd="[workspace $SPECIAL_WS silent;float;size $width $height;move $target_x $target_y] $TERMINAL_CMD"
+ hypr_exec_cmd "$launch_cmd"
local new_addr=""
+ for _ in $(seq 1 20); do
+ local windows_after=$(hyprctl clients -j)
+ local recovered
+ recovered=$(echo "$windows_after" | jq -r --arg CLASS "$DROPDOWN_KITTY_CLASS" \
+ '.[] | select((.class == $CLASS) or (.initialClass == $CLASS)) | .address' | head -1)
+ if [ -n "$recovered" ] && [ "$recovered" != "null" ]; then
+ new_addr="$recovered"
+ break
+ fi
- if [ "$count_after" -gt "$count_before" ]; then
- # Find the new window by comparing before/after lists
- new_addr=$(comm -13 \
- <(echo "$windows_before" | jq -r '.[].address' | sort) \
- <(echo "$windows_after" | jq -r '.[].address' | sort) |
- head -1)
- fi
-
- # Fallback: try to find by the most recently mapped window
- if [ -z "$new_addr" ] || [ "$new_addr" = "null" ]; then
- new_addr=$(hyprctl clients -j | jq -r 'sort_by(.focusHistoryID) | .[-1] | .address')
- fi
+ local count_after=$(echo "$windows_after" | jq 'length')
+ if [ "$count_after" -gt "$count_before" ]; then
+ new_addr=$(comm -13 \
+ <(echo "$windows_before" | jq -r '.[].address' | sort) \
+ <(echo "$windows_after" | jq -r '.[].address' | sort) |
+ head -1)
+ if [ -n "$new_addr" ] && [ "$new_addr" != "null" ]; then
+ break
+ fi
+ fi
+ sleep 0.1
+ done
if [ -n "$new_addr" ] && [ "$new_addr" != "null" ]; then
# Store the address and monitor name
echo "$new_addr $monitor_name" >"$ADDR_FILE"
debug_echo "Terminal created with address: $new_addr in special workspace on monitor $monitor_name"
- # Small delay to ensure it's properly in special workspace
- sleep 0.2
- # Move to current workspace but start hidden off-screen
- hyprctl dispatch movetoworkspacesilent "$CURRENT_WS,address:$new_addr"
- ensure_pinned "$new_addr"
- hyprctl dispatch resizewindowpixel "exact $width $height,address:$new_addr" >/dev/null 2>&1
- local off_y=$((target_y - height - 200))
- hyprctl dispatch movewindowpixel "exact $target_x $off_y,address:$new_addr" >/dev/null 2>&1
- set_hidden_state "hidden"
+ # Configure in special workspace and keep hidden until explicitly toggled.
+ set_window_floating "$new_addr" >/dev/null 2>&1
+ resize_window_exact "$new_addr" "$width" "$height" >/dev/null 2>&1
+ move_window_exact "$new_addr" "$target_x" "$target_y" >/dev/null 2>&1
+ if [ "$STARTUP_MODE" = true ]; then
+ hide_terminal_silent "$new_addr" || debug_echo "Failed to hide new dropdown terminal after spawn (silent)"
+ else
+ hide_terminal "$new_addr" || debug_echo "Failed to hide new dropdown terminal after spawn"
+ fi
return 0
fi
@@ -452,80 +803,31 @@ spawn_terminal() {
# Main logic
TERMINAL_ADDR=$(resolve_terminal_address)
-
-if [ -n "$TERMINAL_ADDR" ]; then
- debug_echo "Found existing terminal: $TERMINAL_ADDR"
- focused_monitor=$(get_monitor_info | awk '{print $6}')
- dropdown_monitor=$(get_terminal_monitor)
- if [ "$focused_monitor" != "$dropdown_monitor" ]; then
- debug_echo "Monitor focus changed: moving dropdown to $focused_monitor"
- # Calculate new position for focused monitor
- pos_info=$(calculate_dropdown_position)
- target_x=$(echo $pos_info | cut -d' ' -f1)
- target_y=$(echo $pos_info | cut -d' ' -f2)
- width=$(echo $pos_info | cut -d' ' -f3)
- height=$(echo $pos_info | cut -d' ' -f4)
- monitor_name=$(echo $pos_info | cut -d' ' -f5)
- # Move and resize window
- hyprctl dispatch movewindowpixel "exact $target_x $target_y,address:$TERMINAL_ADDR"
- hyprctl dispatch resizewindowpixel "exact $width $height,address:$TERMINAL_ADDR"
- # Update ADDR_FILE
- echo "$TERMINAL_ADDR $monitor_name" >"$ADDR_FILE"
+if [ -z "$TERMINAL_ADDR" ]; then
+ debug_echo "No existing terminal found, creating new one"
+ if spawn_terminal; then
+ TERMINAL_ADDR=$(get_terminal_address)
fi
+fi
- hidden_state=$(get_hidden_state)
- if [ "$hidden_state" = "hidden" ] || [ -z "$hidden_state" ] || window_is_hidden "$TERMINAL_ADDR"; then
- debug_echo "Bringing terminal from hidden position with slide down animation"
-
- # Calculate target position
- pos_info=$(calculate_dropdown_position)
- target_x=$(echo $pos_info | cut -d' ' -f1)
- target_y=$(echo $pos_info | cut -d' ' -f2)
- width=$(echo $pos_info | cut -d' ' -f3)
- height=$(echo $pos_info | cut -d' ' -f4)
-
- ensure_pinned "$TERMINAL_ADDR"
-
- # Set size and animate slide down
- hyprctl dispatch resizewindowpixel "exact $width $height,address:$TERMINAL_ADDR"
- animate_slide_down "$TERMINAL_ADDR" "$target_x" "$target_y" "$width" "$height"
-
- hyprctl dispatch focuswindow "address:$TERMINAL_ADDR"
- set_hidden_state "shown"
- else
- debug_echo "Hiding terminal off-screen with slide up animation"
-
- # Get current geometry for animation
- geometry=$(get_window_geometry "$TERMINAL_ADDR")
- if [ -n "$geometry" ]; then
- curr_x=$(echo $geometry | cut -d' ' -f1)
- curr_y=$(echo $geometry | cut -d' ' -f2)
- curr_width=$(echo $geometry | cut -d' ' -f3)
- curr_height=$(echo $geometry | cut -d' ' -f4)
-
- debug_echo "Current geometry: ${curr_x},${curr_y} ${curr_width}x${curr_height}"
+if [ -z "$TERMINAL_ADDR" ]; then
+ debug_echo "No dropdown terminal instance is available"
+ exit 1
+fi
- # Animate slide up first
- animate_slide_up "$TERMINAL_ADDR" "$curr_x" "$curr_y" "$curr_width" "$curr_height"
+if [ "$STARTUP_MODE" = true ]; then
+ debug_echo "Startup mode requested: ensuring dropdown terminal exists and stays hidden"
+ hide_terminal_silent "$TERMINAL_ADDR"
+ exit 0
+fi
+HIDDEN_STATE=$(get_hidden_state)
+if [ "$HIDDEN_STATE" != "hidden" ] && [ "$HIDDEN_STATE" != "shown" ]; then
+ HIDDEN_STATE=$(infer_hidden_state "$TERMINAL_ADDR")
+ set_hidden_state "$HIDDEN_STATE"
+fi
- # Move off-screen after animation
- off_y=$((curr_y - curr_height - 200))
- hyprctl dispatch movewindowpixel "exact $curr_x $off_y,address:$TERMINAL_ADDR" >/dev/null 2>&1
- ensure_unpinned "$TERMINAL_ADDR"
- set_hidden_state "hidden"
- else
- debug_echo "Could not get window geometry, moving off-screen without animation"
- hyprctl dispatch movewindowpixel "exact 0 -1000,address:$TERMINAL_ADDR" >/dev/null 2>&1
- ensure_unpinned "$TERMINAL_ADDR"
- set_hidden_state "hidden"
- fi
- fi
+if [ "$HIDDEN_STATE" = "hidden" ]; then
+ show_terminal "$TERMINAL_ADDR"
else
- debug_echo "No existing terminal found, creating new one"
- if spawn_terminal; then
- TERMINAL_ADDR=$(get_terminal_address)
- if [ -n "$TERMINAL_ADDR" ]; then
- hyprctl dispatch focuswindow "address:$TERMINAL_ADDR"
- fi
- fi
+ hide_terminal "$TERMINAL_ADDR"
fi
diff --git a/config/hypr/scripts/ExternalBrightness.sh b/config/hypr/scripts/ExternalBrightness.sh
index 29c1b238..59081e1d 100755
--- a/config/hypr/scripts/ExternalBrightness.sh
+++ b/config/hypr/scripts/ExternalBrightness.sh
@@ -5,99 +5,253 @@
# License: GNU GPLv3
# SPDX-License-Identifier: GPL-3.0-or-later
# ==================================================
-# External monitor brightness via ddcutil
+# External monitor brightness via ddcutil with dynamic monitor detection
set -u
+# Configuration
step=10
-vcp_code=10
+min=5
+vcp_code=10 # MCCS VCP feature 0x10: Luminance (brightness)
+state_file="/tmp/external_brightness_bus"
+cache_file="/tmp/external_brightness_displays.cache"
+cache_ttl=300 # 5 minutes
-usage() {
- cat <<'EOF'
-Usage: ExternalBrightness.sh [--get|--inc|--dec|--set N] [--display N]
-Env:
- DDCUTIL_DISPLAY Optional display number passed to ddcutil --display
- DDCUTIL_OPTS Extra options passed to ddcutil (e.g. "--sleep-multiplier 0.2")
-EOF
+# Detect active Hyprland config mode (Lua entrypoint vs legacy .conf includes)
+config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
+hypr_dir="$config_home/hypr"
+lua_entry="$hypr_dir/hyprland.lua"
+legacy_lua_entry="$config_home/hyprland.lua"
+
+if [[ -n "${HYPR_CONFIG_MODE:-}" ]]; then
+ case "${HYPR_CONFIG_MODE,,}" in
+ lua) hypr_config_mode="lua" ;;
+ conf|hyprlang) hypr_config_mode="conf" ;;
+ auto) hypr_config_mode="" ;;
+ *) hypr_config_mode="" ;;
+ esac
+fi
+
+if [[ -z "${hypr_config_mode:-}" ]]; then
+ if [[ -f "$lua_entry" || -f "$legacy_lua_entry" ]]; then
+ hypr_config_mode="lua"
+ else
+ hypr_config_mode="conf"
+ fi
+fi
+
+# Get list of displays: bus model index
+# Format: BUS|MODEL|INDEX
+get_displays() {
+ if [[ -f "$cache_file" ]]; then
+ local now mtime
+ now=$(date +%s)
+ mtime=$(stat -c %Y "$cache_file")
+ if (( now - mtime < cache_ttl )); then
+ cat "$cache_file"
+ return
+ fi
+ fi
+
+ local res
+ res=$(ddcutil detect --terse 2>/dev/null | awk '
+ /^Display/ {
+ if (bus) {
+ count[model]++
+ print bus "|" model "|" count[model]
+ }
+ bus=""; model="Unknown"
+ }
+ /I2C bus:/ { bus=$0; sub(/.*\/dev\/i2c-/, "", bus) }
+ /Model:/ { model=$0; sub(/.*Model:[[:space:]]*/, "", model) }
+ END {
+ if (bus) {
+ count[model]++
+ print bus "|" model "|" count[model]
+ }
+ }
+ ')
+
+ if [[ -n "$res" ]]; then
+ echo "$res" > "$cache_file"
+ echo "$res"
+ fi
+}
+
+get_active_bus() {
+ local displays
+ displays=$(get_displays)
+ if [[ -z "$displays" ]]; then
+ return 1
+ fi
+
+ local saved
+ if [[ -f "$state_file" ]]; then
+ saved=$(cat "$state_file")
+ # Check if saved bus still exists in current displays
+ if echo "$displays" | grep -q "^$saved|"; then
+ echo "$saved"
+ return 0
+ fi
+ fi
+
+ # Default to first display's bus
+ echo "$displays" | head -n 1 | cut -d'|' -f1
+}
+
+set_active_bus() {
+ echo "$1" > "$state_file"
+}
+
+cycle_display() {
+ local displays
+ displays=$(get_displays)
+ [[ -z "$displays" ]] && return 1
+
+ local current
+ current=$(get_active_bus) || return 1
+
+ local next
+ next=$(echo "$displays" | awk -v current="$current" -F'|' '
+ {
+ a[n++] = $1
+ }
+ END {
+ for (i=0; i<n; i++) {
+ if (a[i] == current) {
+ print a[(i+1)%n]
+ exit
+ }
+ }
+ print a[0]
+ }
+ ')
+ set_active_bus "$next"
}
ddcutil_cmd() {
- local display_arg=()
- local display="${DDCUTIL_DISPLAY:-}"
- if [[ -n "${display}" ]]; then
- display_arg+=(--display "${display}")
- fi
- ddcutil ${DDCUTIL_OPTS:-} "${display_arg[@]}" "$@"
+ local bus="$1"
+ shift
+ ddcutil --bus "$bus" ${DDCUTIL_OPTS:-} "$@"
}
get_brightness() {
- # Example output: "VCP code 0x10 (Brightness): current value = 50, max value = 100"
- local line
- if ! line="$(ddcutil_cmd getvcp "${vcp_code}" 2>/dev/null | tail -n 1)"; then
- return 1
- fi
- local current max
- current="$(printf "%s" "${line}" | sed -n 's/.*current value = \([0-9]\+\).*/\1/p')"
- max="$(printf "%s" "${line}" | sed -n 's/.*max value = \([0-9]\+\).*/\1/p')"
- [[ -n "${current}" && -n "${max}" ]] || return 1
- printf "%s %s\n" "${current}" "${max}"
+ local bus="$1"
+ local line
+ if ! line="$(ddcutil_cmd "$bus" getvcp "$vcp_code" 2>/dev/null | tail -n 1)"; then
+ return 1
+ fi
+
+ local current max
+ current="$(sed -n 's/.*current value = *\([0-9]\+\).*/\1/p' <<< "$line")"
+ max="$(sed -n 's/.*max value = *\([0-9]\+\).*/\1/p' <<< "$line")"
+
+ [[ -n "$current" && -n "$max" ]] || return 1
+ printf "%s %s\n" "$current" "$max"
}
set_brightness() {
- local value="$1"
- ddcutil_cmd setvcp "${vcp_code}" "${value}" >/dev/null 2>&1
+ local bus="$1"
+ local value="$2"
+ ddcutil_cmd "$bus" setvcp "$vcp_code" "$value" >/dev/null 2>&1
}
json_output() {
- local current max percent icon
- if ! read -r current max < <(get_brightness); then
- printf '{"text":"󰃜 N/A","tooltip":"External brightness unavailable (load i2c-dev, allow i2c access)","class":"brightness-external-off"}\n'
- return 0
- fi
- percent=$(( current * 100 / max ))
- if (( percent >= 80 )); then
- icon="󰃠"
- elif (( percent >= 60 )); then
- icon="󰃟"
- elif (( percent >= 40 )); then
- icon="󰃞"
- elif (( percent >= 20 )); then
- icon="󰃝"
- else
- icon=""
- fi
- printf '{"text":"%s %s%%","tooltip":"External display brightness: %s%%","class":"brightness-external"}\n' "${icon}" "${percent}" "${percent}"
+ local displays
+ displays=$(get_displays)
+ if [[ -z "$displays" ]]; then
+ printf '{"text":"󰃜 N/A","tooltip":"No DDC/CI displays detected","class":"brightness-external-off"}\n'
+ return 0
+ fi
+
+ local active_bus
+ active_bus=$(get_active_bus) || return 1
+
+ local current max percent
+ if ! read -r current max < <(get_brightness "$active_bus"); then
+ current="N/A"
+ percent="N/A"
+ else
+ percent=$(( current * 100 / max ))
+ fi
+
+ # Build tooltip
+ local tooltip=""
+ local active_name="Unknown"
+
+ while IFS='|' read -r bus model index; do
+ local name="${model}"
+ [[ $index -gt 1 ]] && name="${name} #${index}"
+
+ if [[ "$bus" == "$active_bus" ]]; then
+ tooltip="${tooltip}[ ${name} ]\\n"
+ active_name="$name"
+ else
+ tooltip="${tooltip}${name}\\n"
+ fi
+ done <<< "$displays"
+
+ tooltip="${tooltip}\\nBrightness: ${percent}%\\nClick to switch display"
+
+ local icon="󰃟"
+ if [[ "$percent" != "N/A" ]]; then
+ if (( percent >= 80 )); then icon="󰃠";
+ elif (( percent >= 60 )); then icon="󰃟";
+ elif (( percent >= 40 )); then icon="󰃞";
+ elif (( percent >= 20 )); then icon="󰃝";
+ else icon=""; fi
+ printf '{"text":"%s %s%%","tooltip":"%s","class":"brightness-external"}\n' "$icon" "$percent" "$tooltip"
+ else
+ printf '{"text":"󰃜 %s","tooltip":"%s","class":"brightness-external-off"}\n' "$current" "$tooltip"
+ fi
}
case "${1:-}" in
- --get|"")
- json_output
- ;;
- --inc|--dec)
- read -r current max < <(get_brightness) || exit 1
- delta=$step
- [[ "$1" == "--dec" ]] && delta=$(( -step ))
- new=$(( current + delta ))
- (( new < 5 )) && new=5
- (( new > max )) && new="${max}"
- set_brightness "${new}"
- json_output
- ;;
- --set)
- [[ -n "${2:-}" ]] || { usage; exit 1; }
- set_brightness "${2}"
- json_output
- ;;
- --display)
- [[ -n "${2:-}" ]] || { usage; exit 1; }
- DDCUTIL_DISPLAY="${2}" shift 2
- "${0}" "${@:-"--get"}"
- ;;
- -h|--help)
- usage
- ;;
- *)
- usage
- exit 1
- ;;
+ --get|"")
+ json_output
+ ;;
+ --inc|--dec)
+ bus=$(get_active_bus) || exit 0
+ read -r current max < <(get_brightness "$bus") || { json_output; exit 0; }
+ delta=$step
+ [[ "$1" == "--dec" ]] && delta=$(( -step ))
+ new=$(( current + delta ))
+ (( new < min )) && new=$min
+ (( new > max )) && new="$max"
+ set_brightness "$bus" "$new"
+ json_output
+ ;;
+ --set)
+ [[ -n "${2:-}" ]] || exit 1
+ bus=$(get_active_bus) || exit 1
+ set_brightness "$bus" "$2"
+ json_output
+ ;;
+ --cycle)
+ cycle_display
+ json_output
+ ;;
+ --bus)
+ [[ -n "${2:-}" ]] || exit 1
+ set_active_bus "$2"
+ shift 2
+ "${0}" "${@:-"--get"}"
+ ;;
+ --display)
+ # Compatibility with old --display N but now it expects a bus number
+ # Or we could map display number to bus number
+ [[ -n "${2:-}" ]] || exit 1
+ bus_target=$(get_displays | awk -v target="$2" -F'|' 'NR==target {print $1}')
+ if [[ -n "$bus_target" ]]; then
+ set_active_bus "$bus_target"
+ fi
+ shift 2
+ "${0}" "${@:-"--get"}"
+ ;;
+ -h|--help)
+ echo "Usage: $0 [--get|--inc|--dec|--set N|--cycle|--bus N|--display N]"
+ ;;
+ *)
+ exit 1
+ ;;
esac
diff --git a/config/hypr/scripts/Float-all-Windows.sh b/config/hypr/scripts/Float-all-Windows.sh
index e658cabb..25fdc465 100755
--- a/config/hypr/scripts/Float-all-Windows.sh
+++ b/config/hypr/scripts/Float-all-Windows.sh
@@ -6,5 +6,28 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# ==================================================
+# Detect active Hyprland config mode (Lua entrypoint vs legacy .conf includes)
+config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
+hypr_dir="$config_home/hypr"
+lua_entry="$hypr_dir/hyprland.lua"
+legacy_lua_entry="$config_home/hyprland.lua"
+
+if [[ -f "$lua_entry" || -f "$legacy_lua_entry" ]]; then
+ hypr_config_mode="lua"
+else
+ hypr_config_mode="conf"
+fi
+
+# Get current workspace ID
ws=$(hyprctl activeworkspace -j | jq -r .id)
-hyprctl clients -j | jq -r --arg ws "$ws" '.[] | select(.workspace.id == ($ws|tonumber)) | .address' | xargs -r -I {} hyprctl dispatch togglefloating address:{}
+
+# Process all windows on the current workspace
+if [[ "$hypr_config_mode" == "lua" ]]; then
+ # In Lua mode, use the native Lua API via hl.dispatch to ensure compatibility
+ hyprctl clients -j | jq -r --arg ws "$ws" '.[] | select(.workspace.id == ($ws|tonumber)) | .address' | while read -r addr; do
+ hyprctl dispatch "hl.dispatch(hl.dsp.window.float({ window = \"address:${addr}\", action = \"toggle\" }))" >/dev/null 2>&1
+ done
+else
+ # Legacy Hyprlang mode
+ hyprctl clients -j | jq -r --arg ws "$ws" '.[] | select(.workspace.id == ($ws|tonumber)) | .address' | xargs -r -I {} hyprctl dispatch togglefloating address:{}
+fi
diff --git a/config/hypr/scripts/GameMode.sh b/config/hypr/scripts/GameMode.sh
index 9c5b8264..b104179e 100755
--- a/config/hypr/scripts/GameMode.sh
+++ b/config/hypr/scripts/GameMode.sh
@@ -12,31 +12,89 @@ SCRIPTSDIR="$HOME/.config/hypr/scripts"
# shellcheck source=/dev/null
. "$SCRIPTSDIR/WallpaperCmd.sh"
+# Detect active Hyprland config mode (Lua entrypoint vs legacy .conf includes)
+config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
+hypr_dir="$config_home/hypr"
+lua_entry="$hypr_dir/hyprland.lua"
+legacy_lua_entry="$config_home/hyprland.lua"
-HYPRGAMEMODE=$(hyprctl getoption animations:enabled | awk 'NR==1{print $2}')
-if [ "$HYPRGAMEMODE" = 1 ] ; then
- hyprctl --batch "\
- keyword animations:enabled 0;\
- keyword decoration:shadow:enabled 0;\
- keyword decoration:blur:enabled 0;\
- keyword general:gaps_in 0;\
- keyword general:gaps_out 0;\
- keyword general:border_size 1;\
- keyword decoration:rounding 0"
-
-\thyprctl keyword "windowrule opacity 1 override 1 override 1 override, ^(.*)$"
+if [[ -f "$lua_entry" || -f "$legacy_lua_entry" ]]; then
+ hypr_config_mode="lua"
+else
+ hypr_config_mode="conf"
+fi
+
+# Check if animations are currently enabled
+HYPRGAMEMODE=$(hyprctl getoption animations:enabled -j | jq -r '.bool' 2>/dev/null)
+if [[ "$HYPRGAMEMODE" == "null" || -z "$HYPRGAMEMODE" ]]; then
+ HYPRGAMEMODE=$(hyprctl getoption animations:enabled | awk 'NR==1{print $2}')
+fi
+
+if [ "$HYPRGAMEMODE" = "true" ] || [ "$HYPRGAMEMODE" = "1" ] ; then
+ # ENABLE Game Mode (Disable animations/decorations)
+ if [[ "$hypr_config_mode" == "lua" ]]; then
+ hyprctl eval "hl.config({
+ animations = { enabled = false },
+ decoration = { shadow = { enabled = false }, blur = { enabled = false }, rounding = 0 },
+ general = { gaps_in = 0, gaps_out = 0, border_size = 1 }
+ })"
+ hyprctl eval "hl.window_rule({ name = 'gamemode-opacity', match = { class = '.*' }, opacity = 1.0 })"
+ else
+ hyprctl --batch "\
+ keyword animations:enabled 0;\
+ keyword decoration:shadow:enabled 0;\
+ keyword decoration:blur:enabled 0;\
+ keyword general:gaps_in 0;\
+ keyword general:gaps_out 0;\
+ keyword general:border_size 1;\
+ keyword decoration:rounding 0"
+ hyprctl keyword "windowrule opacity 1 override 1 override 1 override, ^(.*)$"
+ fi
+
"$WWW_CMD" kill
notify-send -e -u low -i "$notif" " Gamemode:" " enabled"
sleep 0.1
exit
else
-\t"$WWW_DAEMON" "${WWW_DAEMON_ARGS[@]}" && "$WWW_CMD" img "$HOME/.config/rofi/.current_wallpaper" &
- sleep 0.1
- ${SCRIPTSDIR}/WallustSwww.sh
- sleep 0.5
- hyprctl reload
- ${SCRIPTSDIR}/Refresh.sh
+ # DISABLE Game Mode (Restore animations/decorations)
+ if [[ "$hypr_config_mode" == "lua" ]]; then
+ # Explicitly restore to defaults (matching settings.lua where possible)
+ hyprctl eval "hl.config({
+ animations = { enabled = true },
+ decoration = { shadow = { enabled = true }, blur = { enabled = true }, rounding = 10 },
+ general = { gaps_in = 2, gaps_out = 4, border_size = 2 }
+ })"
+ # Removing rule in Lua mode might require a different approach if no 'remove' exists
+ # We'll reload the config as a fallback or try to nullify it
+ hyprctl eval "hl.window_rule({ name = 'gamemode-opacity', match = { class = 'NONE' }, opacity = 1.0 })"
+ else
+ hyprctl --batch "\
+ keyword animations:enabled 1;\
+ keyword decoration:shadow:enabled 1;\
+ keyword decoration:blur:enabled 1;\
+ keyword general:gaps_in 2;\
+ keyword general:gaps_out 4;\
+ keyword general:border_size 2;\
+ keyword decoration:rounding 10"
+ hyprctl keyword "windowrule opacity 1 override 1 override 1 override, ^(NONE)$"
+ fi
+
+ # Restore wallpaper using the official daemon script
+ if [[ -x "${SCRIPTSDIR}/WallpaperDaemon.sh" ]]; then
+ "${SCRIPTSDIR}/WallpaperDaemon.sh" &
+ fi
+
+ sleep 0.1
+ ${SCRIPTSDIR}/WallustSwww.sh
+ sleep 0.5
+
+ # Refresh UI components
+ if [[ -x "${SCRIPTSDIR}/Refresh.sh" ]]; then
+ "${SCRIPTSDIR}/Refresh.sh"
+ else
+ hyprctl reload
+ fi
+
notify-send -e -u normal -i "$notif" " Gamemode:" " disabled"
exit
fi
-hyprctl reload
diff --git a/config/hypr/scripts/Ghostty_themes.sh b/config/hypr/scripts/Ghostty_themes.sh
index a69f246e..c3fcd792 100755
--- a/config/hypr/scripts/Ghostty_themes.sh
+++ b/config/hypr/scripts/Ghostty_themes.sh
@@ -11,6 +11,10 @@ config_file="$HOME/.config/ghostty/config"
iDIR="$HOME/.config/swaync/images"
rofi_theme_primary="$HOME/.config/rofi/config-ghostty-theme.rasi"
rofi_theme_fallback="$HOME/.config/rofi/config-edit.rasi"
+wallust_include_path="$HOME/.config/ghostty/wallust.conf"
+wallust_option_label="Set by wallpaper"
+default_option_label="Default - no color"
+wallust_refresh_script="$HOME/.config/hypr/scripts/WallustSwww.sh"
notify_user() {
local icon="$1"
@@ -23,6 +27,13 @@ notify_user() {
fi
}
+refresh_wallpaper_theme() {
+ if [[ -x "$wallust_refresh_script" ]]; then
+ "$wallust_refresh_script" >/dev/null 2>&1 || true
+ fi
+ pkill -SIGUSR2 ghostty >/dev/null 2>&1 || true
+}
+
if [[ ! -f "$config_file" ]]; then
notify_user "$iDIR/error.png" "Ghostty Theme" "Config not found: $config_file"
exit 1
@@ -46,6 +57,11 @@ current_theme=$(
}' "$config_file"
)
+wallust_enabled=$(
+ awk '/^[[:space:]]*config-file[[:space:]]*=/ && $0 !~ /^[[:space:]]*#/ && /wallust\.conf/ {print "1"; exit}' "$config_file"
+)
+[[ "$wallust_enabled" != "1" ]] && wallust_enabled="0"
+
mapfile -t available_theme_names < <(
awk -F'=' '/^[[:space:]]*#[[:space:]]*theme[[:space:]]*=/ {
val=$2
@@ -60,29 +76,103 @@ if [[ ${#available_theme_names[@]} -eq 0 ]]; then
notify_user "$iDIR/error.png" "Ghostty Theme" "No commented themes found in $config_file"
exit 1
fi
-
-menu_entries=()
-if [[ -n "$current_theme" ]]; then
- menu_entries+=("Current: $current_theme")
-fi
+menu_entries=("$wallust_option_label" "$default_option_label")
for t in "${available_theme_names[@]}"; do
menu_entries+=("$t")
done
+current_selection_index=0
+if [[ "$wallust_enabled" == "1" ]]; then
+ current_selection_index=0
+elif [[ -z "$current_theme" ]]; then
+ current_selection_index=1
+else
+ current_selection_index=1
+ for i in "${!available_theme_names[@]}"; do
+ if [[ "${available_theme_names[$i]}" == "$current_theme" ]]; then
+ current_selection_index=$((i + 2))
+ break
+ fi
+ done
+fi
choice=$(
printf "%s\n" "${menu_entries[@]}" |
- rofi -i -dmenu -p "Ghostty Theme" "${rofi_config_args[@]}" -mesg "Select a theme to apply"
+ rofi -i -dmenu -p "Ghostty Theme" "${rofi_config_args[@]}" -mesg "Select a theme to apply" -selected-row "$current_selection_index"
)
[[ -z "$choice" ]] && exit 0
-if [[ "$choice" == "Current: "* ]]; then
+
+selected_theme="$choice"
+
+if [[ "$selected_theme" == "$wallust_option_label" ]]; then
+ if [[ "$wallust_enabled" == "1" ]]; then
+ exit 0
+ fi
+
+ tmp_file=$(mktemp)
+ awk -v wallust_include_path="$wallust_include_path" '
+function trim(s) { sub(/^[[:space:]]+/, "", s); sub(/[[:space:]]+$/, "", s); return s }
+{
+ line=$0
+ if ($0 ~ /^[[:space:]]*theme[[:space:]]*=/) {
+ sub(/^[[:space:]]*theme[[:space:]]*=/, "#theme =", line)
+ print line
+ next
+ }
+ if ($0 ~ /^[[:space:]]*#?[[:space:]]*config-file[[:space:]]*=/ && $0 ~ /wallust\.conf/) {
+ print "config-file = " wallust_include_path
+ wallust_set=1
+ next
+ }
+ print $0
+}
+END {
+ if (!wallust_set) {
+ print "config-file = " wallust_include_path
+ }
+}
+' "$config_file" > "$tmp_file"
+ mv "$tmp_file" "$config_file"
+ refresh_wallpaper_theme
+ notify_user "$iDIR/ja.png" "Ghostty Theme Applied" "$wallust_option_label"
exit 0
fi
+if [[ "$selected_theme" == "$default_option_label" ]]; then
+ if [[ "$wallust_enabled" != "1" && -z "$current_theme" ]]; then
+ exit 0
+ fi
-selected_theme="$choice"
+ tmp_file=$(mktemp)
+ awk -v wallust_include_path="$wallust_include_path" '
+{
+ line=$0
+ if ($0 ~ /^[[:space:]]*theme[[:space:]]*=/) {
+ sub(/^[[:space:]]*theme[[:space:]]*=/, "#theme =", line)
+ print line
+ next
+ }
+ if ($0 ~ /^[[:space:]]*#?[[:space:]]*config-file[[:space:]]*=/ && $0 ~ /wallust\.conf/) {
+ print "#config-file = " wallust_include_path
+ wallust_seen=1
+ next
+ }
+ print $0
+}
+END {
+ if (!wallust_seen) {
+ print "#config-file = " wallust_include_path
+ }
+}
+' "$config_file" > "$tmp_file"
+ mv "$tmp_file" "$config_file"
+
+ pkill -SIGUSR2 ghostty >/dev/null 2>&1 || true
+ notify_user "$iDIR/ja.png" "Ghostty Theme Applied" "$default_option_label"
+ exit 0
+fi
-if [[ -n "$current_theme" && "$selected_theme" == "$current_theme" ]]; then
+if [[ "$wallust_enabled" != "1" && -n "$current_theme" && "$selected_theme" == "$current_theme" ]]; then
exit 0
fi
@@ -97,11 +187,16 @@ format_theme_value() {
selected_formatted=$(format_theme_value "$selected_theme")
tmp_file=$(mktemp)
-awk -v selected="$selected_theme" -v selected_formatted="$selected_formatted" '
+awk -v selected="$selected_theme" -v selected_formatted="$selected_formatted" -v wallust_include_path="$wallust_include_path" '
function trim(s) { sub(/^[[:space:]]+/, "", s); sub(/[[:space:]]+$/, "", s); return s }
function strip_quotes(s) { gsub(/^"|"$/, "", s); return s }
{
line=$0
+ if ($0 ~ /^[[:space:]]*#?[[:space:]]*config-file[[:space:]]*=/ && $0 ~ /wallust\.conf/) {
+ print "#config-file = " wallust_include_path
+ wallust_seen=1
+ next
+ }
if ($0 ~ /^[[:space:]]*theme[[:space:]]*=/) {
sub(/^[[:space:]]*theme[[:space:]]*=/, "#theme =", line)
print line
@@ -118,6 +213,11 @@ function strip_quotes(s) { gsub(/^"|"$/, "", s); return s }
}
}
print $0
+}
+END {
+ if (!wallust_seen) {
+ print "#config-file = " wallust_include_path
+ }
}' "$config_file" > "$tmp_file"
mv "$tmp_file" "$config_file"
diff --git a/config/hypr/scripts/HyprLayoutModule.sh b/config/hypr/scripts/HyprLayoutModule.sh
new file mode 100755
index 00000000..22f12920
--- /dev/null
+++ b/config/hypr/scripts/HyprLayoutModule.sh
@@ -0,0 +1,131 @@
+#!/usr/bin/env bash
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# Waybar module for Hyprland layouts
+
+IFS=$'\n\t'
+
+SCRIPTSDIR="$HOME/.config/hypr/scripts"
+rofi_config="$HOME/.config/rofi/config-waybar-layout.rasi"
+change_layout="${SCRIPTSDIR}/ChangeLayout.sh"
+layouts=(dwindle scrolling monocle master)
+
+layout_icon() {
+ case "$1" in
+ dwindle) echo "🄳" ;;
+ scrolling) echo "🅂" ;;
+ monocle) echo "🄼" ;;
+ master) echo "ⓜ" ;;
+ *) echo "󰹑" ;;
+ esac
+}
+
+layout_name() {
+ case "$1" in
+ dwindle) echo "Dwindle" ;;
+ scrolling) echo "Scrolling" ;;
+ monocle) echo "Monocle" ;;
+ master) echo "Master" ;;
+ *) echo "Unknown" ;;
+ esac
+}
+
+get_layout() {
+ hyprctl -j getoption general:layout 2>/dev/null | jq -r '.str // "unknown"' 2>/dev/null
+}
+
+next_layout() {
+ local current="$1"
+ local i
+
+ for i in "${!layouts[@]}"; do
+ if [[ "${layouts[i]}" == "$current" ]]; then
+ echo "${layouts[((i + 1) % ${#layouts[@]})]}"
+ return
+ fi
+ done
+
+ echo "${layouts[0]}"
+}
+
+refresh_waybar() {
+ pkill -RTMIN+8 waybar 2>/dev/null || true
+}
+
+set_layout() {
+ local target="$1"
+
+ "$change_layout" "$target" && refresh_waybar
+}
+
+show_status() {
+ local current icon name tooltip
+
+ current="$(get_layout)"
+ icon="$(layout_icon "$current")"
+ name="$(layout_name "$current")"
+ tooltip="Hyprland layout: ${name} (${icon})\n\nLeft click: Select layout\nRight click: Cycle layout\n\nOptions:\n🄳 Dwindle\n🅂 Scrolling\n🄼 Monocle\nⓜ Master"
+
+ printf '{"text":"%s","tooltip":"%s","class":"%s"}\n' "$icon" "$tooltip" "$current"
+}
+
+show_menu() {
+ local current default_row choice target i
+ local options=()
+
+ current="$(get_layout)"
+ default_row=0
+
+ for i in "${!layouts[@]}"; do
+ local layout="${layouts[i]}"
+ local prefix=" "
+
+ if [[ "$layout" == "$current" ]]; then
+ prefix="● "
+ default_row="$i"
+ fi
+
+ options+=("${prefix}$(layout_icon "$layout") $(layout_name "$layout")")
+ done
+
+ if pgrep -x rofi >/dev/null; then
+ pkill rofi
+ return 0
+ fi
+
+ choice="$(printf '%s\n' "${options[@]}" | rofi -i -dmenu -p "Layout" -mesg "Left click selects • Right click cycles" -selected-row "$default_row" -config "$rofi_config")"
+ [[ -z "$choice" ]] && exit 0
+
+ case "$choice" in
+ *Dwindle*) target="dwindle" ;;
+ *Scrolling*) target="scrolling" ;;
+ *Monocle*) target="monocle" ;;
+ *Master*) target="master" ;;
+ *) exit 1 ;;
+ esac
+
+ set_layout "$target"
+}
+
+case "${1:-status}" in
+status)
+ show_status
+ ;;
+menu)
+ show_menu
+ ;;
+next|toggle)
+ set_layout "$(next_layout "$(get_layout)")"
+ ;;
+dwindle|scrolling|monocle|master)
+ set_layout "$1"
+ ;;
+*)
+ echo "Usage: $(basename "$0") [status|menu|next|dwindle|scrolling|monocle|master]" >&2
+ exit 1
+ ;;
+esac
diff --git a/config/hypr/scripts/JavaManager.sh b/config/hypr/scripts/JavaManager.sh
new file mode 100755
index 00000000..728c69a3
--- /dev/null
+++ b/config/hypr/scripts/JavaManager.sh
@@ -0,0 +1,245 @@
+#!/usr/bin/env bash
+
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# Script to manage Java runtimes
+# Based on script from https://github.com/jmhorcas
+# Submitted to KoolDots >https://github.com/LinuxBeginnings/Hyprland-Dots/issues/49
+
+# --- 1. Icons (Nerd Fonts) ---
+ICON_JAVA=""
+ICON_ACTIVE="󰄬"
+ICON_INSTALLED=""
+ICON_REMOTE=" "
+
+# --- 2. Distro detection ---
+if [ -r /etc/os-release ]; then
+ . /etc/os-release
+fi
+
+DISTRO="unknown"
+case "${ID:-}" in
+arch) DISTRO="arch" ;;
+debian | ubuntu | linuxmint) DISTRO="debian" ;;
+fedora) DISTRO="fedora" ;;
+opensuse* | sles) DISTRO="opensuse" ;;
+esac
+
+if [ "$DISTRO" = "unknown" ] && [ -n "${ID_LIKE:-}" ]; then
+ case "$ID_LIKE" in
+ *arch*) DISTRO="arch" ;;
+ *debian* | *ubuntu*) DISTRO="debian" ;;
+ *fedora*) DISTRO="fedora" ;;
+ *suse*) DISTRO="opensuse" ;;
+ esac
+fi
+
+if [ "$DISTRO" = "unknown" ]; then
+ notify-send "Error" "Unsupported distro for now."
+ exit 1
+fi
+
+# --- 3. Package helpers ---
+list_installed_pkgs() {
+ case "$DISTRO" in
+ arch) pacman -Qq | grep -E '^jdk.*-openjdk$' ;;
+ debian) dpkg -l 'openjdk-*-jdk' 2>/dev/null | awk '/^ii/ {print $2}' ;;
+ fedora | opensuse) rpm -qa | grep -E '^java-[0-9]+-openjdk' ;;
+ esac
+}
+
+list_available_pkgs() {
+ case "$DISTRO" in
+ arch) pacman -Ssq '^jdk.*-openjdk$' | sort -u ;;
+ debian) apt-cache search openjdk- | awk '{print $1}' | grep -E '^openjdk-[0-9]+-jdk$' | sort -u ;;
+ fedora) dnf -q repoquery --qf '%{name}' 'java-*-openjdk' 2>/dev/null | grep -E '^java-[0-9]+-openjdk' | sort -u ;;
+ opensuse) zypper -n search -s 'java-*-openjdk' 2>/dev/null | awk -F'|' '{print $2}' | xargs -n1 | grep -E '^java-[0-9]+-openjdk' | sort -u ;;
+ esac
+}
+
+pkg_description() {
+ local pkg="$1"
+ case "$DISTRO" in
+ arch) pacman -Si "$pkg" | grep "Description" | cut -d ':' -f2- | head -n 1 | xargs ;;
+ debian) apt-cache show "$pkg" 2>/dev/null | awk -F': ' '/^Description/ {print $2; exit}' ;;
+ fedora) dnf info -q "$pkg" 2>/dev/null | awk -F': ' '/^Summary/ {print $2; exit}' ;;
+ opensuse) zypper -n info "$pkg" 2>/dev/null | awk -F': ' '/^Summary/ {print $2; exit}' ;;
+ esac
+}
+
+get_active_version_raw() {
+ case "$DISTRO" in
+ arch) archlinux-java get ;;
+ *) java -version 2>&1 | awk -F\" '/version/ {print $2; exit}' ;;
+ esac
+}
+
+get_active_version_num() {
+ local raw="$1"
+ echo "$raw" | grep -oE '[0-9]+' | head -n1
+}
+
+list_java_alternatives() {
+ case "$DISTRO" in
+ debian) update-alternatives --list java 2>/dev/null ;;
+ fedora | opensuse) alternatives --list java 2>/dev/null ;;
+ *) echo "" ;;
+ esac
+}
+
+set_default_java() {
+ local sel_num="$1"
+ case "$DISTRO" in
+ arch)
+ local java_env
+ java_env=$(archlinux-java status | grep "java-$sel_num" | awk '{print $1}' | head -n 1)
+ if [ -n "$java_env" ]; then
+ notify-send "Java" "Setting $java_env as default..."
+ pkexec archlinux-java set "$java_env"
+ else
+ notify-send "Error" "Version $sel_num is not installed. Install it first."
+ fi
+ ;;
+ debian | fedora | opensuse)
+ local alt_path
+ alt_path=$(list_java_alternatives | grep -E "java-$sel_num|jdk-$sel_num|openjdk-$sel_num" | head -n1)
+ if [ -n "$alt_path" ]; then
+ notify-send "Java" "Setting Java $sel_num as default..."
+ if [ "$DISTRO" = "debian" ]; then
+ pkexec update-alternatives --set java "$alt_path"
+ else
+ pkexec alternatives --set java "$alt_path"
+ fi
+ else
+ notify-send "Error" "Version $sel_num is not installed. Install it first."
+ fi
+ ;;
+ esac
+}
+
+install_pkg() {
+ local pkg="$1"
+ case "$DISTRO" in
+ arch) kitty -e sudo pacman -S "$pkg" ;;
+ debian) kitty -e sudo apt install "$pkg" ;;
+ fedora) kitty -e sudo dnf install "$pkg" ;;
+ opensuse) kitty -e sudo zypper install "$pkg" ;;
+ esac
+}
+
+remove_pkg() {
+ local pkg="$1"
+ case "$DISTRO" in
+ arch) kitty -e sudo pacman -Rs "$pkg" ;;
+ debian) kitty -e sudo apt remove "$pkg" ;;
+ fedora) kitty -e sudo dnf remove "$pkg" ;;
+ opensuse) kitty -e sudo zypper remove "$pkg" ;;
+ esac
+}
+
+# --- 4. Initial data ---
+INSTALLED_PKGS=$(list_installed_pkgs)
+TEMP_ALL=$(list_available_pkgs)
+
+ACTIVE_VERSION_RAW=$(get_active_version_raw)
+ACTIVE_VERSION_NUM=$(get_active_version_num "$ACTIVE_VERSION_RAW")
+
+if [ "$DISTRO" = "arch" ]; then
+ TEMP_ALL_SYSTEM=$(archlinux-java status)
+ LATEST_VERSION=$(echo "$TEMP_ALL" "$TEMP_ALL_SYSTEM" | grep -oE '[0-9]+' | sort -nr | head -n1)
+else
+ LATEST_VERSION=$(echo "$TEMP_ALL" | grep -oE '[0-9]+' | sort -nr | head -n1)
+fi
+
+ALL_AVAILABLE=$(echo "$TEMP_ALL" | awk -v lv="$LATEST_VERSION" '{
+ v=$0; gsub(/[^0-9]/,"",v);
+ if(v=="") v=lv+1;
+ print v " " $0
+}' | sort -nr | cut -d' ' -f2-)
+
+# --- 5. Functions ---
+get_version_num() {
+ local pkg="$1"
+ local v=$(echo "$pkg" | grep -oE '[0-9]+')
+ # If there is not a number, it is the "latest"
+ if [ -z "$v" ]; then
+ echo "$LATEST_VERSION"
+ else
+ echo "$v"
+ fi
+}
+
+generate_list() {
+ for pkg in $ALL_AVAILABLE; do
+ DESC=$(pkg_description "$pkg")
+
+ VERSION=$(get_version_num "$pkg")
+ ICON="$ICON_REMOTE"
+ # We use a temporary variable for the icon to avoid overwriting ICON_REMOTE
+ DISPLAY_ICON="$ICON_REMOTE"
+
+ # 1. Is it installed?
+ if echo "$INSTALLED_PKGS" | grep -q "^$pkg$"; then
+ DISPLAY_ICON="$ICON_INSTALLED"
+ fi
+
+ # 2. Is it the active one?
+ # We compare if the number matches OR if the raw name matches
+ if [[ "$VERSION" == "$ACTIVE_VERSION_NUM" ]] || [[ "$pkg" == "$ACTIVE_VERSION_RAW" ]]; then
+ DISPLAY_ICON="$ICON_ACTIVE"
+ fi
+
+ # Ensure that if the icon is empty (remote) it maintains the space
+ [ -z "$DISPLAY_ICON" ] && DISPLAY_ICON=" "
+
+ printf "%s %s %s │ %s\n" "$ICON_JAVA" "$DISPLAY_ICON" "$DESC" "$pkg"
+ done
+}
+
+# --- 6. rofi ---
+THEME="$HOME/.config/rofi/config.rasi"
+
+SELECTION=$(generate_list | rofi -dmenu -i \
+ -p "󰒓 Java" \
+ -config "$THEME" \
+ -theme-str '
+ window { width: 1400px; }
+ listview { scrollbar: true; }
+ inputbar { children: [ "prompt", "textbox-prompt-colon", "entry" ]; }
+ prompt { background-color: @selected; text-color: @background; padding: 4px 8px; border-radius: 4px; }
+ ' \
+ -kb-custom-1 "Alt+i" \
+ -kb-custom-2 "Alt+r" \
+ -mesg "<b>$ICON_ACTIVE</b> Default | <b>$ICON_INSTALLED</b> Installed | <b>Enter:</b> Set default | <b>Alt+I:</b> Install | <b>Alt+R:</b> Remove")
+
+EXIT_CODE=$?
+[ -z "$SELECTION" ] && exit 0
+
+# --- 7. Clean selection ---
+# 1. Extract the package name from the right side of the │ separator
+PKG_NAME=$(echo "$SELECTION" | awk -F'│' '{print $2}' | xargs | awk '{print $1}')
+
+# 2. Get the real number contained in the name (if it exists)
+SEL_RAW_NUM=$(echo "$PKG_NAME" | grep -oE '[0-9]+')
+
+# If it doesn't have a value (it's the latest package), assign LATEST_VERSION
+if [ -z "$SEL_RAW_NUM" ]; then
+ SEL_RAW_NUM="$LATEST_VERSION"
+fi
+
+# --- 8. Actions ---
+case $EXIT_CODE in
+0) # SET DEFAULT
+ set_default_java "$SEL_RAW_NUM"
+ ;;
+10) # INSTALL
+ install_pkg "$PKG_NAME"
+ ;;
+11) # REMOVE
+ remove_pkg "$PKG_NAME"
+ ;;
+esac
diff --git a/config/hypr/scripts/KeyBinds.sh b/config/hypr/scripts/KeyBinds.sh
index 69111047..1005e797 100755
--- a/config/hypr/scripts/KeyBinds.sh
+++ b/config/hypr/scripts/KeyBinds.sh
@@ -16,15 +16,42 @@ if pidof rofi > /dev/null; then
fi
# define the config files
-keybinds_conf="$HOME/.config/hypr/configs/Keybinds.conf"
-user_keybinds_conf="$HOME/.config/hypr/UserConfigs/UserKeybinds.conf"
-laptop_conf="$HOME/.config/hypr/UserConfigs/Laptops.conf"
+config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
+hypr_dir="$config_home/hypr"
+keybinds_conf="$hypr_dir/configs/Keybinds.conf"
+user_keybinds_conf="$hypr_dir/UserConfigs/UserKeybinds.conf"
+laptop_conf="$hypr_dir/UserConfigs/Laptops.conf"
+lua_keybinds_conf="$hypr_dir/lua/keybinds.lua"
+lua_user_keybinds="$hypr_dir/UserConfigs/user_keybinds.lua"
+lua_system_keybinds="$hypr_dir/configs/system_keybinds.lua"
+lua_legacy_system_keybinds="$hypr_dir/UserConfigs/system_keybinds.lua"
+lua_overrides="$hypr_dir/UserConfigs/user_overrides.lua"
rofi_theme="$HOME/.config/rofi/config-keybinds.rasi"
msg='☣️ NOTE ☣️: Clicking with Mouse or Pressing ENTER will have NO function'
-# collect raw bind lines (strip end-of-line comments) from available files
-files=("$keybinds_conf" "$user_keybinds_conf")
-[[ -f "$laptop_conf" ]] && files+=("$laptop_conf")
+# detect active Hyprland config mode (Lua entrypoint vs legacy .conf includes)
+lua_entry="$hypr_dir/hyprland.lua"
+legacy_lua_entry="$config_home/hyprland.lua"
+if [[ -f "$lua_entry" || -f "$legacy_lua_entry" ]]; then
+ hypr_config_mode="lua"
+else
+ hypr_config_mode="conf"
+fi
+
+# collect raw bind lines from available files
+if [[ "$hypr_config_mode" == "lua" ]]; then
+ files=("$lua_keybinds_conf")
+ if [[ -f "$lua_system_keybinds" ]]; then
+ files+=("$lua_system_keybinds")
+ elif [[ -f "$lua_legacy_system_keybinds" ]]; then
+ files+=("$lua_legacy_system_keybinds")
+ fi
+ [[ -f "$lua_user_keybinds" ]] && files+=("$lua_user_keybinds")
+ [[ -f "$lua_overrides" ]] && files+=("$lua_overrides")
+else
+ files=("$keybinds_conf" "$user_keybinds_conf")
+ [[ -f "$laptop_conf" ]] && files+=("$laptop_conf")
+fi
# Parse binds using the python script for speed
# The last argument must be the user config for override logic to work correctly
diff --git a/config/hypr/scripts/KeybindsLayoutInit.sh b/config/hypr/scripts/KeybindsLayoutInit.sh
index f47197af..280e381b 100755
--- a/config/hypr/scripts/KeybindsLayoutInit.sh
+++ b/config/hypr/scripts/KeybindsLayoutInit.sh
@@ -5,8 +5,7 @@
# License: GNU GPLv3
# SPDX-License-Identifier: GPL-3.0-or-later
# ==================================================
-# Initialize J/K keybinds so they always cycle windows globally (no layout-specific behavior)
-# This avoids double-actions when layouts change.
+# Initialize J/K keybinds so they always cycle windows globally (no layout-specific behavior).
set -euo pipefail
@@ -15,5 +14,5 @@ hyprctl keyword unbind SUPER,j || true
hyprctl keyword unbind SUPER,k || true
# Cycle windows globally
-hyprctl keyword bind SUPER,j,layoutmsg,cyclenext
-hyprctl keyword bind SUPER,k,layoutmsg,cycleprev
+hyprctl keyword bind SUPER,j,cyclenext
+hyprctl keyword bind SUPER,k,cyclenext,prev
diff --git a/config/hypr/scripts/Kitty_themes.sh b/config/hypr/scripts/Kitty_themes.sh
index 3183b20b..24a4ae11 100755
--- a/config/hypr/scripts/Kitty_themes.sh
+++ b/config/hypr/scripts/Kitty_themes.sh
@@ -12,22 +12,55 @@ kitty_themes_DiR="$HOME/.config/kitty/kitty-themes" # Kitty Themes Directory
kitty_config="$HOME/.config/kitty/kitty.conf"
iDIR="$HOME/.config/swaync/images" # For notifications
rofi_theme_for_this_script="$HOME/.config/rofi/config-kitty-theme.rasi"
+wallust_refresh_script="$HOME/.config/hypr/scripts/WallustSwww.sh"
+debug_log="${XDG_CACHE_HOME:-$HOME/.cache}/kooldots-kitty-themes.log"
# --- Helper Functions ---
notify_user() {
notify-send -u low -i "$1" "$2" "$3"
}
+log_debug() {
+ mkdir -p "$(dirname "$debug_log")" 2>/dev/null || true
+ printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >>"$debug_log" 2>/dev/null || true
+}
+
+resolve_theme_selection() {
+ local rofi_output="$1"
+ local idx
+
+ rofi_output="${rofi_output//$'\r'/}"
+ rofi_output="${rofi_output//$'\n'/}"
+
+ if [[ "$rofi_output" =~ ^[0-9]+$ ]] && [ "$rofi_output" -lt "${#available_theme_names[@]}" ]; then
+ current_selection_index="$rofi_output"
+ theme_to_preview_now="${available_theme_names[$current_selection_index]}"
+ return 0
+ fi
+
+ for idx in "${!available_theme_names[@]}"; do
+ if [[ "${available_theme_names[$idx]}" == "$rofi_output" ]]; then
+ current_selection_index="$idx"
+ theme_to_preview_now="${available_theme_names[$current_selection_index]}"
+ return 0
+ fi
+ done
+
+ return 1
+}
+
# Function to apply the selected kitty theme
apply_kitty_theme_to_config() {
local theme_name_to_apply="$1"
local apply_mode="${2:-preview}"
+ local is_wallpaper_mode=0
if [ -z "$theme_name_to_apply" ]; then
echo "Error: No theme name provided to apply_kitty_theme_to_config." >&2
return 1
fi
local theme_file_path_to_apply
if [ "$theme_name_to_apply" = "Set by wallpaper" ]; then
+ is_wallpaper_mode=1
theme_file_path_to_apply="$kitty_themes_DiR/01-Wallust.conf"
elif [ "$theme_name_to_apply" = "Default no color" ]; then
theme_file_path_to_apply="$kitty_themes_DiR/00-Default.conf"
@@ -58,10 +91,20 @@ apply_kitty_theme_to_config() {
cp "$temp_kitty_config_file" "$kitty_config"
rm "$temp_kitty_config_file"
+ local trigger_wallust_refresh=0
+ if [ "$theme_name_to_apply" = "Set by wallpaper" ] && [ -x "$wallust_refresh_script" ]; then
+ trigger_wallust_refresh=1
+ fi
+ if [ "$trigger_wallust_refresh" -eq 1 ]; then
+ "$wallust_refresh_script" >/dev/null 2>&1 &
+ log_debug "wallust_refresh_background_started"
+ fi
if pidof kitty >/dev/null 2>&1; then
- if [ "$apply_mode" = "apply" ] && command -v kitty >/dev/null 2>&1; then
- kitty @ load-config >/dev/null 2>&1
- kitty @ set-colors --all --configured "$theme_file_path_to_apply" >/dev/null 2>&1
+ if [ "$apply_mode" = "apply" ] && [ "$is_wallpaper_mode" -eq 0 ] && command -v kitty >/dev/null 2>&1; then
+ (
+ kitty @ load-config >/dev/null 2>&1 || true
+ kitty @ set-colors --all --configured "$theme_file_path_to_apply" >/dev/null 2>&1 || true
+ ) &
fi
for pid_kitty in $(pidof kitty); do
if [ -n "$pid_kitty" ]; then
@@ -110,6 +153,7 @@ if [ -n "$current_active_theme_name" ]; then
fi
done
fi
+theme_to_preview_now="${available_theme_names[$current_selection_index]}"
while true; do
@@ -119,21 +163,22 @@ while true; do
done
rofi_input_list_trimmed="${rofi_input_list%\\n}"
- chosen_index_from_rofi=$(echo -e "$rofi_input_list_trimmed" |
+ chosen_selection_from_rofi=$(echo -e "$rofi_input_list_trimmed" |
rofi -dmenu -i \
+ -no-custom \
-format 'i' \
-p "Kitty Theme" \
- -mesg "Enter: Preview | Ctrl+S: Apply & Exit | Esc: Cancel" \
+ -mesg "Enter: Preview | Ctrl+S (or Alt+1): Apply & Exit | Esc: Cancel" \
-config "$rofi_theme_for_this_script" \
-selected-row "$current_selection_index" \
- -kb-custom-1 "Control+s")
+ -kb-custom-1 "Control+s,Control+S,Alt+1")
rofi_exit_code=$?
+ log_debug "rofi_exit=$rofi_exit_code rofi_output='${chosen_selection_from_rofi}' current_index=$current_selection_index current_theme='${available_theme_names[$current_selection_index]}'"
if [ $rofi_exit_code -eq 0 ]; then
- if [[ "$chosen_index_from_rofi" =~ ^[0-9]+$ ]] && [ "$chosen_index_from_rofi" -lt "${#available_theme_names[@]}" ]; then
- current_selection_index="$chosen_index_from_rofi"
- theme_to_preview_now="${available_theme_names[$current_selection_index]}"
+ if resolve_theme_selection "$chosen_selection_from_rofi"; then
+ log_debug "resolved_enter index=$current_selection_index theme='${theme_to_preview_now}'"
if ! apply_kitty_theme_to_config "$theme_to_preview_now" "preview"; then
echo "$original_kitty_config_content_backup" >"$kitty_config"
for pid_kitty in $(pidof kitty); do if [ -n "$pid_kitty" ]; then kill -SIGUSR1 "$pid_kitty"; fi; done
@@ -149,7 +194,9 @@ while true; do
echo "$original_kitty_config_content_backup" >"$kitty_config"
for pid_kitty in $(pidof kitty); do if [ -n "$pid_kitty" ]; then kill -SIGUSR1 "$pid_kitty"; fi; done
break
- elif [ $rofi_exit_code -eq 10 ]; then # This is the exit code for -kb-custom-1
+ elif [ $rofi_exit_code -ge 10 ] && [ $rofi_exit_code -le 28 ]; then # custom keybindings
+ resolve_theme_selection "$chosen_selection_from_rofi" || true
+ log_debug "resolved_custom index=$current_selection_index theme='${theme_to_preview_now}' exit=$rofi_exit_code"
apply_kitty_theme_to_config "$theme_to_preview_now" "apply"
notify_user "$iDIR/ja.png" "Kitty Theme Applied" "$theme_to_preview_now"
break
diff --git a/config/hypr/scripts/Kool_Quick_Settings.sh b/config/hypr/scripts/Kool_Quick_Settings.sh
index fcd04998..6ec02bb8 100755
--- a/config/hypr/scripts/Kool_Quick_Settings.sh
+++ b/config/hypr/scripts/Kool_Quick_Settings.sh
@@ -8,22 +8,52 @@
# Rofi menu for KooL Hyprland Quick Settings (SUPER SHIFT E)
# Updated for UserConfigs/configs separation
-# Modify this config file for default terminal and EDITOR
-config_file="$HOME/.config/hypr/UserConfigs/01-UserDefaults.conf"
+# Detect active Hyprland config mode (Lua entrypoint vs legacy .conf includes)
+config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
+hypr_dir="$config_home/hypr"
+lua_entry="$hypr_dir/hyprland.lua"
+legacy_lua_entry="$config_home/hyprland.lua"
+if [[ -f "$lua_entry" || -f "$legacy_lua_entry" ]]; then
+ hypr_config_mode="lua"
+else
+ hypr_config_mode="conf"
+fi
+
+# Resolve defaults file used to get terminal/editor values
+config_file="$hypr_dir/UserConfigs/01-UserDefaults.conf"
+lua_defaults_file="$hypr_dir/UserConfigs/user_defaults.lua"
+term="${term:-${TERM:-kitty}}"
+edit="${edit:-${EDITOR:-nano}}"
+visual="${visual:-${VISUAL:-}}"
-tmp_config_file=$(mktemp)
-sed 's/^\$//g; s/ = /=/g' "$config_file" > "$tmp_config_file"
-source "$tmp_config_file"
+if [[ "$hypr_config_mode" == "conf" && -f "$config_file" ]]; then
+ tmp_config_file=$(mktemp)
+ sed 's/^\$//g; s/ = /=/g' "$config_file" > "$tmp_config_file"
+ source "$tmp_config_file"
+elif [[ "$hypr_config_mode" == "lua" ]]; then
+ defaults_source=""
+ if [[ -f "$lua_defaults_file" ]]; then
+ defaults_source="$lua_defaults_file"
+ fi
+ if [[ -n "$defaults_source" ]]; then
+ lua_term=$(sed -n 's/^[[:space:]]*KOOLDOTS_DEFAULTS\.term[[:space:]]*=[[:space:]]*"\(.*\)"[[:space:]]*$/\1/p' "$defaults_source" | tail -n1)
+ lua_edit=$(sed -n 's/^[[:space:]]*KOOLDOTS_DEFAULTS\.edit[[:space:]]*=[[:space:]]*"\(.*\)"[[:space:]]*$/\1/p' "$defaults_source" | tail -n1)
+ lua_visual=$(sed -n 's/^[[:space:]]*KOOLDOTS_DEFAULTS\.visual[[:space:]]*=[[:space:]]*"\(.*\)"[[:space:]]*$/\1/p' "$defaults_source" | tail -n1)
+ [[ -n "$lua_term" ]] && term="$lua_term"
+ [[ -n "$lua_edit" ]] && edit="$lua_edit"
+ [[ -n "$lua_visual" ]] && visual="$lua_visual"
+ fi
+fi
# ##################################### #
# variables
-configs="$HOME/.config/hypr/configs"
-UserConfigs="$HOME/.config/hypr/UserConfigs"
+configs="$hypr_dir/configs"
+UserConfigs="$hypr_dir/UserConfigs"
rofi_theme="$HOME/.config/rofi/config-edit.rasi"
msg=' ⁉️ Choose what to do ⁉️'
iDIR="$HOME/.config/swaync/images"
-scriptsDir="$HOME/.config/hypr/scripts"
-UserScripts="$HOME/.config/hypr/UserScripts"
+scriptsDir="$hypr_dir/scripts"
+UserScripts="$hypr_dir/UserScripts"
# Function to show info notification
show_info() {
@@ -33,6 +63,50 @@ show_info() {
notify-send "Info" "$1"
fi
}
+
+# Determine whether an editor command is terminal-based (TUI)
+is_tui_editor() {
+ local -a cmd=("$@")
+ local bin base arg
+ [[ ${#cmd[@]} -eq 0 ]] && return 1
+
+ bin="${cmd[0]}"
+ base="$(basename "$bin")"
+
+ case "$base" in
+ vi|vim|nvim|nano|hx|helix|kak|micro|emacs-nox)
+ return 0
+ ;;
+ emacs|emacsclient)
+ for arg in "${cmd[@]:1}"; do
+ case "$arg" in
+ -nw|--no-window-system|-t|--tty)
+ return 0
+ ;;
+ esac
+ done
+ return 1
+ ;;
+ esac
+
+ return 1
+}
+
+resolve_system_lua_file() {
+ local file_name="$1"
+ local preferred="$configs/$file_name"
+ local legacy="$UserConfigs/$file_name"
+ if [[ -f "$preferred" || ! -f "$legacy" ]]; then
+ printf '%s' "$preferred"
+ else
+ printf '%s' "$legacy"
+ fi
+}
+
+resolve_user_defaults_lua_file() {
+ local preferred="$UserConfigs/user_defaults.lua"
+ printf '%s' "$preferred"
+}
# Function to toggle Rainbow Borders script availability and refresh UI components
toggle_rainbow_borders() {
local rainbow_script="$UserScripts/RainbowBorders.sh"
@@ -186,6 +260,7 @@ Edit User Keybinds
Edit User ENV variables
Edit User Startup Apps (overlay)
Edit User Window Rules (overlay)
+Edit User Layer Rules (overlay)
Edit User Settings
Edit User Decorations
Edit User Animations
@@ -194,6 +269,7 @@ Edit User Laptop Settings
Edit System Default Keybinds
Edit System Default Startup Apps
Edit System Default Window Rules
+Edit System Default Layer Rules
Edit System Default Settings
--- UTILITIES ---
Set SDDM Wallpaper
@@ -221,19 +297,42 @@ main() {
# Map choices to corresponding files
case "$choice" in
- "Edit User Defaults") file="$UserConfigs/01-UserDefaults.conf" ;;
- "Edit User ENV variables") file="$UserConfigs/ENVariables.conf" ;;
- "Edit User Keybinds") file="$UserConfigs/UserKeybinds.conf" ;;
- "Edit User Startup Apps (overlay)") file="$UserConfigs/Startup_Apps.conf" ;;
- "Edit User Window Rules (overlay)") file="$UserConfigs/WindowRules.conf" ;;
- "Edit User Settings") file="$configs/SystemSettings.conf"; show_info "Editing default settings. Copy to UserConfigs/UserSettings.conf to override." ;;
- "Edit User Decorations") file="$UserConfigs/UserDecorations.conf" ;;
- "Edit User Animations") file="$UserConfigs/UserAnimations.conf" ;;
- "Edit User Laptop Settings") file="$UserConfigs/Laptops.conf" ;;
- "Edit System Default Keybinds") file="$configs/Keybinds.conf" ;;
- "Edit System Default Startup Apps") file="$configs/Startup_Apps.conf" ;;
- "Edit System Default Window Rules") file="$configs/WindowRules.conf" ;;
- "Edit System Default Settings") file="$configs/SystemSettings.conf" ;;
+ "Edit User Defaults")
+ if [[ "$hypr_config_mode" == "lua" ]]; then file="$(resolve_user_defaults_lua_file)"; else file="$UserConfigs/01-UserDefaults.conf"; fi ;;
+ "Edit User ENV variables")
+ if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_env.lua"; else file="$UserConfigs/ENVariables.conf"; fi ;;
+ "Edit User Keybinds")
+ if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_keybinds.lua"; else file="$UserConfigs/UserKeybinds.conf"; fi ;;
+ "Edit User Startup Apps (overlay)")
+ if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_startup.lua"; else file="$UserConfigs/Startup_Apps.conf"; fi ;;
+ "Edit User Window Rules (overlay)")
+ if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_window_rules.lua"; else file="$UserConfigs/WindowRules.conf"; fi ;;
+ "Edit User Layer Rules (overlay)")
+ if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_layer_rules.lua"; else file="$UserConfigs/LayerRules.conf"; fi ;;
+ "Edit User Settings")
+ if [[ "$hypr_config_mode" == "lua" ]]; then
+ file="$UserConfigs/user_settings.lua"
+ show_info "Lua mode detected. Edit UserConfigs/user_settings.lua for user settings."
+ else
+ file="$configs/SystemSettings.conf"
+ show_info "Editing default settings. Copy to UserConfigs/UserSettings.conf to override."
+ fi ;;
+ "Edit User Decorations")
+ if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_decorations.lua"; else file="$UserConfigs/UserDecorations.conf"; fi ;;
+ "Edit User Animations")
+ if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_animations.lua"; else file="$UserConfigs/UserAnimations.conf"; fi ;;
+ "Edit User Laptop Settings")
+ if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_laptops.lua"; else file="$UserConfigs/Laptops.conf"; fi ;;
+ "Edit System Default Keybinds")
+ if [[ "$hypr_config_mode" == "lua" ]]; then file="$(resolve_system_lua_file system_keybinds.lua)"; else file="$configs/Keybinds.conf"; fi ;;
+ "Edit System Default Startup Apps")
+ if [[ "$hypr_config_mode" == "lua" ]]; then file="$(resolve_system_lua_file system_startup.lua)"; else file="$configs/Startup_Apps.conf"; fi ;;
+ "Edit System Default Window Rules")
+ if [[ "$hypr_config_mode" == "lua" ]]; then file="$(resolve_system_lua_file system_window_rules.lua)"; else file="$configs/WindowRules.conf"; fi ;;
+ "Edit System Default Layer Rules")
+ if [[ "$hypr_config_mode" == "lua" ]]; then file="$(resolve_system_lua_file system_layer_rules.lua)"; else file="$configs/LayerRules.conf"; fi ;;
+ "Edit System Default Settings")
+ if [[ "$hypr_config_mode" == "lua" ]]; then file="$(resolve_system_lua_file system_settings.lua)"; else file="$configs/SystemSettings.conf"; fi ;;
"Set SDDM Wallpaper") $scriptsDir/sddm_wallpaper.sh --normal ;;
"Choose Kitty Terminal Theme") $scriptsDir/Kitty_themes.sh ;;
"Choose Ghostty Terminal Theme") $scriptsDir/Ghostty_themes.sh ;;
@@ -278,9 +377,20 @@ main() {
*) return ;; # Do nothing for invalid choices
esac
- # Open the selected file in the terminal with the text editor
+ # Open selected file using configured editor
if [ -n "$file" ]; then
- $term -e $edit "$file"
+ local -a edit_cmd term_cmd visual_cmd selected_cmd
+ read -r -a edit_cmd <<< "$edit"
+ read -r -a term_cmd <<< "$term"
+ [[ -n "$visual" ]] && read -r -a visual_cmd <<< "$visual"
+ selected_cmd=("${edit_cmd[@]}")
+ [[ ${#visual_cmd[@]} -gt 0 ]] && selected_cmd=("${visual_cmd[@]}")
+
+ if is_tui_editor "${selected_cmd[@]}"; then
+ "${term_cmd[@]}" -e "${selected_cmd[@]}" "$file"
+ else
+ "${selected_cmd[@]}" "$file" >/dev/null 2>&1 &
+ fi
fi
}
diff --git a/config/hypr/scripts/Logout.sh b/config/hypr/scripts/Logout.sh
new file mode 100755
index 00000000..2f173ffe
--- /dev/null
+++ b/config/hypr/scripts/Logout.sh
@@ -0,0 +1,180 @@
+#!/usr/bin/env bash
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# Logout helper for wlogout and keybind callers.
+LOG_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/hypr"
+LOG_FILE="${LOG_DIR}/hypr-logout.log"
+if ! mkdir -p "$LOG_DIR" >/dev/null 2>&1; then
+ LOG_FILE="${XDG_RUNTIME_DIR:-/tmp}/hypr-logout.log"
+fi
+
+log_msg() {
+ printf "[%s] %s\n" "$(date +"%F %T")" "$1" >>"$LOG_FILE"
+}
+
+run_logged() {
+ local label="$1"
+ shift
+ log_msg "RUN ${label}: $*"
+ "$@" >>"$LOG_FILE" 2>&1
+ local rc=$?
+ log_msg "RC ${label}: ${rc}"
+ return "$rc"
+}
+SESSION_USER="${USER:-$(id -un)}"
+SESSION_HYPRLAND_PIDS="$(pgrep -xu "$SESSION_USER" -x Hyprland || true)"
+SESSION_DM_SERVICE=""
+IS_SDDM_SESSION=0
+
+session_hyprland_running() {
+ local pid
+ if [ -n "$SESSION_HYPRLAND_PIDS" ]; then
+ for pid in $SESSION_HYPRLAND_PIDS; do
+ if kill -0 "$pid" >/dev/null 2>&1; then
+ return 0
+ fi
+ done
+ return 1
+ fi
+ pgrep -xu "$SESSION_USER" -x Hyprland >/dev/null 2>&1
+}
+logout_completed() {
+ # Give the session up to 2 seconds to terminate after a successful command.
+ for _ in {1..20}; do
+ session_hyprland_running || return 0
+ sleep 0.1
+ done
+ return 1
+}
+stop_proc() {
+ local name="$1"
+ pkill -u "$SESSION_USER" -x -TERM "$name" >/dev/null 2>&1 || true
+
+ # Wait up to 1 second for graceful shutdown.
+ for _ in {1..10}; do
+ pgrep -xu "$SESSION_USER" -x "$name" >/dev/null 2>&1 || return 0
+ sleep 0.1
+ done
+ pkill -u "$SESSION_USER" -x -KILL "$name" >/dev/null 2>&1 || true
+}
+
+# Close wlogout if it is still visible.
+stop_proc "wlogout"
+HYPRCTL_BIN="$(command -v hyprctl || true)"
+HYPRSHUTDOWN_BIN="$(command -v hyprshutdown || true)"
+UWSM_BIN="$(command -v uwsm || true)"
+LOGINCTL_BIN="$(command -v loginctl || true)"
+if [ -n "$LOGINCTL_BIN" ] && [ -n "${XDG_SESSION_ID:-}" ]; then
+ SESSION_DM_SERVICE="$("$LOGINCTL_BIN" show-session "$XDG_SESSION_ID" -p Service --value 2>/dev/null || true)"
+ if [ "$SESSION_DM_SERVICE" = "sddm" ] || [ "$SESSION_DM_SERVICE" = "sddm-autologin" ]; then
+ IS_SDDM_SESSION=1
+ fi
+fi
+
+# Preferred path: synchronous hyprshutdown, so script does not silently succeed.
+if [ -n "$HYPRSHUTDOWN_BIN" ]; then
+ if run_logged "hyprshutdown-no-fork" "$HYPRSHUTDOWN_BIN" --no-fork; then
+ if logout_completed; then
+ exit 0
+ fi
+ log_msg "hyprshutdown returned success but Hyprland is still running"
+ fi
+fi
+# systemd session fallback.
+if [ -n "$LOGINCTL_BIN" ] && [ -n "${XDG_SESSION_ID:-}" ]; then
+ if [ "$IS_SDDM_SESSION" -eq 1 ]; then
+ log_msg "Skipping loginctl terminate-session for SDDM-managed session (${SESSION_DM_SERVICE})"
+ elif run_logged "loginctl-terminate-session" "$LOGINCTL_BIN" terminate-session "$XDG_SESSION_ID"; then
+ if logout_completed; then
+ exit 0
+ fi
+ log_msg "loginctl terminate-session returned success but Hyprland is still running"
+ fi
+fi
+
+# Fallback: ask Hyprland to spawn hyprshutdown via a normal dispatch exec call.
+if [ -n "$HYPRCTL_BIN" ] && [ -n "$HYPRSHUTDOWN_BIN" ]; then
+ if run_logged \
+ "hyprctl-dispatch-exec-hyprshutdown" \
+ "$HYPRCTL_BIN" dispatch exec "hyprshutdown --no-fork"; then
+ if logout_completed; then
+ exit 0
+ fi
+ log_msg "hyprctl dispatched hyprshutdown but Hyprland is still running"
+ fi
+fi
+
+# UWSM-managed session fallback (common on NixOS).
+if [ -n "$UWSM_BIN" ] && [ "$IS_SDDM_SESSION" -eq 0 ]; then
+ if run_logged "uwsm-stop" "$UWSM_BIN" stop; then
+ if logout_completed; then
+ exit 0
+ fi
+ log_msg "uwsm stop returned success but Hyprland is still running"
+ fi
+elif [ -n "$UWSM_BIN" ] && [ "$IS_SDDM_SESSION" -eq 1 ]; then
+ log_msg "Skipping uwsm stop on SDDM-managed session to avoid delayed logout"
+fi
+
+
+# Last-resort Hyprland exit fallbacks.
+if [ -n "$HYPRCTL_BIN" ]; then
+ if [ "$IS_SDDM_SESSION" -eq 1 ]; then
+ if run_logged "hyprctl-exit-1-sddm" "$HYPRCTL_BIN" dispatch exit 1; then
+ if logout_completed; then
+ exit 0
+ fi
+ log_msg "hyprctl dispatch exit 1 (sddm) returned success but Hyprland is still running"
+ fi
+ if run_logged "hyprctl-exit-x-sddm" "$HYPRCTL_BIN" dispatch exit x; then
+ if logout_completed; then
+ exit 0
+ fi
+ log_msg "hyprctl dispatch exit x (sddm) returned success but Hyprland is still running"
+ fi
+ else
+ if run_logged "hyprctl-exit-1" "$HYPRCTL_BIN" dispatch exit 1; then
+ if logout_completed; then
+ exit 0
+ fi
+ log_msg "hyprctl dispatch exit 1 returned success but Hyprland is still running"
+ fi
+ if run_logged "hyprctl-exit-0" "$HYPRCTL_BIN" dispatch exit 0; then
+ if logout_completed; then
+ exit 0
+ fi
+ log_msg "hyprctl dispatch exit 0 returned success but Hyprland is still running"
+ fi
+ if run_logged "hyprctl-exit-x" "$HYPRCTL_BIN" dispatch exit x; then
+ if logout_completed; then
+ exit 0
+ fi
+ log_msg "hyprctl dispatch exit x returned success but Hyprland is still running"
+ fi
+ if run_logged "hyprctl-exit-noarg" "$HYPRCTL_BIN" dispatch exit; then
+ if logout_completed; then
+ exit 0
+ fi
+ log_msg "hyprctl dispatch exit (no arg) returned success but Hyprland is still running"
+ fi
+ fi
+fi
+
+# Final process-level fallback.
+if run_logged "pkill-hyprland-term" pkill -u "$SESSION_USER" -x -TERM Hyprland; then
+ if logout_completed; then
+ exit 0
+ fi
+ log_msg "SIGTERM sent to Hyprland but process is still running"
+fi
+if run_logged "pkill-hyprland-kill" pkill -u "$SESSION_USER" -x -KILL Hyprland; then
+ exit 0
+fi
+
+log_msg "Logout failed: no method succeeded"
+
+exit 1
diff --git a/config/hypr/scripts/LuaAutoReload.sh b/config/hypr/scripts/LuaAutoReload.sh
new file mode 100755
index 00000000..4a9d5040
--- /dev/null
+++ b/config/hypr/scripts/LuaAutoReload.sh
@@ -0,0 +1,47 @@
+#!/usr/bin/env bash
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# Auto-reload Hyprland when Lua config files change.
+
+set -euo pipefail
+
+watch_root="$HOME/.config/hypr"
+[ -d "$watch_root" ] || exit 0
+
+reload_hypr() {
+ hyprctl reload >/dev/null 2>&1 || true
+}
+
+if command -v inotifywait >/dev/null 2>&1; then
+ debounce_and_reload() {
+ sleep 0.2
+ while inotifywait -q -t 0.2 -e close_write,create,move,delete -r --include '(^|/)[^/]+\.lua$' "$watch_root" >/dev/null 2>&1; do
+ :
+ done
+ reload_hypr
+ }
+
+ inotifywait -m -q -r -e close_write,create,move,delete --include '(^|/)[^/]+\.lua$' "$watch_root" | while read -r _; do
+ debounce_and_reload
+ done
+ exit 0
+fi
+
+# Fallback polling path when inotify-tools isn't installed.
+snapshot() {
+ find "$watch_root" -type f -name '*.lua' -printf '%p:%T@\n' 2>/dev/null | LC_ALL=C sort
+}
+
+previous_state="$(snapshot)"
+while true; do
+ sleep 1
+ current_state="$(snapshot)"
+ if [ "$current_state" != "$previous_state" ]; then
+ previous_state="$current_state"
+ reload_hypr
+ fi
+done
diff --git a/config/hypr/scripts/LuaCycleWindow.sh b/config/hypr/scripts/LuaCycleWindow.sh
new file mode 100755
index 00000000..ee64e67a
--- /dev/null
+++ b/config/hypr/scripts/LuaCycleWindow.sh
@@ -0,0 +1,73 @@
+#!/usr/bin/env bash
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# Cycle focus through visible windows on the active workspace using the
+# Hyprland Lua dispatcher API. This avoids cyclenext/focuswindow no-ops on
+# Lua config builds.
+
+set -u
+
+direction="${1:-next}"
+case "$direction" in
+ next|forward|f)
+ direction="next"
+ ;;
+ previous|prev|back|b)
+ direction="previous"
+ ;;
+ *)
+ exit 0
+ ;;
+esac
+
+active_window="$(hyprctl activewindow -j 2>/dev/null || printf '{}')"
+active_address="$(jq -r '.address // empty' <<<"$active_window")"
+active_workspace="$(jq -r '.workspace.id // empty' <<<"$active_window")"
+
+if [[ -z "$active_address" ]] || ! [[ "$active_workspace" =~ ^-?[0-9]+$ ]]; then
+ exit 0
+fi
+
+clients="$(hyprctl clients -j 2>/dev/null || printf '[]')"
+target_address="$(
+ jq -r \
+ --arg active_address "$active_address" \
+ --argjson active_workspace "$active_workspace" \
+ --arg direction "$direction" '
+ [
+ .[]
+ | select((.mapped // false) == true)
+ | select((.hidden // false) == false)
+ | select(.workspace.id == $active_workspace)
+ | {
+ address,
+ x: (.at[0] // 0),
+ y: (.at[1] // 0)
+ }
+ ]
+ | sort_by(.y, .x, .address)
+ | if length < 2 then
+ empty
+ else
+ . as $windows
+ | ($windows | map(.address) | index($active_address)) as $index
+ | if $index == null then
+ empty
+ elif $direction == "previous" then
+ $windows[(($index - 1 + length) % length)].address
+ else
+ $windows[(($index + 1) % length)].address
+ end
+ end
+ ' <<<"$clients"
+)"
+
+if [[ -z "$target_address" ]]; then
+ exit 0
+fi
+
+hyprctl dispatch "hl.dsp.focus({ window = \"address:${target_address}\" })" >/dev/null 2>&1 || true
diff --git a/config/hypr/scripts/LuaFocusWorkspaceRelative.sh b/config/hypr/scripts/LuaFocusWorkspaceRelative.sh
new file mode 100755
index 00000000..20668110
--- /dev/null
+++ b/config/hypr/scripts/LuaFocusWorkspaceRelative.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# Focus the previous/next numeric workspace through the Lua dispatcher.
+# This allows moving into empty workspaces while avoiding invalid workspace 0.
+
+set -u
+
+direction="${1:-}"
+case "$direction" in
+ next|right|m+1|+1)
+ direction="next"
+ ;;
+ previous|prev|left|m-1|-1)
+ direction="previous"
+ ;;
+ *)
+ exit 0
+ ;;
+esac
+
+active_workspace="$(hyprctl activeworkspace -j 2>/dev/null || printf '{}')"
+active_id="$(jq -r '.id // empty' <<<"$active_workspace")"
+if ! [[ "$active_id" =~ ^-?[0-9]+$ ]]; then
+ exit 0
+fi
+
+case "$direction" in
+ next)
+ target_id=$((active_id + 1))
+ ;;
+ previous)
+ target_id=$((active_id - 1))
+ ;;
+esac
+if ! [[ "${target_id:-}" =~ ^-?[0-9]+$ ]] || [ "$target_id" -lt 1 ]; then
+ exit 0
+fi
+
+hyprctl dispatch "hl.dispatch(hl.dsp.focus({ workspace = ${target_id} }))" >/dev/null 2>&1 || true
diff --git a/config/hypr/scripts/LuaFullscreenMaximized.sh b/config/hypr/scripts/LuaFullscreenMaximized.sh
new file mode 100755
index 00000000..fccc577b
--- /dev/null
+++ b/config/hypr/scripts/LuaFullscreenMaximized.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# Helper for Lua-config sessions where legacy `hyprctl dispatch fullscreen 1`
+# is parsed as Lua and fails.
+
+setsid -f sh -c 'sleep 0.2; hyprctl dispatch "hl.dsp.window.fullscreen({ mode = 1 })"' >/dev/null 2>&1
diff --git a/config/hypr/scripts/LuaMoveWindowDirectional.sh b/config/hypr/scripts/LuaMoveWindowDirectional.sh
new file mode 100755
index 00000000..ea21196e
--- /dev/null
+++ b/config/hypr/scripts/LuaMoveWindowDirectional.sh
@@ -0,0 +1,51 @@
+#!/usr/bin/env bash
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# Guard directional Lua window movement against Hyprland Lua's no-target
+# "invalid workspace" runtime error.
+
+set -u
+
+direction="${1:-}"
+case "$direction" in
+ l|left)
+ direction="left"
+ ;;
+ r|right)
+ direction="right"
+ ;;
+ *)
+ exit 0
+ ;;
+esac
+
+active_window="$(hyprctl activewindow -j 2>/dev/null || printf '{}')"
+if ! jq -e '.address? and .address != ""' >/dev/null 2>&1 <<<"$active_window"; then
+ exit 0
+fi
+
+active_workspace="$(hyprctl activeworkspace -j 2>/dev/null || printf '{}')"
+active_id="$(jq -r '.id // empty' <<<"$active_workspace")"
+if ! [[ "$active_id" =~ ^-?[0-9]+$ ]]; then
+ exit 0
+fi
+
+workspaces="$(hyprctl workspaces -j 2>/dev/null || printf '[]')"
+case "$direction" in
+ left)
+ target_id="$(jq -r --argjson active "$active_id" '[.[] | select((.id < $active) and ((.windows // 0) > 0)) | .id] | max // empty' <<<"$workspaces")"
+ ;;
+ right)
+ target_id="$(jq -r --argjson active "$active_id" '[.[] | select((.id > $active) and ((.windows // 0) > 0)) | .id] | min // empty' <<<"$workspaces")"
+ ;;
+esac
+
+if ! [[ "${target_id:-}" =~ ^-?[0-9]+$ ]]; then
+ exit 0
+fi
+
+hyprctl dispatch "hl.dispatch(hl.dsp.window.move({ direction = \"${direction}\" }))" >/dev/null 2>&1 || true
diff --git a/config/hypr/scripts/LuaMoveWindowWorkspaceRelative.sh b/config/hypr/scripts/LuaMoveWindowWorkspaceRelative.sh
new file mode 100755
index 00000000..f225d4a2
--- /dev/null
+++ b/config/hypr/scripts/LuaMoveWindowWorkspaceRelative.sh
@@ -0,0 +1,51 @@
+#!/usr/bin/env bash
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# Move the active window to the previous/next numeric workspace through
+# the Lua dispatcher. This allows moving into empty workspaces while
+# avoiding invalid workspace 0.
+
+set -u
+
+direction="${1:-}"
+case "$direction" in
+ next|right|+1)
+ direction="next"
+ ;;
+ previous|prev|left|-1)
+ direction="previous"
+ ;;
+ *)
+ exit 0
+ ;;
+esac
+
+active_window="$(hyprctl activewindow -j 2>/dev/null || printf '{}')"
+if ! jq -e '.address? and .address != ""' >/dev/null 2>&1 <<<"$active_window"; then
+ exit 0
+fi
+
+active_workspace="$(hyprctl activeworkspace -j 2>/dev/null || printf '{}')"
+active_id="$(jq -r '.id // empty' <<<"$active_workspace")"
+if ! [[ "$active_id" =~ ^-?[0-9]+$ ]]; then
+ exit 0
+fi
+
+case "$direction" in
+ next)
+ target_id=$((active_id + 1))
+ ;;
+ previous)
+ target_id=$((active_id - 1))
+ ;;
+esac
+
+if ! [[ "${target_id:-}" =~ ^-?[0-9]+$ ]] || [ "$target_id" -lt 1 ]; then
+ exit 0
+fi
+
+hyprctl dispatch "hl.dispatch(hl.dsp.window.move({ workspace = ${target_id} }))" >/dev/null 2>&1 || true
diff --git a/config/hypr/scripts/LuaSwapWindow.sh b/config/hypr/scripts/LuaSwapWindow.sh
new file mode 100755
index 00000000..a1ec38fd
--- /dev/null
+++ b/config/hypr/scripts/LuaSwapWindow.sh
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# Safely swap the active window in a direction from Lua keybinds.
+
+arg="${1:-}"
+arg="${arg//\'/}"
+arg="${arg//\"/}"
+
+case "$arg" in
+left|l) direction="left" ;;
+right|r) direction="right" ;;
+up|u) direction="up" ;;
+down|d) direction="down" ;;
+*) exit 0 ;;
+esac
+
+active="$(hyprctl -j activewindow 2>/dev/null)"
+clients="$(hyprctl -j clients 2>/dev/null)"
+
+has_target="$(
+ jq -en --argjson active "$active" --argjson clients "$clients" --arg direction "$direction" '
+ def overlaps(a1; a2; b1; b2): (a1 < b2 and b1 < a2);
+ ($active.address // "") as $active_address
+ | ($active.workspace.id // null) as $workspace_id
+ | ($active.at[0] // 0) as $ax
+ | ($active.at[1] // 0) as $ay
+ | ($active.size[0] // 0) as $aw
+ | ($active.size[1] // 0) as $ah
+ | any($clients[];
+ (.address != $active_address)
+ and ((.workspace.id // null) == $workspace_id)
+ and (
+ if $direction == "left" then
+ ((.at[0] + .size[0]) <= $ax) and overlaps(.at[1]; (.at[1] + .size[1]); $ay; ($ay + $ah))
+ elif $direction == "right" then
+ (.at[0] >= ($ax + $aw)) and overlaps(.at[1]; (.at[1] + .size[1]); $ay; ($ay + $ah))
+ elif $direction == "up" then
+ ((.at[1] + .size[1]) <= $ay) and overlaps(.at[0]; (.at[0] + .size[0]); $ax; ($ax + $aw))
+ elif $direction == "down" then
+ (.at[1] >= ($ay + $ah)) and overlaps(.at[0]; (.at[0] + .size[0]); $ax; ($ax + $aw))
+ else
+ false
+ end
+ )
+ )
+ ' 2>/dev/null
+)"
+
+[[ "$has_target" == "true" ]] || exit 0
+
+hyprctl dispatch "hl.dsp.window.swap({ direction = \"${direction}\" })" >/dev/null 2>&1 || true
diff --git a/config/hypr/scripts/MonitorProfiles.sh b/config/hypr/scripts/MonitorProfiles.sh
index 78825986..6330d45c 100755
--- a/config/hypr/scripts/MonitorProfiles.sh
+++ b/config/hypr/scripts/MonitorProfiles.sh
@@ -12,13 +12,46 @@ if pidof rofi > /dev/null; then
pkill rofi
fi
+# Detect active Hyprland config mode (Lua entrypoint vs legacy .conf includes)
+config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
+hypr_dir="$config_home/hypr"
+lua_entry="$hypr_dir/hyprland.lua"
+legacy_lua_entry="$config_home/hyprland.lua"
+if [[ -n "$HYPR_CONFIG_MODE" ]]; then
+ case "${HYPR_CONFIG_MODE,,}" in
+ lua) hypr_config_mode="lua" ;;
+ conf|hyprlang) hypr_config_mode="conf" ;;
+ auto) hypr_config_mode="" ;;
+ *) hypr_config_mode="" ;;
+ esac
+fi
+
+if [[ -z "$hypr_config_mode" ]]; then
+ if [[ -f "$lua_entry" || -f "$legacy_lua_entry" ]]; then
+ hypr_config_mode="lua"
+ else
+ hypr_config_mode="conf"
+ fi
+fi
+
# Variables
iDIR="$HOME/.config/swaync/images"
SCRIPTSDIR="$HOME/.config/hypr/scripts"
monitor_dir="$HOME/.config/hypr/Monitor_Profiles"
-target="$HOME/.config/hypr/monitors.conf"
+target_conf="$HOME/.config/hypr/monitors.conf"
+target_lua_user="$HOME/.config/hypr/UserConfigs/monitors.lua"
+target_lua_legacy="$HOME/.config/hypr/lua/monitors.lua"
rofi_theme="$HOME/.config/rofi/config-Monitors.rasi"
-msg='❗NOTE:❗ This will overwrite $HOME/.config/hypr/monitors.conf'
+
+if [[ "$hypr_config_mode" == "lua" ]]; then
+ profile_ext="lua"
+ target="$target_lua_user"
+ msg="❗NOTE:❗ This will overwrite $HOME/.config/hypr/UserConfigs/monitors.lua"
+else
+ profile_ext="conf"
+ target="$target_conf"
+ msg="❗NOTE:❗ This will overwrite $HOME/.config/hypr/monitors.conf"
+fi
# Define the list of files to ignore
ignore_files=(
@@ -26,22 +59,30 @@ ignore_files=(
)
# list of Monitor Profiles, sorted alphabetically with numbers first
-mon_profiles_list=$(find -L "$monitor_dir" -maxdepth 1 -type f | sed 's/.*\///' | sed 's/\.conf$//' | sort -V)
+mon_profiles_list=$(find -L "$monitor_dir" -maxdepth 1 -type f -name "*.${profile_ext}" | sed 's/.*\///' | sed "s/\.${profile_ext}$//" | sort -V)
# Remove ignored files from the list
for ignored_file in "${ignore_files[@]}"; do
mon_profiles_list=$(echo "$mon_profiles_list" | grep -v -E "^$ignored_file$")
done
+if [[ -z "$mon_profiles_list" ]]; then
+ notify-send -u low -i "$iDIR/ja.png" "Monitor Profiles" "No .${profile_ext} profiles found in $monitor_dir"
+ exit 1
+fi
# Rofi Menu
-chosen_file=$(echo "$mon_profiles_list" | rofi -i -dmenu -config $rofi_theme -mesg "$msg")
+chosen_file=$(echo "$mon_profiles_list" | rofi -i -dmenu -config "$rofi_theme" -mesg "$msg")
if [[ -n "$chosen_file" ]]; then
- full_path="$monitor_dir/$chosen_file.conf"
+ full_path="$monitor_dir/$chosen_file.$profile_ext"
+ mkdir -p "$(dirname "$target")"
cp "$full_path" "$target"
+ if [[ "$hypr_config_mode" == "lua" && -f "$target_lua_legacy" ]]; then
+ cp "$full_path" "$target_lua_legacy"
+ fi
notify-send -u low -i "$iDIR/ja.png" "$chosen_file" "Monitor Profile Loaded"
fi
sleep 1
-${SCRIPTSDIR}/RefreshNoWaybar.sh & \ No newline at end of file
+"${SCRIPTSDIR}/RefreshNoWaybar.sh" &
diff --git a/config/hypr/scripts/OverviewToggle.sh b/config/hypr/scripts/OverviewToggle.sh
index 14470eb0..456ccef1 100755
--- a/config/hypr/scripts/OverviewToggle.sh
+++ b/config/hypr/scripts/OverviewToggle.sh
@@ -9,15 +9,18 @@
set -euo pipefail
-# 1) Try Quickshell via IPC (works if QS is running and listening)
-if pgrep -x qs >/dev/null 2>&1; then
- if qs ipc -c overview call overview toggle >/dev/null 2>&1; then
- exit 0
+QS_OVERVIEW_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/quickshell/overview"
+
+# 1) Prefer Quickshell when installed and configured
+if command -v qs >/dev/null 2>&1 && [ -d "$QS_OVERVIEW_DIR" ]; then
+ # Try Quickshell via IPC (works if QS is running and listening)
+ if pgrep -x qs >/dev/null 2>&1; then
+ if qs ipc -c overview call overview toggle >/dev/null 2>&1; then
+ exit 0
+ fi
fi
-fi
-# If QS isn't running, but the CLI exists, try starting it and retry once
-if command -v qs >/dev/null 2>&1; then
+ # If QS isn't running, try starting it and retry once
qs -c overview >/dev/null 2>&1 &
sleep 0.6
if qs ipc -c overview call overview toggle >/dev/null 2>&1; then
diff --git a/config/hypr/scripts/Polkit-Diag.sh b/config/hypr/scripts/Polkit-Diag.sh
index 0f32b640..aa4e69a8 100755
--- a/config/hypr/scripts/Polkit-Diag.sh
+++ b/config/hypr/scripts/Polkit-Diag.sh
@@ -50,20 +50,20 @@ setup_output() {
else
local outdir
outdir=$(dirname "$OUTFILE")
-
+
# Check and create directory if it doesn't exist
if [[ ! -d "$outdir" ]]; then
echo "Directory $outdir does not exist. Creating..."
mkdir -p "$outdir"
fi
-
+
# Backup existing file
if [[ -f "$OUTFILE" ]]; then
local backup_file="${OUTFILE}.bak.$(date +%Y%m%d%H%M%S)"
echo "Existing output file found. Backing up to: $backup_file"
mv "$OUTFILE" "$backup_file"
fi
-
+
echo "Diagnostics will be saved to: $OUTFILE"
exec 3> "$OUTFILE"
fi
@@ -74,7 +74,7 @@ apply_override() {
local msg="\n=== Systemd Override for hyprpolkitagent ==="
[[ $DRY_RUN -eq 0 ]] && echo -e "$msg" >&3
echo -e "$msg"
-
+
local out
if systemctl --user is-enabled hyprpolkitagent.service >/dev/null 2>&1; then
msg="[STATUS] hyprpolkitagent.service is currently enabled."
@@ -94,10 +94,10 @@ apply_override() {
msg="[CONFIRM] Force override requested. Overwriting existing override..."
[[ $DRY_RUN -eq 0 ]] && echo "$msg" >&3; echo "$msg"
fi
-
+
msg="[ACTION] Installing override to $OVERRIDE_FILE..."
[[ $DRY_RUN -eq 0 ]] && echo "$msg" >&3; echo "$msg"
-
+
if [[ $DRY_RUN -eq 0 ]]; then
# Capture dir creation
if out=$(mkdir -p "$OVERRIDE_DIR" 2>&1); then
@@ -106,7 +106,7 @@ apply_override() {
msg=" [ERROR] Failed to create directory $OVERRIDE_DIR.\n Details: $out"
fi
echo -e "$msg" >&3; echo -e "$msg"
-
+
# Capture file write
if out=$(echo "$OVERRIDE_CONTENT" > "$OVERRIDE_FILE" 2>&1); then
msg=" [OK] Successfully wrote override file."
@@ -114,7 +114,7 @@ apply_override() {
msg=" [ERROR] Failed to write override file.\n Details: $out"
fi
echo -e "$msg" >&3; echo -e "$msg"
-
+
# Capture daemon-reload
if out=$(systemctl --user daemon-reload 2>&1); then
msg=" [OK] Systemd daemon reloaded."
@@ -122,12 +122,12 @@ apply_override() {
msg=" [ERROR] Failed to reload systemd daemon.\n Details: $out"
fi
echo -e "$msg" >&3; echo -e "$msg"
-
+
# Capture restart
if systemctl --user is-active --quiet hyprpolkitagent.service; then
msg="[ACTION] Restarting hyprpolkitagent.service..."
[[ $DRY_RUN -eq 0 ]] && echo "$msg" >&3; echo "$msg"
-
+
if out=$(systemctl --user restart hyprpolkitagent.service 2>&1); then
msg=" [OK] Service restarted successfully."
else
@@ -153,31 +153,31 @@ gather_general_info() {
echo "Date: $(date)" >&3
echo -e "\n--- Kernel ---" >&3
uname -a >&3
-
+
echo -e "\n--- OS Release ---" >&3
cat /etc/os-release >&3
-
+
echo -e "\n=======================================" >&3
echo -e " Polkit Service Status" >&3
echo -e "=======================================" >&3
-
+
echo -e "\n--- System Polkit Service ---" >&3
systemctl status polkit.service --no-pager >&3 2>&1 || true
-
+
echo -e "\n--- User Hyprpolkitagent Service ---" >&3
systemctl --user status hyprpolkitagent.service --no-pager >&3 2>&1 || true
-
+
echo -e "\n--- Running Polkit Processes ---" >&3
local polkit_procs
polkit_procs=$(ps aux | grep -i '[p]olkit')
if [[ -n "$polkit_procs" ]]; then
echo "$polkit_procs" >&3
-
+
# Check for conflicting agents
local kde_agent_running=0
local gnome_agent_running=0
local hypr_agent_running=0
-
+
if echo "$polkit_procs" | grep -q "polkit-kde-authentication-agent-1"; then
kde_agent_running=1
fi
@@ -187,7 +187,7 @@ gather_general_info() {
if echo "$polkit_procs" | grep -q "hyprpolkitagent"; then
hypr_agent_running=1
fi
-
+
if [[ $hypr_agent_running -eq 1 && ($kde_agent_running -eq 1 || $gnome_agent_running -eq 1) ]]; then
echo -e "\n[!] CONFLICT DETECTED: Multiple polkit agents are running!" >&3
echo " Hyprpolkitagent is running alongside another desktop environment's agent." >&3
@@ -205,14 +205,14 @@ gather_general_info() {
else
echo "No polkit processes found running." >&3
fi
-
+
echo -e "\n=======================================" >&3
echo -e " Recent Logs" >&3
echo -e "=======================================" >&3
-
+
echo -e "\n--- Journalctl (polkit.service) [Last 50 entries, warnings/errors] ---" >&3
journalctl -u polkit.service -n 50 --no-pager -p 4 >&3 2>&1 || echo "Could not fetch system polkit logs." >&3
-
+
echo -e "\n--- Journalctl (hyprpolkitagent.service) [Last 50 entries] ---" >&3
journalctl --user -u hyprpolkitagent.service -n 50 --no-pager >&3 2>&1 || echo "Could not fetch user hyprpolkitagent logs." >&3
}
@@ -223,7 +223,7 @@ check_packages() {
local install_msg="$2"
shift 2
local pkgs=("$@")
-
+
local missing_pkgs=()
for pkg in "${pkgs[@]}"; do
local out
@@ -235,7 +235,7 @@ check_packages() {
missing_pkgs+=("$pkg")
fi
done
-
+
if [[ ${#missing_pkgs[@]} -gt 0 ]]; then
echo -e "\nWARNING: The following packages are missing:" >&3
for mpkg in "${missing_pkgs[@]}"; do
@@ -251,7 +251,7 @@ check_source_binaries() {
shift
local bins=("$@")
local found_any=0
-
+
echo -e "\n--- Source Builds (${bin_dir}) ---" >&3
for bin in "${bins[@]}"; do
if [[ -x "${bin_dir}/${bin}" ]]; then
@@ -261,7 +261,7 @@ check_source_binaries() {
echo "[MISSING] ${bin_dir}/${bin}" >&3
fi
done
-
+
return $found_any
}
@@ -269,7 +269,7 @@ gather_arch_info() {
echo -e "\n=======================================" >&3
echo -e " Package Info (Arch Linux)" >&3
echo -e "=======================================" >&3
-
+
# Essential packages required for polkit & related UI
local pkgs=(
"qt5-declarative"
@@ -278,19 +278,19 @@ gather_arch_info() {
"hyprpolkitagent"
"polkit"
)
-
+
local aur_pkgs=(
"xfce-polkit"
)
-
+
local missing_any=0
-
+
echo -e "\n--- Official Repositories ---" >&3
check_packages "pacman -Q" "Install official packages by running: sudo pacman -S" "${pkgs[@]}" || missing_any=1
-
+
echo -e "\n--- AUR ---" >&3
check_packages "pacman -Q" "Install AUR packages by running: yay -S" "${aur_pkgs[@]}" || missing_any=1
-
+
if [[ $missing_any -eq 0 ]]; then
echo -e "\nSUCCESS: All expected packages are installed." >&3
fi
@@ -299,7 +299,7 @@ gather_ubuntu_info() {
echo -e "\n=======================================" >&3
echo -e " Package Info (Ubuntu/PPA)" >&3
echo -e "=======================================" >&3
-
+
# Essential packages required for polkit & related UI
local pkgs=(
"qml-module-qtqml"
@@ -313,22 +313,22 @@ gather_ubuntu_info() {
"hyprpolkitagent"
"polkit"
)
-
+
local extra_pkgs=(
"xfce-polkit"
"polkit-kde-agent-1"
"mate-polkit"
)
-
+
local missing_any=0
-
+
echo -e "\n--- Official Repositories / PPA ---" >&3
check_packages "dpkg -s" "Install packages by running: sudo apt install" "${pkgs[@]}" || missing_any=1
-
+
echo -e "\n--- Extra/Alternative ---" >&3
check_packages "dpkg -s" "Install extra packages by running: sudo apt install" "${extra_pkgs[@]}" || missing_any=1
echo "[INFO] lxqt-polkit (optional) — large dependency set." >&3
-
+
if [[ $missing_any -eq 0 ]]; then
echo -e "\nSUCCESS: All expected packages are installed." >&3
fi
@@ -337,16 +337,16 @@ gather_debian_info() {
echo -e "\n=======================================" >&3
echo -e " Package Info (Debian/Ubuntu)" >&3
echo -e "=======================================" >&3
-
+
local source_bins=(
"hyprpolkitagent"
)
-
+
local source_found=0
if check_source_binaries "/usr/local/bin" "${source_bins[@]}"; then
source_found=1
fi
-
+
# Essential packages required for polkit & related UI
local pkgs=(
"qml-module-qtqml"
@@ -359,16 +359,16 @@ gather_debian_info() {
"qml6-module-qtquick-controls"
"polkit"
)
-
+
local extra_pkgs=(
"xfce4-polkit"
"lxqt-policykit"
"polkit-kde-agent-1"
"mate-polkit"
)
-
+
local missing_any=0
-
+
echo -e "\n--- Official Repositories ---" >&3
if [[ $source_found -eq 0 ]]; then
pkgs+=("hyprpolkitagent")
@@ -376,10 +376,10 @@ gather_debian_info() {
echo "[INFO] hyprpolkitagent found in /usr/local/bin (source build). Skipping dpkg check for it." >&3
fi
check_packages "dpkg -s" "Install packages by running: sudo apt install" "${pkgs[@]}" || missing_any=1
-
+
echo -e "\n--- Extra/Alternative ---" >&3
check_packages "dpkg -s" "Install extra packages by running: sudo apt install" "${extra_pkgs[@]}" || missing_any=1
-
+
if [[ $missing_any -eq 0 ]]; then
echo -e "\nSUCCESS: All expected packages are installed." >&3
fi
@@ -389,7 +389,7 @@ gather_fedora_info() {
echo -e "\n=======================================" >&3
echo -e " Package Info (Fedora)" >&3
echo -e "=======================================" >&3
-
+
# Essential packages required for polkit & related UI
local pkgs=(
"qt5-qtdeclarative"
@@ -398,19 +398,19 @@ gather_fedora_info() {
"hyprpolkitagent"
"polkit"
)
-
+
local extra_pkgs=(
"xfce-polkit"
)
-
+
local missing_any=0
-
+
echo -e "\n--- Official Repositories ---" >&3
check_packages "rpm -q" "Install packages by running: sudo dnf install" "${pkgs[@]}" || missing_any=1
-
+
echo -e "\n--- Extra/Alternative ---" >&3
check_packages "rpm -q" "Install extra packages by running: sudo dnf install" "${extra_pkgs[@]}" || missing_any=1
-
+
if [[ $missing_any -eq 0 ]]; then
echo -e "\nSUCCESS: All expected packages are installed." >&3
fi
diff --git a/config/hypr/scripts/PortalHyprland.sh b/config/hypr/scripts/PortalHyprland.sh
index 243ee2e8..3d3dc410 100755
--- a/config/hypr/scripts/PortalHyprland.sh
+++ b/config/hypr/scripts/PortalHyprland.sh
@@ -8,6 +8,19 @@
# For manually starting xdg-desktop-portal-hyprland
set -euo pipefail
+is_ubuntu_family() {
+ if [[ ! -r /etc/os-release ]]; then
+ return 1
+ fi
+
+ # shellcheck disable=SC1091
+ . /etc/os-release
+ [[ "${ID:-}" == "ubuntu" \
+ || "${ID:-}" == "linuxmint" \
+ || "${ID:-}" == "zorin" \
+ || "${ID:-}" == "rhino" \
+ || "${ID_LIKE:-}" == *ubuntu* ]]
+}
kill_quietly() {
killall -q "$1" 2>/dev/null || true
@@ -25,11 +38,15 @@ start_portal_binary() {
echo "Warning: no $description binary found (checked: $*)" >&2
return 1
}
+if ! is_ubuntu_family; then
+ exit 0
+fi
sleep 1
kill_quietly xdg-desktop-portal-hyprland
kill_quietly xdg-desktop-portal-wlr
kill_quietly xdg-desktop-portal-gnome
+kill_quietly xdg-desktop-portal-gtk
kill_quietly xdg-desktop-portal
sleep 1
@@ -39,6 +56,10 @@ start_portal_binary "xdg-desktop-portal-hyprland" \
sleep 2
+start_portal_binary "xdg-desktop-portal-gtk" \
+ /usr/lib/xdg-desktop-portal-gtk \
+ /usr/libexec/xdg-desktop-portal-gtk
+
start_portal_binary "xdg-desktop-portal" \
/usr/lib/xdg-desktop-portal \
/usr/libexec/xdg-desktop-portal
diff --git a/config/hypr/scripts/Refresh.sh b/config/hypr/scripts/Refresh.sh
index 03f55fa0..947b6bfc 100755
--- a/config/hypr/scripts/Refresh.sh
+++ b/config/hypr/scripts/Refresh.sh
@@ -43,16 +43,39 @@ for pid in $(pidof rofi swaync ags swaybg); do
sleep 0.1
done
-# Reload or start waybar once
-if pidof waybar >/dev/null; then
- if command -v waybar-msg >/dev/null 2>&1; then
- waybar-msg cmd reload >/dev/null 2>&1 || true
+# Restart waybar once (works with systemd user unit or manual launch setups)
+restart_waybar() {
+ local manage_with_systemd=0
+
+ if command -v systemctl >/dev/null 2>&1; then
+ if systemctl --user --quiet is-active waybar.service 2>/dev/null || systemctl --user --quiet is-enabled waybar.service 2>/dev/null; then
+ manage_with_systemd=1
+ fi
+ fi
+
+ if [ "$manage_with_systemd" -eq 1 ]; then
+ systemctl --user stop waybar.service >/dev/null 2>&1 || true
+ fi
+
+ pkill -x waybar >/dev/null 2>&1 || true
+ pkill -x '.waybar-wrapped' >/dev/null 2>&1 || true
+ sleep 0.2
+ if pgrep -x waybar >/dev/null 2>&1 || pgrep -x '.waybar-wrapped' >/dev/null 2>&1; then
+ pkill -9 -x waybar >/dev/null 2>&1 || true
+ pkill -9 -x '.waybar-wrapped' >/dev/null 2>&1 || true
+ fi
+ sleep 0.2
+
+ if [ "$manage_with_systemd" -eq 1 ]; then
+ if ! systemctl --user start waybar.service >/dev/null 2>&1; then
+ waybar >/dev/null 2>&1 &
+ fi
else
- killall -SIGUSR2 waybar 2>/dev/null || true
+ waybar >/dev/null 2>&1 &
fi
-else
- waybar &
-fi
+}
+
+restart_waybar
# relaunch swaync
sleep 0.3
diff --git a/config/hypr/scripts/ResizeActive.sh b/config/hypr/scripts/ResizeActive.sh
new file mode 100755
index 00000000..afcdeb85
--- /dev/null
+++ b/config/hypr/scripts/ResizeActive.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+# Resize the active window by delta values (dx, dy) using Lua dispatch.
+
+dx="${1:-0}"
+dy="${2:-0}"
+
+window_json="$(hyprctl activewindow -j)"
+width="$(jq -r '.size[0]' <<<"$window_json")"
+height="$(jq -r '.size[1]' <<<"$window_json")"
+
+new_width=$((width + dx))
+new_height=$((height + dy))
+
+if ((new_width < 100)); then
+ new_width=100
+fi
+if ((new_height < 100)); then
+ new_height=100
+fi
+
+hyprctl dispatch "hl.dsp.window.resize({ x = ${new_width}, y = ${new_height} })"
diff --git a/config/hypr/scripts/Tak0-Autodispatch.sh b/config/hypr/scripts/Tak0-Autodispatch.sh
index 034a6402..cabe1672 100755
--- a/config/hypr/scripts/Tak0-Autodispatch.sh
+++ b/config/hypr/scripts/Tak0-Autodispatch.sh
@@ -71,6 +71,18 @@ fi
echo "=== Deploy '$CMD' → WS $TARGET_WS @ $(date) ===" >>"$LOGFILE"
+# Detect active Hyprland config mode
+config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
+hypr_dir="$config_home/hypr"
+lua_entry="$hypr_dir/hyprland.lua"
+legacy_lua_entry="$config_home/hyprland.lua"
+
+if [[ -f "$lua_entry" || -f "$legacy_lua_entry" ]]; then
+ hypr_config_mode="lua"
+else
+ hypr_config_mode="conf"
+fi
+
# ─────────────────────────────────────────────────────────────────────────────
# 1️⃣ HYPRLAND READINESS GATE
# ─────────────────────────────────────────────────────────────────────────────
@@ -91,11 +103,17 @@ done
cleanup() {
echo "Cleanup: removing temporary capture rules and initialWorkspace at $(date)" >>"$LOGFILE"
- hyprctl keyword windowrulev2 "unset, initialClass:.*" >>"$LOGFILE" 2>&1 || true
- for RULE in "${CAPTURE_RULES[@]}"; do
- echo "Cleanup: removing temporary capture rule: $RULE" >>"$LOGFILE"
- hyprctl keyword windowrulev2 "unset, $RULE" >>"$LOGFILE" 2>&1 || true
- done
+ if [[ "$hypr_config_mode" == "lua" ]]; then
+ # In Lua mode, we try to nullify the temporary rules or trigger a reload
+ # Since we don't have a reliable 'unset' API via eval yet, we reload
+ hyprctl reload >>"$LOGFILE" 2>&1 || true
+ else
+ hyprctl keyword windowrulev2 "unset, initialClass:.*" >>"$LOGFILE" 2>&1 || true
+ for RULE in "${CAPTURE_RULES[@]}"; do
+ echo "Cleanup: removing temporary capture rule: $RULE" >>"$LOGFILE"
+ hyprctl keyword windowrulev2 "unset, $RULE" >>"$LOGFILE" 2>&1 || true
+ done
+ fi
}
trap cleanup EXIT INT TERM ERR
@@ -105,28 +123,35 @@ trap cleanup EXIT INT TERM ERR
# ─────────────────────────────────────────────────────────────────────────────
# Temporarily forces ALL windows (initialClass:.*)
# onto the target workspace.
-#
-# Protects against ultra-fast helpers:
-# • gpu-process
-# • renderer
-# • steamwebhelper
echo "Applying temporary initialWorkspace capture (initialClass:.*)" >>"$LOGFILE"
-hyprctl keyword windowrulev2 \
- "initialWorkspace $TARGET_WS silent, initialClass:.*" \
- >>"$LOGFILE" 2>&1 || true
+if [[ "$hypr_config_mode" == "lua" ]]; then
+ # Note: Using workspace property in hl.window_rule as a best-effort equivalent
+ hyprctl eval "hl.window_rule({ name = 'autodispatch-nuclear', match = { class = '.*' }, workspace = '$TARGET_WS' })" >>"$LOGFILE" 2>&1 || true
+else
+ hyprctl keyword windowrulev2 \
+ "initialWorkspace $TARGET_WS silent, initialClass:.*" \
+ >>"$LOGFILE" 2>&1 || true
+fi
# ─────────────────────────────────────────────────────────────────────────────
# 3️⃣.1 OPTIONAL CLASS-BASED PRE-CAPTURE
# ─────────────────────────────────────────────────────────────────────────────
# Additional precision rules.
-# Useful for Electron / Steam multi-process hell.
for RULE in "${CAPTURE_RULES[@]}"; do
echo "Applying temporary capture rule: $RULE" >>"$LOGFILE"
- hyprctl keyword windowrulev2 \
- "initialWorkspace $TARGET_WS silent, $RULE" \
- >>"$LOGFILE" 2>&1 || true
+ if [[ "$hypr_config_mode" == "lua" ]]; then
+ # Attempt to parse rule string into Lua table if it matches class:pattern
+ if [[ "$RULE" =~ class:\^\((.*)\)\$ ]]; then
+ local class_pat="${BASH_REMATCH[1]}"
+ hyprctl eval "hl.window_rule({ name = 'autodispatch-$class_pat', match = { class = '$class_pat' }, workspace = '$TARGET_WS' })" >>"$LOGFILE" 2>&1 || true
+ fi
+ else
+ hyprctl keyword windowrulev2 \
+ "initialWorkspace $TARGET_WS silent, $RULE" \
+ >>"$LOGFILE" 2>&1 || true
+ fi
done
# ─────────────────────────────────────────────────────────────────────────────
@@ -158,9 +183,14 @@ echo "App gate name: $APP_NAME" >>"$LOGFILE"
sleep 1.5
-#!TO-DO: Release the nuclear option ASAP
echo "Releasing ultra-early wide capture" >>"$LOGFILE"
-hyprctl keyword windowrulev2 "unset, initialClass:.*" >>"$LOGFILE" 2>&1 || true
+if [[ "$hypr_config_mode" == "lua" ]]; then
+ # In Lua mode, we rely on the supervision loop for precision after launch
+ # and cleanup will handle the rest.
+ :
+else
+ hyprctl keyword windowrulev2 "unset, initialClass:.*" >>"$LOGFILE" 2>&1 || true
+fi
# ─────────────────────────────────────────────────────────────────────────────
# 5️⃣ SUPERVISION LOOP (AUTHORITATIVE PHASE)
@@ -221,6 +251,7 @@ while ((SECONDS < END_TIME)); do
if ((MATCH)) && [[ -z "${SEEN[$ADDR]-}" ]]; then
echo "Placing window $ADDR (pid $PID, class $CLASS) → WS $TARGET_WS" >>"$LOGFILE"
+ # Dispatch works the same in both modes
hyprctl dispatch movetoworkspacesilent \
"$TARGET_WS,address:$ADDR" >>"$LOGFILE" 2>&1 || true
SEEN[$ADDR]=1
diff --git a/config/hypr/scripts/Tak0-Per-Window-Switch.sh b/config/hypr/scripts/Tak0-Per-Window-Switch.sh
index 04baebe0..eba3b380 100755
--- a/config/hypr/scripts/Tak0-Per-Window-Switch.sh
+++ b/config/hypr/scripts/Tak0-Per-Window-Switch.sh
@@ -1,3 +1,4 @@
+#!/usr/bin/env bash
# ==================================================
# KoolDots (2026)
# Project URL: https://github.com/LinuxBeginnings
@@ -16,28 +17,65 @@
# smooth and comfortable workflow. #
# #
##################################################################
-# This is for changing kb_layouts. Set kb_layouts in
MAP_FILE="$HOME/.cache/kb_layout_per_window"
-USER_CFG="$HOME/.config/hypr/UserConfigs/UserSettings.conf"
-SYS_CFG="$HOME/.config/hypr/configs/SystemSettings.conf"
ICON="$HOME/.config/swaync/images/ja.png"
SCRIPT_NAME="$(basename "$0")"
+SCRIPT_PATH="$(readlink -f "$0")"
+
+# Detect active Hyprland config mode
+config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
+hypr_dir="$config_home/hypr"
+lua_entry="$hypr_dir/hyprland.lua"
+legacy_lua_entry="$config_home/hyprland.lua"
+
+if [[ -f "$lua_entry" || -f "$legacy_lua_entry" ]]; then
+ hypr_config_mode="lua"
+else
+ hypr_config_mode="conf"
+fi
# Ensure map file exists
touch "$MAP_FILE"
-# Read layouts from config
-if grep -q 'kb_layout' "$USER_CFG" 2>/dev/null; then
- CFG_FILE="$USER_CFG"
-elif grep -q 'kb_layout' "$SYS_CFG" 2>/dev/null; then
- CFG_FILE="$SYS_CFG"
-else
- echo "Error: cannot find kb_layout in UserSettings.conf nor SystemSettings.conf" >&2
- exit 1
+# Function to get layouts from config files
+get_layouts() {
+ local layouts=""
+ if [[ "$hypr_config_mode" == "lua" ]]; then
+ local lua_user="$hypr_dir/UserConfigs/user_settings.lua"
+ local lua_sys="$hypr_dir/configs/system_settings.lua"
+ local lua_legacy_sys="$hypr_dir/UserConfigs/system_settings.lua"
+ local lua_pristine_sys="$hypr_dir/lua/settings.lua"
+ if [[ -f "$lua_user" ]] && grep -q 'kb_layout' "$lua_user" 2>/dev/null; then
+ layouts=$(grep 'kb_layout' "$lua_user" | sed -n 's/.*kb_layout\s*=\s*"\([^"]*\)".*/\1/p' | head -n1)
+ elif [[ -f "$lua_sys" ]] && grep -q 'kb_layout' "$lua_sys" 2>/dev/null; then
+ layouts=$(grep 'kb_layout' "$lua_sys" | sed -n 's/.*kb_layout\s*=\s*"\([^"]*\)".*/\1/p' | head -n1)
+ elif [[ -f "$lua_legacy_sys" ]] && grep -q 'kb_layout' "$lua_legacy_sys" 2>/dev/null; then
+ layouts=$(grep 'kb_layout' "$lua_legacy_sys" | sed -n 's/.*kb_layout\s*=\s*"\([^"]*\)".*/\1/p' | head -n1)
+ elif [[ -f "$lua_pristine_sys" ]] && grep -q 'kb_layout' "$lua_pristine_sys" 2>/dev/null; then
+ layouts=$(grep 'kb_layout' "$lua_pristine_sys" | sed -n 's/.*kb_layout\s*=\s*"\([^"]*\)".*/\1/p' | head -n1)
+ fi
+ else
+ local conf_user="$hypr_dir/UserConfigs/UserSettings.conf"
+ local conf_sys="$hypr_dir/configs/SystemSettings.conf"
+ if [[ -f "$conf_user" ]] && grep -q 'kb_layout' "$conf_user" 2>/dev/null; then
+ layouts=$(grep 'kb_layout' "$conf_user" | cut -d '=' -f2 | tr -d '[:space:]' | head -n1)
+ elif [[ -f "$conf_sys" ]] && grep -q 'kb_layout' "$conf_sys" 2>/dev/null; then
+ layouts=$(grep 'kb_layout' "$conf_sys" | cut -d '=' -f2 | tr -d '[:space:]' | head -n1)
+ fi
+ fi
+ echo "$layouts" | tr ',' ' '
+}
+
+raw_layouts=$(get_layouts)
+if [[ -z "$raw_layouts" ]]; then
+ echo "Error: cannot find kb_layout in configuration files." >&2
+ exit 1
fi
-kb_layouts=($(grep 'kb_layout' "$CFG_FILE" | cut -d '=' -f2 | tr -d '[:space:]' | tr ',' ' '))
+
+kb_layouts=($raw_layouts)
count=${#kb_layouts[@]}
+
# Get current active window ID
get_win() {
hyprctl activewindow -j | jq -r '.address // .id'
@@ -51,7 +89,7 @@ get_keyboards() {
# Save window-specific layout
save_map() {
local W=$1 L=$2
- grep -v "^${W}:" "$MAP_FILE" > "$MAP_FILE.tmp"
+ grep -v "^${W}:" "$MAP_FILE" > "$MAP_FILE.tmp" 2>/dev/null
echo "${W}:${L}" >> "$MAP_FILE.tmp"
mv "$MAP_FILE.tmp" "$MAP_FILE"
}
@@ -60,7 +98,7 @@ save_map() {
load_map() {
local W=$1
local E
- E=$(grep "^${W}:" "$MAP_FILE")
+ E=$(grep "^${W}:" "$MAP_FILE" 2>/dev/null)
[[ -n "$E" ]] && echo "${E#*:}" || echo "${kb_layouts[0]}"
}
@@ -68,16 +106,17 @@ load_map() {
do_switch() {
local IDX=$1
for kb in $(get_keyboards); do
- hyprctl switchxkblayout "$kb" "$IDX" 2>/dev/null
+ hyprctl switchxkblayout "$kb" "$IDX" >/dev/null 2>&1
done
}
# Toggle layout for current window only
cmd_toggle() {
local W=$(get_win)
- [[ -z "$W" ]] && return
+ [[ -z "$W" || "$W" == "null" ]] && return
local CUR=$(load_map "$W")
- local i NEXT
+ local i=0
+ local NEXT
for idx in "${!kb_layouts[@]}"; do
if [[ "${kb_layouts[idx]}" == "$CUR" ]]; then
i=$idx
@@ -93,7 +132,7 @@ cmd_toggle() {
# Restore layout on focus
cmd_restore() {
local W=$(get_win)
- [[ -z "$W" ]] && return
+ [[ -z "$W" || "$W" == "null" ]] && return
local LAY=$(load_map "$W")
for idx in "${!kb_layouts[@]}"; do
if [[ "${kb_layouts[idx]}" == "$LAY" ]]; then
@@ -106,23 +145,37 @@ cmd_restore() {
# Listen to focus events and restore window-specific layouts
subscribe() {
local SOCKET2="$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock"
+ if [[ ! -S "$SOCKET2" ]]; then
+ # Fallback if HYPRLAND_INSTANCE_SIGNATURE is not set correctly in this subshell
+ local sig=$(hyprctl instances -j | jq -r '.[0].instance' 2>/dev/null)
+ SOCKET2="$XDG_RUNTIME_DIR/hypr/$sig/.socket2.sock"
+ fi
+
[[ -S "$SOCKET2" ]] || {
echo "Error: Hyprland socket not found." >&2
exit 1
}
socat -u UNIX-CONNECT:"$SOCKET2" - | while read -r line; do
- [[ "$line" =~ ^activewindow ]] && cmd_restore
+ if [[ "$line" =~ ^activewindow ]]; then
+ cmd_restore
+ fi
done
}
-# Ensure only one listener
-if ! pgrep -f "$SCRIPT_NAME.*--listener" >/dev/null; then
- subscribe --listener &
-fi
-
# CLI
case "$1" in
- toggle|"") cmd_toggle ;;
- *) echo "Usage: $SCRIPT_NAME [toggle]" >&2; exit 1 ;;
+ --listener)
+ subscribe
+ ;;
+ toggle|"")
+ # Ensure only one listener
+ if ! pgrep -f "$SCRIPT_NAME.*--listener" >/dev/null; then
+ "$SCRIPT_PATH" --listener &
+ fi
+ cmd_toggle
+ ;;
+ *)
+ echo "Usage: $SCRIPT_NAME [toggle]" >&2; exit 1
+ ;;
esac
diff --git a/config/hypr/scripts/ThemeChanger.sh b/config/hypr/scripts/ThemeChanger.sh
index b41738f6..c19908e4 100755
--- a/config/hypr/scripts/ThemeChanger.sh
+++ b/config/hypr/scripts/ThemeChanger.sh
@@ -6,6 +6,12 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# ==================================================
set -euo pipefail
+# Wallust v3/v4 compatibility
+wallust_args=()
+# shellcheck source=/dev/null
+if [ -f "$HOME/.config/hypr/scripts/WallustConfig.sh" ]; then
+ . "$HOME/.config/hypr/scripts/WallustConfig.sh"
+fi
# SPDX-FileCopyrightText: 2025-present Ahum Maitra theahummaitra@gmail.com
#
@@ -25,12 +31,130 @@ require rofi
# notify-send is optional
have_notify() { command -v notify-send >/dev/null 2>&1; }
+capture_current_layout() {
+ if command -v jq >/dev/null 2>&1; then
+ hyprctl -j getoption general:layout 2>/dev/null | jq -r '.str // empty'
+ else
+ hyprctl getoption general:layout 2>/dev/null | awk 'NR==1 {print $2}'
+ fi
+}
+restore_layout_after_reload() {
+ local layout="$1"
+ [ -n "$layout" ] || return 0
+
+ if [ -x "$HOME/.config/hypr/scripts/ChangeLayout.sh" ]; then
+ if "$HOME/.config/hypr/scripts/ChangeLayout.sh" --no-notify "$layout" >/dev/null 2>&1; then
+ return 0
+ fi
+ fi
+
+ hyprctl keyword general:layout "$layout" >/dev/null 2>&1 || true
+}
+reload_hypr_preserve_layout() {
+ command -v hyprctl >/dev/null 2>&1 || return 0
+
+ local active_layout
+ active_layout="$(capture_current_layout || true)"
+
+ hyprctl reload config-only >/dev/null 2>&1 || true
+ sleep 0.1
+ restore_layout_after_reload "$active_layout"
+}
+# Cache theme list to avoid slow re-enumeration on every invocation
+cache_dir="${XDG_CACHE_HOME:-$HOME/.cache}"
+theme_cache="${cache_dir}/wallust_theme_list.txt"
+cache_max_age=86400 # seconds
+
+build_theme_list() {
+ wallust "${wallust_args[@]}" theme list \
+ | awk '/^- /{sub(/^- /,""); sub(/ \(.*/, ""); print}'
+}
+
+update_theme_cache() {
+ mkdir -p "$cache_dir"
+ local tmp
+ tmp="$(mktemp "${cache_dir}/wallust-theme-list.XXXXXX")"
+ if build_theme_list > "$tmp"; then
+ if [ -s "$tmp" ]; then
+ mv "$tmp" "$theme_cache"
+ return 0
+ fi
+ fi
+ rm -f "$tmp"
+ return 1
+}
+
+cache_mtime=$(stat -c %Y "$theme_cache" 2>/dev/null || echo 0)
+cache_age=$(( $(date +%s) - cache_mtime ))
+if [ ! -s "$theme_cache" ] || [ "$cache_age" -gt "$cache_max_age" ]; then
+ update_theme_cache || true
+fi
+
+ensure_wallust_waybar_style() {
+ local waybar_style="$HOME/.config/waybar/style.css"
+ local colors_file="$HOME/.config/waybar/wallust/colors-waybar.css"
+ local styles_dir="$HOME/.config/waybar/style"
+ [ -f "$colors_file" ] || return 0
+ if [ -f "$waybar_style" ] && grep -q 'colors-waybar.css' "$waybar_style"; then
+ return 0
+ fi
+ local candidates=(
+ "Wallust-Chroma-Fusion.css"
+ "Wallust-ML4W-modern.css"
+ "Wallust-Colored.css"
+ "Wallust-Box-type.css"
+ "Wallust-Simple.css"
+ )
+ for candidate in "${candidates[@]}"; do
+ if [ -f "$styles_dir/$candidate" ]; then
+ ln -sf "$styles_dir/$candidate" "$waybar_style"
+ break
+ fi
+ done
+}
+reload_running_cava_colors() {
+ # CAVA supports SIGUSR2 to reload colors without full audio reinitialization.
+ if pgrep -x cava >/dev/null 2>&1; then
+ pkill -USR2 -x cava >/dev/null 2>&1 || true
+ fi
+}
+
+wallust_hypr_colors="$HOME/.config/hypr/wallust/wallust-hyprland.conf"
+extract_wallust_hex() {
+ local key="$1"
+ awk -v key="$key" '
+ $1 == "$" key && $2 == "=" {
+ if (match($3, /^rgb\(([0-9A-Fa-f]{6})\)$/, m)) {
+ print toupper(m[1])
+ exit
+ }
+ }
+ ' "$wallust_hypr_colors"
+}
+
+apply_hypr_border_fallback() {
+ [ -s "$wallust_hypr_colors" ] || return 0
+ local color12 color10 color15 color0
+ color12="$(extract_wallust_hex color12)"
+ color10="$(extract_wallust_hex color10)"
+ color15="$(extract_wallust_hex color15)"
+ color0="$(extract_wallust_hex color0)"
+
+ [ -n "$color12" ] && hyprctl keyword general:col.active_border "rgb($color12)" >/dev/null 2>&1 || true
+ [ -n "$color10" ] && hyprctl keyword general:col.inactive_border "rgb($color10)" >/dev/null 2>&1 || true
+ [ -n "$color12" ] && hyprctl keyword decoration:shadow:color "rgb($color12)" >/dev/null 2>&1 || true
+ [ -n "$color10" ] && hyprctl keyword decoration:shadow:color_inactive "rgb($color10)" >/dev/null 2>&1 || true
+ [ -n "$color15" ] && hyprctl keyword group:col.border_active "rgb($color15)" >/dev/null 2>&1 || true
+ [ -n "$color0" ] && hyprctl keyword group:groupbar:col.active "rgb($color0)" >/dev/null 2>&1 || true
+}
# Prompt for theme; guard -e on cancel
set +e
-choice="$(wallust theme list \
- | sed -e '1d' -e 's/^- //' \
- | rofi -dmenu -i -p 'Select Global Theme')"
+if [ -s "$theme_cache" ]; then
+ choice="$(rofi -dmenu -i -p 'Select Global Theme' < "$theme_cache")"
+else
+ choice="$(build_theme_list | rofi -dmenu -i -p 'Select Global Theme')"
+fi
prompt_status=$?
set -e
@@ -41,9 +165,15 @@ fi
# Record time before applying so we can wait for fresh template outputs
start_ts=$(date +%s)
+# Notify quickly so users get feedback immediately
+have_notify && notify-send -a ThemeChanger \
+ -h string:x-dunst-stack-tag:themechanger \
+ "Applying theme" "Selected: ${choice}"
# Apply the theme and report result
-if wallust theme -- "${choice}"; then
+wallust_log="${XDG_CACHE_HOME:-$HOME/.cache}/wallust/themechanger.log"
+mkdir -p "$(dirname "$wallust_log")"
+if wallust "${wallust_args[@]}" theme -- "${choice}" >"$wallust_log" 2>&1; then
have_notify && notify-send -a ThemeChanger \
-h string:x-dunst-stack-tag:themechanger \
"Global theme changed" "Selected: ${choice}"
@@ -55,9 +185,7 @@ if wallust theme -- "${choice}"; then
targets=(
"$HOME/.config/waybar/wallust/colors-waybar.css"
"$HOME/.config/rofi/wallust/colors-rofi.rasi"
- "$HOME/.config/kitty/kitty-themes/01-Wallust.conf"
"$HOME/.config/hypr/wallust/wallust-hyprland.conf"
- "$HOME/.config/ghostty/wallust.conf"
)
# Normalize Ghostty palette syntax in case upstream templates or older targets used ':'
@@ -101,6 +229,13 @@ if wallust theme -- "${choice}"; then
sleep 0.5
fi
+ if [ "${ok:-0}" -ne 1 ]; then
+ have_notify && notify-send -u critical -a ThemeChanger \
+ -h string:x-dunst-stack-tag:themechanger \
+ "Theme files not updated" "See: $wallust_log"
+ exit 1
+ fi
+
# Small cushion before refresh to mirror wallpaper flow
sleep 0.2
# Normalize Rofi selection colors to use the palette's accent (color12)
@@ -118,10 +253,9 @@ if wallust theme -- "${choice}"; then
fi
fi
- # Reload Hyprland so new border colors from wallust-hyprland.conf take effect
- if command -v hyprctl >/dev/null 2>&1; then
- hyprctl reload >/dev/null 2>&1 || true
- fi
+ reload_hypr_preserve_layout
+ ensure_wallust_waybar_style
+ reload_running_cava_colors
# Refresh bars/menus after files are ready
if [ -x "$HOME/.config/hypr/scripts/Refresh.sh" ]; then
@@ -146,6 +280,6 @@ if wallust theme -- "${choice}"; then
else
have_notify && notify-send -u critical -a ThemeChanger \
-h string:x-dunst-stack-tag:themechanger \
- "Failed to apply theme" "${choice}"
+ "Failed to apply theme" "See: $wallust_log"
exit 1
fi
diff --git a/config/hypr/scripts/Toggle-Active-Window-Audio.sh b/config/hypr/scripts/Toggle-Active-Window-Audio.sh
index f32ded0e..c954541f 100755
--- a/config/hypr/scripts/Toggle-Active-Window-Audio.sh
+++ b/config/hypr/scripts/Toggle-Active-Window-Audio.sh
@@ -54,18 +54,18 @@ pidsJson="$(printf '%s\n' "${all_pids[@]}" | jq -s 'map(tonumber)')"
#// Check if any descendant PID matches application.process.id or else verify other statements.
mapfile -t sink_ids < <(jq -r --argjson pids "${pidsJson}" --arg class "${__class}" --arg title "${__title}" '
.[] |
- def lc(x): (x // "" | ascii_downcase);
- def normalize(x): x | gsub("[-_~.]+";" ") ;
+ def norm(x): (x // "" | ascii_downcase | gsub("[-_~.]+";" ") | gsub("[^a-z0-9 ]+";" ") | gsub("[[:space:]]+";" ") | gsub("^ +| +$";""));
+ def to_num(x): (try (x | tostring | tonumber) catch null);
select(
- (.properties["application.process.id"] | tostring | tonumber? as $p | $p != null and ($pids | index($p)))
+ (to_num(.properties["application.process.id"]) as $p | $p != null and ($pids | index($p)))
or
- (lc(.properties["application.name"]) | contains(lc($class)))
+ (norm(.properties["application.name"]) | contains(norm($class)))
or
- (lc(.properties["application.id"]) | contains(lc($class)))
+ (norm(.properties["application.id"]) | contains(norm($class)))
or
- (lc(.properties["application.process.binary"]) | contains(lc($class)))
+ (norm(.properties["application.process.binary"]) | contains(norm($class)))
or
- (normalize(lc(.properties["media.name"])) | contains(normalize(lc($title))))
+ (norm(.properties["media.name"]) | contains(norm($title)))
) | .index' <<< "${sink_json}"
)
@@ -87,8 +87,9 @@ if [[ "${#sink_ids[@]}" -eq 0 ]]; then
done
done
fallbackJson="$(printf '%s\n' "${all_fallback[@]}" | jq -s 'map(tonumber)')"
- mapfile -t sink_ids < <( jq -r --argjson pids "${fallbackJson}" '.[] |
- select((.properties["application.process.id"] | tostring | tonumber? as $p | $p != null and ($pids | index($p)))) | .index' <<< "${sink_json}" )
+ mapfile -t sink_ids < <( jq -r --argjson pids "${fallbackJson}" '.[] |
+ def to_num(x): (try (x | tostring | tonumber) catch null);
+ select((to_num(.properties["application.process.id"]) as $p | $p != null and ($pids | index($p)))) | .index' <<< "${sink_json}" )
fi
fi
diff --git a/config/hypr/scripts/WallpaperCmd.sh b/config/hypr/scripts/WallpaperCmd.sh
index 0191ee14..90a88fd9 100755
--- a/config/hypr/scripts/WallpaperCmd.sh
+++ b/config/hypr/scripts/WallpaperCmd.sh
@@ -24,8 +24,99 @@ if [ "$WWW_CMD" = "awww" ]; then
mkdir -p "$WWW_CACHE_DIR"
if [ ! -f "$WWW_MIGRATION_MARKER" ]; then
awww clear-cache >/dev/null 2>&1 || true
+ mkdir -p "$WWW_CACHE_DIR"
touch "$WWW_MIGRATION_MARKER"
fi
fi
+wallpaper_monitor_dimensions() {
+ local monitor="${1:-}"
+ local dims=""
+
+ command -v hyprctl >/dev/null 2>&1 || return 1
+
+ if command -v jq >/dev/null 2>&1; then
+ if [ -n "$monitor" ]; then
+ dims="$(hyprctl monitors -j 2>/dev/null | jq -r --arg mon "$monitor" '.[] | select(.name == $mon) | "\(.width) \(.height)"' | awk 'NF == 2 {print; exit}')"
+ else
+ dims="$(hyprctl monitors -j 2>/dev/null | jq -r '.[] | select(.focused == true) | "\(.width) \(.height)"' | awk 'NF == 2 {print; exit}')"
+ if [ -z "$dims" ]; then
+ dims="$(hyprctl monitors -j 2>/dev/null | jq -r '.[0] | "\(.width) \(.height)"' | awk 'NF == 2 {print; exit}')"
+ fi
+ fi
+ fi
+
+ if [ -z "$dims" ]; then
+ dims="$(hyprctl monitors 2>/dev/null | awk -v mon="$monitor" '
+ $1=="Monitor" {current=$2; target=(mon=="" || current==mon)}
+ target {
+ if (match($0, /[0-9]+x[0-9]+@/)) {
+ res = substr($0, RSTART, RLENGTH)
+ sub(/@.*/, "", res)
+ split(res, xy, "x")
+ print xy[1], xy[2]
+ exit
+ }
+ }
+ ')"
+ fi
+
+ [ -n "$dims" ] || return 1
+ printf '%s\n' "$dims"
+}
+
+wallpaper_image_dimensions() {
+ local image_path="$1"
+ local dims=""
+
+ [ -n "$image_path" ] && [ -f "$image_path" ] || return 1
+
+ if command -v magick >/dev/null 2>&1; then
+ dims="$(magick identify -ping -format '%w %h' "${image_path}[0]" 2>/dev/null || true)"
+ [ -n "$dims" ] || dims="$(magick identify -ping -format '%w %h' "$image_path" 2>/dev/null || true)"
+ elif command -v identify >/dev/null 2>&1; then
+ dims="$(identify -ping -format '%w %h' "${image_path}[0]" 2>/dev/null || true)"
+ [ -n "$dims" ] || dims="$(identify -ping -format '%w %h' "$image_path" 2>/dev/null || true)"
+ fi
+
+ [ -n "$dims" ] || return 1
+ printf '%s\n' "$dims"
+}
+
+wallpaper_resize_mode() {
+ local image_path="$1"
+ local monitor="${2:-}"
+ local mode="${WALLPAPER_RESIZE_MODE:-auto}"
+ local mon_w mon_h img_w img_h
+
+ mode="${mode,,}"
+ case "$mode" in
+ fit|crop)
+ printf '%s\n' "$mode"
+ return 0
+ ;;
+ auto|"")
+ ;;
+ *)
+ mode="auto"
+ ;;
+ esac
+
+ if ! read -r mon_w mon_h < <(wallpaper_monitor_dimensions "$monitor"); then
+ printf '%s\n' "crop"
+ return 0
+ fi
+ if ! read -r img_w img_h < <(wallpaper_image_dimensions "$image_path"); then
+ printf '%s\n' "crop"
+ return 0
+ fi
+
+ if [ "$img_w" -lt "$mon_w" ] || [ "$img_h" -lt "$mon_h" ]; then
+ printf '%s\n' "crop"
+ return 0
+ fi
+
+ # Auto mode prefers full-screen fill; set WALLPAPER_RESIZE_MODE=fit to preserve full image.
+ printf '%s\n' "crop"
+}
export WWW_CMD WWW_DAEMON WWW_CACHE_DIR WWW_DAEMON_ARGS WWW_MIGRATION_MARKER
diff --git a/config/hypr/scripts/WallpaperDaemon.sh b/config/hypr/scripts/WallpaperDaemon.sh
index 4d1c6e86..60c35a6d 100755
--- a/config/hypr/scripts/WallpaperDaemon.sh
+++ b/config/hypr/scripts/WallpaperDaemon.sh
@@ -11,12 +11,12 @@ SCRIPTSDIR="$HOME/.config/hypr/scripts"
# shellcheck source=/dev/null
. "$SCRIPTSDIR/WallpaperCmd.sh"
-if command -v "$WWW_DAEMON" >/dev/null 2>&1 && command -v "$WWW_CMD" >/dev/null 2>&1; then
+if command -v "$WWW_DAEMON" >/dev/null 2>&1 && command -v "$WWW_CMD" >/dev/null 2>&1 && ! pgrep -x "$WWW_DAEMON" >/dev/null 2>&1; then
"$WWW_DAEMON" "${WWW_DAEMON_ARGS[@]}" &
fi
# Give the daemon a moment to become ready
-for _ in {1..20}; do
+for _ in {1..50}; do
"$WWW_CMD" query >/dev/null 2>&1 && break
sleep 0.1
done
@@ -92,9 +92,11 @@ apply_wallpaper_for_monitor() {
fi
if [ -n "$wallpaper_path" ] && [ -f "$wallpaper_path" ]; then
- if ! "$WWW_CMD" img -o "$monitor" "$wallpaper_path" >/dev/null 2>&1; then
+ local resize_mode
+ resize_mode="$(wallpaper_resize_mode "$wallpaper_path" "$monitor")"
+ if ! "$WWW_CMD" img -o "$monitor" --resize "$resize_mode" "$wallpaper_path" >/dev/null 2>&1; then
sleep 0.3
- "$WWW_CMD" img -o "$monitor" "$wallpaper_path" >/dev/null 2>&1 &
+ "$WWW_CMD" img -o "$monitor" --resize "$resize_mode" "$wallpaper_path" >/dev/null 2>&1 &
fi
fi
}
diff --git a/config/hypr/scripts/WallustConfig.sh b/config/hypr/scripts/WallustConfig.sh
new file mode 100755
index 00000000..44ddff0b
--- /dev/null
+++ b/config/hypr/scripts/WallustConfig.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# Wallust version compatibility helpers
+#
+# Purpose:
+# - Wallust v3 reads ~/.config/wallust/wallust.toml (this repo ships a v3 config)
+# - Wallust v4 alpha uses a different config schema; users frequently install it
+# via wallust-git, which will fail to parse the v3 config.
+#
+# This file detects Wallust major version and sets arrays used by scripts:
+# - wallust_args: args to pass to wallust for wallpaper-derived palette generation
+# - wallust_kitty_args: args to pass to wallust for kitty-only palette generation
+
+wallust_args=()
+wallust_kitty_args=()
+
+wallust_prepare_args() {
+ wallust_args=()
+ wallust_kitty_args=()
+
+ command -v wallust >/dev/null 2>&1 || return 0
+
+ local version major
+ version=$(wallust --version 2>/dev/null | awk '{print $2}')
+ major=${version%%.*}
+
+ # Wallust v4 supports -C/--config-file.
+ if [ -n "$major" ] && [ "$major" -ge 4 ]; then
+ local v4_cfg="$HOME/.config/wallust/wallust-v4.toml"
+ local v4_kitty_cfg="$HOME/.config/wallust/wallust-kitty-v4.toml"
+
+ if [ -f "$v4_cfg" ]; then
+ wallust_args=(-C "$v4_cfg")
+ fi
+ if [ -f "$v4_kitty_cfg" ]; then
+ wallust_kitty_args=(-C "$v4_kitty_cfg")
+ fi
+ fi
+}
+
+wallust_prepare_args
diff --git a/config/hypr/scripts/WallustSwww.sh b/config/hypr/scripts/WallustSwww.sh
index 9df3ed61..3472d519 100755
--- a/config/hypr/scripts/WallustSwww.sh
+++ b/config/hypr/scripts/WallustSwww.sh
@@ -9,6 +9,73 @@
# Usage: WallustSwww.sh [absolute_path_to_wallpaper]
set -euo pipefail
+# Wallust v3/v4 compatibility
+wallust_args=()
+wallust_kitty_args=()
+# shellcheck source=/dev/null
+if [ -f "$HOME/.config/hypr/scripts/WallustConfig.sh" ]; then
+ . "$HOME/.config/hypr/scripts/WallustConfig.sh"
+fi
+have_notify() { command -v notify-send >/dev/null 2>&1; }
+wallust_log="${XDG_CACHE_HOME:-$HOME/.cache}/wallust/wallust-swww.log"
+mkdir -p "$(dirname "$wallust_log")"
+capture_current_layout() {
+ if command -v jq >/dev/null 2>&1; then
+ hyprctl -j getoption general:layout 2>/dev/null | jq -r '.str // empty'
+ else
+ hyprctl getoption general:layout 2>/dev/null | awk 'NR==1 {print $2}'
+ fi
+}
+restore_layout_after_reload() {
+ local layout="$1"
+ [ -n "$layout" ] || return 0
+
+ if [ -x "$HOME/.config/hypr/scripts/ChangeLayout.sh" ]; then
+ if "$HOME/.config/hypr/scripts/ChangeLayout.sh" --no-notify "$layout" >/dev/null 2>&1; then
+ return 0
+ fi
+ fi
+
+ hyprctl keyword general:layout "$layout" >/dev/null 2>&1 || true
+}
+reload_hypr_preserve_layout() {
+ command -v hyprctl >/dev/null 2>&1 || return 0
+
+ local active_layout
+ active_layout="$(capture_current_layout || true)"
+
+ hyprctl reload config-only >/dev/null 2>&1 || true
+ sleep 0.1
+ restore_layout_after_reload "$active_layout"
+}
+ensure_wallust_waybar_style() {
+ local waybar_style="$HOME/.config/waybar/style.css"
+ local colors_file="$HOME/.config/waybar/wallust/colors-waybar.css"
+ local styles_dir="$HOME/.config/waybar/style"
+ [ -f "$colors_file" ] || return 0
+ if [ -f "$waybar_style" ] && grep -q 'colors-waybar.css' "$waybar_style"; then
+ return 0
+ fi
+ local candidates=(
+ "Wallust-Chroma-Fusion.css"
+ "Wallust-ML4W-modern.css"
+ "Wallust-Colored.css"
+ "Wallust-Box-type.css"
+ "Wallust-Simple.css"
+ )
+ for candidate in "${candidates[@]}"; do
+ if [ -f "$styles_dir/$candidate" ]; then
+ ln -sf "$styles_dir/$candidate" "$waybar_style"
+ break
+ fi
+ done
+}
+reload_running_cava_colors() {
+ # CAVA supports SIGUSR2 to reload colors without full audio reinitialization.
+ if pgrep -x cava >/dev/null 2>&1; then
+ pkill -USR2 -x cava >/dev/null 2>&1 || true
+ fi
+}
# Inputs and paths
passed_path="${1:-}"
@@ -124,13 +191,23 @@ wait_for_templates() {
# Run wallust (silent) to regenerate templates defined in ~/.config/wallust/wallust.toml
# -s is used in this repo to keep things quiet and avoid extra prompts
start_ts=$(date +%s)
-wallust run -s "$wallpaper_path" || true
+if ! wallust "${wallust_args[@]}" run -s "$wallpaper_path" >"$wallust_log" 2>&1; then
+ have_notify && notify-send -u critical -a WallustSwww \
+ "Wallust failed" "See: $wallust_log"
+ exit 1
+fi
wallust_targets=(
"$HOME/.config/waybar/wallust/colors-waybar.css"
"$HOME/.config/rofi/wallust/colors-rofi.rasi"
"$HOME/.config/hypr/wallust/wallust-hyprland.conf"
)
-wait_for_templates "$start_ts" "${wallust_targets[@]}" || true
+if ! wait_for_templates "$start_ts" "${wallust_targets[@]}"; then
+ have_notify && notify-send -u critical -a WallustSwww \
+ "Wallust templates not updated" "See: $wallust_log"
+ exit 1
+fi
+ensure_wallust_waybar_style
+reload_running_cava_colors
# Normalize Rofi selection colors to a brighter accent and readable foreground
rofi_colors="$HOME/.config/rofi/wallust/colors-rofi.rasi"
@@ -153,28 +230,78 @@ fi
# Run kitty-only wallust config to keep terminal palette separate
run_wallust_with_config() {
local cfg="$1"
- if wallust run --help 2>&1 | grep -q -E '(^|[[:space:]])-c([,[:space:]]|$)|--config'; then
- wallust run -s -c "$cfg" "$wallpaper_path" || true
- else
- WALLUST_CONFIG="$cfg" wallust run -s "$wallpaper_path" || true
+ # Wallust v4: prefer config-file flag via WallustConfig.sh
+ if [ "${#wallust_kitty_args[@]}" -gt 0 ]; then
+ wallust "${wallust_kitty_args[@]}" run -s "$wallpaper_path" || true
+ return
fi
+ # Wallust v3+: prefer config-file flag when available.
+ # NOTE: Do not use -c here; on wallust 3.x it means colorspace, not config file.
+ if wallust run --help 2>&1 | grep -q -E -- '(^|[[:space:]])-C([,[:space:]]|$)|--config-file'; then
+ wallust run -s -C "$cfg" "$wallpaper_path" || true
+ return
+ fi
+ # Legacy fallback for builds that still honor env-based config override.
+ WALLUST_CONFIG="$cfg" wallust run -s "$wallpaper_path" || true
+}
+wallust_hypr_colors="$HOME/.config/hypr/wallust/wallust-hyprland.conf"
+extract_wallust_hex() {
+ local key="$1"
+ awk -v key="$key" '
+ $1 == "$" key && $2 == "=" {
+ if (match($3, /^rgb\(([0-9A-Fa-f]{6})\)$/, m)) {
+ print toupper(m[1])
+ exit
+ }
+ }
+ ' "$wallust_hypr_colors"
+}
+
+apply_hypr_border_fallback() {
+ [ -s "$wallust_hypr_colors" ] || return 0
+ local color12 color10 color15 color0
+ color12="$(extract_wallust_hex color12)"
+ color10="$(extract_wallust_hex color10)"
+ color15="$(extract_wallust_hex color15)"
+ color0="$(extract_wallust_hex color0)"
+
+ [ -n "$color12" ] && hyprctl keyword general:col.active_border "rgb($color12)" >/dev/null 2>&1 || true
+ [ -n "$color10" ] && hyprctl keyword general:col.inactive_border "rgb($color10)" >/dev/null 2>&1 || true
+ [ -n "$color12" ] && hyprctl keyword decoration:shadow:color "rgb($color12)" >/dev/null 2>&1 || true
+ [ -n "$color10" ] && hyprctl keyword decoration:shadow:color_inactive "rgb($color10)" >/dev/null 2>&1 || true
+ [ -n "$color15" ] && hyprctl keyword group:col.border_active "rgb($color15)" >/dev/null 2>&1 || true
+ [ -n "$color0" ] && hyprctl keyword group:groupbar:col.active "rgb($color0)" >/dev/null 2>&1 || true
+}
+
+apply_hypr_gap_fallback() {
+ local decorations_lua="$HOME/.config/hypr/UserConfigs/user_decorations.lua"
+ [ -s "$decorations_lua" ] || return 0
+ local gaps_in gaps_out border_size
+ gaps_in="$(sed -n 's/^[[:space:]]*gaps_in[[:space:]]*=[[:space:]]*\([0-9]\+\).*/\1/p' "$decorations_lua" | head -n1)"
+ gaps_out="$(sed -n 's/^[[:space:]]*gaps_out[[:space:]]*=[[:space:]]*\([0-9]\+\).*/\1/p' "$decorations_lua" | head -n1)"
+ border_size="$(sed -n 's/^[[:space:]]*border_size[[:space:]]*=[[:space:]]*\([0-9]\+\).*/\1/p' "$decorations_lua" | head -n1)"
+
+ [ -n "$gaps_in" ] && hyprctl keyword general:gaps_in "$gaps_in" >/dev/null 2>&1 || true
+ [ -n "$gaps_out" ] && hyprctl keyword general:gaps_out "$gaps_out" >/dev/null 2>&1 || true
+ [ -n "$border_size" ] && hyprctl keyword general:border_size "$border_size" >/dev/null 2>&1 || true
}
+# Apply Hyprland updates immediately to avoid delayed border/gap changes.
+reload_hypr_preserve_layout
+
kitty_cfg="$HOME/.config/wallust/wallust-kitty.toml"
+if [ "${#wallust_kitty_args[@]}" -gt 0 ]; then
+ kitty_cfg="$HOME/.config/wallust/wallust-kitty-v4.toml"
+fi
(
if [ -f "$kitty_cfg" ]; then
- kitty_ts=$(date +%s)
run_wallust_with_config "$kitty_cfg"
- wait_for_templates "$kitty_ts" "$HOME/.config/kitty/kitty-themes/01-Wallust.conf" || true
fi
- # Reload kitty colors when wallpaper-based theme is active
+ # Reload kitty colors when wallpaper-based theme is active.
+ # Use SIGUSR1 directly to avoid extra latency from kitty remote-control calls.
kitty_wallust_theme="$HOME/.config/kitty/kitty-themes/01-Wallust.conf"
if [ -s "$kitty_wallust_theme" ]; then
- if command -v kitty >/dev/null 2>&1; then
- kitty @ load-config >/dev/null 2>&1 || true
- kitty @ set-colors --all --configured "$kitty_wallust_theme" >/dev/null 2>&1 || true
- fi
if pidof kitty >/dev/null 2>&1; then
for pid in $(pidof kitty); do
kill -SIGUSR1 "$pid" 2>/dev/null || true
@@ -195,8 +322,5 @@ kitty_cfg="$HOME/.config/wallust/wallust-kitty.toml"
if pidof ghostty >/dev/null; then
for pid in $(pidof ghostty); do kill -SIGUSR2 "$pid" 2>/dev/null || true; done
fi
- # Reload Hyprland so new border colors from wallust-hyprland.conf take effect
- if command -v hyprctl >/dev/null 2>&1; then
- hyprctl reload >/dev/null 2>&1 || true
- fi
+ # Hyprland reload/keyword updates are applied above to avoid delayed color/gap updates.
) >/dev/null 2>&1 &
diff --git a/config/hypr/scripts/WaybarStartup.sh b/config/hypr/scripts/WaybarStartup.sh
new file mode 100755
index 00000000..ac269600
--- /dev/null
+++ b/config/hypr/scripts/WaybarStartup.sh
@@ -0,0 +1,88 @@
+#!/usr/bin/env bash
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# Dedicated startup helper for Waybar.
+# Handles both systemd user service setups and direct Waybar launch.
+
+runtime_dir="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
+export XDG_RUNTIME_DIR="$runtime_dir"
+
+is_waybar_running() {
+ pgrep -x "waybar" >/dev/null 2>&1 || pgrep -x '\.waybar-wrapped' >/dev/null 2>&1
+}
+
+wait_for_wayland() {
+ # If WAYLAND_DISPLAY is already valid, use it.
+ if [ -n "${WAYLAND_DISPLAY:-}" ] && [ -S "$runtime_dir/$WAYLAND_DISPLAY" ]; then
+ return 0
+ fi
+
+ # Otherwise wait briefly for an available Wayland socket.
+ for _ in $(seq 1 120); do
+ if [ -n "${WAYLAND_DISPLAY:-}" ] && [ -S "$runtime_dir/$WAYLAND_DISPLAY" ]; then
+ return 0
+ fi
+
+ for socket in "$runtime_dir"/wayland-[0-9]*; do
+ [ -S "$socket" ] || continue
+ case "$(basename "$socket")" in
+ *awww*) continue ;;
+ esac
+ export WAYLAND_DISPLAY="$(basename "$socket")"
+ return 0
+ done
+ sleep 0.1
+ done
+
+ return 1
+}
+
+start_waybar_direct() {
+ if command -v waybar >/dev/null 2>&1; then
+ waybar >/dev/null 2>&1 &
+ return 0
+ fi
+
+ if command -v .waybar-wrapped >/dev/null 2>&1; then
+ .waybar-wrapped >/dev/null 2>&1 &
+ return 0
+ fi
+
+ return 1
+}
+
+start_waybar_via_systemd() {
+ [ -x "$(command -v systemctl)" ] || return 1
+
+ local load_state
+ load_state="$(systemctl --user show waybar.service --property=LoadState --value 2>/dev/null || true)"
+ [ -n "$load_state" ] && [ "$load_state" != "not-found" ] || return 1
+
+ systemctl --user start waybar.service >/dev/null 2>&1 || return 1
+ sleep 0.4
+ is_waybar_running
+}
+
+main() {
+ # Allow key startup services to settle before launching Waybar.
+ sleep 1
+ wait_for_wayland || true
+
+ is_waybar_running && exit 0
+
+ if start_waybar_via_systemd; then
+ exit 0
+ fi
+
+ if is_waybar_running; then
+ exit 0
+ fi
+
+ start_waybar_direct || exit 1
+}
+
+main
diff --git a/config/hypr/scripts/keybinds_parser.py b/config/hypr/scripts/keybinds_parser.py
index 5b75d81c..bd6142d9 100755
--- a/config/hypr/scripts/keybinds_parser.py
+++ b/config/hypr/scripts/keybinds_parser.py
@@ -8,10 +8,30 @@
import sys
import re
import os
+CODE_KEY_MAP = {
+ 10: "1",
+ 11: "2",
+ 12: "3",
+ 13: "4",
+ 14: "5",
+ 15: "6",
+ 16: "7",
+ 17: "8",
+ 18: "9",
+ 19: "0",
+}
def normalize_combo(combo):
return combo.replace(" ", "").replace("\t", "")
+def humanize_key_token(mods, key):
+ key = key.strip()
+ code_match = re.match(r'(?i)^code:(\d+)$', key)
+ if code_match:
+ code_num = int(code_match.group(1))
+ return CODE_KEY_MAP.get(code_num, key)
+ return key
+
def extract_combo(line):
# Remove comments and whitespace
line = re.sub(r'\s*#.*$', '', line).strip()
@@ -128,6 +148,244 @@ def parse_files(files):
missing_unbind_suggestions.append(suggest)
return raw_keybinds, missing_unbind_suggestions
+def _parse_lua_string(value):
+ value = value.strip()
+ if len(value) < 2:
+ return None
+ if (value[0] == value[-1]) and value[0] in ("'", '"'):
+ quote = value[0]
+ body = value[1:-1]
+ if quote == '"':
+ body = body.replace('\\"', '"')
+ else:
+ body = body.replace("\\'", "'")
+ body = body.replace("\\\\", "\\")
+ return body
+ return None
+
+def _split_lua_args(arg_text):
+ args = []
+ current = []
+ depth = 0
+ in_string = None
+ escape = False
+ for ch in arg_text:
+ if in_string:
+ current.append(ch)
+ if escape:
+ escape = False
+ elif ch == '\\':
+ escape = True
+ elif ch == in_string:
+ in_string = None
+ continue
+ if ch in ("'", '"'):
+ in_string = ch
+ current.append(ch)
+ continue
+ if ch in "([{":
+ depth += 1
+ current.append(ch)
+ continue
+ if ch in ")]}":
+ depth = max(depth - 1, 0)
+ current.append(ch)
+ continue
+ if ch == ',' and depth == 0:
+ args.append("".join(current).strip())
+ current = []
+ continue
+ current.append(ch)
+ if current:
+ args.append("".join(current).strip())
+ return args
+
+def _find_lua_calls(text, function_names):
+ calls = []
+ pattern = re.compile(r'\b(' + "|".join(re.escape(name) for name in function_names) + r')\s*\(')
+ pos = 0
+ while True:
+ match = pattern.search(text, pos)
+ if not match:
+ break
+ fn = match.group(1)
+ start = match.end()
+ idx = start
+ depth = 1
+ in_string = None
+ escape = False
+ while idx < len(text):
+ ch = text[idx]
+ if in_string:
+ if escape:
+ escape = False
+ elif ch == '\\':
+ escape = True
+ elif ch == in_string:
+ in_string = None
+ else:
+ if ch in ("'", '"'):
+ in_string = ch
+ elif ch == '(':
+ depth += 1
+ elif ch == ')':
+ depth -= 1
+ if depth == 0:
+ calls.append((fn, text[start:idx]))
+ pos = idx + 1
+ break
+ idx += 1
+ else:
+ break
+ return calls
+
+def _find_lua_block(text, start_idx, open_char="{", close_char="}"):
+ depth = 0
+ in_string = None
+ escape = False
+ for idx in range(start_idx, len(text)):
+ ch = text[idx]
+ if in_string:
+ if escape:
+ escape = False
+ elif ch == "\\":
+ escape = True
+ elif ch == in_string:
+ in_string = None
+ continue
+ if ch in ("'", '"'):
+ in_string = ch
+ continue
+ if ch == open_char:
+ depth += 1
+ elif ch == close_char:
+ depth -= 1
+ if depth == 0:
+ return text[start_idx + 1:idx], idx + 1
+ return None, None
+
+def _extract_lua_bind_calls(text):
+ binds = []
+ calls = _find_lua_calls(text, ["bind", "bindm", "hl.bind"])
+ for fn, args_text in calls:
+ args = _split_lua_args(args_text)
+ if len(args) < 2:
+ continue
+ mods = _parse_lua_string(args[0])
+ key = _parse_lua_string(args[1])
+ if mods is None or key is None:
+ continue
+ description = None
+ desc_match = re.search(r'description\s*=\s*(\"(?:\\.|[^\"])*\"|\'(?:\\.|[^\'])*\')', args_text, re.DOTALL)
+ if desc_match:
+ description = _parse_lua_string(desc_match.group(1))
+ elif fn == "bindm" and len(args) >= 4:
+ description = _parse_lua_string(args[3])
+ binds.append({
+ "mods": mods,
+ "key": key,
+ "description": description or "",
+ })
+ return binds
+
+def _extract_lua_bind_tables(text):
+ binds = []
+ pattern = re.compile(r'\bapp_binds\s*=\s*\{', re.MULTILINE)
+ for match in pattern.finditer(text):
+ block, end_idx = _find_lua_block(text, match.end() - 1)
+ if block is None:
+ continue
+ idx = 0
+ depth = 0
+ in_string = None
+ escape = False
+ entry_start = None
+ while idx < len(block):
+ ch = block[idx]
+ if in_string:
+ if escape:
+ escape = False
+ elif ch == "\\":
+ escape = True
+ elif ch == in_string:
+ in_string = None
+ idx += 1
+ continue
+ if ch in ("'", '"'):
+ in_string = ch
+ idx += 1
+ continue
+ if ch == "{":
+ depth += 1
+ if depth == 1:
+ entry_start = idx + 1
+ elif ch == "}":
+ if depth == 1 and entry_start is not None:
+ entry_text = block[entry_start:idx]
+ args = _split_lua_args(entry_text)
+ if len(args) >= 4:
+ mods = _parse_lua_string(args[0])
+ key = _parse_lua_string(args[1])
+ description = _parse_lua_string(args[3])
+ if mods is not None and key is not None:
+ binds.append({
+ "mods": mods,
+ "key": key,
+ "description": description or "",
+ })
+ entry_start = None
+ depth = max(depth - 1, 0)
+ idx += 1
+ return binds
+
+def _extract_lua_binds(text):
+ binds = []
+ binds.extend(_extract_lua_bind_calls(text))
+ binds.extend(_extract_lua_bind_tables(text))
+ return binds
+
+def _format_lua_binds(binds):
+ formatted_lines = []
+ for bind in binds:
+ mods = bind["mods"].replace("$mainMod", "SUPER")
+ mods = re.sub(r'[ \t]+', '+', mods.strip())
+ key = humanize_key_token(mods, bind["key"])
+ if mods and key:
+ combo_str = f"{mods}+{key}"
+ elif key:
+ combo_str = key
+ else:
+ combo_str = mods
+ desc = (bind.get("description") or "").strip()
+ if desc:
+ formatted_lines.append(f"{combo_str} — {desc}")
+ else:
+ formatted_lines.append(combo_str)
+ return formatted_lines
+
+def parse_lua_files(files):
+ order = []
+ bind_map = {}
+ for file_path in files:
+ if not os.path.exists(file_path):
+ continue
+ try:
+ with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
+ binds = _extract_lua_binds(f.read())
+ except Exception as e:
+ sys.stderr.write(f"Error reading {file_path}: {e}\n")
+ continue
+ for bind in binds:
+ combo_key = normalize_combo(f"{bind['mods']},{bind['key']}")
+ if combo_key in bind_map:
+ try:
+ order.remove(combo_key)
+ except ValueError:
+ pass
+ bind_map[combo_key] = bind
+ order.append(combo_key)
+ effective_binds = [bind_map[key] for key in order if key in bind_map]
+ return _format_lua_binds(effective_binds)
def format_for_rofi(raw_binds):
formatted_lines = []
@@ -186,6 +444,7 @@ def format_for_rofi(raw_binds):
# Formatting mods
mods = mods.replace("$mainMod", "SUPER")
mods = re.sub(r'[ \t]+', '+', mods)
+ key = humanize_key_token(mods, key)
# Build combo string
if mods and key:
@@ -214,7 +473,16 @@ def main():
sys.exit(0)
config_files = sys.argv[1:]
-
+ has_lua = any(path.endswith(".lua") for path in config_files)
+ if has_lua:
+ formatted = parse_lua_files(config_files)
+ if not formatted:
+ print("no keybinds found.")
+ sys.exit(1)
+ for line in formatted:
+ print(line)
+ return
+
binds, suggestions = parse_files(config_files)
if not binds:
diff --git a/config/hypr/scripts/update_WindowRules.sh b/config/hypr/scripts/update_WindowRules.sh
index c8d236c4..293b14e9 100755
--- a/config/hypr/scripts/update_WindowRules.sh
+++ b/config/hypr/scripts/update_WindowRules.sh
@@ -9,12 +9,6 @@
CONFIGS_DIR="$HOME/.config/hypr/configs"
TARGET_FILE="$CONFIGS_DIR/WindowRules.conf"
-V3_FILE="$CONFIGS_DIR/WindowRules-config-v3.conf"
-
-if [[ ! -f "$V3_FILE" ]]; then
- echo "Error: Source configuration file not found: $V3_FILE"
- exit 1
-fi
get_hyprland_version() {
local ver="0.0.0"
@@ -46,13 +40,11 @@ REQUIRED_VER="0.53"
SMALLEST=$(printf '%s\n' "$REQUIRED_VER" "$VERSION" | sort -V | head -n1)
if [ "$SMALLEST" = "$REQUIRED_VER" ]; then
- echo "Version $VERSION >= $REQUIRED_VER. Updating WindowRules config..."
- # Backup existing config if it exists
if [ -f "$TARGET_FILE" ]; then
- echo "Backing up existing WindowRules.conf to WindowRules.conf.bak"
- mv "$TARGET_FILE" "$TARGET_FILE.bak"
+ echo "Version $VERSION >= $REQUIRED_VER. Using WindowRules.conf directly (no -config-v3 migration file)."
+ else
+ echo "Warning: WindowRules.conf not found at $TARGET_FILE"
fi
- cp "$V3_FILE" "$TARGET_FILE"
if command -v hyprctl &>/dev/null; then
if hyprctl instances &>/dev/null; then
diff --git a/config/hypr/v2.3.23 b/config/hypr/v2.3.23
deleted file mode 100644
index 51de9972..00000000
--- a/config/hypr/v2.3.23
+++ /dev/null
@@ -1,5 +0,0 @@
-### https://github.com/LinuxBeginnings ###
-## https://github.com/LinuxBeginnings/Hyprland-Dots
-## This is to have a reference of which version would be
-
-## note that this will always be higher than the released versions \ No newline at end of file
diff --git a/config/hypr/v2.3.24 b/config/hypr/v2.3.24
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/config/hypr/v2.3.24
diff --git a/config/kitty/kitty.conf b/config/kitty/kitty.conf
index a9571d59..fa7eb95b 100644
--- a/config/kitty/kitty.conf
+++ b/config/kitty/kitty.conf
@@ -4,7 +4,7 @@
include ./kitty-themes/01-Wallust.conf
font_family FantasqueSansM Nerd Font Mono
-font_size 16.0
+font_size 14.0
bold_font auto
italic_font auto
bold_italic_font auto
diff --git a/config/rofi/0-shared-fonts.rasi b/config/rofi/0-shared-fonts.rasi
index ba546b52..d0981550 100644
--- a/config/rofi/0-shared-fonts.rasi
+++ b/config/rofi/0-shared-fonts.rasi
@@ -6,11 +6,11 @@
/*****-- Fonts Size and Font Size -----*****/
configuration {
- font: "JetBrainsMono Nerd Font SemiBold 15";
+font: "JetBrainsMono Nerd Font SemiBold 13";
}
/*****-- Elements Font Size -----*****/
element-text {
- font: "JetBrainsMono Nerd Font SemiBold 13";
+font: "JetBrainsMono Nerd Font SemiBold 11";
}
diff --git a/config/rofi/config.rasi b/config/rofi/config.rasi
index f1280a95..9eb31f39 100644
--- a/config/rofi/config.rasi
+++ b/config/rofi/config.rasi
@@ -1,16 +1,16 @@
/* ---- 💫 https://github.com/LinuxBeginnings 💫 ---- */
-/* dKoolDots - Default
+/* dKoolDots - Default
* All main themes or configs are located in ~/.config/rofi/themes/
-* If you want to edit the config, that is where you should edit NOT here
+* If you want to edit the config, that is where you should edit NOT here
* To load a new theme, manually edit the file path below or choose desired theme via rofi theme selector (choose via app menu)
-* Alternative way to Load (preferred) own cooked by Ja
-* SUPER CTRL R - Choose style & SUPER CTRL SHIFT R
+* Alternative way to Load (preferred) own cooked by Ja
+* SUPER CTRL R - Choose style & SUPER CTRL SHIFT R
-* TIPS
-* If you have edited a config, rename it with a unique name. During update, the contents of
+* TIPS
+* If you have edited a config, rename it with a unique name. During update, the contents of
* ~/.config/rofi/themes/ will be replaced. */
/* ---- Global Configuration Fonts ---- */
diff --git a/config/rofi/dwm-config-horiz.rasi b/config/rofi/dwm-config-horiz.rasi
index e93bcc5e..2ce9f02f 100644
--- a/config/rofi/dwm-config-horiz.rasi
+++ b/config/rofi/dwm-config-horiz.rasi
@@ -2,7 +2,6 @@ configuration {
modi: "drun";
font: "JetBrainsMono Nerd Font 10";
show-icons: false;
- terminal: "kitty";
drun-display-format: "{name}";
display-drun: " ";
timeout {
diff --git a/config/rofi/dwm-config-vert.rasi b/config/rofi/dwm-config-vert.rasi
index 6e3e735e..6ac5d05d 100644
--- a/config/rofi/dwm-config-vert.rasi
+++ b/config/rofi/dwm-config-vert.rasi
@@ -2,7 +2,6 @@ configuration {
modi: "drun";
font: "JetBrainsMono Nerd Font 10";
show-icons: false;
- terminal: "kitty";
drun-display-format: "{name}";
display-drun: " ";
timeout {
diff --git a/config/rofi/themes/KooL_dwm.rasi b/config/rofi/themes/KooL_dwm.rasi
index 6c6d2b7e..2604a2e9 100644
--- a/config/rofi/themes/KooL_dwm.rasi
+++ b/config/rofi/themes/KooL_dwm.rasi
@@ -2,7 +2,6 @@ configuration {
modi: "drun";
font: "JetBrainsMono Nerd Font 10";
show-icons: true;
- terminal: "alacritty";
icon-theme: "Papirus-Dark";
drun-display-format: "{name}";
display-drun: "";
diff --git a/config/swaync/config.json b/config/swaync/config.json
index a5518596..7a30dbec 100755
--- a/config/swaync/config.json
+++ b/config/swaync/config.json
@@ -72,7 +72,7 @@
},
{
"label": "󰍃",
- "command": "hyprctl dispatch exit"
+ "command": "bash -c $HOME/.config/hypr/scripts/Logout.sh"
},
{
"label": "󰀝",
diff --git a/config/wallust/templates/colors-cava b/config/wallust/templates/colors-cava
index 3860904f..51eaed4c 100644
--- a/config/wallust/templates/colors-cava
+++ b/config/wallust/templates/colors-cava
@@ -84,8 +84,8 @@
method = pulse
source = auto
- method = pipewire
- source = auto
+; method = pipewire
+; source = auto
; method = alsa
; source = hw:Loopback,1
diff --git a/config/wallust/templates/colors-ghostty.conf b/config/wallust/templates/colors-ghostty.conf
index c1817cc4..7ef73fb5 100644
--- a/config/wallust/templates/colors-ghostty.conf
+++ b/config/wallust/templates/colors-ghostty.conf
@@ -1,6 +1,6 @@
# /* ---- 💫 https://github.com/LinuxBeginnings 💫 ---- */
# wallust template - colors for Ghostty
-# This file is included by ~/.config/ghostty/ghostty.config when present.
+# This file is included by ~/.config/ghostty/config when present.
# Core UI colors
foreground = {{foreground}}
diff --git a/config/wallust/wallust-kitty-v4.toml b/config/wallust/wallust-kitty-v4.toml
new file mode 100644
index 00000000..8be1dcd2
--- /dev/null
+++ b/config/wallust/wallust-kitty-v4.toml
@@ -0,0 +1,13 @@
+# /* ---- 💫 https://github.com/LinuxBeginnings 💫 ---- */ #
+# wallust configuration - kitty only (v4)
+
+backend = "fastresize"
+palette = "kmeans"
+style = "dark"
+use16cols = true
+kmeans = { k = 16, min_dist = 10.0 }
+threshold = 11
+
+[templates]
+kitty.template = 'colors-kitty.conf'
+kitty.target = '~/.config/kitty/kitty-themes/01-Wallust.conf'
diff --git a/config/wallust/wallust-v4.toml b/config/wallust/wallust-v4.toml
new file mode 100644
index 00000000..9dd74e79
--- /dev/null
+++ b/config/wallust/wallust-v4.toml
@@ -0,0 +1,53 @@
+# /* ---- 💫 https://github.com/LinuxBeginnings 💫 ---- */ #
+# wallust configuration - for wallust version 4.x
+#
+# NOTE:
+# - This repo also ships a v3 config at wallust.toml.
+# - Many distros install wallust-git which reports wallust 4.0.0-alpha.
+# Wallust v4 cannot parse the v3 config.
+#
+# This config is used automatically by scripts when wallust major version >= 4.
+
+# How the image is parsed in order to get the colors:
+# full - resized - wal - thumb - fastresize
+backend = "fastresize"
+
+# How the image colors are processed into a palette:
+# salience - ansi - kmeans
+palette = "kmeans"
+
+# Controls whether to generate a dark or light scheme
+style = "dark"
+
+# Dim the upper half of the palette (color8-color15) for 16-color variation
+use16cols = true
+
+# Kmeans tuning (v4 default values shown here explicitly)
+kmeans = { k = 16, min_dist = 10.0 }
+
+# Difference between similar colors, used by the colorspace:
+# 1 Not perceptible by human eyes.
+# 1 - 2 Perceptible through close observation.
+# 2 - 10 Perceptible at a glance.
+# 11 - 49 Colors are more similar than opposite
+# 100 Colors are exact opposite
+threshold = 11
+
+[templates]
+cava.template = 'colors-cava'
+cava.target = '~/.config/cava/config'
+
+hypr.template = 'colors-hyprland.conf'
+hypr.target = '~/.config/hypr/wallust/wallust-hyprland.conf'
+
+rofi.template = 'colors-rofi.rasi'
+rofi.target = '~/.config/rofi/wallust/colors-rofi.rasi'
+
+waybar.template = 'colors-waybar.css'
+waybar.target = '~/.config/waybar/wallust/colors-waybar.css'
+
+ghostty.template = 'colors-ghostty.conf'
+ghostty.target = '~/.config/ghostty/wallust.conf'
+
+quickshell.template = 'qml_color.json'
+quickshell.target = '~/.config/quickshell/qml_color.json'
diff --git a/config/waybar/Modules b/config/waybar/Modules
index 3b9e9ab3..1d7bd231 100644
--- a/config/waybar/Modules
+++ b/config/waybar/Modules
@@ -97,8 +97,8 @@
"clock": {
"interval": 1,
- //"format": " {:%I:%M %p}", // AM PM format
- "format": " {:%H:%M:%S}", // 24H
+ "format": " {:%I:%M %p}", // AM PM format
+ //"format": " {:%H:%M:%S}",// 24H
"format-alt": " {:L%H:%M  %Y, %d %B, %A}",
"tooltip-format": "<tt><small>{calendar}</small></tt>",
"calendar": {
@@ -125,8 +125,8 @@
},
"clock#2": {
- //"format": " {:%I:%M %p}", // AM PM format
- "format": " {:%H:%M}", // 24H
+ "format": " {:%I:%M %p}", // AM PM format
+ //"format": " {:%H:%M}",// 24H
"format-alt": "{:L%A | %H:%M | %e %B}",
"tooltip-format": "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>"
},
@@ -146,8 +146,8 @@
},
"clock#5": {
- //"format": "{:%A, %I:%M %P}", // AM PM format
- "format": "{:%a %d | %H:%M}", // 24H
+ "format": "{:%A, %I:%M %P}",// AM PM format
+ //"format": "{:%a %d | %H:%M}",// 24H
"format-alt": "{:L%A, %d %B, %Y (%R)}",
"tooltip-format": "<big>{:%B %Y}</big>\n<tt><small>{calendar}</small></tt>",
},
diff --git a/config/waybar/ModulesCustom b/config/waybar/ModulesCustom
index f3e49da4..87ea6d69 100644
--- a/config/waybar/ModulesCustom
+++ b/config/waybar/ModulesCustom
@@ -115,6 +115,17 @@
"format": " {}",
"on-click": "$HOME/.config/hypr/scripts/KeyboardLayout.sh switch",
},
+"custom/hypr_layout": {
+ "exec": "$HOME/.config/hypr/scripts/HyprLayoutModule.sh status",
+ "return-type": "json",
+ "interval": 2,
+ "signal": 8,
+ "format": "{}",
+ "on-click": "$HOME/.config/hypr/scripts/HyprLayoutModule.sh menu",
+ "on-click-right": "$HOME/.config/hypr/scripts/HyprLayoutModule.sh next",
+ "tooltip": true,
+ "escape": false
+},
"custom/light_dark": {
"format": "󰔎 ",
@@ -174,7 +185,7 @@
"on-scroll-down": "$HOME/.config/hypr/scripts/Volume.sh --dec",
"smooth-scrolling-threshold": 1,
},
-
+
"custom/power": {
"format": " ⏻ ",
"on-click": "$HOME/.config/hypr/scripts/Wlogout.sh",
@@ -189,10 +200,10 @@
"tooltip": true,
"tooltip-format": "Left Click: Reboot",
},
-
+
"custom/quit": {
"format": "󰗼",
- "on-click": "hyprctl dispatch exit",
+ "on-click": "$HOME/.config/hypr/scripts/Logout.sh",
"tooltip": true,
"tooltip-format": "Left Click: Exit Hyprland",
},
diff --git a/config/waybar/configs/BOT-&-Left-SouthWest b/config/waybar/configs/BOT-&-Left-SouthWest
index 5eb6329d..b637f35d 100644
--- a/config/waybar/configs/BOT-&-Left-SouthWest
+++ b/config/waybar/configs/BOT-&-Left-SouthWest
@@ -23,6 +23,9 @@
"margin-bottom": 2,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/menu",
"cpu",
"temperature",
diff --git a/config/waybar/configs/BOT-&-Right-SouthEast b/config/waybar/configs/BOT-&-Right-SouthEast
index d3de215a..f50ee7ff 100644
--- a/config/waybar/configs/BOT-&-Right-SouthEast
+++ b/config/waybar/configs/BOT-&-Right-SouthEast
@@ -23,6 +23,9 @@
"margin-bottom": 2,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/menu",
"cpu",
"temperature",
diff --git a/config/waybar/configs/BOT-Camellia b/config/waybar/configs/BOT-Camellia
index 5e09e64c..4b7374a1 100644
--- a/config/waybar/configs/BOT-Camellia
+++ b/config/waybar/configs/BOT-Camellia
@@ -27,6 +27,9 @@
//"margin-right": 0,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"hyprland/workspaces#cam",
"custom/separator#line",
"mpris",
diff --git a/config/waybar/configs/BOT-Chrysanthemum b/config/waybar/configs/BOT-Chrysanthemum
index 366d0312..6527e7b0 100644
--- a/config/waybar/configs/BOT-Chrysanthemum
+++ b/config/waybar/configs/BOT-Chrysanthemum
@@ -25,6 +25,9 @@
"margin-top": 0,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"clock#5",
"mpris",
"tray",
diff --git a/config/waybar/configs/BOT-Default b/config/waybar/configs/BOT-Default
index 3e8bfe46..89bd7781 100644
--- a/config/waybar/configs/BOT-Default
+++ b/config/waybar/configs/BOT-Default
@@ -22,7 +22,9 @@
"margin-right": 8,
"modules-left": [
- "custom/separator#blank",
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/cava_mviz",
"custom/separator#blank",
"custom/playerctl",
diff --git a/config/waybar/configs/BOT-Default-Laptop b/config/waybar/configs/BOT-Default-Laptop
index df0c9fc4..77b5ccdc 100644
--- a/config/waybar/configs/BOT-Default-Laptop
+++ b/config/waybar/configs/BOT-Default-Laptop
@@ -22,7 +22,9 @@
"margin-right": 8,
"modules-left": [
- "custom/separator#blank",
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/cava_mviz",
"custom/separator#blank",
"custom/playerctl",
diff --git a/config/waybar/configs/BOT-Gardenia b/config/waybar/configs/BOT-Gardenia
index 09c7537e..79b4d4da 100644
--- a/config/waybar/configs/BOT-Gardenia
+++ b/config/waybar/configs/BOT-Gardenia
@@ -26,6 +26,9 @@
"width": 1000,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"clock#5",
"mpris",
"tray",
diff --git a/config/waybar/configs/BOT-Peony b/config/waybar/configs/BOT-Peony
index 8a11dc8e..cee664b8 100644
--- a/config/waybar/configs/BOT-Peony
+++ b/config/waybar/configs/BOT-Peony
@@ -26,6 +26,9 @@
"width": 1444,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"hyprland/workspaces#roman",
"mpris",
"group/notify",
diff --git a/config/waybar/configs/BOT-Simple b/config/waybar/configs/BOT-Simple
index 05941ed5..9fd197dd 100644
--- a/config/waybar/configs/BOT-Simple
+++ b/config/waybar/configs/BOT-Simple
@@ -20,6 +20,9 @@
"margin-top": 2,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"idle_inhibitor",
"group/mobo_drawer",
"hyprland/workspaces#rw",
diff --git a/config/waybar/configs/BOT-Sleek b/config/waybar/configs/BOT-Sleek
index 2220db6c..8da830a3 100644
--- a/config/waybar/configs/BOT-Sleek
+++ b/config/waybar/configs/BOT-Sleek
@@ -18,6 +18,9 @@
"margin-bottom": 2,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/menu",
"custom/separator#blank_2",
"hyprland/workspaces",
diff --git a/config/waybar/configs/LEFT-WestWing b/config/waybar/configs/LEFT-WestWing
index 2195750f..2462b0a5 100644
--- a/config/waybar/configs/LEFT-WestWing
+++ b/config/waybar/configs/LEFT-WestWing
@@ -23,6 +23,9 @@
//"gtk-layer-shell": true,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"clock#vertical",
"custom/light_dark",
],
diff --git a/config/waybar/configs/LEFT-WestWing-v2 b/config/waybar/configs/LEFT-WestWing-v2
index e472e9f6..9df35c43 100644
--- a/config/waybar/configs/LEFT-WestWing-v2
+++ b/config/waybar/configs/LEFT-WestWing-v2
@@ -23,6 +23,9 @@
//"gtk-layer-shell": true,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"group/notify",
"clock#vertical",
diff --git a/config/waybar/configs/RIGHT-EastWing b/config/waybar/configs/RIGHT-EastWing
index 8b964f03..93eb7888 100644
--- a/config/waybar/configs/RIGHT-EastWing
+++ b/config/waybar/configs/RIGHT-EastWing
@@ -23,6 +23,9 @@
//"gtk-layer-shell": true,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"clock#vertical",
"custom/light_dark",
],
diff --git a/config/waybar/configs/RIGHT-EastWing-v2 b/config/waybar/configs/RIGHT-EastWing-v2
index 628f912f..09ab4779 100644
--- a/config/waybar/configs/RIGHT-EastWing-v2
+++ b/config/waybar/configs/RIGHT-EastWing-v2
@@ -23,6 +23,9 @@
//"gtk-layer-shell": true,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"group/notify",
"clock#vertical",
diff --git a/config/waybar/configs/TOP-&-BOT-SummitSplit b/config/waybar/configs/TOP-&-BOT-SummitSplit
index 7ed65f97..82d13417 100644
--- a/config/waybar/configs/TOP-&-BOT-SummitSplit
+++ b/config/waybar/configs/TOP-&-BOT-SummitSplit
@@ -23,6 +23,9 @@
"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"cpu",
"power-profiles-daemon",
"temperature",
diff --git a/config/waybar/configs/TOP-&-BOT-SummitSplit-glass b/config/waybar/configs/TOP-&-BOT-SummitSplit-glass
index 0cef4521..1a653434 100644
--- a/config/waybar/configs/TOP-&-BOT-SummitSplit-glass
+++ b/config/waybar/configs/TOP-&-BOT-SummitSplit-glass
@@ -23,6 +23,9 @@
"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"cpu",
"power-profiles-daemon",
"temperature",
diff --git a/config/waybar/configs/TOP-&-BOT-SummitSplit-v2 b/config/waybar/configs/TOP-&-BOT-SummitSplit-v2
index ec5ce391..1267c08e 100644
--- a/config/waybar/configs/TOP-&-BOT-SummitSplit-v2
+++ b/config/waybar/configs/TOP-&-BOT-SummitSplit-v2
@@ -21,6 +21,9 @@
"gtk-layer-shell": true,
"reload_style_on_change": true,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"group/app_drawer",
"keyboard-state",
"clock",
diff --git a/config/waybar/configs/TOP-&-BOT-SummitSplit-v3 b/config/waybar/configs/TOP-&-BOT-SummitSplit-v3
index fc2ebecb..10d7e1b2 100644
--- a/config/waybar/configs/TOP-&-BOT-SummitSplit-v3
+++ b/config/waybar/configs/TOP-&-BOT-SummitSplit-v3
@@ -18,6 +18,9 @@
"gtk-layer-shell": true,
"reload_style_on_change": true,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"idle_inhibitor",
"custom/separator#blank",
"tray",
diff --git a/config/waybar/configs/TOP-&-Left-NorthWest b/config/waybar/configs/TOP-&-Left-NorthWest
index 99282e23..c36916ab 100644
--- a/config/waybar/configs/TOP-&-Left-NorthWest
+++ b/config/waybar/configs/TOP-&-Left-NorthWest
@@ -24,6 +24,9 @@
"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/menu",
"custom/separator#blank_2",
"group/motherboard",
diff --git a/config/waybar/configs/TOP-&-Right-NorthEast b/config/waybar/configs/TOP-&-Right-NorthEast
index deba8fb0..60054997 100644
--- a/config/waybar/configs/TOP-&-Right-NorthEast
+++ b/config/waybar/configs/TOP-&-Right-NorthEast
@@ -24,6 +24,9 @@
"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/menu",
"custom/separator#blank_2",
"group/motherboard",
diff --git a/config/waybar/configs/TOP-0-Ja-0 b/config/waybar/configs/TOP-0-Ja-0
index e54d32f8..ba81a058 100644
--- a/config/waybar/configs/TOP-0-Ja-0
+++ b/config/waybar/configs/TOP-0-Ja-0
@@ -22,6 +22,9 @@
"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"idle_inhibitor",
"custom/separator#blank",
"tray",
diff --git a/config/waybar/configs/TOP-Arrow b/config/waybar/configs/TOP-Arrow
index 14089a41..74c8be50 100644
--- a/config/waybar/configs/TOP-Arrow
+++ b/config/waybar/configs/TOP-Arrow
@@ -15,6 +15,9 @@
"position": "top",
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"hyprland/mode",
"hyprland/workspaces",
"custom/arrow10",
diff --git a/config/waybar/configs/TOP-Camellia b/config/waybar/configs/TOP-Camellia
index d6723438..91b790ee 100644
--- a/config/waybar/configs/TOP-Camellia
+++ b/config/waybar/configs/TOP-Camellia
@@ -27,6 +27,9 @@
//"margin-right": 0,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"hyprland/workspaces#cam",
"custom/separator#line",
"mpris",
diff --git a/config/waybar/configs/TOP-Chrysanthemum b/config/waybar/configs/TOP-Chrysanthemum
index 2028b179..4ba89ff4 100644
--- a/config/waybar/configs/TOP-Chrysanthemum
+++ b/config/waybar/configs/TOP-Chrysanthemum
@@ -25,6 +25,9 @@
"margin-top": 0,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"clock#5",
"mpris",
"tray",
diff --git a/config/waybar/configs/TOP-Default b/config/waybar/configs/TOP-Default
index 03dba497..ffcbdbe8 100644
--- a/config/waybar/configs/TOP-Default
+++ b/config/waybar/configs/TOP-Default
@@ -23,6 +23,8 @@
"modules-left": [
"custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/cava_mviz",
"custom/separator#blank",
"custom/playerctl",
diff --git a/config/waybar/configs/TOP-Default-Laptop b/config/waybar/configs/TOP-Default-Laptop
index 0d17d832..b20bd357 100644
--- a/config/waybar/configs/TOP-Default-Laptop
+++ b/config/waybar/configs/TOP-Default-Laptop
@@ -23,6 +23,8 @@
"modules-left": [
"custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/cava_mviz",
"custom/separator#blank",
"custom/playerctl",
diff --git a/config/waybar/configs/TOP-Default-Laptop-glass b/config/waybar/configs/TOP-Default-Laptop-glass
index 1e94d40a..514a6da7 100644
--- a/config/waybar/configs/TOP-Default-Laptop-glass
+++ b/config/waybar/configs/TOP-Default-Laptop-glass
@@ -23,6 +23,8 @@
"modules-left": [
"custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/cava_mviz",
"custom/separator#blank",
"custom/playerctl",
diff --git a/config/waybar/configs/TOP-Default-Laptop-old-v1 b/config/waybar/configs/TOP-Default-Laptop-old-v1
index 76dcd85e..fff0fdac 100644
--- a/config/waybar/configs/TOP-Default-Laptop-old-v1
+++ b/config/waybar/configs/TOP-Default-Laptop-old-v1
@@ -22,6 +22,9 @@
"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"hyprland/workspaces#pacman",
"custom/separator#dot-line",
"cpu",
diff --git a/config/waybar/configs/TOP-Default-Laptop-old-v2 b/config/waybar/configs/TOP-Default-Laptop-old-v2
index 5aea9d9b..e878bc4c 100644
--- a/config/waybar/configs/TOP-Default-Laptop-old-v2
+++ b/config/waybar/configs/TOP-Default-Laptop-old-v2
@@ -22,6 +22,9 @@
"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/menu",
"custom/light_dark",
"custom/separator#dot-line",
diff --git a/config/waybar/configs/TOP-Default-Laptop-old-v3 b/config/waybar/configs/TOP-Default-Laptop-old-v3
index 762eddb1..10636f12 100644
--- a/config/waybar/configs/TOP-Default-Laptop-old-v3
+++ b/config/waybar/configs/TOP-Default-Laptop-old-v3
@@ -22,6 +22,9 @@
"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/menu",
"custom/light_dark",
"custom/separator#dot-line",
diff --git a/config/waybar/configs/TOP-Default-Laptop-old-v4 b/config/waybar/configs/TOP-Default-Laptop-old-v4
index b20c284d..67a2f4a2 100644
--- a/config/waybar/configs/TOP-Default-Laptop-old-v4
+++ b/config/waybar/configs/TOP-Default-Laptop-old-v4
@@ -22,6 +22,9 @@
"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"group/app_drawer",
"custom/separator#dot-line",
"group/mobo_drawer",
diff --git a/config/waybar/configs/TOP-Default-Laptop-old-v5 b/config/waybar/configs/TOP-Default-Laptop-old-v5
index af827aa3..8fa917a3 100644
--- a/config/waybar/configs/TOP-Default-Laptop-old-v5
+++ b/config/waybar/configs/TOP-Default-Laptop-old-v5
@@ -23,6 +23,8 @@
"modules-left": [
"custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/cava_mviz",
"custom/separator#blank",
"custom/playerctl",
diff --git a/config/waybar/configs/TOP-Default-old-v1 b/config/waybar/configs/TOP-Default-old-v1
index 83e3726c..81938907 100644
--- a/config/waybar/configs/TOP-Default-old-v1
+++ b/config/waybar/configs/TOP-Default-old-v1
@@ -22,6 +22,9 @@
"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"hyprland/workspaces#pacman",
"custom/separator#dot-line",
"cpu",
diff --git a/config/waybar/configs/TOP-Default-old-v2 b/config/waybar/configs/TOP-Default-old-v2
index ef28bf86..6548213e 100644
--- a/config/waybar/configs/TOP-Default-old-v2
+++ b/config/waybar/configs/TOP-Default-old-v2
@@ -22,6 +22,9 @@
"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/menu",
"custom/light_dark",
"custom/separator#dot-line",
diff --git a/config/waybar/configs/TOP-Default-old-v3 b/config/waybar/configs/TOP-Default-old-v3
index 273ddbd9..ef11a0bd 100644
--- a/config/waybar/configs/TOP-Default-old-v3
+++ b/config/waybar/configs/TOP-Default-old-v3
@@ -22,6 +22,9 @@
"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/menu",
"custom/light_dark",
"custom/separator#dot-line",
diff --git a/config/waybar/configs/TOP-Default-old-v4 b/config/waybar/configs/TOP-Default-old-v4
index dd5a9033..8a6c0d34 100644
--- a/config/waybar/configs/TOP-Default-old-v4
+++ b/config/waybar/configs/TOP-Default-old-v4
@@ -22,6 +22,9 @@
"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"group/app_drawer",
"custom/separator#dot-line",
"group/mobo_drawer",
diff --git a/config/waybar/configs/TOP-Everforest b/config/waybar/configs/TOP-Everforest
index 26bec9d8..d27b926f 100644
--- a/config/waybar/configs/TOP-Everforest
+++ b/config/waybar/configs/TOP-Everforest
@@ -23,6 +23,9 @@
//"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/arch",
"custom/separator#blank_2",
"hyprland/workspaces#rw",
diff --git a/config/waybar/configs/TOP-Everforest-glass b/config/waybar/configs/TOP-Everforest-glass
index 65e7542a..80c732fe 100644
--- a/config/waybar/configs/TOP-Everforest-glass
+++ b/config/waybar/configs/TOP-Everforest-glass
@@ -23,6 +23,9 @@
//"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/arch",
"hyprland/workspaces#rw",
// "mpris",
diff --git a/config/waybar/configs/TOP-Gardenia b/config/waybar/configs/TOP-Gardenia
index 1357da5f..f67fc65a 100644
--- a/config/waybar/configs/TOP-Gardenia
+++ b/config/waybar/configs/TOP-Gardenia
@@ -26,6 +26,9 @@
"width": 1000,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"clock#5",
"mpris",
"tray",
diff --git a/config/waybar/configs/TOP-Minimal-Long b/config/waybar/configs/TOP-Minimal-Long
index a40aa673..2ae8c75b 100644
--- a/config/waybar/configs/TOP-Minimal-Long
+++ b/config/waybar/configs/TOP-Minimal-Long
@@ -23,6 +23,9 @@
"margin-right": 8,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/menu",
"custom/separator#blank_2",
"hyprland/workspaces#pacman",
diff --git a/config/waybar/configs/TOP-Minimal-Short b/config/waybar/configs/TOP-Minimal-Short
index 5f0af150..533dfdf2 100644
--- a/config/waybar/configs/TOP-Minimal-Short
+++ b/config/waybar/configs/TOP-Minimal-Short
@@ -16,6 +16,9 @@
"margin-top": 3,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"clock",
"custom/weather2",
],
diff --git a/config/waybar/configs/TOP-Peony b/config/waybar/configs/TOP-Peony
index 7f666c2f..daa98957 100644
--- a/config/waybar/configs/TOP-Peony
+++ b/config/waybar/configs/TOP-Peony
@@ -26,6 +26,9 @@
"width": 1444,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"hyprland/workspaces#roman",
"mpris",
"group/notify",
diff --git a/config/waybar/configs/TOP-Simple b/config/waybar/configs/TOP-Simple
index acfa8a43..44a297dc 100644
--- a/config/waybar/configs/TOP-Simple
+++ b/config/waybar/configs/TOP-Simple
@@ -20,6 +20,9 @@
"margin-top": 2,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"idle_inhibitor",
"group/mobo_drawer",
"hyprland/workspaces#rw",
diff --git a/config/waybar/configs/TOP-Simpliest b/config/waybar/configs/TOP-Simpliest
index 15c40918..93eec8c2 100644
--- a/config/waybar/configs/TOP-Simpliest
+++ b/config/waybar/configs/TOP-Simpliest
@@ -20,6 +20,9 @@
"margin-top": 2,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"hyprland/workspaces",
"tray",
"mpris",
diff --git a/config/waybar/configs/TOP-Sleek b/config/waybar/configs/TOP-Sleek
index cd50039c..d7caacfa 100644
--- a/config/waybar/configs/TOP-Sleek
+++ b/config/waybar/configs/TOP-Sleek
@@ -17,6 +17,9 @@
"margin-top": 2,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"custom/menu",
"custom/separator#blank_2",
"hyprland/workspaces",
diff --git a/config/waybar/configs/TOP-ddubs-simple-bar b/config/waybar/configs/TOP-ddubs-simple-bar
index be5f136e..70461a44 100644
--- a/config/waybar/configs/TOP-ddubs-simple-bar
+++ b/config/waybar/configs/TOP-ddubs-simple-bar
@@ -23,6 +23,7 @@
"modules-left": [
"custom/separator#blank",
+ "custom/hypr_layout",
"custom/separator#blank",
"custom/cava_mviz",
"custom/separator#blank",
diff --git a/config/waybar/configs/[TOP & BOT] SummitSplit v3 b/config/waybar/configs/[TOP & BOT] SummitSplit v3
index fc2ebecb..10d7e1b2 100644
--- a/config/waybar/configs/[TOP & BOT] SummitSplit v3
+++ b/config/waybar/configs/[TOP & BOT] SummitSplit v3
@@ -18,6 +18,9 @@
"gtk-layer-shell": true,
"reload_style_on_change": true,
"modules-left": [
+ "custom/separator#blank",
+ "custom/hypr_layout",
+ "custom/separator#blank",
"idle_inhibitor",
"custom/separator#blank",
"tray",
diff --git a/config/waybar/style/0-VERTICAL-Catpuccin-Mocha.css b/config/waybar/style/0-VERTICAL-Catpuccin-Mocha.css
index e699cc65..a72b2694 100644
--- a/config/waybar/style/0-VERTICAL-Catpuccin-Mocha.css
+++ b/config/waybar/style/0-VERTICAL-Catpuccin-Mocha.css
@@ -109,6 +109,7 @@ tooltip label {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -240,3 +241,27 @@ window#waybar.bottombar #pulseaudio-slider trough {
border-radius: 5px;
background-color: @blue;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/0-VERTICAL-Golden-Noir.css b/config/waybar/style/0-VERTICAL-Golden-Noir.css
index 61db3fd5..45a6fe5a 100644
--- a/config/waybar/style/0-VERTICAL-Golden-Noir.css
+++ b/config/waybar/style/0-VERTICAL-Golden-Noir.css
@@ -136,6 +136,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -223,4 +224,28 @@ window#waybar.bottombar #pulseaudio-slider trough {
min-width: 5px;
border-radius: 5px;
background-color: #ba5663;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/0-VERTICAL-Oglo-Chicklets.css b/config/waybar/style/0-VERTICAL-Oglo-Chicklets.css
index 0403cb10..90b287fd 100644
--- a/config/waybar/style/0-VERTICAL-Oglo-Chicklets.css
+++ b/config/waybar/style/0-VERTICAL-Oglo-Chicklets.css
@@ -102,6 +102,7 @@ button.active {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -420,4 +421,28 @@ window#waybar.bottombar #pulseaudio-slider trough {
min-width: 5px;
border-radius: 5px;
background-color: #64b6ac;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Black-&-White-Monochrome.css b/config/waybar/style/Black-&-White-Monochrome.css
index 59005708..60ff6e6e 100644
--- a/config/waybar/style/Black-&-White-Monochrome.css
+++ b/config/waybar/style/Black-&-White-Monochrome.css
@@ -146,6 +146,7 @@ tooltip label{
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -225,4 +226,28 @@ tooltip label{
#pulseaudio-slider highlight {
min-height: 10px;
border-radius: 5px;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Catppuccin-Frappe.css b/config/waybar/style/Catppuccin-Frappe.css
index 21e86b3e..228098a6 100644
--- a/config/waybar/style/Catppuccin-Frappe.css
+++ b/config/waybar/style/Catppuccin-Frappe.css
@@ -109,6 +109,7 @@ window#waybar.hidden {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -289,4 +290,28 @@ window#waybar.hidden {
#pulseaudio-slider highlight {
min-height: 10px;
border-radius: 5px;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Catppuccin-Latte.css b/config/waybar/style/Catppuccin-Latte.css
index 3bc3ef91..013eb098 100644
--- a/config/waybar/style/Catppuccin-Latte.css
+++ b/config/waybar/style/Catppuccin-Latte.css
@@ -108,6 +108,7 @@ window#waybar.hidden {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -289,3 +290,27 @@ window#waybar.hidden {
min-height: 10px;
border-radius: 5px;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Catppuccin-Mocha.css b/config/waybar/style/Catppuccin-Mocha.css
index b62ca830..e1bd0eee 100644
--- a/config/waybar/style/Catppuccin-Mocha.css
+++ b/config/waybar/style/Catppuccin-Mocha.css
@@ -133,6 +133,7 @@ window#waybar.empty #window {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -308,4 +309,28 @@ window#waybar.empty #window {
#pulseaudio-slider highlight {
min-height: 10px;
border-radius: 5px;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Colored-Chroma-Glow.css b/config/waybar/style/Colored-Chroma-Glow.css
index cce79973..4a1c8e4f 100644
--- a/config/waybar/style/Colored-Chroma-Glow.css
+++ b/config/waybar/style/Colored-Chroma-Glow.css
@@ -137,6 +137,7 @@ tooltip label{
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -345,3 +346,27 @@ label:focus {
min-height: 10px;
border-radius: 5px;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Colored-Translucent.css b/config/waybar/style/Colored-Translucent.css
index ecd9366b..12818f6c 100644
--- a/config/waybar/style/Colored-Translucent.css
+++ b/config/waybar/style/Colored-Translucent.css
@@ -134,6 +134,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -361,3 +362,27 @@ label:focus {
min-height: 10px;
border-radius: 5px;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Colorful-Aurora-Blossom.css b/config/waybar/style/Colorful-Aurora-Blossom.css
index a07d2b72..cb1e9269 100644
--- a/config/waybar/style/Colorful-Aurora-Blossom.css
+++ b/config/waybar/style/Colorful-Aurora-Blossom.css
@@ -127,6 +127,7 @@ tooltip label{
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -211,3 +212,27 @@ tooltip label{
min-width: 10px;
border-radius: 5px;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Colorful-Aurora.css b/config/waybar/style/Colorful-Aurora.css
index 030bd9be..d56cdd22 100644
--- a/config/waybar/style/Colorful-Aurora.css
+++ b/config/waybar/style/Colorful-Aurora.css
@@ -114,6 +114,7 @@ tooltip label{
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -216,4 +217,28 @@ tooltip label{
#pulseaudio-slider highlight {
min-height: 10px;
border-radius: 5px;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Colorful-Oglo-Chicklets.css b/config/waybar/style/Colorful-Oglo-Chicklets.css
index 5959e510..e870c3e7 100644
--- a/config/waybar/style/Colorful-Oglo-Chicklets.css
+++ b/config/waybar/style/Colorful-Oglo-Chicklets.css
@@ -102,6 +102,7 @@ button.active {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -431,3 +432,27 @@ tooltip label {
min-width: 10px;
border-radius: 5px;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Colorful-Rainbow-Spectrum.css b/config/waybar/style/Colorful-Rainbow-Spectrum.css
index 1e754e75..a23fb79a 100644
--- a/config/waybar/style/Colorful-Rainbow-Spectrum.css
+++ b/config/waybar/style/Colorful-Rainbow-Spectrum.css
@@ -121,6 +121,7 @@ tooltip label{
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -338,3 +339,27 @@ tooltip label{
min-height: 10px;
border-radius: 5px;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Colorful-stolen-style.css b/config/waybar/style/Colorful-stolen-style.css
index fbefb6e3..b3ba6149 100644
--- a/config/waybar/style/Colorful-stolen-style.css
+++ b/config/waybar/style/Colorful-stolen-style.css
@@ -63,6 +63,7 @@ window#waybar.empty #window {
#custom-github,
#custom-hint,
#custom-hyprWindowMode,
+#custom-hypr_layout,
#custom-keyboard,
#custom-light_dark,
#custom-nightlight,
@@ -358,3 +359,27 @@ window#waybar.empty #window {
padding-left: 6px;
color: #f7768e;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Crystal-Clear-Glass.css b/config/waybar/style/Crystal-Clear-Glass.css
index 817b304c..16bef8b8 100644
--- a/config/waybar/style/Crystal-Clear-Glass.css
+++ b/config/waybar/style/Crystal-Clear-Glass.css
@@ -223,6 +223,7 @@ window#waybar.empty #window {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -249,3 +250,27 @@ window#waybar.empty #window {
#custom-weather.sunnyDay {
background-color: transparent;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Dark-Golden-Eclipse.css b/config/waybar/style/Dark-Golden-Eclipse.css
index b4fb9b09..0a8e7fe4 100644
--- a/config/waybar/style/Dark-Golden-Eclipse.css
+++ b/config/waybar/style/Dark-Golden-Eclipse.css
@@ -72,6 +72,7 @@ window#waybar.hidden {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-power_vertical,
#custom-power,
@@ -214,3 +215,26 @@ window#waybar.hidden {
border-radius: 5px;
}
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Dark-Golden-Noir.css b/config/waybar/style/Dark-Golden-Noir.css
index d0e7fee9..edfd3c7f 100644
--- a/config/waybar/style/Dark-Golden-Noir.css
+++ b/config/waybar/style/Dark-Golden-Noir.css
@@ -136,6 +136,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -216,4 +217,28 @@ tooltip {
min-height: 10px;
border-radius: 5px;
background-color: #ba5663;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Dark-Half-Moon.css b/config/waybar/style/Dark-Half-Moon.css
index e83728cb..797a1c68 100644
--- a/config/waybar/style/Dark-Half-Moon.css
+++ b/config/waybar/style/Dark-Half-Moon.css
@@ -134,6 +134,7 @@ font-size: 14px;
#custom-dot_update,
#custom-swaync,
#custom-hypridle,
+#custom-hypr_layout,
#idle_inhibitor,
#clock {
color: #B8CC52;
@@ -335,4 +336,28 @@ font-size: 14px;
min-height: 10px;
border-radius: 5px;
background-color: purple;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Dark-Latte-Wallust-combined-v2.css b/config/waybar/style/Dark-Latte-Wallust-combined-v2.css
index 5d28efce..fdc29b53 100644
--- a/config/waybar/style/Dark-Latte-Wallust-combined-v2.css
+++ b/config/waybar/style/Dark-Latte-Wallust-combined-v2.css
@@ -148,6 +148,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -274,3 +275,27 @@ tooltip {
}
#swaync{
color: #ffd700;}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Dark-Latte-Wallust-combined.css b/config/waybar/style/Dark-Latte-Wallust-combined.css
index 04898191..898c3dc2 100644
--- a/config/waybar/style/Dark-Latte-Wallust-combined.css
+++ b/config/waybar/style/Dark-Latte-Wallust-combined.css
@@ -155,6 +155,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -286,3 +287,27 @@ tooltip {
}
#swaync{
color: #ffd700;}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Dark-Purpl.css b/config/waybar/style/Dark-Purpl.css
index c0674851..9fa8f628 100644
--- a/config/waybar/style/Dark-Purpl.css
+++ b/config/waybar/style/Dark-Purpl.css
@@ -140,6 +140,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -235,4 +236,28 @@ tooltip {
min-height: 10px;
border-radius: 5px;
background-color: purple;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Dark-Wallust-Obsidian-Edge.css b/config/waybar/style/Dark-Wallust-Obsidian-Edge.css
index c315e3cb..84199a7e 100644
--- a/config/waybar/style/Dark-Wallust-Obsidian-Edge.css
+++ b/config/waybar/style/Dark-Wallust-Obsidian-Edge.css
@@ -129,6 +129,7 @@ tooltip label {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -208,4 +209,28 @@ tooltip label {
#pulseaudio-slider highlight {
min-height: 10px;
border-radius: 5px;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Extra-Arrow.css b/config/waybar/style/Extra-Arrow.css
index 282318ff..506f0c73 100644
--- a/config/waybar/style/Extra-Arrow.css
+++ b/config/waybar/style/Extra-Arrow.css
@@ -98,6 +98,7 @@
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -294,3 +295,27 @@
color: @unfocused;
background: transparent;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Extra-Crimson.css b/config/waybar/style/Extra-Crimson.css
index 1a2db007..3a326a02 100644
--- a/config/waybar/style/Extra-Crimson.css
+++ b/config/waybar/style/Extra-Crimson.css
@@ -124,6 +124,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -205,5 +206,27 @@ tooltip {
border-radius: 5px;
background-color: #ba5663;
}
-
- \ No newline at end of file
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Extra-EverForest.css b/config/waybar/style/Extra-EverForest.css
index 69911ed2..e91221ba 100644
--- a/config/waybar/style/Extra-EverForest.css
+++ b/config/waybar/style/Extra-EverForest.css
@@ -221,6 +221,7 @@ window#waybar.hidden {
}
#custom-hypridle,
+#custom-hypr_layout,
#idle_inhibitor {
padding: 0px 5px;
border-radius: 5px;
@@ -332,4 +333,28 @@ window#waybar.hidden {
#custom-weather.sunnyDay {
padding-right: 5px;
padding-left: 5px;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Extra-ML4W-starter.css b/config/waybar/style/Extra-ML4W-starter.css
index 1e545ded..d9412124 100644
--- a/config/waybar/style/Extra-ML4W-starter.css
+++ b/config/waybar/style/Extra-ML4W-starter.css
@@ -176,6 +176,7 @@ window#waybar.empty #window {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -373,3 +374,26 @@ label:focus {
background-color: #f53c3c;
}
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Extra-Mauve.css b/config/waybar/style/Extra-Mauve.css
index 35403d9c..2c8ad2af 100644
--- a/config/waybar/style/Extra-Mauve.css
+++ b/config/waybar/style/Extra-Mauve.css
@@ -143,6 +143,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -225,3 +226,27 @@ tooltip {
border-radius: 5px;
background-color: purple;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Extra-Modern-Combined-Transparent.css b/config/waybar/style/Extra-Modern-Combined-Transparent.css
index 41208141..353c321c 100644
--- a/config/waybar/style/Extra-Modern-Combined-Transparent.css
+++ b/config/waybar/style/Extra-Modern-Combined-Transparent.css
@@ -3,18 +3,18 @@
/* NOTE: This style is NOT vertical layout friendly! */
-@define-color white #F2F2F2;
-@define-color black #000000;
-@define-color text #FFFFFF;
-@define-color lightgray #686868;
-@define-color darkgray #353535;
+@define-color white #F2F2F2;
+@define-color black #000000;
+@define-color text #FFFFFF;
+@define-color lightgray #686868;
+@define-color darkgray #353535;
-@define-color transparent rgba(1, 1, 1, 0.5);
-@define-color teal-trans rgba(1, 117, 84, 0.5);
-@define-color cyan rgba(53, 140, 169, 1);
+@define-color transparent rgba(1, 1, 1, 0.5);
+@define-color teal-trans rgba(1, 117, 84, 0.5);
+@define-color cyan rgba(53, 140, 169, 1);
@define-color background-module @background-alt;
-@define-color background-module2 @background;
+@define-color background-module2 @background;
@define-color border-color @color12;
@define-color button-color @color10;
@define-color button-hover @color13;
@@ -36,7 +36,7 @@
* {
font-family: "JetBrainsMono Nerd Font";
font-weight: bold;
- min-height: 0;
+ min-height: 0;
/* set font-size to 100% if font scaling is set to 1.00 using nwg-look */
/* NOTE: Waybar v14+ ignores % font-size values */
font-size: 99%;
@@ -113,10 +113,10 @@ tooltip {
.modules-center {
background-color: @background-module;
border-radius: 0px 0px 45px 45px;
- padding-top: 8px;
- padding-bottom: 8px;
- padding-left: 10px;
- padding-right: 6px;
+ padding-top: 8px;
+ padding-bottom: 8px;
+ padding-left: 10px;
+ padding-right: 6px;
}
#backlight,
@@ -156,6 +156,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -173,7 +174,7 @@ tooltip {
#custom-weather.clearNight,
#custom-weather.cloudyFoggyDay,
#custom-weather.cloudyFoggyNight,
-#custom-weather.default,
+#custom-weather.default,
#custom-weather.rainyDay,
#custom-weather.rainyNight,
#custom-weather.severe,
@@ -181,8 +182,8 @@ tooltip {
#custom-weather.snowyIcyNight,
#custom-weather.sunnyDay {
color: white;
- padding-right: 6px;
- padding-left: 6px;
+ padding-right: 6px;
+ padding-left: 6px;
}
#temperature.critical {
@@ -225,25 +226,25 @@ tooltip {
#backlight-slider slider,
#pulseaudio-slider slider {
- min-width: 0px;
- min-height: 0px;
- opacity: 0;
- background-image: none;
- border: none;
- box-shadow: none;
+ min-width: 0px;
+ min-height: 0px;
+ opacity: 0;
+ background-image: none;
+ border: none;
+ box-shadow: none;
}
#backlight-slider trough,
#pulseaudio-slider trough {
- min-width: 80px;
- min-height: 5px;
- border-radius: 5px;
+ min-width: 80px;
+ min-height: 5px;
+ border-radius: 5px;
}
#backlight-slider highlight,
#pulseaudio-slider highlight {
- min-height: 10px;
- border-radius: 5px;
+ min-height: 10px;
+ border-radius: 5px;
}
#custom-hypridle,
@@ -258,7 +259,7 @@ tooltip {
#custom-weather.clearNight,
#custom-weather.cloudyFoggyDay,
#custom-weather.cloudyFoggyNight,
-#custom-weather.default,
+#custom-weather.default,
#custom-weather.rainyDay,
#custom-weather.rainyNight,
#custom-weather.severe,
@@ -288,3 +289,27 @@ tooltip {
#custom-swaync{
color: #ffd700;}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Extra-Modern-Combined.css b/config/waybar/style/Extra-Modern-Combined.css
index 93f7f859..f50140dd 100644
--- a/config/waybar/style/Extra-Modern-Combined.css
+++ b/config/waybar/style/Extra-Modern-Combined.css
@@ -3,18 +3,18 @@
/* NOTE: This style is NOT vertical layout friendly! */
-@define-color white #F2F2F2;
-@define-color black #000000;
-@define-color text #FFFFFF;
-@define-color lightgray #686868;
-@define-color darkgray #353535;
+@define-color white #F2F2F2;
+@define-color black #000000;
+@define-color text #FFFFFF;
+@define-color lightgray #686868;
+@define-color darkgray #353535;
-@define-color transparent rgba(1, 1, 1, 0.5);
-@define-color teal-trans rgba(1, 117, 84, 0.5);
-@define-color cyan rgba(53, 140, 169, 1);
+@define-color transparent rgba(1, 1, 1, 0.5);
+@define-color teal-trans rgba(1, 117, 84, 0.5);
+@define-color cyan rgba(53, 140, 169, 1);
@define-color background-module @background-alt;
-@define-color background-module2 @background;
+@define-color background-module2 @background;
@define-color border-color @color12;
@define-color button-color @color10;
@define-color button-hover @color13;
@@ -36,7 +36,7 @@
* {
font-family: "JetBrainsMono Nerd Font";
font-weight: bold;
- min-height: 0;
+ min-height: 0;
/* set font-size to 100% if font scaling is set to 1.00 using nwg-look */
/* NOTE: Waybar v14+ ignores % font-size values */
font-size: 99%;
@@ -118,10 +118,10 @@ tooltip {
.modules-center {
background-color: @background-module;
border-radius: 0px 0px 45px 45px;
- padding-top: 8px;
- padding-bottom: 8px;
- padding-left: 10px;
- padding-right: 6px;
+ padding-top: 8px;
+ padding-bottom: 8px;
+ padding-left: 10px;
+ padding-right: 6px;
}
#backlight,
@@ -159,6 +159,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -171,8 +172,8 @@ tooltip {
#custom-tty,
#custom-updater {
color: @foreground;
- padding-right: 6px;
- padding-left: 6px;
+ padding-right: 6px;
+ padding-left: 6px;
}
#temperature.critical {
@@ -271,7 +272,7 @@ tooltip {
#custom-weather.clearNight,
#custom-weather.cloudyFoggyDay,
#custom-weather.cloudyFoggyNight,
-#custom-weather.default,
+#custom-weather.default,
#custom-weather.rainyDay,
#custom-weather.rainyNight,
#custom-weather.severe,
@@ -301,3 +302,27 @@ tooltip {
#custom-swaync{
color: #ffd700;}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Extra-Neon-Circuit.css b/config/waybar/style/Extra-Neon-Circuit.css
index b913fc04..6f45c0ad 100644
--- a/config/waybar/style/Extra-Neon-Circuit.css
+++ b/config/waybar/style/Extra-Neon-Circuit.css
@@ -119,6 +119,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -177,26 +178,17 @@ tooltip {
#clock {
color: #F38BA8;
- border-radius: 12px;
- border-top-left-radius: 0px;
- border-bottom-right-radius: 0px;
+ border-radius: 20px;
border-width: 2px;
border-style: solid;
- border-left-style: none;
- border-right-style: none;
- border-left-width: 0px;
- border-width: 2px;
border-color: #F38BA8;
margin-right: 5px;
}
#idle_inhibitor {
color: #94e2d5;
- border-radius: 12px;
- border-top-right-radius: 0px;
- border-bottom-left-radius: 0px;
+ border-radius: 20px;
border-style: solid;
- border-right-style: none;
border-width: 2px;
border-color: #F38BA8;
margin-right: 0px;
@@ -209,10 +201,7 @@ tooltip {
#temperature {
color: #cdd6f4;
border-radius: 20px;
- border-top-right-radius: 0px;
- border-bottom-right-radius: 0px;
border-style: solid;
- border-right-style: none;
border-width: 2px;
border-color: #cdd6f4;
margin-left: 5px;
@@ -232,10 +221,8 @@ tooltip {
#disk,
#memory {
color: #cdd6f4;
- border-radius: 0px;
+ border-radius: 20px;
border-style: solid;
- border-left-style: none;
- border-right-style: none;
border-width: 2px;
border-color: #cdd6f4;
margin-right: 0px;
@@ -243,12 +230,8 @@ tooltip {
#custom-menu {
color: #ff5a5a;
- border-radius: 6px;
- border-top-right-radius: 0px;
- border-bottom-left-radius: 0px;
+ border-radius: 20px;
border-style: solid;
- border-left-style: none;
- border-right-style: none;
border-width: 2px;
border-color: #cdd6f4;
padding-right: 5px;
@@ -256,12 +239,8 @@ tooltip {
}
#network {
- border-radius: 12px;
- border-top-left-radius: 0px;
- border-bottom-left-radius: 0px;
+ border-radius: 20px;
border-style: solid;
- border-left-style: none;
- border-left-width: 0px;
border-width: 2px;
border-color: #cdd6f4;
margin-right: 5px;
@@ -269,11 +248,8 @@ tooltip {
#backlight {
color: #F5E0DC;
- border-radius: 12px;
- border-top-right-radius: 0px;
- border-bottom-right-radius: 0px;
+ border-radius: 20px;
border-style: solid;
- border-right-style: none;
border-width: 2px;
border-color: #F5E0DC;
margin-left: 5px;
@@ -282,10 +258,7 @@ tooltip {
#pulseaudio {
color: #F5E0DC;
border-radius: 20px;
- border-top-left-radius: 0px;
- border-bottom-left-radius: 0px;
border-style: solid;
- border-left-style: none;
border-width: 2px;
border-color: #F5E0DC;
margin-right: 0px;
@@ -298,11 +271,7 @@ tooltip {
#keyboard-state {
color: #F5E0DC;
border-radius: 20px;
- border-top-left-radius: 0px;
- border-bottom-left-radius: 0px;
border-style: solid;
- border-left-style: none;
- border-left-width: 0px;
border-width: 2px;
border-color: #F5E0DC;
margin-right: 5px;
@@ -310,10 +279,8 @@ tooltip {
#custom-updater {
color: #F5E0DC;
- border-radius: 0px;
+ border-radius: 20px;
border-style: solid;
- border-left-style: none;
- border-right-style: none;
border-width: 2px;
border-color: #F5E0DC;
margin-right: 0px;
@@ -321,13 +288,8 @@ tooltip {
#custom-hint {
color: #F5E0DC;
- border-radius: 12px;
- border-top-left-radius: 0px;
- border-bottom-right-radius: 0px;
+ border-radius: 20px;
border-style: solid;
- border-left-style: none;
- border-right-style: none;
- border-left-width: 0px;
border-width: 2px;
border-color: #F5E0DC;
margin-right: 5px;
@@ -336,14 +298,9 @@ tooltip {
#tray {
color: #b4befe;
font-size: 16;
- border-radius: 12px;
- border-top-right-radius: 0px;
- border-bottom-left-radius: 0px;
+ border-radius: 20px;
border-width: 2px;
border-style: solid;
- border-left-style: none;
- border-right-style: none;
- border-width: 2px;
border-color: #b4befe;
margin-left: 5px;
padding-left: 8px;
@@ -356,12 +313,8 @@ tooltip {
}
#custom-swaync {
- border-radius: 12px;
- border-top-left-radius: 0px;
- border-bottom-right-radius: 0px;
+ border-radius: 20px;
border-style: solid;
- border-left-style: none;
- border-right-style: none;
border-width: 2px;
border-color: #b4befe;
margin-right: 0px;
@@ -369,11 +322,7 @@ tooltip {
#battery {
border-radius: 20px;
- border-top-left-radius: 0px;
- border-bottom-left-radius: 0px;
border-style: solid;
- border-left-style: none;
- border-left-width: 0px;
border-width: 2px;
border-color: #b4befe;
margin-right: 5px;
@@ -381,11 +330,8 @@ tooltip {
}
#custom-power {
- border-radius: 12px;
- border-top-left-radius: 0px;
- border-bottom-right-radius: 0px;
+ border-radius: 20px;
border-style: solid;
- border-left-style: none;
border-width: 2px;
border-color: #F38BA8;
padding-left: 0px;
@@ -405,13 +351,9 @@ tooltip {
#custom-weather.showyIcyDay,
#custom-weather.snowyIcyNight,
#custom-weather.sunnyDay {
- border-radius: 12px;
- border-top-left-radius: 0px;
- border-bottom-right-radius: 0px;
+ border-radius: 20px;
border-width: 2px;
border-style: solid;
- border-left-style: none;
- border-right-style: none;
border-color: #E06C75;
color: #E06C75;
margin-right: 5px;
@@ -423,8 +365,30 @@ tooltip {
border-radius: 20px;
border-width: 2px;
border-style: solid;
- border-left-style: none;
- border-right-style: none;
border-color: #f5e0dc;
margin-right: 5px;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Extra-Prismatic-Glow.css b/config/waybar/style/Extra-Prismatic-Glow.css
index e1cfb779..cc824969 100644
--- a/config/waybar/style/Extra-Prismatic-Glow.css
+++ b/config/waybar/style/Extra-Prismatic-Glow.css
@@ -178,6 +178,7 @@ window#waybar.empty {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -300,4 +301,28 @@ label:focus {
min-height: 10px;
border-radius: 5px;
background-color: purple;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Extra-Rose-Pine.css b/config/waybar/style/Extra-Rose-Pine.css
index ee842983..94b40f7b 100644
--- a/config/waybar/style/Extra-Rose-Pine.css
+++ b/config/waybar/style/Extra-Rose-Pine.css
@@ -144,6 +144,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -247,3 +248,27 @@ tooltip {
min-height: 10px;
border-radius: 5px;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Extra-Simple-Pink.css b/config/waybar/style/Extra-Simple-Pink.css
index 665b9450..9b69a8bd 100644
--- a/config/waybar/style/Extra-Simple-Pink.css
+++ b/config/waybar/style/Extra-Simple-Pink.css
@@ -136,6 +136,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -217,4 +218,28 @@ tooltip {
min-height: 10px;
border-radius: 5px;
background-color: #ba5663;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Light-Monochrome-Contrast.css b/config/waybar/style/Light-Monochrome-Contrast.css
index def9ad42..afa18d0b 100644
--- a/config/waybar/style/Light-Monochrome-Contrast.css
+++ b/config/waybar/style/Light-Monochrome-Contrast.css
@@ -126,6 +126,7 @@ tooltip label{
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -210,3 +211,27 @@ tooltip label{
min-height: 10px;
border-radius: 5px;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Light-Obsidian-Glow.css b/config/waybar/style/Light-Obsidian-Glow.css
index 19b90078..ab428569 100644
--- a/config/waybar/style/Light-Obsidian-Glow.css
+++ b/config/waybar/style/Light-Obsidian-Glow.css
@@ -115,6 +115,7 @@ tooltip label {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -212,4 +213,28 @@ tooltip label {
min-height: 10px;
border-radius: 5px;
background-color: #ba5663;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/ML4W-Glass-3d.css b/config/waybar/style/ML4W-Glass-3d.css
index 58aaf4e1..4502d528 100644
--- a/config/waybar/style/ML4W-Glass-3d.css
+++ b/config/waybar/style/ML4W-Glass-3d.css
@@ -308,6 +308,7 @@ window#waybar.empty #window {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -334,3 +335,27 @@ window#waybar.empty #window {
#custom-weather.sunnyDay {
background-color: transparent;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/ML4W-Glass.css b/config/waybar/style/ML4W-Glass.css
index be0c6698..131e58a3 100644
--- a/config/waybar/style/ML4W-Glass.css
+++ b/config/waybar/style/ML4W-Glass.css
@@ -288,6 +288,7 @@ window#waybar.empty #window {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -314,3 +315,27 @@ window#waybar.empty #window {
#custom-weather.sunnyDay {
background-color: transparent;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/ML4W/glass.css b/config/waybar/style/ML4W/glass.css
index 6986a6d1..846dd17f 100644
--- a/config/waybar/style/ML4W/glass.css
+++ b/config/waybar/style/ML4W/glass.css
@@ -50,3 +50,27 @@ SPDX-License-Identifier: GPL-3.0-or-later */
@define-color error @color9;
@define-color on_error @color7;
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Rainbow-RGB-Bordered.css b/config/waybar/style/Rainbow-RGB-Bordered.css
index a831832d..932f75b8 100644
--- a/config/waybar/style/Rainbow-RGB-Bordered.css
+++ b/config/waybar/style/Rainbow-RGB-Bordered.css
@@ -134,6 +134,7 @@ window#waybar.empty #window {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -317,4 +318,28 @@ window#waybar.empty #window {
#pulseaudio-slider highlight {
min-height: 10px;
border-radius: 5px;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Retro-Simple-Style.css b/config/waybar/style/Retro-Simple-Style.css
index 6658c593..03ae4a33 100644
--- a/config/waybar/style/Retro-Simple-Style.css
+++ b/config/waybar/style/Retro-Simple-Style.css
@@ -84,6 +84,7 @@ window#waybar {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -184,4 +185,28 @@ window#waybar {
min-height: 10px;
border-radius: 5px;
background-color: @green;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Transparent-Crystal-Clear.css b/config/waybar/style/Transparent-Crystal-Clear.css
index 0f14891e..ae4f57c0 100644
--- a/config/waybar/style/Transparent-Crystal-Clear.css
+++ b/config/waybar/style/Transparent-Crystal-Clear.css
@@ -109,6 +109,7 @@ window#waybar.empty #window {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -204,5 +205,27 @@ window#waybar.empty #window {
border-radius: 5px;
background-color: wheat;
}
-
- \ No newline at end of file
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/VERTICAL-Catpuccin-Mocha.css b/config/waybar/style/VERTICAL-Catpuccin-Mocha.css
index 9a0d48ed..f2fecff9 100644
--- a/config/waybar/style/VERTICAL-Catpuccin-Mocha.css
+++ b/config/waybar/style/VERTICAL-Catpuccin-Mocha.css
@@ -108,6 +108,7 @@ tooltip label {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -243,3 +244,27 @@ window#waybar.bottombar #pulseaudio-slider trough {
border-radius: 5px;
background-color: @blue;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Wallust-Bordered-Chroma-Fusion-Edge.css b/config/waybar/style/Wallust-Bordered-Chroma-Fusion-Edge.css
index b9d14b78..6426a420 100644
--- a/config/waybar/style/Wallust-Bordered-Chroma-Fusion-Edge.css
+++ b/config/waybar/style/Wallust-Bordered-Chroma-Fusion-Edge.css
@@ -96,6 +96,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -321,4 +322,26 @@ tooltip {
border-radius: 5px;
}
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Wallust-Bordered-Chroma-Simple.css b/config/waybar/style/Wallust-Bordered-Chroma-Simple.css
index 4e427c15..3f51751a 100644
--- a/config/waybar/style/Wallust-Bordered-Chroma-Simple.css
+++ b/config/waybar/style/Wallust-Bordered-Chroma-Simple.css
@@ -131,6 +131,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -363,3 +364,27 @@ tooltip {
color: @color15;
border: 2px solid @color13;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Wallust-Box-type.css b/config/waybar/style/Wallust-Box-type.css
index e60f05bf..b5d0424f 100644
--- a/config/waybar/style/Wallust-Box-type.css
+++ b/config/waybar/style/Wallust-Box-type.css
@@ -1,7 +1,7 @@
/* ---- 💫 https://github.com/LinuxBeginnings 💫 ---- */
/* Wallust - Box type */
-@import "../../.config/waybar/wallust/colors-waybar.css";
+@import "wallust/colors-waybar.css";
* {
font-family: "JetBrainsMono Nerd Font";
@@ -135,6 +135,7 @@ window#waybar.empty #window {
#custom-tty,
#custom-updater,
#custom-hyprpicker,
+#custom-hypr_layout,
#custom-weather,
#custom-weather2,
#custom-weather.clearNight,
@@ -177,6 +178,41 @@ window#waybar.empty #window {
padding-right: 12px;
}
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention,
+#tray image {
+ color: @color15;
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+}
+
+#tray {
+ background: @background;
+ border-radius: 10px;
+ padding-left: 6px;
+ padding-right: 6px;
+ border-bottom-width: 5px;
+ border-bottom-color: @color12;
+ border-bottom-style: solid;
+}
+
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: @color13;
+ color: @background;
+ border-radius: 8px;
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+}
+
+#tray image {
+ color: @background;
+}
+
#temperature.critical {
background-color: red;
color: black;
@@ -231,3 +267,27 @@ window#waybar.empty #window {
min-height: 10px;
border-radius: 5px;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Wallust-Chroma-Edge.css b/config/waybar/style/Wallust-Chroma-Edge.css
index a59050d1..b1d6811b 100644
--- a/config/waybar/style/Wallust-Chroma-Edge.css
+++ b/config/waybar/style/Wallust-Chroma-Edge.css
@@ -1,7 +1,7 @@
/* ---- 💫 https://github.com/LinuxBeginnings 💫 ---- */
/* Wallust Chroma Edge */
-@import "../../.config/waybar/wallust/colors-waybar.css";
+@import "wallust/colors-waybar.css";
* {
font-family: "JetBrainsMono Nerd Font";
@@ -26,7 +26,8 @@ window#waybar {
font-size: 14px;
}
-window#waybar.empty window#waybar.empty #window {
+window#waybar.empty,
+window#waybar.empty #window {
padding: 0px;
border: 0px;
background-color: transparent;
@@ -129,6 +130,7 @@ tooltip label {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -306,6 +308,15 @@ label:focus {
color: #f53c3c;
}
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention,
+#tray image {
+ color: @color15;
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+}
+
#custom-media {
background-color: #66cc99;
color: #2a5c45;
@@ -386,3 +397,27 @@ label:focus {
min-height: 10px;
border-radius: 5px;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Wallust-Chroma-Fusion.css b/config/waybar/style/Wallust-Chroma-Fusion.css
index f16acbc4..808c7e9b 100644
--- a/config/waybar/style/Wallust-Chroma-Fusion.css
+++ b/config/waybar/style/Wallust-Chroma-Fusion.css
@@ -97,6 +97,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -186,7 +187,9 @@ tooltip {
}
#custom-cava_mviz {
- color: @color2;
+ color: @color15;
+ background-color: rgba(15, 96, 95, 0.65);
+ border: 1px solid @color10;
}
#custom-lock,
@@ -218,7 +221,8 @@ tooltip {
#workspaces button {
margin: 1px 1px;
border-radius: 15px;
- border:0px;
+ border: 1px solid transparent;
+ background: transparent;
color: @color15;
padding-left: 2px;
padding-right: 2px;
@@ -229,8 +233,9 @@ tooltip {
#taskbar button.active,
#workspaces button.active {
- color: #FFFFFF;
- background: @button-color;
+ color: @color0;
+ background: @color12;
+ border: 1px solid @color15;
border-radius: 15px;
padding-left: 4px;
padding-right: 4px;
@@ -246,8 +251,9 @@ tooltip {
#taskbar button:hover,
#workspaces button:hover {
- color: #FFFFFF;
- background: @button-hover;
+ color: @color0;
+ background: @color11;
+ border: 1px solid @color15;
border-radius: 15px;
opacity:1.0;
padding-left: 2px;
@@ -323,4 +329,26 @@ tooltip {
border-radius: 5px;
}
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Wallust-Chroma-Tally-V2.css b/config/waybar/style/Wallust-Chroma-Tally-V2.css
index 1ef933dd..4fd9e6b3 100644
--- a/config/waybar/style/Wallust-Chroma-Tally-V2.css
+++ b/config/waybar/style/Wallust-Chroma-Tally-V2.css
@@ -107,6 +107,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -282,3 +283,27 @@ tooltip {
border-radius: 5px;
background-color: @color6; /* Lighter highlight */
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Wallust-Chroma-Tally.css b/config/waybar/style/Wallust-Chroma-Tally.css
index 97ad5d09..faa6c206 100644
--- a/config/waybar/style/Wallust-Chroma-Tally.css
+++ b/config/waybar/style/Wallust-Chroma-Tally.css
@@ -106,6 +106,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -282,3 +283,27 @@ tooltip {
min-height: 10px;
border-radius: 5px;
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Wallust-Colored.css b/config/waybar/style/Wallust-Colored.css
index 29049a34..f4bc3eef 100644
--- a/config/waybar/style/Wallust-Colored.css
+++ b/config/waybar/style/Wallust-Colored.css
@@ -149,6 +149,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -231,4 +232,28 @@ tooltip {
#custom-cava_mviz {
padding-right: 10px;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Wallust-ML4W-modern-mixed.css b/config/waybar/style/Wallust-ML4W-modern-mixed.css
index 1201fedc..75be2d7b 100644
--- a/config/waybar/style/Wallust-ML4W-modern-mixed.css
+++ b/config/waybar/style/Wallust-ML4W-modern-mixed.css
@@ -160,6 +160,7 @@ window#waybar.empty #window {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -402,4 +403,28 @@ background-color: @color13;
#pulseaudio-slider highlight {
min-height: 10px;
border-radius: 5px;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Wallust-ML4W-modern.css b/config/waybar/style/Wallust-ML4W-modern.css
index 84c553fe..7b765490 100644
--- a/config/waybar/style/Wallust-ML4W-modern.css
+++ b/config/waybar/style/Wallust-ML4W-modern.css
@@ -167,6 +167,7 @@ window#waybar.empty #window {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -395,4 +396,28 @@ background-color: @color13;
#pulseaudio-slider highlight {
min-height: 10px;
border-radius: 5px;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Wallust-Simple.css b/config/waybar/style/Wallust-Simple.css
index 20a000b8..052f7b79 100644
--- a/config/waybar/style/Wallust-Simple.css
+++ b/config/waybar/style/Wallust-Simple.css
@@ -126,6 +126,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -219,4 +220,28 @@ tooltip {
#pulseaudio-slider highlight {
min-height: 10px;
border-radius: 5px;
-} \ No newline at end of file
+}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/Wallust-Transparent-Crystal-Clear.css b/config/waybar/style/Wallust-Transparent-Crystal-Clear.css
index e6db9b1c..a6541a59 100644
--- a/config/waybar/style/Wallust-Transparent-Crystal-Clear.css
+++ b/config/waybar/style/Wallust-Transparent-Crystal-Clear.css
@@ -144,6 +144,7 @@ tooltip {
#custom-lock,
#custom-hint,
#custom-hypridle,
+#custom-hypr_layout,
#custom-menu,
#custom-playerctl,
#custom-power_vertical,
@@ -224,5 +225,27 @@ tooltip {
border-radius: 5px;
background-color: wheat;
}
-
- \ No newline at end of file
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/catppuccin-themes/frappe.css b/config/waybar/style/catppuccin-themes/frappe.css
index c06b8fb7..c8f50ccd 100644
--- a/config/waybar/style/catppuccin-themes/frappe.css
+++ b/config/waybar/style/catppuccin-themes/frappe.css
@@ -24,3 +24,27 @@
@define-color base #303446;
@define-color mantle #292c3c;
@define-color crust #232634;
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/catppuccin-themes/latte.css b/config/waybar/style/catppuccin-themes/latte.css
index 085cc3e0..f045e580 100644
--- a/config/waybar/style/catppuccin-themes/latte.css
+++ b/config/waybar/style/catppuccin-themes/latte.css
@@ -35,3 +35,27 @@
@define-color pink #ea76cb;
@define-color flamingo #dd7878;
@define-color rosewater #dc8a78;
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/catppuccin-themes/mocha.css b/config/waybar/style/catppuccin-themes/mocha.css
index 7f4e3374..afca3216 100644
--- a/config/waybar/style/catppuccin-themes/mocha.css
+++ b/config/waybar/style/catppuccin-themes/mocha.css
@@ -36,3 +36,26 @@
@define-color flamingo #f2cdcd;
@define-color rosewater #f5e0dc;
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/waybar/style/catppuccin-themes/rgbmocha.css b/config/waybar/style/catppuccin-themes/rgbmocha.css
index 14b07c49..30498eba 100644
--- a/config/waybar/style/catppuccin-themes/rgbmocha.css
+++ b/config/waybar/style/catppuccin-themes/rgbmocha.css
@@ -47,3 +47,27 @@
border-image: linear-gradient(90deg, red, orange, yellow, green, blue, indigo, violet) 1;
}
}
+
+/* --- tray readability override (global) --- */
+#tray > *,
+#tray > .passive,
+#tray > .active,
+#tray > .needs-attention {
+ background: rgba(137, 180, 250, 0.55);
+ border-radius: 8px;
+ border: 1px solid rgba(17, 17, 27, 0.35);
+ margin-left: 1px;
+ margin-right: 1px;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-effect: none;
+}
+
+#tray image {
+ background: transparent;
+ color: rgba(17, 17, 27, 0.98);
+ -gtk-icon-style: symbolic;
+ -gtk-icon-effect: none;
+ opacity: 1;
+}
diff --git a/config/wezterm/wezterm.lua b/config/wezterm/wezterm.lua
index 8740cbcf..9241c773 100644
--- a/config/wezterm/wezterm.lua
+++ b/config/wezterm/wezterm.lua
@@ -1,3 +1,10 @@
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+
-- Config from Drew @justaguylinux small mods
local wezterm = require("wezterm")
diff --git a/config/wlogout/layout b/config/wlogout/layout
index bcebbf44..701ef189 100644
--- a/config/wlogout/layout
+++ b/config/wlogout/layout
@@ -18,7 +18,7 @@
}
{
"label" : "logout",
- "action" : "hyprctl dispatch exit 0",
+ "action" : "$HOME/.config/hypr/scripts/Logout.sh",
"text" : "Logout",
"keybind" : "e"
}
diff --git a/config/yazi/flavors/catppuccin-macchiato.yazi/flavor.toml b/config/yazi/flavors/catppuccin-macchiato.yazi/flavor.toml
new file mode 100644
index 00000000..d8a7501e
--- /dev/null
+++ b/config/yazi/flavors/catppuccin-macchiato.yazi/flavor.toml
@@ -0,0 +1,1204 @@
+[manager]
+cwd = { fg = "#8bd5ca" }
+
+# Hovered
+hovered = { fg = "#24273a", bg = "#8aadf4" }
+preview_hovered = { underline = true }
+
+# Find
+find_keyword = { fg = "#eed49f", italic = true }
+find_position = { fg = "#f5bde6", bg = "reset", italic = true }
+
+# Marker
+marker_copied = { fg = "#a6da95", bg = "#a6da95" }
+marker_cut = { fg = "#ed8796", bg = "#ed8796" }
+marker_selected = { fg = "#8aadf4", bg = "#8aadf4" }
+
+# Tab
+tab_active = { fg = "#24273a", bg = "#cad3f5" }
+tab_inactive = { fg = "#cad3f5", bg = "#494d64" }
+tab_width = 1
+
+# Count
+count_copied = { fg = "#24273a", bg = "#a6da95" }
+count_cut = { fg = "#24273a", bg = "#ed8796" }
+count_selected = { fg = "#24273a", bg = "#8aadf4" }
+
+# Border
+border_symbol = "│"
+border_style = { fg = "#8087a2" }
+
+# Highlighting
+syntect_theme = "~/.config/bat/themes/Catppuccin-macchiato.tmTheme"
+
+[status]
+separator_open = ""
+separator_close = ""
+separator_style = { fg = "#494d64", bg = "#494d64" }
+
+# Mode
+mode_normal = { fg = "#24273a", bg = "#8aadf4" }
+mode_select = { fg = "#24273a", bg = "#a6da95" }
+mode_unset = { fg = "#24273a", bg = "#f0c6c6" }
+
+# Progress
+progress_label = { fg = "#cad3f5" }
+progress_normal = { fg = "#8aadf4", bg = "#494d64" }
+progress_error = { fg = "#ed8796", bg = "#494d64" }
+
+# Permissions
+permissions_t = { fg = "#8aadf4" }
+permissions_r = { fg = "#eed49f" }
+permissions_w = { fg = "#ed8796" }
+permissions_x = { fg = "#a6da95" }
+permissions_s = { fg = "#8087a2" }
+
+[input]
+border = { fg = "#8aadf4" }
+title = {}
+value = {}
+selected = { reversed = true }
+
+[select]
+border = { fg = "#8aadf4" }
+active = { fg = "#f5bde6" }
+inactive = {}
+
+[tasks]
+border = { fg = "#8aadf4" }
+title = {}
+hovered = { underline = true }
+
+[which]
+mask = { bg = "#363a4f" }
+cand = { fg = "#8bd5ca" }
+rest = { fg = "#939ab7" }
+desc = { fg = "#f5bde6" }
+separator = "  "
+separator_style = { fg = "#5b6078" }
+
+[help]
+on = { fg = "#f5bde6" }
+exec = { fg = "#8bd5ca" }
+desc = { fg = "#939ab7" }
+hovered = { bg = "#5b6078" }
+footer = { fg = "#494d64", bg = "#cad3f5" }
+
+[filetype]
+
+rules = [
+ { name = "*", is = "block", fg = "#cad3f5" },
+ { name = "*", is = "char", fg = "#a6da95" },
+ { name = "*/", fg = "#8aadf4" },
+ { name = "*", is = "exec", fg = "#ed8796", bold = true },
+ { name = "*", is = "fifo", fg = "#181926", bg = "#8aadf4" },
+ { name = "*", is = "orphan", fg = "#181926", bg = "#ed8796" },
+ { name = "*", is = "sock", fg = "#181926", bg = "#f5bde6" },
+ { name = "*", is = "link", fg = "#f5bde6" },
+ { name = "*", is = "sticky", fg = "#cad3f5" },
+ { name = "*.txt", fg = "#eed49f" },
+ { name = "*README", fg = "#eed49f" },
+ { name = "*README.rst", fg = "#eed49f" },
+ { name = "*README.md", fg = "#eed49f" },
+ { name = "*README.txt", fg = "#eed49f" },
+ { name = "*LICENSE", fg = "#939ab7" },
+ { name = "*LICENSE-MIT", fg = "#939ab7" },
+ { name = "*LICENSE-APACHE", fg = "#939ab7" },
+ { name = "*LICENSE.md", fg = "#939ab7" },
+ { name = "*LICENSE.txt", fg = "#939ab7" },
+ { name = "*COPYING", fg = "#939ab7" },
+ { name = "*COPYRIGHT", fg = "#939ab7" },
+ { name = "*INSTALL", fg = "#eed49f" },
+ { name = "*INSTALL.md", fg = "#eed49f" },
+ { name = "*INSTALL.txt", fg = "#eed49f" },
+ { name = "*AUTHORS", fg = "#eed49f" },
+ { name = "*HISTORY", fg = "#eed49f" },
+ { name = "*CODE_OF_CONDUCT", fg = "#eed49f" },
+ { name = "*CODE_OF_CONDUCT.md", fg = "#eed49f" },
+ { name = "*CODE_OF_CONDUCT.txt", fg = "#eed49f" },
+ { name = "*CONTRIBUTING", fg = "#eed49f" },
+ { name = "*CONTRIBUTING.md", fg = "#eed49f" },
+ { name = "*CONTRIBUTING.txt", fg = "#eed49f" },
+ { name = "*CONTRIBUTORS", fg = "#eed49f" },
+ { name = "*CONTRIBUTORS.md", fg = "#eed49f" },
+ { name = "*CONTRIBUTORS.txt", fg = "#eed49f" },
+ { name = "*CHANGELOG", fg = "#eed49f" },
+ { name = "*CHANGELOG.md", fg = "#eed49f" },
+ { name = "*CHANGELOG.txt", fg = "#eed49f" },
+ { name = "*CODEOWNERS", fg = "#8bd5ca" },
+ { name = "*PATENTS", fg = "#eed49f" },
+ { name = "*VERSION", fg = "#eed49f" },
+ { name = "*NOTICE", fg = "#eed49f" },
+ { name = "*CHANGES", fg = "#eed49f" },
+ { name = "*LEGACY", fg = "#eed49f" },
+ { name = "*TODO", fg = "#eed49f" },
+ { name = "*TODO.md", fg = "#eed49f" },
+ { name = "*TODO.txt", fg = "#eed49f" },
+ { name = "*.log", fg = "#5b6078" },
+ { name = "*.asciidoc", fg = "#eed49f" },
+ { name = "*.etx", fg = "#eed49f" },
+ { name = "*.info", fg = "#eed49f" },
+ { name = "*.markdown", fg = "#eed49f" },
+ { name = "*.md", fg = "#eed49f" },
+ { name = "*.mkd", fg = "#eed49f" },
+ { name = "*.mdx", fg = "#eed49f" },
+ { name = "*.org", fg = "#eed49f" },
+ { name = "*.norg", fg = "#eed49f" },
+ { name = "*.tex", fg = "#a6da95" },
+ { name = "*.textile", fg = "#a6da95" },
+ { name = "*.bib", fg = "#eed49f" },
+ { name = "*.bst", fg = "#eed49f" },
+ { name = "*.json", fg = "#eed49f" },
+ { name = "*.jsonc", fg = "#eed49f" },
+ { name = "*.json5", fg = "#eed49f" },
+ { name = "*.hjson", fg = "#eed49f" },
+ { name = "*.jsonl", fg = "#eed49f" },
+ { name = "*.jsonnet", fg = "#eed49f" },
+ { name = "*.ndjson", fg = "#eed49f" },
+ { name = "*.rss", fg = "#ed8796" },
+ { name = "*.xml", fg = "#eed49f" },
+ { name = "*.fxml", fg = "#eed49f" },
+ { name = "*.toml", fg = "#eed49f" },
+ { name = "*.ps1", fg = "#eed49f" },
+ { name = "*.tml", fg = "#eed49f" },
+ { name = "*.yaml", fg = "#eed49f" },
+ { name = "*.yml", fg = "#eed49f" },
+ { name = "*.ml", fg = "#a6da95" },
+ { name = "*.mli", fg = "#a6da95" },
+ { name = "*.xmp", fg = "#eed49f" },
+ { name = "*.ltx", fg = "#a6da95" },
+ { name = "*.db", fg = "#a6da95" },
+ { name = "*.pdf", fg = "#ed8796" },
+ { name = "*.PDF", fg = "#ed8796" },
+ { name = "*.epub", fg = "#ed8796" },
+ { name = "*.docm", fg = "#87afff", underline = true },
+ { name = "*.doc", fg = "#ed8796" },
+ { name = "*.docx", fg = "#ed8796" },
+ { name = "*.odb", fg = "#87afff" },
+ { name = "*.odt", fg = "#ed8796" },
+ { name = "*.rtf", fg = "#ed8796" },
+ { name = "*.pages", fg = "#87afff" },
+ { name = "*.odp", fg = "#ed8796" },
+ { name = "*.pps", fg = "#ed8796" },
+ { name = "*.ppt", fg = "#ed8796" },
+ { name = "*.pptx", fg = "#ed8796" },
+ { name = "*.ppts", fg = "#ed8796" },
+ { name = "*.pptxm", fg = "#ed8796", underline = true },
+ { name = "*.pptsm", fg = "#ed8796", underline = true },
+ { name = "*.prisma", fg = "#ed8796" },
+ { name = "*.csv", fg = "#eed49f" },
+ { name = "*.tsv", fg = "#eed49f" },
+ { name = "*.ods", fg = "#ed8796" },
+ { name = "*.xlr", fg = "#ed8796" },
+ { name = "*.o", fg = "#5b6078" },
+ { name = "*.la", fg = "#5b6078" },
+ { name = "*.lo", fg = "#5b6078" },
+ { name = "*CMakeCache", fg = "#5b6078" },
+ { name = "*MakeFile.in", fg = "#5b6078" },
+ { name = "*.cache", fg = "#5b6078" },
+ { name = "*.class", fg = "#5b6078" },
+ { name = "*.scons_opt", fg = "#5b6078" },
+ { name = "*.scons_dblite", fg = "#5b6078" },
+ { name = "*.xls", fg = "#ed8796" },
+ { name = "*.xlsx", fg = "#ed8796" },
+ { name = "*.xlsxm", fg = "#ed8796", underline = true },
+ { name = "*.xltm", fg = "#ed8796", underline = true },
+ { name = "*.xltx", fg = "#ed8796" },
+ { name = "*.key", fg = "#eed49f" },
+ { name = "*.config", fg = "#eed49f" },
+ { name = "*.cfg", fg = "#eed49f" },
+ { name = "*.conf", fg = "#eed49f" },
+ { name = "*authorized_keys", fg = "#eed49f" },
+ { name = "*known_hosts", fg = "#eed49f" },
+ { name = "*.ini", fg = "#eed49f" },
+ { name = "*.ui", fg = "#eed49f" },
+ { name = "*.webmanifest", fg = "#eed49f" },
+ { name = "*.profile", fg = "#a6da95" },
+ { name = "*.bash_profile", fg = "#a6da95" },
+ { name = "*.bash_logout", fg = "#eed49f" },
+ { name = "*.bashrc", fg = "#a6da95" },
+ { name = "*.zshenv", fg = "#a6da95" },
+ { name = "*.zprofile", fg = "#a6da95" },
+ { name = "*.viminfo", fg = "#eed49f" },
+ { name = "*.icon", fg = "#f0c6c6" },
+ { name = "*.epf", fg = "#ed8796" },
+ { name = "*.git", fg = "#5b6078" },
+ { name = "*.github", fg = "#5b6078" },
+ { name = "*.gitignore", fg = "#8bd5ca" },
+ { name = "*.ignore", fg = "#8bd5ca" },
+ { name = "*.cmake", fg = "#8bd5ca" },
+ { name = "*.CMakeLists.txt", fg = "#8bd5ca" },
+ { name = "*.cmake.in", fg = "#8bd5ca" },
+ { name = "*.fdignore", fg = "#8bd5ca" },
+ { name = "*.rgignore", fg = "#8bd5ca" },
+ { name = "*.tfignore", fg = "#8bd5ca" },
+ { name = "*.gitattributes", fg = "#8bd5ca" },
+ { name = "*.gitmodules", fg = "#8bd5ca" },
+ { name = "*.gitconfig", fg = "#8bd5ca" },
+ { name = "*.mailmap", fg = "#8bd5ca" },
+ { name = "*.awk", fg = "#a6da95" },
+ { name = "*.bash", fg = "#a6da95" },
+ { name = "*.bat", fg = "#ed8796", bold = true },
+ { name = "*.com", fg = "#ed8796", bold = true },
+ { name = "*.exe", fg = "#ed8796", bold = true },
+ { name = "*.sh", fg = "#a6da95" },
+ { name = "*.zsh", fg = "#a6da95" },
+ { name = "*.fish", fg = "#a6da95" },
+ { name = "*.vim", fg = "#a6da95" },
+ { name = "*.py", fg = "#a6da95" },
+ { name = "*.ipynb", fg = "#a6da95" },
+ { name = "*.rb", fg = "#a6da95" },
+ { name = "*.gemspec", fg = "#8bd5ca" },
+ { name = "*v.mod", fg = "#8bd5ca" },
+ { name = "*.flake8", fg = "#8bd5ca" },
+ { name = "*.clang-format", fg = "#8bd5ca" },
+ { name = "*.msql", fg = "#a6da95" },
+ { name = "*.mysql", fg = "#a6da95" },
+ { name = "*.prql", fg = "#a6da95" },
+ { name = "*.pgsql", fg = "#a6da95" },
+ { name = "*.sql", fg = "#a6da95" },
+ { name = "*.sqlite3", fg = "#a6da95" },
+ { name = "*.sqlite", fg = "#a6da95" },
+ { name = "*.r", fg = "#a6da95" },
+ { name = "*.R", fg = "#a6da95" },
+ { name = "*.clj", fg = "#a6da95" },
+ { name = "*.cljs", fg = "#a6da95" },
+ { name = "*.cljc", fg = "#a6da95" },
+ { name = "*.cljw", fg = "#a6da95" },
+ { name = "*.scala", fg = "#a6da95" },
+ { name = "*.dart", fg = "#a6da95" },
+ { name = "*.asm", fg = "#a6da95" },
+ { name = "*.lisp", fg = "#a6da95" },
+ { name = "*.matlab", fg = "#a6da95" },
+ { name = "*.kt", fg = "#a6da95" },
+ { name = "*.kts", fg = "#a6da95" },
+ { name = "*.mojo", fg = "#a6da95" },
+ { name = "*.elc", fg = "#a6da95" },
+ { name = "*.elm", fg = "#a6da95" },
+ { name = "*.lua", fg = "#a6da95" },
+ { name = "*.c", fg = "#a6da95" },
+ { name = "*.C", fg = "#a6da95" },
+ { name = "*.h", fg = "#a6da95" },
+ { name = "*.H", fg = "#a6da95" },
+ { name = "*.c++", fg = "#a6da95" },
+ { name = "*.h++", fg = "#a6da95" },
+ { name = "*.hpp", fg = "#a6da95" },
+ { name = "*.hxx", fg = "#a6da95" },
+ { name = "*.M", fg = "#a6da95" },
+ { name = "*.m", fg = "#a6da95" },
+ { name = "*.cc", fg = "#a6da95" },
+ { name = "*.cs", fg = "#a6da95" },
+ { name = "*.csx", fg = "#a6da95" },
+ { name = "*.cp", fg = "#a6da95" },
+ { name = "*.cpp", fg = "#a6da95" },
+ { name = "*.cxx", fg = "#a6da95" },
+ { name = "*.cr", fg = "#a6da95" },
+ { name = "*.go", fg = "#a6da95" },
+ { name = "*.f", fg = "#a6da95" },
+ { name = "*.F", fg = "#a6da95" },
+ { name = "*.for", fg = "#a6da95" },
+ { name = "*.ftn", fg = "#a6da95" },
+ { name = "*.nim", fg = "#a6da95" },
+ { name = "*.nimble", fg = "#a6da95" },
+ { name = "*.s", fg = "#a6da95" },
+ { name = "*.S", fg = "#a6da95" },
+ { name = "*.rs", fg = "#a6da95" },
+ { name = "*.scpt", fg = "#a6da95" },
+ { name = "*.swift", fg = "#a6da95" },
+ { name = "*.vala", fg = "#a6da95" },
+ { name = "*.hs", fg = "#a6da95" },
+ { name = "*.lhs", fg = "#a6da95" },
+ { name = "*.agda", fg = "#a6da95" },
+ { name = "*.lagda", fg = "#a6da95" },
+ { name = "*.lagda.tex", fg = "#a6da95" },
+ { name = "*.lagda.rst", fg = "#a6da95" },
+ { name = "*.lagda.md", fg = "#a6da95" },
+ { name = "*.zig", fg = "#a6da95" },
+ { name = "*.v", fg = "#a6da95" },
+ { name = "*.pyc", fg = "#5b6078" },
+ { name = "*.pyd", fg = "#5b6078" },
+ { name = "*.pyo", fg = "#5b6078" },
+ { name = "*.fs", fg = "#a6da95" },
+ { name = "*.fsi", fg = "#a6da95" },
+ { name = "*.fsx", fg = "#a6da95" },
+ { name = "*.http", fg = "#a6da95" },
+ { name = "*.css", fg = "#a6da95" },
+ { name = "*.less", fg = "#a6da95" },
+ { name = "*.sass", fg = "#a6da95" },
+ { name = "*.scss", fg = "#a6da95" },
+ { name = "*.htm", fg = "#eed49f" },
+ { name = "*.html", fg = "#eed49f" },
+ { name = "*.xhtml", fg = "#eed49f" },
+ { name = "*.shtml", fg = "#eed49f" },
+ { name = "*.jhtm", fg = "#eed49f" },
+ { name = "*.mht", fg = "#eed49f" },
+ { name = "*.svelte", fg = "#a6da95" },
+ { name = "*.vue", fg = "#a6da95" },
+ { name = "*.astro", fg = "#a6da95" },
+ { name = "*.js", fg = "#a6da95" },
+ { name = "*.jsx", fg = "#a6da95" },
+ { name = "*.ts", fg = "#a6da95" },
+ { name = "*.tsx", fg = "#a6da95" },
+ { name = "*.mjs", fg = "#a6da95" },
+ { name = "*.cjs", fg = "#a6da95" },
+ { name = "*.coffee", fg = "#a6da95" },
+ { name = "*.java", fg = "#a6da95" },
+ { name = "*.jl", fg = "#a6da95" },
+ { name = "*.php", fg = "#a6da95" },
+ { name = "*.twig", fg = "#a6da95" },
+ { name = "*.vb", fg = "#a6da95" },
+ { name = "*Containerfile", fg = "#8bd5ca" },
+ { name = "*.containerignore", fg = "#8bd5ca" },
+ { name = "*Dockerfile", fg = "#eed49f" },
+ { name = "*.dockerignore", fg = "#8bd5ca" },
+ { name = "*Makefile", fg = "#8bd5ca" },
+ { name = "*Makefile.am", fg = "#8bd5ca" },
+ { name = "*configure", fg = "#8bd5ca" },
+ { name = "*configure.ac", fg = "#8bd5ca" },
+ { name = "*requirements.txt", fg = "#8bd5ca" },
+ { name = "*.make", fg = "#8bd5ca" },
+ { name = "*.mk", fg = "#8bd5ca" },
+ { name = "*.nix", fg = "#eed49f" },
+ { name = "*appveyor.yml", fg = "#8bd5ca" },
+ { name = "*azure-pipelines.yml", fg = "#8bd5ca" },
+ { name = "*.cirrus.yml", fg = "#8bd5ca" },
+ { name = "*.gitlab-ci.yml", fg = "#8bd5ca" },
+ { name = "*.travis.yml", fg = "#8bd5ca" },
+ { name = "*.old", fg = "#5b6078" },
+ { name = "*.out", fg = "#5b6078" },
+ { name = "*.SKIP", fg = "#5b6078" },
+ { name = "*.diff", fg = "#a6da95" },
+ { name = "*.patch", fg = "#a6da95" },
+ { name = "*.bmp", fg = "#f0c6c6" },
+ { name = "*.exr", fg = "#f0c6c6" },
+ { name = "*.gif", fg = "#f0c6c6" },
+ { name = "*.3fr", fg = "#f0c6c6" },
+ { name = "*.bay", fg = "#f0c6c6" },
+ { name = "*.cdr", fg = "#f0c6c6" },
+ { name = "*.dicom", fg = "#f0c6c6" },
+ { name = "*.fliff", fg = "#f0c6c6" },
+ { name = "*.tif", fg = "#f0c6c6" },
+ { name = "*.tiff", fg = "#f0c6c6" },
+ { name = "*.ppm", fg = "#f0c6c6" },
+ { name = "*.qoi", fg = "#f0c6c6" },
+ { name = "*.tga", fg = "#f0c6c6" },
+ { name = "*.heif", fg = "#f0c6c6" },
+ { name = "*.ico", fg = "#f0c6c6" },
+ { name = "*.icns", fg = "#f0c6c6" },
+ { name = "*.jpeg", fg = "#f0c6c6" },
+ { name = "*.jpg", fg = "#f0c6c6" },
+ { name = "*.jxl", fg = "#f0c6c6" },
+ { name = "*.nth", fg = "#f0c6c6" },
+ { name = "*.png", fg = "#f0c6c6" },
+ { name = "*.mos", fg = "#f0c6c6" },
+ { name = "*.raw", fg = "#f0c6c6" },
+ { name = "*.psd", fg = "#f0c6c6" },
+ { name = "*.xvf", fg = "#f0c6c6" },
+ { name = "*.avif", fg = "#f0c6c6" },
+ { name = "*.pxm", fg = "#f0c6c6" },
+ { name = "*.xpm", fg = "#f0c6c6" },
+ { name = "*.ai", fg = "#f0c6c6" },
+ { name = "*.pxd", fg = "#f0c6c6" },
+ { name = "*.webp", fg = "#f0c6c6" },
+ { name = "*.webm", fg = "#f0c6c6" },
+ { name = "*.kra", fg = "#f0c6c6" },
+ { name = "*.svg", fg = "#f0c6c6" },
+ { name = "*.ps", fg = "#ed8796" },
+ { name = "*.avi", fg = "#f0c6c6" },
+ { name = "*.m2v", fg = "#f0c6c6" },
+ { name = "*.m4v", fg = "#f0c6c6" },
+ { name = "*.mkv", fg = "#f0c6c6" },
+ { name = "*.MOV", fg = "#f0c6c6" },
+ { name = "*.mov", fg = "#f0c6c6" },
+ { name = "*.mp4", fg = "#f0c6c6" },
+ { name = "*.obj", fg = "#f0c6c6" },
+ { name = "*.usd", fg = "#f0c6c6" },
+ { name = "*.step", fg = "#f0c6c6" },
+ { name = "*.blend", fg = "#f0c6c6" },
+ { name = "*.amf", fg = "#f0c6c6" },
+ { name = "*.mpeg", fg = "#f0c6c6" },
+ { name = "*.mpg", fg = "#f0c6c6" },
+ { name = "*.sample", fg = "#f0c6c6" },
+ { name = "*.wmv", fg = "#f0c6c6" },
+ { name = "*.webm", fg = "#f0c6c6" },
+ { name = "*.flv", fg = "#f0c6c6" },
+ { name = "*.h264", fg = "#f0c6c6" },
+ { name = "*.ogv", fg = "#f0c6c6" },
+ { name = "*.f4v", fg = "#f0c6c6" },
+ { name = "*.VOB", fg = "#f0c6c6" },
+ { name = "*.vob", fg = "#f0c6c6" },
+ { name = "*.m4a", fg = "#f0c6c6" },
+ { name = "*.mp3", fg = "#f0c6c6" },
+ { name = "*.mp4a", fg = "#f0c6c6" },
+ { name = "*.ogg", fg = "#f0c6c6" },
+ { name = "*.opus", fg = "#f0c6c6" },
+ { name = "*.wma", fg = "#f0c6c6" },
+ { name = "*.ape", fg = "#f0c6c6" },
+ { name = "*.aif", fg = "#f0c6c6" },
+ { name = "*.flac", fg = "#f0c6c6" },
+ { name = "*.mid", fg = "#f0c6c6" },
+ { name = "*.midi", fg = "#f0c6c6" },
+ { name = "*.wav", fg = "#f0c6c6" },
+ { name = "*.wv", fg = "#f0c6c6" },
+ { name = "*.wmv", fg = "#f0c6c6" },
+ { name = "*.afm", fg = "#f0c6c6" },
+ { name = "*.fon", fg = "#f0c6c6" },
+ { name = "*.fnt", fg = "#f0c6c6" },
+ { name = "*.pfb", fg = "#f0c6c6" },
+ { name = "*.pfm", fg = "#f0c6c6" },
+ { name = "*.ttf", fg = "#f0c6c6" },
+ { name = "*.otf", fg = "#f0c6c6" },
+ { name = "*.woff", fg = "#f0c6c6" },
+ { name = "*.woff2", fg = "#f0c6c6" },
+ { name = "*.PFA", fg = "#f0c6c6" },
+ { name = "*.pfa", fg = "#f0c6c6" },
+ { name = "*.7z", fg = "#7dc4e4" },
+ { name = "*.arj", fg = "#7dc4e4" },
+ { name = "*.a", fg = "#7dc4e4" },
+ { name = "*.bz", fg = "#7dc4e4" },
+ { name = "*.bz2", fg = "#7dc4e4" },
+ { name = "*.gz", fg = "#7dc4e4" },
+ { name = "*.pkg", fg = "#7dc4e4" },
+ { name = "*.rar", fg = "#7dc4e4" },
+ { name = "*.tar", fg = "#7dc4e4" },
+ { name = "*.tbz", fg = "#7dc4e4" },
+ { name = "*.tbz2", fg = "#7dc4e4" },
+ { name = "*.tgz", fg = "#7dc4e4" },
+ { name = "*.xz", fg = "#7dc4e4" },
+ { name = "*.z", fg = "#7dc4e4" },
+ { name = "*.zz", fg = "#7dc4e4" },
+ { name = "*.zip", fg = "#7dc4e4" },
+ { name = "*.zipx", fg = "#7dc4e4" },
+ { name = "*.zst", fg = "#7dc4e4" },
+ { name = "*.zstd", fg = "#7dc4e4" },
+ { name = "*.cpio", fg = "#7dc4e4" },
+ { name = "*.lrz", fg = "#7dc4e4" },
+ { name = "*.lz", fg = "#7dc4e4" },
+ { name = "*.lzma", fg = "#7dc4e4" },
+ { name = "*.lzo", fg = "#7dc4e4" },
+ { name = "*.apk", fg = "#7dc4e4" },
+ { name = "*.ipa", fg = "#7dc4e4" },
+ { name = "*.deb", fg = "#7dc4e4" },
+ { name = "*.rpm", fg = "#7dc4e4" },
+ { name = "*.jar", fg = "#7dc4e4" },
+ { name = "*.xbps", fg = "#7dc4e4" },
+ { name = "*.jad", fg = "#7dc4e4" },
+ { name = "*.bag", fg = "#7dc4e4" },
+ { name = "*.dmg", fg = "#7dc4e4" },
+ { name = "*.iso", fg = "#7dc4e4" },
+ { name = "*.toast", fg = "#7dc4e4" },
+ { name = "*.bin", fg = "#7dc4e4" },
+ { name = "*.pak", fg = "#7dc4e4" },
+ { name = "*.pk3", fg = "#7dc4e4" },
+ { name = "*.xpi", fg = "#7dc4e4" },
+ { name = "*.img", fg = "#7dc4e4" },
+ { name = "*.qcow", fg = "#7dc4e4" },
+ { name = "*.fvd", fg = "#7dc4e4" },
+ { name = "*.sparseimage", fg = "#7dc4e4" },
+ { name = "*.vcd", fg = "#7dc4e4" },
+ { name = "*.vdi", fg = "#7dc4e4" },
+ { name = "*.vhd", fg = "#7dc4e4" },
+ { name = "*.vhdx", fg = "#7dc4e4" },
+ { name = "*.vfd", fg = "#7dc4e4" },
+ { name = "*.vmdk", fg = "#7dc4e4" },
+ { name = "*.tmp", fg = "#5b6078" },
+ { name = "*.timestamp", fg = "#5b6078" },
+ { name = "*~", fg = "#5b6078" },
+ { name = "*.bak", fg = "#5b6078" },
+ { name = "*.rlib", fg = "#5b6078" },
+ { name = "*.rmeta", fg = "#5b6078" },
+ { name = "*.dll", fg = "#ed8796" },
+ { name = "*.pid", fg = "#5b6078" },
+ { name = "*.state", fg = "#5b6078" },
+ { name = "*lockfile", fg = "#5b6078" },
+ { name = "*lock", fg = "#5b6078" },
+ { name = "*.err", fg = "#ed8796" },
+ { name = "*.error", fg = "#ed8796" },
+ { name = "*.stderr", fg = "#5b6078" },
+ { name = "*.service", fg = "#eed49f" },
+ { name = "*@.service", fg = "#eed49f" },
+ { name = "*.socket", fg = "#eed49f" },
+ { name = "*.swap", fg = "#7dc4e4" },
+ { name = "*.device", fg = "#7dc4e4" },
+ { name = "*.mount", fg = "#7dc4e4" },
+ { name = "*.automount", fg = "#7dc4e4" },
+ { name = "*.target", fg = "#7dc4e4" },
+ { name = "*.path", fg = "#7dc4e4" },
+ { name = "*.timer", fg = "#7dc4e4" },
+ { name = "*.snapshot", fg = "#7dc4e4" },
+ { name = "*.lnk", fg = "#7dc4e4" },
+ { name = "*.applescript", fg = "#a6da95" },
+ { name = "*.m3u", fg = "#f0c6c6" },
+ { name = "*.m3u8", fg = "#f0c6c6" },
+ { name = "*.md5", fg = "#f0c6c6" },
+ { name = "*.properties", fg = "#eed49f" },
+ { name = "*.theme", fg = "#eed49f" },
+ { name = "*.torrent", fg = "#7dc4e4" },
+ { name = "*.asc", fg = "#a6da95" },
+ { name = "*.gpg", fg = "#a6da95" },
+ { name = "*.signature", fg = "#a6da95" },
+ { name = "*.sig", fg = "#a6da95" },
+ { name = "*.p12", fg = "#a6da95" },
+ { name = "*.pem", fg = "#a6da95" },
+ { name = "*.pgp", fg = "#a6da95" },
+ { name = "*.p7s", fg = "#a6da95" },
+ { name = "*.pub", fg = "#a6da95" },
+ { name = "*id_dsa", fg = "#a6da95" },
+ { name = "*id_rsa", fg = "#a6da95" },
+ { name = "*id_ecdsa", fg = "#a6da95" },
+ { name = "*id_ed25519", fg = "#a6da95" },
+ { name = "*.DS_Store", fg = "#5b6078" },
+ { name = "*.localized", fg = "#5b6078" },
+ { name = "*.CFUserTextEncoding", fg = "#5b6078" },
+ { name = "*.groovy", fg = "#a6da95" },
+ { name = "*.gvy", fg = "#a6da95" },
+ { name = "*go.mod", fg = "#8bd5ca" },
+ { name = "*setup.py", fg = "#8bd5ca" },
+ { name = "*pyproject.toml", fg = "#8bd5ca" },
+ { name = "*.editorconfig", fg = "#8bd5ca" },
+ { name = "*.pro", fg = "#8bd5ca" },
+ { name = "*Doxyfile", fg = "#8bd5ca" },
+ { name = "*.dox", fg = "#8bd5ca" },
+ { name = "*.gradle", fg = "#a6da95" },
+ { name = "*PkgInfo", fg = "#5b6078" },
+ { name = "*.desktop", fg = "#eed49f" },
+ { name = "*passwd", fg = "#eed49f" },
+ { name = "*shadow", fg = "#eed49f" },
+ { name = "*.pas", fg = "#a6da95" },
+ { name = "*.strings", fg = "#8bd5ca" },
+ { name = "*package-lock.json", fg = "#5b6078" },
+ { name = "*go.sum", fg = "#5b6078" },
+ { name = "*bun.lockb", fg = "#5b6078" },
+ { name = "*stdin", fg = "#5b6078" },
+ { name = "*stdout", fg = "#5b6078" },
+ { name = "*.ex", fg = "#a6da95" },
+ { name = "*.exs", fg = "#a6da95" },
+ { name = "*.ics", fg = "#ed8796" },
+]
+
+[icon]
+dirs = [
+ { name = ".config", text = "" },
+ { name = ".git", text = "" },
+ { name = ".github", text = "" },
+ { name = "Desktop", text = "" },
+ { name = "Documents", text = "" },
+ { name = "Downloads", text = "" },
+ { name = "Library", text = "" },
+ { name = "Obsidian", text = "󰠮" },
+ { name = "Games", text = "" },
+ { name = "Movies", text = "" },
+ { name = "Music", text = "" },
+ { name = "Pictures", text = "" },
+ { name = "Public", text = "" },
+ { name = "Templates", text = "" },
+ { name = "Videos", text = "" },
+ { name = "desktop", text = "" },
+ { name = "dev", text = "" },
+ { name = "documents", text = "" },
+ { name = "downloads", text = "" },
+ { name = "library", text = "" },
+ { name = "obsidian", text = "󰠮" },
+ { name = "games", text = "" },
+ { name = "movies", text = "" },
+ { name = "music", text = "" },
+ { name = "pictures", text = "" },
+ { name = "public", text = "" },
+ { name = "templates", text = "" },
+ { name = "videos", text = "" },
+]
+
+files = [
+ { name = "gulpfile.js", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = ".babelrc", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "copying.lesser", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = ".npmrc", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "docker-compose.yml", text = "󰡨", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "svelte.config.js", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "copying", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "prettier.config.ts", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "gruntfile.babel.js", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = ".SRCINFO", text = "󰣇", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = ".xinitrc", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "docker-compose.yaml", text = "󰡨", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "nuxt.config.ts", text = "󱄆", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = "build", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = ".editorconfig", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "nuxt.config.mjs", text = "󱄆", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = ".gitlab-ci.yml", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "PKGBUILD", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = ".bash_profile", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = ".bashrc", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "compose.yml", text = "󰡨", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "eslint.config.cjs", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "go.mod", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = ".mailmap", text = "󰊢", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "gtkrc", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "go.work", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "justfile", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "kritadisplayrc", text = "", fg_dark = "#c6a0f6", fg_light = "#c6a0f6" },
+ { name = "commitlint.config.js", text = "󰜘", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = ".env", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "PrusaSlicerGcodeViewer.ini", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "r", text = "󰟔", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "license", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = ".gitignore", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "tailwind.config.js", text = "󱏿", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = ".prettierrc.yml", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = ".zprofile", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = ".zshenv", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "xmonad.hs", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = ".eslintignore", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "tsconfig.json", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = ".prettierrc.json5", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = ".ds_store", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "gulpfile.coffee", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "R", text = "󰟔", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = ".zshrc", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = ".prettierrc.toml", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = ".gvimrc", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = ".xsession", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = ".justfile", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = ".gitconfig", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "gradle-wrapper.properties", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "ionic.config.json", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "cantorrc", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = ".gleam", text = "", fg_dark = "#f5bde6", fg_light = "#f5bde6" },
+ { name = "package-lock.json", text = "", fg_dark = "#363a4f", fg_light = "#363a4f" },
+ { name = "package.json", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "hyprland.conf", text = "", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = "gulpfile.babel.js", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = ".nvmrc", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = ".prettierignore", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "ext_typoscript_setup.txt", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "QtProject.conf", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "avif", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "mix.lock", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "build.gradle", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "gemfile$", text = "", fg_dark = "#181926", fg_light = "#181926" },
+ { name = ".vimrc", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "i18n.config.ts", text = "󰗊", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "gulpfile.ts", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "build.zig.zon", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "checkhealth", text = "󰓙", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "xmobarrc", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "_vimrc", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = ".luaurc", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "kdenlive-layoutsrc", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "gradlew", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "xsettingsd.conf", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "vlcrc", text = "󰕼", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "xorg.conf", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "xmobarrc.hs", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "workspace", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = ".gitattributes", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "favicon.ico", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "go.sum", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "pom.xml", text = "", fg_dark = "#363a4f", fg_light = "#363a4f" },
+ { name = "webpack", text = "󰜫", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "vagrantfile$", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "unlicense", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "tmux.conf.local", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "settings.gradle", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = ".dockerignore", text = "󰡨", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "sym-lib-table", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "_gvimrc", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "kdenliverc", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "kdeglobals", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = ".prettierrc.yaml", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "rmd", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "tailwind.config.mjs", text = "󱏿", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "sxhkdrc", text = "", fg_dark = "#1e2030", fg_light = "#1e2030" },
+ { name = "robots.txt", text = "󰚩", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "tailwind.config.ts", text = "󱏿", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "prettier.config.mjs", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "mpv.conf", text = "", fg_dark = "#24273a", fg_light = "#24273a" },
+ { name = "py.typed", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "PrusaSlicer.ini", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "procfile", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "rakefile", text = "", fg_dark = "#181926", fg_light = "#181926" },
+ { name = "kritarc", text = "", fg_dark = "#c6a0f6", fg_light = "#c6a0f6" },
+ { name = ".Xresources", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "prettier.config.js", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "commitlint.config.ts", text = "󰜘", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = "weston.ini", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "eslint.config.js", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "cmakelists.txt", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = ".git-blame-ignore-revs", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "config", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "nuxt.config.cjs", text = "󱄆", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = "node_modules", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "makefile", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "lxqt.conf", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "i18n.config.js", text = "󰗊", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "FreeCAD.conf", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "prettier.config.cjs", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "tmux.conf", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "kalgebrarc", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "i3status.conf", text = "", fg_dark = "#cad3f5", fg_light = "#cad3f5" },
+ { name = ".settings.json", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "containerfile", text = "󰡨", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "i3blocks.conf", text = "", fg_dark = "#cad3f5", fg_light = "#cad3f5" },
+ { name = "lxde-rc.xml", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "gradle.properties", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "hypridle.conf", text = "", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = "gruntfile.ts", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "gruntfile.js", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "dockerfile", text = "󰡨", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "groovy", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "hyprlock.conf", text = "", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = ".prettierrc", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "gnumakefile", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "commit_editmsg", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "fp-lib-table", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "fp-info-cache", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "eslint.config.ts", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "nuxt.config.js", text = "󱄆", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = "platformio.ini", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = ".nuxtrc", text = "󱄆", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = "gruntfile.coffee", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "eslint.config.mjs", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "compose.yaml", text = "󰡨", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "bspwmrc", text = "", fg_dark = "#1e2030", fg_light = "#1e2030" },
+ { name = "brewfile", text = "", fg_dark = "#181926", fg_light = "#181926" },
+ { name = ".eslintrc", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = ".gtkrc-2.0", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = ".Xauthority", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = ".prettierrc.json", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = ".npmignore", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = ".gitmodules", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+]
+exts = [
+ { name = "rake", text = "", fg_dark = "#181926", fg_light = "#181926" },
+ { name = "skp", text = "󰻫", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "eln", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "razor", text = "󱦘", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "vue", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "sln", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "el", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "blp", text = "󰺾", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "jl", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "mdx", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "jsx", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "ml", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "less", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "pot", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "pl", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "mli", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "gif", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "aif", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "cxxm", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "fcbak", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "aac", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "query", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "android", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "m3u8", text = "󰲹", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "leex", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "liquid", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "cue", text = "󰲹", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "fcmacro", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "log", text = "󰌱", fg_dark = "#cad3f5", fg_light = "#cad3f5" },
+ { name = "pm", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "brep", text = "󰻫", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "blend", text = "󰂫", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "md5", text = "󰕥", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "sql", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "xcplayground", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "erb", text = "", fg_dark = "#181926", fg_light = "#181926" },
+ { name = "t", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "cache", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "r", text = "󰟔", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "x", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "import", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "m", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "lrc", text = "󰨖", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "o", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "d", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "c", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "h", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "rss", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "hbs", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "godxot", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "eot", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "awk", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "fsx", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "a", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "pyi", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "asc", text = "󰦝", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "ass", text = "󰨖", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "css", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "psb", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "csproj", text = "󰪮", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "csv", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "gcode", text = "󰐫", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "ics", text = "", fg_dark = "#363a4f", fg_light = "#363a4f" },
+ { name = "mk", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "bz", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "fctb", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "gz", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "wasm", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "glb", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "elc", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "flf", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "elf", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "dropbox", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "tres", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "apk", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "ape", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "slvs", text = "󰻫", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "apl", text = "⍝", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "cs", text = "󰌛", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "azcli", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "pp", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "flc", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "gemspec", text = "", fg_dark = "#181926", fg_light = "#181926" },
+ { name = "pls", text = "󰲹", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "cfg", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "fcscript", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "gnumakefile", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "zst", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "pxi", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "woff2", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "kicad_pcb", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "zsh", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "kicad_wks", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "info", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "cppm", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "svg", text = "󰜡", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "flac", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "cuh", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "bin", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "zig", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "yml", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "yaml", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "fsscript", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "xz", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "diff", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "mojo", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "cshtml", text = "󱦗", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "bak", text = "󰁯", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "nfo", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "bat", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "cpy", text = "⚙", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "gql", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "c++", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "lff", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "obj", text = "󰆧", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "sha512", text = "󰕥", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "scm", text = "󰘧", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "aiff", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "sig", text = "λ", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "webm", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "zip", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "wrz", text = "󰆧", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "jwmrc", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "xml", text = "󰗀", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "cbl", text = "⚙", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "rmd", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "xaml", text = "󰙳", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "xm", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "wvc", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "drl", text = "", fg_dark = "#ee99a0", fg_light = "#ee99a0" },
+ { name = "erl", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "3gp", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "ccm", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "ino", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "kbx", text = "󰯄", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "test.js", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "wrl", text = "󰆧", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "pcm", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "woff", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "scala", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "webpack", text = "󰜫", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "hrl", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "kra", text = "", fg_dark = "#c6a0f6", fg_light = "#c6a0f6" },
+ { name = "kicad_pro", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "bazel", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "toml", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "iges", text = "󰻫", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "crdownload", text = "", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = "so", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "strings", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "xls", text = "󰈛", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "wav", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "vsix", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "kicad_prl", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "mov", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "bash", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "sqlite3", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "vsh", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "vim", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "lck", text = "", fg_dark = "#b8c0e0", fg_light = "#b8c0e0" },
+ { name = "go", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "pyo", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "vhdl", text = "󰍛", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "vhd", text = "󰍛", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "rar", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "magnet", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "vala", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "coffee", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "kdbx", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "po", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "v", text = "󰍛", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "prisma", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "f90", text = "󱈚", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "txt", text = "󰈙", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "mo", text = "∞", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "mp4", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "cljc", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "heex", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "exs", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "clj", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "luau", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "fcparam", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "markdown", text = "", fg_dark = "#cad3f5", fg_light = "#cad3f5" },
+ { name = "dxf", text = "󰻫", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "luac", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "desktop", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "docx", text = "󰈬", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "cljd", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "txz", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "bicepparam", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "kt", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "fcstd", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "md", text = "", fg_dark = "#cad3f5", fg_light = "#cad3f5" },
+ { name = "edn", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "sub", text = "󰨖", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "ttf", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "tsx", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "hurl", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "dll", text = "", fg_dark = "#181926", fg_light = "#181926" },
+ { name = "lhs", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "tsconfig", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "msf", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "ts", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "rproj", text = "󰗆", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "org", text = "", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = "signature", text = "λ", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "elm", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "pyc", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "tmux", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "tgz", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "nu", text = ">", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "tfvars", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "lua", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "astro", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "lib", text = "", fg_dark = "#181926", fg_light = "#181926" },
+ { name = "tex", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "ogg", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "stp", text = "󰻫", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "sublime", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "test.tsx", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "nswag", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "test.ts", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "test.jsx", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "dwg", text = "󰻫", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "bib", text = "󱉟", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "sass", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "templ", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "tcl", text = "󰛓", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "pck", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "swift", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "makefile", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "xcstrings", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "slim", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "iso", text = "", fg_dark = "#f0c6c6", fg_light = "#f0c6c6" },
+ { name = "fsi", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "dart", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "nix", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "svelte", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "sv", text = "󰍛", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "bz2", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "sha256", text = "󰕥", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "twig", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "material", text = "󰔉", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "ppt", text = "󰈧", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "pyd", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "step", text = "󰻫", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "hx", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "webmanifest", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "kicad_sch", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "cjs", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "stl", text = "󰆧", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "ejs", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "ssa", text = "󰨖", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "license", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "jsonc", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "download", text = "", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = "ige", text = "󰻫", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "sqlite", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "psd1", text = "󰨊", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "dump", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "resi", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "spec.ts", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "fnl", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "cu", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "scss", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "config.ru", text = "", fg_dark = "#181926", fg_light = "#181926" },
+ { name = "psd", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "db", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "epub", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "haml", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "sol", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "sml", text = "λ", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "svh", text = "󰍛", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "sldprt", text = "󰻫", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "ico", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "xlsx", text = "󰈛", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "rs", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "dconf", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "bz3", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "fdmdownload", text = "", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = "fs", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "patch", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "hs", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "xcf", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "js", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "pyw", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "sha384", text = "󰕥", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "fcmat", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "csh", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "suo", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "sha224", text = "󰕥", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "sha1", text = "󰕥", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "cr", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "huff", text = "󰡘", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "sh", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "sc", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "ksh", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "cc", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "wma", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "mp3", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "conf", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "3mf", text = "󰆧", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "sbt", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "kicad_mod", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "terminal", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "rlib", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "pdf", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "mts", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "kdenlive", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "kts", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "spec.tsx", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "res", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "hxx", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "rb", text = "", fg_dark = "#181926", fg_light = "#181926" },
+ { name = "vh", text = "󰍛", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "ixx", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "cson", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "cts", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "7z", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "ex", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "cpp", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "qss", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "app", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "jxl", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "qrc", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "qml", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "epp", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "otf", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "hh", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "qm", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "pro", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "exe", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "kdenlivetitle", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "kdb", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "mpp", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "Dockerfile", text = "󰡨", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "bqn", text = "⎉", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "torrent", text = "", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = "m3u", text = "󰲹", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "py", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "pxd", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "f3d", text = "󰻫", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "out", text = "", fg_dark = "#494d64", fg_light = "#494d64" },
+ { name = "spec.jsx", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "kicad_dru", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "a6da95", text = "󰨊", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "ui", text = "", fg_dark = "#363a4f", fg_light = "#363a4f" },
+ { name = "styl", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "f#", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "png", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "ply", text = "󰆧", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "php", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "eex", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "tbc", text = "󰛓", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "part", text = "", fg_dark = "#8bd5ca", fg_light = "#8bd5ca" },
+ { name = "pub", text = "󰷖", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "ipynb", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "opus", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "git", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "bmp", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "blade.php", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "nim", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "xpi", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "mustache", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "tscn", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "scad", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "ai", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "hex", text = "", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "hpp", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "xul", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "mobi", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "fcstd1", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "ical", text = "", fg_dark = "#363a4f", fg_light = "#363a4f" },
+ { name = "icalendar", text = "", fg_dark = "#363a4f", fg_light = "#363a4f" },
+ { name = "bicep", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "mm", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "mkv", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "graphql", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "mjs", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "mint", text = "󰌪", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "m4v", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "m4a", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "tf", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "gv", text = "󱁉", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "lock", text = "", fg_dark = "#b8c0e0", fg_light = "#b8c0e0" },
+ { name = "krz", text = "", fg_dark = "#c6a0f6", fg_light = "#c6a0f6" },
+ { name = "kpp", text = "", fg_dark = "#c6a0f6", fg_light = "#c6a0f6" },
+ { name = "ko", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "kicad_sym", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "psm1", text = "󰨊", fg_dark = "#6e738d", fg_light = "#6e738d" },
+ { name = "pyx", text = "", fg_dark = "#8aadf4", fg_light = "#8aadf4" },
+ { name = "json5", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "json", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "bzl", text = "", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "ifb", text = "", fg_dark = "#363a4f", fg_light = "#363a4f" },
+ { name = "image", text = "", fg_dark = "#f0c6c6", fg_light = "#f0c6c6" },
+ { name = "jpg", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "jpeg", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "java", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "wv", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "ini", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "cast", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "cp", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "fctl", text = "", fg_dark = "#ed8796", fg_light = "#ed8796" },
+ { name = "ifc", text = "󰻫", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "sldasm", text = "󰻫", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "html", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "typoscript", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "🔥", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "htm", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "ste", text = "󰻫", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "spec.js", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "gresource", text = "", fg_dark = "#f4dbd6", fg_light = "#f4dbd6" },
+ { name = "ebook", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "gradle", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "gd", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "fish", text = "", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "igs", text = "󰻫", fg_dark = "#a6da95", fg_light = "#a6da95" },
+ { name = "fbx", text = "󰆧", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "env", text = "", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "srt", text = "󰨖", fg_dark = "#eed49f", fg_light = "#eed49f" },
+ { name = "dot", text = "󱁉", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "doc", text = "󰈬", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "d.ts", text = "", fg_dark = "#f5a97f", fg_light = "#f5a97f" },
+ { name = "applescript", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "cxx", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "img", text = "", fg_dark = "#f0c6c6", fg_light = "#f0c6c6" },
+ { name = "cljs", text = "", fg_dark = "#7dc4e4", fg_light = "#7dc4e4" },
+ { name = "cobol", text = "⚙", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "cob", text = "⚙", fg_dark = "#5b6078", fg_light = "#5b6078" },
+ { name = "cmake", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+ { name = "webp", text = "", fg_dark = "#8087a2", fg_light = "#8087a2" },
+]
diff --git a/config/yazi/init.lua b/config/yazi/init.lua
new file mode 100644
index 00000000..c88c77c3
--- /dev/null
+++ b/config/yazi/init.lua
@@ -0,0 +1,168 @@
+local catppuccin_palette = {
+ rosewater = "#f4dbd6",
+ flamingo = "#f0c6c6",
+ pink = "#f5bde6",
+ mauve = "#c6a0f6",
+ red = "#ed8796",
+ maroon = "#ee99a0",
+ peach = "#f5a97f",
+ yellow = "#eed49f",
+ green = "#a6da95",
+ teal = "#8bd5ca",
+ sky = "#91d7e3",
+ sapphire = "#7dc4e4",
+ blue = "#8aadf4",
+ lavender = "#b7bdf8",
+ text = "#cad3f5",
+ subtext1 = "#b8c0e0",
+ subtext0 = "#a5adcb",
+ overlay2 = "#939ab7",
+ overlay1 = "#8087a2",
+ overlay0 = "#6e738d",
+ surface2 = "#5b6078",
+ surface1 = "#494d64",
+ surface0 = "#363a4f",
+ base = "#24273a",
+ mantle = "#1e2030",
+ crust = "#181926",
+}
+
+-- Plugins
+require("full-border"):setup({
+ type = ui.Border.ROUNDED,
+})
+
+require("zoxide"):setup({
+ update_db = true,
+})
+
+require("session"):setup({
+ sync_yanked = true,
+})
+
+require("yatline"):setup({
+ section_separator = { open = "", close = "" },
+ inverse_separator = { open = "", close = "" },
+ part_separator = { open = "", close = "" },
+
+ style_a = {
+ fg = catppuccin_palette.mantle,
+ bg_mode = {
+ normal = catppuccin_palette.blue,
+ select = catppuccin_palette.mauve,
+ un_set = catppuccin_palette.red,
+ },
+ },
+ style_b = { bg = catppuccin_palette.surface0, fg = catppuccin_palette.text },
+ style_c = { bg = catppuccin_palette.base, fg = catppuccin_palette.text },
+
+ permissions_t_fg = catppuccin_palette.green,
+ permissions_r_fg = catppuccin_palette.yellow,
+ permissions_w_fg = catppuccin_palette.red,
+ permissions_x_fg = catppuccin_palette.sky,
+ permissions_s_fg = catppuccin_palette.lavender,
+
+ selected = { icon = "󰻭", fg = catppuccin_palette.yellow },
+ copied = { icon = "", fg = catppuccin_palette.green },
+ cut = { icon = "", fg = catppuccin_palette.red },
+
+ total = { icon = "", fg = catppuccin_palette.yellow },
+ succ = { icon = "", fg = catppuccin_palette.green },
+ fail = { icon = "", fg = catppuccin_palette.red },
+ found = { icon = "", fg = catppuccin_palette.blue },
+ processed = { icon = "", fg = catppuccin_palette.green },
+
+ tab_width = 20,
+ tab_use_inverse = true,
+
+ show_background = false,
+
+ display_header_line = true,
+ display_status_line = true,
+
+ header_line = {
+ left = {
+ section_a = {
+ { type = "line", custom = false, name = "tabs", params = { "left" } },
+ },
+ section_b = {
+ { type = "coloreds", custom = false, name = "githead" },
+ },
+ section_c = {},
+ },
+ right = {
+ section_a = {
+ { type = "string", custom = false, name = "tab_path" },
+ },
+ section_b = {
+ { type = "coloreds", custom = false, name = "task_workload" },
+ },
+ section_c = {
+ { type = "coloreds", custom = false, name = "task_states" },
+ },
+ },
+ },
+
+ status_line = {
+ left = {
+ section_a = {
+ { type = "string", custom = false, name = "tab_mode" },
+ },
+ section_b = {
+ { type = "string", custom = false, name = "hovered_size" },
+ },
+ section_c = {
+ { type = "string", custom = false, name = "hovered_name" },
+ { type = "coloreds", custom = false, name = "count" },
+ },
+ },
+ right = {
+ section_a = {
+ { type = "string", custom = false, name = "cursor_position" },
+ },
+ section_b = {
+ { type = "string", custom = false, name = "cursor_percentage" },
+ },
+ section_c = {
+ { type = "string", custom = false, name = "hovered_file_extension", params = { true } },
+ { type = "coloreds", custom = false, name = "permissions" },
+ },
+ },
+ },
+})
+
+require("yatline-githead"):setup({
+ show_branch = true,
+ branch_prefix = "",
+ branch_symbol = "",
+ branch_borders = "",
+
+ commit_symbol = " ",
+
+ show_stashes = true,
+ stashes_symbol = " ",
+
+ show_state = true,
+ show_state_prefix = true,
+ state_symbol = "󱅉",
+
+ show_staged = true,
+ staged_symbol = " ",
+
+ show_unstaged = true,
+ unstaged_symbol = " ",
+
+ show_untracked = true,
+ untracked_symbol = " ",
+
+ prefix_color = catppuccin_palette.pink,
+ branch_color = catppuccin_palette.pink,
+ commit_color = catppuccin_palette.mauve,
+ stashes_color = catppuccin_palette.teal,
+ state_color = catppuccin_palette.lavender,
+ staged_color = catppuccin_palette.green,
+ unstaged_color = catppuccin_palette.yellow,
+ untracked_color = catppuccin_palette.pink,
+})
+
+require("git"):setup()
diff --git a/config/yazi/keymap.toml b/config/yazi/keymap.toml
new file mode 100644
index 00000000..ba212c92
--- /dev/null
+++ b/config/yazi/keymap.toml
@@ -0,0 +1,99 @@
+
+[manager]
+
+prepend_keymap = [
+ { on = [
+ "<C-s>",
+ ], run = '''shell "$SHELL" --block --confirm''', desc = "Open shell here" },
+ { on = [
+ "c",
+ "a",
+ ], run = "plugin compress", desc = "Archive selected files" },
+ { on = "<C-u>", run = "seek -5", desc = "Seek up 5 units in the preview" },
+ { on = "<C-d>", run = "seek 5", desc = "Seek down 5 units in the preview" },
+ { on = "K", run = "arrow -50%", desc = "Move cursor up half page" },
+ { on = "J", run = "arrow 50%", desc = "Move cursor down half page" },
+ { on = "<A-k>", run = "arrow -5", desc = "Move cursor up half page" },
+ { on = "<A-j>", run = "arrow 5", desc = "Move cursor down half page" },
+ { on = [
+ "f",
+ "g",
+ ], run = "plugin fg", desc = "find file by content (fuzzy match)" },
+ { on = [
+ "f",
+ "G",
+ ], run = "plugin fg --args='rg'", desc = "find file by content (ripgrep match)" },
+ { on = [
+ "f",
+ "n",
+ ], run = "plugin fg --args='fzf'", desc = "find file by filename" },
+ { on = [
+ "f",
+ "f",
+ ], run = "filter --smart", desc = "Filter files" },
+ { on = [
+ "f",
+ "F",
+ ], run = "plugin smart-filter", desc = "Smart Filter" },
+ { on = [
+ "s",
+ ], run = "plugin searchjump", desc = "searchjump mode" },
+ { on = "S", run = "search fd", desc = "Search files by name using fd" },
+ { on = [
+ "T",
+ ], run = "plugin --sync hide-preview", desc = "Hide or show the preview" },
+ { on = [
+ "y",
+ ], run = [
+ '''shell 'for path in "$@"; do echo "file://$path"; done | wl-copy -t text/uri-list' --confirm''',
+ "yank",
+ ], desc = "yank files and copy to clipboard" },
+ { on = "A", run = "create --dir", desc = "Create a dir" },
+]
+
+append_keymap = [
+ { on = [
+ "e",
+ ], run = "open", desc = "Open the selected files" },
+ { on = [
+ "E",
+ ], run = "open --interactive", desc = "Open the selected files interactively" },
+ { on = [
+ "g",
+ "n",
+ ], run = "cd ~/.config/nvim/", desc = "Go to the nvim directory" },
+ { on = [
+ "g",
+ "v",
+ ], run = "cd ~/videos/", desc = "Go to the videos directory" },
+ { on = [
+ "g",
+ "p",
+ ], run = "cd ~/pictures/", desc = "Go to the pictures directory" },
+ { on = [
+ "g",
+ "s",
+ ], run = "cd ~/pictures/screenshots/", desc = "Go to the screenshots directory" },
+ { on = [
+ "g",
+ "D",
+ ], run = "cd ~/documents/", desc = "Go to the docs directory" },
+ { on = [
+ "g",
+ "o",
+ ], run = "cd ~/documents/obsidian-vaults", desc = "Go to the obsidian directory" },
+ { on = [
+ "g",
+ "e",
+ ], run = "cd ~/dev/", desc = "Go to the dev directory" },
+]
+
+[input]
+
+prepend_keymap = [{ on = ["<Esc>"], run = "close", desc = "Cancel input" }]
+
+[completion]
+prepend_keymap = [
+ { on = "<C-k>", run = "arrow -1", desc = "Move cursor up" },
+ { on = "<C-j>", run = "arrow 1", desc = "Move cursor down" },
+]
diff --git a/config/yazi/package.toml b/config/yazi/package.toml
new file mode 100644
index 00000000..deedca73
--- /dev/null
+++ b/config/yazi/package.toml
@@ -0,0 +1,37 @@
+[[plugin.deps]]
+use = "yazi-rs/plugins:full-border"
+rev = "1db18bb"
+hash = "eff8ff12fa4e5f035a10d8aeeb4c258d"
+
+[[plugin.deps]]
+use = "KKV9/compress"
+rev = "46a6b9f"
+hash = "771af2becc575a3f43d0542de823969d"
+
+[[plugin.deps]]
+use = "imsi32/yatline"
+rev = "c5d4b48"
+hash = "e6e98d12b1648d1894c2b560d85eeaa7"
+
+[[plugin.deps]]
+use = "imsi32/yatline-githead"
+rev = "929e52c"
+hash = "8282baf02fcd6aac00ccad2276775358"
+
+[[plugin.deps]]
+use = "yazi-rs/plugins:smart-filter"
+rev = "1db18bb"
+hash = "c887903a63a2ff520081b6d90a4b3392"
+
+[[plugin.deps]]
+use = "yazi-rs/plugins:hide-preview"
+rev = "1db18bb"
+hash = "99aa06d3014798d86001c324468d497f"
+
+[[plugin.deps]]
+use = "yazi-rs/plugins:git"
+rev = "1db18bb"
+hash = "c8d30a70659f1b880407e61c564ab4e8"
+
+[flavor]
+deps = []
diff --git a/config/yazi/plugins/compress.yazi/LICENSE b/config/yazi/plugins/compress.yazi/LICENSE
new file mode 100644
index 00000000..7ce7a2f1
--- /dev/null
+++ b/config/yazi/plugins/compress.yazi/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 Ciarán O'Brien
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/config/yazi/plugins/compress.yazi/README.md b/config/yazi/plugins/compress.yazi/README.md
new file mode 100644
index 00000000..7241cf7d
--- /dev/null
+++ b/config/yazi/plugins/compress.yazi/README.md
@@ -0,0 +1,152 @@
+<h1 align="center">🗜️ compress.yazi</h1>
+<p align="center">
+ <b>A blazing fast, flexible archive plugin for <a href="https://github.com/sxyazi/yazi">Yazi</a></b><br>
+ <i>Effortlessly compress your files and folders with style!</i>
+</p>
+
+## 📖 Table of Contents
+
+- [Features](#-features)
+- [Supported File Types](#-supported-file-types)
+- [Installation](#%EF%B8%8F-installation)
+- [Keymap Example](#-keymap-example)
+- [Usage](#%EF%B8%8F-usage)
+- [Flags](#%EF%B8%8F-flags)
+- [Tips](#-tips)
+- [Credits](#-credits)
+
+## 🚀 Features
+
+- 🗂️ **Multi-format support:** zip, 7z, rar, tar, tar.gz, tar.xz, tar.bz2, tar.zst, tar.lz4, tar.lha
+- 🌍 **Cross-platform:** Works on Unix & Windows
+- 🔒 **Password protection:** Secure your archives (zip/7z/rar)
+- 🛡️ **Header encryption:** Hide file lists (7z/rar)
+- ⚡ **Compression level:** Choose your balance of speed vs. size
+- 🛑 **Overwrite safety:** Never lose files by accident
+- 🎯 **Seamless Yazi integration:** Fast, native-like UX
+
+## 📦 Supported File Types
+
+| Extension | Default Command | 7z Command | Bsdtar Command (Win10+ & Unix) |
+| ------------- | ----------------- | -------------- | ------------------------------ |
+| `.zip` | `zip -r` | `7z a -tzip` | `tar -caf` |
+| `.7z` | `7z a` | `7z a` | |
+| `.rar` | `rar a` | | |
+| `.tar` | `tar rpf` | | `tar rpf` |
+| `.tar.gz` | `tar rpf + gzip` | `7z a -tgzip` | `tar -czf` |
+| `.tar.xz` | `tar rpf + xz` | `7z a -txz` | `tar -cJf` |
+| `.tar.bz2` | `tar rpf + bzip2` | `7z a -tbzip2` | `tar -cjf` |
+| `.tar.zst` | `tar rpf + zstd` | | `tar --zstd -cf` |
+| `.tar.lz4` | `tar rpf + lz4` | | |
+| `.tar.lha` | `tar rpf + lha` | | |
+
+
+## ⚡️ Installation
+
+```bash
+# Unix
+git clone https://github.com/KKV9/compress.yazi.git ~/.config/yazi/plugins/compress.yazi
+
+# Windows (CMD, not PowerShell!)
+git clone https://github.com/KKV9/compress.yazi.git %AppData%\yazi\config\plugins\compress.yazi
+
+# Or with yazi plugin manager
+ya pkg add KKV9/compress
+```
+### 🔧 Extras (Windows)
+
+To enable additional compression formats and features on Windows, follow these steps:
+
+1. **Install [7-Zip](https://www.7-zip.org/):**
+ Add `C:\Program Files\7-Zip` to your `PATH`.
+ This enables support for `.7z` archives and password-protected `.zip` files.
+
+2. **Alternative: Install [Nanazip](https://github.com/M2Team/NanaZip):**
+ A modern alternative to 7-Zip with similar functionality and extra features.
+
+3. **Install [WinRAR](https://www.win-rar.com/download.html):**
+ Add `C:\Program Files\WinRAR` to your `PATH`.
+ This enables support for `.rar` archives.
+
+4. **Install Additional Tools:**
+ To use formats like `lha`, `lz4`, `gzip`, etc., install their respective tools and ensure they are added to your `PATH`.
+
+## 🎹 Keymap Example
+
+Add this to your `keymap.toml`:
+
+
+```toml
+[[mgr.prepend_keymap]]
+on = [ "c", "a", "a" ]
+run = "plugin compress"
+desc = "Archive selected files"
+
+[[mgr.prepend_keymap]]
+on = [ "c", "a", "p" ]
+run = "plugin compress -p"
+desc = "Archive selected files (password)"
+
+[[mgr.prepend_keymap]]
+on = [ "c", "a", "h" ]
+run = "plugin compress -ph"
+desc = "Archive selected files (password+header)"
+
+[[mgr.prepend_keymap]]
+on = [ "c", "a", "l" ]
+run = "plugin compress -l"
+desc = "Archive selected files (compression level)"
+
+[[mgr.prepend_keymap]]
+on = [ "c", "a", "u" ]
+run = "plugin compress -phl"
+desc = "Archive selected files (password+header+level)"
+```
+
+## 🛠️ Usage
+
+1. **Select files/folders** in Yazi.
+2. Press <kbd>c</kbd> <kbd>a</kbd> to open the archive dialog.
+3. Choose:
+ - <kbd>a</kbd> for a standard archive
+ - <kbd>p</kbd> for password protection (zip/7z/rar)
+ - <kbd>h</kbd> to encrypt header (7z/rar)
+ - <kbd>l</kbd> to set compression level (all compression algorithims)
+ - <kbd>u</kbd> for all options together
+4. **Type a name** for your archive (or leave blank for suggested name).
+5. **Enter password** and/or **compression level** if prompted.
+6. **Overwrite protect** if a file already exists, the new file will be given a suffix _#.
+7. Enjoy your shiny new archive!
+
+## 🏳️‍🌈 Flags
+
+- Combine flags for more power!
+- when separating flags with spaces, make sure to single quote them (eg., `'-ph rar'`)
+- `-p` Password protect (zip/7z/rar)
+- `-h` Encrypt header (7z/rar)
+- `-l` Set compression level (all compression algorithims)
+- `-s` Silence success message
+- `<extention>` Specify a default extention (eg., `7z`, `tar.gz`)
+
+#### Combining multiple flags:
+```toml
+[[mgr.prepend_keymap]]
+on = [ "c", "a", "7" ]
+run = "plugin compress '-ph 7z'"
+desc = "Archive selected files to 7z (password+header)"
+[[mgr.prepend_keymap]]
+on = [ "c", "a", "r" ]
+run = "plugin compress '-p -l rar'"
+desc = "Archive selected files to rar (password+level)"
+```
+## 💡 Tips
+
+- The file extension **must** match a supported type.
+- The required compression tool **must** be installed and in your `PATH` (7zip/rar etc.).
+- If no extention is provided, the default extention (zip) will be appended automatically.
+- If you leave the filename blank, the plugin will use the selected filename or parent directory, when multiple files are selected, to name the archive.
+
+## 📣 Credits
+
+Made with ❤️ for [Yazi](https://github.com/sxyazi/yazi) by [KKV9](https://github.com/KKV9).
+Contributions are welcome! Feel free to submit a pull request.
diff --git a/config/yazi/plugins/compress.yazi/main.lua b/config/yazi/plugins/compress.yazi/main.lua
new file mode 100644
index 00000000..440f6e22
--- /dev/null
+++ b/config/yazi/plugins/compress.yazi/main.lua
@@ -0,0 +1,577 @@
+--- @since 25.12.29
+
+-- Check for windows
+local is_windows = ya.target_family() == "windows"
+
+-- Define default flags and strings
+local is_password, is_encrypted, is_level, is_silent_success = false, false, false, false
+local default_extension = "zip"
+
+-- Allow dots when matching file extension arguments
+local function extension_pattern(ext)
+ return "%." .. ext:gsub("%.", "%%.") .. "$"
+end
+
+-- Function to check valid filename
+local function is_valid_filename(name)
+ -- Trim whitespace from both ends
+ name = name:match("^%s*(.-)%s*$")
+ if name == "" then
+ return false
+ end
+ if is_windows then
+ -- Windows forbidden chars and reserved names
+ if name:find('[<>:"/\\|%?%*]') then
+ return false
+ end
+ else
+ -- Unix forbidden chars
+ if name:find("/") or name:find("%z") then
+ return false
+ end
+ end
+ return true
+end
+
+-- Function to send notifications
+local function notify(message, level)
+ ya.notify({
+ title = "Archive",
+ content = message,
+ level = level,
+ timeout = 5,
+ })
+end
+
+-- Function to check if command is available
+local function is_command_available(cmd)
+ local stat_cmd
+ if is_windows then
+ stat_cmd = string.format("where %s > nul 2>&1", cmd)
+ else
+ stat_cmd = string.format("command -v %s >/dev/null 2>&1", cmd)
+ end
+ return os.execute(stat_cmd)
+end
+
+-- Function to find first available command from list
+local function find_command_name(cmd_list)
+ for _, cmd in ipairs(cmd_list) do
+ if is_command_available(cmd) then
+ return cmd
+ end
+ end
+ return cmd_list[1] -- Return first command as fallback
+end
+
+-- Function to append filename to its parent directory url
+local function combine_url(path, file)
+ local path_url = Url(path)
+ local file_url = Url(file)
+ return tostring(path_url:join(file_url))
+end
+
+-- Function to make a table of selected or hovered files: path = filenames
+local selected_or_hovered = ya.sync(function()
+ local tab = cx.active
+ local paths = {}
+ local names = {}
+ local path_fnames = {}
+
+ for _, u in pairs(tab.selected) do
+ paths[#paths + 1] = tostring(u.parent)
+ names[#names + 1] = tostring(u.name)
+ end
+
+ if #paths == 0 and tab.current.hovered then
+ paths[1] = tostring(tab.current.hovered.url.parent)
+ names[1] = tostring(tab.current.hovered.name)
+ end
+
+ for idx, name in ipairs(names) do
+ local path = paths[idx]
+ if not path_fnames[path] then
+ path_fnames[path] = {}
+ end
+ table.insert(path_fnames[path], name)
+ end
+
+ return path_fnames, names, tostring(tab.current.cwd)
+end)
+
+-- Function to cleanup temporary directory
+local function cleanup_temp_dir(temp_dir)
+ local status, err = fs.remove("dir_all", Url(temp_dir))
+ if not status then
+ notify(
+ string.format("Failed to clean up temporary directory %s, error: %s", ya.quote(temp_dir), tostring(err)),
+ "error"
+ )
+ return false
+ end
+ return true
+end
+
+-- Function for compression level
+local function add_compression_level(target_args, level_arg, level_value)
+ if type(level_arg) == "table" then
+ -- Insert each element except last
+ for i = 1, #level_arg - 1 do
+ table.insert(target_args, i, level_arg[i])
+ end
+ -- Add the level value with the last element
+ table.insert(target_args, #level_arg, level_arg[#level_arg] .. level_value)
+ else
+ -- Single string argument
+ table.insert(target_args, 1, level_arg .. level_value)
+ end
+end
+
+-- Function for password handling
+local function get_password_args(archive_cmd, encrypted, header_arg)
+ local output_password, event = ya.input({
+ title = "Enter password:",
+ obscure = true,
+ pos = { "top-center", y = 3, w = 40 },
+ })
+ if event ~= 1 or output_password == "" then
+ return nil
+ end
+ -- Handling for RAR with encryption
+ if archive_cmd == "rar" and encrypted then
+ return { header_arg .. output_password }
+ end
+ return { "-P" .. output_password }
+end
+
+-- Table of archive commands
+local archive_commands = {
+ ["%.zip$"] = {
+ { command = "zip", args = { "-r" }, level_arg = "-", level_min = 0, level_max = 9, passwordable = true },
+ {
+ command = { "7z", "7zz", "7za" },
+ args = { "a", "-tzip" },
+ level_arg = "-mx=",
+ level_min = 0,
+ level_max = 9,
+ passwordable = true,
+ },
+ {
+ command = { "tar", "bsdtar" },
+ args = { "-caf" },
+ level_arg = { "--option", "compression-level=" },
+ level_min = 1,
+ level_max = 9,
+ },
+ },
+ ["%.7z$"] = {
+ {
+ command = { "7z", "7zz", "7za" },
+ args = { "a" },
+ level_arg = "-mx=",
+ level_min = 0,
+ level_max = 9,
+ header_arg = "-mhe=on",
+ passwordable = true,
+ },
+ },
+ ["%.rar$"] = {
+ {
+ command = "rar",
+ args = { "a" },
+ level_arg = "-m",
+ level_min = 0,
+ level_max = 5,
+ header_arg = "-hp",
+ passwordable = true,
+ },
+ },
+ ["%.tar%.gz$"] = {
+ {
+ command = { "tar", "bsdtar" },
+ args = { "rpf" },
+ level_arg = "-",
+ level_min = 1,
+ level_max = 9,
+ compress = "gzip",
+ },
+ {
+ command = { "tar", "bsdtar" },
+ args = { "rpf" },
+ level_arg = "-mx=",
+ level_min = 1,
+ level_max = 9,
+ compress = "7z",
+ compress_args = { "a", "-tgzip" },
+ },
+ {
+ command = { "tar", "bsdtar" },
+ args = { "-czf" },
+ level_arg = { "--option", "gzip:compression-level=" },
+ level_min = 1,
+ level_max = 9,
+ },
+ },
+ ["%.tar%.xz$"] = {
+ {
+ command = { "tar", "bsdtar" },
+ args = { "rpf" },
+ level_arg = "-",
+ level_min = 1,
+ level_max = 9,
+ compress = "xz",
+ },
+ {
+ command = { "tar", "bsdtar" },
+ args = { "rpf" },
+ level_arg = "-mx=",
+ level_min = 1,
+ level_max = 9,
+ compress = "7z",
+ compress_args = { "a", "-txz" },
+ },
+ {
+ command = { "tar", "bsdtar" },
+ args = { "-cJf" },
+ level_arg = { "--option", "xz:compression-level=" },
+ level_min = 1,
+ level_max = 9,
+ },
+ },
+ ["%.tar%.bz2$"] = {
+ {
+ command = { "tar", "bsdtar" },
+ args = { "rpf" },
+ level_arg = "-",
+ level_min = 1,
+ level_max = 9,
+ compress = "bzip2",
+ },
+ {
+ command = { "tar", "bsdtar" },
+ args = { "rpf" },
+ level_arg = "-mx=",
+ level_min = 1,
+ level_max = 9,
+ compress = "7z",
+ compress_args = { "a", "-tbzip2" },
+ },
+ {
+ command = { "tar", "bsdtar" },
+ args = { "-cjf" },
+ level_arg = { "--option", "bzip2:compression-level=" },
+ level_min = 1,
+ level_max = 9,
+ },
+ },
+ ["%.tar%.zst$"] = {
+ {
+ command = { "tar", "bsdtar" },
+ args = { "rpf" },
+ level_arg = "-",
+ level_min = 1,
+ level_max = 22,
+ compress = "zstd",
+ compress_args = { "--ultra" },
+ },
+ },
+ ["%.tar%.lz4$"] = {
+ {
+ command = { "tar", "bsdtar" },
+ args = { "rpf" },
+ level_arg = "-",
+ level_min = 1,
+ level_max = 12,
+ compress = "lz4",
+ },
+ },
+ ["%.tar%.lha$"] = {
+ {
+ command = { "tar", "bsdtar" },
+ args = { "rpf" },
+ level_arg = "-o",
+ level_min = 5,
+ level_max = 7,
+ compress = "lha",
+ compress_args = { "-a" },
+ },
+ },
+ ["%.tar$"] = {
+ { command = { "tar", "bsdtar" }, args = { "rpf" } },
+ },
+}
+
+-- Function for command matching
+local function find_archive_command(output_name)
+ for pattern, cmd_list in pairs(archive_commands) do
+ if output_name:match(pattern) then
+ for _, cmd in ipairs(cmd_list) do
+ -- Check if archive command is available
+ local cmd_name = type(cmd.command) == "table" and find_command_name(cmd.command) or cmd.command
+ if is_command_available(cmd_name) then
+ -- Check if compress command (if listed) is available
+ if not cmd.compress or is_command_available(cmd.compress) then
+ return {
+ cmd = cmd_name,
+ args = cmd.args,
+ compress = cmd.compress or "",
+ level_arg = cmd.level_arg or "",
+ level_min = cmd.level_min,
+ level_max = cmd.level_max,
+ header_arg = cmd.header_arg or "",
+ passwordable = cmd.passwordable or false,
+ compress_args = cmd.compress_args or {},
+ }
+ end
+ end
+ end
+ -- Pattern matched but no suitable command found
+ return nil
+ end
+ end
+ -- No pattern matched - unsupported extension
+ return false
+end
+
+return {
+ entry = function(_, job)
+ -- Parse flags and default extension
+ if job.args then
+ for _, arg in ipairs(job.args) do
+ if arg:match("^%-(%w+)$") then
+ -- Handle combined flags (e.g., -phl)
+ for flag in arg:sub(2):gmatch(".") do
+ if flag == "p" then
+ is_password = true
+ elseif flag == "h" then
+ is_encrypted = true
+ elseif flag == "l" then
+ is_level = true
+ elseif flag == "s" then
+ is_silent_success = true
+ end
+ end
+ elseif arg:match("^[%w%.]+$") then
+ -- Handle default extension (e.g., 7z, zip)
+ if archive_commands[extension_pattern(arg)] then
+ default_extension = arg
+ else
+ notify(string.format("Unsupported extension: %s", arg), "warn")
+ end
+ else
+ notify(string.format("Unknown argument: %s", arg), "warn")
+ end
+ end
+ end
+
+ -- Exit visual mode
+ ya.emit("escape", { visual = true })
+
+ -- Define file table and output_dir (pwd)
+ local path_fnames, fnames, output_dir = selected_or_hovered()
+
+ -- Get archive filename
+ local output_name, event = ya.input({
+ title = "Create archive:",
+ pos = { "top-center", y = 3, w = 40 },
+ })
+ if event ~= 1 then
+ return
+ end
+
+ -- Determine the default name for the archive
+ local default_name = #fnames == 1 and fnames[1] or Url(output_dir).name
+ output_name = output_name == "" and string.format("%s.%s", default_name, default_extension) or output_name
+
+ -- Add default extension if none is specified
+ if not output_name:match("%.%w+$") then
+ output_name = string.format("%s.%s", output_name, default_extension)
+ end
+
+ -- Validate the final archive filename
+ if not is_valid_filename(output_name) then
+ notify("Invalid archive filename", "error")
+ return
+ end
+
+ -- Command matching
+ local archive_config = find_archive_command(output_name)
+ if archive_config == false then
+ notify("Unsupported file extension", "error")
+ return
+ elseif not archive_config then
+ notify("Could not find a suitable archive program for the selected file extension", "error")
+ return
+ end
+
+ -- Extract configuration
+ local archive_cmd = archive_config.cmd
+ local archive_args = archive_config.args
+ local archive_compress = archive_config.compress
+ local archive_level_arg = is_level and archive_config.level_arg or ""
+ local archive_level_min = archive_config.level_min
+ local archive_level_max = archive_config.level_max
+ local archive_header_arg = is_encrypted and archive_config.header_arg or ""
+ local archive_passwordable = archive_config.passwordable
+ local archive_compress_args = archive_config.compress_args
+
+ -- Password handling
+ if archive_passwordable and is_password then
+ local password_args = get_password_args(archive_cmd, is_encrypted, archive_header_arg)
+ if password_args then
+ for _, arg in ipairs(password_args) do
+ table.insert(archive_args, arg)
+ end
+ end
+ end
+
+ -- Add header arg if selected for 7z
+ if is_encrypted and archive_header_arg ~= "" and archive_cmd ~= "rar" then
+ table.insert(archive_args, archive_header_arg)
+ end
+
+ -- Use extracted compression level
+ if archive_level_arg ~= "" and is_level then
+ local output_level, level_event = ya.input({
+ title = string.format("Enter compression level (%s - %s)", archive_level_min, archive_level_max),
+ pos = { "top-center", y = 3, w = 40 },
+ })
+ if level_event ~= 1 then
+ return
+ end
+ -- Validate user input for compression level
+ local level_num = tonumber(output_level)
+ if level_num and level_num >= archive_level_min and level_num <= archive_level_max then
+ local target_args = archive_compress == "" and archive_args or archive_compress_args
+ add_compression_level(target_args, archive_level_arg, output_level)
+ else
+ notify("Invalid level specified. Using defaults.", "warn")
+ end
+ end
+
+ -- Store the original output name for later use
+ local original_name = output_name
+
+ -- If compression is needed, adjust the output name to exclude extensions like ".tar"
+ if archive_compress ~= "" then
+ output_name = output_name:match("(.*%.tar)") or output_name
+ end
+
+ -- Create a temporary directory for intermediate files
+ local temp_dir_name = ".tmp_compress"
+ local temp_dir = combine_url(output_dir, temp_dir_name)
+ temp_dir = tostring(fs.unique_name(Url(temp_dir)))
+
+ -- Attempt to create the temporary directory
+ local temp_dir_status, temp_dir_err = fs.create("dir_all", Url(temp_dir))
+ if not temp_dir_status then
+ -- Notify the user if the temporary directory creation fails
+ notify(string.format("Failed to create temp directory, error code: %s", tostring(temp_dir_err)), "error")
+ return
+ end
+
+ -- Define the temporary output file path within the temporary directory
+ local temp_output_url = combine_url(temp_dir, output_name)
+
+ -- Add files to the output archive
+ for filepath, filenames in pairs(path_fnames) do
+ -- Execute the archive command for each path and its respective files
+ local archive_status, archive_err =
+ Command(archive_cmd):arg(archive_args):arg(temp_output_url):arg(filenames):cwd(filepath):spawn():wait()
+ if not archive_status or not archive_status.success then
+ -- Notify the user if the archiving process fails and clean up the temporary directory
+ notify(
+ string.format(
+ "Failed to create archive %s with '%s', error: %s",
+ ya.quote(output_name),
+ archive_cmd,
+ tostring(archive_err)
+ ),
+ "error"
+ )
+ cleanup_temp_dir(temp_dir)
+ return
+ end
+ end
+
+ -- If compression is required, execute the compression command
+ if archive_compress ~= "" then
+ local compress_status, compress_err
+
+ -- Check if using 7z for compression (requires output file argument)
+ if archive_compress:match("^7z") then
+ local compressed_output = combine_url(temp_dir, original_name)
+ compress_status, compress_err = Command(archive_compress)
+ :arg(archive_compress_args)
+ :arg(compressed_output)
+ :arg(temp_output_url)
+ :spawn()
+ :wait()
+ else
+ -- Native compression tools (gzip, xz, bzip2, etc.) compress in-place
+ compress_status, compress_err =
+ Command(archive_compress):arg(archive_compress_args):arg(temp_output_url):spawn():wait()
+ end
+
+ if not compress_status or not compress_status.success then
+ -- Notify the user if the compression process fails and clean up the temporary directory
+ notify(
+ string.format(
+ "Failed to compress archive %s with '%s', error: %s",
+ ya.quote(output_name),
+ archive_compress,
+ tostring(compress_err)
+ ),
+ "error"
+ )
+ cleanup_temp_dir(temp_dir)
+ return
+ end
+ end
+
+ -- Move the final file from the temporary directory to the output directory
+ local final_output_url = combine_url(output_dir, original_name)
+ local temp_url_processed = combine_url(temp_dir, original_name)
+ final_output_url = tostring(fs.unique_name(Url(final_output_url)))
+ local from, to = Url(temp_url_processed), Url(final_output_url)
+ local move_status, move_err = fs.rename(from, to)
+ if not move_status then
+ if move_err and move_err.kind == "CrossesDevices" then
+ local copy_status, copy_err = fs.copy(from, to)
+ if not copy_status then
+ notify(
+ string.format(
+ "Failed to copy across devices %s to %s, error: %s",
+ ya.quote(from.name),
+ ya.quote(to.name),
+ copy_err and tostring(copy_err.kind) or "unknown"
+ ),
+ "error"
+ )
+ cleanup_temp_dir(temp_dir)
+ return
+ end
+ else
+ notify(
+ string.format(
+ "Failed to move %s to %s, error: %s",
+ ya.quote(from.name),
+ ya.quote(to.name),
+ move_err and tostring(move_err.kind) or "unknown"
+ ),
+ "error"
+ )
+ cleanup_temp_dir(temp_dir)
+ return
+ end
+ end
+
+ -- Cleanup the temporary directory after successful operation
+ cleanup_temp_dir(temp_dir)
+
+ -- Notify user of success
+ if not is_silent_success then
+ notify(string.format("Successfully created archive: %s", ya.quote(to.name)), "info")
+ end
+ end,
+}
diff --git a/config/yazi/plugins/full-border.yazi/LICENSE b/config/yazi/plugins/full-border.yazi/LICENSE
new file mode 100644
index 00000000..fb5b1d62
--- /dev/null
+++ b/config/yazi/plugins/full-border.yazi/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 yazi-rs
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/config/yazi/plugins/full-border.yazi/README.md b/config/yazi/plugins/full-border.yazi/README.md
new file mode 100644
index 00000000..269ca8ec
--- /dev/null
+++ b/config/yazi/plugins/full-border.yazi/README.md
@@ -0,0 +1,32 @@
+# full-border.yazi
+
+Add a full border to Yazi to make it look fancier.
+
+![full-border](https://github.com/yazi-rs/plugins/assets/17523360/ef81b560-2465-4d36-abf2-5d21dcb7b987)
+
+## Installation
+
+```sh
+ya pkg add yazi-rs/plugins:full-border
+```
+
+## Usage
+
+Add this to your `init.lua` to enable the plugin:
+
+```lua
+require("full-border"):setup()
+```
+
+Or you can customize the border type:
+
+```lua
+require("full-border"):setup {
+ -- Available values: ui.Border.PLAIN, ui.Border.ROUNDED
+ type = ui.Border.ROUNDED,
+}
+```
+
+## License
+
+This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file.
diff --git a/config/yazi/plugins/full-border.yazi/main.lua b/config/yazi/plugins/full-border.yazi/main.lua
new file mode 100644
index 00000000..501156d7
--- /dev/null
+++ b/config/yazi/plugins/full-border.yazi/main.lua
@@ -0,0 +1,53 @@
+--- @since 25.2.26
+
+local function setup(_, opts)
+ local type = opts and opts.type or ui.Border.ROUNDED
+ local old_build = Tab.build
+
+ Tab.build = function(self, ...)
+ local bar = function(c, x, y)
+ if x <= 0 or x == self._area.w - 1 or th.mgr.border_symbol ~= "│" then
+ return ui.Bar(ui.Edge.TOP)
+ end
+
+ return ui.Bar(ui.Edge.TOP)
+ :area(
+ ui.Rect { x = x, y = math.max(0, y), w = ya.clamp(0, self._area.w - x, 1), h = math.min(1, self._area.h) }
+ )
+ :symbol(c)
+ end
+
+ local c = self._chunks
+ self._chunks = {
+ c[1]:pad(ui.Pad.y(1)),
+ -- TODO: remove this compatibility hack
+ fs.unique and c[2]:pad(ui.Pad.y(1)) or c[2]:pad(ui.Pad(1, c[3].w > 0 and 0 or 1, 1, c[1].w > 0 and 0 or 1)),
+ c[3]:pad(ui.Pad.y(1)),
+ }
+
+ local style = th.mgr.border_style
+ if rt.opener then -- TODO: remove this compatibility hack
+ self._base = ya.list_merge(self._base or {}, {
+ ui.Border(ui.Edge.ALL):area(self._area):type(type):style(style),
+
+ bar("┬", c[2].x, c[1].y),
+ bar("┴", c[2].x, c[1].bottom - 1),
+ bar("┬", c[2].right - 1, c[2].y),
+ bar("┴", c[2].right - 1, c[2].bottom - 1),
+ })
+ else
+ self._base = ya.list_merge(self._base or {}, {
+ ui.Border(ui.Edge.ALL):area(self._area):type(type):style(style),
+
+ bar("┬", c[1].right - 1, c[1].y),
+ bar("┴", c[1].right - 1, c[1].bottom - 1),
+ bar("┬", c[2].right, c[2].y),
+ bar("┴", c[2].right, c[2].bottom - 1),
+ })
+ end
+
+ old_build(self, ...)
+ end
+end
+
+return { setup = setup }
diff --git a/config/yazi/plugins/git.yazi/LICENSE b/config/yazi/plugins/git.yazi/LICENSE
new file mode 100644
index 00000000..fb5b1d62
--- /dev/null
+++ b/config/yazi/plugins/git.yazi/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 yazi-rs
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/config/yazi/plugins/git.yazi/README.md b/config/yazi/plugins/git.yazi/README.md
new file mode 100644
index 00000000..042bac6c
--- /dev/null
+++ b/config/yazi/plugins/git.yazi/README.md
@@ -0,0 +1,89 @@
+# git.yazi
+
+Show the status of Git file changes as linemode in the file list.
+
+https://github.com/user-attachments/assets/34976be9-a871-4ffe-9d5a-c4cdd0bf4576
+
+## Installation
+
+```sh
+ya pkg add yazi-rs/plugins:git
+```
+
+## Setup
+
+Add the following to your `~/.config/yazi/init.lua`:
+
+```lua
+require("git"):setup {
+ -- Order of status signs showing in the linemode
+ order = 1500,
+}
+```
+
+And register it as fetchers in your `~/.config/yazi/yazi.toml`:
+
+```toml
+[[plugin.prepend_fetchers]]
+id = "git" # Remove if Yazi > v26.1.22
+url = "*"
+run = "git"
+group = "git"
+
+[[plugin.prepend_fetchers]]
+id = "git" # Remove if Yazi > v26.1.22
+url = "*/"
+run = "git"
+group = "git"
+```
+
+## Advanced
+
+> [!NOTE]
+> The following configuration must be put before `require("git"):setup()`
+
+You can customize the [Style](https://yazi-rs.github.io/docs/plugins/layout#style) of the status sign with:
+
+- `[git].unknown` - status cannot/not yet determined
+- `[git].modified` - modified file
+- `[git].added` - added file
+- `[git].untracked` - untracked file
+- `[git].ignored` - ignored file
+- `[git].deleted` - deleted file
+- `[git].updated` - updated file
+- `[git].clean` - clean file
+
+For example:
+
+```toml
+# theme.toml / flavor.toml
+[git]
+modified = { fg = "blue" }
+deleted = { fg = "red", bold = true }
+```
+
+You can also customize the text of the status sign with:
+
+- `[git].unknown_sign` - status cannot/not yet determined
+- `[git].modified_sign` - modified file
+- `[git].added_sign` - added file
+- `[git].untracked_sign` - untracked file
+- `[git].ignored_sign` - ignored file
+- `[git].deleted_sign` - deleted file
+- `[git].updated_sign` - updated file
+- `[git].clean_sign` - clean file
+
+For example:
+
+```toml
+# theme.toml / flavor.toml
+[git]
+unknown_sign = " "
+modified_sign = "M"
+deleted_sign = "D"
+clean_sign = "✔"
+```
+
+## License
+
+This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file.
diff --git a/config/yazi/plugins/git.yazi/main.lua b/config/yazi/plugins/git.yazi/main.lua
new file mode 100644
index 00000000..19f5c445
--- /dev/null
+++ b/config/yazi/plugins/git.yazi/main.lua
@@ -0,0 +1,259 @@
+--- @since 26.5.6
+
+local WINDOWS = ya.target_family() == "windows"
+
+-- The code of supported git status,
+-- also used to determine which status to show for directories when they contain different statuses
+-- see `bubble_up`
+---@enum CODES
+local CODES = {
+ unknown = 100, -- status cannot/not yet determined
+ excluded = 99, -- ignored directory
+ ignored = 6, -- ignored file
+ untracked = 5,
+ modified = 4,
+ added = 3,
+ deleted = 2,
+ updated = 1,
+ clean = 0,
+}
+
+local PATTERNS = {
+ { "!$", CODES.ignored },
+ { "?$", CODES.untracked },
+ { "[MT]", CODES.modified },
+ { "[AC]", CODES.added },
+ { "D", CODES.deleted },
+ { "U", CODES.updated },
+ { "[AD][AD]", CODES.updated },
+}
+
+---@param line string
+---@return CODES, string
+local function match(line)
+ local signs = line:sub(1, 2)
+ for _, p in ipairs(PATTERNS) do
+ local path, pattern, code = nil, p[1], p[2]
+ if signs:find(pattern) then
+ path = line:sub(4, 4) == '"' and line:sub(5, -2) or line:sub(4)
+ path = WINDOWS and path:gsub("/", "\\") or path
+ end
+ if not path then
+ elseif path:find("[/\\]$") then
+ -- Mark the ignored directory as `excluded`, so we can process it further within `propagate_down`
+ return code == CODES.ignored and CODES.excluded or code, path:sub(1, -2)
+ else
+ return code, path
+ end
+ ---@diagnostic disable-next-line: missing-return
+ end
+end
+
+---@param cwd Url
+---@return string?
+local function root(cwd)
+ local is_worktree = function(url)
+ local file, head = io.open(tostring(url)), nil
+ if file then
+ head = file:read(8)
+ file:close()
+ end
+ return head == "gitdir: "
+ end
+
+ repeat
+ local next = cwd:join(".git")
+ local cha = fs.cha(next)
+ if cha and (cha.is_dir or is_worktree(next)) then
+ return tostring(cwd)
+ end
+ cwd = cwd.parent
+ until not cwd
+end
+
+---@param changed Changes
+---@return Changes
+local function bubble_up(changed)
+ local new, empty = {}, Url("")
+ for path, code in pairs(changed) do
+ if code ~= CODES.ignored then
+ local url = Url(path).parent
+ while url and url ~= empty do
+ local s = tostring(url)
+ new[s] = (new[s] or CODES.clean) > code and new[s] or code
+ url = url.parent
+ end
+ end
+ end
+ return new
+end
+
+---@param excluded string[]
+---@param cwd Url
+---@param repo Url
+---@return Changes
+local function propagate_down(excluded, cwd, repo)
+ local new, rel = {}, cwd:strip_prefix(repo)
+ for _, path in ipairs(excluded) do
+ if rel:starts_with(path) then
+ -- If `cwd` is a subdirectory of an excluded directory, also mark it as `excluded`
+ new[tostring(cwd)] = CODES.excluded
+ elseif cwd == repo:join(path).parent then
+ -- If `path` is a direct subdirectory of `cwd`, mark it as `ignored`
+ new[path] = CODES.ignored
+ else
+ -- Skipping, we only care about `cwd` itself and its direct subdirectories for maximum performance
+ end
+ end
+ return new
+end
+
+---@param cwd string
+---@param repo string
+---@param changed Changes
+local add = ya.sync(function(st, cwd, repo, changed)
+ ---@cast st State
+
+ st.dirs[cwd] = repo
+ st.repos[repo] = st.repos[repo] or {}
+ for path, code in pairs(changed) do
+ if code == CODES.clean then
+ st.repos[repo][path] = nil
+ elseif code == CODES.excluded then
+ -- Mark the directory with a special value `excluded` so that it can be distinguished during UI rendering
+ st.dirs[path] = CODES.excluded
+ else
+ st.repos[repo][path] = code
+ end
+ end
+ ui.render()
+end)
+
+---@param cwd string
+local remove = ya.sync(function(st, cwd)
+ ---@cast st State
+
+ local repo = st.dirs[cwd]
+ if not repo then
+ return
+ end
+
+ ui.render()
+ st.dirs[cwd] = nil
+ if not st.repos[repo] then
+ return
+ end
+
+ for _, r in pairs(st.dirs) do
+ if r == repo then
+ return
+ end
+ end
+ st.repos[repo] = nil
+end)
+
+---@param st State
+---@param opts Options
+local function setup(st, opts)
+ st.dirs = {}
+ st.repos = {}
+
+ opts = opts or {}
+ opts.order = opts.order or 1500
+
+ local t = th.git or {}
+ local styles = {
+ [CODES.unknown] = t.unknown or ui.Style(),
+ [CODES.ignored] = t.ignored or ui.Style():fg("darkgray"),
+ [CODES.untracked] = t.untracked or ui.Style():fg("magenta"),
+ [CODES.modified] = t.modified or ui.Style():fg("yellow"),
+ [CODES.added] = t.added or ui.Style():fg("green"),
+ [CODES.deleted] = t.deleted or ui.Style():fg("red"),
+ [CODES.updated] = t.updated or ui.Style():fg("yellow"),
+ [CODES.clean] = t.clean or ui.Style(),
+ }
+ local signs = {
+ [CODES.unknown] = t.unknown_sign or "",
+ [CODES.ignored] = t.ignored_sign or " ",
+ [CODES.untracked] = t.untracked_sign or "? ",
+ [CODES.modified] = t.modified_sign or " ",
+ [CODES.added] = t.added_sign or " ",
+ [CODES.deleted] = t.deleted_sign or " ",
+ [CODES.updated] = t.updated_sign or " ",
+ [CODES.clean] = t.clean_sign or "",
+ }
+
+ Linemode:children_add(function(self)
+ if not self._file.in_current then
+ return ""
+ end
+
+ local url = self._file.url
+ local repo = st.dirs[tostring(url.base or url.parent)]
+ local code = CODES.unknown
+ if repo then
+ code = repo == CODES.excluded and CODES.ignored or st.repos[repo][tostring(url):sub(#repo + 2)] or CODES.clean
+ end
+
+ if signs[code] == "" then
+ return ""
+ elseif self._file.is_hovered then
+ return ui.Line { " ", signs[code] }
+ else
+ return ui.Line { " ", ui.Span(signs[code]):style(styles[code]) }
+ end
+ end, opts.order)
+end
+
+---@type UnstableFetcher
+local function fetch(_, job)
+ local cwd = job.files[1].url.base or job.files[1].url.parent
+ local repo = root(cwd)
+ if not repo then
+ remove(tostring(cwd))
+ return true
+ end
+
+ local paths = {}
+ for _, file in ipairs(job.files) do
+ paths[#paths + 1] = tostring(file.url)
+ end
+
+ -- stylua: ignore
+ local output, err = Command("git")
+ :cwd(tostring(cwd))
+ :arg({ "--no-optional-locks", "-c", "core.quotePath=", "status", "--porcelain", "-unormal", "--no-renames", "--ignored=matching" })
+ :arg(paths)
+ :output()
+ if not output then
+ return true, Err("Cannot spawn `git` command, error: %s", err)
+ end
+
+ local changed, excluded = {}, {}
+ for line in output.stdout:gmatch("[^\r\n]+") do
+ local code, path = match(line)
+ if code == CODES.excluded then
+ excluded[#excluded + 1] = path
+ else
+ changed[path] = code
+ end
+ end
+
+ if job.files[1].cha.is_dir then
+ ya.dict_merge(changed, bubble_up(changed))
+ end
+ ya.dict_merge(changed, propagate_down(excluded, cwd, Url(repo)))
+
+ -- Reset the status of any files that don't appear in the output of `git status` to `clean`,
+ -- so that cleaning up outdated statuses from `st.repos`
+ for _, path in ipairs(paths) do
+ local s = path:sub(#repo + 2)
+ changed[s] = changed[s] or CODES.clean
+ end
+
+ add(tostring(cwd), repo, changed)
+
+ return false
+end
+
+return { setup = setup, fetch = fetch }
diff --git a/config/yazi/plugins/git.yazi/types.lua b/config/yazi/plugins/git.yazi/types.lua
new file mode 100644
index 00000000..99368495
--- /dev/null
+++ b/config/yazi/plugins/git.yazi/types.lua
@@ -0,0 +1,12 @@
+---@class State
+---@field dirs table<string, string|CODES> Mapping between a directory and its corresponding repository
+---@field repos table<string, Changes> Mapping between a repository and the status of each of its files
+
+---@class Options
+---@field order number The order in which the status is displayed
+---@field renamed boolean Whether to include renamed files in the status (or treat them as modified)
+
+-- TODO: move this to `types.yazi` once it's get stable
+---@alias UnstableFetcher fun(self: unknown, job: { files: File[] }): boolean, Error?
+
+---@alias Changes table<string, CODES>
diff --git a/config/yazi/plugins/smart-filter.yazi/LICENSE b/config/yazi/plugins/smart-filter.yazi/LICENSE
new file mode 100644
index 00000000..fb5b1d62
--- /dev/null
+++ b/config/yazi/plugins/smart-filter.yazi/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 yazi-rs
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/config/yazi/plugins/smart-filter.yazi/README.md b/config/yazi/plugins/smart-filter.yazi/README.md
new file mode 100644
index 00000000..29653394
--- /dev/null
+++ b/config/yazi/plugins/smart-filter.yazi/README.md
@@ -0,0 +1,28 @@
+# smart-filter.yazi
+
+A Yazi plugin that makes filters smarter: continuous filtering, automatically enter unique directory, open file on submitting.
+
+https://github.com/yazi-rs/plugins/assets/17523360/72aaf117-1378-4f7e-93ba-d425a79deac5
+
+## Installation
+
+```sh
+ya pkg add yazi-rs/plugins:smart-filter
+```
+
+## Usage
+
+Add this to your `~/.config/yazi/keymap.toml`:
+
+```toml
+[[mgr.prepend_keymap]]
+on = "F"
+run = "plugin smart-filter"
+desc = "Smart filter"
+```
+
+Note that, the keybindings above are just examples, please tune them up as needed to ensure they don't conflict with your other actions/plugins.
+
+## License
+
+This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file.
diff --git a/config/yazi/plugins/smart-filter.yazi/main.lua b/config/yazi/plugins/smart-filter.yazi/main.lua
new file mode 100644
index 00000000..2d1c3cde
--- /dev/null
+++ b/config/yazi/plugins/smart-filter.yazi/main.lua
@@ -0,0 +1,50 @@
+--- @since 25.12.29
+
+local hovered = ya.sync(function()
+ local h = cx.active.current.hovered
+ if not h then
+ return {}
+ end
+
+ return {
+ url = h.url,
+ is_dir = h.cha.is_dir,
+ unique = #cx.active.current.files == 1,
+ }
+end)
+
+local function prompt()
+ return ya.input {
+ title = "Smart filter:",
+ pos = { "center", w = 50 },
+ realtime = true,
+ debounce = 0.1,
+ }
+end
+
+local function entry()
+ local input = prompt()
+
+ while true do
+ local value, event = input:recv()
+ if event ~= 1 and event ~= 3 then
+ ya.emit("escape", { filter = true })
+ break
+ end
+
+ ya.emit("filter_do", { value, smart = true })
+
+ local h = hovered()
+ if h.unique and h.is_dir then
+ ya.emit("escape", { filter = true })
+ ya.emit("enter", {})
+ input = prompt()
+ elseif event == 1 then
+ ya.emit("escape", { filter = true })
+ ya.emit(h.is_dir and "enter" or "open", { h.url })
+ break
+ end
+ end
+end
+
+return { entry = entry }
diff --git a/config/yazi/plugins/yatline-githead.yazi/LICENSE b/config/yazi/plugins/yatline-githead.yazi/LICENSE
new file mode 100644
index 00000000..0c37e850
--- /dev/null
+++ b/config/yazi/plugins/yatline-githead.yazi/LICENSE
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright (c) 2024 imsi32
+Copyright (c) 2024 llanosrocas
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/config/yazi/plugins/yatline-githead.yazi/README.md b/config/yazi/plugins/yatline-githead.yazi/README.md
new file mode 100644
index 00000000..e2af22e2
--- /dev/null
+++ b/config/yazi/plugins/yatline-githead.yazi/README.md
@@ -0,0 +1,213 @@
+# yatline-githead.yazi
+
+Manual clone of [githead.yazi](https://github.com/llanosrocas/githead.yazi) for supporting [yatline.yazi](https://github.com/imsi32/yatline.yazi)
+
+> [!IMPORTANT]
+> This repository will not add new features other than coming from original repository.
+> The latest commit in there is 317d09f728928943f0af72ff6ce31ea335351202.
+> Which can be found in [here](https://github.com/llanosrocas/githead.yazi/commit/317d09f728928943f0af72ff6ce31ea335351202)
+
+All supported features are listed [here](#features)
+
+## Requirements
+
+- yazi version >= 25.5.28.
+- Font with symbol support. For example [Nerd Fonts](https://www.nerdfonts.com/).
+- [yatline.yazi](https://github.com/imsi32/yatline.yazi) (Mandatory)
+
+> [!IMPORTANT]
+> Recommended to use [githead.yazi](https://github.com/llanosrocas/githead.yazi), if you are not using yatline.yazi
+
+## Installation
+
+```sh
+ya pkg add imsi32/yatline-githead
+```
+
+## Usage
+
+Add this to your `~/.config/yazi/init.lua`, after yatline.yazi configuration:
+
+```lua
+require("yatline-githead"):setup()
+```
+
+### Default Configuration
+
+```lua
+require("yatline-githead"):setup({
+ order = {
+ "branch",
+ "remote",
+ "tag",
+ "commit",
+ "behind_ahead_remote",
+ "stashes",
+ "state",
+ "staged",
+ "unstaged",
+ "untracked",
+ },
+
+ show_numbers = true, -- shows staged, unstaged, untracked, stashes count
+
+ show_branch = true,
+ branch_prefix = "",
+ branch_color = "blue",
+ branch_symbol = "",
+ branch_borders = "",
+
+ show_remote_branch = true, -- only shown if different from local branch
+ always_show_remote_branch = false, -- always show remote branch even if it the same as local branch
+ always_show_remote_repo = false, -- Adds `origin/` if `always_show_remote_branch` is enabled
+ remote_branch_prefix = ":",
+ remote_branch_color = "bright magenta",
+
+ show_tag = true, -- only shown if branch is not available
+ always_show_tag = false,
+ tag_color = "magenta",
+ tag_symbol = "#",
+
+ show_commit = true, -- only shown if branch AND tag are not available
+ always_show_commit = false,
+ commit_color = "bright magenta",
+ commit_symbol = "@",
+
+ show_behind_ahead_remote = true,
+ behind_remote_color = "bright magenta",
+ behind_remote_symbol = "⇣",
+ ahead_remote_color = "bright magenta",
+ ahead_remote_symbol = "⇡",
+
+ show_stashes = true,
+ stashes_color = "bright magenta",
+ stashes_symbol = "$",
+
+ show_state = true,
+ show_state_prefix = true,
+ state_color = "red",
+ state_symbol = "~",
+
+ show_staged = true,
+ staged_color = "bright yellow",
+ staged_symbol = "+",
+
+ show_unstaged = true,
+ unstaged_color = "bright yellow",
+ unstaged_symbol = "!",
+
+ show_untracked = true,
+ untracked_color = "blue",
+ untracked_symbol = "?",
+})
+```
+
+### Theme
+
+You can also use a [theme](https://github.com/imsi32/yatline-themes):
+
+```lua
+local your_theme = {
+ branch_color = "blue",
+ remote_branch_color = "bright magenta",
+ tag_color = "magenta",
+ commit_color = "bright magenta",
+ behind_remote_color = "bright magenta",
+ ahead_remote_color = "bright magenta",
+ stashes_color = "bright magenta",
+ state_color = "red",
+ staged_color = "bright yellow",
+ unstaged_color = "bright yellow",
+ untracked_color = "blue",
+}
+
+require("yatline-githead"):setup({
+-- ===
+
+ theme = your_theme,
+
+-- ===
+})
+```
+
+### Adding as a Component
+
+If you are using yatline.yazi, you can use this component:
+
+``` lua
+-- ===
+
+ {type = "coloreds", custom = false, name = "githead"},
+
+-- ===
+```
+
+``` text
+/cwd on ( feature):origin/main #v1.0.0 #1234567 ⇣2⇡3 $1 rebase 1/2 ~2 +4 !1 ?5
+| | | | ││ | | | | | | | | | | | |
+| | | | ││ | | | | | | | | | | | └─── untracked_symbol
+| | | | ││ | | | | | | | | | | └────── unstaged_symbol
+| | | | ││ | | | | | | | | | └───────── staged_symbol
+| | | | ││ | | | | | | | | └──────────── state_symbol
+| | | | ││ | | | | | | | └─────────────────────── state_prefix
+| | | | ││ | | | | | | └────────────────────────── stashes_symbol
+| | | | ││ | | | | | └───────────────────────────── ahead_symbol
+| | | | ││ | | | | └─────────────────────────────── behind_symbol
+| | | | ││ | | | └──────────────────────────────────────── commit_symbol
+| | | | ││ | | └──────────────────────────────────────────────── tag_symbol
+| | | | ││ | └───────────────────────────────────────────────────── remote_branch
+| | | | ││ └─────────────────────────────────────────────────────────── remote_repo
+| | | | |└───────────────────────────────────────────────────────────── remote_branch_prefix
+| | | | └────────────────────────────────────────────────────────────── branch_borders
+| | | └──────────────────────────────────────────────────────────────────── branch
+| | └─────────────────────────────────────────────────────────────────────── branch_symbol
+| └─────────────────────────────────────────────────────────────────────────── branch_prefix
+└──────────────────────────────────────────────────────────────────────────────── cwd
+```
+
+## Features
+
+- [x] Current branch
+- [x] Remote and remote branch
+- [x] Latest tag
+- [x] Latest commit
+- [x] Behind/Ahead of the remote
+- [x] Stashes
+- [x] States
+ - [x] merge
+ - [x] cherry
+ - [x] rebase (+ done counter)
+ - [x] revert
+ - [x] bisect
+- [x] Staged
+- [x] Unstaged
+- [x] Untracked
+
+### Under the hood
+
+The goal is to use minimum amount of shell commands.
+
+- Branch, stashes, staged files, unstaged files, untracked files.
+
+```shell
+git status --ignore-submodules=dirty --branch --show-stash --ahead-behind
+```
+
+- Remote branch and repo:
+
+```shell
+git rev-parse --abbrev-ref --symbolic-full-name @{upstream}
+```
+
+- Latest tag and commit:
+
+```shell
+git log --format="commit %h%d" -n 1
+```
+
+## Credits
+
+- [githead.yazi](https://github.com/llanosrocas/githead.yazi)
+- [yazi source code](https://github.com/sxyazi/yazi)
+- [powerlevel10k](https://github.com/romkatv/powerlevel10k)
+- [twio142](https://github.com/twio142/githead.yazi)
diff --git a/config/yazi/plugins/yatline-githead.yazi/main.lua b/config/yazi/plugins/yatline-githead.yazi/main.lua
new file mode 100644
index 00000000..ab49987f
--- /dev/null
+++ b/config/yazi/plugins/yatline-githead.yazi/main.lua
@@ -0,0 +1,569 @@
+---@diagnostic disable: undefined-global
+
+local save = ya.sync(function(this, cwd, output)
+ if cwd:match("%.git[/\\]") or cwd:match("%.git$") then
+ this.output = nil
+ return
+ end
+ if cx.active.current.cwd == Url(cwd) then
+ ---@type GitStatusData
+ this.output = output
+ ui.render()
+ end
+end)
+
+return {
+ setup = function(this, options)
+ options = options or {}
+
+ local config = {
+ order = options.order or {
+ "branch",
+ "remote_branch",
+ "tag",
+ "commit",
+ "behind_ahead_remote",
+ "stashes",
+ "state",
+ "staged",
+ "unstaged",
+ "untracked",
+ },
+
+ show_numbers = options.show_numbers == nil and true or options.show_numbers,
+
+ show_branch = options.show_branch == nil and true or options.show_branch,
+ branch_prefix = options.branch_prefix or "",
+ branch_symbol = options.branch_symbol or "",
+ branch_borders = options.branch_borders or "",
+
+ show_remote_branch = options.show_remote_branch == nil and true or options.show_remote_branch,
+ always_show_remote_branch = options.always_show_remote_branch == nil and false
+ or options.always_show_remote_branch,
+ always_show_remote_repo = options.always_show_remote_repo == nil and false
+ or options.always_show_remote_repo,
+ remote_branch_prefix = options.remote_branch_prefix or ":",
+
+ show_tag = options.show_tag == nil and true or options.show_tag,
+ always_show_tag = options.always_show_tag == nil and false or options.always_show_tag,
+ tag_symbol = options.tag_symbol == nil and "#" or options.tag_symbol,
+
+ show_commit = options.show_commit == nil and true or options.show_commit,
+ always_show_commit = options.always_show_commit == nil and false or options.always_show_commit,
+ commit_symbol = options.commit_symbol == nil and "@" or options.commit_symbol,
+
+ show_behind_ahead_remote = options.show_behind_ahead_remote == nil and true
+ or options.show_behind_ahead_remote,
+ behind_remote_symbol = options.behind_remote_symbol or "⇣",
+ ahead_remote_symbol = options.ahead_remote_symbol or "⇡",
+
+ show_stashes = options.show_stashes == nil and true or options.show_stashes,
+ stashes_symbol = options.stashes_symbol or "$",
+
+ show_state = options.show_state == nil and true or options.show_state,
+ show_state_prefix = options.show_state_prefix == nil and true or options.show_state_prefix,
+ state_symbol = options.state_symbol or "~",
+
+ show_staged = options.show_staged == nil and true or options.show_staged,
+ staged_symbol = options.staged_symbol or "+",
+
+ show_unstaged = options.show_unstaged == nil and true or options.show_unstaged,
+ unstaged_symbol = options.unstaged_symbol or "!",
+
+ show_untracked = options.show_untracked == nil and true or options.show_untracked,
+ untracked_symbol = options.untracked_symbol or "?",
+ }
+
+ if options.theme then
+ options = options.theme
+ end
+
+ local theme = {
+ branch_color = options.branch_color or "blue",
+ remote_branch_color = options.remote_branch_color or "bright magenta",
+ tag_color = options.tag_color or "magenta",
+ commit_color = options.commit_color or "bright magenta",
+ behind_remote_color = options.behind_remote_color or "bright magenta",
+ ahead_remote_color = options.ahead_remote_color or "bright magenta",
+ stashes_color = options.stashes_color or "bright magenta",
+ state_color = options.state_color or "red",
+ staged_color = options.staged_color or "bright yellow",
+ unstaged_color = options.unstaged_color or "bright yellow",
+ untracked_color = options.untracked_color or "bright blue",
+ }
+
+ local function render_branch()
+ local branch = this.output.branch
+
+ if not branch then
+ return nil
+ end
+
+ local left_border = config.branch_borders:sub(1, 1)
+ local right_border = config.branch_borders:sub(2, 2)
+
+ local branch_string = ""
+
+ if config.branch_symbol == "" then
+ branch_string = left_border .. branch .. right_border
+ else
+ branch_string = left_border .. config.branch_symbol .. branch .. right_border
+ end
+
+ local branch_prefix = config.branch_prefix == "" and "" or config.branch_prefix .. " "
+
+ return {
+ { branch_prefix, nil },
+ { branch_string, theme.branch_color },
+ }
+ end
+
+ local function render_remote_branch()
+ local branch = this.output.branch
+ local remote_branch = this.output.remote_branch
+ local remote_repo = this.output.remote_repo
+
+ if not remote_branch then
+ return nil
+ end
+
+ local show_remote = config.always_show_remote_branch or branch ~= remote_branch
+ if not show_remote then
+ return nil
+ end
+
+ local remote_branch_label = config.always_show_remote_repo and (remote_repo .. "/" .. remote_branch)
+ or remote_branch
+
+ return {
+ { config.remote_branch_prefix, nil },
+ { remote_branch_label, theme.remote_branch_color },
+ }
+ end
+
+ local function render_tag()
+ local branch = this.output.branch
+ local tag = this.output.tag
+
+ if not tag then
+ return nil
+ end
+
+ if not branch or config.always_show_tag then
+ return {
+ { config.tag_symbol, nil },
+ { tag, theme.tag_color },
+ }
+ end
+ end
+
+ local function render_commit()
+ local branch = this.output.branch
+ local tag = this.output.tag
+ local commit = this.output.commit
+
+ if not commit then
+ return nil
+ end
+
+ if (not branch and not tag) or config.always_show_commit then
+ return {
+ { config.commit_symbol, nil },
+ { commit, theme.commit_color },
+ }
+ end
+ end
+
+ local function render_behind_ahead_remote()
+ local behind = this.output.behind_remote
+ local ahead = this.output.ahead_remote
+
+ local behind_label = behind
+ and behind > 0
+ and {
+ config.behind_remote_symbol .. (config.show_numbers and behind or ""),
+ theme.behind_remote_color,
+ }
+
+ local ahead_label = ahead
+ and ahead > 0
+ and {
+ config.ahead_remote_symbol .. (config.show_numbers and ahead or ""),
+ theme.ahead_remote_color,
+ }
+
+ if ahead_label and behind_label then
+ return {
+ behind_label,
+ ahead_label,
+ }
+ elseif ahead_label then
+ return ahead_label
+ elseif behind_label then
+ return behind_label
+ else
+ return nil
+ end
+ end
+
+ local function render_stashes()
+ local stashes_count = this.output.stashes
+
+ if not stashes_count then
+ return nil
+ end
+
+ local stashes_label = config.stashes_symbol
+
+ if config.show_numbers then
+ stashes_label = stashes_label .. stashes_count
+ end
+
+ return { stashes_label, theme.stashes_color }
+ end
+
+ local function render_state()
+ local state_prefix = this.output.state_prefix
+ local unmerged_count = this.output.unmerged_count
+ local rebase_done = this.output.rebase_done
+ local rebase_total = this.output.rebase_total
+
+ if state_prefix then
+ local state_label = ""
+ if config.show_state_prefix then
+ state_label = state_prefix
+ if state_prefix == "rebase-i" and config.show_numbers and rebase_done and rebase_total then
+ state_label = state_label .. " " .. rebase_done .. "/" .. rebase_total
+ end
+ end
+
+ local unmerged_label = ""
+ local symbol = ""
+
+ if unmerged_count and unmerged_count > 0 then
+ symbol = " " .. config.state_symbol
+ if config.show_numbers then
+ unmerged_label = tostring(unmerged_count)
+ end
+ end
+
+ return { state_label .. symbol .. unmerged_label, theme.state_color }
+ end
+ return nil
+ end
+
+ local function render_staged()
+ local staged = this.output.staged
+
+ if staged then
+ local staged_label = config.staged_symbol
+
+ if config.show_numbers then
+ local filtered_staged = staged:gsub("^[%s]*%b()[%s]*", "")
+
+ local staged_count = 0
+ for line in filtered_staged:gmatch("[^\r\n]+") do
+ if line:match("%S") then
+ staged_count = staged_count + 1
+ end
+ end
+
+ staged_label = staged_label .. staged_count
+ end
+
+ return { staged_label, theme.staged_color }
+ end
+
+ return nil
+ end
+
+ local function render_unstaged()
+ local unstaged = this.output.unstaged
+
+ if unstaged then
+ local unstaged_label = config.unstaged_symbol
+
+ if config.show_numbers then
+ local filtered_unstaged = unstaged:gsub("^[%s]*%b()[\r\n]*", ""):gsub("^[%s]*%b()[\r\n]*", "")
+
+ local unstaged_count = 0
+ for line in filtered_unstaged:gmatch("[^\r\n]+") do
+ if line:match("%S") then
+ unstaged_count = unstaged_count + 1
+ end
+ end
+
+ unstaged_label = unstaged_label .. unstaged_count
+ end
+
+ return { unstaged_label, theme.unstaged_color }
+ end
+
+ return nil
+ end
+
+ local function render_untracked()
+ local untracked = this.output.untracked
+
+ if untracked then
+ local untracked_label = config.untracked_symbol
+
+ if config.show_numbers then
+ local filtered_untracked = untracked:gsub("^[%s]*%b()[\r\n]*", "")
+ local untracked_count = 0
+
+ for line in filtered_untracked:gmatch("[^\r\n]+") do
+ if line:match("%S") then
+ untracked_count = untracked_count + 1
+ end
+ end
+
+ untracked_label = untracked_label .. untracked_count
+ end
+
+ return { untracked_label, theme.untracked_color }
+ end
+
+ return nil
+ end
+
+ function Yatline.coloreds.get:githead()
+ if not this.output then
+ return nil
+ end
+
+ local fn_table = {
+ branch = render_branch,
+ remote_branch = render_remote_branch,
+ tag = render_tag,
+ commit = render_commit,
+ behind_ahead_remote = render_behind_ahead_remote,
+ stashes = render_stashes,
+ state = render_state,
+ staged = render_staged,
+ unstaged = render_unstaged,
+ untracked = render_untracked,
+ }
+
+ local head = {}
+
+ for _, key in ipairs(config.order) do
+ local fn = fn_table[key]
+ local is_shown = config["show_" .. key]
+
+ if fn and is_shown then
+ local value = fn()
+ if value then
+ if #head ~= 0 and head[#head][1] ~= " " and head[#head][2] ~= "black" then
+ table.insert(head, { " ", "black" })
+ end
+ if type(value[1]) == "table" then
+ table.move(value, 1, #value, #head + 1, head)
+ else
+ table.insert(head, value)
+ end
+ end
+ end
+ end
+
+ if #head ~= 0 then
+ return head
+ else
+ return nil
+ end
+ end
+
+ local callback = function()
+ local cwd = cx.active.current.cwd
+ ya.emit("plugin", {
+ this._id,
+ ya.quote(tostring(cwd), true),
+ })
+ end
+
+ ps.sub("cd", callback)
+ ps.sub("rename", callback)
+ ps.sub("bulk", callback)
+ ps.sub("move", callback)
+ ps.sub("trash", callback)
+ ps.sub("delete", callback)
+ ps.sub("tab", callback)
+ end,
+
+ entry = function(_, job)
+ local args = job.args or job
+
+ ---@class GitStatusData
+ ---@field ahead_remote? integer
+ ---@field behind_remote? integer
+ ---@field branch? string
+ ---@field commit? string
+ ---@field rebase_done? integer
+ ---@field remote_branch? string
+ ---@field remote_repo? string
+ ---@field staged? string
+ ---@field stashes? integer
+ ---@field state_prefix? "bisect"|"cherry"|"merge"|"rebase-i"|"revert"
+ ---@field tag? string
+ ---@field unmerged_count? integer
+ ---@field unstaged? string
+ ---@field untracked? string
+ local data = {}
+
+ --- @param status string
+ local get_behind_ahead_remote = function(status)
+ local diverged_ahead, diverged_behind = status:match("have (%d+) and (%d+) different")
+ if diverged_ahead and diverged_behind then
+ data.behind_remote = tonumber(diverged_behind)
+ data.ahead_remote = tonumber(diverged_ahead)
+ else
+ local behind_remote = status:match("behind %S+ by (%d+) commits?")
+ local ahead_remote = status:match("ahead of %S+ by (%d+) commits?")
+
+ data.behind_remote = tonumber(behind_remote)
+ data.ahead_remote = tonumber(ahead_remote)
+ end
+ end
+
+ --- @param status string
+ local get_branch = function(status)
+ data.branch = status:match("On branch (%S+)")
+ end
+
+ --- @param status string
+ local get_stashes = function(status)
+ data.stashes = tonumber(status:match("Your stash currently has (%d+)"))
+ end
+
+ --- @param status string
+ local get_state = function(status)
+ local unmerged = status:match("Unmerged paths:%s*(.-)%s*\n\n")
+ if unmerged then
+ local filtered_unmerged = unmerged:gsub("^[%s]*%b()[%s]*", ""):gsub("^[%s]*%b()[%s]*", "")
+ local count = 0
+ for line in filtered_unmerged:gmatch("[^\r\n]+") do
+ if line:match("%S") then
+ count = count + 1
+ end
+ end
+ data.unmerged_count = count
+ end
+
+ if status:find("git merge") then
+ data.state_prefix = "merge"
+ elseif status:find("git cherry%-pick") then
+ data.state_prefix = "cherry"
+ elseif status:find("git rebase") then
+ data.state_prefix = "rebase-i"
+ local commands_done = status:match("%((%d+) commands? done%)")
+ if commands_done then
+ data.rebase_done = commands_done
+ if not data.unmerged_count then
+ data.rebase_total = commands_done
+ else
+ data.rebase_total = data.unmerged_count
+ end
+ end
+ elseif status:find("git revert") then
+ data.state_prefix = "revert"
+ elseif status:find("git bisect") then
+ data.state_prefix = "bisect"
+ end
+ end
+
+ --- @param status string
+ local get_staged = function(status)
+ data.staged = status:match("Changes to be committed:%s*(.-)%s*\n\n")
+ end
+
+ --- @param status string
+ local get_unstaged = function(status)
+ data.unstaged = status:match("Changes not staged for commit:%s*(.-)%s*\n\n")
+ end
+
+ --- @param status string
+ local get_untracked = function(status)
+ data.untracked = status:match("Untracked files:%s*(.-)%s*\n\n")
+ end
+
+ local get_status = function()
+ local cmd = Command("git")
+ :arg({
+ "status",
+ "--ignore-submodules=dirty",
+ "--branch",
+ "--show-stash",
+ "--ahead-behind",
+ })
+ :cwd(args[1])
+ :env("LANGUAGE", "en_US.UTF-8")
+ :stdout(Command.PIPED)
+ local cmd_output = cmd:output()
+
+ if cmd_output then
+ local status = cmd_output.stdout
+
+ get_branch(status)
+ get_behind_ahead_remote(status)
+ get_stashes(status)
+ get_state(status)
+ get_staged(status)
+ get_unstaged(status)
+ get_untracked(status)
+ end
+ end
+
+ local get_remote_branch = function()
+ local cmd = Command("git")
+ :arg({
+ "rev-parse",
+ "--abbrev-ref",
+ "--symbolic-full-name",
+ "@{upstream}",
+ })
+ :cwd(args[1])
+ :env("LANGUAGE", "en_US.UTF-8")
+ :stdout(Command.PIPED)
+ local cmd_output = cmd:output()
+
+ if cmd_output then
+ local remote_branch = cmd_output.stdout
+
+ data.remote_branch = remote_branch:gsub("[\r\n]", ""):match("^[^/]+/(.+)")
+ data.remote_repo = remote_branch:gsub("[\r\n]", ""):match("^([^/]+)/")
+ end
+ end
+
+ --- @param log string
+ local get_tag = function(log)
+ data.tag = log:match("tag: ([^, )]+)")
+ end
+
+ --- @param log string
+ local get_commit = function(log)
+ data.commit = log:match("^commit%s+([a-f0-9]+)")
+ end
+
+ local get_git_log = function()
+ local cmd = Command("git")
+ :arg({ "log", "--format=commit %h%d", "-n", "1" })
+ :cwd(args[1])
+ :env("LANGUAGE", "en_US.UTF-8")
+ :stdout(Command.PIPED)
+ local cmd_output = cmd:output()
+
+ if cmd_output then
+ local log = cmd_output.stdout
+
+ get_tag(log)
+ get_commit(log)
+ end
+ end
+
+ get_status()
+ get_remote_branch()
+ get_git_log()
+
+ save(args[1], data)
+ end,
+}
diff --git a/config/yazi/plugins/yatline.yazi/LICENSE b/config/yazi/plugins/yatline.yazi/LICENSE
new file mode 100644
index 00000000..6374a660
--- /dev/null
+++ b/config/yazi/plugins/yatline.yazi/LICENSE
@@ -0,0 +1,23 @@
+MIT License
+
+Copyright (c) 2024 imsi32
+Copyright (c) 2023 - sxyazi
+Copyright (c) 2023 yazi-rs
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/config/yazi/plugins/yatline.yazi/README.md b/config/yazi/plugins/yatline.yazi/README.md
new file mode 100644
index 00000000..1ee9c1eb
--- /dev/null
+++ b/config/yazi/plugins/yatline.yazi/README.md
@@ -0,0 +1,23 @@
+# yatline.yazi
+
+The first Yazi plugin for customizing both header-line and status-line.
+
+![yatline](https://github.com/user-attachments/assets/61013ec8-7fd9-42df-a9f4-f254663871fe)
+
+> [!NOTE]
+> Check out [wiki](https://github.com/imsi32/yatline.yazi/wiki) for installation steps, configuration and further information.
+
+## Features
+
+- Lualine-like Design
+- Flexible
+- Simple
+- Automatic Configuration
+- Support for Yazi Plugins
+- Themes (See: [yatline-themes](https://github.com/imsi32/yatline-themes))
+- Add-ons (See: [yatline-addons](https://github.com/imsi32/yatline-addons))
+
+## Credits
+
+- [Lualine](https://github.com/nvim-lualine/lualine.nvim)
+- [Yazi](https://github.com/sxyazi/yazi)
diff --git a/config/yazi/plugins/yatline.yazi/main.lua b/config/yazi/plugins/yatline.yazi/main.lua
new file mode 100644
index 00000000..eda7213b
--- /dev/null
+++ b/config/yazi/plugins/yatline.yazi/main.lua
@@ -0,0 +1,1464 @@
+--- @since 25.12.29
+--- @diagnostic disable: undefined-global, undefined-field
+--- @alias Mode Mode Comes from Yazi.
+--- @alias Rect Rect Comes from Yazi.
+--- @alias Paragraph Paragraph Comes from Yazi.
+--- @alias Line Line Comes from Yazi.
+--- @alias Span Span Comes from Yazi.
+--- @alias Color Color Comes from Yazi.
+
+--==================--
+-- Type Declaration --
+--==================--
+
+--- @enum Side
+local Side = {
+ LEFT = 0, -- The left side of either the header-line or status-line. [ LEFT ... ]
+ RIGHT = 1, -- The right side of either the header-line or status-line. [ ... RIGHT]
+}
+
+--- @enum SeparatorType
+local SeparatorType = {
+ OUTER = 0, -- Separators on the outer side of sections. [ c o | c o | c o ... ] or [ ... o c | o c | o c ]
+ INNER = 1, -- Separators on the inner side of sections. [ c i c | c i c | c i c ... ] or [ ... c i c | c i c | c i c ]
+}
+
+--- @enum ComponentType
+local ComponentType = {
+ A = 0, -- Components on the first section. [ A | | ... ] or [ ... | | A ]
+ B = 1, -- Components on the second section. [ | B | ... ] or [ ... | B | ]
+ C = 2, -- Components on the third section. [ | | C ... ] or [ ... C | | ]
+}
+
+--- @alias Colored [string, Color] Stores text and its foreground color.
+--- @alias Coloreds Colored[] The array of Coloreds.
+
+--- @generic T
+--- @alias T T Type of the component.
+
+--- @class Yatline
+--- @field config YatlineConfig Configuration of Yatline.
+--- @field string? {} Table that stores string components.
+--- @field line? {} Table that stores Line components.
+--- @field coloreds? {} Table that stores Coloreds components.
+Yatline = {}
+
+--- @class (exact) ComponentConfig
+--- @field type string Defines the type of the component (T).
+--- @field custom? boolean Toggles the usage of a function defined or name field.
+--- @field name string | T Either defined function name or variable of defined type T.
+--- @field params? {} Contains the parameters that can be used by the function called.
+
+--- @class (exact) SideConfig
+--- @field section_a ComponentConfig[] Array of configuration of components in the first section.
+--- @field section_b ComponentConfig[] Array of configuration of components in the second section.
+--- @field section_c ComponentConfig[] Array of configuration of components in the third section.
+
+--- @class (exact) LineConfig
+--- @field left SideConfig Configuration of the left side of the line.
+--- @field right SideConfig Configuration of the right side of the line.
+
+--- @class (exact) YatlineConfig
+--- @field section_separator {open: string, close: string} Separators that are between sections.
+--- @field part_separator {open: string, close: string} Separators that are between components.
+--- @field inverse_separator {open: string, close: string} Separators that are used when foreground color of separator is reset.
+--- @field padding {inner: integer, outer: integer} Number of space padding surronding the component.
+--- @field style_a {bg: Color, fg: Color, bg_mode: {normal: Color, select: Color, un_set: Color}} Style of the first section.
+--- @field style_b {bg: Color, fg: Color} Style of the second section.
+--- @field style_c {bg: Color, fg: Color} Style of the third section.
+--- @field permissions_t_fg Color Foreground color of the type of permission.
+--- @field permissions_r_fg Color Foreground color of the read permission.
+--- @field permissions_w_fg Color Foreground color of the write permission.
+--- @field permissions_x_fg Color Foreground color of the execute permission.
+--- @field permissions_s_fg Color Foreground color of the separators between permission.
+--- @field tab_width integer Maximum tab width of the tabs component.
+--- @field selected {icon: string, fg: Color} Configuration for the count of files that selected.
+--- @field copied {icon: string, fg: Color} Configuration for the count of files that copied.
+--- @field cut {icon: string, fg: Color} Configuration for the count of files that cut.
+--- @field files {icon: string, fg: Color} Configuration for the count of files in the active tab.
+--- @field filtereds {icon: string, fg: Color} Configuration for the count of files in the active tab that are filtered.
+--- @field total {icon: string, fg: Color} Configuration for the count of progress tasks that finished.
+--- @field success {icon: string, fg: Color} Configuration for the count of progress tasks that successed.
+--- @field failed {icon: string, fg: Color} Configuration for the count of progress tasks that failed.
+--- @field show_background boolean Toggle the visibility of the background where no component exists.
+--- @field display_header_line boolean Toggle the visibility of the header-line.
+--- @field display_status_line boolean Toggle the visibility of the status-line.
+--- @field component_positions string[] Arrange positions of the Yazi sections.
+--- @field header_line LineConfig Configuration of header-line components.
+--- @field status_line LineConfig Configuration of status-line components.
+Yatline.config = {
+ section_separator = { open = "", close = "" },
+ part_separator = { open = "", close = "" },
+ inverse_separator = { open = "", close = "" },
+
+ padding = { inner = 1, outer = 1 },
+
+ style_a = {
+ bg = "white",
+ fg = "black",
+ bg_mode = {
+ normal = "white",
+ select = "brightyellow",
+ un_set = "brightred",
+ },
+ },
+ style_b = { bg = "brightblack", fg = "brightwhite" },
+ style_c = { bg = "black", fg = "brightwhite" },
+
+ permissions_t_fg = "green",
+ permissions_r_fg = "yellow",
+ permissions_w_fg = "red",
+ permissions_x_fg = "cyan",
+ permissions_s_fg = "white",
+
+ tab_width = 20,
+
+ selected = { icon = "󰻭", fg = "yellow" },
+ copied = { icon = "", fg = "green" },
+ cut = { icon = "", fg = "red" },
+
+ files = { icon = "", fg = "blue" },
+ filtereds = { icon = "", fg = "magenta" },
+
+ total = { icon = "󰮍", fg = "yellow" },
+ success = { icon = "", fg = "green" },
+ failed = { icon = "", fg = "red" },
+
+ show_background = true,
+
+ display_header_line = true,
+ display_status_line = true,
+
+ component_positions = { "header", "tab", "status" },
+
+ header_line = {
+ left = {
+ section_a = {
+ { type = "line", name = "tabs" },
+ },
+ section_b = {},
+ section_c = {},
+ },
+ right = {
+ section_a = {
+ { type = "string", name = "date", params = { "%A, %d %B %Y" } },
+ },
+ section_b = {
+ { type = "string", name = "date", params = { "%X" } },
+ },
+ section_c = {},
+ },
+ },
+
+ status_line = {
+ left = {
+ section_a = {
+ { type = "string", name = "tab_mode" },
+ },
+ section_b = {
+ { type = "string", name = "hovered_size" },
+ },
+ section_c = {
+ { type = "string", name = "hovered_path" },
+ { type = "coloreds", name = "count" },
+ },
+ },
+ right = {
+ section_a = {
+ { type = "string", name = "cursor_position" },
+ },
+ section_b = {
+ { type = "string", name = "cursor_percentage" },
+ },
+ section_c = {
+ { type = "string", name = "hovered_file_extension", params = { true } },
+ { type = "coloreds", name = "permissions" },
+ },
+ },
+ },
+}
+
+--=================--
+-- Component Setup --
+--=================--
+
+--- Sets the background of style_a according to the tab's mode.
+--- @param mode Mode The mode of the active tab.
+--- @see cx.active.mode To get the active tab's mode.
+local function set_mode_style(mode)
+ if mode.is_select then
+ Yatline.config.style_a.bg = Yatline.config.style_a.bg_mode.select
+ elseif mode.is_unset then
+ Yatline.config.style_a.bg = Yatline.config.style_a.bg_mode.un_set
+ else
+ Yatline.config.style_a.bg = Yatline.config.style_a.bg_mode.normal
+ end
+end
+
+--- Helper function to apply style table to a component
+--- @param component Span The component to style
+--- @param style table The style table with fg and/or bg fields
+local function apply_style_table(component, style)
+ if not style then
+ return component
+ end
+ -- Apply manually
+ if style.fg then
+ component:fg(style.fg)
+ end
+ if style.bg then
+ component:bg(style.bg)
+ end
+ if style.bold then
+ component:bold()
+ end
+ if style.dim then
+ component:dim()
+ end
+ if style.italic then
+ component:italic()
+ end
+ if style.underline then
+ component:underline()
+ end
+ if style.blink then
+ component:blink()
+ end
+ if style.blink_rapid then
+ component:blink_rapid()
+ end
+ if style.reverse then
+ component:reverse()
+ end
+ if style.hidden then
+ component:hidden()
+ end
+ if style.crossed then
+ component:crossed()
+ end
+
+ return component
+end
+
+--- Helper function to apply style table to a component
+--- @param component Span The component to style
+--- @param style table The style table with fg and/or bg fields
+local function apply_style_table(component, style)
+ if not style then
+ return component
+ end
+ -- Apply manually
+ if style.fg then component:fg(style.fg) end
+ if style.bg then component:bg(style.bg) end
+ if style.bold then component:bold() end
+ if style.dim then component:dim() end
+ if style.italic then component:italic() end
+ if style.underline then component:underline() end
+ if style.blink then component:blink() end
+ if style.blink_rapid then component:blink_rapid() end
+ if style.reverse then component:reverse() end
+ if style.hidden then component:hidden() end
+ if style.crossed then component:crossed() end
+ return component
+end
+
+--- Sets the style of the component according to the its type.
+--- @param component Span Component that will be styled.
+--- @param component_type ComponentType Which section component will be in [ a | b | c ].
+--- @see Style To see how to style, in Yazi's documentation.
+local function set_component_style(component, component_type)
+ if component_type == ComponentType.A then
+ apply_style_table(component, Yatline.config.style_a):bold()
+ elseif component_type == ComponentType.B then
+ apply_style_table(component, Yatline.config.style_b)
+ else
+ apply_style_table(component, Yatline.config.style_c)
+ end
+end
+
+--- Surronds component with paddings.
+--- @param component string | Span | Line Component that will be connected to paddings.
+--- @param component_type ComponentType Which section component will be in [ a | b | c ].
+--- @param in_side Side Left or right side of the either header-line or status-line.
+--- @return Line line A Line which is a component that has padding.
+local function connect_padding(component, component_type, in_side)
+ local inner = ui.Span(string.rep(" ", Yatline.config.padding.inner))
+ local outer = ui.Span(string.rep(" ", Yatline.config.padding.outer))
+
+ set_mode_style(cx.active.mode)
+ set_component_style(inner, component_type)
+ set_component_style(outer, component_type)
+
+ if in_side == Side.LEFT then
+ return ui.Line({ outer, component, inner })
+ else
+ return ui.Line({ inner, component, outer })
+ end
+end
+
+--- Connects component to a separator.
+--- @param component Span Component that will be connected to separator.
+--- @param in_side Side Left or right side of the either header-line or status-line.
+--- @param separator_type SeparatorType Where will there be a separator in the section.
+--- @param separator_style {bg: string?, fg: string?} Holds the style of the separator.
+--- @return Line line A Line which may have either both component and separator, or component.
+local function connect_separator(component, in_side, separator_type, separator_style)
+ local open, close
+ if
+ separator_type == SeparatorType.OUTER and not (separator_style.bg == "reset" and separator_style.fg == "reset")
+ then
+ open = ui.Span(Yatline.config.section_separator.open)
+ close = ui.Span(Yatline.config.section_separator.close)
+
+ if separator_style.fg == "reset" then
+ if separator_style.bg ~= "" then
+ open = ui.Span(Yatline.config.inverse_separator.open)
+ close = ui.Span(Yatline.config.inverse_separator.close)
+
+ separator_style.fg, separator_style.bg = separator_style.bg, separator_style.fg
+ else
+ return ui.Line({ component })
+ end
+ end
+ else
+ open = ui.Span(Yatline.config.part_separator.open)
+ close = ui.Span(Yatline.config.part_separator.close)
+ end
+
+ apply_style_table(open, separator_style)
+ apply_style_table(close, separator_style)
+
+ if in_side == Side.LEFT then
+ return ui.Line({ component, close })
+ else
+ return ui.Line({ open, component })
+ end
+end
+
+--==================--
+-- Helper Functions --
+--==================--
+
+--- Gets the file name from given file extension.
+--- @param file_name string The name of a file whose extension will be taken.
+--- @return string file_extension Extension of a file.
+local function get_file_extension(file_name)
+ local extension = file_name:match("^.+%.(.+)$")
+
+ if extension == nil or extension == "" then
+ return "null"
+ else
+ return extension
+ end
+end
+
+--- Reverse the order of given array
+--- @param array Line Array which wants to be reversed.
+--- @return table reversed Reversed ordered given array.
+local function reverse_order(array)
+ local reversed = {}
+ for i = #array, 1, -1 do
+ table.insert(reversed, array[i])
+ end
+
+ return reversed
+end
+
+--- the number of characters in a UTF-8 string
+--- @param s string The string to process.
+--- @return integer The number of characters in the string.
+local function utf8len(s)
+ -- count the number of non-continuing bytes
+ return select(2, s:gsub("[^\128-\193]", ""))
+end
+
+--- like string.sub() but i, j are utf8 strings
+--- a utf8-safe string.sub()
+--- @param s string The string to process.
+--- @param i integer The start position.
+--- @param j integer The end position.
+--- @return string The substring.
+local function utf8sub(s, i, j)
+ -- pattern for matching UTF-8 characters
+ local pattern = "[%z\1-\127\194-\244][\128-\191]*"
+
+ -- helper function for position calculation
+ --- @param pos integer The position of the character.
+ --- @param len integer The length of the string.
+ --- @return integer The relative position of the character.
+ local function posrelat(pos, len)
+ if pos < 0 then
+ pos = len + pos + 1
+ end
+ return pos
+ end
+
+ -- helper function to iterate over UTF-8 chars
+ local function chars(_s, no_subs)
+ local function map(f)
+ local _i = 0
+ if no_subs then
+ for b, e in _s:gmatch("()" .. pattern .. "()") do
+ _i = _i + 1
+ local c = e - b
+ f(_i, c, b)
+ end
+ else
+ for b, c in _s:gmatch("()(" .. pattern .. ")") do
+ _i = _i + 1
+ f(_i, c, b)
+ end
+ end
+ end
+ return coroutine.wrap(function()
+ return map(coroutine.yield)
+ end)
+ end
+
+ local l = utf8len(s)
+
+ i = posrelat(i, l)
+ j = j and posrelat(j, l) or l
+
+ if i < 1 then
+ i = 1
+ end
+ if j > l then
+ j = l
+ end
+
+ if i > j then
+ return ""
+ end
+
+ local diff = j - i
+ local iter = chars(s, true)
+
+ -- advance up to i
+ for _ = 1, i - 1 do
+ iter()
+ end
+
+ local c, b = select(2, iter())
+
+ -- becareful with the edge case of empty string
+ if not b then
+ return ""
+ end
+
+ -- i and j are the same, single-character sub
+ if diff == 0 then
+ return string.sub(s, b, b + c - 1)
+ end
+
+ i = b
+
+ -- advance up to j
+ for _ = 1, diff - 1 do
+ iter()
+ end
+
+ c, b = select(2, iter())
+
+ return string.sub(s, i, b + c - 1)
+end
+
+--- Trims the filename if it is longer than the max_length.
+--- @param filename string The name of a file which will be trimmed.
+--- @param max_length integer Maximum length of the filename.
+--- @param trim_length integer Length of the trimmed filename.
+--- @return string trimmed_filename Trimmed filename.
+local function trim_filename(filename, max_length, trim_length)
+ if not max_length or not trim_length then
+ return filename
+ end
+
+ -- Count UTF-8 characters
+ local len = utf8len(filename)
+
+ if len <= max_length then
+ return filename
+ end
+
+ if len <= trim_length * 2 then
+ return filename
+ end
+
+ return utf8sub(filename, 1, trim_length) .. "..." .. utf8sub(filename, len - trim_length + 1, len)
+end
+
+--========================--
+-- Component String Group --
+--========================--
+
+Yatline.string = {}
+Yatline.string.get = {}
+Yatline.string.has_separator = true
+
+--- Creates a component from given string according to other parameters.
+--- @param string string The text which will be shown inside of the component.
+--- @param component_type ComponentType Which section component will be in [ a | b | c ].
+--- @return Line line Customized Line which follows desired style of the parameters.
+--- @see set_mode_style To know how mode style selected.
+--- @see set_component_style To know how component style applied.
+function Yatline.string.create(string, component_type)
+ local span = ui.Span(string)
+ set_mode_style(cx.active.mode)
+ set_component_style(span, component_type)
+
+ return ui.Line({ span })
+end
+
+--- Gets the hovered file's name of the current active tab.
+--- @param trimmed? boolean Whether to trim the filename if it's too long (default: false)
+--- @param max_length? integer Maximum length of the filename (default: 24)
+--- @param trim_length? integer Length of each end when trimming (default: 10)
+--- @param show_symlink? boolean Whether to show symlink target (default: false)
+--- @return string name Current active tab's hovered file's name
+function Yatline.string.get:hovered_name(trimmed, max_length, trim_length, show_symlink)
+ trimmed = trimmed or false
+ max_length = max_length or 24
+ trim_length = trim_length or 10
+ show_symlink = show_symlink or false
+
+ local hovered = cx.active.current.hovered
+ if not hovered then
+ return ""
+ end
+
+ local link_delimiter = " -> "
+ local linked = (show_symlink and hovered.link_to ~= nil) and (link_delimiter .. tostring(hovered.link_to)) or ""
+
+ if trimmed then
+ local trimmed_name = trim_filename(hovered.name, max_length, trim_length)
+ local trimmed_linked = #linked ~= 0
+ and link_delimiter .. trim_filename(
+ string.sub(linked, #link_delimiter + 1, -1),
+ max_length,
+ trim_length
+ )
+ or ""
+ return trimmed_name .. trimmed_linked
+ else
+ return hovered.name .. linked
+ end
+end
+
+--- Gets the hovered file's path of the current active tab.
+--- @param trimmed? boolean Whether to trim the file path if it's too long (default: false)
+--- @param max_length? integer Maximum length of the file path (default: 24)
+--- @param trim_length? integer Length of each end when trimming (default: 10)
+--- @return string path Current active tab's hovered file's path.
+function Yatline.string.get:hovered_path(trimmed, max_length, trim_length)
+ trimmed = trimmed or false
+ max_length = max_length or 24
+ trim_length = trim_length or 10
+
+ local hovered = cx.active.current.hovered
+ if not hovered then
+ return ""
+ end
+
+ if trimmed then
+ return trim_filename(ya.readable_path(tostring(hovered.url)), max_length, trim_length)
+ else
+ return ya.readable_path(tostring(hovered.url))
+ end
+end
+
+--- Gets the hovered file's size of the current active tab.
+--- @return string size Current active tab's hovered file's size.
+function Yatline.string.get:hovered_size()
+ local hovered = cx.active.current.hovered
+ if hovered then
+ return ya.readable_size(hovered:size() or hovered.cha.len)
+ else
+ return ""
+ end
+end
+
+--- Gets the hovered file's path of the current active tab.
+--- @return string mime Current active tab's hovered file's mime.
+function Yatline.string.get:hovered_mime()
+ local hovered = cx.active.current.hovered
+ if hovered then
+ return hovered:mime()
+ else
+ return ""
+ end
+end
+
+--- Gets the hovered file's user and group ownership of the current active tab.
+--- Unix-like systems only.
+--- @return string ownership Current active tab's hovered file's user and group ownership.
+function Yatline.string.get:hovered_ownership()
+ local hovered = cx.active.current.hovered
+
+ if hovered then
+ if not hovered.cha.uid or not hovered.cha.gid then
+ return ""
+ end
+
+ local username = ya.user_name(hovered.cha.uid) or tostring(hovered.cha.uid)
+ local groupname = ya.group_name(hovered.cha.gid) or tostring(hovered.cha.gid)
+
+ return username .. ":" .. groupname
+ else
+ return ""
+ end
+end
+
+--- Gets the hovered file's extension of the current active tab.
+--- @param show_icon boolean Whether or not an icon will be shown.
+--- @return string file_extension Current active tab's hovered file's extension.
+function Yatline.string.get:hovered_file_extension(show_icon)
+ local hovered = cx.active.current.hovered
+
+ if hovered then
+ local cha = hovered.cha
+
+ local name
+ if cha.is_dir then
+ name = "dir"
+ else
+ name = get_file_extension(hovered.url.name)
+ end
+
+ if show_icon then
+ local icon = hovered:icon().text
+ return icon .. " " .. name
+ else
+ return name
+ end
+ else
+ return ""
+ end
+end
+
+--- Gets the path of the current active tab.
+--- @param trimmed? boolean Whether to trim the current active tab's path if it's too long (default: false)
+--- @param max_length? integer Maximum length of the current active tab's path (default: 24)
+--- @param trim_length? integer Length of each end when trimming (default: 10)
+--- @return string path Current active tab's path.
+function Yatline.string.get:tab_path(trimmed, max_length, trim_length)
+ trimmed = trimmed or false
+ max_length = max_length or 24
+ trim_length = trim_length or 10
+
+ local cwd = cx.active.current.cwd
+ local filter = cx.active.current.files.filter
+ local finder = cx.active.finder
+
+ local t = {}
+ if cwd.is_search then
+ t[#t + 1] = string.format("search: %s", cwd.domain)
+ end
+ if filter then
+ t[#t + 1] = string.format("filter: %s", filter)
+ end
+ if finder then
+ t[#t + 1] = string.format("find: %s", finder)
+ end
+
+ local suffix
+ if #t ~= 0 then
+ suffix = " (" .. table.concat(t, ", ") .. ")"
+ else
+ suffix = ""
+ end
+
+ if trimmed then
+ return trim_filename(ya.readable_path(tostring(cwd)), max_length, trim_length) .. suffix
+ else
+ return ya.readable_path(tostring(cwd)) .. suffix
+ end
+end
+
+--- Gets the filtered query.
+--- @param key? string Key value that indicates filtered query (default: "filter:")
+--- @return string query Filtered query.
+function Yatline.string.get:filter_query(key)
+ key = key or "filter:"
+
+ local filter = cx.active.current.files.filter
+
+ if filter then
+ return string.format("%s %s", key, tostring(filter))
+ else
+ return ""
+ end
+end
+
+--- Gets the searched query.
+--- @param key? string Key value that indicates searched query (default: "search:")
+--- @return string query Searched query.
+function Yatline.string.get:search_query(key)
+ key = key or "search:"
+
+ local cwd = cx.active.current.cwd
+
+ if cwd.is_search then
+ return string.format("%s %s", key, cwd.domain)
+ else
+ return ""
+ end
+end
+
+--- Gets the finded query.
+--- @param key? string Key value that indicates finded query (default: "find:")
+--- @return string query Finded query.
+function Yatline.string.get:finder_query(key)
+ key = key or "find:"
+
+ local finder = cx.active.finder
+
+ if finder then
+ return string.format("%s %s", key, tostring(finder))
+ else
+ return ""
+ end
+end
+
+--- Gets the mode of active tab.
+--- @return string mode Active tab's mode.
+function Yatline.string.get:tab_mode()
+ local mode = tostring(cx.active.mode):upper()
+ if mode == "UNSET" then
+ mode = "UN-SET"
+ end
+
+ return mode
+end
+
+--- Gets the number of files in the current active tab.
+--- @return string num_files Number of files in the current active tab.
+function Yatline.string.get:tab_num_files()
+ return tostring(#cx.active.current.files)
+end
+
+--- Gets the cursor position in the current active tab.
+--- @return string cursor_position Current active tab's cursor position.
+function Yatline.string.get:cursor_position()
+ local cursor = cx.active.current.cursor
+ local length = #cx.active.current.files
+
+ if length ~= 0 then
+ return string.format("%d/%d", cursor + 1, length)
+ else
+ return "0"
+ end
+end
+
+--- Gets the cursor position as percentage which is according to the number of files inside of current active tab.
+--- @return string percentage Percentage of current active tab's cursor position and number of percentages.
+function Yatline.string.get:cursor_percentage()
+ local percentage = 0
+ local cursor = cx.active.current.cursor
+ local length = #cx.active.current.files
+ if cursor ~= 0 and length ~= 0 then
+ percentage = math.floor((cursor + 1) * 100 / length)
+ end
+
+ if percentage == 0 then
+ return "Top"
+ elseif percentage == 100 then
+ return "Bot"
+ else
+ return string.format("%d%%", percentage)
+ end
+end
+
+--- Gets the local date or time values.
+--- @param format string Format for giving desired date or time values.
+--- @return string date Date or time values.
+--- @see os.date To see how format works.
+function Yatline.string.get:date(format)
+ return tostring(os.date(format))
+end
+
+--======================--
+-- Component Line Group --
+--======================--
+
+Yatline.line = {}
+Yatline.line.get = {}
+Yatline.line.has_separator = false
+
+--- To follow component group naming and functions, returns the given line without any changes.
+--- @param line Line The line already pre-defined.
+--- @param component_type ComponentType Which section component will be in [ a | b | c ]. Will not be used.
+--- @return Line line The given line as an input.
+function Yatline.line.create(line, component_type)
+ return line
+end
+
+--- Creates and returns line component for tabs.
+--- @param side? string Left or right side of the either header-line or status-line.
+--- @return Line line Customized Line which contains tabs.
+--- @see set_mode_style To know how mode style selected.
+--- @see set_component_style To know how component style applied.
+--- @see connect_padding To know how components have paddings.
+--- @see connect_separator To know how component and separator connected.
+function Yatline.line.get:tabs(side)
+ side = side or "left"
+
+ local tabs = #cx.tabs
+ local lines = {}
+
+ local in_side
+ if side == "left" then
+ in_side = Side.LEFT
+ else
+ in_side = Side.RIGHT
+ end
+
+ for i = 1, tabs do
+ local text = tostring(i)
+ if Yatline.config.tab_width > 2 then
+ text = ui.truncate(text .. " " .. cx.tabs[i].name, { max = Yatline.config.tab_width })
+ end
+
+ local separator_style = { bg = nil, fg = nil }
+ if i == cx.tabs.idx then
+ local tab = connect_padding(text, ComponentType.A, in_side)
+ set_mode_style(cx.tabs[i].mode)
+ set_component_style(tab, ComponentType.A)
+
+ if Yatline.config.style_a.bg ~= "reset" or Yatline.config.show_background then
+ separator_style.fg = Yatline.config.style_a.bg
+ if Yatline.config.show_background then
+ separator_style.bg = Yatline.config.style_c.bg
+ end
+
+ lines[#lines + 1] = connect_separator(tab, in_side, SeparatorType.OUTER, separator_style)
+ else
+ separator_style.fg = Yatline.config.style_a.fg
+
+ lines[#lines + 1] = connect_separator(tab, in_side, SeparatorType.INNER, separator_style)
+ end
+ else
+ local tab = ui.Span(text)
+ local inner = ui.Span(string.rep(" ", Yatline.config.padding.inner))
+ local outer = ui.Span(string.rep(" ", Yatline.config.padding.outer))
+
+ if Yatline.config.show_background then
+ set_component_style(inner, ComponentType.C)
+ set_component_style(outer, ComponentType.C)
+ set_component_style(tab, ComponentType.C)
+ else
+ apply_style_table(tab, { fg = Yatline.config.style_c.fg })
+ end
+
+ if in_side == Side.LEFT then
+ tab = ui.Line({ outer, tab, inner })
+ else
+ tab = ui.Line({ inner, tab, outer })
+ end
+
+ if i == cx.tabs.idx - 1 then
+ set_mode_style(cx.tabs[i + 1].mode)
+
+ local open, close
+ if
+ Yatline.config.style_a.bg ~= "reset"
+ or (Yatline.config.show_background and Yatline.config.style_c.bg ~= "reset")
+ then
+ if
+ not Yatline.config.show_background
+ or (Yatline.config.show_background and Yatline.config.style_c.bg == "reset")
+ then
+ separator_style.fg = Yatline.config.style_a.bg
+ if Yatline.config.show_background then
+ separator_style.bg = Yatline.config.style_c.bg
+ end
+
+ open = ui.Span(Yatline.config.inverse_separator.open)
+ close = ui.Span(Yatline.config.inverse_separator.close)
+ else
+ separator_style.bg = Yatline.config.style_a.bg
+ if Yatline.config.show_background then
+ separator_style.fg = Yatline.config.style_c.bg
+ end
+
+ open = ui.Span(Yatline.config.section_separator.open)
+ close = ui.Span(Yatline.config.section_separator.close)
+ end
+ else
+ separator_style.fg = Yatline.config.style_c.fg
+
+ open = ui.Span(Yatline.config.part_separator.open)
+ close = ui.Span(Yatline.config.part_separator.close)
+ end
+
+ apply_style_table(open, separator_style)
+ apply_style_table(close, separator_style)
+
+ if in_side == Side.LEFT then
+ lines[#lines + 1] = ui.Line({ tab, close })
+ else
+ lines[#lines + 1] = ui.Line({ open, tab })
+ end
+ else
+ separator_style.fg = Yatline.config.style_c.fg
+ if Yatline.config.show_background then
+ separator_style.bg = Yatline.config.style_c.bg
+ end
+
+ lines[#lines + 1] = connect_separator(tab, in_side, SeparatorType.INNER, separator_style)
+ end
+ end
+ end
+
+ if in_side == Side.RIGHT then
+ return ui.Line(reverse_order(lines))
+ else
+ return ui.Line(lines)
+ end
+end
+
+--==========================--
+-- Component Coloreds Group --
+--==========================--
+
+Yatline.coloreds = {}
+Yatline.coloreds.get = {}
+Yatline.coloreds.has_separator = true
+
+--- Creates a component from given Coloreds according to other parameters.
+--- The component it created, can contain multiple strings with different foreground color.
+--- @param coloreds Coloreds The array which contains an array which contains text which will be shown inside of the component and its foreground color.
+--- @param component_type ComponentType Which section component will be in [ a | b | c ].
+--- @return Line line Customized Line which follows desired style of the parameters.
+--- @see set_mode_style To know how mode style selected.
+--- @see set_component_style To know how component style applied.
+function Yatline.coloreds.create(coloreds, component_type)
+ set_mode_style(cx.active.mode)
+
+ local spans = {}
+ for i, colored in ipairs(coloreds) do
+ local span = ui.Span(colored[1])
+ set_component_style(span, component_type)
+ span:fg(colored[2])
+
+ spans[i] = span
+ end
+
+ return ui.Line(spans)
+end
+
+--- Gets the hovered file's permissions of the current active tab.
+--- Unix-like systems only.
+--- @return Coloreds? coloreds Current active tab's hovered file's permissions
+function Yatline.coloreds.get:permissions()
+ local hovered = cx.active.current.hovered
+
+ if hovered then
+ local perm = hovered.cha:perm()
+
+ if perm then
+ local coloreds = {}
+
+ for i = 1, #perm do
+ local c = perm:sub(i, i)
+
+ local fg = Yatline.config.permissions_t_fg
+ if c == "-" then
+ fg = Yatline.config.permissions_s_fg
+ elseif c == "r" then
+ fg = Yatline.config.permissions_r_fg
+ elseif c == "w" then
+ fg = Yatline.config.permissions_w_fg
+ elseif c == "x" or c == "s" or c == "S" or c == "t" or c == "T" then
+ fg = Yatline.config.permissions_x_fg
+ end
+
+ table.insert(coloreds, { c, fg })
+ end
+
+ return coloreds
+ else
+ return nil
+ end
+ else
+ return nil
+ end
+end
+
+--- Gets the number of selected and yanked files and also number of files or filtered files of the active tab.
+--- @param filter? boolean Whether or not number of files (or filtered files) will be shown.
+--- @param zero_check? boolean Whether or not counts will be shown if count is zero.
+--- @return Coloreds? coloreds Active tab's number of selected and yanked files and also number of files or filtered files
+function Yatline.coloreds.get:count(filter, zero_check)
+ filter = filter or false
+ zero_check = zero_check or false
+
+ local num_yanked = #cx.yanked
+ local num_selected = #cx.active.selected
+ local num_files = #cx.active.current.files
+
+ local coloreds = {}
+
+ if filter then
+ local files_count_fg, files_count_icon
+ if cx.active.current.files.filter or cx.active.current.cwd.is_search then
+ files_count_fg = Yatline.config.filtereds.fg
+ files_count_icon = Yatline.config.filtereds.icon
+ else
+ files_count_fg = Yatline.config.files.fg
+ files_count_icon = Yatline.config.files.icon
+ end
+
+ if (zero_check and num_files > 0) or not zero_check then
+ table.insert(coloreds, { string.format("%s %d", files_count_icon, num_files), files_count_fg })
+ end
+ end
+
+ if (zero_check and num_selected > 0) or not zero_check then
+ if #coloreds > 0 then
+ table.insert(coloreds, { " ", Yatline.config.selected.fg })
+ end
+
+ table.insert(
+ coloreds,
+ { string.format("%s %d", Yatline.config.selected.icon, num_selected), Yatline.config.selected.fg }
+ )
+ end
+
+ if (zero_check and num_yanked > 0) or not zero_check then
+ local yanked_fg, yanked_icon
+ if cx.yanked.is_cut then
+ yanked_fg = Yatline.config.cut.fg
+ yanked_icon = Yatline.config.cut.icon
+ else
+ yanked_fg = Yatline.config.copied.fg
+ yanked_icon = Yatline.config.copied.icon
+ end
+
+ if #coloreds > 0 then
+ table.insert(coloreds, { " ", yanked_fg })
+ end
+
+ table.insert(coloreds, { string.format("%s %d", yanked_icon, num_yanked), yanked_fg })
+ end
+
+ if #coloreds > 0 then
+ return coloreds
+ else
+ return nil
+ end
+end
+
+--- Gets the number of task states.
+--- @param zero_check? boolean Whether or not counts will be shown if count is zero.
+--- @return Coloreds? coloreds Number of task states.
+function Yatline.coloreds.get:task_states(zero_check)
+ zero_check = zero_check or false
+
+ local summary = cx.tasks.summary
+ local coloreds = {}
+
+ if (zero_check and summary.total > 0) or not zero_check then
+ table.insert(
+ coloreds,
+ { string.format("%s %d", Yatline.config.total.icon, summary.total), Yatline.config.total.fg }
+ )
+ end
+
+ if (zero_check and summary.success > 0) or not zero_check then
+ if #coloreds > 0 then
+ table.insert(coloreds, { " ", Yatline.config.success.fg })
+ end
+
+ table.insert(
+ coloreds,
+ { string.format("%s %d", Yatline.config.success.icon, summary.success), Yatline.config.success.fg }
+ )
+ end
+
+ if (zero_check and summary.failed > 0) or not zero_check then
+ if #coloreds > 0 then
+ table.insert(coloreds, { " ", Yatline.config.failed.fg })
+ end
+
+ table.insert(
+ coloreds,
+ { string.format("%s %d", Yatline.config.failed.icon, summary.failed), Yatline.config.failed.fg }
+ )
+ end
+
+ if #coloreds > 0 then
+ return coloreds
+ else
+ return nil
+ end
+end
+
+--- Gets colored which contains string based component's string and desired foreground color.
+--- @param component_name string String based component's name.
+--- @param fg Color Desired foreground color.
+--- @param params? table Array of parameters of string based component. It is optional.
+--- @return Coloreds? coloreds Array of solely array of string based component's string and desired foreground color.
+function Yatline.coloreds.get:string_based_component(component_name, fg, params)
+ local getter = Yatline.string.get[component_name]
+
+ if getter then
+ local output
+ if params then
+ output = getter(Yatline.string.get, table.unpack(params))
+ else
+ output = getter()
+ end
+
+ if output ~= nil and output ~= "" then
+ return { { output, fg } }
+ end
+ end
+
+ return nil
+end
+
+--===============--
+-- Configuration --
+--===============--
+
+--- Configure separators if it is need to be added to the components.
+--- Connects them with each component.
+--- @param section_components [Line, boolean][] Array of components in one of the sections.
+--- @param component_type ComponentType Which section component will be in [ a | b | c ].
+--- @param in_side Side Left or right side of the either header-line or status-line.
+--- @param num_section_b_components integer Number of components in section-b.
+--- @param num_section_c_components integer Number of components in section-c.
+--- @return table section_line_components Array of line components whether or not connected with separators.
+--- @see connect_padding To know how components have paddings.
+--- @see connect_separator To know how component and separator connected.
+local function config_components_separators(
+ section_components,
+ component_type,
+ in_side,
+ num_section_b_components,
+ num_section_c_components
+)
+ local num_section_components = #section_components
+ local section_line_components = {}
+ for i, component in ipairs(section_components) do
+ if component[2] == true then -- Does component have separator?
+ local separator_style = { bg = nil, fg = nil }
+
+ local separator_type
+ if i ~= num_section_components then -- Does component is not at the end of the section?
+ separator_type = SeparatorType.INNER
+
+ if component_type == ComponentType.A then
+ separator_style = Yatline.config.style_a
+ elseif component_type == ComponentType.B then
+ separator_style = Yatline.config.style_b
+ else
+ separator_style = Yatline.config.style_c
+ end
+ else -- Does component is at the end of the section?
+ separator_type = SeparatorType.OUTER
+
+ if component_type == ComponentType.A then
+ separator_style.fg = Yatline.config.style_a.bg
+ elseif component_type == ComponentType.B then
+ separator_style.fg = Yatline.config.style_b.bg
+ else
+ separator_style.fg = Yatline.config.style_c.bg
+ end
+
+ if component_type == ComponentType.A and num_section_b_components ~= 0 then
+ separator_style.bg = Yatline.config.style_b.bg
+ elseif num_section_c_components == 0 or component_type == ComponentType.C then
+ if Yatline.config.show_background then
+ separator_style.bg = Yatline.config.style_c.bg
+ end
+ else
+ separator_style.bg = Yatline.config.style_c.bg
+ end
+ end
+
+ component[1] = connect_padding(component[1], component_type, in_side)
+ section_line_components[i] = connect_separator(component[1], in_side, separator_type, separator_style)
+ else
+ section_line_components[i] = component[1]
+ end
+ end
+
+ return section_line_components
+end
+
+--- Creates configured section according to its components' config.
+--- @param section ComponentConfig[] Array of components' config in a section.
+--- @param component_type ComponentType Which section that components will be.
+--- @return [Line, boolean][] section_components Configured components array whose components are in section.
+local function config_section(section, component_type)
+ --- @type [Line, boolean][]
+ local section_components = {}
+
+ for _, component in ipairs(section) do
+ local component_group = Yatline[component.type]
+
+ if component_group then -- Does component group exist?
+ if component.custom then -- Does component is custom?
+ if component.name ~= nil and component.name ~= "" and #component.name ~= 0 then -- Does component name is valid?
+ section_components[#section_components + 1] = -- Insert component to the table.
+ { component_group.create(component.name, component_type), component_group.has_separator }
+ end
+ else
+ local getter = component_group.get[component.name] -- Get component function that will be called.
+
+ if getter then -- Does function exist?
+ local output -- Output of the function.
+ if component.params then -- Does component function has parameters?
+ output = getter(component_group.get, table.unpack(component.params))
+ else
+ output = getter()
+ end
+
+ if output ~= nil and output ~= "" then -- Does component is not empty?
+ section_components[#section_components + 1] = -- Insert component to the table.
+ { component_group.create(output, component_type), component_group.has_separator }
+ end
+ end
+ end
+ end
+ end
+
+ return section_components
+end
+
+--- Automatically creates and configures either header-line or status-line.
+--- @param side SideConfig Configuration of either left or right side.
+--- @param in_side Side Which side components will be.
+--- @return Line left_line Consist of components that are in left side of the line.
+--- @return Line right_line Consist of components that are in right side of the line.
+--- @see config_section To know how components are gotten from sections' config.
+--- @see config_components_separators To know how components are connected with separators.
+local function config_line(side, in_side)
+ -- Configures components of sections.
+ local section_a_components = config_section(side.section_a, ComponentType.A)
+ local section_b_components = config_section(side.section_b, ComponentType.B)
+ local section_c_components = config_section(side.section_c, ComponentType.C)
+
+ local num_section_b_components = #section_b_components
+ local num_section_c_components = #section_c_components
+
+ -- Connects components of section by separators.
+ local section_a_line_components = config_components_separators(
+ section_a_components,
+ ComponentType.A,
+ in_side,
+ num_section_b_components,
+ num_section_c_components
+ )
+ local section_b_line_components = config_components_separators(
+ section_b_components,
+ ComponentType.B,
+ in_side,
+ num_section_b_components,
+ num_section_c_components
+ )
+ local section_c_line_components = config_components_separators(
+ section_c_components,
+ ComponentType.C,
+ in_side,
+ num_section_b_components,
+ num_section_c_components
+ )
+
+ if in_side == Side.RIGHT then -- Reverse the order of the components if it is in the right side.
+ section_a_line_components = reverse_order(section_a_line_components)
+ section_b_line_components = reverse_order(section_b_line_components)
+ section_c_line_components = reverse_order(section_c_line_components)
+ end
+
+ -- Combines components of section into single components.
+ local section_a_line = ui.Line(section_a_line_components)
+ local section_b_line = ui.Line(section_b_line_components)
+ local section_c_line = ui.Line(section_c_line_components)
+
+ if in_side == Side.LEFT then
+ return ui.Line({ section_a_line, section_b_line, section_c_line })
+ else
+ return ui.Line({ section_c_line, section_b_line, section_a_line })
+ end
+end
+
+--- Checks if either header-line or status-line contains components.
+--- @param line LineConfig Configuration of either header-line or status-line.
+--- @return boolean show_line Returns yes if it contains components, otherwise returns no.
+local function show_line(line)
+ for _, side in pairs(line) do
+ for _, section in pairs(side) do
+ if #section ~= 0 then
+ return true
+ end
+ end
+ end
+
+ return false
+end
+
+--- Creates and configures paragraph which is used as left or right of either
+--- header-line or status-line.
+--- @param area Rect The area where paragraph will be placed in.
+--- @param line? Line The line which used in paragraph. It is optional.
+--- @return Paragraph paragraph Configured parapgraph.
+local function config_paragraph(area, line)
+ local line_array = { line } or {}
+ if Yatline.config.show_background then
+ return apply_style_table(ui.Text(line_array):area(area), Yatline.config.style_c)
+ else
+ return ui.Text(line_array):area(area)
+ end
+end
+
+return {
+ setup = function(_, config, pre_theme)
+ if config then
+ -- Fills the sections that are not given if the line exists.
+ for _, line in ipairs({ "header_line", "status_line" }) do
+ if config[line] then
+ for _, side in ipairs({ "left", "right" }) do
+ if config[line][side] then
+ for _, section in ipairs({ "section_a", "section_b", "section_c" }) do
+ config[line][side][section] = config[line][side][section] or {}
+ end
+ else
+ config[line][side] = {}
+ for _, section in ipairs({ "section_a", "section_b", "section_c" }) do
+ config[line][side][section] = {}
+ end
+ end
+ end
+ end
+ end
+
+ -- Get the current theme according to the light/dark mode. (default: config.theme)
+ config.theme = (not rt.term.light and config.theme_dark)
+ or (rt.term.light and config.theme_light)
+ or config.theme
+
+ -- Extracts theme fields to the config unless that fields does not exists.
+ if config.theme then
+ for key, value in pairs(config.theme) do
+ if not config[key] then
+ config[key] = value
+ end
+ end
+ end
+
+ -- Extracts config fields to the YatlineConfig if that fields exists.
+ for key, value in pairs(config) do
+ if Yatline.config[key] then
+ Yatline.config[key] = value
+ end
+ end
+ end
+
+ -- Extracts pre_theme fields to the YatlineConfig if that fields exists.
+ if pre_theme then
+ for key, value in pairs(pre_theme) do
+ if Yatline.config[key] then
+ Yatline.config[key] = value
+ end
+ end
+ end
+
+ if Yatline.config.display_header_line then -- Controls displaying header-line.
+ if show_line(Yatline.config.header_line) then -- Controls recoding of header-line.
+ -- Empties default Yazi header-line.
+ Header._left = {}
+ Header._right = {}
+
+ Header.redraw = function(self)
+ -- Gets Yazi components.
+ local right = self:children_redraw(self.RIGHT)
+ self._right_width = right:width()
+ local left = self:children_redraw(self.LEFT)
+
+ -- Gets Yatline components.
+ local left_line = config_line(Yatline.config.header_line.left, Side.LEFT)
+ local right_line = config_line(Yatline.config.header_line.right, Side.RIGHT)
+
+ return {
+ config_paragraph(self._area, ui.Line({ left_line, left })), -- Styles left_line if show_background set.
+ ui.Line({ right, right_line }):area(self._area):align(ui.Align.RIGHT),
+ }
+ end
+ end
+ else
+ Header.redraw = function()
+ return {}
+ end
+ end
+
+ if Yatline.config.display_status_line then -- Controls displaying status-line.
+ if show_line(Yatline.config.status_line) then -- Controls recoding of status-line.
+ -- Empties default Yazi status-line.
+ Status._left = {}
+ Status._right = {}
+
+ Status.redraw = function(self)
+ -- Gets Yazi components.
+ local left = self:children_redraw(self.LEFT)
+ local right = self:children_redraw(self.RIGHT)
+
+ -- Gets Yatline components.
+ local left_line = config_line(Yatline.config.status_line.left, Side.LEFT)
+ local right_line = config_line(Yatline.config.status_line.right, Side.RIGHT)
+
+ local sum_right = ui.Line({ right, right_line }) -- Needed for error prevention.
+ return {
+ config_paragraph(self._area, ui.Line({ left_line, left })), -- Styles left_line if show_background set.
+ sum_right:area(self._area):align(ui.Align.RIGHT),
+ table.unpack(ui.redraw(Progress:new(self._area, sum_right:width()))), -- Inserts Progress bar.
+ }
+ end
+ end
+ else
+ Status.redraw = function()
+ return {}
+ end
+ end
+
+ Root.layout = function(self)
+ local constraints = {}
+ -- Sets Yazi layout according to the given positions.
+ for _, component in ipairs(Yatline.config.component_positions) do
+ if
+ (component == "header" and Yatline.config.display_header_line)
+ or (component == "status" and Yatline.config.display_status_line)
+ then
+ table.insert(constraints, ui.Constraint.Length(1))
+ elseif component == "tab" then
+ table.insert(constraints, ui.Constraint.Fill(1))
+ end
+ end
+
+ self._chunks = ui.Layout():direction(ui.Layout.VERTICAL):constraints(constraints):split(self._area)
+ end
+
+ Root.build = function(self)
+ local childrens = {}
+ -- Fills the layout according to the given positions.
+ local i = 1
+ for _, component in ipairs(Yatline.config.component_positions) do
+ if component == "header" and Yatline.config.display_header_line then
+ table.insert(childrens, Header:new(self._chunks[i], cx.active))
+ i = i + 1
+ elseif component == "tab" then
+ table.insert(childrens, Tab:new(self._chunks[i], cx.active))
+ i = i + 1
+ elseif component == "status" and Yatline.config.display_status_line then
+ table.insert(childrens, Status:new(self._chunks[i], cx.active))
+ i = i + 1
+ end
+ end
+
+ table.insert(childrens, Modal:new(self._area))
+
+ self._children = childrens
+ end
+ end,
+}
diff --git a/config/yazi/theme.toml b/config/yazi/theme.toml
new file mode 100644
index 00000000..e00934de
--- /dev/null
+++ b/config/yazi/theme.toml
@@ -0,0 +1,3 @@
+
+[flavor]
+use = "catppuccin-macchiato"
diff --git a/config/yazi/yazi.toml b/config/yazi/yazi.toml
new file mode 100644
index 00000000..ac531750
--- /dev/null
+++ b/config/yazi/yazi.toml
@@ -0,0 +1,88 @@
+
+[manager]
+ratio = [1, 4, 3]
+sort_by = "natural"
+sort_dir_first = true
+show_hidden = true
+[opener]
+folder = [
+ { run = 'hyprctl dispatch exec "[float; size 60% 60%; center 1] nemo" "$@"', orphan = true, desc = "nemo", for = "linux" },
+ { run = '''fish -c "nvim "$1""''', block = true, desc = "neovim", for = "linux" },
+ { run = 'kitty --detach nvim "$@"', orphan = true, desc = "neovim (detached)", for = "linux" },
+ { run = '''fish -c "lazygit -p "$1""''', block = true, desc = "lazygit", for = "linux" },
+ { run = 'codium "$@"', orphan = true, desc = "vscodium", for = "linux" },
+ { run = 'kitty "$@"', orphan = true, desc = "kitty", for = "linux" },
+ { run = 'xdg-open "$@"', orphan = true, desc = "xdg-open", for = "linux" },
+]
+
+text = [
+ { run = '$EDITOR "$@"', block = true, desc = "$EDITOR", for = "linux" },
+ { run = 'nvim "$@"', block = true, desc = "neovim", for = "linux" },
+ { run = 'kitty --detach nvim "$@"', block = true, desc = "neovim (detached)", for = "linux" },
+ { run = 'codium "$@"', orphan = true, desc = "vscodium", for = "linux" },
+ { run = 'xdg-open "$@"', orphan = true, desc = "xdg-open", for = "linux" },
+]
+
+document = [
+ { run = 'xdg-open "$@"', orphan = true, desc = "xdg-open", for = "linux" },
+ { run = 'zathura "$@"', orphan = true, desc = "zathura", for = "linux" },
+ { run = 'libreoffice "$@"', orphan = true, desc = "libreoffice", for = "linux" },
+]
+
+image = [
+ { run = 'xdg-open "$@"', orphan = true, desc = "xdg-open", for = "linux" },
+ { run = 'qimgv "$@"', orphan = true, desc = "qimgv", for = "linux" },
+ { run = 'krita "$@"', orphan = true, desc = "krita", for = "linux" },
+ { run = 'satty --filename "$@"', orphan = true, desc = "satty", for = "linux" },
+]
+video = [
+ { run = 'xdg-open "$@"', orphan = true, desc = "xdg-open", for = "linux" },
+ { run = 'mpv "$@"', orphan = true, desc = "mpv", for = "linux" },
+]
+audio = [
+ { run = 'xdg-open "$@"', orphan = true, desc = "xdg-open", for = "linux" },
+ { run = 'mpv "$@"', orphan = true, desc = "mpv", for = "linux" },
+]
+fallback = [
+ { run = 'xdg-open "$@"', orphan = true, desc = "xdg-open", for = "linux" },
+]
+
+[open]
+rules = [
+ { url = "*/", use = "folder" },
+
+ { mime = "text/*", use = "text" },
+ { mime = "image/*", use = "image" },
+ { mime = "video/*", use = "video" },
+ { mime = "application/octet-stream", use = "video" },
+ { mime = "audio/*", use = "audio" },
+ { mime = "inode/x-empty", use = "text" },
+ { mime = "application/json", use = "text" },
+
+ { mime = "application/zip", use = "archive" },
+ { mime = "application/gzip", use = "archive" },
+ { mime = "application/x-bzip", use = "archive" },
+ { mime = "application/x-bzip2", use = "archive" },
+ { mime = "application/x-tar", use = "archive" },
+ { mime = "application/x-7z-compressed", use = "archive" },
+ { mime = "application/x-rar", use = "archive" },
+ { mime = "application/pdf", use = "document" },
+ { mime = "application/epub+zip", use = "document" },
+ { mime = "application/x-mobipocket-ebook", use = "document" },
+
+ { mime = "*", use = "fallback" },
+]
+
+[[plugin.prepend_fetchers]]
+id = "git"
+name = "*"
+url = "*"
+run = "git"
+group = "default"
+
+[[plugin.prepend_fetchers]]
+id = "git"
+name = "*/"
+url = "*/"
+run = "git"
+group = "default"
diff --git a/copy.sh b/copy.sh
index cbef4d1c..af7cbe69 100755
--- a/copy.sh
+++ b/copy.sh
@@ -805,7 +805,12 @@ fi
printf "\n%.0s" {1..1}
# initialize wallust to avoid config error on hyprland
-wallust run -s $wallpaper 2>&1 | tee -a "$LOG"
+wallust_args=()
+# shellcheck source=/dev/null
+if [ -f "$DOTFILES_DIR/config/hypr/scripts/WallustConfig.sh" ]; then
+ . "$DOTFILES_DIR/config/hypr/scripts/WallustConfig.sh"
+fi
+wallust "${wallust_args[@]}" run -s "$wallpaper" 2>&1 | tee -a "$LOG"
if is_nixos && ! command -v waybar-weather >/dev/null 2>&1; then
echo "${WARN} waybar-weather binary is missing." 2>&1 | tee -a "$LOG"
echo "Install the current NixOS-Hyprland version to install waybar-weather applet for Waybar" 2>&1 | tee -a "$LOG"
diff --git a/docs/HOWTO-fix-ventoy-GUI.md b/docs/HOWTO-fix-ventoy-GUI.md
index 01441f30..c070f120 100644
--- a/docs/HOWTO-fix-ventoy-GUI.md
+++ b/docs/HOWTO-fix-ventoy-GUI.md
@@ -116,4 +116,3 @@ source ~/.config/fish/config.fish
## Success!
You should now be able to launch Ventoy GUI from your terminal or your application launcher seamlessly under Wayland.
-
diff --git a/scripts/fix-systemsettings-lua.sh b/scripts/fix-systemsettings-lua.sh
new file mode 100755
index 00000000..e1b550fc
--- /dev/null
+++ b/scripts/fix-systemsettings-lua.sh
@@ -0,0 +1,229 @@
+#!/usr/bin/env bash
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# Regenerate ~/.config/hypr/configs/system_settings.lua from SystemSettings.conf.
+
+set -euo pipefail
+
+CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
+HYPR_DIR="${CONFIG_HOME}/hypr"
+CONFIGS_DIR="${HYPR_DIR}/configs"
+LEGACY_DIR="${CONFIGS_DIR}/LegacyConfigs"
+SYSTEM_SETTINGS_CONF="${CONFIGS_DIR}/SystemSettings.conf"
+SYSTEM_SETTINGS_LUA="${CONFIGS_DIR}/system_settings.lua"
+
+python3 - <<'PY'
+from pathlib import Path
+import os
+import re
+
+HEADER = """-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+"""
+
+config_home = Path(os.getenv("XDG_CONFIG_HOME") or (Path.home() / ".config"))
+hypr_dir = config_home / "hypr"
+configs_dir = hypr_dir / "configs"
+legacy_dir = configs_dir / "LegacyConfigs"
+system_settings_path = configs_dir / "SystemSettings.conf"
+output_path = configs_dir / "system_settings.lua"
+
+def strip_comment(line: str) -> str:
+ return line.split("#", 1)[0].strip()
+
+def lua_string(value: str) -> str:
+ return '"' + value.replace("\\", "\\\\").replace('"', '\\"') + '"'
+
+def scalar(value: str, *, bool_words: bool = True) -> str:
+ value = value.strip()
+ lower = value.lower()
+ if bool_words and lower in {"on", "true", "yes"}:
+ return "true"
+ if bool_words and lower in {"off", "false", "no"}:
+ return "false"
+ if re.fullmatch(r"[-+]?\d+(\.\d+)?", value):
+ return value
+ return lua_string(value)
+
+def render_table(value, indent=4):
+ lines = []
+ for key, child in value.items():
+ if isinstance(child, dict):
+ lines.append(" " * indent + f"{key} = {{")
+ lines.extend(render_table(child, indent + 2))
+ lines.append(" " * indent + "},")
+ else:
+ lines.append(" " * indent + f"{key} = {scalar(str(child))},")
+ return lines
+
+def latest_legacy_file(path: Path):
+ if not legacy_dir.is_dir():
+ return None
+ candidates = []
+ for snapshot in sorted(legacy_dir.iterdir()):
+ if not snapshot.is_dir():
+ continue
+ candidate = snapshot / path.name
+ if candidate.is_file():
+ candidates.append(candidate)
+ return candidates[-1] if candidates else None
+
+def parse_hyprlang_sections(path: Path):
+ sections = {}
+ if path is None or not path.exists():
+ return sections
+ stack = [sections]
+ for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines():
+ line = strip_comment(raw)
+ if not line:
+ continue
+ if line.startswith("source"):
+ continue
+ if line.endswith("{"):
+ name = line[:-1].strip().replace("-", "_")
+ if not name or name.startswith("$"):
+ continue
+ current = stack[-1]
+ target = current.setdefault(name, {})
+ stack.append(target)
+ continue
+ if line == "}":
+ if len(stack) > 1:
+ stack.pop()
+ continue
+ if "=" in line:
+ key, value = [part.strip() for part in line.split("=", 1)]
+ if not key or key.startswith("$"):
+ continue
+ key = key.replace("-", "_")
+ container = stack[-1]
+ parts = [part.replace("-", "_") for part in key.split(".") if part]
+ for part in parts[:-1]:
+ container = container.setdefault(part, {})
+ container[parts[-1]] = value
+ return sections
+
+def parse_scripts_dir(path: Path):
+ if path is None or not path.exists():
+ return None
+ for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines():
+ line = strip_comment(raw)
+ if not line:
+ continue
+ match = re.match(r"^\$scriptsDir\s*=\s*(.+)$", line)
+ if match:
+ value = match.group(1).strip().strip('"').strip("'")
+ return value
+ return None
+
+def parse_gestures(path: Path):
+ simple = []
+ complex_entries = []
+ if path is None or not path.exists():
+ return simple, complex_entries
+ for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines():
+ line = strip_comment(raw)
+ if not line:
+ continue
+ match = re.match(r"^gesture\s*=\s*(.+)$", line)
+ if not match:
+ continue
+ payload = match.group(1).strip()
+ parts = [part.strip() for part in payload.split(",")]
+ if len(parts) >= 3 and parts[2] == "workspace":
+ try:
+ fingers = int(parts[0])
+ except ValueError:
+ complex_entries.append(payload)
+ continue
+ simple.append({"fingers": fingers, "direction": parts[1], "action": "workspace"})
+ else:
+ complex_entries.append(payload)
+ return simple, complex_entries
+
+source_path = system_settings_path if system_settings_path.exists() else latest_legacy_file(system_settings_path)
+
+lines = [
+ "-- System Settings (auto-generated).",
+ "-- This file keeps migrated settings split from user overrides.",
+ "-- Add only Lua entries here.",
+ "-- Example:",
+ "-- hl.config({ general = { gaps_in = 4, gaps_out = 8 } })",
+ "",
+]
+
+if source_path is None:
+ lines.append("-- No active entries were found in SystemSettings.conf.")
+else:
+ scripts_dir = parse_scripts_dir(source_path)
+ if scripts_dir:
+ lines.append(f"local scriptsDir = {lua_string(scripts_dir)}")
+ lines.append("")
+
+ sections = parse_hyprlang_sections(source_path)
+ gestures_section = sections.pop("gestures", None)
+ if gestures_section and "gesture" in gestures_section:
+ gestures_section.pop("gesture", None)
+
+ ordered_sections = [
+ "dwindle",
+ "master",
+ "scrolling",
+ "general",
+ "input",
+ "gestures",
+ "misc",
+ "binds",
+ "xwayland",
+ "render",
+ "cursor",
+ ]
+ for section in ordered_sections:
+ if section == "gestures":
+ data = gestures_section
+ elif section == "misc":
+ data = sections.get(section) or {}
+ if "force_default_wallpaper" not in data:
+ data["force_default_wallpaper"] = "false"
+ else:
+ data = sections.get(section)
+ if not data:
+ continue
+ lines.append("hl.config({")
+ lines.append(f" {section} = {{")
+ lines.extend(render_table(data, indent=4))
+ lines.append(" },")
+ lines.append("})")
+ lines.append("")
+
+ simple_gestures, complex_gestures = parse_gestures(source_path)
+ for spec in simple_gestures:
+ lines.extend([
+ "hl.gesture({",
+ f" fingers = {spec['fingers']},",
+ f" direction = {lua_string(spec['direction'])},",
+ f" action = {lua_string(spec['action'])},",
+ "})",
+ "",
+ ])
+
+ if complex_gestures:
+ lines.append("-- Complex dispatcher gestures from SystemSettings.conf are pending explicit Lua API parity:")
+ for entry in complex_gestures:
+ lines.append(f"-- gesture = {entry}")
+ lines.append("")
+
+content = "\n".join(lines).rstrip() + "\n"
+if not content.startswith(HEADER):
+ content = HEADER + "\n" + content.lstrip("\n")
+output_path.write_text(content, encoding="utf-8")
+print(f"[OK] Wrote {output_path}")
+PY
diff --git a/scripts/lib_apps.sh b/scripts/lib_apps.sh
index 9472831d..579b5fd2 100644
--- a/scripts/lib_apps.sh
+++ b/scripts/lib_apps.sh
@@ -109,10 +109,43 @@ install_terminal_configs() {
choose_default_editor() {
local log="$1"
local base="${DOTFILES_DIR:-.}"
+ local defaults_file="$base/config/hypr/UserConfigs/01-UserDefaults.conf"
local editor_set=0
+ set_env_default() {
+ local var_name="$1"
+ local value="$2"
+ local note="$3"
+ local tmp_file
+ tmp_file=$(mktemp)
+
+ awk -v var_name="$var_name" -v value="$value" -v note="$note" '
+ BEGIN { updated = 0 }
+ {
+ if ($0 ~ "^[[:space:]#]*env[[:space:]]*=[[:space:]]*" var_name ",") {
+ if (value != "") {
+ print "env = " var_name "," value note
+ } else {
+ print "#env = " var_name "," note
+ }
+ updated = 1
+ } else {
+ print $0
+ }
+ }
+ END {
+ if (!updated) {
+ if (value != "") {
+ print "env = " var_name "," value note
+ } else {
+ print "#env = " var_name "," note
+ }
+ }
+ }
+ ' "$defaults_file" > "$tmp_file" && mv "$tmp_file" "$defaults_file"
+ }
update_editor() {
local editor=$1
- sed -i "s/#env = EDITOR,.*/env = EDITOR,$editor #default editor/" "$base/config/hypr/UserConfigs/01-UserDefaults.conf"
+ set_env_default "EDITOR" "$editor" " #default editor"
echo "${OK:-[OK]} Default editor set to ${MAGENTA:-}$editor${RESET:-}." 2>&1 | tee -a "$log"
}
if command -v nvim &>/dev/null; then
@@ -134,6 +167,37 @@ choose_default_editor() {
fi
fi
fi
+
+ local visual_choice=""
+ local visual_value=""
+ local prompt_visual_input=0
+ if [[ -n "${VISUAL:-}" ]]; then
+ printf "${INFO:-[INFO]} VISUAL is currently set to ${MAGENTA:-}%s${RESET:-}\\n" "${VISUAL}"
+ if read -r -p "${CAT:-[ACTION]} Use this as Quick Settings VISUAL editor? (Y/n): " visual_choice </dev/tty; then
+ if [[ "$visual_choice" != [Nn]* ]]; then
+ visual_value="${VISUAL}"
+ else
+ prompt_visual_input=1
+ fi
+ fi
+ else
+ prompt_visual_input=1
+ fi
+
+ if [[ "$prompt_visual_input" -eq 1 ]]; then
+ printf "${INFO:-[INFO]} Optional GUI editor for Quick Settings (examples: neovide, geany, code, codium).\\n"
+ if read -r -p "${CAT:-[ACTION]} Enter VISUAL editor command or leave empty to skip: " visual_choice </dev/tty; then
+ visual_value="$visual_choice"
+ fi
+ fi
+
+ if [[ -n "$visual_value" ]]; then
+ set_env_default "VISUAL" "$visual_value" " #default visual editor for quick settings (optional)"
+ echo "${OK:-[OK]} VISUAL editor set to ${MAGENTA:-}$visual_value${RESET:-}." 2>&1 | tee -a "$log"
+ else
+ set_env_default "VISUAL" "" " #default visual editor for quick settings (optional)"
+ echo "${NOTE:-[NOTE]} VISUAL editor not set (optional)." 2>&1 | tee -a "$log"
+ fi
}
# Install waybar-weather on non-NixOS: prefer Arch AUR, otherwise copy prebuilt asset to /usr/bin
diff --git a/scripts/lib_copy.sh b/scripts/lib_copy.sh
index 2eb02671..9a1c0444 100644
--- a/scripts/lib_copy.sh
+++ b/scripts/lib_copy.sh
@@ -119,7 +119,7 @@ copy_waybar() {
copy_phase2() {
local log="$1"
local base="${DOTFILES_DIR:-.}"
- local DIR="btop cava hypr Kvantum qt5ct qt6ct swappy wallust wlogout"
+ local DIR="btop cava hypr Kvantum qt5ct qt6ct swappy wallust wlogout yazi"
for DIR_NAME in $DIR; do
local DIRPATH="$HOME/.config/$DIR_NAME"
if [ -d "$DIRPATH" ]; then
@@ -143,43 +143,83 @@ restore_hypr_assets() {
local express_mode="$2"
local HYPR_DIR="$HOME/.config/hypr"
+ local CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
local BACKUP_DIR
BACKUP_DIR=$(get_backup_dirname)
local BACKUP_HYPR_PATH="$HYPR_DIR-backup-$BACKUP_DIR"
if [ -d "$BACKUP_HYPR_PATH" ]; then
- if [ "$express_mode" -eq 1 ]; then
- echo "${NOTE:-[NOTE]} Express mode: skipping automatic restoration of animations and monitor profiles." 2>&1 | tee -a "$log"
- return
+ local backup_mode="conf"
+ if [ -f "$BACKUP_HYPR_PATH/hyprland.lua" ] || [ -f "$CONFIG_HOME/hyprland.lua" ]; then
+ backup_mode="lua"
fi
- echo -e "\n${NOTE:-[NOTE]} Restoring ${SKY_BLUE:-}Animations & Monitor Profiles${RESET:-} into ${YELLOW:-}$HYPR_DIR${RESET:-}..."
+ # Preserve active Lua entrypoint automatically to avoid dropping users
+ # back to hyprland.conf after an upgrade.
+ if [ -f "$BACKUP_HYPR_PATH/hyprland.lua" ]; then
+ cp -f "$BACKUP_HYPR_PATH/hyprland.lua" "$HYPR_DIR/hyprland.lua" 2>&1 | tee -a "$log"
+ echo "${OK:-[OK]} - Restored file: ${MAGENTA:-}hyprland.lua${RESET:-}" 2>&1 | tee -a "$log"
+ fi
- # Fresh installs should apply repo defaults; do not restore a previous wallpaper.
- # RUN_MODE is set by copy.sh (install|upgrade|express) and is visible here.
- local DIR_B=("Monitor_Profiles" "animations")
- if [ "${RUN_MODE:-}" != "install" ]; then
- DIR_B+=("wallpaper_effects")
+ if [ "$express_mode" -eq 1 ]; then
+ echo "${NOTE:-[NOTE]} Express mode: skipping automatic restoration of animations and monitor profile directories." 2>&1 | tee -a "$log"
else
- echo "${NOTE:-[NOTE]} Fresh install: skipping restore of wallpaper_effects so default wallpaper applies." 2>&1 | tee -a "$log"
+ echo -e "\n${NOTE:-[NOTE]} Restoring ${SKY_BLUE:-}Animations & Monitor Profiles${RESET:-} into ${YELLOW:-}$HYPR_DIR${RESET:-}..."
+
+ # Fresh installs should apply repo defaults; do not restore a previous wallpaper.
+ # RUN_MODE is set by copy.sh (install|upgrade|express) and is visible here.
+ local DIR_B=("Monitor_Profiles" "animations")
+ if [ "${RUN_MODE:-}" != "install" ]; then
+ DIR_B+=("wallpaper_effects")
+ else
+ echo "${NOTE:-[NOTE]} Fresh install: skipping restore of wallpaper_effects so default wallpaper applies." 2>&1 | tee -a "$log"
+ fi
+
+ for DIR_RESTORE in "${DIR_B[@]}"; do
+ local BACKUP_SUBDIR="$BACKUP_HYPR_PATH/$DIR_RESTORE"
+ if [ -d "$BACKUP_SUBDIR" ]; then
+ cp -r "$BACKUP_SUBDIR" "$HYPR_DIR/" 2>&1 | tee -a "$log"
+ echo "${OK:-[OK]} - Restored directory: ${MAGENTA:-}$DIR_RESTORE${RESET:-}" 2>&1 | tee -a "$log"
+ fi
+ done
fi
- for DIR_RESTORE in "${DIR_B[@]}"; do
- local BACKUP_SUBDIR="$BACKUP_HYPR_PATH/$DIR_RESTORE"
- if [ -d "$BACKUP_SUBDIR" ]; then
- cp -r "$BACKUP_SUBDIR" "$HYPR_DIR/" 2>&1 | tee -a "$log"
- echo "${OK:-[OK]} - Restored directory: ${MAGENTA:-}$DIR_RESTORE${RESET:-}" 2>&1 | tee -a "$log"
+ # Keep monitor/workspace state across upgrades, including express mode.
+ if [ "$backup_mode" = "lua" ]; then
+ local LUA_USER_DIR="$HYPR_DIR/UserConfigs"
+ mkdir -p "$LUA_USER_DIR"
+
+ local BACKUP_LUA_MONITORS=""
+ local BACKUP_LUA_WORKSPACES=""
+ if [ -f "$BACKUP_HYPR_PATH/UserConfigs/monitors.lua" ]; then
+ BACKUP_LUA_MONITORS="$BACKUP_HYPR_PATH/UserConfigs/monitors.lua"
+ elif [ -f "$BACKUP_HYPR_PATH/lua/monitors.lua" ]; then
+ BACKUP_LUA_MONITORS="$BACKUP_HYPR_PATH/lua/monitors.lua"
+ fi
+ if [ -f "$BACKUP_HYPR_PATH/UserConfigs/workspaces.lua" ]; then
+ BACKUP_LUA_WORKSPACES="$BACKUP_HYPR_PATH/UserConfigs/workspaces.lua"
+ elif [ -f "$BACKUP_HYPR_PATH/lua/workspaces.lua" ]; then
+ BACKUP_LUA_WORKSPACES="$BACKUP_HYPR_PATH/lua/workspaces.lua"
fi
- done
- local FILE_B=("monitors.conf" "workspaces.conf")
- for FILE_RESTORE in "${FILE_B[@]}"; do
- local BACKUP_FILE="$BACKUP_HYPR_PATH/$FILE_RESTORE"
- if [ -f "$BACKUP_FILE" ]; then
- cp "$BACKUP_FILE" "$HYPR_DIR/$FILE_RESTORE" 2>&1 | tee -a "$log"
- echo "${OK:-[OK]} - Restored file: ${MAGENTA:-}$FILE_RESTORE${RESET:-}" 2>&1 | tee -a "$log"
+ if [ -n "$BACKUP_LUA_MONITORS" ]; then
+ cp -f "$BACKUP_LUA_MONITORS" "$LUA_USER_DIR/monitors.lua" 2>&1 | tee -a "$log"
+ echo "${OK:-[OK]} - Restored file: ${MAGENTA:-}UserConfigs/monitors.lua${RESET:-}" 2>&1 | tee -a "$log"
fi
- done
+ if [ -n "$BACKUP_LUA_WORKSPACES" ]; then
+ cp -f "$BACKUP_LUA_WORKSPACES" "$LUA_USER_DIR/workspaces.lua" 2>&1 | tee -a "$log"
+ echo "${OK:-[OK]} - Restored file: ${MAGENTA:-}UserConfigs/workspaces.lua${RESET:-}" 2>&1 | tee -a "$log"
+ fi
+ else
+ local FILE_B=("monitors.conf" "workspaces.conf")
+ for FILE_RESTORE in "${FILE_B[@]}"; do
+ local BACKUP_FILE="$BACKUP_HYPR_PATH/$FILE_RESTORE"
+ if [ -f "$BACKUP_FILE" ]; then
+ cp "$BACKUP_FILE" "$HYPR_DIR/$FILE_RESTORE" 2>&1 | tee -a "$log"
+ echo "${OK:-[OK]} - Restored file: ${MAGENTA:-}$FILE_RESTORE${RESET:-}" 2>&1 | tee -a "$log"
+ fi
+ done
+ fi
fi
}
@@ -348,20 +388,27 @@ restore_user_configs() {
local log="$1"
local express_mode="$2"
local old_version="$3"
- if [ "${RUN_MODE:-}" = "install" ]; then
- return
- fi
local DIRPATH="$HOME/.config/hypr"
local BACKUP_DIR
BACKUP_DIR=$(get_backup_dirname)
local BACKUP_DIR_PATH="$DIRPATH-backup-$BACKUP_DIR/UserConfigs"
+ local BACKUP_CONFIGS_PATH="$DIRPATH-backup-$BACKUP_DIR/configs"
if [ -z "$BACKUP_DIR" ]; then
echo "${ERROR:-[ERROR]} - Backup directory name is empty. Exiting." 2>&1 | tee -a "$log"
exit 1
fi
+ if [ "${RUN_MODE:-}" = "install" ]; then
+ if [ -d "$BACKUP_DIR_PATH" ]; then
+ echo "${NOTE:-[NOTE]} Preserving existing UserConfigs directory during install." 2>&1 | tee -a "$log"
+ rsync -a "$BACKUP_DIR_PATH/" "$DIRPATH/UserConfigs/" 2>&1 | tee -a "$log"
+ echo "${OK:-[OK]} - UserConfigs directory preserved." 2>&1 | tee -a "$log"
+ fi
+ return
+ fi
+
if [ -d "$BACKUP_DIR_PATH" ]; then
local VERSION_FILE
VERSION_FILE=$(find "$DIRPATH" -maxdepth 1 -name "v*.*.*" | head -n 1)
@@ -409,11 +456,13 @@ restore_user_configs() {
"ENVariables.conf"
"LaptopDisplay.conf"
"Laptops.conf"
+ "monitors.lua"
"Startup_Apps.conf"
"UserDecorations.conf"
"UserAnimations.conf"
"UserKeybinds.conf"
"UserSettings.conf"
+ "workspaces.lua"
"WindowRules.conf"
)
@@ -455,6 +504,19 @@ restore_user_configs() {
fi
fi
+ if [ -d "$BACKUP_CONFIGS_PATH" ]; then
+ local restored_system_lua=0
+ local lua_file
+ mkdir -p "$DIRPATH/configs"
+ while IFS= read -r -d '' lua_file; do
+ cp -f "$lua_file" "$DIRPATH/configs/"
+ restored_system_lua=1
+ done < <(find "$BACKUP_CONFIGS_PATH" -maxdepth 1 -type f -name 'system_*.lua' -print0)
+ if [ "$restored_system_lua" -eq 1 ]; then
+ echo "${OK:-[OK]} - Restored migrated system Lua overlays to $DIRPATH/configs." 2>&1 | tee -a "$log"
+ fi
+ fi
+
# Always run de-dupe based on the installed dotfiles version so that
# express mode and standard mode behave consistently. Prefer the
# pre-upgrade version (old_version) if provided so we still clean up
diff --git a/scripts/migrate-hypr-to-lua.sh b/scripts/migrate-hypr-to-lua.sh
new file mode 100755
index 00000000..ccbd6ed9
--- /dev/null
+++ b/scripts/migrate-hypr-to-lua.sh
@@ -0,0 +1,2212 @@
+#!/usr/bin/env bash
+# ==================================================
+# KoolDots (2026)
+# Project URL: https://github.com/LinuxBeginnings
+# License: GNU GPLv3
+# SPDX-License-Identifier: GPL-3.0-or-later
+# ==================================================
+# Opt-in helper for testing Hyprland's Lua config entrypoint.
+
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
+SRC_HYPR_DIR="$REPO_DIR/config/hypr"
+DEST_HYPR_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr"
+BACKUP_DIR="${DEST_HYPR_DIR}-backup-lua-$(date +%Y%m%d-%H%M%S)"
+MIGRATION_TS="$(date +%Y%m%d-%H%M%S)"
+DRY_RUN=0
+YES=0
+REVERT=0
+
+USER_CONFIGS_DIR="$DEST_HYPR_DIR/UserConfigs"
+CONFIGS_DIR="$DEST_HYPR_DIR/configs"
+LEGACY_CONFIGS_DIR_NAME="LegacyConfigs"
+USER_WINDOW_RULES="$USER_CONFIGS_DIR/WindowRules.conf"
+USER_KEYBINDS="$USER_CONFIGS_DIR/UserKeybinds.conf"
+USER_ENV_VARS="$USER_CONFIGS_DIR/ENVariables.conf"
+USER_STARTUP_APPS="$USER_CONFIGS_DIR/Startup_Apps.conf"
+USER_SETTINGS="$USER_CONFIGS_DIR/UserSettings.conf"
+USER_DECORATIONS="$USER_CONFIGS_DIR/UserDecorations.conf"
+USER_ANIMATIONS="$USER_CONFIGS_DIR/UserAnimations.conf"
+USER_LAPTOPS="$USER_CONFIGS_DIR/Laptops.conf"
+USER_LAYER_RULES="$USER_CONFIGS_DIR/LayerRules.conf"
+SYSTEM_WINDOW_RULES="$CONFIGS_DIR/WindowRules.conf"
+SYSTEM_LAYER_RULES="$CONFIGS_DIR/LayerRules.conf"
+SYSTEM_KEYBINDS="$CONFIGS_DIR/Keybinds.conf"
+SYSTEM_ENV_VARS="$CONFIGS_DIR/ENVariables.conf"
+SYSTEM_STARTUP_APPS="$CONFIGS_DIR/Startup_Apps.conf"
+SYSTEM_SETTINGS="$CONFIGS_DIR/SystemSettings.conf"
+SYSTEM_LAPTOPS="$CONFIGS_DIR/Laptops.conf"
+USER_CONFIGS_LEGACY_ROOT="$USER_CONFIGS_DIR/$LEGACY_CONFIGS_DIR_NAME"
+CONFIGS_LEGACY_ROOT="$CONFIGS_DIR/$LEGACY_CONFIGS_DIR_NAME"
+USER_CONFIGS_LEGACY_DIR="$USER_CONFIGS_LEGACY_ROOT/$MIGRATION_TS"
+CONFIGS_LEGACY_DIR="$CONFIGS_LEGACY_ROOT/$MIGRATION_TS"
+USER_OVERRIDES_SHIM="$DEST_HYPR_DIR/lua/user_overrides.lua"
+DEST_MONITORS_CONF="$DEST_HYPR_DIR/monitors.conf"
+DEST_LUA_MONITORS="$DEST_HYPR_DIR/lua/monitors.lua"
+DEST_WORKSPACES_CONF="$DEST_HYPR_DIR/workspaces.conf"
+DEST_LUA_WORKSPACES="$DEST_HYPR_DIR/lua/workspaces.lua"
+SOURCE_LUA_ENTRY_ENABLED="$SRC_HYPR_DIR/hyprland.lua"
+SOURCE_LUA_ENTRY_DISABLED="$SRC_HYPR_DIR/hyprland.lua.disable"
+DEST_LUA_ENTRY="$DEST_HYPR_DIR/hyprland.lua"
+DEST_LUA_ENTRY_DISABLED="$DEST_HYPR_DIR/hyprland.lua.disable"
+SOURCE_LUA_ENTRY=""
+
+usage() {
+ cat <<USAGE
+Usage: $(basename "$0") [--yes] [--dry-run] [--revert]
+
+Copies the repo's Hyprland Lua entrypoint into:
+ $DEST_HYPR_DIR
+
+This preserves hyprland.conf as fallback and creates a full backup of the
+current Hyprland config directory before changing files.
+
+Options:
+ -y, --yes Run without confirmation prompts.
+ -n, --dry-run Show what would change without copying files.
+ -r, --revert Revert migration by restoring latest LegacyConfigs/<timestamp> .conf files.
+ -h, --help Show this help.
+USAGE
+}
+
+while [ "$#" -gt 0 ]; do
+ case "$1" in
+ -y|--yes)
+ YES=1
+ ;;
+ -n|--dry-run)
+ DRY_RUN=1
+ ;;
+ -r|--revert)
+ REVERT=1
+ ;;
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ *)
+ echo "[ERROR] Unknown option: $1" >&2
+ usage >&2
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+if [ -f "$SOURCE_LUA_ENTRY_ENABLED" ]; then
+ SOURCE_LUA_ENTRY="$SOURCE_LUA_ENTRY_ENABLED"
+elif [ -f "$SOURCE_LUA_ENTRY_DISABLED" ]; then
+ SOURCE_LUA_ENTRY="$SOURCE_LUA_ENTRY_DISABLED"
+fi
+
+if [ "$REVERT" -eq 0 ] && [ ! -d "$SRC_HYPR_DIR/lua" ]; then
+ echo "[ERROR] Lua config source files were not found under $SRC_HYPR_DIR" >&2
+ exit 1
+fi
+
+if [ "$REVERT" -eq 0 ] && [ -z "$SOURCE_LUA_ENTRY" ] && [ ! -f "$DEST_LUA_ENTRY" ] && [ ! -f "$DEST_LUA_ENTRY_DISABLED" ]; then
+ echo "[ERROR] No Lua entrypoint was found at $SRC_HYPR_DIR/hyprland.lua(.disable) or $DEST_HYPR_DIR/hyprland.lua(.disable)" >&2
+ exit 1
+fi
+
+if command -v Hyprland >/dev/null 2>&1; then
+ HYPR_VERSION="$(Hyprland --version 2>/dev/null | sed -n '1p' || true)"
+ echo "[INFO] Detected $HYPR_VERSION"
+else
+ echo "[WARN] Hyprland binary was not found in PATH; continuing because this may be an offline config migration."
+fi
+
+echo "[INFO] Source: $SRC_HYPR_DIR"
+echo "[INFO] Target: $DEST_HYPR_DIR"
+echo "[INFO] Backup: $BACKUP_DIR"
+if [ "$REVERT" -eq 1 ]; then
+ echo "[WARN] Revert mode: restores latest LegacyConfigs/<timestamp> .conf files in UserConfigs and configs."
+else
+ echo "[WARN] This enables Hyprland's Lua entrypoint for builds that support hyprland.lua."
+ echo "[WARN] hyprland.conf remains in place as fallback; old .conf files move into LegacyConfigs/<timestamp>."
+ echo "[INFO] hypridle.conf and hyprlock*.conf stay as native .conf files because Hypridle/Hyprlock do not use Hyprland's Lua API."
+fi
+
+restore_latest_conf_backup() {
+ local target_dir="$1"
+ local label="$2"
+ local latest_archive=""
+ local legacy_root="$target_dir/$LEGACY_CONFIGS_DIR_NAME"
+ local moved=0
+ local file
+ local archives=()
+
+ [ -d "$target_dir" ] || return 0
+
+ if [ -d "$legacy_root" ]; then
+ mapfile -t archives < <(find "$legacy_root" -mindepth 1 -maxdepth 1 -type d | sort)
+ fi
+
+ if [ "${#archives[@]}" -eq 0 ]; then
+ mapfile -t archives < <(find "$target_dir" -mindepth 1 -maxdepth 1 -type d -name 'backup-*' | sort)
+ fi
+
+ [ "${#archives[@]}" -gt 0 ] || return 0
+ latest_archive="${archives[${#archives[@]}-1]}"
+
+ while IFS= read -r -d '' file; do
+ cp -a "$file" "$target_dir/"
+ moved=1
+ done < <(find "$latest_archive" -maxdepth 1 -type f -name '*.conf' -print0)
+
+ if [ "$moved" -eq 1 ]; then
+ echo "[OK] Restored $label/*.conf from $latest_archive"
+ else
+ echo "[INFO] No .conf files found in latest archive for $label: $latest_archive"
+ fi
+}
+
+if [ "$YES" -eq 0 ]; then
+ if [ "$REVERT" -eq 1 ]; then
+ printf "[ACTION] Continue and revert Lua migration using latest legacy archives? [y/N] "
+ else
+ printf "[ACTION] Continue with Lua config migration? [y/N] "
+ fi
+ read -r reply
+ case "$reply" in
+ [Yy]|[Yy][Ee][Ss])
+ ;;
+ *)
+ echo "[INFO] Cancelled. No changes made."
+ exit 0
+ ;;
+ esac
+fi
+
+if [ "$DRY_RUN" -eq 1 ]; then
+ if [ "$REVERT" -eq 1 ]; then
+ if [ -f "$DEST_LUA_ENTRY" ]; then
+ echo "[DRY-RUN] Would disable Lua entrypoint: $DEST_LUA_ENTRY -> $DEST_LUA_ENTRY_DISABLED"
+ elif [ -f "$DEST_LUA_ENTRY_DISABLED" ]; then
+ echo "[DRY-RUN] Lua entrypoint already disabled: $DEST_LUA_ENTRY_DISABLED"
+ else
+ echo "[DRY-RUN] No Lua entrypoint found to disable at: $DEST_LUA_ENTRY"
+ fi
+ echo "[DRY-RUN] Would restore latest LegacyConfigs/<timestamp> .conf files into:"
+ echo "[DRY-RUN] - $USER_CONFIGS_DIR"
+ echo "[DRY-RUN] - $CONFIGS_DIR"
+ else
+ echo "[DRY-RUN] Would create target directory if missing: $DEST_HYPR_DIR"
+ if [ -d "$DEST_HYPR_DIR" ]; then
+ echo "[DRY-RUN] Would copy backup: $DEST_HYPR_DIR -> $BACKUP_DIR"
+ fi
+ if [ -f "$DEST_LUA_ENTRY_DISABLED" ]; then
+ echo "[DRY-RUN] Would enable Lua entrypoint: $DEST_LUA_ENTRY_DISABLED -> $DEST_LUA_ENTRY"
+ elif [ -f "$DEST_LUA_ENTRY" ]; then
+ echo "[DRY-RUN] Lua entrypoint already enabled: $DEST_LUA_ENTRY"
+ elif [ -n "$SOURCE_LUA_ENTRY" ]; then
+ echo "[DRY-RUN] Would install Lua entrypoint: $SOURCE_LUA_ENTRY -> $DEST_LUA_ENTRY"
+ fi
+ echo "[DRY-RUN] Would replace Lua module directory: $DEST_HYPR_DIR/lua"
+ echo "[DRY-RUN] Would generate split configs/UserConfigs Lua overlays:"
+ echo "[DRY-RUN] - $CONFIGS_DIR/system_env.lua"
+ echo "[DRY-RUN] - $CONFIGS_DIR/system_startup.lua"
+ echo "[DRY-RUN] - $CONFIGS_DIR/system_window_rules.lua"
+ echo "[DRY-RUN] - $CONFIGS_DIR/system_layer_rules.lua"
+ echo "[DRY-RUN] - $CONFIGS_DIR/system_keybinds.lua"
+ echo "[DRY-RUN] - $CONFIGS_DIR/system_settings.lua"
+ echo "[DRY-RUN] - $CONFIGS_DIR/system_laptops.lua"
+ echo "[DRY-RUN] - $USER_CONFIGS_DIR/user_env.lua"
+ echo "[DRY-RUN] - $USER_CONFIGS_DIR/user_startup.lua"
+ echo "[DRY-RUN] - $USER_CONFIGS_DIR/user_window_rules.lua"
+ echo "[DRY-RUN] - $USER_CONFIGS_DIR/user_layer_rules.lua"
+ echo "[DRY-RUN] - $USER_CONFIGS_DIR/user_keybinds.lua"
+ echo "[DRY-RUN] - $USER_CONFIGS_DIR/user_settings.lua"
+ echo "[DRY-RUN] - $USER_CONFIGS_DIR/user_decorations.lua"
+ echo "[DRY-RUN] - $USER_CONFIGS_DIR/user_animations.lua"
+ echo "[DRY-RUN] - $USER_CONFIGS_DIR/user_laptops.lua"
+ echo "[DRY-RUN] - $USER_CONFIGS_DIR/user_defaults.lua"
+ echo "[DRY-RUN] - $DEST_LUA_MONITORS (generated from $DEST_MONITORS_CONF)"
+ echo "[DRY-RUN] - $DEST_LUA_WORKSPACES (generated from $DEST_WORKSPACES_CONF)"
+ if [ -d "$USER_CONFIGS_DIR" ]; then
+ echo "[DRY-RUN] Would move UserConfigs/*.conf into: $USER_CONFIGS_LEGACY_DIR"
+ fi
+ if [ -d "$CONFIGS_DIR" ]; then
+ echo "[DRY-RUN] Would move configs/*.conf into: $CONFIGS_LEGACY_DIR"
+ fi
+ fi
+ exit 0
+fi
+if [ "$REVERT" -eq 1 ]; then
+ if [ -f "$DEST_LUA_ENTRY" ]; then
+ mv -f "$DEST_LUA_ENTRY" "$DEST_LUA_ENTRY_DISABLED"
+ echo "[OK] Disabled Lua entrypoint: $DEST_LUA_ENTRY_DISABLED"
+ elif [ -f "$DEST_LUA_ENTRY_DISABLED" ]; then
+ echo "[INFO] Lua entrypoint already disabled: $DEST_LUA_ENTRY_DISABLED"
+ else
+ echo "[INFO] No Lua entrypoint found to disable at $DEST_LUA_ENTRY"
+ fi
+ restore_latest_conf_backup "$USER_CONFIGS_DIR" "$USER_CONFIGS_DIR"
+ restore_latest_conf_backup "$CONFIGS_DIR" "$CONFIGS_DIR"
+ echo "[OK] Revert complete."
+ echo "[INFO] Restart Hyprland to load restored .conf files."
+ exit 0
+fi
+
+mkdir -p "$DEST_HYPR_DIR"
+
+if [ -d "$DEST_HYPR_DIR" ] && [ -n "$(find "$DEST_HYPR_DIR" -mindepth 1 -maxdepth 1 -print -quit)" ]; then
+ cp -a "$DEST_HYPR_DIR" "$BACKUP_DIR"
+ echo "[OK] Backup created at $BACKUP_DIR"
+fi
+if [ -f "$DEST_LUA_ENTRY_DISABLED" ]; then
+ if [ -f "$DEST_LUA_ENTRY" ]; then
+ rm -f "$DEST_LUA_ENTRY_DISABLED"
+ echo "[INFO] Removed duplicate disabled entrypoint: $DEST_LUA_ENTRY_DISABLED"
+ else
+ mv "$DEST_LUA_ENTRY_DISABLED" "$DEST_LUA_ENTRY"
+ echo "[OK] Enabled Lua entrypoint: $DEST_LUA_ENTRY"
+ fi
+elif [ -f "$DEST_LUA_ENTRY" ]; then
+ echo "[INFO] Lua entrypoint already enabled: $DEST_LUA_ENTRY"
+elif [ -n "$SOURCE_LUA_ENTRY" ]; then
+ cp -f "$SOURCE_LUA_ENTRY" "$DEST_LUA_ENTRY"
+ echo "[OK] Installed Lua entrypoint: $SOURCE_LUA_ENTRY -> $DEST_LUA_ENTRY"
+else
+ echo "[ERROR] Unable to locate a Lua entrypoint to enable." >&2
+ exit 1
+fi
+rm -rf "$DEST_HYPR_DIR/lua"
+cp -a "$SRC_HYPR_DIR/lua" "$DEST_HYPR_DIR/lua"
+mkdir -p "$USER_CONFIGS_DIR" "$CONFIGS_DIR"
+python3 - \
+ "$CONFIGS_DIR" \
+ "$USER_CONFIGS_DIR" \
+ "$SYSTEM_WINDOW_RULES" \
+ "$SYSTEM_LAYER_RULES" \
+ "$SYSTEM_KEYBINDS" \
+ "$SYSTEM_ENV_VARS" \
+ "$SYSTEM_STARTUP_APPS" \
+ "$SYSTEM_SETTINGS" \
+ "$SYSTEM_LAPTOPS" \
+ "$USER_WINDOW_RULES" \
+ "$USER_LAYER_RULES" \
+ "$USER_KEYBINDS" \
+ "$USER_ENV_VARS" \
+ "$USER_STARTUP_APPS" \
+ "$USER_SETTINGS" \
+ "$USER_DECORATIONS" \
+ "$USER_ANIMATIONS" \
+ "$USER_LAPTOPS" \
+ "$USER_CONFIGS_DIR/01-UserDefaults.conf" \
+ "$DEST_MONITORS_CONF" \
+ "$DEST_LUA_MONITORS" \
+ "$DEST_WORKSPACES_CONF" \
+ "$DEST_LUA_WORKSPACES" <<'PY'
+import os
+import re
+import sys
+from pathlib import Path
+HEADER = """-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+"""
+system_configs_dir = Path(sys.argv[1])
+user_configs_dir = Path(sys.argv[2])
+system_window_rules_path = Path(sys.argv[3])
+system_layer_rules_path = Path(sys.argv[4])
+system_keybinds_path = Path(sys.argv[5])
+system_env_path = Path(sys.argv[6])
+system_startup_path = Path(sys.argv[7])
+system_settings_path = Path(sys.argv[8])
+system_laptops_path = Path(sys.argv[9])
+window_rules_path = Path(sys.argv[10])
+layer_rules_path = Path(sys.argv[11])
+keybinds_path = Path(sys.argv[12])
+env_path = Path(sys.argv[13])
+startup_path = Path(sys.argv[14])
+settings_path = Path(sys.argv[15])
+decorations_path = Path(sys.argv[16])
+animations_path = Path(sys.argv[17])
+laptops_path = Path(sys.argv[18])
+user_defaults_path = Path(sys.argv[19])
+monitors_conf_path = Path(sys.argv[20])
+monitors_lua_path = Path(sys.argv[21])
+workspaces_conf_path = Path(sys.argv[22])
+workspaces_lua_path = Path(sys.argv[23])
+
+files_out = {
+ "system_env": system_configs_dir / "system_env.lua",
+ "system_startup": system_configs_dir / "system_startup.lua",
+ "system_window_rules": system_configs_dir / "system_window_rules.lua",
+ "system_layer_rules": system_configs_dir / "system_layer_rules.lua",
+ "system_keybinds": system_configs_dir / "system_keybinds.lua",
+ "system_settings": system_configs_dir / "system_settings.lua",
+ "system_laptops": system_configs_dir / "system_laptops.lua",
+ "env": user_configs_dir / "user_env.lua",
+ "startup": user_configs_dir / "user_startup.lua",
+ "window_rules": user_configs_dir / "user_window_rules.lua",
+ "layer_rules": user_configs_dir / "user_layer_rules.lua",
+ "keybinds": user_configs_dir / "user_keybinds.lua",
+ "settings": user_configs_dir / "user_settings.lua",
+ "decorations": user_configs_dir / "user_decorations.lua",
+ "animations": user_configs_dir / "user_animations.lua",
+ "laptops": user_configs_dir / "user_laptops.lua",
+ "user_defaults": user_configs_dir / "user_defaults.lua",
+ "monitors": monitors_lua_path,
+ "workspaces": workspaces_lua_path,
+}
+
+def strip_comment(line):
+ return line.split("#", 1)[0].strip()
+
+def split_items(value):
+ return [item.strip() for item in value.split(",") if item.strip()]
+
+def lua_string(value):
+ return '"' + value.replace("\\", "\\\\").replace('"', '\\"') + '"'
+def write_file(path, lines):
+ content = "\n".join(lines).rstrip() + "\n"
+ if not content.startswith(HEADER):
+ content = HEADER + "\n" + content.lstrip("\n")
+ path.write_text(content, encoding="utf-8")
+ print(f"[OK] Wrote {path}")
+
+def source_examples(path):
+ if not path.exists():
+ return []
+ lines = []
+ for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines():
+ stripped = raw.strip()
+ if not stripped or stripped.startswith("#"):
+ continue
+ lines.append(f"-- {stripped}")
+ return lines
+def latest_legacy_file(path):
+ legacy_root = path.parent / "LegacyConfigs"
+ if not legacy_root.is_dir():
+ return None
+ candidates = []
+ for snapshot in sorted(legacy_root.iterdir()):
+ if not snapshot.is_dir():
+ continue
+ candidate = snapshot / path.name
+ if candidate.is_file():
+ candidates.append(candidate)
+ return candidates[-1] if candidates else None
+
+def parse_env(path):
+ entries = []
+ source_path = path if path.exists() else latest_legacy_file(path)
+ if source_path is None:
+ return entries
+ if source_path != path:
+ print(f"[INFO] {path.name} not found at {path}; using legacy source {source_path}")
+ for raw in source_path.read_text(encoding="utf-8", errors="ignore").splitlines():
+ line = strip_comment(raw)
+ if not line:
+ continue
+ comma_match = re.match(r"^env\s*=\s*([^,]+)\s*,\s*(.+)$", line)
+ if comma_match:
+ entries.append((comma_match.group(1).strip(), comma_match.group(2).strip()))
+ continue
+ equals_match = re.match(r"^env\s*=\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.+)$", line)
+ if equals_match:
+ entries.append((equals_match.group(1).strip(), equals_match.group(2).strip()))
+ return entries
+
+def parse_startup(path, *, variables=None, visited=None):
+ entries = []
+ if not path.exists():
+ return entries
+
+ if variables is None:
+ variables = {}
+ if visited is None:
+ visited = set()
+
+ try:
+ resolved = path.resolve()
+ except FileNotFoundError:
+ resolved = path
+
+ if resolved in visited:
+ return []
+ visited.add(resolved)
+
+ def expand(value):
+ for _ in range(8):
+ new_value = value
+ for name, var_value in variables.items():
+ new_value = new_value.replace(f"${name}", var_value)
+ if new_value == value:
+ break
+ value = new_value
+ return os.path.expandvars(value)
+
+ for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines():
+ line = strip_comment(raw)
+ if not line:
+ continue
+
+ source_match = re.match(r"^source\s*=\s*(.+)$", line)
+ if source_match:
+ source_value = expand(source_match.group(1).strip())
+ source_path = Path(source_value).expanduser()
+ entries.extend(parse_startup(source_path, variables=variables, visited=visited))
+ continue
+
+ variable = re.match(r"^\$([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.+)$", line)
+ if variable:
+ variables[variable.group(1)] = expand(variable.group(2).strip())
+ continue
+
+ match = re.match(r"^exec(?:-once)?\s*=\s*(.+)$", line)
+ if match:
+ entries.append(expand(match.group(1).strip()))
+
+ return entries
+
+MONITOR_DIRECTIVE_KEYS = {
+ "mirror",
+ "bitdepth",
+ "transform",
+ "cm",
+ "icc",
+ "vrr",
+ "addreserved",
+ "reserved",
+ "supports_hdr",
+ "supports_wide_color",
+ "supportshdr",
+ "supportswidecolor",
+ "max_luminance",
+ "max_avg_luminance",
+ "min_luminance",
+ "maxluminance",
+ "maxavgluminance",
+ "minluminance",
+ "sdr_max_luminance",
+ "sdr_min_luminance",
+ "sdr_eotf",
+ "sdrmaxluminance",
+ "sdrminluminance",
+ "sdreotf",
+ "sdrbrightness",
+ "sdrsaturation",
+}
+
+MONITOR_FIELD_MAP = {
+ "addreserved": "reserved",
+ "supportswidecolor": "supports_wide_color",
+ "supportshdr": "supports_hdr",
+ "maxluminance": "max_luminance",
+ "maxavgluminance": "max_avg_luminance",
+ "minluminance": "min_luminance",
+ "sdrmaxluminance": "sdr_max_luminance",
+ "sdrminluminance": "sdr_min_luminance",
+ "sdreotf": "sdr_eotf",
+}
+
+def parse_monitors(path):
+ entries = []
+ if not path.exists():
+ return entries
+
+ for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines():
+ line = strip_comment(raw)
+ if not line:
+ continue
+ match = re.match(r"^monitor\s*=\s*(.+)$", line)
+ if not match:
+ continue
+
+ parts = [part.strip() for part in match.group(1).split(",")]
+ if len(parts) < 2:
+ continue
+
+ spec = {"output": parts[0]}
+ mode_or_directive = parts[1].lower().replace("-", "_")
+ extras = []
+
+ if mode_or_directive == "disable":
+ spec["mode"] = "disable"
+ entries.append(spec)
+ continue
+
+ if len(parts) >= 4 and mode_or_directive not in MONITOR_DIRECTIVE_KEYS:
+ spec["mode"] = parts[1]
+ if parts[2]:
+ spec["position"] = parts[2]
+ if parts[3]:
+ spec["scale"] = parts[3]
+ extras = parts[4:]
+ else:
+ extras = parts[1:]
+
+ i = 0
+ while i < len(extras):
+ key = extras[i].strip().lower().replace("-", "_")
+ if not key:
+ i += 1
+ continue
+ field = MONITOR_FIELD_MAP.get(key, key)
+
+ if field == "reserved" and i + 4 < len(extras):
+ spec["reserved"] = [
+ extras[i + 1].strip(),
+ extras[i + 2].strip(),
+ extras[i + 3].strip(),
+ extras[i + 4].strip(),
+ ]
+ i += 5
+ continue
+
+ if i + 1 >= len(extras):
+ i += 1
+ continue
+
+ value = extras[i + 1].strip()
+ if value:
+ spec[field] = value
+ i += 2
+
+ entries.append(spec)
+
+ return entries
+def parse_bool_word(value):
+ lowered = value.strip().lower()
+ if lowered in {"on", "true", "yes"}:
+ return True
+ if lowered in {"off", "false", "no"}:
+ return False
+ return None
+
+WORKSPACE_FIELD_MAP = {
+ "gapsin": "gaps_in",
+ "gapsout": "gaps_out",
+ "bordersize": "border_size",
+ "on_created_empty": "on_created_empty",
+ "layoutopt": "layout_opts",
+ "layoutopts": "layout_opts",
+}
+
+WORKSPACE_INVERTED_BOOL_FIELDS = {
+ "border": "no_border",
+ "rounding": "no_rounding",
+ "shadow": "no_shadow",
+}
+
+def parse_workspaces(path):
+ entries = []
+ if not path.exists():
+ return entries
+
+ for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines():
+ line = strip_comment(raw)
+ if not line:
+ continue
+ match = re.match(r"^workspace\s*=\s*(.+)$", line)
+ if not match:
+ continue
+
+ parts = [part.strip() for part in match.group(1).split(",")]
+ if not parts or not parts[0]:
+ continue
+
+ rule = {"workspace": parts[0]}
+ for part in parts[1:]:
+ if ":" not in part:
+ continue
+ key, value = part.split(":", 1)
+ key = key.strip().lower().replace("-", "_")
+ value = value.strip()
+ if not key or value == "":
+ continue
+
+ if key in WORKSPACE_INVERTED_BOOL_FIELDS:
+ bool_value = parse_bool_word(value)
+ if bool_value is None:
+ continue
+ rule[WORKSPACE_INVERTED_BOOL_FIELDS[key]] = not bool_value
+ continue
+
+ normalized = WORKSPACE_FIELD_MAP.get(key, key)
+ bool_value = parse_bool_word(value)
+ if bool_value is not None:
+ rule[normalized] = bool_value
+ else:
+ rule[normalized] = value
+
+ entries.append(rule)
+
+ return entries
+
+def emit_monitor(spec):
+ lines = [
+ "hl.monitor({",
+ f" output = {lua_string(spec.get('output', ''))},",
+ ]
+
+ if "mode" in spec:
+ lines.append(f" mode = {lua_string(spec['mode'])},")
+ if "position" in spec:
+ lines.append(f" position = {lua_string(spec['position'])},")
+ if "scale" in spec:
+ lines.append(f" scale = {lua_string(spec['scale'])},")
+ if "mirror" in spec:
+ lines.append(f" mirror = {lua_string(spec['mirror'])},")
+
+ for key in [
+ "bitdepth",
+ "transform",
+ "vrr",
+ "supports_hdr",
+ "supports_wide_color",
+ "max_luminance",
+ "max_avg_luminance",
+ "min_luminance",
+ "sdr_max_luminance",
+ "sdr_min_luminance",
+ "sdrbrightness",
+ "sdrsaturation",
+ ]:
+ if key in spec:
+ lines.append(f" {key} = {scalar(spec[key])},")
+
+ for key in ["cm", "icc", "sdr_eotf"]:
+ if key in spec:
+ lines.append(f" {key} = {lua_string(spec[key])},")
+
+ if "reserved" in spec and len(spec["reserved"]) == 4:
+ top, right, bottom, left = spec["reserved"]
+ lines.extend([
+ " reserved = {",
+ f" top = {scalar(top)},",
+ f" right = {scalar(right)},",
+ f" bottom = {scalar(bottom)},",
+ f" left = {scalar(left)},",
+ " },",
+ ])
+
+ lines.append("})")
+ return "\n".join(lines)
+
+def emit_workspace_rule(spec):
+ lines = [
+ "hl.workspace_rule({",
+ f" workspace = {lua_string(spec['workspace'])},",
+ ]
+ for key, value in spec.items():
+ if key == "workspace":
+ continue
+ if isinstance(value, bool):
+ rendered = "true" if value else "false"
+ else:
+ text = str(value).strip()
+ if re.fullmatch(r"[-+]?\d+(\.\d+)?", text):
+ rendered = text
+ else:
+ rendered = lua_string(text)
+ lines.append(f" {key} = {rendered},")
+ lines.append("})")
+ return "\n".join(lines)
+def unquote(value):
+ value = value.strip()
+ if len(value) >= 2 and (
+ (value[0] == "\"" and value[-1] == "\"")
+ or (value[0] == "'" and value[-1] == "'")
+ ):
+ return value[1:-1]
+ return value
+
+def resolve_shell_default(value):
+ value = value.strip()
+ match = re.fullmatch(r"\$\{([A-Za-z_][A-Za-z0-9_]*)\:-([^}]*)\}", value)
+ if match:
+ env_value = os.getenv(match.group(1), "")
+ return env_value if env_value else match.group(2)
+ match = re.fullmatch(r"\$\{([A-Za-z_][A-Za-z0-9_]*)-([^}]*)\}", value)
+ if match:
+ env_value = os.getenv(match.group(1))
+ return env_value if env_value is not None else match.group(2)
+ match = re.fullmatch(r"\$([A-Za-z_][A-Za-z0-9_]*)", value)
+ if match:
+ return os.getenv(match.group(1), "")
+ return value
+
+def parse_user_defaults(path):
+ defaults = {}
+ if not path.exists():
+ return defaults
+ for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines():
+ line = strip_comment(raw)
+ if not line:
+ continue
+ match = re.match(r"^\$([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.+)$", line)
+ if not match:
+ continue
+ key = match.group(1)
+ value = unquote(resolve_shell_default(match.group(2)))
+ defaults[key] = value
+ return defaults
+
+def parse_hyprlang_sections(path):
+ sections = {}
+ if path is None or not path.exists():
+ return sections
+
+ stack = [sections]
+ for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines():
+ line = strip_comment(raw)
+ if not line:
+ continue
+ if line.startswith("source"):
+ continue
+ if line.endswith("{"):
+ name = line[:-1].strip().replace("-", "_")
+ if not name or name.startswith("$"):
+ continue
+ current = stack[-1]
+ target = current.setdefault(name, {})
+ stack.append(target)
+ continue
+ if line == "}":
+ if len(stack) > 1:
+ stack.pop()
+ continue
+ if "=" in line:
+ key, value = [part.strip() for part in line.split("=", 1)]
+ if not key or key.startswith("$"):
+ continue
+ key = key.replace("-", "_")
+ container = stack[-1]
+ parts = [part.replace("-", "_") for part in key.split(".") if part]
+ for part in parts[:-1]:
+ container = container.setdefault(part, {})
+ container[parts[-1]] = value
+ return sections
+
+def parse_scripts_dir(path):
+ if path is None or not path.exists():
+ return None
+ for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines():
+ line = strip_comment(raw)
+ if not line:
+ continue
+ match = re.match(r"^\\$scriptsDir\\s*=\\s*(.+)$", line)
+ if match:
+ return unquote(match.group(1).strip())
+ return None
+
+def parse_gestures(path):
+ simple = []
+ complex_entries = []
+ if path is None or not path.exists():
+ return simple, complex_entries
+ for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines():
+ line = strip_comment(raw)
+ if not line:
+ continue
+ match = re.match(r"^gesture\\s*=\\s*(.+)$", line)
+ if not match:
+ continue
+ payload = match.group(1).strip()
+ parts = [part.strip() for part in payload.split(",")]
+ if len(parts) >= 3 and parts[2] == "workspace":
+ try:
+ fingers = int(parts[0])
+ except ValueError:
+ complex_entries.append(payload)
+ continue
+ simple.append({
+ "fingers": fingers,
+ "direction": parts[1],
+ "action": "workspace",
+ })
+ else:
+ complex_entries.append(payload)
+ return simple, complex_entries
+
+WALLUST_FALLBACKS = {
+ "color12": "rgba(8db4ffff)",
+ "color10": "rgba(5f6578ff)",
+ "color15": "rgba(ffffffff)",
+ "color0": "rgba(0f111aff)",
+}
+
+def wallust_expr(value):
+ value = value.strip()
+ if not value.startswith("$"):
+ return None
+ var = value[1:].strip().lower()
+ if re.fullmatch(r"color\d+", var):
+ fallback = WALLUST_FALLBACKS.get(var)
+ if fallback:
+ return f"wallust_color({lua_string(var)}, {lua_string(fallback)})"
+ return f"wallust_color({lua_string(var)})"
+ return None
+
+def lua_value(value):
+ wallust_value = wallust_expr(value)
+ if wallust_value is not None:
+ return wallust_value
+ return scalar(value)
+
+def render_table(value, indent=4):
+ lines = []
+ for key, child in value.items():
+ if isinstance(child, dict):
+ lines.append(" " * indent + f"{key} = {{")
+ lines.extend(render_table(child, indent + 2))
+ lines.append(" " * indent + "},")
+ else:
+ rendered = lua_value(str(child))
+ if rendered is None:
+ continue
+ lines.append(" " * indent + f"{key} = {rendered},")
+ return lines
+
+def scalar(value, *, bool_words=True):
+ value = value.strip()
+ lower = value.lower()
+ if bool_words and lower in {"on", "true", "yes"}:
+ return "true"
+ if bool_words and lower in {"off", "false", "no"}:
+ return "false"
+ if re.fullmatch(r"[-+]?\d+(\.\d+)?", value):
+ return value
+ return lua_string(value)
+
+def normalize_field(name):
+ aliases = {
+ "floating": "float",
+ "pinned": "pin",
+ "fullscreenstate": "fullscreen_state",
+ "initialclass": "initial_class",
+ "initialtitle": "initial_title",
+ "xdgtag": "xdg_tag",
+ "onworkspace": "workspace",
+ "ignorealpha": "ignore_alpha",
+ "ignorezero": "ignore_zero",
+ "noanim": "no_anim",
+ "noblur": "no_blur",
+ "noshadow": "no_shadow",
+ "nofocus": "no_focus",
+ "noinitialfocus": "no_initial_focus",
+ "keepaspectratio": "keep_aspect_ratio",
+ "idleinhibit": "idle_inhibit",
+ "bordersize": "border_size",
+ "bordercolor": "border_color",
+ "roundingpower": "rounding_power",
+ "allowsinput": "allows_input",
+ "dimaround": "dim_around",
+ "focusonactivate": "focus_on_activate",
+ "nearestneighbor": "nearest_neighbor",
+ "nofollowmouse": "no_follow_mouse",
+ "noscreenshare": "no_screen_share",
+ "novrr": "no_vrr",
+ "forcergbx": "force_rgbx",
+ "suppressevent": "suppress_event",
+ "maxsize": "max_size",
+ "minsize": "min_size",
+ "persistentsize": "persistent_size",
+ "nomaxsize": "no_max_size",
+ }
+ compact = name.strip().replace("-", "_")
+ return aliases.get(compact.lower(), compact)
+
+MATCH_BOOL_FIELDS = {
+ "xwayland",
+ "float",
+ "fullscreen",
+ "pin",
+ "focus",
+ "group",
+ "modal",
+}
+
+def parse_rule_item(item, rule):
+ if item.startswith("match:"):
+ body = item[len("match:"):].strip()
+ if "=" in body:
+ key, value = body.split("=", 1)
+ else:
+ parts = body.split(None, 1)
+ if len(parts) != 2:
+ return
+ key, value = parts
+ key = normalize_field(key)
+ rule.setdefault("match", {})[key] = scalar(value, bool_words=key in MATCH_BOOL_FIELDS)
+ return
+
+ parts = item.split(None, 1)
+ key = normalize_field(parts[0])
+ value = parts[1] if len(parts) > 1 else "on"
+ rule[key] = scalar(value)
+
+def parse_block(lines, start_index):
+ rule_type = "window" if lines[start_index].strip().startswith("windowrule") else "layer"
+ rule = {"match": {}}
+ i = start_index + 1
+ while i < len(lines):
+ line = strip_comment(lines[i])
+ if line == "}":
+ break
+ if line:
+ if "=" in line:
+ key, value = [part.strip() for part in line.split("=", 1)]
+ if key.startswith("match:"):
+ match_key = normalize_field(key[len("match:"):])
+ rule["match"][match_key] = scalar(value, bool_words=match_key in MATCH_BOOL_FIELDS)
+ elif key == "name":
+ rule["name"] = lua_string(value)
+ else:
+ rule[normalize_field(key)] = scalar(value)
+ i += 1
+ return rule_type, rule, i
+
+def parse_rules(path, prefix):
+ if not path.exists():
+ return []
+
+ parsed = []
+ lines = path.read_text(encoding="utf-8", errors="ignore").splitlines()
+ i = 0
+ rule_index = 1
+ layer_index = 1
+ pending_name = None
+ while i < len(lines):
+ raw_line = lines[i]
+ name_hint = re.match(r"^\s*#\s*name\s*[:=]\s*(.+?)\s*$", raw_line)
+ if name_hint:
+ pending_name = lua_string(name_hint.group(1).strip())
+ i += 1
+ continue
+
+ line = strip_comment(raw_line)
+ if not line:
+ i += 1
+ continue
+
+ if re.match(r"^(windowrule|layerrule)\s*\{", line):
+ rule_type, rule, i = parse_block(lines, i)
+ if rule.get("match"):
+ if "name" not in rule:
+ if pending_name is not None:
+ rule["name"] = pending_name
+ elif rule_type == "window":
+ rule["name"] = lua_string(f"{prefix}-windowrule-{rule_index:03d}")
+ rule_index += 1
+ else:
+ rule["name"] = lua_string(f"{prefix}-layerrule-{layer_index:03d}")
+ layer_index += 1
+ pending_name = None
+ parsed.append((rule_type, rule))
+ i += 1
+ continue
+
+ match = re.match(r"^(windowrule|layerrule)\s*=\s*(.+)$", line)
+ if match:
+ rule_type = "window" if match.group(1) == "windowrule" else "layer"
+ rule = {"match": {}}
+ for item in split_items(match.group(2)):
+ parse_rule_item(item, rule)
+ if rule.get("match"):
+ if "name" not in rule:
+ if pending_name is not None:
+ rule["name"] = pending_name
+ elif rule_type == "window":
+ rule["name"] = lua_string(f"{prefix}-windowrule-{rule_index:03d}")
+ rule_index += 1
+ else:
+ rule["name"] = lua_string(f"{prefix}-layerrule-{layer_index:03d}")
+ layer_index += 1
+ pending_name = None
+ parsed.append((rule_type, rule))
+ else:
+ pending_name = None
+ i += 1
+ continue
+
+ pending_name = None
+ i += 1
+ return parsed
+
+def emit_rule(rule_type, rule):
+ fn = "apply_window_rule" if rule_type == "window" else "apply_layer_rule"
+ lines = [f"{fn}({{"]
+ if "name" in rule:
+ lines.append(f" name = {rule['name']},")
+ if rule.get("match"):
+ lines.append(" match = {")
+ for key, value in rule["match"].items():
+ lines.append(f" {key} = {value},")
+ lines.append(" },")
+ for key, value in rule.items():
+ if key in {"name", "match"}:
+ continue
+ lines.append(f" {key} = {value},")
+ lines.append("})")
+ return "\n".join(lines)
+
+def parse_keybinds(path, *, variables=None, visited=None):
+ if not path.exists():
+ return []
+
+ if variables is None:
+ variables = {}
+ if visited is None:
+ visited = set()
+
+ try:
+ resolved = path.resolve()
+ except FileNotFoundError:
+ resolved = path
+
+ if resolved in visited:
+ return []
+ visited.add(resolved)
+
+ converted = []
+
+ def expand(value):
+ for _ in range(8):
+ new_value = value
+ for name, var_value in variables.items():
+ new_value = new_value.replace(f"${name}", var_value)
+ if new_value == value:
+ return new_value
+ value = new_value
+ return value
+
+ for raw_line in path.read_text(encoding="utf-8", errors="ignore").splitlines():
+ line = strip_comment(raw_line)
+ if not line:
+ continue
+
+ source_match = re.match(r"^source\s*=\s*(.+)$", line)
+ if source_match:
+ source_value = expand(source_match.group(1).strip())
+ source_value = os.path.expandvars(source_value)
+ source_path = Path(source_value).expanduser()
+ converted.extend(parse_keybinds(source_path, variables=variables, visited=visited))
+ continue
+
+ variable = re.match(r"^\$([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.+)$", line)
+ if variable:
+ variables[variable.group(1)] = expand(variable.group(2).strip())
+ continue
+
+ unbind = re.match(r"^unbind\s*=\s*(.+)$", line)
+ if unbind:
+ parts = [expand(part.strip()) for part in unbind.group(1).split(",")]
+ if len(parts) >= 2:
+ converted.append(f"unbind({lua_string(parts[0])}, {lua_string(parts[1])})")
+ continue
+
+ bind = re.match(r"^(bind[a-z]*)\s*=\s*(.+)$", line)
+ if bind:
+ binder = bind.group(1)
+ parts = [expand(part.strip()) for part in bind.group(2).split(",")]
+ has_description = "d" in binder and binder != "bind"
+ description = ""
+ if has_description and len(parts) >= 4:
+ mods, key = parts[0], parts[1]
+ description = parts[2]
+ dispatcher = parts[3]
+ args = ", ".join(part for part in parts[4:] if part)
+ elif len(parts) >= 3:
+ mods, key = parts[0], parts[1]
+ dispatcher = parts[2]
+ args = ", ".join(part for part in parts[3:] if part)
+ else:
+ continue
+
+ opts = []
+ if description:
+ opts.append(f"description = {lua_string(description)}")
+ if "l" in binder:
+ opts.append("locked = true")
+ if "e" in binder or "r" in binder:
+ opts.append("[\"repeat\"] = true")
+ opts_text = ", { " + ", ".join(opts) + " }" if opts else ""
+
+ if dispatcher == "exec":
+ converted.append(f"bind({lua_string(mods)}, {lua_string(key)}, exec_cmd({lua_string(args)}){opts_text})")
+ else:
+ converted.append(f"bind({lua_string(mods)}, {lua_string(key)}, dispatch({lua_string(dispatcher)}, {lua_string(args)}){opts_text})")
+
+ return converted
+
+system_window_rules = [rule for rule in parse_rules(system_window_rules_path, "system-window") if rule[0] == "window"]
+system_layer_rules = [rule for rule in parse_rules(system_layer_rules_path, "system-layer") if rule[0] == "layer"]
+window_rules = [rule for rule in parse_rules(window_rules_path, "user-window") if rule[0] == "window"]
+layer_rules = [rule for rule in parse_rules(layer_rules_path, "user-layer") if rule[0] == "layer"]
+base_keybind_vars = {}
+parse_keybinds(user_defaults_path, variables=base_keybind_vars)
+system_keybinds = parse_keybinds(system_keybinds_path, variables=dict(base_keybind_vars))
+keybinds = parse_keybinds(keybinds_path, variables=dict(base_keybind_vars))
+system_env_entries = parse_env(system_env_path)
+env_entries = parse_env(env_path)
+system_startup_entries = parse_startup(system_startup_path, variables=dict(base_keybind_vars))
+startup_entries = parse_startup(startup_path, variables=dict(base_keybind_vars))
+monitor_entries = parse_monitors(monitors_conf_path)
+workspace_entries = parse_workspaces(workspaces_conf_path)
+parsed_user_defaults = parse_user_defaults(user_defaults_path)
+resolved_edit = parsed_user_defaults.get("edit", os.getenv("EDITOR") or "nano")
+resolved_visual = parsed_user_defaults.get("visual", os.getenv("VISUAL") or "")
+resolved_term = parsed_user_defaults.get("term", "kitty")
+resolved_files = parsed_user_defaults.get("files", "thunar")
+resolved_search_engine = parsed_user_defaults.get(
+ "Search_Engine",
+ parsed_user_defaults.get("search_engine", "https://www.google.com/search?q={}"),
+)
+
+user_defaults_lines = [
+ "-- User defaults overrides (auto-generated).",
+ "-- Edit this file for terminal/editor/file-manager/search defaults in Lua mode.",
+ "-- Example:",
+ "-- KOOLDOTS_DEFAULTS.term = \"ghostty\"",
+ "",
+ "KOOLDOTS_DEFAULTS = KOOLDOTS_DEFAULTS or {}",
+ f"KOOLDOTS_DEFAULTS.edit = {lua_string(resolved_edit)}",
+ f"KOOLDOTS_DEFAULTS.visual = {lua_string(resolved_visual)}",
+ f"KOOLDOTS_DEFAULTS.term = {lua_string(resolved_term)}",
+ f"KOOLDOTS_DEFAULTS.files = {lua_string(resolved_files)}",
+ f"KOOLDOTS_DEFAULTS.search_engine = {lua_string(resolved_search_engine)}",
+ f"KOOLDOTS_DEFAULTS.Search_Engine = {lua_string(resolved_search_engine)}",
+]
+write_file(files_out["user_defaults"], user_defaults_lines)
+
+if monitor_entries:
+ monitor_lines = [
+ "-- Monitors migrated from monitors.conf (auto-generated).",
+ "-- Edit monitors.conf and rerun scripts/migrate-hypr-to-lua.sh to regenerate this file.",
+ "",
+ ]
+ for spec in monitor_entries:
+ monitor_lines.append(emit_monitor(spec))
+ monitor_lines.append("")
+ write_file(files_out["monitors"], monitor_lines)
+else:
+ print(f"[INFO] No active monitor entries found in {monitors_conf_path}; keeping existing {files_out['monitors']}")
+if workspace_entries:
+ workspace_lines = [
+ "-- Workspace rules migrated from workspaces.conf (auto-generated).",
+ "-- Edit workspaces.conf and rerun scripts/migrate-hypr-to-lua.sh to regenerate this file.",
+ "",
+ ]
+ for spec in workspace_entries:
+ workspace_lines.append(emit_workspace_rule(spec))
+ workspace_lines.append("")
+ write_file(files_out["workspaces"], workspace_lines)
+else:
+ print(f"[INFO] No active workspace rules found in {workspaces_conf_path}; keeping existing {files_out['workspaces']}")
+system_env_lines = [
+ "-- System defaults migrated from configs/ENVariables.conf (auto-generated).",
+ "-- Edit this file to keep your previous configs/ ENVariables customizations in Lua mode.",
+ "-- Example:",
+ "-- hl.env(\"QT_QPA_PLATFORMTHEME\", \"qt6ct\")",
+ "",
+]
+if system_env_entries:
+ system_env_lines.append("-- Converted from configs/ENVariables.conf")
+ for key, value in system_env_entries:
+ system_env_lines.append(f"hl.env({lua_string(key)}, {lua_string(value)})")
+ write_file(files_out["system_env"], system_env_lines)
+else:
+ if files_out["system_env"].exists():
+ print(f"[INFO] No active env entries found in {system_env_path}; keeping existing {files_out['system_env']}")
+ else:
+ system_env_lines.append("-- No active env entries were found in configs/ENVariables.conf.")
+ write_file(files_out["system_env"], system_env_lines)
+
+startup_readiness = (
+ "runtime=${XDG_RUNTIME_DIR:-/run/user/$(id -u)}; "
+ "export XDG_RUNTIME_DIR=\"$runtime\"; "
+ "for _ in $(seq 1 200); do "
+ "if [ -n \"$WAYLAND_DISPLAY\" ] && [ -S \"$runtime/$WAYLAND_DISPLAY\" ]; then break; fi; "
+ "for sock in \"$runtime\"/wayland-[0-9]*; do [ -S \"$sock\" ] || continue; "
+ "case \"$(basename \"$sock\")\" in *awww*) continue ;; esac; "
+ "export WAYLAND_DISPLAY=\"$(basename \"$sock\")\"; break 2; done; "
+ "sleep 0.1; done; "
+ "if [ -n \"$HYPRLAND_INSTANCE_SIGNATURE\" ]; then "
+ "hypr_sock=\"$runtime/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket.sock\"; "
+ "for _ in $(seq 1 200); do [ -S \"$hypr_sock\" ] && break; sleep 0.1; done; fi"
+)
+
+system_startup_lines = [
+ "-- System defaults migrated from configs/Startup_Apps.conf (auto-generated).",
+ "-- Add commands with exec_once(\"your command\")",
+ "-- Example:",
+ "-- exec_once(\"swaync\")",
+ "",
+ "local session = os.getenv(\"HYPRLAND_INSTANCE_SIGNATURE\") or \"default\"",
+ "",
+ "local function shell_quote(value)",
+ " return \"'\" .. tostring(value):gsub(\"'\", \"'\\\\''\") .. \"'\"",
+ "end",
+ "",
+ "local function exec_once(cmd)",
+ " local key = cmd:gsub(\"[^%w_.-]\", \"_\"):sub(1, 80)",
+ " local marker = \"/tmp/hypr-lua-system-exec-once-\" .. session .. \"-\" .. key",
+ " local log = \"/tmp/hypr-lua-system-startup-\" .. key .. \".log\"",
+ f" local readiness = {lua_string(startup_readiness)}",
+ " local inner = readiness .. \"; \" .. cmd",
+ " local script = \"[ -e \" .. shell_quote(marker) .. \" ] || { touch \" .. shell_quote(marker) .. \" && sh -lc \" .. shell_quote(inner) .. \" >>\" .. shell_quote(log) .. \" 2>&1 & }\"",
+ " os.execute(\"sh -lc \" .. shell_quote(script))",
+ "end",
+ "",
+]
+if system_startup_entries:
+ system_startup_lines.append("-- Converted from configs/Startup_Apps.conf")
+ system_startup_lines.append("local startup_commands = {")
+ for cmd in system_startup_entries:
+ system_startup_lines.append(f" {lua_string(cmd)},")
+ system_startup_lines.extend([
+ "}",
+ "",
+ "local function run_startup_commands()",
+ " for _, cmd in ipairs(startup_commands) do",
+ " exec_once(cmd)",
+ " end",
+ "end",
+ "",
+ "if hl and hl.on then",
+ " hl.on(\"hyprland.start\", run_startup_commands)",
+ "else",
+ " run_startup_commands()",
+ "end",
+ ])
+ write_file(files_out["system_startup"], system_startup_lines)
+else:
+ if files_out["system_startup"].exists():
+ print(f"[INFO] No active startup entries found in {system_startup_path}; keeping existing {files_out['system_startup']}")
+ else:
+ system_startup_lines.append("-- No active startup entries were found in configs/Startup_Apps.conf.")
+ write_file(files_out["system_startup"], system_startup_lines)
+
+system_window_lines = [
+ "-- System defaults migrated from configs/WindowRules.conf (auto-generated).",
+ "-- Add additional rules with apply_window_rule({...}).",
+ "-- Example:",
+ "-- apply_window_rule({",
+ "-- name = \"My System Rule\",",
+ "-- match = { class = \"^pavucontrol$\" },",
+ "-- float = true,",
+ "-- })",
+ "",
+ "local function apply_window_rule(rule)",
+ " if hl.window_rule then",
+ " hl.window_rule(rule)",
+ " end",
+ "end",
+ "",
+]
+if system_window_rules:
+ system_window_lines.append("-- Converted from configs/WindowRules.conf")
+ for rule_type, rule in system_window_rules:
+ system_window_lines.append(emit_rule(rule_type, rule))
+ system_window_lines.append("")
+else:
+ system_window_lines.append("-- No active window rules were found in configs/WindowRules.conf.")
+write_file(files_out["system_window_rules"], system_window_lines)
+
+system_layer_lines = [
+ "-- System defaults migrated from configs/LayerRules.conf (auto-generated).",
+ "-- Add additional rules with apply_layer_rule({...}).",
+ "-- Example:",
+ "-- apply_layer_rule({",
+ "-- name = \"My Layer Rule\",",
+ "-- match = { namespace = \"rofi\" },",
+ "-- blur = true,",
+ "-- })",
+ "",
+ "local function apply_layer_rule(rule)",
+ " if hl.layer_rule then",
+ " hl.layer_rule(rule)",
+ " end",
+ "end",
+ "",
+]
+if system_layer_rules:
+ system_layer_lines.append("-- Converted from configs/LayerRules.conf")
+ for rule_type, rule in system_layer_rules:
+ system_layer_lines.append(emit_rule(rule_type, rule))
+ system_layer_lines.append("")
+else:
+ system_layer_lines.append("-- No active layer rules were found in configs/LayerRules.conf.")
+write_file(files_out["system_layer_rules"], system_layer_lines)
+
+system_keybind_lines = [
+ "-- System defaults migrated from configs/Keybinds.conf (auto-generated).",
+ "-- Add keybinds with bind(\"MODS\", \"KEY\", fn, opts).",
+ "-- Example:",
+ "-- bind(\"SUPER\", \"Z\", exec_cmd(\"thunar\"), { description = \"Open file manager\" })",
+ "",
+ "local dsp = hl.dsp or hl",
+ "local function resolve_cmd(cmd)",
+ " local defaults = rawget(_G, \"KOOLDOTS_DEFAULTS\") or {}",
+ " local resolved_term = defaults.term or os.getenv(\"TERMINAL\") or \"kitty\"",
+ " local resolved_files = defaults.files or \"thunar\"",
+ " local resolved_edit = defaults.edit or os.getenv(\"EDITOR\") or \"nano\"",
+ " cmd = tostring(cmd)",
+ " cmd = cmd:gsub(\"%$term\", resolved_term)",
+ " cmd = cmd:gsub(\"%$files\", resolved_files)",
+ " cmd = cmd:gsub(\"%$edit\", resolved_edit)",
+ " return cmd",
+ "end",
+ "",
+ "local function exec_cmd(cmd)",
+ " local resolved = resolve_cmd(cmd)",
+ " if dsp and dsp.exec_cmd then",
+ " return dsp.exec_cmd(resolved)",
+ " end",
+ " return function() hl.exec_cmd(resolved) end",
+ "end",
+ "",
+ "local function shell_quote(value)",
+ " return \"'\" .. tostring(value):gsub(\"'\", \"'\\\\''\") .. \"'\"",
+ "end",
+ "",
+ "local function raw_dispatch_cmd(command)",
+ " if dsp and dsp.exec_raw then",
+ " return dsp.exec_raw(tostring(command))",
+ " end",
+ " local expression = \"hl.dsp.exec_raw(\" .. string.format(\"%q\", tostring(command)) .. \")\"",
+ " return exec_cmd(\"hyprctl dispatch \" .. shell_quote(expression))",
+ "end",
+ "",
+ "local function trim(value)",
+ " return (value or \"\"):gsub(\"^%s+\", \"\"):gsub(\"%s+$\", \"\")",
+ "end",
+ "",
+ "local function chord(mods, key)",
+ " mods = trim(mods):gsub(\"%s+\", \" + \")",
+ " key = trim(key)",
+ " if mods == \"\" then",
+ " return key",
+ " end",
+ " return mods .. \" + \" .. key",
+ "end",
+ "",
+ "local function key_variants(key, mods)",
+ " key = trim(key):gsub(\"^xf86\", \"XF86\")",
+ " local key_aliases = {",
+ " XF86AudioPlayPause = \"XF86AudioPlay\",",
+ " XF86audiolowervolume = \"XF86AudioLowerVolume\",",
+ " XF86audiomute = \"XF86AudioMute\",",
+ " XF86audioraisevolume = \"XF86AudioRaiseVolume\",",
+ " XF86audiostop = \"XF86AudioStop\",",
+ " }",
+ " key = key_aliases[key] or key",
+ " local shifted_number_keys = {",
+ " [\"code:10\"] = \"exclam\",",
+ " [\"code:11\"] = \"at\",",
+ " [\"code:12\"] = \"numbersign\",",
+ " [\"code:13\"] = \"dollar\",",
+ " [\"code:14\"] = \"percent\",",
+ " [\"code:15\"] = \"asciicircum\",",
+ " [\"code:16\"] = \"ampersand\",",
+ " [\"code:17\"] = \"asterisk\",",
+ " [\"code:18\"] = \"parenleft\",",
+ " [\"code:19\"] = \"parenright\",",
+ " }",
+ " local number_keys = {",
+ " [\"code:10\"] = \"1\",",
+ " [\"code:11\"] = \"2\",",
+ " [\"code:12\"] = \"3\",",
+ " [\"code:13\"] = \"4\",",
+ " [\"code:14\"] = \"5\",",
+ " [\"code:15\"] = \"6\",",
+ " [\"code:16\"] = \"7\",",
+ " [\"code:17\"] = \"8\",",
+ " [\"code:18\"] = \"9\",",
+ " [\"code:19\"] = \"0\",",
+ " }",
+ " if mods:match(\"SHIFT\") and shifted_number_keys[key] then",
+ " local number_key = number_keys[key]",
+ " if number_key then",
+ " return { shifted_number_keys[key], number_key }",
+ " end",
+ " return { shifted_number_keys[key] }",
+ " end",
+ " if number_keys[key] then",
+ " return { number_keys[key] }",
+ " end",
+ " return { key }",
+ "end",
+ "",
+ "local function workspace_value(value)",
+ " value = trim(value)",
+ " return tonumber(value) or value",
+ "end",
+ "",
+ "local function direction(value)",
+ " local directions = {",
+ " l = \"left\",",
+ " r = \"right\",",
+ " u = \"up\",",
+ " d = \"down\",",
+ " left = \"left\",",
+ " right = \"right\",",
+ " up = \"up\",",
+ " down = \"down\",",
+ " }",
+ " return directions[trim(value)] or trim(value)",
+ "end",
+ "",
+ "local function dispatch(name, args)",
+ " local window_api = (dsp and dsp.window) or hl.window or {}",
+ " name = trim(name)",
+ " args = trim(args)",
+ " if name == \"exec\" then",
+ " return exec_cmd(args)",
+ " end",
+ " if name == \"killactive\" and window_api.close then",
+ " return window_api.close()",
+ " end",
+ " if name == \"fullscreen\" and window_api.fullscreen then",
+ " if args == \"1\" then",
+ " return window_api.fullscreen({ mode = \"maximized\" })",
+ " end",
+ " return window_api.fullscreen({ mode = \"fullscreen\" })",
+ " end",
+ " if name == \"movefocus\" and dsp and dsp.focus then",
+ " return function()",
+ " local ok, dispatcher = pcall(dsp.focus, { direction = direction(args) })",
+ " if ok and dispatcher then",
+ " hl.dispatch(dispatcher)",
+ " end",
+ " end",
+ " end",
+ " if name == \"cyclenext\" then",
+ " if args == \"prev\" or args == \"b\" then",
+ " return exec_cmd(\"$HOME/.config/hypr/scripts/LuaCycleWindow.sh previous\")",
+ " end",
+ " return exec_cmd(\"$HOME/.config/hypr/scripts/LuaCycleWindow.sh next\")",
+ " end",
+ " if name == \"swapwindow\" then",
+ " local swap_direction = trim(args)",
+ " if swap_direction == \"\" then",
+ " return nil",
+ " end",
+ " return exec_cmd(\"$HOME/.config/hypr/scripts/LuaSwapWindow.sh \" .. swap_direction)",
+ " end",
+ " if name == \"workspace\" and dsp and dsp.focus then",
+ " return function() hl.dispatch(dsp.focus({ workspace = workspace_value(args) })) end",
+ " end",
+ " if name == \"movetoworkspace\" and window_api.move then",
+ " return function() hl.dispatch(window_api.move({ workspace = workspace_value(args) })) end",
+ " end",
+ " if name == \"movetoworkspacesilent\" and window_api.move then",
+ " return function() hl.dispatch(window_api.move({ workspace = workspace_value(args), follow = false })) end",
+ " end",
+ " if name == \"togglefloating\" and window_api.float then",
+ " return function() hl.dispatch(window_api.float({ action = \"toggle\" })) end",
+ " end",
+ " if name == \"resizewindow\" and window_api.resize then",
+ " return window_api.resize()",
+ " end",
+ " if name == \"resizeactive\" and window_api.resize then",
+ " local x, y = args:match(\"^(%-?%d+)%s+(%-?%d+)$\")",
+ " if x and y then",
+ " return window_api.resize({ x = tonumber(x) or 0, y = tonumber(y) or 0, relative = true })",
+ " end",
+ " end",
+ " if name == \"movewindow\" and args == \"\" and window_api.drag then",
+ " return window_api.drag()",
+ " end",
+ " if args ~= \"\" then",
+ " return raw_dispatch_cmd(name .. \" \" .. args)",
+ " end",
+ " return raw_dispatch_cmd(name)",
+ "end",
+ "",
+ "local function bind(mods, key, fn, opts)",
+ " local seen = {}",
+ " for _, key_variant in ipairs(key_variants(key, mods)) do",
+ " local key_chord = chord(mods, key_variant)",
+ " if not seen[key_chord] then",
+ " seen[key_chord] = true",
+ " if opts then",
+ " hl.bind(key_chord, fn, opts)",
+ " else",
+ " hl.bind(key_chord, fn)",
+ " end",
+ " end",
+ " end",
+ "end",
+ "",
+ "local function unbind(mods, key)",
+ " if hl.unbind then",
+ " local seen = {}",
+ " for _, key_variant in ipairs(key_variants(key, mods)) do",
+ " local key_chord = chord(mods, key_variant)",
+ " if not seen[key_chord] then",
+ " seen[key_chord] = true",
+ " local ok = pcall(hl.unbind, mods, key_variant)",
+ " if not ok then",
+ " pcall(hl.unbind, key_chord)",
+ " end",
+ " end",
+ " end",
+ " end",
+ "end",
+ "",
+]
+if system_keybinds:
+ system_keybind_lines.append("-- Converted from configs/Keybinds.conf")
+ system_keybind_lines.extend(system_keybinds)
+ write_file(files_out["system_keybinds"], system_keybind_lines)
+else:
+ if files_out["system_keybinds"].exists():
+ print(f"[INFO] No active keybind entries found in {system_keybinds_path}; keeping existing {files_out['system_keybinds']}")
+ else:
+ system_keybind_lines.append("-- No active keybind entries were found in configs/Keybinds.conf.")
+ write_file(files_out["system_keybinds"], system_keybind_lines)
+
+for name, source in [
+ ("system_settings", system_settings_path),
+ ("system_laptops", system_laptops_path),
+]:
+ title = f"-- {name.replace('_', ' ').title()} (auto-generated)."
+ lines = [
+ title,
+ "-- This file keeps migrated settings split from user overrides.",
+ "-- Add only Lua entries here.",
+ "-- Example:",
+ "-- hl.config({ general = { gaps_in = 4, gaps_out = 8 } })",
+ "",
+ ]
+ source_path = source if source.exists() else latest_legacy_file(source)
+ if source_path and source_path != source:
+ print(f"[INFO] {source.name} not found at {source}; using legacy source {source_path}")
+
+ if name == "system_settings":
+ if source_path is None:
+ lines.append(f"-- No active entries were found in {source.name}.")
+ write_file(files_out[name], lines)
+ else:
+ scripts_dir = parse_scripts_dir(source_path)
+ if scripts_dir:
+ lines.append(f"local scriptsDir = {lua_string(scripts_dir)}")
+ lines.append("")
+
+ sections = parse_hyprlang_sections(source_path)
+ gestures_section = sections.pop("gestures", None)
+ if gestures_section and "gesture" in gestures_section:
+ gestures_section.pop("gesture", None)
+
+ ordered_sections = [
+ "dwindle",
+ "master",
+ "scrolling",
+ "general",
+ "input",
+ "gestures",
+ "misc",
+ "binds",
+ "xwayland",
+ "render",
+ "cursor",
+ ]
+ for section in ordered_sections:
+ if section == "gestures":
+ data = gestures_section
+ elif section == "misc":
+ data = sections.get(section) or {}
+ if "force_default_wallpaper" not in data:
+ data["force_default_wallpaper"] = "false"
+ else:
+ data = sections.get(section)
+ if not data:
+ continue
+ lines.append("hl.config({")
+ lines.append(f" {section} = {{")
+ lines.extend(render_table(data, indent=4))
+ lines.append(" },")
+ lines.append("})")
+ lines.append("")
+
+ simple_gestures, complex_gestures = parse_gestures(source_path)
+ for spec in simple_gestures:
+ lines.extend([
+ "hl.gesture({",
+ f" fingers = {spec['fingers']},",
+ f" direction = {lua_string(spec['direction'])},",
+ f" action = {lua_string(spec['action'])},",
+ "})",
+ "",
+ ])
+
+ if complex_gestures:
+ lines.append("-- Complex dispatcher gestures from SystemSettings.conf are pending explicit Lua API parity:")
+ for entry in complex_gestures:
+ lines.append(f"-- gesture = {entry}")
+ lines.append("")
+
+ write_file(files_out[name], lines)
+ continue
+
+ reference = source_examples(source_path) if source_path else []
+ if reference:
+ lines.extend([
+ f"-- Source reference from {source_path.name} (hyprlang):",
+ *reference,
+ ])
+ else:
+ lines.append(f"-- No active entries were found in {source.name}.")
+ write_file(files_out[name], lines)
+
+env_lines = [
+ "-- User ENV overrides (auto-generated).",
+ "-- Add values using: hl.env(\"KEY\", \"VALUE\")",
+ "-- Example:",
+ "-- hl.env(\"MOZ_ENABLE_WAYLAND\", \"1\")",
+ "",
+]
+if env_entries:
+ env_lines.append("-- Converted from ENVariables.conf")
+ for key, value in env_entries:
+ env_lines.append(f"hl.env({lua_string(key)}, {lua_string(value)})")
+ write_file(files_out["env"], env_lines)
+else:
+ if files_out["env"].exists():
+ print(f"[INFO] No active env entries found in {env_path}; keeping existing {files_out['env']}")
+ else:
+ env_lines.extend([
+ "-- No active env entries were found in ENVariables.conf.",
+ "-- Uncomment and customize examples below:",
+ "-- hl.env(\"GDK_SCALE\", \"1\")",
+ "-- hl.env(\"QT_SCALE_FACTOR\", \"1\")",
+ ])
+ write_file(files_out["env"], env_lines)
+
+startup_lines = [
+ "-- User startup overrides (auto-generated).",
+ "-- Add commands with exec_once(\"your command\")",
+ "-- Example:",
+ "-- exec_once(\"$HOME/.config/hypr/UserScripts/MyStartup.sh\")",
+ "",
+ "local user_startup_helper = nil",
+ "do",
+ " local source = (debug.getinfo(1, \"S\") or {}).source or \"\"",
+ " local source_path = source:match(\"^@(.+)$\")",
+ " local source_dir = source_path and source_path:match(\"^(.*)/[^/]+$\") or nil",
+ " local home = os.getenv(\"HOME\") or \"\"",
+ " local candidate_paths = {",
+ " source_dir and (source_dir .. \"/../lua/user_startup_helper.lua\") or nil,",
+ " home ~= \"\" and (home .. \"/.config/hypr/lua/user_startup_helper.lua\") or nil,",
+ " home ~= \"\" and (home .. \"/.config/hypr/user_startup_helper.lua\") or nil,",
+ " }",
+ "",
+ " local tried_paths = {}",
+ " for _, helper_path in ipairs(candidate_paths) do",
+ " if helper_path then",
+ " table.insert(tried_paths, helper_path)",
+ " local f = io.open(helper_path, \"r\")",
+ " if f then",
+ " f:close()",
+ " local loaded_ok, loaded_helpers = pcall(dofile, helper_path)",
+ " if loaded_ok and type(loaded_helpers) == \"table\" and loaded_helpers.exec_once then",
+ " user_startup_helper = loaded_helpers",
+ " break",
+ " end",
+ " end",
+ " end",
+ " end",
+ "",
+ " if not user_startup_helper then",
+ " error(\"Failed to load user_startup_helper.lua from: \" .. table.concat(tried_paths, \", \"))",
+ " end",
+ "end",
+ "local exec_once = user_startup_helper.exec_once",
+ "",
+]
+if startup_entries:
+ startup_lines.append("-- Converted from Startup_Apps.conf")
+ startup_lines.append("local startup_commands = {")
+ for cmd in startup_entries:
+ startup_lines.append(f" {lua_string(cmd)},")
+ startup_lines.extend([
+ "}",
+ "",
+ "local function run_startup_commands()",
+ " for _, cmd in ipairs(startup_commands) do",
+ " exec_once(cmd)",
+ " end",
+ "end",
+ "",
+ "if hl and hl.on then",
+ " hl.on(\"hyprland.start\", run_startup_commands)",
+ "else",
+ " run_startup_commands()",
+ "end",
+ ])
+ write_file(files_out["startup"], startup_lines)
+else:
+ if files_out["startup"].exists():
+ print(f"[INFO] No active startup entries found in {startup_path}; keeping existing {files_out['startup']}")
+ else:
+ startup_lines.extend([
+ "-- No active startup entries were found in Startup_Apps.conf.",
+ "-- exec_once(\"nm-applet --indicator\")",
+ ])
+ write_file(files_out["startup"], startup_lines)
+
+window_lines = [
+ "-- User window rule overrides (auto-generated).",
+ "-- Add your own rules with apply_window_rule({...})",
+ "-- Example:",
+ "-- apply_window_rule({",
+ "-- name = \"My Float Rule\",",
+ "-- match = { class = \"^pavucontrol$\" },",
+ "-- float = true,",
+ "-- center = true,",
+ "-- })",
+ "",
+ "local user_window_rules_helper = nil",
+ "do",
+ " local source = (debug.getinfo(1, \"S\") or {}).source or \"\"",
+ " local source_path = source:match(\"^@(.+)$\")",
+ " local source_dir = source_path and source_path:match(\"^(.*)/[^/]+$\") or nil",
+ " local home = os.getenv(\"HOME\") or \"\"",
+ " local candidate_paths = {",
+ " source_dir and (source_dir .. \"/../lua/user_window_rules_helper.lua\") or nil,",
+ " home ~= \"\" and (home .. \"/.config/hypr/lua/user_window_rules_helper.lua\") or nil,",
+ " home ~= \"\" and (home .. \"/.config/hypr/user_window_rules_helper.lua\") or nil,",
+ " }",
+ "",
+ " local tried_paths = {}",
+ " for _, helper_path in ipairs(candidate_paths) do",
+ " if helper_path then",
+ " table.insert(tried_paths, helper_path)",
+ " local f = io.open(helper_path, \"r\")",
+ " if f then",
+ " f:close()",
+ " local loaded_ok, loaded_helpers = pcall(dofile, helper_path)",
+ " if loaded_ok and type(loaded_helpers) == \"table\" and loaded_helpers.apply_window_rule then",
+ " user_window_rules_helper = loaded_helpers",
+ " break",
+ " end",
+ " end",
+ " end",
+ " end",
+ "",
+ " if not user_window_rules_helper then",
+ " error(\"Failed to load user_window_rules_helper.lua from: \" .. table.concat(tried_paths, \", \"))",
+ " end",
+ "end",
+ "local apply_window_rule = user_window_rules_helper.apply_window_rule",
+ "",
+]
+if window_rules:
+ window_lines.append("-- Converted from WindowRules.conf")
+ for rule_type, rule in window_rules:
+ window_lines.append(emit_rule(rule_type, rule))
+ window_lines.append("")
+else:
+ window_lines.append("-- No active window rules were found in WindowRules.conf.")
+write_file(files_out["window_rules"], window_lines)
+
+layer_lines = [
+ "-- User layer rule overrides (auto-generated).",
+ "-- Add your own rules with apply_layer_rule({...})",
+ "-- Example:",
+ "-- apply_layer_rule({",
+ "-- name = \"My Layer Rule\",",
+ "-- match = { namespace = \"notifications\" },",
+ "-- blur = true,",
+ "-- })",
+ "",
+ "local user_layer_rules_helper = nil",
+ "do",
+ " local source = (debug.getinfo(1, \"S\") or {}).source or \"\"",
+ " local source_path = source:match(\"^@(.+)$\")",
+ " local source_dir = source_path and source_path:match(\"^(.*)/[^/]+$\") or nil",
+ " local home = os.getenv(\"HOME\") or \"\"",
+ " local candidate_paths = {",
+ " source_dir and (source_dir .. \"/../lua/user_layer_rules_helper.lua\") or nil,",
+ " home ~= \"\" and (home .. \"/.config/hypr/lua/user_layer_rules_helper.lua\") or nil,",
+ " home ~= \"\" and (home .. \"/.config/hypr/user_layer_rules_helper.lua\") or nil,",
+ " }",
+ "",
+ " local tried_paths = {}",
+ " for _, helper_path in ipairs(candidate_paths) do",
+ " if helper_path then",
+ " table.insert(tried_paths, helper_path)",
+ " local f = io.open(helper_path, \"r\")",
+ " if f then",
+ " f:close()",
+ " local loaded_ok, loaded_helpers = pcall(dofile, helper_path)",
+ " if loaded_ok and type(loaded_helpers) == \"table\" and loaded_helpers.apply_layer_rule then",
+ " user_layer_rules_helper = loaded_helpers",
+ " break",
+ " end",
+ " end",
+ " end",
+ " end",
+ "",
+ " if not user_layer_rules_helper then",
+ " error(\"Failed to load user_layer_rules_helper.lua from: \" .. table.concat(tried_paths, \", \"))",
+ " end",
+ "end",
+ "local apply_layer_rule = user_layer_rules_helper.apply_layer_rule",
+ "",
+]
+if layer_rules:
+ layer_lines.append("-- Converted from LayerRules.conf")
+ for rule_type, rule in layer_rules:
+ layer_lines.append(emit_rule(rule_type, rule))
+ layer_lines.append("")
+else:
+ layer_lines.append("-- No active layer rules were found in LayerRules.conf.")
+write_file(files_out["layer_rules"], layer_lines)
+
+keybind_lines = [
+ "-- User keybind overrides (auto-generated).",
+ "-- Add keybinds with bind(\"MODS\", \"KEY\", fn, opts).",
+ "-- Example:",
+ "-- bind(\"SUPER\", \"Z\", exec_cmd(\"ghostty\"), { description = \"Launch ghostty\" })",
+ "-- Helper functions live in ~/.config/hypr/lua/user_keybinds_helper.lua so they can be updated separately.",
+ "local user_keybinds_helper = nil",
+ "do",
+ " local source = (debug.getinfo(1, \"S\") or {}).source or \"\"",
+ " local source_path = source:match(\"^@(.+)$\")",
+ " local source_dir = source_path and source_path:match(\"^(.*)/[^/]+$\") or nil",
+ " local home = os.getenv(\"HOME\") or \"\"",
+ " local candidate_paths = {",
+ " source_dir and (source_dir .. \"/../lua/user_keybinds_helper.lua\") or nil,",
+ " home ~= \"\" and (home .. \"/.config/hypr/lua/user_keybinds_helper.lua\") or nil,",
+ " home ~= \"\" and (home .. \"/.config/hypr/user_keybinds_helper.lua\") or nil,",
+ " }",
+ "",
+ " local tried_paths = {}",
+ " for _, helper_path in ipairs(candidate_paths) do",
+ " if helper_path then",
+ " table.insert(tried_paths, helper_path)",
+ " local f = io.open(helper_path, \"r\")",
+ " if f then",
+ " f:close()",
+ " local loaded_ok, loaded_helpers = pcall(dofile, helper_path)",
+ " if loaded_ok and type(loaded_helpers) == \"table\" and loaded_helpers.bind then",
+ " user_keybinds_helper = loaded_helpers",
+ " break",
+ " end",
+ " end",
+ " end",
+ " end",
+ "",
+ " if not user_keybinds_helper then",
+ " error(\"Failed to load user_keybinds_helper.lua from: \" .. table.concat(tried_paths, \", \"))",
+ " end",
+ "end",
+ "local exec_cmd = user_keybinds_helper.exec_cmd",
+ "local dispatch = user_keybinds_helper.dispatch",
+ "local bind = user_keybinds_helper.bind",
+ "local unbind = user_keybinds_helper.unbind",
+ "",
+]
+if keybinds:
+ keybind_lines.append("-- Converted from UserKeybinds.conf")
+ keybind_lines.extend(keybinds)
+ write_file(files_out["keybinds"], keybind_lines)
+else:
+ if files_out["keybinds"].exists():
+ print(f"[INFO] No active keybind entries found in {keybinds_path}; keeping existing {files_out['keybinds']}")
+ else:
+ keybind_lines.extend([
+ "-- No active keybind entries were found in UserKeybinds.conf.",
+ "-- bind(\"SUPER\", \"Z\", exec_cmd(\"thunar\"), { description = \"Open file manager\" })",
+ ])
+ write_file(files_out["keybinds"], keybind_lines)
+
+for name, source in [
+ ("settings", settings_path),
+ ("decorations", decorations_path),
+ ("animations", animations_path),
+ ("laptops", laptops_path),
+]:
+ title = f"-- User {name} overrides (auto-generated)."
+ lines = [
+ title,
+ "-- This file is intentionally split from other user overrides.",
+ "-- Add only user-specific Lua overrides here.",
+ "-- Example:",
+ "-- hl.config({ general = { gaps_in = 4, gaps_out = 8 } })",
+ "",
+ ]
+ reference = source_examples(source)
+ if name == "decorations":
+ if reference or not files_out[name].exists():
+ parsed_decorations = parse_hyprlang_sections(source)
+ decoration_lines = [
+ title,
+ "-- This file is intentionally split from other user overrides.",
+ "-- Add only user-specific Lua overrides here.",
+ "-- Reads active border/shadow colors from wallust-hyprland.conf.",
+ "",
+ "local config_home = os.getenv(\"XDG_CONFIG_HOME\") or ((os.getenv(\"HOME\") or \"\") .. \"/.config\")",
+ "local wallust_colors_file = config_home .. \"/hypr/wallust/wallust-hyprland.conf\"",
+ "",
+ "local user_decorations_helper = nil",
+ "do",
+ " local source = (debug.getinfo(1, \"S\") or {}).source or \"\"",
+ " local source_path = source:match(\"^@(.+)$\")",
+ " local source_dir = source_path and source_path:match(\"^(.*)/[^/]+$\") or nil",
+ " local home = os.getenv(\"HOME\") or \"\"",
+ " local candidate_paths = {",
+ " source_dir and (source_dir .. \"/../lua/user_decorations_helper.lua\") or nil,",
+ " home ~= \"\" and (home .. \"/.config/hypr/lua/user_decorations_helper.lua\") or nil,",
+ " home ~= \"\" and (home .. \"/.config/hypr/user_decorations_helper.lua\") or nil,",
+ " }",
+ "",
+ " local tried_paths = {}",
+ " for _, helper_path in ipairs(candidate_paths) do",
+ " if helper_path then",
+ " table.insert(tried_paths, helper_path)",
+ " local f = io.open(helper_path, \"r\")",
+ " if f then",
+ " f:close()",
+ " local loaded_ok, loaded_helpers = pcall(dofile, helper_path)",
+ " if loaded_ok and type(loaded_helpers) == \"table\" and loaded_helpers.load_wallust_colors then",
+ " user_decorations_helper = loaded_helpers",
+ " break",
+ " end",
+ " end",
+ " end",
+ " end",
+ "",
+ " if not user_decorations_helper then",
+ " error(\"Failed to load user_decorations_helper.lua from: \" .. table.concat(tried_paths, \", \"))",
+ " end",
+ "end",
+ "local load_wallust_colors = user_decorations_helper.load_wallust_colors",
+ "",
+ "local wallust = load_wallust_colors(wallust_colors_file)",
+ "local function wallust_color(name, fallback)",
+ " local value = wallust[name]",
+ " if value ~= nil then",
+ " return value",
+ " end",
+ " return fallback",
+ "end",
+ ]
+ if parsed_decorations:
+ for section_name in ("general", "decoration", "group"):
+ section = parsed_decorations.get(section_name)
+ if not section:
+ continue
+ decoration_lines.append("")
+ decoration_lines.append("hl.config({")
+ decoration_lines.append(f" {section_name} = {{")
+ decoration_lines.extend(render_table(section, indent=4))
+ decoration_lines.append(" },")
+ decoration_lines.append("})")
+ else:
+ decoration_lines.extend([
+ "",
+ "hl.config({",
+ " general = {",
+ " border_size = 2,",
+ " gaps_in = 2,",
+ " gaps_out = 4,",
+ " col = {",
+ " active_border = wallust_color(\"color12\", \"rgba(8db4ffff)\"),",
+ " inactive_border = wallust_color(\"color10\", \"rgba(5f6578ff)\"),",
+ " },",
+ " },",
+ "})",
+ "",
+ "hl.config({",
+ " decoration = {",
+ " rounding = 10,",
+ " active_opacity = 1.0,",
+ " inactive_opacity = 0.9,",
+ " fullscreen_opacity = 1.0,",
+ " dim_inactive = true,",
+ " dim_strength = 0.1,",
+ " dim_special = 0.8,",
+ " shadow = {",
+ " enabled = true,",
+ " range = 3,",
+ " render_power = 1,",
+ " color = wallust_color(\"color12\", \"rgba(8db4ffff)\"),",
+ " color_inactive = wallust_color(\"color10\", \"rgba(5f6578ff)\"),",
+ " },",
+ " blur = {",
+ " enabled = true,",
+ " size = 6,",
+ " passes = 3,",
+ " new_optimizations = true,",
+ " xray = true,",
+ " ignore_opacity = true,",
+ " special = true,",
+ " popups = true,",
+ " },",
+ " },",
+ "})",
+ "",
+ "hl.config({",
+ " group = {",
+ " col = {",
+ " border_active = wallust_color(\"color15\", \"rgba(ffffffff)\"),",
+ " },",
+ " groupbar = {",
+ " col = {",
+ " active = wallust_color(\"color0\", \"rgba(0f111aff)\"),",
+ " },",
+ " },",
+ " },",
+ "})",
+ ])
+ if reference:
+ decoration_lines.extend([
+ "",
+ f"-- Source reference from {source.name} (hyprlang):",
+ *reference,
+ ])
+ write_file(files_out[name], decoration_lines)
+ else:
+ print(f"[INFO] No active entries found in {source}; keeping existing {files_out[name]}")
+ continue
+ if reference:
+ lines.extend([
+ f"-- Source reference from {source.name} (hyprlang):",
+ *reference,
+ ])
+ write_file(files_out[name], lines)
+ else:
+ if files_out[name].exists():
+ print(f"[INFO] No active entries found in {source}; keeping existing {files_out[name]}")
+ else:
+ lines.append(f"-- No active entries were found in {source.name}.")
+ write_file(files_out[name], lines)
+PY
+
+cat > "$USER_OVERRIDES_SHIM" <<'LUA'
+-- ==================================================
+-- KoolDots (2026)
+-- Project URL: https://github.com/LinuxBeginnings
+-- License: GNU GPLv3
+-- SPDX-License-Identifier: GPL-3.0-or-later
+-- ==================================================
+-- Auto-generated by scripts/migrate-hypr-to-lua.sh.
+-- Loads split system/user Lua files from ~/.config/hypr/configs and ~/.config/hypr/UserConfigs.
+local configHome = os.getenv("XDG_CONFIG_HOME") or ((os.getenv("HOME") or "") .. "/.config")
+local hyprDir = configHome .. "/hypr"
+local systemDir = hyprDir .. "/configs"
+local userDir = configHome .. "/hypr/UserConfigs"
+
+local function load_optional(path)
+ local ok, err = pcall(dofile, path)
+ if ok then
+ return true
+ end
+ if err and tostring(err):find("No such file or directory", 1, true) ~= nil then
+ return false
+ end
+ print("[WARN] Unable to load user override file " .. path .. ": " .. tostring(err))
+ return false
+end
+
+local system_files = {
+ "system_env.lua",
+ "system_startup.lua",
+ "system_window_rules.lua",
+ "system_layer_rules.lua",
+ "system_keybinds.lua",
+ "system_settings.lua",
+ "system_laptops.lua",
+}
+for _, file in ipairs(system_files) do
+ local primary = systemDir .. "/" .. file
+ local legacy = userDir .. "/" .. file
+ if not load_optional(primary) then
+ load_optional(legacy)
+ end
+end
+local loaded_user_split = false
+
+local user_files = {
+ "user_env.lua",
+ "user_startup.lua",
+ "user_window_rules.lua",
+ "user_layer_rules.lua",
+ "user_keybinds.lua",
+ "user_settings.lua",
+ "user_decorations.lua",
+ "user_animations.lua",
+ "user_laptops.lua",
+}
+for _, file in ipairs(user_files) do
+ local path = userDir .. "/" .. file
+ if load_optional(path) then
+ loaded_user_split = true
+ end
+end
+if not loaded_user_split then
+ load_optional(userDir .. "/user_overrides.lua") -- backward compatibility with older single-file overrides
+end
+LUA
+
+move_conf_files_to_legacy() {
+ local source_dir="$1"
+ local legacy_dir="$2"
+ local label="$3"
+ local moved=0
+ local file
+
+ [ -d "$source_dir" ] || return 0
+ mkdir -p "$legacy_dir"
+
+ while IFS= read -r -d '' file; do
+ mv "$file" "$legacy_dir/"
+ moved=1
+ done < <(find "$source_dir" -maxdepth 1 -type f -name '*.conf' -print0)
+
+ if [ "$moved" -eq 1 ]; then
+ echo "[OK] Moved $label/*.conf -> $legacy_dir"
+ fi
+}
+print_conversion_coverage_summary() {
+ echo "[INFO] Migration coverage summary (Hyprland Lua mode):"
+ cat <<SUMMARY
+[INFO] Converted .conf -> .lua:
+[INFO] - $DEST_MONITORS_CONF -> $DEST_LUA_MONITORS
+[INFO] - $DEST_WORKSPACES_CONF -> $DEST_LUA_WORKSPACES
+[INFO] - $SYSTEM_ENV_VARS -> $CONFIGS_DIR/system_env.lua
+[INFO] - $SYSTEM_STARTUP_APPS -> $CONFIGS_DIR/system_startup.lua
+[INFO] - $SYSTEM_WINDOW_RULES -> $CONFIGS_DIR/system_window_rules.lua
+[INFO] - $SYSTEM_LAYER_RULES -> $CONFIGS_DIR/system_layer_rules.lua
+[INFO] - $SYSTEM_KEYBINDS -> $CONFIGS_DIR/system_keybinds.lua
+[INFO] - $SYSTEM_SETTINGS -> $CONFIGS_DIR/system_settings.lua
+[INFO] - $SYSTEM_LAPTOPS -> $CONFIGS_DIR/system_laptops.lua
+[INFO] - $USER_ENV_VARS -> $USER_CONFIGS_DIR/user_env.lua
+[INFO] - $USER_STARTUP_APPS -> $USER_CONFIGS_DIR/user_startup.lua
+[INFO] - $USER_WINDOW_RULES -> $USER_CONFIGS_DIR/user_window_rules.lua
+[INFO] - $USER_LAYER_RULES -> $USER_CONFIGS_DIR/user_layer_rules.lua
+[INFO] - $USER_KEYBINDS -> $USER_CONFIGS_DIR/user_keybinds.lua
+[INFO] - $USER_SETTINGS -> $USER_CONFIGS_DIR/user_settings.lua
+[INFO] - $USER_DECORATIONS -> $USER_CONFIGS_DIR/user_decorations.lua
+[INFO] - $USER_ANIMATIONS -> $USER_CONFIGS_DIR/user_animations.lua
+[INFO] - $USER_LAPTOPS -> $USER_CONFIGS_DIR/user_laptops.lua
+[INFO] - $USER_CONFIGS_DIR/01-UserDefaults.conf -> $USER_CONFIGS_DIR/user_defaults.lua
+[INFO] Intentionally native/template .conf files:
+[INFO] - $DEST_HYPR_DIR/hypridle.conf
+[INFO] - $DEST_HYPR_DIR/hyprlock.conf, hyprlock-1080p.conf, hyprlock-2k.conf
+[INFO] - $DEST_HYPR_DIR/hyprland.conf (fallback/non-Lua entrypoint)
+[INFO] - $DEST_HYPR_DIR/Monitor_Profiles/*.conf and $DEST_HYPR_DIR/animations/*.conf (preset profiles)
+[INFO] - $USER_CONFIGS_DIR/LaptopDisplay.conf and $USER_CONFIGS_DIR/WorkSpaceRules.conf (legacy/helper files)
+SUMMARY
+}
+
+move_conf_files_to_legacy "$USER_CONFIGS_DIR" "$USER_CONFIGS_LEGACY_DIR" "$USER_CONFIGS_DIR"
+move_conf_files_to_legacy "$CONFIGS_DIR" "$CONFIGS_LEGACY_DIR" "$CONFIGS_DIR"
+print_conversion_coverage_summary
+
+echo "[OK] Lua Hyprland config copied."
+echo "[INFO] Restart Hyprland to test Lua config pickup."
+echo "[INFO] To rollback: $(basename "$0") --revert"
diff --git a/wallpapers/3d-door.jpg b/wallpapers/3d-door.jpg
new file mode 100755
index 00000000..16659bb3
--- /dev/null
+++ b/wallpapers/3d-door.jpg
Binary files differ
diff --git a/wallpapers/Catppuccin-pond-bridge.jpg b/wallpapers/Catppuccin-pond-bridge.jpg
new file mode 100644
index 00000000..2021eb09
--- /dev/null
+++ b/wallpapers/Catppuccin-pond-bridge.jpg
Binary files differ
diff --git a/wallpapers/a_black_sand_beach_with_waves_and_clouds_above.jpg b/wallpapers/a_black_sand_beach_with_waves_and_clouds_above.jpg
new file mode 100644
index 00000000..6030d8fa
--- /dev/null
+++ b/wallpapers/a_black_sand_beach_with_waves_and_clouds_above.jpg
Binary files differ
diff --git a/wallpapers/a_group_of_wooden_posts_in_water.jpg b/wallpapers/a_group_of_wooden_posts_in_water.jpg
new file mode 100644
index 00000000..8522ef7c
--- /dev/null
+++ b/wallpapers/a_group_of_wooden_posts_in_water.jpg
Binary files differ
diff --git a/wallpapers/astralbed.png b/wallpapers/astralbed.png
new file mode 100755
index 00000000..dbfc7f0b
--- /dev/null
+++ b/wallpapers/astralbed.png
Binary files differ
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage