diff options
264 files changed, 18806 insertions, 2320 deletions
@@ -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 @@ -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. + + + +## 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. + + + +> [!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" @@ -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 Binary files differnew file mode 100755 index 00000000..16659bb3 --- /dev/null +++ b/wallpapers/3d-door.jpg diff --git a/wallpapers/Catppuccin-pond-bridge.jpg b/wallpapers/Catppuccin-pond-bridge.jpg Binary files differnew file mode 100644 index 00000000..2021eb09 --- /dev/null +++ b/wallpapers/Catppuccin-pond-bridge.jpg 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 Binary files differnew file mode 100644 index 00000000..6030d8fa --- /dev/null +++ b/wallpapers/a_black_sand_beach_with_waves_and_clouds_above.jpg diff --git a/wallpapers/a_group_of_wooden_posts_in_water.jpg b/wallpapers/a_group_of_wooden_posts_in_water.jpg Binary files differnew file mode 100644 index 00000000..8522ef7c --- /dev/null +++ b/wallpapers/a_group_of_wooden_posts_in_water.jpg diff --git a/wallpapers/astralbed.png b/wallpapers/astralbed.png Binary files differnew file mode 100755 index 00000000..dbfc7f0b --- /dev/null +++ b/wallpapers/astralbed.png |
