aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Guzman <55927935+brockar@users.noreply.github.com>2025-11-22 13:42:39 -0300
committerGitHub <noreply@github.com>2025-11-22 13:42:39 -0300
commitbcfd5e7c2b67f0a62b1ceeb62d20b0a80ca55a70 (patch)
treee87f649fe0c9d8f382b8f465d1468b6495fb5886
parentc862835221decf03b6640bb43e4044861cceaa04 (diff)
parent1351220a092414ae593bc006e3a3ebc09523198d (diff)
Merge pull request #871 from JaKooLit/development
[Bug] Change to waybar sleep timers was too long, slowed down waybar start/refressh
-rw-r--r--.gitignore40
-rw-r--r--CHANGELOG.md34
-rw-r--r--CHANGES-v2.3.18.md72
-rwxr-xr-xDistro-Hyprland.sh2
-rw-r--r--config/fastfetch/config-compact.jsonc12
-rw-r--r--config/fastfetch/config-pokemon.jsonc10
-rw-r--r--config/fastfetch/config-v2.jsonc42
-rw-r--r--config/fastfetch/config.jsonc13
-rw-r--r--config/hypr/UserConfigs/ENVariables.conf3
-rw-r--r--config/hypr/UserConfigs/UserKeybinds.conf87
-rw-r--r--config/hypr/UserConfigs/UserSettings.conf2
-rw-r--r--config/hypr/UserConfigs/WindowRules-v3.conf671
-rw-r--r--config/hypr/UserConfigs/WindowRules.conf24
-rwxr-xr-xconfig/hypr/UserScripts/RainbowBorders.sh2
-rwxr-xr-xconfig/hypr/UserScripts/RofiBeats.sh203
-rwxr-xr-xconfig/hypr/UserScripts/RofiCalc.sh2
-rwxr-xr-xconfig/hypr/UserScripts/Tak0-Autodispatch.sh2
-rwxr-xr-xconfig/hypr/UserScripts/WallpaperAutoChange.sh2
-rwxr-xr-xconfig/hypr/UserScripts/WallpaperEffects.sh2
-rwxr-xr-xconfig/hypr/UserScripts/WallpaperRandom.sh2
-rwxr-xr-xconfig/hypr/UserScripts/WallpaperSelect.sh2
-rwxr-xr-xconfig/hypr/UserScripts/Weather.py767
-rwxr-xr-xconfig/hypr/UserScripts/Weather.sh164
-rwxr-xr-xconfig/hypr/UserScripts/WeatherWrap.sh33
-rwxr-xr-xconfig/hypr/UserScripts/ZshChangeTheme.sh2
-rw-r--r--config/hypr/configs/Keybinds.conf198
-rw-r--r--config/hypr/configs/Startup_Apps.conf (renamed from config/hypr/UserConfigs/Startup_Apps.conf)8
-rw-r--r--config/hypr/configs/WindowRules-config-v3.conf690
-rw-r--r--config/hypr/configs/WindowRules.conf235
-rw-r--r--config/hypr/hyprland.conf23
-rw-r--r--config/hypr/hyprlock-1080p.conf80
-rw-r--r--config/hypr/hyprlock.conf99
-rwxr-xr-xconfig/hypr/initial-boot.sh2
-rwxr-xr-xconfig/hypr/scripts/AirplaneMode.sh2
-rwxr-xr-xconfig/hypr/scripts/Animations.sh2
-rwxr-xr-x[-rw-r--r--]config/hypr/scripts/Battery.sh2
-rwxr-xr-xconfig/hypr/scripts/Brightness.sh2
-rwxr-xr-xconfig/hypr/scripts/BrightnessKbd.sh2
-rwxr-xr-xconfig/hypr/scripts/ChangeBlur.sh2
-rwxr-xr-xconfig/hypr/scripts/ChangeLayout.sh12
-rwxr-xr-xconfig/hypr/scripts/ClipManager.sh2
-rwxr-xr-xconfig/hypr/scripts/DarkLight.sh2
-rwxr-xr-xconfig/hypr/scripts/Distro_update.sh2
-rwxr-xr-xconfig/hypr/scripts/Dropterminal.sh592
-rwxr-xr-xconfig/hypr/scripts/GameMode.sh3
-rwxr-xr-xconfig/hypr/scripts/Hypridle.sh2
-rwxr-xr-xconfig/hypr/scripts/Hyprsunset.sh22
-rwxr-xr-xconfig/hypr/scripts/KeyBinds.sh71
-rwxr-xr-xconfig/hypr/scripts/KeyHints.sh2
-rwxr-xr-xconfig/hypr/scripts/KeybindsLayoutInit.sh14
-rwxr-xr-xconfig/hypr/scripts/KillActiveProcess.sh2
-rwxr-xr-xconfig/hypr/scripts/Kitty_themes.sh2
-rwxr-xr-xconfig/hypr/scripts/KooLsDotsUpdate.sh2
-rwxr-xr-xconfig/hypr/scripts/Kool_Quick_Settings.sh6
-rwxr-xr-xconfig/hypr/scripts/LockScreen.sh10
-rwxr-xr-xconfig/hypr/scripts/MediaCtrl.sh2
-rwxr-xr-xconfig/hypr/scripts/MonitorProfiles.sh2
-rwxr-xr-xconfig/hypr/scripts/OverviewToggle.sh41
-rwxr-xr-xconfig/hypr/scripts/Polkit-NixOS.sh2
-rwxr-xr-xconfig/hypr/scripts/Polkit.sh2
-rwxr-xr-xconfig/hypr/scripts/PortalHyprland.sh2
-rwxr-xr-xconfig/hypr/scripts/Refresh.sh35
-rwxr-xr-xconfig/hypr/scripts/RefreshNoWaybar.sh2
-rwxr-xr-xconfig/hypr/scripts/RofiEmoji.sh2
-rwxr-xr-xconfig/hypr/scripts/RofiSearch.sh2
-rwxr-xr-xconfig/hypr/scripts/RofiThemeSelector-modified.sh2
-rwxr-xr-xconfig/hypr/scripts/RofiThemeSelector.sh2
-rwxr-xr-xconfig/hypr/scripts/ScreenShot.sh2
-rwxr-xr-xconfig/hypr/scripts/Sounds.sh2
-rwxr-xr-xconfig/hypr/scripts/SwitchKeyboardLayout.sh2
-rwxr-xr-xconfig/hypr/scripts/Tak0-Autodispatch.sh2
-rwxr-xr-xconfig/hypr/scripts/TouchPad.sh2
-rwxr-xr-xconfig/hypr/scripts/Volume.sh2
-rwxr-xr-xconfig/hypr/scripts/WallustSwww.sh2
-rwxr-xr-xconfig/hypr/scripts/WaybarLayout.sh4
-rwxr-xr-xconfig/hypr/scripts/WaybarScripts.sh2
-rwxr-xr-xconfig/hypr/scripts/WaybarStyles.sh4
-rwxr-xr-xconfig/hypr/scripts/Wlogout.sh2
-rwxr-xr-x[-rw-r--r--]config/hypr/scripts/sddm_wallpaper.sh2
-rw-r--r--config/hypr/v2.3.18 (renamed from config/hypr/v2.3.17)0
-rw-r--r--config/rofi/online_music.list17
-rw-r--r--config/waybar/ModulesCustom5
-rw-r--r--config/waybar/ModulesGroups2
-rw-r--r--config/waybar/ModulesWorkspaces41
-rwxr-xr-xcopy.sh161
-rwxr-xr-xrelease.sh2
-rwxr-xr-xupgrade.sh5
87 files changed, 3589 insertions, 1056 deletions
diff --git a/.gitignore b/.gitignore
index d20a9670..f85a9570 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,43 @@
WARP.md
.warp.md
result
+
+# Python artifacts
+__pycache__/
+*.py[cod]
+*.pyo
+*.pyd
+*.so
+*.egg
+*.egg-info/
+.eggs/
+dist/
+build/
+eggs/
+pip-wheel-metadata/
+
+# Virtual environments
+.venv/
+venv/
+env/
+ENV/
+.env
+
+# Testing and coverage
+.pytest_cache/
+.coverage
+.cache/
+.tox/
+htmlcov/
+
+# Type checking and linting
+.mypy_cache/
+.pytype/
+.flake8
+.ruff_cache/
+
+# IDE and editor directories
+.idea/
+.vscode/
+*.swp
+*.swo
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cd0effc4..f6623708 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,19 +1,46 @@
# Changelog — JAK's Hyprland Dotfiles
+## v2.3.18 — 2025-11-05
+
+- Keybinds: initialize SUPER+J/K at login to match the default layout (master or dwindle).
+ - Adds scripts/KeybindsLayoutInit.sh and wires it to Startup_Apps so J/K and O (togglesplit) are correct on first session.
+ - ChangeLayout.sh continues to rebind dynamically when layouts are toggled.
+ - Credits: [Suresh Thagunna](https://github.com/suresh466) for identifying the mismatch and proposing an auto-alignment approach.
+- Startup config sourcing: load vendor Startup_Apps and WindowRules first, then user overlays, restoring baseline autostarts while keeping user additions.
+- Quick Settings: “Edit Startup Apps” opens the full vendor defaults for clarity.
+
## October 2025
+### ⌨️ Keybinds
+
+- Convert Hyprland keybinds to description form (`bindd`, `bindld`, `binded`,
+ `bindmd`, `bindlnd`) in `config/hypr/...`.
+- Add concise descriptions for each keybind; keep the name "powermenu".
+- Update `config/hypr/scripts/KeyBinds.sh` to parse and display descriptions
+ as: MODS+KEY — DESCRIPTION — DISPATCHER [PARAMS].
+
### 🐛 Fixes
+- Updated `/bin/bash` to `/usr/bin/env bash`
- Correct `windowrule` syntax error.
- Ensure wallpaper selector applies wallpaper to SDDM.
- Update theme colors when a new wallpaper is selected.
+### 🖥️ Jak dotfiles version now in `fastfetch` output.
+
### 🌦️ Weather.py
+Key Changes:
+
+- 2nd Weather.py Update by prabinpanta0
- ♻️ Substantial rewrite.
-- ✅ Launches properly in Waybar.
-- 📍 Improved location detection; overridable variables exposed.
-- 🌐 Switched to Open-Meteo for weather data with fallback providers.
+- ✨ New unified weather entrypoint (weatherWrap.sh)
+ - With Python-first execution
+- 🔒 Automatic weather updates before screen lock
+- 🚀 Weather cache initialization at session startup
+- 🛡️ Enhanced error handling and fallback mechanisms
+- 📍 Automatic location detection via IP geolocation
+- 🎨 Improved weather condition mapping and JSON output
### 🖥️ Support for debian and ubuntu installs
@@ -34,6 +61,7 @@
### 👥 Contributors
+- [prabinpanta0](https://github.com/prabinpanta0)
- [CharlyMH](https://github.com/CharlyMH)
- [ndeekshith](https://github.com/ndeekshith)
- [SherLock707](https://github.com/SherLock707)
diff --git a/CHANGES-v2.3.18.md b/CHANGES-v2.3.18.md
new file mode 100644
index 00000000..29eb7c41
--- /dev/null
+++ b/CHANGES-v2.3.18.md
@@ -0,0 +1,72 @@
+# CHANGES: Hyprland-Dots v2.3.18
+
+## FIXES:
+
+- Fixed: Overview Toggle keyind SUPER + A now properly detects QuickShell
+ - If QS fails, or not installed AGS will be started instead
+- Fixed: Super J/K cycle next/prev weren't working in both master / dwindle
+- Fixed: Weather.py one-off run
+- Removed: Hyprsunt from status group.
+ - Credit: Alberson Miranda
+- Added: more application icons for waybars
+- Weather.py basically rewritten to improve look and functionality
+ - Credit: Prabin Panta
+ - The Jak team also heavily contributed to the rewrite
+- Fixed: Waybar
+ - Changing the waybar config `SUPERALT + B` would sometimes need to be done twice
+ - Cause: options were incorrect annotated with "👉 ${name}"
+- Fixed: `GameMode.sh` to function consistently
+- Updated: `WalllustSwww.sh` wallpaper path
+- Corrected: Typo in Show Open Apps
+- GameMode.sh / Refresh.sh
+ - Enabling / Disabling repeatedly would result in multiple waybars
+ - Added additional `sleep` commands in `GameMode.sh` and `Refresh.sh`
+ - Resolves [Issue 870](https://github.com/JaKooLit/Hyprland-Dots/issues/870)
+
+## CHANGES:
+
+- Changed: Hyprland Packages from SID
+ - No longer built from source
+ - Hyprland Version @ v0.51.1
+ - If/When SID it updated, updates will be done as normal process
+- Lock screen:
+ - Clock now horizontal and smaller
+ - Adjust spacing margines of the various fields
+ - Small changes to color variabbles Trying to balance colors
+ - Fixed both 1080 and 2K+ configurations
+- `UserConfigs/Startup_App.conf` is now sourced in `hyprland.conf`
+ - It was being sourced twice
+- Some scripts weren't executable
+ - `scripts/Battery.sh`
+ - `scripts/ComposeHyprConfigs.sh`
+ - `scripts/OverviewToggle.sh`
+ - `scripts/sddm_wallpaper.sh`
+- Updated: SWWW to v0.11.2
+ - Fixes numerous issues
+ - Portrait monitors especially
+ - SWWW isn't being maintained In future will switch to AWWWW
+- Added: A message before installing wallpapers that some are AI generated or enhanced
+- Changed: `/usr/bin/bash` to `/usr/bin/evn bash` for better portability
+- Adjusted: Small change to `DropDownterminal.sh`
+ - Increased top margin % to center it more
+ - Widened it.
+ - These options are settable in the script.
+
+## FEATURES:
+
+- Hyprsunet retains last state on/off
+ - Credit: Alberson Miranda
+- Fastfetch now displays the version of the Jak Dotfiles
+- ChangeLayout.sh
+ - Dynamically binds SUPER J/K based on current layout
+ - Previously only worked in Master Layout
+ - Credit: Suresh Thagunna
+ - Along with that KeybindsLayoutInit script reads current default layout
+ - Then it adjusts the SUPER J/K keybindings appropriately
+- RofiBeats dynamic music system added
+- Binds now include descriptions.
+ - Switched from `bind` to `bindd`
+ - Improves usability of keybind search
+- Add new laptop gesture for zoom system.
+
+Thanks to everyone that contributed, or reported issues.
diff --git a/Distro-Hyprland.sh b/Distro-Hyprland.sh
index ff88325f..99a1fc34 100755
--- a/Distro-Hyprland.sh
+++ b/Distro-Hyprland.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# https://github.com/JaKooLit
# Script design to clone the Distro-Hyprland install scripts
diff --git a/config/fastfetch/config-compact.jsonc b/config/fastfetch/config-compact.jsonc
index fc2c4884..962b6bb3 100644
--- a/config/fastfetch/config-compact.jsonc
+++ b/config/fastfetch/config-compact.jsonc
@@ -21,16 +21,22 @@
{
"type": "custom",
"format": " ─────────────────────────── "
- },
+ },
{
"type": "kernel",
"key": " ",
"keyColor": "yellow"
},
{
+ "type": "custom",
+ "key": " ",
+ "format": "JaKooLit: {$DOTS_VERSION}",
+ "keyColor": "blue"
+ },
+ {
"type": "wm",
"key": " ",
- "keyColor": "blue"
+ "keyColor": "magenta"
},
{
"type": "shell",
@@ -69,6 +75,6 @@
"type": "custom",
"format": " \u001b[31m \u001b[32m \u001b[33m \u001b[34m \u001b[35m \u001b[36m \u001b[37m \u001b[90m "
},
- "break",
+ "break"
]
}
diff --git a/config/fastfetch/config-pokemon.jsonc b/config/fastfetch/config-pokemon.jsonc
index 2b4522f4..0435033c 100644
--- a/config/fastfetch/config-pokemon.jsonc
+++ b/config/fastfetch/config-pokemon.jsonc
@@ -27,9 +27,15 @@
"keyColor": "yellow"
},
{
+ "type": "custom",
+ "key": " ",
+ "keyColor": "blue",
+ "format": "JaKooLit Version: {$DOTS_VERSION}"
+ },
+ {
"type": "wm",
"key": " ",
- "keyColor": "blue"
+ "keyColor": "magenta"
},
{
"type": "shell",
@@ -68,6 +74,6 @@
"type": "custom",
"format": " \u001b[31m \u001b[32m \u001b[33m \u001b[34m \u001b[35m \u001b[36m \u001b[37m \u001b[90m "
},
- "break",
+ "break"
]
}
diff --git a/config/fastfetch/config-v2.jsonc b/config/fastfetch/config-v2.jsonc
index 59509fe7..6d20c695 100644
--- a/config/fastfetch/config-v2.jsonc
+++ b/config/fastfetch/config-v2.jsonc
@@ -20,95 +20,101 @@
{
"type": "os",
"key": " DISTRO",
- "keyColor": "31",
+ "keyColor": "31"
},
{
"type": "kernel",
"key": " ├  ",
- "keyColor": "31",
+ "keyColor": "31"
+ },
+ {
+ "type": "custom",
+ "key": " ├  ",
+ "format": "JaKooLit Version: {$DOTS_VERSION}",
+ "keyColor": "31"
},
{
"type": "packages",
"key": " ├ 󰏖 ",
- "keyColor": "31",
+ "keyColor": "31"
},
{
"type": "shell",
"key": " └  ",
- "keyColor": "31",
+ "keyColor": "31"
},
"break",
{
"type": "wm",
"key": " DE/WM",
- "keyColor": "32",
+ "keyColor": "32"
},
{
"type": "wmtheme",
"key": " ├ 󰉼 ",
- "keyColor": "32",
+ "keyColor": "32"
},
{
"type": "icons",
"key": " ├ 󰀻 ",
- "keyColor": "32",
+ "keyColor": "32"
},
{
"type": "cursor",
"key": " ├  ",
- "keyColor": "32",
+ "keyColor": "32"
},
{
"type": "terminal",
"key": " ├  ",
- "keyColor": "32",
+ "keyColor": "32"
},
{
"type": "terminalfont",
"key": " └  ",
- "keyColor": "32",
+ "keyColor": "32"
},
"break",
{
"type": "host",
"format": "{2}",
"key": "󰌢 SYSTEM",
- "keyColor": "33",
+ "keyColor": "33"
},
{
"type": "cpu",
"format": "{1} ({3}) @ {7} GHz",
"key": " ├  ",
- "keyColor": "33",
+ "keyColor": "33"
},
{
"type": "gpu",
"format": "{2}",
"key": " ├ 󰢮 ",
- "keyColor": "33",
+ "keyColor": "33"
},
{
"type": "memory",
"key": " ├  ",
- "keyColor": "33",
+ "keyColor": "33"
},
{
"type": "swap",
"key": " ├ 󰓡 ",
- "keyColor": "33",
+ "keyColor": "33"
},
{
"type": "disk",
"key": " ├ 󰋊 ",
- "keyColor": "33",
+ "keyColor": "33"
},
{
"type": "display",
"key": " └  ",
"compactType": "original-with-refresh-rate",
- "keyColor": "33",
+ "keyColor": "33"
},
"break",
- "break",
+ "break"
]
}
diff --git a/config/fastfetch/config.jsonc b/config/fastfetch/config.jsonc
index e3f8c3c6..dce06d78 100644
--- a/config/fastfetch/config.jsonc
+++ b/config/fastfetch/config.jsonc
@@ -17,10 +17,17 @@
"key": " DISTRO",
"keyColor": "yellow"
},
+
{
"type": "kernel",
"key": "│ ├",
"keyColor": "yellow"
+ },
+ {
+ "type": "custom",
+ "key": "│ ├",
+ "format": "JaKooLit Version: {$DOTS_VERSION}",
+ "keyColor": "yellow"
},
{
"type": "packages",
@@ -50,12 +57,12 @@
{
"type": "cursor",
"key": "│ ├",
- "keyColor": "blue",
+ "keyColor": "blue"
},
{
"type": "terminalfont",
"key": "│ ├",
- "keyColor": "blue",
+ "keyColor": "blue"
},
{
"type": "terminal",
@@ -124,6 +131,6 @@
"type": "custom",
"format": "\u001b[90m \u001b[31m \u001b[32m \u001b[33m \u001b[34m \u001b[35m \u001b[36m \u001b[37m \u001b[38m \u001b[39m \u001b[39m  \u001b[38m \u001b[37m \u001b[36m \u001b[35m \u001b[34m \u001b[33m \u001b[32m \u001b[31m \u001b[90m "
},
- "break",
+ "break"
]
}
diff --git a/config/hypr/UserConfigs/ENVariables.conf b/config/hypr/UserConfigs/ENVariables.conf
index f24cc306..4e736dc3 100644
--- a/config/hypr/UserConfigs/ENVariables.conf
+++ b/config/hypr/UserConfigs/ENVariables.conf
@@ -4,6 +4,9 @@
# Set your defaults editor through ENV in ~/.config/hypr/UserConfigs/01-UserDefaults.conf
# environment-variables
+# Current Version of JakooLit Dotfiles:
+env = DOTS_VERSION,2.3.18
+
# Toolkit Backend Variables
env = GDK_BACKEND,wayland,x11,*
env = QT_QPA_PLATFORM,wayland;xcb
diff --git a/config/hypr/UserConfigs/UserKeybinds.conf b/config/hypr/UserConfigs/UserKeybinds.conf
index 338bf0d1..17711559 100644
--- a/config/hypr/UserConfigs/UserKeybinds.conf
+++ b/config/hypr/UserConfigs/UserKeybinds.conf
@@ -16,67 +16,68 @@ source= $UserConfigs/01-UserDefaults.conf
# common shortcuts
#bindr = $mainMod, $mainMod_L, exec, pkill rofi || rofi -show drun -modi drun,filebrowser,run,window # Super Key to Launch rofi menu
-bind = $mainMod, D, exec, pkill rofi || true && rofi -show drun -modi drun,filebrowser,run,window # Main Menu (APP Launcher)
-bind = $mainMod, B, exec, xdg-open "https://" # default browser
-#bind = $mainMod, A, exec, pkill rofi || true && ags -t 'overview' # desktop overview (if installed)
-#bind = $mainMod, A, global, quickshell:overviewToggle # desktop overview (if installed)
-bind = $mainMod, Return, exec, $term #terminal
-bind = $mainMod, E, exec, $files #file manager
+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
# FEATURES / EXTRAS
-bind = $mainMod, H, exec, $scriptsDir/KeyHints.sh # help / cheat sheet
-bind = $mainMod ALT, R, exec, $scriptsDir/Refresh.sh # Refresh waybar, swaync, rofi
-bind = $mainMod ALT, E, exec, $scriptsDir/RofiEmoji.sh # emoji menu
-bind = $mainMod, S, exec, $scriptsDir/RofiSearch.sh # Google search using rofi
-bind = $mainMod CTRL, S, exec, rofi -show window # list/switch apps using rofi
-bind = $mainMod ALT, O, exec, $scriptsDir/ChangeBlur.sh # Toggle blur settings
-bind = $mainMod SHIFT, G, exec, $scriptsDir/GameMode.sh # Toggle animations ON/OFF
-bind = $mainMod ALT, L, exec, $scriptsDir/ChangeLayout.sh # Toggle Master or Dwindle Layout
-bind = $mainMod ALT, V, exec, $scriptsDir/ClipManager.sh # Clipboard Manager
-bind = $mainMod CTRL, R, exec, $scriptsDir/RofiThemeSelector.sh # KooL Rofi Menu Theme Selector
-bind = $mainMod CTRL SHIFT, R, exec, pkill rofi || true && $scriptsDir/RofiThemeSelector-modified.sh # modified Rofi Theme Selector
+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 master/dwindle layout, exec, $scriptsDir/ChangeLayout.sh
+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
-bind = $mainMod SHIFT, F, fullscreen # whole full screen
-bind = $mainMod CTRL, F, fullscreen, 1 # fake full screen
-bind = $mainMod, SPACE, togglefloating, #Float Mode
-bind = $mainMod ALT, SPACE, exec, hyprctl dispatch workspaceopt allfloat #All Float Mode
-bind = $mainMod SHIFT, Return, exec, $scriptsDir/Dropterminal.sh $term # Dropdown terminal
+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, hyprctl dispatch workspaceopt allfloat
+bindd = $mainMod SHIFT, Return, DropDown terminal, exec, $scriptsDir/Dropterminal.sh $term
# Desktop zooming or magnifier
-bind = $mainMod ALT, mouse_down, 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}')"
-bind = $mainMod ALT, mouse_up, 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}')"
## NOTES for ja (Hyprland version 0.39 (Ubuntu 24.04))
#bind = $mainMod ALT, mouse_down, exec, hyprctl keyword misc:cursor_zoom_factor "$(hyprctl getoption misc:cursor_zoom_factor | awk 'NR==1 {factor = $2; if (factor < 1) {factor = 1}; print factor * 2.0}')"
#bind = $mainMod ALT, mouse_up, exec, hyprctl keyword misc:cursor_zoom_factor "$(hyprctl getoption misc:cursor_zoom_factor | awk 'NR==1 {factor = $2; if (factor < 1) {factor = 1}; print factor / 2.0}')"
# Waybar / Bar related
-bind = $mainMod CTRL ALT, B, exec, pkill -SIGUSR1 waybar # Toggle hide/show waybar
-bind = $mainMod CTRL, B, exec, $scriptsDir/WaybarStyles.sh # Waybar Styles Menu
-bind = $mainMod ALT, B, exec, $scriptsDir/WaybarLayout.sh # Waybar Layout Menu
+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)
-bind = $mainMod, N, exec, $scriptsDir/Hyprsunset.sh toggle
+bindd = $mainMod, N, toggle night light, exec, $scriptsDir/Hyprsunset.sh toggle
# FEATURES / EXTRAS (UserScripts)
-bind = $mainMod SHIFT, M, exec, $UserScripts/RofiBeats.sh # online music using rofi
-bind = $mainMod, W, exec, $UserScripts/WallpaperSelect.sh # Select wallpaper to apply
-bind = $mainMod SHIFT, W, exec, $UserScripts/WallpaperEffects.sh # Wallpaper Effects by imagemagick
-bind = CTRL ALT, W, exec, $UserScripts/WallpaperRandom.sh # Random wallpapers
-bind = $mainMod CTRL, O, exec, hyprctl setprop active opaque toggle # disable opacity on active window
-bind = $mainMod SHIFT, K, exec, $scriptsDir/KeyBinds.sh # search keybinds via rofi
-bind = $mainMod SHIFT, A, exec, $scriptsDir/Animations.sh #hyprland animations menu
-bind = $mainMod SHIFT, O, exec, $UserScripts/ZshChangeTheme.sh # Change oh-my-zsh theme
-bindln = ALT_L, SHIFT_L, exec, $scriptsDir/SwitchKeyboardLayout.sh # Change keyboard layout globally
-bindln = SHIFT_L, ALT_L, exec, $scriptsDir/Tak0-Per-Window-Switch.sh # Change keyboard layout locally for each window
-bind = $mainMod ALT, C, exec, $UserScripts/RofiCalc.sh # calculator (qalculate)
+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, exec, hyprctl 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/SwitchKeyboardLayout.sh
+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)
-bind = $mainMod CTRL, F9, movecurrentworkspacetomonitor, l #move current workspace to LEFT monitor
-bind = $mainMod CTRL, F10, movecurrentworkspacetomonitor, r #move current workspace to RIGHT monitor
-bind = $mainMod CTRL, F11, movecurrentworkspacetomonitor, u #move current workspace to UP monitor
-bind = $mainMod CTRL, F12, movecurrentworkspacetomonitor, d #move current workspace to DOWN monitor
+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
# For passthrough keyboard into a VM
diff --git a/config/hypr/UserConfigs/UserSettings.conf b/config/hypr/UserConfigs/UserSettings.conf
index f81ccc6a..4802e79a 100644
--- a/config/hypr/UserConfigs/UserSettings.conf
+++ b/config/hypr/UserConfigs/UserSettings.conf
@@ -73,6 +73,8 @@ gestures {
workspace_swipe_create_new = true
workspace_swipe_forever = true
#workspace_swipe_use_r = true #uncomment if wanted a forever create a new workspace with swipe right
+ 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}')"
}
misc {
diff --git a/config/hypr/UserConfigs/WindowRules-v3.conf b/config/hypr/UserConfigs/WindowRules-v3.conf
new file mode 100644
index 00000000..f093faf6
--- /dev/null
+++ b/config/hypr/UserConfigs/WindowRules-v3.conf
@@ -0,0 +1,671 @@
+# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ #
+# For window rules and layerrules
+# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
+
+# NOTES: This is only for Hyprland > 0.52
+
+# note for ja: This should NOT be implemented on Debian and Ubuntu
+
+# windowrule - tags - add apps under appropriate tag to use the same settings
+# browser tags
+# notif tags
+# KooL settings tag
+# terminal tags
+# email tags
+# project tags
+# screenshare tags
+# IM tags
+# game tags
+# gamestore tags
+# file-manager tags
+# wallpaper tags
+# multimedia tags
+# multimedia-video tags
+# settings tags
+# viewer tags
+# Some special override rules
+
+# POSITION
+# windowrule = center,floating:1 # warning, it cause even the menu to float and center.
+#windowrule = move 72% 7%,title:^(Firefox)$
+
+# windowrule to avoid idle for fullscreen apps
+#windowrule = idleinhibit fullscreen, class:^(*)$
+#windowrule = idleinhibit fullscreen, title:^(*)$
+
+# 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, class:^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$
+#windowrule = float, title:^(Firefox)$
+
+# windowrule - ######### float popups and dialogue #######
+
+
+# OPACITY
+
+# SIZE
+
+#windowrule = size 25% 25%, title:^(Picture-in-Picture)$
+#windowrule = size 25% 25%, title:^(Firefox)$
+
+# PINNING
+#windowrule = pin,title:^(Firefox)$
+
+# windowrule - extras
+
+# BLUR & FULLSCREEN
+
+
+#This not gonna take the focus to the window that appears when hovering over some of the parts of the IntelliJ Products
+
+#This will gonna make the VS Code bluer like other apps
+
+#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 = 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
+
+# --- Auto-generated window rules ---
+windowrule {
+ name = windowrule-1
+ match:class = ^([Ff]irefox|org.mozilla.firefox|[Ff]irefox-esr|[Ff]irefox-bin)$
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-2
+ match:class = ^([Gg]oogle-chrome(-beta|-dev|-unstable)?)$
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-3
+ match:class = ^(chrome-.+-Default)$ # Chrome PWAs
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-4
+ match:class = ^([Cc]hromium)$
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-5
+ match:class = ^([Mm]icrosoft-edge(-stable|-beta|-dev|-unstable))$
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-6
+ match:class = ^(Brave-browser(-beta|-dev|-unstable)?)$
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-7
+ match:class = ^([Tt]horium-browser|[Cc]achy-browser)$
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-8
+ match:class = ^(zen-alpha|zen)$
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-9
+ match:class = ^(swaync-control-center|swaync-notification-window|swaync-client|class)$
+ tag = +notif
+}
+
+windowrule {
+ name = windowrule-10
+ match:title = ^(KooL Quick Cheat Sheet)$
+ tag = +KooL_Cheat
+}
+
+windowrule {
+ name = windowrule-11
+ match:title = ^(KooL Hyprland Settings)$
+ tag = +KooL_Settings
+}
+
+windowrule {
+ name = windowrule-12
+ match:class = ^(nwg-displays|nwg-look)$
+ tag = +KooL-Settings
+}
+
+windowrule {
+ name = windowrule-13
+ match:class = ^(Alacritty|kitty|kitty-dropterm)$
+ tag = +terminal
+}
+
+windowrule {
+ name = windowrule-14
+ match:class = ^([Tt]hunderbird|org.gnome.Evolution)$
+ tag = +email
+}
+
+windowrule {
+ name = windowrule-15
+ match:class = ^(eu.betterbird.Betterbird)$
+ tag = +email
+}
+
+windowrule {
+ name = windowrule-16
+ match:class = ^(codium|codium-url-handler|VSCodium)$
+ tag = +projects
+}
+
+windowrule {
+ name = windowrule-17
+ match:class = ^(VSCode|code-url-handler)$
+ tag = +projects
+}
+
+windowrule {
+ name = windowrule-18
+ match:class = ^(jetbrains-.+)$ # JetBrains IDEs
+ tag = +projects
+}
+
+windowrule {
+ name = windowrule-19
+ match:class = ^(com.obsproject.Studio)$
+ tag = +screenshare
+}
+
+windowrule {
+ name = windowrule-20
+ match:class = ^([Dd]iscord|[Ww]ebCord|[Vv]esktop)$
+ tag = +im
+}
+
+windowrule {
+ name = windowrule-21
+ match:class = ^([Ff]erdium)$
+ center = on
+ float = on
+ size = 60% = 70%
+ tag = +im
+}
+
+windowrule {
+ name = windowrule-22
+ match:class = ^([Ww]hatsapp-for-linux)$
+ tag = +im
+}
+
+windowrule {
+ name = windowrule-23
+ match:class = ^(ZapZap|com.rtosta.zapzap)$
+ tag = +im
+}
+
+windowrule {
+ name = windowrule-24
+ match:class = ^(org.telegram.desktop|io.github.tdesktop_x64.TDesktop)$
+ tag = +im
+}
+
+windowrule {
+ name = windowrule-25
+ match:class = ^(teams-for-linux)$
+ tag = +im
+}
+
+windowrule {
+ name = windowrule-26
+ match:class = ^(im.riot.Riot|Element)$ # Element Matrix client
+ tag = +im
+}
+
+windowrule {
+ name = windowrule-27
+ match:class = ^(gamescope)$
+ tag = +games
+}
+
+windowrule {
+ name = windowrule-28
+ match:class = ^(steam_app_\d+)$
+ tag = +games
+}
+
+windowrule {
+ name = windowrule-29
+ match:class = ^([Ss]team)$
+ tag = +gamestore
+}
+
+windowrule {
+ name = windowrule-30
+ match:title = ^([Ll]utris)$
+ tag = +gamestore
+}
+
+windowrule {
+ name = windowrule-31
+ match:class = ^(com.heroicgameslauncher.hgl)$
+ tag = +gamestore
+}
+
+windowrule {
+ name = windowrule-32
+ match:class = ^([Tt]hunar|org.gnome.Nautilus|[Pp]cmanfm-qt)$
+ tag = +file-manager
+}
+
+windowrule {
+ name = windowrule-33
+ match:class = ^(app.drey.Warp)$
+ tag = +file-manager
+}
+
+windowrule {
+ name = windowrule-34
+ match:class = ^([Ww]aytrogen)$
+ tag = +wallpaper
+}
+
+windowrule {
+ name = windowrule-35
+ match:class = ^([Aa]udacious)$
+ tag = +multimedia
+}
+
+windowrule {
+ name = windowrule-36
+ match:class = ^([Mm]pv|vlc)$
+ tag = +multimedia_video
+}
+
+windowrule {
+ name = windowrule-37
+ match:title = ^(ROG Control)$
+ center = on
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-38
+ match:class = ^(wihotspot(-gui)?)$ # wifi hotspot
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-39
+ match:class = ^([Bb]aobab|org.gnome.[Bb]aobab)$ # Disk usage analyzer
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-40
+ match:class = ^(gnome-disks|wihotspot(-gui)?)$
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-41
+ match:title = (Kvantum Manager)
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-42
+ match:class = ^(file-roller|org.gnome.FileRoller)$ # archive manager
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-43
+ match:class = ^(nm-applet|nm-connection-editor|blueman-manager)$
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-44
+ match:class = ^(pavucontrol|org.pulseaudio.pavucontrol|com.saivert.pwvucontrol)$
+ center = on
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-45
+ match:class = ^(qt5ct|qt6ct|[Yy]ad)$
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-46
+ match:class = (xdg-desktop-portal-gtk)
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-47
+ match:class = ^(org.kde.polkit-kde-authentication-agent-1)$
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-48
+ match:class = ^([Rr]ofi)$
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-49
+ match:class = ^(gnome-system-monitor|org.gnome.SystemMonitor|io.missioncenter.MissionCenter)$ # system monitor
+ tag = +viewer
+}
+
+windowrule {
+ name = windowrule-50
+ match:class = ^(evince)$ # document viewer
+ tag = +viewer
+}
+
+windowrule {
+ name = windowrule-51
+ match:class = ^(eog|org.gnome.Loupe)$ # image viewer
+ tag = +viewer
+}
+
+windowrule {
+ name = windowrule-52
+ match:tag = multimedia_video*
+ no_blur = on
+ opacity = 1.0
+}
+
+windowrule {
+ name = windowrule-53
+ match:tag = KooL_Cheat*
+ center = on
+ float = on
+ size = 65% = 90%
+}
+
+windowrule {
+ name = windowrule-54
+ match:class = ([Tt]hunar)
+ match:title = negative:(.*[Tt]hunar.*)
+ center = on
+ float = on
+}
+
+windowrule {
+ name = windowrule-55
+ match:tag = KooL-Settings*
+ center = on
+ float = on
+}
+
+windowrule {
+ name = windowrule-56
+ match:title = ^(Keybindings)$
+ center = on
+}
+
+windowrule {
+ name = windowrule-57
+ match:class = ^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$
+ center = on
+ size = 60% = 70%
+}
+
+windowrule {
+ name = windowrule-58
+ match:title = ^(Picture-in-Picture)$
+ float = on
+ move = 72% = 7%
+ opacity = 0.95 = 0.75
+ pin = 0
+}
+
+windowrule {
+ name = windowrule-59
+ match:fullscreen = 1
+ idle_inhibit = fullscreen
+}
+
+windowrule {
+ name = windowrule-60
+ match:tag = wallpaper*
+ float = on
+ opacity = 0.9 = 0.7
+ size = 70% = 70%
+}
+
+windowrule {
+ name = windowrule-61
+ match:tag = settings*
+ float = on
+ opacity = 0.8 = 0.7
+ size = 70% = 70%
+}
+
+windowrule {
+ name = windowrule-62
+ match:tag = viewer*
+ float = on
+ opacity = 0.82 = 0.75
+}
+
+windowrule {
+ name = windowrule-63
+ match:class = ([Zz]oom|onedriver|onedriver-launcher)$
+ float = on
+}
+
+windowrule {
+ name = windowrule-64
+ match:class = (org.gnome.Calculator)
+ match:title = (Calculator)
+ float = on
+}
+
+windowrule {
+ name = windowrule-65
+ match:class = ^(mpv|com.github.rafostar.Clapper)$
+ float = on
+}
+
+windowrule {
+ name = windowrule-66
+ match:class = ^([Qq]alculate-gtk)$
+ float = on
+}
+
+windowrule {
+ name = windowrule-67
+ match:title = ^(Authentication Required)$
+ center = on
+ float = on
+}
+
+windowrule {
+ name = windowrule-68
+ match:class = (codium|codium-url-handler|VSCodium)
+ match:title = negative:(.*codium.*|.*VSCodium.*)
+ float = on
+}
+
+windowrule {
+ name = windowrule-69
+ match:class = ^(com.heroicgameslauncher.hgl)$
+ match:title = negative:(Heroic Games Launcher)
+ float = on
+}
+
+windowrule {
+ name = windowrule-70
+ match:class = ^([Ss]team)$
+ match:title = negative:^([Ss]team)$
+ float = on
+}
+
+windowrule {
+ name = windowrule-71
+ match:title = ^(Add Folder to Workspace)$
+ center = on
+ float = on
+ size = 70% = 60%
+}
+
+windowrule {
+ name = windowrule-72
+ match:title = ^(Save As)$
+ center = on
+ float = on
+ size = 70% = 60%
+}
+
+windowrule {
+ name = windowrule-73
+ match:initial_title = (Open Files)
+ float = on
+ size = 70% = 60%
+}
+
+windowrule {
+ name = windowrule-74
+ match:title = ^(SDDM Background)$ #KooL's Dots YAD for setting SDDM background
+ center = on
+ float = on
+ size = 16% = 12%
+}
+
+windowrule {
+ name = windowrule-75
+ match:tag = browser*
+ opacity = 0.99 = 0.8
+}
+
+windowrule {
+ name = windowrule-76
+ match:tag = projects*
+ opacity = 0.9 = 0.8
+}
+
+windowrule {
+ name = windowrule-77
+ match:tag = im*
+ opacity = 0.94 = 0.86
+}
+
+windowrule {
+ name = windowrule-78
+ match:tag = multimedia*
+ opacity = 0.94 = 0.86
+}
+
+windowrule {
+ name = windowrule-79
+ match:tag = file-manager*
+ opacity = 0.9 = 0.8
+}
+
+windowrule {
+ name = windowrule-80
+ match:tag = terminal*
+ opacity = 0.9 = 0.7
+}
+
+windowrule {
+ name = windowrule-81
+ match:class = ^(gedit|org.gnome.TextEditor|mousepad)$
+ opacity = 0.8 = 0.7
+}
+
+windowrule {
+ name = windowrule-82
+ match:class = ^(deluge)$
+ opacity = 0.9 = 0.8
+}
+
+windowrule {
+ name = windowrule-83
+ match:class = ^(seahorse)$ # gnome-keyring gui
+ opacity = 0.9 = 0.8
+}
+
+windowrule {
+ name = windowrule-84
+ match:class = ^(code)$
+ opacity = 0.8
+ opacity = 0.9
+}
+
+windowrule {
+ name = windowrule-85
+ match:tag = games*
+ fullscreen = 0
+ no_blur = on
+}
+
+windowrule {
+ name = windowrule-86
+ match:class = ^(jetbrains-*)
+ no_initial_focus = on
+}
+
+windowrule {
+ name = windowrule-87
+ match:title = ^(wind.*)$
+ no_initial_focus = on
+}
+
+# --- Auto-generated layer rules ---
+layerrule {
+ name = layerrule-1
+ match:namespace = rofi
+ blur = on
+ ignore_alpha = 0
+}
+
+layerrule {
+ name = layerrule-2
+ match:namespace = notifications
+ blur = on
+ ignore_alpha = 0
+}
+
+layerrule {
+ name = layerrule-3
+ match:namespace = quickshell:overview
+ blur = on
+ ignore_alpha = 0
+ ignore_alpha = 0.5
+}
diff --git a/config/hypr/UserConfigs/WindowRules.conf b/config/hypr/UserConfigs/WindowRules.conf
index d6959dc4..2c24dafc 100644
--- a/config/hypr/UserConfigs/WindowRules.conf
+++ b/config/hypr/UserConfigs/WindowRules.conf
@@ -113,20 +113,20 @@ windowrule = move 72% 7%,title:^(Picture-in-Picture)$
windowrule = idleinhibit fullscreen, fullscreen:1
# windowrule move to workspace
-windowrule = workspace 1, tag:email*
-windowrule = workspace 2, tag:browser*
+#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 = 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*
-
+#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*
@@ -167,12 +167,12 @@ windowrule = size 16% 12%, title:^(SDDM Background)$ #KooL's Dots YAD for settin
# END of float popups and dialogue #######
# OPACITY
-windowrule = opacity 0.9 0.7, tag:browser*
+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.8 0.7, tag:terminal*
+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*
diff --git a/config/hypr/UserScripts/RainbowBorders.sh b/config/hypr/UserScripts/RainbowBorders.sh
index cc1419fb..0a7fd721 100755
--- a/config/hypr/UserScripts/RainbowBorders.sh
+++ b/config/hypr/UserScripts/RainbowBorders.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# for rainbow borders animation
diff --git a/config/hypr/UserScripts/RofiBeats.sh b/config/hypr/UserScripts/RofiBeats.sh
index 1cddce09..a002a518 100755
--- a/config/hypr/UserScripts/RofiBeats.sh
+++ b/config/hypr/UserScripts/RofiBeats.sh
@@ -1,35 +1,39 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
-# For Rofi Beats to play online Music or Locally saved media files
+# RofiBeats - unified, dynamic UI (add, remove, manage, play)
-# Variables
mDIR="$HOME/Music/"
iDIR="$HOME/.config/swaync/icons"
rofi_theme="$HOME/.config/rofi/config-rofi-Beats.rasi"
-rofi_theme_1="$HOME/.config/rofi/config-rofi-Beats-menu.rasi"
+rofi_theme_menu="$HOME/.config/rofi/config-rofi-Beats-menu.rasi"
+music_list="$HOME/.config/rofi/online_music.list"
-# Online Stations. Edit as required
-declare -A online_music=(
- ["FM - Easy Rock 96.3 📻🎶"]="https://radio-stations-philippines.com/easy-rock"
- ["FM - Easy Rock - Baguio 91.9 📻🎶"]="https://radio-stations-philippines.com/easy-rock-baguio"
- ["FM - Love Radio 90.7 📻🎶"]="https://radio-stations-philippines.com/love"
- ["FM - WRock - CEBU 96.3 📻🎶"]="https://onlineradio.ph/126-96-3-wrock.html"
- ["FM - Fresh Philippines 📻🎶"]="https://onlineradio.ph/553-fresh-fm.html"
- ["Radio - Lofi Girl 🎧🎶"]="https://play.streamafrica.net/lofiradio"
- ["Radio - Chillhop 🎧🎶"]="http://stream.zeno.fm/fyn8eh3h5f8uv"
- ["Radio - Ibiza Global 🎧🎶"]="https://filtermusic.net/ibiza-global"
- ["Radio - Metal Music 🎧🎶"]="https://tunein.com/radio/mETaLmuSicRaDio-s119867/"
- ["YT - Wish 107.5 YT Pinoy HipHop 📻🎶"]="https://youtube.com/playlist?list=PLkrzfEDjeYJnmgMYwCKid4XIFqUKBVWEs&si=vahW_noh4UDJ5d37"
- ["YT - Youtube Top 100 Songs Global 📹🎶"]="https://youtube.com/playlist?list=PL4fGSI1pDJn6puJdseH2Rt9sMvt9E2M4i&si=5jsyfqcoUXBCSLeu"
- ["YT - Wish 107.5 YT Wishclusives 📹🎶"]="https://youtube.com/playlist?list=PLkrzfEDjeYJn5B22H9HOWP3Kxxs-DkPSM&si=d_Ld2OKhGvpH48WO"
- ["YT - Relaxing Piano Music 🎹🎶"]="https://youtu.be/6H7hXzjFoVU?si=nZTPREC9lnK1JJUG"
- ["YT - Youtube Remix 📹🎶"]="https://youtube.com/playlist?list=PLeqTkIUlrZXlSNn3tcXAa-zbo95j0iN-0"
- ["YT - Korean Drama OST 📹🎶"]="https://youtube.com/playlist?list=PLUge_o9AIFp4HuA-A3e3ZqENh63LuRRlQ"
- ["YT - lofi hip hop radio beats 📹🎶"]="https://www.youtube.com/live/jfKfPfyJRdk?si=PnJIA9ErQIAw6-qd"
- ["YT - Relaxing Piano Jazz Music 🎹🎶"]="https://youtu.be/85UEqRat6E4?si=jXQL1Yp2VP_G6NSn"
-)
+mkdir -p "$(dirname "$music_list")"
+[[ -f "$music_list" ]] || touch "$music_list"
-# Populate local_music array with files from music directory and subdirectories
+# Send notification
+notification() {
+ notify-send -u normal -i "$iDIR/music.png" "$@"
+}
+
+# Check if mpv is currently playing
+music_playing() { pgrep -x "mpv" >/dev/null; }
+
+# Stop all mpv processes except mpvpaper
+stop_music() {
+ mpv_pids=$(pgrep -x mpv)
+ if [ -n "$mpv_pids" ]; then
+ mpvpaper_pid=$(ps aux | grep -- 'unique-wallpaper-process' | grep -v 'grep' | awk '{print $2}')
+ for pid in $mpv_pids; do
+ if ! echo "$mpvpaper_pid" | grep -q "$pid"; then
+ kill -9 $pid || true
+ fi
+ done
+ notification "Music stopped"
+ fi
+}
+
+# Populate local music file list
populate_local_music() {
local_music=()
filenames=()
@@ -39,115 +43,94 @@ populate_local_music() {
done < <(find -L "$mDIR" -type f \( -iname "*.mp3" -o -iname "*.flac" -o -iname "*.wav" -o -iname "*.ogg" -o -iname "*.mp4" \))
}
-# Function for displaying notifications
-notification() {
- notify-send -u normal -i "$iDIR/music.png" "Now Playing:" "$@"
-}
-
-# Main function for playing local music
+# Play selected local music file
play_local_music() {
populate_local_music
-
- # Prompt the user to select a song
- choice=$(printf "%s\n" "${filenames[@]}" | rofi -i -dmenu -config $rofi_theme)
-
- if [ -z "$choice" ]; then
- exit 1
- fi
-
- # Find the corresponding file path based on user's choice and set that to play the song then continue on the list
- for (( i=0; i<"${#filenames[@]}"; ++i )); do
+ choice=$(printf "%s\n" "${filenames[@]}" | rofi -i -dmenu -config "$rofi_theme" \
+ -theme-str 'entry { placeholder: "🎵 Choose Local Music"; }')
+ [[ -z "$choice" ]] && exit 1
+ for ((i = 0; i < "${#filenames[@]}"; ++i)); do
if [ "${filenames[$i]}" = "$choice" ]; then
-
- if music_playing; then
- stop_music
- fi
- notification "$choice"
- mpv --playlist-start="$i" --loop-playlist --vid=no "${local_music[@]}"
-
+ music_playing && stop_music
+ notification "Now Playing:" "$choice"
+ mpv --no-video --playlist-start="$i" --loop-playlist "${local_music[@]}"
break
fi
done
}
-# Main function for shuffling local music
+# Shuffle and play all local music
shuffle_local_music() {
- if music_playing; then
- stop_music
- fi
+ music_playing && stop_music
notification "Shuffle Play local music"
-
- # Play music in $mDIR on shuffle
- mpv --shuffle --loop-playlist --vid=no "$mDIR"
+ mpv --no-video --shuffle --loop-playlist "$mDIR"
}
-# Main function for playing online music
+# Play selected online music
play_online_music() {
- choice=$(for online in "${!online_music[@]}"; do
- echo "$online"
- done | sort | rofi -i -dmenu -config "$rofi_theme")
-
- if [ -z "$choice" ]; then
- exit 1
+ if [ ! -s "$music_list" ]; then
+ notify-send -u low -i "$iDIR/music.png" "No online music found" "Add some with Manage Music"
+ exit 0
fi
-
- link="${online_music[$choice]}"
-
- if music_playing; then
- stop_music
- fi
- notification "$choice"
-
- # Play the selected online music using mpv
- mpv --shuffle --vid=no "$link"
-}
-
-# Function to check if music is already playing
-music_playing() {
- pgrep -x "mpv" > /dev/null
+ choice=$(awk -F'|' '{print $1}' "$music_list" | sort | rofi -i -dmenu -config "$rofi_theme" \
+ -theme-str 'entry { placeholder: "🌐 Choose Online Station"; }')
+ [[ -z "$choice" ]] && exit 1
+ link=$(awk -F'|' -v name="$choice" '$1 == name {print $2; exit}' "$music_list")
+ [[ -z "$link" ]] && {
+ notify-send -u low -i "$iDIR/music.png" "URL not found for" "$choice"
+ exit 1
+ }
+ music_playing && stop_music
+ notification "Now Playing:" "$choice"
+ mpv --no-video --shuffle "$link"
}
-# Function to stop music and kill mpv processes
-stop_music() {
- mpv_pids=$(pgrep -x mpv)
+# Manage online music list (add, remove, view)
+manage_music() {
+ sub_choice=$(printf "Add Music\nRemove Music\nView List" | rofi -dmenu \
+ -config "$rofi_theme_menu" \
+ -theme-str 'entry { placeholder: "🛠️ Manage Music List"; }')
- if [ -n "$mpv_pids" ]; then
- # Get the PID of the mpv process used by mpvpaper (using the unique argument added)
- mpvpaper_pid=$(ps aux | grep -- 'unique-wallpaper-process' | grep -v 'grep' | awk '{print $2}')
-
- for pid in $mpv_pids; do
- if ! echo "$mpvpaper_pid" | grep -q "$pid"; then
- kill -9 $pid || true
- fi
- done
- notify-send -u low -i "$iDIR/music.png" "Music stopped" || true
- fi
+ case "$sub_choice" in
+ "Add Music")
+ name=$(rofi -dmenu -lines 0 -config "$rofi_theme_menu" \
+ -theme-str 'entry { placeholder: "🎼 Enter Music Title"; }')
+ [[ -z "$name" ]] && return
+ url=$(rofi -dmenu -lines 0 -config "$rofi_theme_menu" \
+ -theme-str 'entry { placeholder: "🔗 Enter Music URL"; }')
+ [[ -z "$url" ]] && return
+ echo "$name|$url" >>"$music_list"
+ notification "Added" "$name"
+ ;;
+ "Remove Music")
+ entry=$(awk -F'|' '{print $1}' "$music_list" | rofi -dmenu -config "$rofi_theme_menu" \
+ -theme-str 'entry { placeholder: "🗑️ Select Music to Remove"; }')
+ [[ -z "$entry" ]] && return
+ grep -vF "$entry" "$music_list" >"$music_list.tmp" && mv "$music_list.tmp" "$music_list"
+ notification "Removed" "$entry"
+ ;;
+ "View List")
+ # Show only titles, not URLs
+ awk -F'|' '{print $1}' "$music_list" | rofi -dmenu -config "$rofi_theme_menu" \
+ -theme-str 'entry { placeholder: "📜 Online Music List"; }' >/dev/null
+ ;;
+ esac
}
+# Main menu
user_choice=$(printf "%s\n" \
"Play from Online Stations" \
"Play from Music directory" \
"Shuffle Play from Music directory" \
"Stop RofiBeats" \
- | rofi -dmenu -config $rofi_theme_1)
-
-echo "User choice: $user_choice"
+ "Manage Music List" |
+ rofi -dmenu -config "$rofi_theme_menu" \
+ -theme-str 'entry { placeholder: "🎧 RofiBeats Menu"; }')
case "$user_choice" in
- "Play from Online Stations")
- play_online_music
- ;;
- "Play from Music directory")
- play_local_music
- ;;
- "Shuffle Play from Music directory")
- shuffle_local_music
- ;;
- "Stop RofiBeats")
- if music_playing; then
- stop_music
- fi
- ;;
- *)
- ;;
+"Play from Online Stations") play_online_music ;;
+"Play from Music directory") play_local_music ;;
+"Shuffle Play from Music directory") shuffle_local_music ;;
+"Stop RofiBeats") music_playing && stop_music ;;
+"Manage Music List") manage_music ;;
esac
diff --git a/config/hypr/UserScripts/RofiCalc.sh b/config/hypr/UserScripts/RofiCalc.sh
index 4b3b8b69..b72d5f3e 100755
--- a/config/hypr/UserScripts/RofiCalc.sh
+++ b/config/hypr/UserScripts/RofiCalc.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */
# /* Calculator (using qalculate) and rofi */
# /* Submitted by: https://github.com/JosephArmas */
diff --git a/config/hypr/UserScripts/Tak0-Autodispatch.sh b/config/hypr/UserScripts/Tak0-Autodispatch.sh
index a1f72129..114a3e8e 100755
--- a/config/hypr/UserScripts/Tak0-Autodispatch.sh
+++ b/config/hypr/UserScripts/Tak0-Autodispatch.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# USAGE / ІНСТРУКЦІЯ:
# 1) Run from terminal:
# ./dispatch.sh <application_command> <target_workspace_number>
diff --git a/config/hypr/UserScripts/WallpaperAutoChange.sh b/config/hypr/UserScripts/WallpaperAutoChange.sh
index a6d2cedd..6d8e8735 100755
--- a/config/hypr/UserScripts/WallpaperAutoChange.sh
+++ b/config/hypr/UserScripts/WallpaperAutoChange.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# source https://wiki.archlinux.org/title/Hyprland#Using_a_script_to_change_wallpaper_every_X_minutes
diff --git a/config/hypr/UserScripts/WallpaperEffects.sh b/config/hypr/UserScripts/WallpaperEffects.sh
index ac8fc0e8..89577efa 100755
--- a/config/hypr/UserScripts/WallpaperEffects.sh
+++ b/config/hypr/UserScripts/WallpaperEffects.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ #
# Wallpaper Effects using ImageMagick (SUPER SHIFT W)
diff --git a/config/hypr/UserScripts/WallpaperRandom.sh b/config/hypr/UserScripts/WallpaperRandom.sh
index 79396508..654d4bd3 100755
--- a/config/hypr/UserScripts/WallpaperRandom.sh
+++ b/config/hypr/UserScripts/WallpaperRandom.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Script for Random Wallpaper ( CTRL ALT W)
diff --git a/config/hypr/UserScripts/WallpaperSelect.sh b/config/hypr/UserScripts/WallpaperSelect.sh
index 466832ba..9e51125f 100755
--- a/config/hypr/UserScripts/WallpaperSelect.sh
+++ b/config/hypr/UserScripts/WallpaperSelect.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */
# This script for selecting wallpapers (SUPER W)
diff --git a/config/hypr/UserScripts/Weather.py b/config/hypr/UserScripts/Weather.py
index ca1d5281..a6483777 100755
--- a/config/hypr/UserScripts/Weather.py
+++ b/config/hypr/UserScripts/Weather.py
@@ -3,21 +3,48 @@
# Rewritten to use Open-Meteo APIs (worldwide, no API key) for robust weather data.
# Outputs Waybar-compatible JSON and a simple text cache.
+from __future__ import annotations
+
import json
import os
import sys
import time
import html
-from typing import Any, Dict, List, Optional, Tuple
-
+from pathlib import Path
+from typing import Any, Dict, List, Optional, Tuple, TypeVar, Union, cast
+from typing import NamedTuple
import requests
+from dataclasses import dataclass
+
+@dataclass
+class Location:
+ lat: float
+ lon: float
+ place: Optional[str] = None
+
+
+@dataclass
+class WeatherData:
+ temp_str: str
+ feels_str: str
+ icon: str
+ status: str
+ min_max: str
+ wind_text: str
+ humidity_text: str
+ visibility_text: str
+ aqi_text: str
+ hourly_precip: str
+ is_day: int
+ code: int
+
# =============== Configuration ===============
# You can configure behavior via environment variables OR the constants below.
# Examples (zsh):
# # One-off run
# # WEATHER_UNITS can be "metric" or "imperial"
-# WEATHER_UNITS=imperial WEATHER_PLACE="Concord, NH" python3 /home/dwilliams/Projects/Weather.py
+# WEATHER_UNITS=imperial WEATHER_PLACE="Concord, NH" python3 ~/.config/hypr/UserScripts/Weather.py
#
# # Persist in current shell session
# export WEATHER_UNITS=imperial
@@ -27,10 +54,10 @@ import requests
# export WEATHER_TOOLTIP_MARKUP=1 # 1 to enable Pango markup, 0 to disable
# export WEATHER_LOC_ICON="📍" # or "*" for ASCII-only
#
-CACHE_DIR = os.path.expanduser("~/.cache")
-API_CACHE_PATH = os.path.join(CACHE_DIR, "open_meteo_cache.json")
-SIMPLE_TEXT_CACHE_PATH = os.path.join(CACHE_DIR, ".weather_cache")
-CACHE_TTL_SECONDS = int(os.getenv("WEATHER_CACHE_TTL", "600")) # default 10 minutes
+CACHE_DIR: Path = Path.home() / ".cache"
+API_CACHE_PATH: Path = CACHE_DIR / "open_meteo_cache.json"
+SIMPLE_TEXT_CACHE_PATH: Path = CACHE_DIR / ".weather_cache"
+CACHE_TTL_SECONDS = int(os.getenv("WEATHER_CACHE_TTL", "300")) # default 5 minutes
# Units: metric or imperial (default metric)
UNITS = os.getenv("WEATHER_UNITS", "metric").strip().lower() # metric|imperial
@@ -38,16 +65,17 @@ UNITS = os.getenv("WEATHER_UNITS", "metric").strip().lower() # metric|imperial
# Optional manual coordinates
ENV_LAT = os.getenv("WEATHER_LAT")
ENV_LON = os.getenv("WEATHER_LON")
-# Optional manual place override for tooltip
+# Optional manual place override for tooltip (and optional forward geocoding)
ENV_PLACE = os.getenv("WEATHER_PLACE")
-# Manual place name set inside this file. If set (non-empty), this takes top priority.
+# Manual place name set inside this file. If set (non-empty), this takes top priority for display
+# and, if coordinates are not provided, will be used to geocode latitude/longitude.
# Example: MANUAL_PLACE = "Concord, NH, US"
-MANUAL_PLACE: Optional[str] = None
+MANUAL_PLACE: Optional[str] = "" #Set your city HERE
# Location icon in tooltip (default to a standard emoji to avoid missing glyphs)
LOC_ICON = os.getenv("WEATHER_LOC_ICON", "📍")
# Enable/disable Pango markup in tooltip (1/0, true/false)
-TOOLTIP_MARKUP = os.getenv("WEATHER_TOOLTIP_MARKUP", "1").lower() not in ("0", "false", "no")
+TOOLTIP_MARKUP = os.getenv("WEATHER_TOOLTIP_MARKUP", "0").lower() in ("1", "true", "yes")
# Optional debug logging to stderr (set WEATHER_DEBUG=1 to enable)
DEBUG = os.getenv("WEATHER_DEBUG", "0").lower() not in ("0", "false", "no")
@@ -138,19 +166,68 @@ def log_debug(msg: str) -> None:
def ensure_cache_dir() -> None:
try:
- os.makedirs(CACHE_DIR, exist_ok=True)
+ # CACHE_DIR is a Path
+ CACHE_DIR.mkdir(parents=True, exist_ok=True)
except Exception as e:
print(f"Error creating cache dir: {e}", file=sys.stderr)
+def _coerce_numeric(value: Any, to_int: bool) -> Optional[Union[int, float]]:
+ if to_int:
+ if isinstance(value, int):
+ return value
+ if isinstance(value, (float, str)):
+ try:
+ return int(float(value))
+ except (ValueError, TypeError):
+ return None
+ return None
+ else:
+ if isinstance(value, float):
+ return value
+ if isinstance(value, int):
+ return float(value)
+ if isinstance(value, str):
+ try:
+ return float(value)
+ except (ValueError, TypeError):
+ return None
+ return None
+
+
+def coerce_int(value: Any) -> Optional[int]:
+ return cast(Optional[int], _coerce_numeric(value, True))
+
+
+def coerce_float(value: Any) -> Optional[float]:
+ return cast(Optional[float], _coerce_numeric(value, False))
+
+
+def coerce_number(value: Any) -> Union[int, float, None]:
+ if isinstance(value, (int, float)):
+ return value
+ if isinstance(value, str):
+ try:
+ # Parse to float, then return int if it has no fractional part
+ f = float(value)
+ return int(f) if f.is_integer() else f
+ except (ValueError, TypeError):
+ return None
+ return None
+
+
def read_api_cache() -> Optional[Dict[str, Any]]:
try:
- if not os.path.exists(API_CACHE_PATH):
+ if not API_CACHE_PATH.exists():
return None
- with open(API_CACHE_PATH, "r", encoding="utf-8") as f:
+ with API_CACHE_PATH.open("r", encoding="utf-8") as f:
data = json.load(f)
- if (time.time() - data.get("timestamp", 0)) <= CACHE_TTL_SECONDS:
- return data
+ # Use ensure_dict for safety
+ data_dict = ensure_dict(data)
+ timestamp_val = data_dict.get("timestamp", 0)
+ timestamp = coerce_float(timestamp_val) or 0
+ if (time.time() - timestamp) <= CACHE_TTL_SECONDS:
+ return data_dict
return None
except Exception as e:
print(f"Error reading cache: {e}", file=sys.stderr)
@@ -161,7 +238,7 @@ def write_api_cache(payload: Dict[str, Any]) -> None:
try:
ensure_cache_dir()
payload["timestamp"] = time.time()
- with open(API_CACHE_PATH, "w", encoding="utf-8") as f:
+ with API_CACHE_PATH.open("w", encoding="utf-8") as f:
json.dump(payload, f)
except Exception as e:
print(f"Error writing API cache: {e}", file=sys.stderr)
@@ -170,34 +247,42 @@ def write_api_cache(payload: Dict[str, Any]) -> None:
def write_simple_text_cache(text: str) -> None:
try:
ensure_cache_dir()
- with open(SIMPLE_TEXT_CACHE_PATH, "w", encoding="utf-8") as f:
+ with SIMPLE_TEXT_CACHE_PATH.open("w", encoding="utf-8") as f:
f.write(text)
except Exception as e:
print(f"Error writing simple cache: {e}", file=sys.stderr)
-def get_coords() -> Tuple[float, float]:
- # 1) Explicit env
+def get_coords_from_env() -> Optional[Tuple[float, float]]:
if ENV_LAT and ENV_LON:
try:
return float(ENV_LAT), float(ENV_LON)
except ValueError:
print("Invalid WEATHER_LAT/WEATHER_LON; falling back to IP geolocation", file=sys.stderr)
+ return None
+
- # 2) Try cached coordinates from last successful forecast
+def get_coords_from_cache() -> Optional[Tuple[float, float]]:
try:
cached = read_api_cache()
- if cached and isinstance(cached, dict):
- fc = cached.get("forecast") or {}
- lat = fc.get("latitude")
- lon = fc.get("longitude")
- if isinstance(lat, (int, float)) and isinstance(lon, (int, float)):
- return float(lat), float(lon)
+ if cached:
+ fc = ensure_dict(cached.get("forecast"))
+ lat_raw = safe_get(fc, "latitude")
+ lon_raw = safe_get(fc, "longitude")
+ lat = coerce_float(lat_raw)
+ lon = coerce_float(lon_raw)
+ if lat is None:
+ log_debug(f"Unexpected type for cached latitude: {type(lat_raw)}")
+ if lon is None:
+ log_debug(f"Unexpected type for cached longitude: {type(lon_raw)}")
+ if lat is not None and lon is not None:
+ return lat, lon
except Exception as e:
print(f"Reading cached coords failed: {e}", file=sys.stderr)
+ return None
- # 3) IP-based geolocation with multiple providers (prefer ipwho.is, ipapi.co; ipinfo.io as fallback)
- # ipwho.is
+
+def get_coords_from_ipwho() -> Optional[Tuple[float, float]]:
try:
resp = SESSION.get("https://ipwho.is/", timeout=TIMEOUT)
resp.raise_for_status()
@@ -209,8 +294,10 @@ def get_coords() -> Tuple[float, float]:
return float(lat), float(lon)
except Exception as e:
print(f"ipwho.is failed: {e}", file=sys.stderr)
+ return None
- # ipapi.co
+
+def get_coords_from_ipapi() -> Optional[Tuple[float, float]]:
try:
resp = SESSION.get("https://ipapi.co/json", timeout=TIMEOUT)
resp.raise_for_status()
@@ -221,8 +308,10 @@ def get_coords() -> Tuple[float, float]:
return float(lat), float(lon)
except Exception as e:
print(f"ipapi.co failed: {e}", file=sys.stderr)
+ return None
+
- # ipinfo.io (fallback)
+def get_coords_from_ipinfo() -> Optional[Tuple[float, float]]:
try:
resp = SESSION.get("https://ipinfo.io/json", timeout=TIMEOUT)
resp.raise_for_status()
@@ -233,8 +322,68 @@ def get_coords() -> Tuple[float, float]:
return float(lat_s), float(lon_s)
except Exception as e:
print(f"ipinfo.io failed: {e}", file=sys.stderr)
+ return None
+
- # 4) Last resort
+def get_coords_from_place_name(name: str) -> Optional[Tuple[float, float]]:
+ """Forward geocode a place name to coordinates using Open-Meteo Geocoding API.
+
+ Returns (lat, lon) if found, else None.
+ """
+ try:
+ base = "https://geocoding-api.open-meteo.com/v1/search"
+ params: Dict[str, Union[str, float]] = {
+ "name": name,
+ "count": 1,
+ "language": os.getenv("WEATHER_LANG", "en"),
+ "format": "json",
+ }
+ resp = SESSION.get(base, params=params, timeout=TIMEOUT)
+ resp.raise_for_status()
+ data = ensure_dict(resp.json())
+ results = ensure_list(data.get("results"))
+ if results:
+ p = ensure_dict(results[0])
+ lat = coerce_float(p.get("latitude"))
+ lon = coerce_float(p.get("longitude"))
+ if lat is not None and lon is not None:
+ return float(lat), float(lon)
+ except Exception as e:
+ print(f"Place geocoding failed: {e}", file=sys.stderr)
+ return None
+
+
+def get_coords() -> Tuple[float, float]:
+ # 1) Forward geocode from MANUAL_PLACE first (highest priority)
+ if MANUAL_PLACE:
+ place_name = MANUAL_PLACE.strip()
+ coords = get_coords_from_place_name(place_name)
+ if coords:
+ return coords
+
+ # 2) Explicit env coordinates
+ coords = get_coords_from_env()
+ if coords:
+ return coords
+
+ # 3) Forward geocode from ENV_PLACE
+ if ENV_PLACE:
+ place_name = ENV_PLACE.strip()
+ coords = get_coords_from_place_name(place_name)
+ if coords:
+ return coords
+
+ # 4) Try cached coordinates
+ coords = get_coords_from_cache()
+ if coords:
+ return coords
+
+ # 5) IP-based geolocation
+ coords = get_coords_from_ipwho() or get_coords_from_ipapi() or get_coords_from_ipinfo()
+ if coords:
+ return coords
+
+ # 6) Last resort
print("IP geolocation failed: no providers succeeded", file=sys.stderr)
return 0.0, 0.0
@@ -272,7 +421,7 @@ def format_visibility(meters: Optional[float]) -> str:
def fetch_open_meteo(lat: float, lon: float) -> Dict[str, Any]:
base = "https://api.open-meteo.com/v1/forecast"
- params = {
+ params: Dict[str, Union[str, float]] = {
"latitude": lat,
"longitude": lon,
"current": "temperature_2m,apparent_temperature,relative_humidity_2m,wind_speed_10m,wind_direction_10m,weather_code,visibility,precipitation,pressure_msl,is_day",
@@ -289,7 +438,7 @@ def fetch_open_meteo(lat: float, lon: float) -> Dict[str, Any]:
def fetch_aqi(lat: float, lon: float) -> Optional[Dict[str, Any]]:
try:
base = "https://air-quality-api.open-meteo.com/v1/air-quality"
- params = {
+ params: Dict[str, Union[str, float]] = {
"latitude": lat,
"longitude": lon,
"current": "european_aqi",
@@ -303,37 +452,54 @@ def fetch_aqi(lat: float, lon: float) -> Optional[Dict[str, Any]]:
return None
-def fetch_place(lat: float, lon: float) -> Optional[str]:
- """Reverse geocode lat/lon to an approximate place. Tries Nominatim first, then Open-Meteo."""
- lang = os.getenv("WEATHER_LANG", "en")
+def extract_place_parts_nominatim(data_dict: JSONDict) -> List[str]:
+ address = ensure_dict(data_dict.get("address"))
+ candidates = [data_dict.get("name"), address.get("city"), address.get("town"), address.get("village"), address.get("hamlet")]
+ name = cast(Optional[str], next((c for c in candidates if c is not None), None))
+ admin1 = cast(Optional[str], address.get("state"))
+ country = cast(Optional[str], address.get("country"))
+ parts: List[str] = []
+ if name is not None:
+ parts.append(name)
+ if admin1 is not None:
+ parts.append(admin1)
+ if country is not None:
+ parts.append(country)
+ return parts
- # 1) Nominatim (OpenStreetMap)
+
+def extract_place_parts_open_meteo(p: JSONDict) -> List[str]:
+ name = cast(Optional[str], p.get("name"))
+ admin1 = cast(Optional[str], p.get("admin1"))
+ country = cast(Optional[str], p.get("country"))
+ parts: List[str] = []
+ if name is not None:
+ parts.append(name)
+ if admin1 is not None:
+ parts.append(admin1)
+ if country is not None:
+ parts.append(country)
+ return parts
+
+
+def reverse_geocode(base: str, params: Dict[str, Union[str, float]], headers: Optional[Dict[str, str]] = None) -> Optional[str]:
try:
- base = "https://nominatim.openstreetmap.org/reverse"
- params = {
- "lat": lat,
- "lon": lon,
- "format": "jsonv2",
- "accept-language": lang,
- }
- headers = {"User-Agent": UA + " Weather.py/1.0"}
resp = SESSION.get(base, params=params, headers=headers, timeout=TIMEOUT)
resp.raise_for_status()
data = resp.json()
- address = data.get("address", {})
- name = data.get("name") or address.get("city") or address.get("town") or address.get("village") or address.get("hamlet")
- admin1 = address.get("state")
- country = address.get("country")
- parts = [part for part in [name, admin1, country] if part]
+ data_dict = ensure_dict(data)
+ parts = extract_place_parts_nominatim(data_dict)
if parts:
return ", ".join(parts)
except Exception as e:
- log_debug(f"Reverse geocoding (Nominatim) failed: {e}")
+ log_debug(f"Reverse geocoding failed: {e}")
+ return None
- # 2) Open-Meteo reverse (fallback)
+
+def reverse_geocode_open_meteo(lat: float, lon: float, lang: str) -> Optional[str]:
try:
base = "https://geocoding-api.open-meteo.com/v1/reverse"
- params = {
+ params: Dict[str, Union[str, float]] = {
"latitude": lat,
"longitude": lon,
"language": lang,
@@ -342,48 +508,117 @@ def fetch_place(lat: float, lon: float) -> Optional[str]:
resp = SESSION.get(base, params=params, timeout=TIMEOUT)
resp.raise_for_status()
data = resp.json()
- results = data.get("results") or []
+ data_dict = ensure_dict(data)
+ results = ensure_list(data_dict.get("results"))
if results:
- p = results[0]
- name = p.get("name")
- admin1 = p.get("admin1")
- country = p.get("country")
- parts = [part for part in [name, admin1, country] if part]
+ p = ensure_dict(results[0])
+ parts = extract_place_parts_open_meteo(p)
if parts:
return ", ".join(parts)
except Exception as e:
log_debug(f"Reverse geocoding (Open-Meteo) failed: {e}")
-
return None
+def fetch_place(lat: float, lon: float) -> Optional[str]:
+ """Reverse geocode lat/lon to an approximate place. Tries Nominatim first, then Open-Meteo."""
+ lang = os.getenv("WEATHER_LANG", "en")
+
+ # 1) Nominatim (OpenStreetMap)
+ base = "https://nominatim.openstreetmap.org/reverse"
+ params: Dict[str, Union[str, float]] = {
+ "lat": lat,
+ "lon": lon,
+ "format": "jsonv2",
+ "accept-language": lang,
+ }
+ headers = {"User-Agent": UA + " Weather.py/1.0"}
+ place = reverse_geocode(base, params, headers)
+ if place:
+ return place
+
+ # 2) Open-Meteo reverse (fallback)
+ return reverse_geocode_open_meteo(lat, lon, lang)
+
+
# =============== Build Output ===============
-def safe_get(dct: Dict[str, Any], *keys, default=None):
- cur: Any = dct
- for k in keys:
+_T = TypeVar("_T")
+
+JSONValue = Union[str, int, float, bool, None, "JSONDict", "JSONList"]
+JSONDict = Dict[str, JSONValue]
+JSONList = List[JSONValue]
+
+
+def ensure_dict(value: Any) -> JSONDict:
+ """Return a JSON-like dict when the incoming value looks like one."""
+ if isinstance(value, dict):
+ return cast(JSONDict, value)
+ # Warn about unexpected type to catch API shape mismatches
+ val_repr = repr(value) if value is not None else "None"
+ if len(val_repr) > 100:
+ val_repr = val_repr[:100] + "..."
+ print(f"Warning: ensure_dict received {type(value).__name__} instead of dict: {val_repr}", file=sys.stderr)
+ return cast(JSONDict, {})
+
+
+def ensure_list(value: Any) -> JSONList:
+ """Return a JSON-like list when the incoming value looks like one."""
+ if isinstance(value, list):
+ return cast(JSONList, value)
+ # Warn about unexpected type to catch API shape mismatches
+ val_repr = repr(value) if value is not None else "None"
+ if len(val_repr) > 100:
+ val_repr = val_repr[:100] + "..."
+ print(f"Warning: ensure_list received {type(value).__name__} instead of list: {val_repr}", file=sys.stderr)
+ return cast(JSONList, [])
+
+
+def safe_get(
+ obj: JSONValue | None,
+ *keys: Union[str, int],
+ default: _T | None = None,
+) -> _T | JSONValue | None:
+ """Safely traverse nested dict/list structures.
+
+ Keys may be strings (for mapping lookups) or ints (for list indices).
+ Returns ``default`` if any lookup fails.
+ """
+
+ cur: JSONValue | None = obj
+ for key in keys:
if isinstance(cur, dict):
- if k not in cur:
+ if not isinstance(key, str) or key not in cur:
return default
- cur = cur[k]
+ cur = cur[key]
elif isinstance(cur, list):
- try:
- cur = cur[k] # type: ignore[index]
- except Exception:
+ if not isinstance(key, int) or key < 0 or key >= len(cur):
return default
+ cur = cur[key]
else:
return default
- return cur
+ return cast(_T | JSONValue | None, cur)
+
+
+def get_precipitation_probabilities(forecast: JSONDict) -> List[Optional[float]]:
+ probs_raw = safe_get(forecast, "hourly", "precipitation_probability")
+ probs_raw_list = ensure_list(probs_raw)
+ return [coerce_float(p) if p is not None else None for p in probs_raw_list]
+
+
+def find_current_index(times: List[str], cur_time: Optional[str]) -> int:
+ if cur_time is not None and cur_time in times:
+ return times.index(cur_time)
+ return 0
-def build_hourly_precip(forecast: Dict[str, Any]) -> str:
+def build_hourly_precip(forecast: JSONDict) -> str:
try:
- times: List[str] = safe_get(forecast, "hourly", "time", default=[]) or []
- probs: List[Optional[float]] = safe_get(
- forecast, "hourly", "precipitation_probability", default=[]
- ) or []
- cur_time: Optional[str] = safe_get(forecast, "current", "time")
- idx = times.index(cur_time) if cur_time in times else 0
+ times_raw = safe_get(forecast, "hourly", "time")
+ times: List[str] = cast(List[str], ensure_list(times_raw))
+ probs = get_precipitation_probabilities(forecast)
+ cur_time: Optional[str] = cast(Optional[str], safe_get(forecast, "current", "time"))
+ idx = find_current_index(times, cur_time)
window = probs[idx : idx + 6]
if not window:
return ""
@@ -393,152 +628,308 @@ def build_hourly_precip(forecast: Dict[str, Any]) -> str:
return ""
-def build_output(lat: float, lon: float, forecast: Dict[str, Any], aqi: Optional[Dict[str, Any]], place: Optional[str] = None) -> Tuple[Dict[str, Any], str]:
- cur = forecast.get("current", {})
- cur_units = forecast.get("current_units", {})
- daily = forecast.get("daily", {})
- daily_units = forecast.get("daily_units", {})
+def build_weather_strings(cur: JSONDict, cur_units: JSONDict, daily: JSONDict, daily_units: JSONDict, temp_unit: str) -> Tuple[str, str, int, int, str, str, str]:
+ temp_val = coerce_float(cur.get("temperature_2m"))
+ temp_unit_str = cast(str, cur_units.get("temperature_2m", ""))
+ temp_str = f"{int(round(temp_val))}{temp_unit_str}" if temp_val is not None else "N/A"
- temp_val = cur.get("temperature_2m")
- temp_unit = cur_units.get("temperature_2m", "")
- temp_str = f"{int(round(temp_val))}{temp_unit}" if isinstance(temp_val, (int, float)) else "N/A"
+ feels_val = coerce_float(cur.get("apparent_temperature"))
+ feels_unit = cast(str, cur_units.get("apparent_temperature", ""))
+ feels_str = f"Feels like {int(round(feels_val))}{feels_unit}" if feels_val is not None else ""
- feels_val = cur.get("apparent_temperature")
- feels_unit = cur_units.get("apparent_temperature", "")
- feels_str = f"Feels like {int(round(feels_val))}{feels_unit}" if isinstance(feels_val, (int, float)) else ""
-
- is_day = int(cur.get("is_day", 1) or 1)
- code = int(cur.get("weather_code", -1) or -1)
+ is_day_val = cur.get("is_day")
+ is_day_int = coerce_int(is_day_val)
+ is_day = is_day_int if is_day_int is not None else 1
+ weather_code_val = cur.get("weather_code")
+ code_int = coerce_int(weather_code_val)
+ code = code_int if code_int is not None else -1
icon = wmo_to_icon(code, is_day)
status = wmo_to_status(code)
- # min/max today (index 0)
- tmin_val = safe_get(daily, "temperature_2m_min", 0)
- tmax_val = safe_get(daily, "temperature_2m_max", 0)
- dtemp_unit = daily_units.get("temperature_2m_min", temp_unit)
- tmin_str = f"{int(round(tmin_val))}{dtemp_unit}" if isinstance(tmin_val, (int, float)) else ""
- tmax_str = f"{int(round(tmax_val))}{dtemp_unit}" if isinstance(tmax_val, (int, float)) else ""
+ tmin_val = coerce_float(safe_get(daily, "temperature_2m_min", 0))
+ tmax_val = coerce_float(safe_get(daily, "temperature_2m_max", 0))
+ dtemp_unit = cast(str, daily_units.get("temperature_2m_min", temp_unit))
+ tmin_str = f"{int(round(tmin_val))}{dtemp_unit}" if tmin_val is not None else ""
+ tmax_str = f"{int(round(tmax_val))}{dtemp_unit}" if tmax_val is not None else ""
min_max = f" {tmin_str}\t\t {tmax_str}" if tmin_str and tmax_str else ""
- wind_val = cur.get("wind_speed_10m")
- wind_unit = cur_units.get("wind_speed_10m", "")
- wind_text = f" {int(round(wind_val))}{wind_unit}" if isinstance(wind_val, (int, float)) else ""
+ return temp_str, feels_str, is_day, code, icon, status, min_max
- hum_val = cur.get("relative_humidity_2m")
- humidity_text = f" {int(hum_val)}%" if isinstance(hum_val, (int, float)) else ""
- vis_val = cur.get("visibility")
- visibility_text = f" {format_visibility(vis_val)}" if isinstance(vis_val, (int, float)) else ""
+def build_weather_details(cur: JSONDict, cur_units: JSONDict) -> Tuple[str, str, str]:
+ wind_val_raw = cur.get("wind_speed_10m")
+ wind_val = coerce_float(wind_val_raw)
+ wind_unit = cast(str, cur_units.get("wind_speed_10m", ""))
+ if wind_val is None:
+ log_debug(f"Unexpected type for wind_speed_10m: {type(wind_val_raw)}")
+ wind_text = f" {int(round(wind_val))}{wind_unit}" if wind_val is not None else ""
- aqi_val = safe_get(aqi or {}, "current", "european_aqi")
- aqi_text = f"AQI {int(aqi_val)}" if isinstance(aqi_val, (int, float)) else "AQI N/A"
+ hum_val_raw = cur.get("relative_humidity_2m")
+ hum_val = coerce_float(hum_val_raw)
+ if hum_val is None:
+ log_debug(f"Unexpected type for relative_humidity_2m: {type(hum_val_raw)}")
+ humidity_text = f" {int(hum_val)}%" if hum_val is not None else ""
- hourly_precip = build_hourly_precip(forecast)
- prediction = f"\n\n{hourly_precip}" if hourly_precip else ""
+ vis_val_raw = cur.get("visibility")
+ vis_val = coerce_float(vis_val_raw)
+ if vis_val is None:
+ log_debug(f"Unexpected type for visibility: {type(vis_val_raw)}")
+ visibility_text = f" {format_visibility(vis_val)}" if vis_val is not None else ""
- # Build place string (priority: MANUAL_PLACE > ENV_PLACE > reverse geocode > lat,lon)
- place_str = (MANUAL_PLACE or ENV_PLACE or place or f"{lat:.3f}, {lon:.3f}")
- location_text = f"{LOC_ICON} {place_str}"
+ return wind_text, humidity_text, visibility_text
+
+
+def build_aqi_info(aqi: Optional[Dict[str, Any]]) -> str:
+ aqi_dict = ensure_dict(aqi)
+ aqi_val_raw = safe_get(aqi_dict, "current", "european_aqi")
+ aqi_val = coerce_float(aqi_val_raw)
+ if aqi_val is None:
+ log_debug(f"Unexpected type for european_aqi: {type(aqi_val_raw)}")
+ return f"AQI {int(aqi_val)}" if aqi_val is not None else "AQI N/A"
+
+
+def build_place_str(lat: float, lon: float, place: Optional[str]) -> str:
+ effective_place = MANUAL_PLACE or ENV_PLACE or place
+ if effective_place:
+ return f"{effective_place} ({lat:.3f}, {lon:.3f})"
+ return f"{lat:.3f}, {lon:.3f}"
+
+
+
+
+class TooltipParams(NamedTuple):
+ temp_str: str
+ icon: str
+ status: str
+ location_text: str
+ feels_str: str
+ min_max: str
+ wind_text: str
+ humidity_text: str
+ visibility_text: str
+ aqi_text: str
+ hourly_precip: str
- # Build tooltip (markup or plain)
+
+def build_tooltip_markup(params: TooltipParams) -> str:
+ return str.format(
+ "\t\t{}\t\t\n{}\n{}\n{}\n{}\n\n{}\n{}\n{}{}",
+ f'<span size="xx-large">{esc(params.temp_str)}</span>',
+ f"<big> {params.icon}</big>",
+ f"<b>{esc(params.status)}</b>",
+ esc(params.location_text),
+ f"<small>{esc(params.feels_str)}</small>" if params.feels_str else "",
+ f"<b>{esc(params.min_max)}</b>" if params.min_max else "",
+ f"{esc(params.wind_text)}\t{esc(params.humidity_text)}",
+ f"{esc(params.visibility_text)}\t{esc(params.aqi_text)}",
+ f"<i> {esc(params.hourly_precip)}</i>" if params.hourly_precip else "",
+ )
+
+
+def build_tooltip_plain(params: TooltipParams) -> str:
+ lines = [
+ f"{params.icon} {params.temp_str}",
+ params.status,
+ params.location_text,
+ ]
+ if params.feels_str:
+ lines.append(params.feels_str)
+ if params.min_max:
+ lines.append(params.min_max)
+ combined_wind = f"{params.wind_text} {params.humidity_text}".strip()
+ if combined_wind:
+ lines.append(combined_wind)
+ combined_visibility = f"{params.visibility_text} {params.aqi_text}".strip()
+ if combined_visibility:
+ lines.append(combined_visibility)
+ if params.hourly_precip:
+ lines.append(params.hourly_precip)
+ return "\n".join([ln for ln in lines if ln])
+
+
+def build_tooltip_text(params: TooltipParams) -> str:
if TOOLTIP_MARKUP:
- # Escape dynamic text to avoid breaking Pango markup
- tooltip_text = str.format(
- "\t\t{}\t\t\n{}\n{}\n{}\n{}\n\n{}\n{}\n{}{}",
- f'<span size="xx-large">{esc(temp_str)}</span>',
- f"<big> {icon}</big>",
- f"<b>{esc(status)}</b>",
- esc(location_text),
- f"<small>{esc(feels_str)}</small>" if feels_str else "",
- f"<b>{esc(min_max)}</b>" if min_max else "",
- f"{esc(wind_text)}\t{esc(humidity_text)}",
- f"{esc(visibility_text)}\t{esc(aqi_text)}",
- f"<i> {esc(prediction)}</i>" if prediction else "",
- )
+ return build_tooltip_markup(params)
else:
- lines = [
- f"{icon} {temp_str}",
- status,
- location_text,
- ]
- if feels_str:
- lines.append(feels_str)
- if min_max:
- lines.append(min_max)
- lines.append(f"{wind_text} {humidity_text}".strip())
- lines.append(f"{visibility_text} {aqi_text}".strip())
- if prediction:
- lines.append(hourly_precip)
- tooltip_text = "\n".join([ln for ln in lines if ln])
+ return build_tooltip_plain(params)
+
+
+def gather_weather_data(forecast: Optional[Dict[str, Any]], aqi: Optional[Dict[str, Any]]) -> WeatherData:
+ forecast_dict = ensure_dict(forecast)
+ cur = ensure_dict(forecast_dict.get("current"))
+ cur_units = ensure_dict(forecast_dict.get("current_units"))
+ daily = ensure_dict(forecast_dict.get("daily"))
+ daily_units = ensure_dict(forecast_dict.get("daily_units"))
+
+ temp_str, feels_str, is_day, code, icon, status, min_max = build_weather_strings(cur, cur_units, daily, daily_units, cast(str, cur_units.get("temperature_2m", "")))
+ wind_text, humidity_text, visibility_text = build_weather_details(cur, cur_units)
+ aqi_text = build_aqi_info(aqi)
+ hourly_precip = build_hourly_precip(forecast_dict)
+
+ return WeatherData(
+ temp_str=temp_str,
+ feels_str=feels_str,
+ icon=icon,
+ status=status,
+ min_max=min_max,
+ wind_text=wind_text,
+ humidity_text=humidity_text,
+ visibility_text=visibility_text,
+ aqi_text=aqi_text,
+ hourly_precip=hourly_precip,
+ is_day=is_day,
+ code=code,
+ )
+
+
+def build_output(loc: Location, forecast: Optional[Dict[str, Any]], aqi: Optional[Dict[str, Any]]) -> Tuple[Dict[str, str], str]:
+ data = gather_weather_data(forecast, aqi)
+
+ place_str = build_place_str(loc.lat, loc.lon, loc.place)
+ location_text = f"{LOC_ICON} {place_str}"
+
+ tooltip_text = build_tooltip_text(
+ TooltipParams(
+ data.temp_str, data.icon, data.status, location_text, data.feels_str, data.min_max,
+ data.wind_text, data.humidity_text, data.visibility_text, data.aqi_text, data.hourly_precip
+ )
+ )
- out_data = {
- "text": f"{icon} {temp_str}",
- "alt": status,
+ out_data: Dict[str, Any] = {
+ "text": f"{data.icon} {data.temp_str}",
+ "alt": data.status,
"tooltip": tooltip_text,
- "class": f"wmo-{code} {'day' if is_day else 'night'}",
+ "class": f"wmo-{data.code} {'day' if data.is_day else 'night'}",
}
simple_weather = (
- f"{icon} {status}\n"
- + f" {temp_str} ({feels_str})\n"
- + (f"{wind_text} \n" if wind_text else "")
- + (f"{humidity_text} \n" if humidity_text else "")
- + f"{visibility_text} {aqi_text}\n"
+ f"{place_str}\n"
+ f"{data.icon} {data.status}\n"
+ + f" {data.temp_str} ({data.feels_str})\n"
+ + (f" {data.wind_text} \n" if data.wind_text else "")
+ + (f" {data.humidity_text} \n" if data.humidity_text else "")
+ + f" {data.visibility_text} {data.aqi_text}\n"
)
return out_data, simple_weather
-def main() -> None:
- lat, lon = get_coords()
-
- # Try cache first
+def try_cached_weather(lat: float, lon: float) -> Optional[Tuple[Dict[str, str], str]]:
cached = read_api_cache()
- if cached and isinstance(cached, dict):
- forecast = cached.get("forecast")
- aqi = cached.get("aqi")
- cached_place = cached.get("place") if isinstance(cached.get("place"), str) else None
- place_effective = MANUAL_PLACE or ENV_PLACE or cached_place
+ if cached:
+ forecast = cast(Optional[Dict[str, Any]], cached.get("forecast"))
+ aqi = cast(Optional[Dict[str, Any]], cached.get("aqi"))
+ place_val = cached.get("place")
+ cached_place = place_val if isinstance(place_val, str) else None
+ # Ensure the cached forecast corresponds to the requested lat/lon
+ fc = ensure_dict(cached.get("forecast"))
+ c_lat = coerce_float(safe_get(fc, "latitude"))
+ c_lon = coerce_float(safe_get(fc, "longitude"))
+ if c_lat is not None and c_lon is not None:
+ if abs(c_lat - lat) > 0.1 or abs(c_lon - lon) > 0.1:
+ return None # force fresh fetch for new location
try:
- out, simple = build_output(lat, lon, forecast, aqi, place_effective)
- print(json.dumps(out, ensure_ascii=False))
- write_simple_text_cache(simple)
- return
+ return build_output(Location(lat, lon, cached_place), forecast, aqi)
except Exception as e:
print(f"Cached data build failed, refetching: {e}", file=sys.stderr)
+ return None
- # Fetch fresh
+
+def fetch_fresh_weather(lat: float, lon: float) -> Optional[Tuple[Dict[str, str], str]]:
try:
forecast = fetch_open_meteo(lat, lon)
aqi = fetch_aqi(lat, lon)
- # Use manual/env place if provided; otherwise reverse geocode
- place_effective = MANUAL_PLACE or ENV_PLACE or fetch_place(lat, lon)
- write_api_cache({"forecast": forecast, "aqi": aqi, "place": place_effective})
- out, simple = build_output(lat, lon, forecast, aqi, place_effective)
- print(json.dumps(out, ensure_ascii=False))
- write_simple_text_cache(simple)
+ # If MANUAL_PLACE is set, don't reverse geocode - use the manual place instead
+ place = MANUAL_PLACE if MANUAL_PLACE else fetch_place(lat, lon)
+ write_api_cache({"forecast": forecast, "aqi": aqi, "place": place})
+ return build_output(Location(lat, lon, place), forecast, aqi)
except Exception as e:
print(f"Open-Meteo fetch failed: {e}", file=sys.stderr)
- # Last resort: try stale cache without TTL
- try:
- if os.path.exists(API_CACHE_PATH):
- with open(API_CACHE_PATH, "r", encoding="utf-8") as f:
- stale = json.load(f)
- out, simple = build_output(lat, lon, stale.get("forecast", {}), stale.get("aqi"), stale.get("place") if isinstance(stale.get("place"), str) else None)
- print(json.dumps(out, ensure_ascii=False))
- write_simple_text_cache(simple)
- return
- except Exception as e2:
- print(f"Failed to use stale cache: {e2}", file=sys.stderr)
- # Fallback minimal output
- fallback = {
- "text": f"{WEATHER_ICONS['default']} N/A",
- "alt": "Unavailable",
- "tooltip": "Weather unavailable",
- "class": "unavailable",
- }
- print(json.dumps(fallback, ensure_ascii=False))
+ return None
+
+
+def try_stale_weather(lat: float, lon: float) -> Optional[Tuple[Dict[str, str], str]]:
+ try:
+ if API_CACHE_PATH.exists():
+ with API_CACHE_PATH.open("r", encoding="utf-8") as f:
+ stale = json.load(f)
+ stale_dict = ensure_dict(stale)
+ place_val = stale_dict.get("place")
+ place = place_val if isinstance(place_val, str) else None
+ forecast = cast(Optional[Dict[str, Any]], stale_dict.get("forecast"))
+ aqi = cast(Optional[Dict[str, Any]], stale_dict.get("aqi"))
+ return build_output(Location(lat, lon, place), forecast, aqi)
+ except Exception as e2:
+ print(f"Failed to use stale cache: {e2}", file=sys.stderr)
+ return None
+
+
+def main() -> None:
+ lat, lon = get_coords()
+
+ # Try cache first
+ result = try_cached_weather(lat, lon)
+ if result:
+ out, simple = result
+ print(json.dumps(out, ensure_ascii=False))
+ write_simple_text_cache(simple)
+ return
+
+ # Fetch fresh
+ result = fetch_fresh_weather(lat, lon)
+ if result:
+ out, simple = result
+ print(json.dumps(out, ensure_ascii=False))
+ write_simple_text_cache(simple)
+ return
+
+ # Last resort: try stale cache
+ result = try_stale_weather(lat, lon)
+ if result:
+ out, simple = result
+ print(json.dumps(out, ensure_ascii=False))
+ write_simple_text_cache(simple)
+ return
+
+ # Fallback minimal output
+ fallback = {
+ "text": f"{WEATHER_ICONS['default']} N/A",
+ "alt": "Unavailable",
+ "tooltip": "Weather unavailable",
+ "class": "unavailable",
+ }
+ print(json.dumps(fallback, ensure_ascii=False))
+
+
+def test_coerce_functions():
+ """Manual testing for coerce functions."""
+ # Test coerce_int
+ assert coerce_int(5) == 5
+ assert coerce_int(5.5) == 5
+ assert coerce_int("5") == 5
+ assert coerce_int("5.7") == 5
+ assert coerce_int("abc") is None
+ assert coerce_int(None) is None
+
+ # Test coerce_float
+ assert coerce_float(5.5) == 5.5
+ assert coerce_float(5) == 5.0
+ assert coerce_float("5.5") == 5.5
+ assert coerce_float("abc") is None
+ assert coerce_float(None) is None
+
+ # Test coerce_number
+ assert coerce_number(5) == 5
+ assert coerce_number(5.5) == 5.5
+ assert coerce_number("5") == 5
+ assert coerce_number("5.5") == 5.5
+ assert coerce_number("abc") is None
+
+ print("All coerce function tests passed.", file=sys.stderr)
if __name__ == "__main__":
- main()
+ if len(sys.argv) > 1 and sys.argv[1] == "--test":
+ test_coerce_functions()
+ else:
+ main()
diff --git a/config/hypr/UserScripts/Weather.sh b/config/hypr/UserScripts/Weather.sh
index 9bdaff4a..ac9abc13 100755
--- a/config/hypr/UserScripts/Weather.sh
+++ b/config/hypr/UserScripts/Weather.sh
@@ -1,18 +1,42 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# weather info from wttr. https://github.com/chubin/wttr.in
# Remember to add city
-city=
+city=""
+
+
+# if city is blank, use https://ipapi.co/json to get location from IP
+if [ -z "$city" ]; then
+ city=$(curl -fsS https://ipapi.co/json | grep city | cut -f4 -d'"')
+fi
+
+
+# URL-encode city for safe use in URLs
+encoded_city="$city"
+if command -v python3 >/dev/null 2>&1; then
+ encoded_city=$(python3 -c 'import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))' "$city")
+elif command -v jq >/dev/null 2>&1; then
+ encoded_city=$(printf '%s' "$city" | jq -sRr @uri)
+else
+ # Minimal fallback: encode a few common special characters
+ encoded_city=$(printf '%s' "$city" | sed -e 's/ /%20/g' -e 's/&/%26/g' -e 's/?/%3F/g' -e 's/#/%23/g')
+fi
+
+
cachedir="$HOME/.cache/rbn"
-cachefile=${0##*/}-$1
+# Include city and arg in cache key so changing city invalidates old cache
+cache_key="${city}_${1}"
+# Sanitize cache key to avoid problematic characters in filename
+safe_key=$(printf '%s' "$cache_key" | tr -c '[:alnum:]_-' '_')
+cachefile=${0##*/}-$safe_key
-if [ ! -d $cachedir ]; then
- mkdir -p $cachedir
+if [ ! -d "$cachedir" ]; then
+ mkdir -p "$cachedir"
fi
-if [ ! -f $cachedir/$cachefile ]; then
- touch $cachedir/$cachefile
+if [ ! -f "$cachedir/$cachefile" ]; then
+ touch "$cachedir/$cachefile"
fi
# Save current IFS
@@ -20,25 +44,88 @@ SAVEIFS=$IFS
# Change IFS to new line.
IFS=$'\n'
-cacheage=$(($(date +%s) - $(stat -c '%Y' "$cachedir/$cachefile")))
-if [ $cacheage -gt 1740 ] || [ ! -s $cachedir/$cachefile ]; then
- data=($(curl -s https://en.wttr.in/"$city"$1\?0qnT 2>&1))
- echo ${data[0]} | cut -f1 -d, > $cachedir/$cachefile
- echo ${data[1]} | sed -E 's/^.{15}//' >> $cachedir/$cachefile
- echo ${data[2]} | sed -E 's/^.{15}//' >> $cachedir/$cachefile
+file="$cachedir/$cachefile"
+# Portable file mtime retrieval (GNU/BSD):
+# - GNU: stat -c %Y <file>
+# - BSD/macOS: stat -f %m <file>
+mtime=$(stat -c %Y "$file" 2>/dev/null || stat -f %m "$file" 2>/dev/null || echo 0)
+now=$(date +%s)
+cacheage=$(( now - mtime ))
+if [ $cacheage -gt 1740 ] || [ ! -s "$cachedir/$cachefile" ]; then
+ # Prefer structured format for reliable parsing (3 lines: location, condition, temperature)
+ mapfile -t sdata < <(curl -fsS "https://wttr.in/${encoded_city}?format=%25l%0A%25C%0A%25t&lang=en" 2>/dev/null || true)
+ if [ ${#sdata[@]} -ge 3 ]; then
+ printf "%s\n" "${sdata[0]}" > "$cachedir/$cachefile"
+ printf "%s\n" "${sdata[1]}" >> "$cachedir/$cachefile"
+ printf "%s\n" "${sdata[2]}" >> "$cachedir/$cachefile"
+ else
+ # Try fetching each field separately if combined format is flaky
+ loc=$(curl -fsS "https://wttr.in/${encoded_city}?format=%25l&lang=en" 2>/dev/null || true)
+ cond_only=$(curl -fsS "https://wttr.in/${encoded_city}?format=%25C&lang=en" 2>/dev/null || true)
+ temp_only=$(curl -fsS "https://wttr.in/${encoded_city}?format=%25t" 2>/dev/null || true)
+ if [ -n "$loc" ] && [ -n "$cond_only" ] && [ -n "$temp_only" ]; then
+ printf "%s\n" "$loc" > "$cachedir/$cachefile"
+ printf "%s\n" "$cond_only" >> "$cachedir/$cachefile"
+ printf "%s\n" "$temp_only" >> "$cachedir/$cachefile"
+ else
+ # Fallback: try ASCII output and extract best-effort fields
+ url="https://en.wttr.in/${encoded_city}?1"
+ mapfile -t data < <(curl -fsS "$url" 2>/dev/null || true)
+ if [ ${#data[@]} -ge 3 ] && ! echo "${data[0]}" | grep -qi 'not found\|unknown location'; then
+ loc=$(echo "${data[0]}" | sed -E 's/^.*: *//')
+ # Attempt to pull condition and temperature hints from nearby lines
+ cond=$(echo "${data[2]}" | sed -E 's/^.{0,15}//; s/^\s+//')
+ temp=$(printf "%s\n" "${data[@]}" | grep -Eo '\+?-?[0-9]+(\([^)]+\))? ?°?[CF]' | head -n1)
+ # Only write if we have at least location and something else meaningful
+ if [ -n "$loc" ] && { [ -n "$cond" ] || [ -n "$temp" ]; }; then
+ printf "%s\n" "$loc" > "$cachedir/$cachefile"
+ printf "%s\n" "${cond:-Unknown}" >> "$cachedir/$cachefile"
+ printf "%s\n" "${temp:-N/A}" >> "$cachedir/$cachefile"
+ fi
+ fi
+ fi
+ fi
fi
-weather=($(cat $cachedir/$cachefile))
+# Read cache robustly (line-wise)
+mapfile -t weather < "$cachedir/$cachefile"
+
+# If cache is still empty or invalid, emit a single error JSON and exit to avoid double-prints
+if [ ${#weather[@]} -lt 3 ] || ! echo "${weather[2]}" | grep -qE '[-+0-9].*°'; then
+ # Last-chance: try live structured fetch and populate cache and runtime weather
+ mapfile -t sdata < <(curl -fsS "https://wttr.in/${encoded_city}?format=%25l%0A%25C%0A%25t&lang=en" 2>/dev/null || true)
+ if [ ${#sdata[@]} -ge 3 ]; then
+ weather=("${sdata[@]}")
+ printf "%s\n" "${sdata[0]}" > "$cachedir/$cachefile"
+ printf "%s\n" "${sdata[1]}" >> "$cachedir/$cachefile"
+ printf "%s\n" "${sdata[2]}" >> "$cachedir/$cachefile"
+ else
+ loc=$(curl -fsS "https://wttr.in/${encoded_city}?format=%25l&lang=en" 2>/dev/null || true)
+ cond_only=$(curl -fsS "https://wttr.in/${encoded_city}?format=%25C&lang=en" 2>/dev/null || true)
+ temp_only=$(curl -fsS "https://wttr.in/${encoded_city}?format=%25t" 2>/dev/null || true)
+ if [ -n "$loc" ] && [ -n "$cond_only" ] && [ -n "$temp_only" ]; then
+ weather=("$loc" "$cond_only" "$temp_only")
+ printf "%s\n" "$loc" > "$cachedir/$cachefile"
+ printf "%s\n" "$cond_only" >> "$cachedir/$cachefile"
+ printf "%s\n" "$temp_only" >> "$cachedir/$cachefile"
+ else
+ echo -e "{\"text\":\"\uf06a\", \"alt\":\"\", \"tooltip\":\": \"}"
+ exit 1
+ fi
+ fi
+fi
# Restore IFSClear
IFS=$SAVEIFS
-temperature=$(echo ${weather[2]} | sed -E 's/([[:digit:]]+)\.\./\1 to /g')
+temperature=$(echo "${weather[2]}" | sed -E 's/([[:digit:]]+)\.\./\1 to /g')
#echo ${weather[1]##*,}
# https://fontawesome.com/icons?s=solid&c=weather
-case $(echo ${weather[1]##*,} | tr '[:upper:]' '[:lower:]') in
+# Normalize condition string for matching
+cond_key=$(echo "${weather[1]##*,}" | tr '[:upper:]' '[:lower:]' | sed -E 's/^\s+//; s/\s+$//')
+case "$cond_key" in
"clear" | "sunny")
condition=""
;;
@@ -54,7 +141,7 @@ case $(echo ${weather[1]##*,} | tr '[:upper:]' '[:lower:]') in
"fog" | "freezing fog")
condition=""
;;
-"patchy rain possible" | "patchy light drizzle" | "light drizzle" | "patchy light rain" | "light rain" | "light rain shower" | "mist" | "rain")
+"patchy rain possible" | "patchy light drizzle" | "light drizzle" | "patchy light rain" | "light rain" | "light rain shower" | "mist" | "rain" | "patchy rain nearby")
condition="󰼳"
;;
"moderate rain at times" | "moderate rain" | "heavy rain at times" | "heavy rain" | "moderate or heavy rain shower" | "torrential rain shower" | "rain shower")
@@ -74,14 +161,49 @@ case $(echo ${weather[1]##*,} | tr '[:upper:]' '[:lower:]') in
;;
*)
condition=""
- echo -e "{\"text\":\""$condition"\", \"alt\":\""${weather[0]}"\", \"tooltip\":\""${weather[0]}: $temperature ${weather[1]}"\"}"
;;
esac
+# If still unknown, try substring heuristics to pick a reasonable icon
+if [ "$condition" = "" ]; then
+ if echo "$cond_key" | grep -q "rain\|drizzle\|shower"; then
+ condition="󰼳"
+ elif echo "$cond_key" | grep -q "heavy rain\|torrential"; then
+ condition=""
+ elif echo "$cond_key" | grep -q "snow"; then
+ condition="󰙿"
+ elif echo "$cond_key" | grep -q "sleet\|freezing\|ice"; then
+ condition="󰼴"
+ elif echo "$cond_key" | grep -q "thunder"; then
+ condition=""
+ elif echo "$cond_key" | grep -q "overcast"; then
+ condition=""
+ elif echo "$cond_key" | grep -q "cloud"; then
+ condition=""
+ elif echo "$cond_key" | grep -q "sunny\|clear"; then
+ condition=""
+ fi
+fi
+
#echo $temp $condition
-echo -e "{\"text\":\""$temperature $condition"\", \"alt\":\""${weather[0]}"\", \"tooltip\":\""${weather[0]}: $temperature ${weather[1]}"\"}"
+# Ensure temperature has a value; if empty, keep whatever is in weather[2] or N/A
+if [ -z "$temperature" ]; then
+ temperature="${weather[2]:-N/A}"
+fi
+
+cond_disp=$(echo "${weather[1]}" | sed -E 's/^\s+//; s/\s+$//')
+
+# Escape strings for safe JSON embedding (escape backslashes and double quotes)
+json_escape() {
+ printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e 's/\"/\\\"/g'
+}
+
+text_json=$(json_escape "$temperature $condition")
+alt_json=$(json_escape "${weather[0]}")
+tooltip_json=$(json_escape "${weather[0]}: $temperature $cond_disp")
-cached_weather=" $temperature \n$condition ${weather[1]}"
+printf '{"text":"%s", "alt":"%s", "tooltip":"%s"}\n' "$text_json" "$alt_json" "$tooltip_json"
-echo -e $cached_weather > "$HOME/.cache/.weather_cache" \ No newline at end of file
+# Write a two-line cache with an actual newline between lines
+printf ' %s \n%s %s\n' "$temperature" "$condition" "${weather[1]}" > "$HOME/.cache/.weather_cache" \ No newline at end of file
diff --git a/config/hypr/UserScripts/WeatherWrap.sh b/config/hypr/UserScripts/WeatherWrap.sh
new file mode 100755
index 00000000..10c125dc
--- /dev/null
+++ b/config/hypr/UserScripts/WeatherWrap.sh
@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
+# Weather entrypoint: prefer Python (Open‑Meteo), fallback to legacy Bash (wttr.in)
+
+SCRIPT_DIR="$(dirname "$0")"
+PY_SCRIPT="$SCRIPT_DIR/Weather.py"
+BASH_FALLBACK="$SCRIPT_DIR/Weather.sh"
+
+run_fallback() {
+ if [ -f "$BASH_FALLBACK" ]; then
+ # Invoke via bash to avoid requiring +x and ensure consistent shell
+ bash "$BASH_FALLBACK" "$@"
+ return $?
+ else
+ echo "Weather fallback not found: $BASH_FALLBACK" >&2
+ return 127
+ fi
+}
+
+if command -v python3 >/dev/null 2>&1; then
+ python3 "$PY_SCRIPT" "$@"
+ exit_code=$?
+ if [ "$exit_code" -eq 0 ]; then
+ exit 0
+ fi
+ echo "Weather.py failed with code $exit_code — falling back to Weather.sh" >&2
+ run_fallback "$@"
+ exit $?
+else
+ echo "python3 not found in PATH — falling back to Weather.sh" >&2
+ run_fallback "$@"
+ exit $?
+fi \ No newline at end of file
diff --git a/config/hypr/UserScripts/ZshChangeTheme.sh b/config/hypr/UserScripts/ZshChangeTheme.sh
index cffaf5cb..690f0f13 100755
--- a/config/hypr/UserScripts/ZshChangeTheme.sh
+++ b/config/hypr/UserScripts/ZshChangeTheme.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Script for Oh my ZSH theme ( CTRL SHIFT O)
diff --git a/config/hypr/configs/Keybinds.conf b/config/hypr/configs/Keybinds.conf
index c2ba9681..fbe3bfe5 100644
--- a/config/hypr/configs/Keybinds.conf
+++ b/config/hypr/configs/Keybinds.conf
@@ -8,142 +8,144 @@ $scriptsDir = $HOME/.config/hypr/scripts
$UserConfigs = $HOME/.config/hypr/UserConfigs
$UserScripts = $HOME/.config/hypr/UserScripts
-bind = CTRL ALT, Delete, exec, hyprctl dispatch exit 0 # exit Hyprland
-bind = $mainMod, Q, killactive, # close active (not kill)
-bind = $mainMod SHIFT, Q, exec, $scriptsDir/KillActiveProcess.sh # Kill active process
-bind = CTRL ALT, L, exec, $scriptsDir/LockScreen.sh # screen lock
-bind = CTRL ALT, P, exec, $scriptsDir/Wlogout.sh # power menu
-bind = $mainMod SHIFT, N, exec, swaync-client -t -sw # swayNC notification panel
-bind = $mainMod SHIFT, E, exec, $scriptsDir/Kool_Quick_Settings.sh # Settings Menu KooL Hyprland Settings
+bindd = CTRL ALT, Delete, exit Hyprland, exec, hyprctl dispatch exit 0
+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 = $mainMod SHIFT, E, Quick settings menu, exec, $scriptsDir/Kool_Quick_Settings.sh
# Master Layout
-bind = $mainMod CTRL, D, layoutmsg, removemaster
-bind = $mainMod, I, layoutmsg, addmaster
-bind = $mainMod, J, layoutmsg, cyclenext
-bind = $mainMod, K, layoutmsg, cycleprev
-bind = $mainMod CTRL, Return, layoutmsg, swapwithmaster
+bindd = $mainMod CTRL, D, remove master, layoutmsg, removemaster
+bindd = $mainMod, I, add master, layoutmsg, addmaster
+# NOTE: J/K bindings are set dynamically by scripts/KeybindsLayoutInit.sh and scripts/ChangeLayout.sh
+# (we intentionally do not bind them statically here to avoid conflicts across layouts)
+# bindd = $mainMod, J, cycle next, layoutmsg, cyclenext
+# bindd = $mainMod, K, cycle previous, layoutmsg, cycleprev
+bindd = $mainMod CTRL, Return, swap with master, layoutmsg, swapwithmaster
# Dwindle Layout
-bind = $mainMod SHIFT, I, togglesplit # only works on dwindle layout
-bind = $mainMod, P, pseudo, # dwindle
+bindd = $mainMod SHIFT, I, toggle split (dwindle), togglesplit
+bindd = $mainMod, P, toggle pseudo (dwindle), pseudo,
# Works on either layout (Master or Dwindle)
-bind = $mainMod, M, exec, hyprctl dispatch splitratio 0.3
+bindd = $mainMod, M, set split ratio 0.3, exec, hyprctl dispatch splitratio 0.3
# group
-bind = $mainMod, G, togglegroup # toggle group
-bind = $mainMod CTRL, tab, changegroupactive # change focus to another window
+bindd = $mainMod, G, toggle group, togglegroup
+bindd = $mainMod CTRL, tab, change active in group, changegroupactive
- # Cycle windows if floating bring to top
-bind = ALT, tab, cyclenext
-bind = ALT, tab, bringactivetotop
+# Cycle windows; if floating bring to top
+bindd = ALT, tab, cycle next window, cyclenext
+bindd = ALT, tab, bring active to top, bringactivetotop
# Special Keys / Hot Keys
-bindel = , xf86audioraisevolume, exec, $scriptsDir/Volume.sh --inc # volume up
-bindel = , xf86audiolowervolume, exec, $scriptsDir/Volume.sh --dec # volume down
-bindl = , xf86AudioMicMute, exec, $scriptsDir/Volume.sh --toggle-mic # mic mute
-bindl = , xf86audiomute, exec, $scriptsDir/Volume.sh --toggle # mute
-bindl = , xf86Sleep, exec, systemctl suspend # sleep button
-bindl = , xf86Rfkill, exec, $scriptsDir/AirplaneMode.sh # Airplane mode
+bindeld = , xf86audioraisevolume, volume up, exec, $scriptsDir/Volume.sh --inc
+bindeld = , xf86audiolowervolume, volume down, exec, $scriptsDir/Volume.sh --dec
+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
-bindl = , xf86AudioPlayPause, exec, $scriptsDir/MediaCtrl.sh --pause
-bindl = , xf86AudioPause, exec, $scriptsDir/MediaCtrl.sh --pause
-bindl = , xf86AudioPlay, exec, $scriptsDir/MediaCtrl.sh --pause
-bindl = , xf86AudioNext, exec, $scriptsDir/MediaCtrl.sh --nxt
-bindl = , xf86AudioPrev, exec, $scriptsDir/MediaCtrl.sh --prv
-bindl = , xf86audiostop, 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
-bind = $mainMod, Print, exec, $scriptsDir/ScreenShot.sh --now # screenshot
-bind = $mainMod SHIFT, Print, exec, $scriptsDir/ScreenShot.sh --area # screenshot (area)
-bind = $mainMod CTRL, Print, exec, $scriptsDir/ScreenShot.sh --in5 # screenshot (5 secs delay)
-bind = $mainMod CTRL SHIFT, Print, exec, $scriptsDir/ScreenShot.sh --in10 # screenshot (10 secs delay)
-bind = ALT, Print, exec, $scriptsDir/ScreenShot.sh --active # screenshot (active window only)
+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)
-bind = $mainMod SHIFT, S, exec, $scriptsDir/ScreenShot.sh --swappy #screenshot (swappy)
+bindd = $mainMod SHIFT, S, screenshot (swappy), exec, $scriptsDir/ScreenShot.sh --swappy
# Resize windows
-binde = $mainMod SHIFT, left, resizeactive,-50 0
-binde = $mainMod SHIFT, right, resizeactive,50 0
-binde = $mainMod SHIFT, up, resizeactive,0 -50
-binde = $mainMod SHIFT, down, 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
-bind = $mainMod CTRL, left, movewindow, l
-bind = $mainMod CTRL, right, movewindow, r
-bind = $mainMod CTRL, up, movewindow, u
-bind = $mainMod CTRL, 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
-bind = $mainMod ALT, left, swapwindow, l
-bind = $mainMod ALT, right, swapwindow, r
-bind = $mainMod ALT, up, swapwindow, u
-bind = $mainMod ALT, 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
# Move focus with mainMod + arrow keys
-bind = $mainMod, left, movefocus, l
-bind = $mainMod, right, movefocus, r
-bind = $mainMod, up, movefocus, u
-bind = $mainMod, 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
-bind = $mainMod, tab, workspace, m+1
-bind = $mainMod SHIFT, tab, workspace, m-1
+bindd = $mainMod, tab, next workspace, workspace, m+1
+bindd = $mainMod SHIFT, tab, previous workspace, workspace, m-1
# Special workspace
-bind = $mainMod SHIFT, U, movetoworkspace, special
-bind = $mainMod, U, 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]
-bind = $mainMod, code:10, workspace, 1 # NOTE: code:10 = key 1
-bind = $mainMod, code:11, workspace, 2 # NOTE: code:11 = key 2
-bind = $mainMod, code:12, workspace, 3 # NOTE: code:12 = key 3
-bind = $mainMod, code:13, workspace, 4 # NOTE: code:13 = key 4
-bind = $mainMod, code:14, workspace, 5 # NOTE: code:14 = key 5
-bind = $mainMod, code:15, workspace, 6 # NOTE: code:15 = key 6
-bind = $mainMod, code:16, workspace, 7 # NOTE: code:16 = key 7
-bind = $mainMod, code:17, workspace, 8 # NOTE: code:17 = key 8
-bind = $mainMod, code:18, workspace, 9 # NOTE: code:18 = key 9
-bind = $mainMod, code:19, 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]
-bind = $mainMod SHIFT, code:10, movetoworkspace, 1 # NOTE: code:10 = key 1
-bind = $mainMod SHIFT, code:11, movetoworkspace, 2 # NOTE: code:11 = key 2
-bind = $mainMod SHIFT, code:12, movetoworkspace, 3 # NOTE: code:12 = key 3
-bind = $mainMod SHIFT, code:13, movetoworkspace, 4 # NOTE: code:13 = key 4
-bind = $mainMod SHIFT, code:14, movetoworkspace, 5 # NOTE: code:14 = key 5
-bind = $mainMod SHIFT, code:15, movetoworkspace, 6 # NOTE: code:15 = key 6
-bind = $mainMod SHIFT, code:16, movetoworkspace, 7 # NOTE: code:16 = key 7
-bind = $mainMod SHIFT, code:17, movetoworkspace, 8 # NOTE: code:17 = key 8
-bind = $mainMod SHIFT, code:18, movetoworkspace, 9 # NOTE: code:18 = key 9
-bind = $mainMod SHIFT, code:19, movetoworkspace, 10 # NOTE: code:19 = key 0
-bind = $mainMod SHIFT, bracketleft, movetoworkspace, -1 # brackets [
-bind = $mainMod SHIFT, bracketright, 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]
-bind = $mainMod CTRL, code:10, movetoworkspacesilent, 1 # NOTE: code:10 = key 1
-bind = $mainMod CTRL, code:11, movetoworkspacesilent, 2 # NOTE: code:11 = key 2
-bind = $mainMod CTRL, code:12, movetoworkspacesilent, 3 # NOTE: code:12 = key 3
-bind = $mainMod CTRL, code:13, movetoworkspacesilent, 4 # NOTE: code:13 = key 4
-bind = $mainMod CTRL, code:14, movetoworkspacesilent, 5 # NOTE: code:14 = key 5
-bind = $mainMod CTRL, code:15, movetoworkspacesilent, 6 # NOTE: code:15 = key 6
-bind = $mainMod CTRL, code:16, movetoworkspacesilent, 7 # NOTE: code:16 = key 7
-bind = $mainMod CTRL, code:17, movetoworkspacesilent, 8 # NOTE: code:17 = key 8
-bind = $mainMod CTRL, code:18, movetoworkspacesilent, 9 # NOTE: code:18 = key 9
-bind = $mainMod CTRL, code:19, movetoworkspacesilent, 10 # NOTE: code:19 = key 0
-bind = $mainMod CTRL, bracketleft, movetoworkspacesilent, -1 # brackets [
-bind = $mainMod CTRL, bracketright, 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
-bind = $mainMod, mouse_down, workspace, e+1
-bind = $mainMod, mouse_up, workspace, e-1
-bind = $mainMod, period, workspace, e+1
-bind = $mainMod, comma, 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
-bindm = $mainMod, mouse:272, movewindow # NOTE: mouse:272 = left click
-bindm = $mainMod, mouse:273, resizewindow # NOTE: mouse:272 = right click \ No newline at end of file
+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/UserConfigs/Startup_Apps.conf b/config/hypr/configs/Startup_Apps.conf
index 7b668b77..c1670595 100644
--- a/config/hypr/UserConfigs/Startup_Apps.conf
+++ b/config/hypr/configs/Startup_Apps.conf
@@ -1,5 +1,5 @@
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ #
-# Commands and Apps to be executed at launch
+# Commands and Apps to be executed at launch (vendor defaults)
$scriptsDir = $HOME/.config/hypr/scripts
$UserScripts = $HOME/.config/hypr/UserScripts
@@ -19,6 +19,7 @@ exec-once = swww-daemon --format xrgb
# 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 = $scriptsDir/KeybindsLayoutInit.sh
# Initialize Drop Down terminal - See Bug#810 https://github.com/JaKooLit/Hyprland-Dots/issues/810#issuecomment-3351947644
exec-once = $HOME/.config/hypr/scripts/Dropterminal.sh kitty &
@@ -29,6 +30,7 @@ exec-once = $scriptsDir/Polkit.sh
# starup apps
exec-once = nm-applet --indicator
+exec-once = nm-tray # For ubuntu
exec-once = swaync
#exec-once = ags
#exec-once = blueman-applet
@@ -46,6 +48,8 @@ exec-once = $UserScripts/RainbowBorders.sh
# Starting hypridle to start hyprlock
exec-once = hypridle
+# Resume Hyprsunset if state is "on" from previous session
+exec-once = $scriptsDir/Hyprsunset.sh init
# Here are list of features available but disabled by default
# exec-once = swww-daemon --format xrgb && swww img $HOME/Pictures/wallpapers/mecha-nostalgia.png # persistent wallpaper
@@ -54,4 +58,4 @@ exec-once = hypridle
#exec-once = $scriptsDir/Polkit-NixOS.sh
# xdg-desktop-portal-hyprland (should be auto starting. However, you can force to start)
-#exec-once = $scriptsDir/PortalHyprland.sh
+#exec-once = $scriptsDir/PortalHyprland.sh \ No newline at end of file
diff --git a/config/hypr/configs/WindowRules-config-v3.conf b/config/hypr/configs/WindowRules-config-v3.conf
new file mode 100644
index 00000000..b54c6a85
--- /dev/null
+++ b/config/hypr/configs/WindowRules-config-v3.conf
@@ -0,0 +1,690 @@
+# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ #
+# 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
+
+# note for ja: This should NOT be implemented on Debian and Ubuntu
+
+# windowrule - tags - add apps under appropriate tag to use the same settings
+# browser tags
+
+# notif tags
+
+# KooL settings tag
+
+# terminal tags
+
+# email tags
+
+# project tags
+
+# screenshare tags
+
+# IM tags
+
+# game tags
+
+# gamestore tags
+
+# file-manager tags
+
+# wallpaper tags
+
+# multimedia tags
+
+# multimedia-video tags
+
+# settings tags
+
+# viewer tags
+
+# Some special override rules
+
+# POSITION
+# windowrule = center,floating:1 # warning, it cause even the menu to float and center.
+#windowrule = move 72% 7%,title:^(Firefox)$
+
+# windowrule to avoid idle for fullscreen apps
+#windowrule = idleinhibit fullscreen, class:^(*)$
+#windowrule = idleinhibit fullscreen, title:^(*)$
+
+# 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, class:^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$
+#windowrule = float, title:^(Firefox)$
+
+# windowrule - ######### float popups and dialogue #######
+
+
+
+
+# END of float popups and dialogue #######
+
+# OPACITY
+
+# SIZE
+
+#windowrule = size 25% 25%, title:^(Picture-in-Picture)$
+#windowrule = size 25% 25%, title:^(Firefox)$
+
+# PINNING
+#windowrule = pin,title:^(Firefox)$
+
+# windowrule - extras
+
+# BLUR & FULLSCREEN
+
+
+#This not gonna take the focus to the window that appears when hovering over some of the parts of the IntelliJ Products
+
+#This will gonna make the VS Code bluer like other apps
+
+#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 = 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
+# --- Auto-generated window rules ---
+windowrule {
+ name = windowrule-1
+ match:class = ^([Ff]irefox|org.mozilla.firefox|[Ff]irefox-esr|[Ff]irefox-bin)$
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-2
+ match:class = ^([Gg]oogle-chrome(-beta|-dev|-unstable)?)$
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-3
+ match:class = ^(chrome-.+-Default)$ # Chrome PWAs
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-4
+ match:class = ^([Cc]hromium)$
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-5
+ match:class = ^([Mm]icrosoft-edge(-stable|-beta|-dev|-unstable))$
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-6
+ match:class = ^(Brave-browser(-beta|-dev|-unstable)?)$
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-7
+ match:class = ^([Tt]horium-browser|[Cc]achy-browser)$
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-8
+ match:class = ^(zen-alpha|zen)$
+ tag = +browser
+}
+
+windowrule {
+ name = windowrule-9
+ match:class = ^(swaync-control-center|swaync-notification-window|swaync-client|class)$
+ tag = +notif
+}
+
+windowrule {
+ name = windowrule-10
+ match:title = ^(KooL Quick Cheat Sheet)$
+ tag = +KooL_Cheat
+}
+
+windowrule {
+ name = windowrule-11
+ match:title = ^(KooL Hyprland Settings)$
+ tag = +KooL_Settings
+}
+
+windowrule {
+ name = windowrule-12
+ match:class = ^(nwg-displays|nwg-look)$
+ tag = +KooL-Settings
+}
+
+windowrule {
+ name = windowrule-13
+ match:class = ^(Alacritty|kitty|kitty-dropterm)$
+ tag = +terminal
+}
+
+windowrule {
+ name = windowrule-14
+ match:class = ^([Tt]hunderbird|org.gnome.Evolution)$
+ tag = +email
+}
+
+windowrule {
+ name = windowrule-15
+ match:class = ^(eu.betterbird.Betterbird)$
+ tag = +email
+}
+
+windowrule {
+ name = windowrule-16
+ match:class = ^(codium|codium-url-handler|VSCodium)$
+ tag = +projects
+}
+
+windowrule {
+ name = windowrule-17
+ match:class = ^(VSCode|code-url-handler)$
+ tag = +projects
+}
+
+windowrule {
+ name = windowrule-18
+ match:class = ^(jetbrains-.+)$ # JetBrains IDEs
+ tag = +projects
+}
+
+windowrule {
+ name = windowrule-19
+ match:class = ^(com.obsproject.Studio)$
+ tag = +screenshare
+}
+
+windowrule {
+ name = windowrule-20
+ match:class = ^([Dd]iscord|[Ww]ebCord|[Vv]esktop)$
+ tag = +im
+}
+
+windowrule {
+ name = windowrule-21
+ match:class = ^([Ff]erdium)$
+ center = on
+ float = on
+ size = 60% = 70%
+ tag = +im
+}
+
+windowrule {
+ name = windowrule-22
+ match:class = ^([Ww]hatsapp-for-linux)$
+ tag = +im
+}
+
+windowrule {
+ name = windowrule-23
+ match:class = ^(ZapZap|com.rtosta.zapzap)$
+ tag = +im
+}
+
+windowrule {
+ name = windowrule-24
+ match:class = ^(org.telegram.desktop|io.github.tdesktop_x64.TDesktop)$
+ tag = +im
+}
+
+windowrule {
+ name = windowrule-25
+ match:class = ^(teams-for-linux)$
+ tag = +im
+}
+
+windowrule {
+ name = windowrule-26
+ match:class = ^(im.riot.Riot|Element)$ # Element Matrix client
+ tag = +im
+}
+
+windowrule {
+ name = windowrule-27
+ match:class = ^(gamescope)$
+ tag = +games
+}
+
+windowrule {
+ name = windowrule-28
+ match:class = ^(steam_app_\d+)$
+ tag = +games
+}
+
+windowrule {
+ name = windowrule-29
+ match:class = ^([Ss]team)$
+ tag = +gamestore
+}
+
+windowrule {
+ name = windowrule-30
+ match:title = ^([Ll]utris)$
+ tag = +gamestore
+}
+
+windowrule {
+ name = windowrule-31
+ match:class = ^(com.heroicgameslauncher.hgl)$
+ tag = +gamestore
+}
+
+windowrule {
+ name = windowrule-32
+ match:class = ^([Tt]hunar|org.gnome.Nautilus|[Pp]cmanfm-qt)$
+ tag = +file-manager
+}
+
+windowrule {
+ name = windowrule-33
+ match:class = ^(app.drey.Warp)$
+ tag = +file-manager
+}
+
+windowrule {
+ name = windowrule-34
+ match:class = ^([Ww]aytrogen)$
+ tag = +wallpaper
+}
+
+windowrule {
+ name = windowrule-35
+ match:class = ^([Aa]udacious)$
+ tag = +multimedia
+}
+
+windowrule {
+ name = windowrule-36
+ match:class = ^([Mm]pv|vlc)$
+ tag = +multimedia_video
+}
+
+windowrule {
+ name = windowrule-37
+ match:title = ^(ROG Control)$
+ center = on
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-38
+ match:class = ^(wihotspot(-gui)?)$ # wifi hotspot
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-39
+ match:class = ^([Bb]aobab|org.gnome.[Bb]aobab)$ # Disk usage analyzer
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-40
+ match:class = ^(gnome-disks|wihotspot(-gui)?)$
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-41
+ match:title = (Kvantum Manager)
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-42
+ match:class = ^(file-roller|org.gnome.FileRoller)$ # archive manager
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-43
+ match:class = ^(nm-applet|nm-connection-editor|blueman-manager)$
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-44
+ match:class = ^(pavucontrol|org.pulseaudio.pavucontrol|com.saivert.pwvucontrol)$
+ center = on
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-45
+ match:class = ^(qt5ct|qt6ct|[Yy]ad)$
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-46
+ match:class = (xdg-desktop-portal-gtk)
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-47
+ match:class = ^(org.kde.polkit-kde-authentication-agent-1)$
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-48
+ match:class = ^([Rr]ofi)$
+ tag = +settings
+}
+
+windowrule {
+ name = windowrule-49
+ match:class = ^(gnome-system-monitor|org.gnome.SystemMonitor|io.missioncenter.MissionCenter)$ # system monitor
+ tag = +viewer
+}
+
+windowrule {
+ name = windowrule-50
+ match:class = ^(evince)$ # document viewer
+ tag = +viewer
+}
+
+windowrule {
+ name = windowrule-51
+ match:class = ^(eog|org.gnome.Loupe)$ # image viewer
+ tag = +viewer
+}
+
+windowrule {
+ name = windowrule-52
+ match:tag = multimedia_video*
+ no_blur = on
+ opacity = 1.0
+}
+
+windowrule {
+ name = windowrule-53
+ match:tag = KooL_Cheat*
+ center = on
+ float = on
+ size = 65% = 90%
+}
+
+windowrule {
+ name = windowrule-54
+ match:class = ([Tt]hunar)
+ match:title = negative:(.*[Tt]hunar.*)
+ center = on
+ float = on
+}
+
+windowrule {
+ name = windowrule-55
+ match:tag = KooL-Settings*
+ center = on
+ float = on
+}
+
+windowrule {
+ name = windowrule-56
+ match:title = ^(Keybindings)$
+ center = on
+}
+
+windowrule {
+ name = windowrule-57
+ match:class = ^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$
+ center = on
+ size = 60% = 70%
+}
+
+windowrule {
+ name = windowrule-58
+ match:title = ^(Picture-in-Picture)$
+ float = on
+ move = 72% = 7%
+ opacity = 0.95 = 0.75
+ pin = 0
+}
+
+windowrule {
+ name = windowrule-59
+ match:fullscreen = 1
+ idle_inhibit = fullscreen
+}
+
+windowrule {
+ name = windowrule-60
+ match:tag = wallpaper*
+ float = on
+ opacity = 0.9 = 0.7
+ size = 70% = 70%
+}
+
+windowrule {
+ name = windowrule-61
+ match:tag = settings*
+ float = on
+ opacity = 0.8 = 0.7
+ size = 70% = 70%
+}
+
+windowrule {
+ name = windowrule-62
+ match:tag = viewer*
+ float = on
+ opacity = 0.82 = 0.75
+}
+
+windowrule {
+ name = windowrule-63
+ match:class = ([Zz]oom|onedriver|onedriver-launcher)$
+ float = on
+}
+
+windowrule {
+ name = windowrule-64
+ match:class = (org.gnome.Calculator)
+ match:title = (Calculator)
+ float = on
+}
+
+windowrule {
+ name = windowrule-65
+ match:class = ^(mpv|com.github.rafostar.Clapper)$
+ float = on
+}
+
+windowrule {
+ name = windowrule-66
+ match:class = ^([Qq]alculate-gtk)$
+ float = on
+}
+
+windowrule {
+ name = windowrule-67
+ match:title = ^(Authentication Required)$
+ center = on
+ float = on
+}
+
+windowrule {
+ name = windowrule-68
+ match:class = (codium|codium-url-handler|VSCodium)
+ match:title = negative:(.*codium.*|.*VSCodium.*)
+ float = on
+}
+
+windowrule {
+ name = windowrule-69
+ match:class = ^(com.heroicgameslauncher.hgl)$
+ match:title = negative:(Heroic Games Launcher)
+ float = on
+}
+
+windowrule {
+ name = windowrule-70
+ match:class = ^([Ss]team)$
+ match:title = negative:^([Ss]team)$
+ float = on
+}
+
+windowrule {
+ name = windowrule-71
+ match:title = ^(Add Folder to Workspace)$
+ center = on
+ float = on
+ size = 70% = 60%
+}
+
+windowrule {
+ name = windowrule-72
+ match:title = ^(Save As)$
+ center = on
+ float = on
+ size = 70% = 60%
+}
+
+windowrule {
+ name = windowrule-73
+ match:initial_title = (Open Files)
+ float = on
+ size = 70% = 60%
+}
+
+windowrule {
+ name = windowrule-74
+ match:title = ^(SDDM Background)$ #KooL's Dots YAD for setting SDDM background
+ center = on
+ float = on
+ size = 16% = 12%
+}
+
+windowrule {
+ name = windowrule-75
+ match:tag = browser*
+ opacity = 0.99 = 0.8
+}
+
+windowrule {
+ name = windowrule-76
+ match:tag = projects*
+ opacity = 0.9 = 0.8
+}
+
+windowrule {
+ name = windowrule-77
+ match:tag = im*
+ opacity = 0.94 = 0.86
+}
+
+windowrule {
+ name = windowrule-78
+ match:tag = multimedia*
+ opacity = 0.94 = 0.86
+}
+
+windowrule {
+ name = windowrule-79
+ match:tag = file-manager*
+ opacity = 0.9 = 0.8
+}
+
+windowrule {
+ name = windowrule-80
+ match:tag = terminal*
+ opacity = 0.9 = 0.7
+}
+
+windowrule {
+ name = windowrule-81
+ match:class = ^(gedit|org.gnome.TextEditor|mousepad)$
+ opacity = 0.8 = 0.7
+}
+
+windowrule {
+ name = windowrule-82
+ match:class = ^(deluge)$
+ opacity = 0.9 = 0.8
+}
+
+windowrule {
+ name = windowrule-83
+ match:class = ^(seahorse)$ # gnome-keyring gui
+ opacity = 0.9 = 0.8
+}
+
+windowrule {
+ name = windowrule-84
+ match:class = ^(code)$
+ opacity = 0.8
+ opacity = 0.9
+}
+
+windowrule {
+ name = windowrule-85
+ match:tag = games*
+ fullscreen = 0
+ no_blur = on
+}
+
+windowrule {
+ name = windowrule-86
+ match:class = ^(jetbrains-*)
+ no_initial_focus = on
+}
+
+windowrule {
+ name = windowrule-87
+ match:title = ^(wind.*)$
+ no_initial_focus = on
+}
+
+# --- Auto-generated layer rules ---
+layerrule {
+ name = layerrule-1
+ match:namespace = rofi
+ blur = on
+ ignore_alpha = 0
+}
+
+layerrule {
+ name = layerrule-2
+ match:namespace = notifications
+ blur = on
+ ignore_alpha = 0
+}
+
+layerrule {
+ name = layerrule-3
+ match:namespace = quickshell:overview
+ blur = on
+ ignore_alpha = 0
+ ignore_alpha = 0.5
+}
diff --git a/config/hypr/configs/WindowRules.conf b/config/hypr/configs/WindowRules.conf
new file mode 100644
index 00000000..f02c5d29
--- /dev/null
+++ b/config/hypr/configs/WindowRules.conf
@@ -0,0 +1,235 @@
+# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ #
+# 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
+
+# note for ja: This should NOT be implemented on Debian and Ubuntu
+
+# 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-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)$
+windowrule = opacity 0.9,class:^(code)$
+
+# 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.*)$
+
+#This will gonna make the VS Code bluer like other apps
+windowrule = opacity 0.8,class:^(code)$
+
+#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 \ No newline at end of file
diff --git a/config/hypr/hyprland.conf b/config/hypr/hyprland.conf
index 71f243e7..f509a76d 100644
--- a/config/hypr/hyprland.conf
+++ b/config/hypr/hyprland.conf
@@ -9,35 +9,30 @@ exec-once = $HOME/.config/hypr/initial-boot.sh
# Sourcing external config files
$configs = $HOME/.config/hypr/configs # Default Configs directory path
-
-source=$configs/Keybinds.conf # Pre-configured keybinds
-
# ## This is where you want to start tinkering
$UserConfigs = $HOME/.config/hypr/UserConfigs # User Configs directory path
-source= $UserConfigs/Startup_Apps.conf # put your start-up packages on this file
+source=$configs/Keybinds.conf # Pre-configured keybinds
-source= $UserConfigs/ENVariables.conf # Environment variables to load
+# Load vendor defaults, then user additions/overrides
+source= $configs/Startup_Apps.conf
+source= $UserConfigs/Startup_Apps.conf
-#source= $UserConfigs/Monitors.conf # Its all about your monitor config (old dots) will remove on push to main
-#source= $UserConfigs/WorkspaceRules.conf # Hyprland workspaces (old dots) will remove on push to main
+source= $UserConfigs/ENVariables.conf # Environment variables to load
source= $UserConfigs/Laptops.conf # For laptop related
-
source= $UserConfigs/LaptopDisplay.conf # Laptop display related. You need to read the comment on this file
-source= $UserConfigs/WindowRules.conf # all about Hyprland Window Rules and Layer Rules
+# Load vendor defaults, then user additions
+source= $configs/WindowRules.conf # all about Hyprland Window Rules and Layer Rules (defaults)
+source= $UserConfigs/WindowRules.conf # Window Rules and Layer Rules user configs
source= $UserConfigs/UserDecorations.conf # Decorations config file
-
source= $UserConfigs/UserAnimations.conf # Animation config file
-
source= $UserConfigs/UserKeybinds.conf # Put your own keybinds here
-
source= $UserConfigs/UserSettings.conf # Main Hyprland Settings.
-
source= $UserConfigs/01-UserDefaults.conf # settings for User defaults apps
# nwg-displays
source= $HOME/.config/hypr/monitors.conf
-source= $HOME/.config/hypr/workspaces.conf \ No newline at end of file
+source= $HOME/.config/hypr/workspaces.conf
diff --git a/config/hypr/hyprlock-1080p.conf b/config/hypr/hyprlock-1080p.conf
index 14f2f35e..4251ac68 100644
--- a/config/hypr/hyprlock-1080p.conf
+++ b/config/hypr/hyprlock-1080p.conf
@@ -37,9 +37,9 @@ label {
monitor =
text = cmd[update:18000000] echo "<b> "$(date +'%A, %-d %B')" </b>"
color = $color13
- font_size = 16
+ font_size = 48
font_family = Victor Mono Bold Italic
- position = 0, -120
+ position = 0, -60
halign = center
valign = center
}
@@ -47,42 +47,42 @@ label {
# Hour-Time
label {
monitor =
- text = cmd[update:1000] echo "$(date +"%H")"
-# text = cmd[update:1000] echo "$(date +"%I")" #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 = $color13
- font_size = 200
+ color = $color8
+ font_size = 130
font_family = JetBrainsMono Nerd Font ExtraBold
- position = 0, -60
+ 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 = 200
- font_family = JetBrainsMono Nerd Font ExtraBold
- position = 0, -340
- halign = center
- valign = top
-}
+# 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")"
+#label {
+# monitor =
+## text = cmd[update:1000] echo "$(date +"%S")"
# text = cmd[update:1000] echo "$(date +"%S %p")" #AM/PM
- color = $color11
- font_size = 35
- font_family = JetBrainsMono Nerd Font ExtraBold
- position = 0, -350
- halign = center
- valign = top
-}
+# 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 {
@@ -103,10 +103,10 @@ label {
label {
monitor =
text =  $USER
- color = $color13
- font_size = 24
+ color = $color9
+ font_size = 36
font_family = Victor Mono Bold Oblique
- position = 0, 220
+ position = 0, 275
halign = center
valign = bottom
}
@@ -114,12 +114,12 @@ label {
# INPUT FIELD
input-field {
monitor =
- size = 200, 60
+ 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 = $color11
+ outer_color = $color8
inner_color = rgba(255, 255, 255, 0.1)
capslock_color = rgb(255,255,255)
font_color = $color13
@@ -136,8 +136,8 @@ input-field {
label {
monitor =
text = $LAYOUT
- color = $color13
- font_size = 10
+ color = $color8
+ font_size = 14
font_family = Victor Mono Bold Oblique
position = 0, 70
halign = center
@@ -148,8 +148,8 @@ label {
label {
monitor =
text = cmd[update:60000] echo "<b> "$(uptime -p || $Scripts/UptimeNixOS.sh)" </b>"
- color = $color13
- font_size = 16
+ color = $color8
+ font_size = 24
font_family = Victor Mono Bold Oblique
position = 0, 0
halign = right
@@ -160,7 +160,7 @@ label {
label {
monitor =
text = cmd[update:1000] echo "<b> "$($Scripts/Battery.sh)" </b>"
- color = $color13
+ color = $color8
font_size = 16
font_family = Victor Mono Bold Oblique
position = 0, 30
@@ -174,8 +174,8 @@ label {
label {
monitor =
text = cmd[update:3600000] [ -f "$HOME/.cache/.weather_cache" ] && cat "$HOME/.cache/.weather_cache"
- color = $color13
- font_size = 16
+ color = $color8
+ 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
index b67bba51..f359357f 100644
--- a/config/hypr/hyprlock.conf
+++ b/config/hypr/hyprlock.conf
@@ -37,52 +37,52 @@ label {
monitor =
text = cmd[update:18000000] echo "<b> "$(date +'%A, %-d %B')" </b>"
color = $color13
- font_size = 18
+ font_size = 64
font_family = Victor Mono Bold Italic
- position = 0, -120
+ position = 0, -20
halign = center
valign = center
}
-# Hour-Time
+# Hour-Time (single horizontal time like 1080p variant)
label {
monitor =
- text = cmd[update:1000] echo "$(date +"%H")"
-# text = cmd[update:1000] echo "$(date +"%I")" #AM/PM
+# 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 = $color13
- font_size = 240
+ color = $color8
+ font_size = 173
font_family = JetBrainsMono Nerd Font ExtraBold
- position = 0, -100
+ position = 0, -133
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 = 240
- font_family = JetBrainsMono Nerd Font ExtraBold
- position = 0, -450
- 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
-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
-}
+# 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 {
@@ -103,10 +103,10 @@ label {
label {
monitor =
text =  $USER
- color = $color13
- font_size = 24
+ color = $color9
+ font_size = 48
font_family = Victor Mono Bold Oblique
- position = 0, 280
+ position = 0, 300
halign = center
valign = bottom
}
@@ -114,33 +114,32 @@ label {
# INPUT FIELD
input-field {
monitor =
- size = 300, 60
+ 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 = $color11
+ outer_color = $color8
inner_color = rgba(255, 255, 255, 0.1)
+ capslock_color = rgb(255,255,255)
font_color = $color13
- capslock_color = rgb(255,255,255)
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, 120
+ position = 0, 100
halign = center
valign = bottom
}
-
# Keyboard LAYOUT
label {
monitor =
text = $LAYOUT
- color = $color13
- font_size = 12
+ color = $color8
+ font_size = 19
font_family = Victor Mono Bold Oblique
- position = 0, 80
+ position = 0, 53
halign = center
valign = bottom
}
@@ -149,8 +148,8 @@ label {
label {
monitor =
text = cmd[update:60000] echo "<b> "$(uptime -p || $Scripts/UptimeNixOS.sh)" </b>"
- color = $color13
- font_size = 18
+ color = $color8
+ font_size = 32
font_family = Victor Mono Bold Oblique
position = 0, 0
halign = right
@@ -161,10 +160,10 @@ label {
label {
monitor =
text = cmd[update:1000] echo "<b> "$($Scripts/Battery.sh)" </b>"
- color = $color13
- font_size = 18
+ color = $color8
+ font_size = 21
font_family = Victor Mono Bold Oblique
- position = 0, 30
+ position = 0, 40
halign = right
valign = bottom
}
@@ -175,8 +174,8 @@ label {
label {
monitor =
text = cmd[update:3600000] [ -f "$HOME/.cache/.weather_cache" ] && cat "$HOME/.cache/.weather_cache"
- color = $color13
- font_size = 18
+ color = $color8
+ font_size = 19
font_family = Victor Mono Bold Oblique
position = 50, 0
halign = left
diff --git a/config/hypr/initial-boot.sh b/config/hypr/initial-boot.sh
index 5b49cb6d..1313f104 100755
--- a/config/hypr/initial-boot.sh
+++ b/config/hypr/initial-boot.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ #
# A bash script designed to run only once dotfiles installed
diff --git a/config/hypr/scripts/AirplaneMode.sh b/config/hypr/scripts/AirplaneMode.sh
index 4379935d..548b9d6b 100755
--- a/config/hypr/scripts/AirplaneMode.sh
+++ b/config/hypr/scripts/AirplaneMode.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Airplane Mode. Turning on or off all wifi using rfkill.
diff --git a/config/hypr/scripts/Animations.sh b/config/hypr/scripts/Animations.sh
index 477e5cd3..4bbe050f 100755
--- a/config/hypr/scripts/Animations.sh
+++ b/config/hypr/scripts/Animations.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# For applying Animations from different users
diff --git a/config/hypr/scripts/Battery.sh b/config/hypr/scripts/Battery.sh
index d7830058..2baed6ca 100644..100755
--- a/config/hypr/scripts/Battery.sh
+++ b/config/hypr/scripts/Battery.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
for i in {0..3}; do
if [ -f /sys/class/power_supply/BAT$i/capacity ]; then
diff --git a/config/hypr/scripts/Brightness.sh b/config/hypr/scripts/Brightness.sh
index 63fd02f3..ce443ef2 100755
--- a/config/hypr/scripts/Brightness.sh
+++ b/config/hypr/scripts/Brightness.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Script for Monitor backlights (if supported) using brightnessctl
diff --git a/config/hypr/scripts/BrightnessKbd.sh b/config/hypr/scripts/BrightnessKbd.sh
index 24737b73..93e09d86 100755
--- a/config/hypr/scripts/BrightnessKbd.sh
+++ b/config/hypr/scripts/BrightnessKbd.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Script for keyboard backlights (if supported) using brightnessctl
diff --git a/config/hypr/scripts/ChangeBlur.sh b/config/hypr/scripts/ChangeBlur.sh
index 895987a4..0060285b 100755
--- a/config/hypr/scripts/ChangeBlur.sh
+++ b/config/hypr/scripts/ChangeBlur.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Script for changing blurs on the fly
diff --git a/config/hypr/scripts/ChangeLayout.sh b/config/hypr/scripts/ChangeLayout.sh
index b083fcdc..e2436b79 100755
--- a/config/hypr/scripts/ChangeLayout.sh
+++ b/config/hypr/scripts/ChangeLayout.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# for changing Hyprland Layouts (Master or Dwindle) on the fly
@@ -9,20 +9,14 @@ LAYOUT=$(hyprctl -j getoption general:layout | jq '.str' | sed 's/"//g')
case $LAYOUT in
"master")
hyprctl keyword general:layout dwindle
- hyprctl keyword unbind SUPER,J
- hyprctl keyword unbind SUPER,K
- hyprctl keyword bind SUPER,J,cyclenext
- hyprctl keyword bind SUPER,K,cyclenext,prev
+ # SUPER+J/K are global and managed by KeybindsLayoutInit.sh; only manage SUPER+O here
hyprctl keyword bind SUPER,O,togglesplit
notify-send -e -u low -i "$notif" " Dwindle Layout"
;;
"dwindle")
hyprctl keyword general:layout master
- hyprctl keyword unbind SUPER,J
- hyprctl keyword unbind SUPER,K
+ # Drop togglesplit binding on SUPER+O when switching back to master
hyprctl keyword unbind SUPER,O
- hyprctl keyword bind SUPER,J,layoutmsg,cyclenext
- hyprctl keyword bind SUPER,K,layoutmsg,cycleprev
notify-send -e -u low -i "$notif" " Master Layout"
;;
*) ;;
diff --git a/config/hypr/scripts/ClipManager.sh b/config/hypr/scripts/ClipManager.sh
index 9937b6f4..3ba5d91a 100755
--- a/config/hypr/scripts/ClipManager.sh
+++ b/config/hypr/scripts/ClipManager.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Clipboard Manager. This script uses cliphist, rofi, and wl-copy.
diff --git a/config/hypr/scripts/DarkLight.sh b/config/hypr/scripts/DarkLight.sh
index 1bc1602f..e473efb2 100755
--- a/config/hypr/scripts/DarkLight.sh
+++ b/config/hypr/scripts/DarkLight.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
## /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# For Dark and Light switching
# Note: Scripts are looking for keywords Light or Dark except for wallpapers as the are in a separate directories
diff --git a/config/hypr/scripts/Distro_update.sh b/config/hypr/scripts/Distro_update.sh
index b0b1446b..2b3376e3 100755
--- a/config/hypr/scripts/Distro_update.sh
+++ b/config/hypr/scripts/Distro_update.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Simple bash script to check and will try to update your system
diff --git a/config/hypr/scripts/Dropterminal.sh b/config/hypr/scripts/Dropterminal.sh
index 4833545c..9b2eeecb 100755
--- a/config/hypr/scripts/Dropterminal.sh
+++ b/config/hypr/scripts/Dropterminal.sh
@@ -1,9 +1,9 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
#
# Made and brought to by Kiran George
# /* -- ✨ https://github.com/SherLock707 ✨ -- */ ##
-# Dropdown Terminal
+# Dropdown Terminal
# Usage: ./Dropdown.sh [-d] <terminal_command>
# Example: ./Dropdown.sh foot
# ./Dropdown.sh -d foot (with debug output)
@@ -15,186 +15,186 @@ SPECIAL_WS="special:scratchpad"
ADDR_FILE="/tmp/dropdown_terminal_addr"
# Dropdown size and position configuration (percentages)
-WIDTH_PERCENT=50 # Width as percentage of screen width
-HEIGHT_PERCENT=50 # Height as percentage of screen height
-Y_PERCENT=5 # Y position as percentage from top (X is auto-centered)
+WIDTH_PERCENT=65 # Width as percentage of screen width
+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
+ANIMATION_DURATION=100 # milliseconds
SLIDE_STEPS=5
-SLIDE_DELAY=5 # milliseconds between steps
+SLIDE_DELAY=5 # milliseconds between steps
# Parse arguments
if [ "$1" = "-d" ]; then
- DEBUG=true
- shift
+ DEBUG=true
+ shift
fi
TERMINAL_CMD="$1"
# Debug echo function
debug_echo() {
- if [ "$DEBUG" = true ]; then
- echo "$@"
- fi
+ if [ "$DEBUG" = true ]; then
+ echo "$@"
+ fi
}
# Validate input
if [ -z "$TERMINAL_CMD" ]; then
- echo "Missing terminal command. Usage: $0 [-d] <terminal_command>"
- echo "Examples:"
- echo " $0 foot"
- echo " $0 -d foot (with debug output)"
- echo " $0 'kitty -e zsh'"
- echo " $0 'alacritty --working-directory /home/user'"
- echo ""
- echo "Edit the script to modify size and position:"
- echo " WIDTH_PERCENT - Width as percentage of screen (default: 50)"
- echo " HEIGHT_PERCENT - Height as percentage of screen (default: 50)"
- echo " Y_PERCENT - Y position from top as percentage (default: 5)"
- echo " Note: X position is automatically centered"
- exit 1
+ echo "Missing terminal command. Usage: $0 [-d] <terminal_command>"
+ echo "Examples:"
+ echo " $0 foot"
+ echo " $0 -d foot (with debug output)"
+ echo " $0 'kitty -e zsh'"
+ echo " $0 'alacritty --working-directory /home/user'"
+ echo ""
+ echo "Edit the script to modify size and position:"
+ echo " WIDTH_PERCENT - Width as percentage of screen (default: 50)"
+ echo " HEIGHT_PERCENT - Height as percentage of screen (default: 50)"
+ echo " Y_PERCENT - Y position from top as percentage (default: 5)"
+ echo " Note: X position is automatically centered"
+ exit 1
fi
# Function to get window geometry
get_window_geometry() {
- local addr="$1"
- hyprctl clients -j | jq -r --arg ADDR "$addr" '.[] | select(.address == $ADDR) | "\(.at[0]) \(.at[1]) \(.size[0]) \(.size[1])"'
+ local addr="$1"
+ hyprctl clients -j | jq -r --arg ADDR "$addr" '.[] | select(.address == $ADDR) | "\(.at[0]) \(.at[1]) \(.size[0]) \(.size[1])"'
}
# Function to animate window slide down (show)
animate_slide_down() {
- local addr="$1"
- local target_x="$2"
- local target_y="$3"
- local width="$4"
- local height="$5"
-
- 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))
-
- # 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
-
- # 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
- done
-
- # Ensure final position is exact
- hyprctl dispatch movewindowpixel "exact $target_x $target_y,address:$addr" >/dev/null 2>&1
+ local addr="$1"
+ local target_x="$2"
+ local target_y="$3"
+ local width="$4"
+ local height="$5"
+
+ 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))
+
+ # 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
+
+ # 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
+ done
+
+ # Ensure final position is exact
+ hyprctl dispatch movewindowpixel "exact $target_x $target_y,address:$addr" >/dev/null 2>&1
}
# Function to animate window slide up (hide)
animate_slide_up() {
- local addr="$1"
- local start_x="$2"
- local start_y="$3"
- local width="$4"
- local height="$5"
-
- 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))
-
- # 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
- done
-
- debug_echo "Slide up animation completed"
+ local addr="$1"
+ local start_x="$2"
+ local start_y="$3"
+ local width="$4"
+ local height="$5"
+
+ 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))
+
+ # 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
+ done
+
+ debug_echo "Slide up animation completed"
}
# Function to get monitor info including scale and name of focused monitor
get_monitor_info() {
- local monitor_data=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | "\(.x) \(.y) \(.width) \(.height) \(.scale) \(.name)"')
- if [ -z "$monitor_data" ] || [[ "$monitor_data" =~ ^null ]]; then
- debug_echo "Error: Could not get focused monitor information"
- return 1
- fi
- echo "$monitor_data"
+ local monitor_data=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | "\(.x) \(.y) \(.width) \(.height) \(.scale) \(.name)"')
+ if [ -z "$monitor_data" ] || [[ "$monitor_data" =~ ^null ]]; then
+ debug_echo "Error: Could not get focused monitor information"
+ return 1
+ fi
+ echo "$monitor_data"
}
# Function to calculate dropdown position with proper scaling and centering
calculate_dropdown_position() {
- local monitor_info=$(get_monitor_info)
-
- if [ $? -ne 0 ] || [ -z "$monitor_info" ]; then
- debug_echo "Error: Failed to get monitor info, using fallback values"
- echo "100 100 800 600 fallback-monitor"
- return 1
- fi
-
- local mon_x=$(echo $monitor_info | cut -d' ' -f1)
- local mon_y=$(echo $monitor_info | cut -d' ' -f2)
- local mon_width=$(echo $monitor_info | cut -d' ' -f3)
- local mon_height=$(echo $monitor_info | cut -d' ' -f4)
- local mon_scale=$(echo $monitor_info | cut -d' ' -f5)
- local mon_name=$(echo $monitor_info | cut -d' ' -f6)
-
- debug_echo "Monitor info: x=$mon_x, y=$mon_y, width=$mon_width, height=$mon_height, scale=$mon_scale"
-
- # Validate scale value and provide fallback
- if [ -z "$mon_scale" ] || [ "$mon_scale" = "null" ] || [ "$mon_scale" = "0" ]; then
- debug_echo "Invalid scale value, using 1.0 as fallback"
- mon_scale="1.0"
- fi
-
- # Calculate logical dimensions by dividing physical dimensions by scale
- local logical_width logical_height
- if command -v bc >/dev/null 2>&1; then
- # Use bc for precise floating point calculation
- logical_width=$(echo "scale=0; $mon_width / $mon_scale" | bc | cut -d'.' -f1)
- logical_height=$(echo "scale=0; $mon_height / $mon_scale" | bc | cut -d'.' -f1)
- else
- # Fallback to integer math (multiply by 100 for precision, then divide)
- local scale_int=$(echo "$mon_scale" | sed 's/\.//' | sed 's/^0*//')
- if [ -z "$scale_int" ]; then scale_int=100; fi
-
- logical_width=$(((mon_width * 100) / scale_int))
- logical_height=$(((mon_height * 100) / scale_int))
- fi
-
- # Ensure we have valid integer values
- if ! [[ "$logical_width" =~ ^-?[0-9]+$ ]]; then logical_width=$mon_width; fi
- if ! [[ "$logical_height" =~ ^-?[0-9]+$ ]]; then logical_height=$mon_height; fi
-
- debug_echo "Physical resolution: ${mon_width}x${mon_height}"
- debug_echo "Logical resolution: ${logical_width}x${logical_height} (physical ÷ scale)"
-
- # Calculate window dimensions based on LOGICAL space percentages
- local width=$((logical_width * WIDTH_PERCENT / 100))
- local height=$((logical_height * HEIGHT_PERCENT / 100))
-
- # Calculate Y position from top based on percentage of LOGICAL height
- local y_offset=$((logical_height * Y_PERCENT / 100))
-
- # Calculate centered X position in LOGICAL space
- local x_offset=$(((logical_width - width) / 2))
-
- # Apply monitor offset to get final positions in logical coordinates
- local final_x=$((mon_x + x_offset))
- local final_y=$((mon_y + y_offset))
-
- debug_echo "Window size: ${width}x${height} (logical pixels)"
- debug_echo "Final position: x=$final_x, y=$final_y (logical coordinates)"
- debug_echo "Hyprland will scale these to physical coordinates automatically"
-
- echo "$final_x $final_y $width $height $mon_name"
+ local monitor_info=$(get_monitor_info)
+
+ if [ $? -ne 0 ] || [ -z "$monitor_info" ]; then
+ debug_echo "Error: Failed to get monitor info, using fallback values"
+ echo "100 100 800 600 fallback-monitor"
+ return 1
+ fi
+
+ local mon_x=$(echo $monitor_info | cut -d' ' -f1)
+ local mon_y=$(echo $monitor_info | cut -d' ' -f2)
+ local mon_width=$(echo $monitor_info | cut -d' ' -f3)
+ local mon_height=$(echo $monitor_info | cut -d' ' -f4)
+ local mon_scale=$(echo $monitor_info | cut -d' ' -f5)
+ local mon_name=$(echo $monitor_info | cut -d' ' -f6)
+
+ debug_echo "Monitor info: x=$mon_x, y=$mon_y, width=$mon_width, height=$mon_height, scale=$mon_scale"
+
+ # Validate scale value and provide fallback
+ if [ -z "$mon_scale" ] || [ "$mon_scale" = "null" ] || [ "$mon_scale" = "0" ]; then
+ debug_echo "Invalid scale value, using 1.0 as fallback"
+ mon_scale="1.0"
+ fi
+
+ # Calculate logical dimensions by dividing physical dimensions by scale
+ local logical_width logical_height
+ if command -v bc >/dev/null 2>&1; then
+ # Use bc for precise floating point calculation
+ logical_width=$(echo "scale=0; $mon_width / $mon_scale" | bc | cut -d'.' -f1)
+ logical_height=$(echo "scale=0; $mon_height / $mon_scale" | bc | cut -d'.' -f1)
+ else
+ # Fallback to integer math (multiply by 100 for precision, then divide)
+ local scale_int=$(echo "$mon_scale" | sed 's/\.//' | sed 's/^0*//')
+ if [ -z "$scale_int" ]; then scale_int=100; fi
+
+ logical_width=$(((mon_width * 100) / scale_int))
+ logical_height=$(((mon_height * 100) / scale_int))
+ fi
+
+ # Ensure we have valid integer values
+ if ! [[ "$logical_width" =~ ^-?[0-9]+$ ]]; then logical_width=$mon_width; fi
+ if ! [[ "$logical_height" =~ ^-?[0-9]+$ ]]; then logical_height=$mon_height; fi
+
+ debug_echo "Physical resolution: ${mon_width}x${mon_height}"
+ debug_echo "Logical resolution: ${logical_width}x${logical_height} (physical ÷ scale)"
+
+ # Calculate window dimensions based on LOGICAL space percentages
+ local width=$((logical_width * WIDTH_PERCENT / 100))
+ local height=$((logical_height * HEIGHT_PERCENT / 100))
+
+ # Calculate Y position from top based on percentage of LOGICAL height
+ local y_offset=$((logical_height * Y_PERCENT / 100))
+
+ # Calculate centered X position in LOGICAL space
+ local x_offset=$(((logical_width - width) / 2))
+
+ # Apply monitor offset to get final positions in logical coordinates
+ local final_x=$((mon_x + x_offset))
+ local final_y=$((mon_y + y_offset))
+
+ debug_echo "Window size: ${width}x${height} (logical pixels)"
+ debug_echo "Final position: x=$final_x, y=$final_y (logical coordinates)"
+ debug_echo "Hyprland will scale these to physical coordinates automatically"
+
+ echo "$final_x $final_y $width $height $mon_name"
}
# Get the current workspace
@@ -202,179 +202,179 @@ CURRENT_WS=$(hyprctl activeworkspace -j | jq -r '.id')
# Function to get stored terminal address
get_terminal_address() {
- if [ -f "$ADDR_FILE" ] && [ -s "$ADDR_FILE" ]; then
- cut -d' ' -f1 "$ADDR_FILE"
- fi
+ if [ -f "$ADDR_FILE" ] && [ -s "$ADDR_FILE" ]; then
+ cut -d' ' -f1 "$ADDR_FILE"
+ fi
}
# Function to get stored monitor name
get_terminal_monitor() {
- if [ -f "$ADDR_FILE" ] && [ -s "$ADDR_FILE" ]; then
- cut -d' ' -f2- "$ADDR_FILE"
- fi
+ if [ -f "$ADDR_FILE" ] && [ -s "$ADDR_FILE" ]; then
+ cut -d' ' -f2- "$ADDR_FILE"
+ fi
}
# Function to check if terminal exists
terminal_exists() {
- local addr=$(get_terminal_address)
- if [ -n "$addr" ]; then
- hyprctl clients -j | jq -e --arg ADDR "$addr" 'any(.[]; .address == $ADDR)' >/dev/null 2>&1
- else
- return 1
- fi
+ local addr=$(get_terminal_address)
+ if [ -n "$addr" ]; then
+ hyprctl clients -j | jq -e --arg ADDR "$addr" 'any(.[]; .address == $ADDR)' >/dev/null 2>&1
+ else
+ return 1
+ fi
}
# Function to check if terminal is in special workspace
terminal_in_special() {
- local addr=$(get_terminal_address)
- if [ -n "$addr" ]; then
- hyprctl clients -j | jq -e --arg ADDR "$addr" 'any(.[]; .address == $ADDR and .workspace.name == "special:scratchpad")' >/dev/null 2>&1
- else
- return 1
- fi
+ local addr=$(get_terminal_address)
+ if [ -n "$addr" ]; then
+ hyprctl clients -j | jq -e --arg ADDR "$addr" 'any(.[]; .address == $ADDR and .workspace.name == "special:scratchpad")' >/dev/null 2>&1
+ else
+ return 1
+ fi
}
# Function to spawn terminal and capture its address
spawn_terminal() {
- debug_echo "Creating new dropdown terminal with command: $TERMINAL_CMD"
-
- # Calculate dropdown position for later use
- local pos_info=$(calculate_dropdown_position)
- if [ $? -ne 0 ]; then
- debug_echo "Warning: Using fallback positioning"
- 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)
- local monitor_name=$(echo $pos_info | cut -d' ' -f5)
-
- debug_echo "Target position: ${target_x},${target_y}, size: ${width}x${height}"
-
- # Get window count before spawning
- 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')
-
- local new_addr=""
-
- 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
-
- 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
-
- # Now bring it back with the same animation as subsequent shows
- # Use movetoworkspacesilent to avoid affecting workspace history
- hyprctl dispatch movetoworkspacesilent "$CURRENT_WS,address:$new_addr"
- hyprctl dispatch pin "address:$new_addr"
- animate_slide_down "$new_addr" "$target_x" "$target_y" "$width" "$height"
-
- return 0
- fi
-
- debug_echo "Failed to get terminal address"
- return 1
+ debug_echo "Creating new dropdown terminal with command: $TERMINAL_CMD"
+
+ # Calculate dropdown position for later use
+ local pos_info=$(calculate_dropdown_position)
+ if [ $? -ne 0 ]; then
+ debug_echo "Warning: Using fallback positioning"
+ 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)
+ local monitor_name=$(echo $pos_info | cut -d' ' -f5)
+
+ debug_echo "Target position: ${target_x},${target_y}, size: ${width}x${height}"
+
+ # Get window count before spawning
+ 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')
+
+ local new_addr=""
+
+ 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
+
+ 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
+
+ # Now bring it back with the same animation as subsequent shows
+ # Use movetoworkspacesilent to avoid affecting workspace history
+ hyprctl dispatch movetoworkspacesilent "$CURRENT_WS,address:$new_addr"
+ hyprctl dispatch pin "address:$new_addr"
+ animate_slide_down "$new_addr" "$target_x" "$target_y" "$width" "$height"
+
+ return 0
+ fi
+
+ debug_echo "Failed to get terminal address"
+ return 1
}
# Main logic
if terminal_exists; then
- TERMINAL_ADDR=$(get_terminal_address)
- 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"
- fi
+ TERMINAL_ADDR=$(get_terminal_address)
+ 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"
+ fi
- if terminal_in_special; then
- debug_echo "Bringing terminal from scratchpad 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)
-
- # Use movetoworkspacesilent to avoid affecting workspace history
- hyprctl dispatch movetoworkspacesilent "$CURRENT_WS,address:$TERMINAL_ADDR"
- hyprctl dispatch pin "address:$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"
+ if terminal_in_special; then
+ debug_echo "Bringing terminal from scratchpad 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)
+
+ # Use movetoworkspacesilent to avoid affecting workspace history
+ hyprctl dispatch movetoworkspacesilent "$CURRENT_WS,address:$TERMINAL_ADDR"
+ hyprctl dispatch pin "address:$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"
+ else
+ debug_echo "Hiding terminal to scratchpad 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}"
+
+ # Animate slide up first
+ animate_slide_up "$TERMINAL_ADDR" "$curr_x" "$curr_y" "$curr_width" "$curr_height"
+
+ # Small delay then move to special workspace and unpin
+ sleep 0.1
+ hyprctl dispatch pin "address:$TERMINAL_ADDR" # Unpin (toggle)
+ hyprctl dispatch movetoworkspacesilent "$SPECIAL_WS,address:$TERMINAL_ADDR"
else
- debug_echo "Hiding terminal to scratchpad 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}"
-
- # Animate slide up first
- animate_slide_up "$TERMINAL_ADDR" "$curr_x" "$curr_y" "$curr_width" "$curr_height"
-
- # Small delay then move to special workspace and unpin
- sleep 0.1
- hyprctl dispatch pin "address:$TERMINAL_ADDR" # Unpin (toggle)
- hyprctl dispatch movetoworkspacesilent "$SPECIAL_WS,address:$TERMINAL_ADDR"
- else
- debug_echo "Could not get window geometry, moving to scratchpad without animation"
- hyprctl dispatch pin "address:$TERMINAL_ADDR"
- hyprctl dispatch movetoworkspacesilent "$SPECIAL_WS,address:$TERMINAL_ADDR"
- fi
+ debug_echo "Could not get window geometry, moving to scratchpad without animation"
+ hyprctl dispatch pin "address:$TERMINAL_ADDR"
+ hyprctl dispatch movetoworkspacesilent "$SPECIAL_WS,address:$TERMINAL_ADDR"
fi
+ fi
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
+ 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
fi
diff --git a/config/hypr/scripts/GameMode.sh b/config/hypr/scripts/GameMode.sh
index 7a39da3d..59cf7372 100755
--- a/config/hypr/scripts/GameMode.sh
+++ b/config/hypr/scripts/GameMode.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Game Mode. Turning off all animations
@@ -20,6 +20,7 @@ if [ "$HYPRGAMEMODE" = 1 ] ; then
hyprctl keyword "windowrule opacity 1 override 1 override 1 override, ^(.*)$"
swww kill
notify-send -e -u low -i "$notif" " Gamemode:" " enabled"
+ sleep 0.1
exit
else
swww-daemon --format xrgb && swww img "$HOME/.config/rofi/.current_wallpaper" &
diff --git a/config/hypr/scripts/Hypridle.sh b/config/hypr/scripts/Hypridle.sh
index 56176716..6acff434 100755
--- a/config/hypr/scripts/Hypridle.sh
+++ b/config/hypr/scripts/Hypridle.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# This is for custom version of waybar idle_inhibitor which activates / deactivates hypridle instead
diff --git a/config/hypr/scripts/Hyprsunset.sh b/config/hypr/scripts/Hyprsunset.sh
index c7c4b395..4a2b52f4 100755
--- a/config/hypr/scripts/Hyprsunset.sh
+++ b/config/hypr/scripts/Hyprsunset.sh
@@ -8,12 +8,12 @@ set -euo pipefail
# - On: sunset icon if available, otherwise a blue sun
#
# Customize via env vars:
-# HYPERSUNSET_TEMP default 4500 (K)
-# HYPERSUNSET_ICON_MODE sunset|blue (default: sunset)
+# HYPRSUNSET_TEMP default 4500 (K)
+# HYPRSUNSET_ICON_MODE sunset|blue (default: sunset)
STATE_FILE="$HOME/.cache/.hyprsunset_state"
-TARGET_TEMP="${HYPERSUNSET_TEMP:-4500}"
-ICON_MODE="${HYPERSUNSET_ICON_MODE:-sunset}"
+TARGET_TEMP="${HYPRSUNSET_TEMP:-4500}"
+ICON_MODE="${HYPRSUNSET_ICON_MODE:-sunset}"
ensure_state() {
[[ -f "$STATE_FILE" ]] || echo "off" > "$STATE_FILE"
@@ -92,8 +92,20 @@ cmd_status() {
printf '{"text":"%s","class":"%s","tooltip":"%s"}\n' "$txt" "$cls" "$tip"
}
+cmd_init() {
+ ensure_state
+ state="$(cat "$STATE_FILE" || echo off)"
+
+ if [[ "$state" == "on" ]]; then
+ if command -v hyprsunset >/dev/null 2>&1; then
+ nohup hyprsunset -t "$TARGET_TEMP" >/dev/null 2>&1 &
+ fi
+ fi
+}
+
case "${1:-}" in
toggle) cmd_toggle ;;
status) cmd_status ;;
- *) echo "usage: $0 [toggle|status]" >&2; exit 2 ;;
+ init) cmd_init ;;
+ *) echo "usage: $0 [toggle|status|init]" >&2; exit 2 ;;
esac
diff --git a/config/hypr/scripts/KeyBinds.sh b/config/hypr/scripts/KeyBinds.sh
index 9c6b5ab7..46953cc5 100755
--- a/config/hypr/scripts/KeyBinds.sh
+++ b/config/hypr/scripts/KeyBinds.sh
@@ -1,6 +1,6 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
-# searchable enabled keybinds using rofi
+# searchable enabled keybinds using rofi (supports bindd descriptions)
# kill yad to not interfere with this binds
pkill yad || true
@@ -17,23 +17,66 @@ laptop_conf="$HOME/.config/hypr/UserConfigs/Laptops.conf"
rofi_theme="$HOME/.config/rofi/config-keybinds.rasi"
msg='☣️ NOTE ☣️: Clicking with Mouse or Pressing ENTER will have NO function'
-# combine the contents of the keybinds files and filter for keybinds
-keybinds=$(cat "$keybinds_conf" "$user_keybinds_conf" | grep -E '^bind')
+# collect raw bind lines (strip end-of-line comments) from available files
+files=("$keybinds_conf" "$user_keybinds_conf")
+[[ -f "$laptop_conf" ]] && files+=("$laptop_conf")
-# check if laptop.conf exists and add its keybinds if present
-if [[ -f "$laptop_conf" ]]; then
- laptop_binds=$(grep -E '^bind' "$laptop_conf")
- keybinds+=$'\n'"$laptop_binds"
-fi
+raw_keybinds=$(cat "${files[@]}" 2>/dev/null \
+ | grep -E '^[[:space:]]*bind' \
+ | sed -E 's/[[:space:]]+#.*$//')
# check for any keybinds to display
-if [[ -z "$keybinds" ]]; then
+if [[ -z "$raw_keybinds" ]]; then
echo "no keybinds found."
exit 1
fi
-# replace $mainmod with super in the displayed keybinds for rofi
-display_keybinds=$(echo "$keybinds" | sed 's/\$mainMod/SUPER/g')
+# transform into a readable list: MODS+KEY — DESCRIPTION — DISPATCHER [PARAMS]
+display_keybinds=$(echo "$raw_keybinds" | awk -F'=' '
+ function trim(s){ gsub(/^[ \t]+|[ \t]+$/,"",s); return s }
+ /^[[:space:]]*bind/ {
+ binder=$1; gsub(/[ \t]/, "", binder);
+ hasdesc = (index(binder, "d")>0);
+
+ rhs=$2; rhs=trim(rhs);
+ n=split(rhs, a, /[ \t]*,[ \t]*/);
+
+ mods=trim(a[1]); key=(n>=2?trim(a[2]):"");
+ desc=""; dispatcher=""; params="";
+
+ if (hasdesc) {
+ desc=(n>=3?trim(a[3]):"");
+ dispatcher=(n>=4?trim(a[4]):"");
+ start=5;
+ } else {
+ dispatcher=(n>=3?trim(a[3]):"");
+ start=4;
+ }
+
+ for(i=start;i<=n;i++){ if(length(a[i])){ p=trim(a[i]); if(p!="") params = (params?params", ":"") p } }
+
+ gsub(/\$mainMod/,"SUPER",mods);
+ gsub(/[ \t]+/,"+",mods);
+
+ combo = (mods && key) ? mods "+" key : (key?key:mods);
+
+ if (desc != "") {
+ if (dispatcher != "" && params != "")
+ print combo, " — ", desc, " — ", dispatcher, " ", params;
+ else if (dispatcher != "")
+ print combo, " — ", desc, " — ", dispatcher;
+ else
+ print combo, " — ", desc;
+ } else {
+ if (dispatcher != "" && params != "")
+ print combo, " — ", dispatcher, " ", params;
+ else if (dispatcher != "")
+ print combo, " — ", dispatcher;
+ else
+ print combo;
+ }
+ }
+')
-# use rofi to display the keybinds with the modified content
-echo "$display_keybinds" | rofi -dmenu -i -config "$rofi_theme" -mesg "$msg" \ No newline at end of file
+# use rofi to display the keybinds
+printf '%s\n' "$display_keybinds" | rofi -dmenu -i -config "$rofi_theme" -mesg "$msg"
diff --git a/config/hypr/scripts/KeyHints.sh b/config/hypr/scripts/KeyHints.sh
index 7917ae3a..8a478039 100755
--- a/config/hypr/scripts/KeyHints.sh
+++ b/config/hypr/scripts/KeyHints.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# GDK BACKEND. Change to either wayland or x11 if having issues
diff --git a/config/hypr/scripts/KeybindsLayoutInit.sh b/config/hypr/scripts/KeybindsLayoutInit.sh
new file mode 100755
index 00000000..0a53eaaf
--- /dev/null
+++ b/config/hypr/scripts/KeybindsLayoutInit.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
+# Initialize J/K keybinds so they always cycle windows globally (no layout-specific behavior)
+# This avoids double-actions when layouts change.
+
+set -euo pipefail
+
+# Always reset and bind SUPER+J/K the same way on startup
+hyprctl keyword unbind SUPER,J || true
+hyprctl keyword unbind SUPER,K || true
+
+# Cycle windows globally: J = next, K = previous
+hyprctl keyword bind SUPER,J,cyclenext
+hyprctl keyword bind SUPER,K,cyclenext,prev
diff --git a/config/hypr/scripts/KillActiveProcess.sh b/config/hypr/scripts/KillActiveProcess.sh
index bee146d7..2bc108f2 100755
--- a/config/hypr/scripts/KillActiveProcess.sh
+++ b/config/hypr/scripts/KillActiveProcess.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Copied from Discord post. Thanks to @Zorg
diff --git a/config/hypr/scripts/Kitty_themes.sh b/config/hypr/scripts/Kitty_themes.sh
index 48bfa99f..55da7e44 100755
--- a/config/hypr/scripts/Kitty_themes.sh
+++ b/config/hypr/scripts/Kitty_themes.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */  #
# Kitty Themes Source https://github.com/dexpota/kitty-themes #
diff --git a/config/hypr/scripts/KooLsDotsUpdate.sh b/config/hypr/scripts/KooLsDotsUpdate.sh
index f4b8814a..51277ab1 100755
--- a/config/hypr/scripts/KooLsDotsUpdate.sh
+++ b/config/hypr/scripts/KooLsDotsUpdate.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# simple bash script to check if update is available by comparing local version and github version
diff --git a/config/hypr/scripts/Kool_Quick_Settings.sh b/config/hypr/scripts/Kool_Quick_Settings.sh
index e43749bf..16742492 100755
--- a/config/hypr/scripts/Kool_Quick_Settings.sh
+++ b/config/hypr/scripts/Kool_Quick_Settings.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Rofi menu for KooL Hyprland Quick Settings (SUPER SHIFT E)
@@ -55,10 +55,10 @@ main() {
case "$choice" in
"view/edit User Defaults") file="$UserConfigs/01-UserDefaults.conf" ;;
"view/edit ENV variables") file="$UserConfigs/ENVariables.conf" ;;
- "view/edit Window Rules") file="$UserConfigs/WindowRules.conf" ;;
+ "view/edit Window Rules") file="$configs/WindowRules.conf" ;;
"view/edit User Keybinds") file="$UserConfigs/UserKeybinds.conf" ;;
"view/edit User Settings") file="$UserConfigs/UserSettings.conf" ;;
- "view/edit Startup Apps") file="$UserConfigs/Startup_Apps.conf" ;;
+ "view/edit Startup Apps") file="$configs/Startup_Apps.conf" ;;
"view/edit Decorations") file="$UserConfigs/UserDecorations.conf" ;;
"view/edit Animations") file="$UserConfigs/UserAnimations.conf" ;;
"view/edit Laptop Keybinds") file="$UserConfigs/Laptops.conf" ;;
diff --git a/config/hypr/scripts/LockScreen.sh b/config/hypr/scripts/LockScreen.sh
index 5e799181..d58f5c21 100755
--- a/config/hypr/scripts/LockScreen.sh
+++ b/config/hypr/scripts/LockScreen.sh
@@ -1,7 +1,11 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# For Hyprlock
-#pidof hyprlock || hyprlock -q
+#pidof hyprlock || hyprlock -q
+
+# Ensure weather cache is up-to-date before locking (Waybar/lockscreen readers)
+bash "$HOME/.config/hypr/UserScripts/WeatherWrap.sh" >/dev/null 2>&1
+
+loginctl lock-session
-loginctl lock-session \ No newline at end of file
diff --git a/config/hypr/scripts/MediaCtrl.sh b/config/hypr/scripts/MediaCtrl.sh
index 000c3ade..9dc3571d 100755
--- a/config/hypr/scripts/MediaCtrl.sh
+++ b/config/hypr/scripts/MediaCtrl.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Playerctl
diff --git a/config/hypr/scripts/MonitorProfiles.sh b/config/hypr/scripts/MonitorProfiles.sh
index 67316c09..1176a46a 100755
--- a/config/hypr/scripts/MonitorProfiles.sh
+++ b/config/hypr/scripts/MonitorProfiles.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# For applying Pre-configured Monitor Profiles
diff --git a/config/hypr/scripts/OverviewToggle.sh b/config/hypr/scripts/OverviewToggle.sh
new file mode 100755
index 00000000..2737234c
--- /dev/null
+++ b/config/hypr/scripts/OverviewToggle.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ #
+# Overview toggle wrapper - tries Quickshell first, falls back to AGS
+
+set -euo pipefail
+
+# 1) Try Quickshell via Hyprland global dispatch (works if QS is running and listening)
+# Only attempt this if a Quickshell process is running; otherwise Hyprland will
+# still return success for the dispatch and we'll never fall back to AGS.
+if pgrep -x quickshell >/dev/null 2>&1; then
+ if hyprctl dispatch global quickshell:overviewToggle >/dev/null 2>&1; then
+ exit 0
+ 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
+ qs >/dev/null 2>&1 &
+ sleep 0.6
+ if hyprctl dispatch global quickshell:overviewToggle >/dev/null 2>&1; then
+ exit 0
+ fi
+fi
+
+# 2) Fall back to AGS template
+if command -v ags >/dev/null 2>&1; then
+ pkill rofi || true
+ if ags -t 'overview' >/dev/null 2>&1; then
+ exit 0
+ fi
+ # If it failed, try starting AGS daemon then call the template
+ ags >/dev/null 2>&1 &
+ sleep 0.6
+ if ags -t 'overview' >/dev/null 2>&1; then
+ exit 0
+ fi
+fi
+
+# If we get here, neither worked
+notify-send "Overview" "Neither Quickshell nor AGS is available" -u low 2>/dev/null || true
+exit 1
diff --git a/config/hypr/scripts/Polkit-NixOS.sh b/config/hypr/scripts/Polkit-NixOS.sh
index 51675eff..28642d19 100755
--- a/config/hypr/scripts/Polkit-NixOS.sh
+++ b/config/hypr/scripts/Polkit-NixOS.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# For NixOS starting of polkit-gnome. Dec 2023, the settings stated in NixOS wiki does not work so have to manual start it
diff --git a/config/hypr/scripts/Polkit.sh b/config/hypr/scripts/Polkit.sh
index dcea7653..1af8fd1b 100755
--- a/config/hypr/scripts/Polkit.sh
+++ b/config/hypr/scripts/Polkit.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# This script starts the first available Polkit agent from a list of possible locations
diff --git a/config/hypr/scripts/PortalHyprland.sh b/config/hypr/scripts/PortalHyprland.sh
index 9bdf4b8c..21cb7db4 100755
--- a/config/hypr/scripts/PortalHyprland.sh
+++ b/config/hypr/scripts/PortalHyprland.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# For manually starting xdg-desktop-portal-hyprland
diff --git a/config/hypr/scripts/Refresh.sh b/config/hypr/scripts/Refresh.sh
index 719c368d..76757aa4 100755
--- a/config/hypr/scripts/Refresh.sh
+++ b/config/hypr/scripts/Refresh.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Scripts for refreshing ags, waybar, rofi, swaync, wallust
@@ -7,23 +7,25 @@ UserScripts=$HOME/.config/hypr/UserScripts
# Define file_exists function
file_exists() {
- if [ -e "$1" ]; then
- return 0 # File exists
- else
- return 1 # File does not exist
- fi
+ if [ -e "$1" ]; then
+ return 0 # File exists
+ else
+ return 1 # File does not exist
+ fi
}
# Kill already running processes
_ps=(waybar rofi swaync ags)
for _prs in "${_ps[@]}"; do
- if pidof "${_prs}" >/dev/null; then
- pkill "${_prs}"
- fi
+ if pidof "${_prs}" >/dev/null; then
+ pkill "${_prs}"
+ fi
done
# added since wallust sometimes not applying
-killall -SIGUSR2 waybar
+killall -SIGUSR2 waybar
+# Added sleep for GameMode causing multiple waybar
+sleep 0.1
# quit ags & relaunch ags
#ags -q && ags &
@@ -33,23 +35,24 @@ killall -SIGUSR2 waybar
# some process to kill
for pid in $(pidof waybar rofi swaync ags swaybg); do
- kill -SIGUSR1 "$pid"
+ kill -SIGUSR1 "$pid"
+ sleep 0.1
done
#Restart waybar
-sleep 1
+sleep 0.1
waybar &
# relaunch swaync
-sleep 0.5
-swaync > /dev/null 2>&1 &
+sleep 0.3
+swaync >/dev/null 2>&1 &
# reload swaync
swaync-client --reload-config
# Relaunching rainbow borders if the script exists
sleep 1
if file_exists "${UserScripts}/RainbowBorders.sh"; then
- ${UserScripts}/RainbowBorders.sh &
+ ${UserScripts}/RainbowBorders.sh &
fi
-exit 0 \ No newline at end of file
+exit 0
diff --git a/config/hypr/scripts/RefreshNoWaybar.sh b/config/hypr/scripts/RefreshNoWaybar.sh
index 8454124e..54c760bd 100755
--- a/config/hypr/scripts/RefreshNoWaybar.sh
+++ b/config/hypr/scripts/RefreshNoWaybar.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Modified version of Refresh.sh but waybar wont refresh
diff --git a/config/hypr/scripts/RofiEmoji.sh b/config/hypr/scripts/RofiEmoji.sh
index 4570831e..7e3ef0f3 100755
--- a/config/hypr/scripts/RofiEmoji.sh
+++ b/config/hypr/scripts/RofiEmoji.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Variables
diff --git a/config/hypr/scripts/RofiSearch.sh b/config/hypr/scripts/RofiSearch.sh
index 4218bed3..8ef12c46 100755
--- a/config/hypr/scripts/RofiSearch.sh
+++ b/config/hypr/scripts/RofiSearch.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# For Searching via web browsers
diff --git a/config/hypr/scripts/RofiThemeSelector-modified.sh b/config/hypr/scripts/RofiThemeSelector-modified.sh
index 2cfc2d24..d6a353c0 100755
--- a/config/hypr/scripts/RofiThemeSelector-modified.sh
+++ b/config/hypr/scripts/RofiThemeSelector-modified.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# A modified version of Rofi-Theme-Selector, concentrating only on ~/.local and also, applying only 10 @themes in ~/.config/rofi/config.rasi
# as opposed to continous adding of //@theme
diff --git a/config/hypr/scripts/RofiThemeSelector.sh b/config/hypr/scripts/RofiThemeSelector.sh
index 8b2fcb71..b7236e8f 100755
--- a/config/hypr/scripts/RofiThemeSelector.sh
+++ b/config/hypr/scripts/RofiThemeSelector.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */  #
# Rofi Themes - Script to preview and apply themes by live-reloading the config.
diff --git a/config/hypr/scripts/ScreenShot.sh b/config/hypr/scripts/ScreenShot.sh
index 0a37c7e4..0ef70964 100755
--- a/config/hypr/scripts/ScreenShot.sh
+++ b/config/hypr/scripts/ScreenShot.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Screenshots scripts
diff --git a/config/hypr/scripts/Sounds.sh b/config/hypr/scripts/Sounds.sh
index 8b2cc76e..b372d714 100755
--- a/config/hypr/scripts/Sounds.sh
+++ b/config/hypr/scripts/Sounds.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# This script is used to play system sounds.
# Script is used by Volume.Sh and ScreenShots.sh
diff --git a/config/hypr/scripts/SwitchKeyboardLayout.sh b/config/hypr/scripts/SwitchKeyboardLayout.sh
index f505fa6c..18a9517e 100755
--- a/config/hypr/scripts/SwitchKeyboardLayout.sh
+++ b/config/hypr/scripts/SwitchKeyboardLayout.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# This is for changing kb_layouts. Set kb_layouts in $settings_file
diff --git a/config/hypr/scripts/Tak0-Autodispatch.sh b/config/hypr/scripts/Tak0-Autodispatch.sh
index a1f72129..114a3e8e 100755
--- a/config/hypr/scripts/Tak0-Autodispatch.sh
+++ b/config/hypr/scripts/Tak0-Autodispatch.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# USAGE / ІНСТРУКЦІЯ:
# 1) Run from terminal:
# ./dispatch.sh <application_command> <target_workspace_number>
diff --git a/config/hypr/scripts/TouchPad.sh b/config/hypr/scripts/TouchPad.sh
index 8509d79f..030c36de 100755
--- a/config/hypr/scripts/TouchPad.sh
+++ b/config/hypr/scripts/TouchPad.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# For disabling touchpad.
# Edit the Touchpad_Device on ~/.config/hypr/UserConfigs/Laptops.conf according to your system
diff --git a/config/hypr/scripts/Volume.sh b/config/hypr/scripts/Volume.sh
index 8efdb55c..4c82f543 100755
--- a/config/hypr/scripts/Volume.sh
+++ b/config/hypr/scripts/Volume.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Scripts for volume controls for audio and mic
diff --git a/config/hypr/scripts/WallustSwww.sh b/config/hypr/scripts/WallustSwww.sh
index 5e0148ee..657f41ab 100755
--- a/config/hypr/scripts/WallustSwww.sh
+++ b/config/hypr/scripts/WallustSwww.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Wallust: derive colors from the current wallpaper and update templates
# Usage: WallustSwww.sh [absolute_path_to_wallpaper]
diff --git a/config/hypr/scripts/WaybarLayout.sh b/config/hypr/scripts/WaybarLayout.sh
index b4d9c493..d3725a91 100755
--- a/config/hypr/scripts/WaybarLayout.sh
+++ b/config/hypr/scripts/WaybarLayout.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Script for waybar layout or configs
@@ -50,7 +50,7 @@ main() {
[[ -z "$choice" ]] && { echo "No option selected. Exiting."; exit 0; }
# Strip marker before applying
- choice=${choice# $MARKER}
+ choice=${choice#"$MARKER "}
case "$choice" in
"no panel")
diff --git a/config/hypr/scripts/WaybarScripts.sh b/config/hypr/scripts/WaybarScripts.sh
index 7b3aaba2..d2205c42 100755
--- a/config/hypr/scripts/WaybarScripts.sh
+++ b/config/hypr/scripts/WaybarScripts.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ #
# This file used on waybar modules sourcing defaults set in $HOME/.config/hypr/UserConfigs/01-UserDefaults.conf
diff --git a/config/hypr/scripts/WaybarStyles.sh b/config/hypr/scripts/WaybarStyles.sh
index a439f8eb..8ebfed92 100755
--- a/config/hypr/scripts/WaybarStyles.sh
+++ b/config/hypr/scripts/WaybarStyles.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Script for waybar styles
@@ -51,7 +51,7 @@ main() {
[[ -z "$choice" ]] && { echo "No option selected. Exiting."; exit 0; }
# remove annotation and apply
- choice=${choice# $MARKER}
+ choice=${choice#"$MARKER "}
apply_style "$choice"
}
diff --git a/config/hypr/scripts/Wlogout.sh b/config/hypr/scripts/Wlogout.sh
index f552b83d..8879858c 100755
--- a/config/hypr/scripts/Wlogout.sh
+++ b/config/hypr/scripts/Wlogout.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# wlogout (Power, Screen Lock, Suspend, etc)
diff --git a/config/hypr/scripts/sddm_wallpaper.sh b/config/hypr/scripts/sddm_wallpaper.sh
index 9487188c..9dca2f72 100644..100755
--- a/config/hypr/scripts/sddm_wallpaper.sh
+++ b/config/hypr/scripts/sddm_wallpaper.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */
# SDDM Wallpaper and Wallust Colors Setter
diff --git a/config/hypr/v2.3.17 b/config/hypr/v2.3.18
index 31b3414d..31b3414d 100644
--- a/config/hypr/v2.3.17
+++ b/config/hypr/v2.3.18
diff --git a/config/rofi/online_music.list b/config/rofi/online_music.list
new file mode 100644
index 00000000..bb21b9d4
--- /dev/null
+++ b/config/rofi/online_music.list
@@ -0,0 +1,17 @@
+FM - Easy Rock 96.3 📻🎶|https://radio-stations-philippines.com/easy-rock
+FM - Easy Rock - Baguio 91.9 📻🎶|https://radio-stations-philippines.com/easy-rock-baguio
+FM - Love Radio 90.7 📻🎶|https://radio-stations-philippines.com/love
+FM - WRock - CEBU 96.3 📻🎶|https://onlineradio.ph/126-96-3-wrock.html
+FM - Fresh Philippines 📻🎶|https://onlineradio.ph/553-fresh-fm.html
+Radio - Lofi Girl 🎧🎶|https://play.streamafrica.net/lofiradio
+Radio - Chillhop 🎧🎶|http://stream.zeno.fm/fyn8eh3h5f8uv
+Radio - Ibiza Global 🎧🎶|https://filtermusic.net/ibiza-global
+Radio - Metal Music 🎧🎶|https://tunein.com/radio/mETaLmuSicRaDio-s119867/
+YT - Wish 107.5 YT Pinoy HipHop 📻🎶|https://youtube.com/playlist?list=PLkrzfEDjeYJnmgMYwCKid4XIFqUKBVWEs&si=vahW_noh4UDJ5d37
+YT - Youtube Top 100 Songs Global 📹🎶|https://youtube.com/playlist?list=PL4fGSI1pDJn6puJdseH2Rt9sMvt9E2M4i&si=5jsyfqcoUXBCSLeu
+YT - Wish 107.5 YT Wishclusives 📹🎶|https://youtube.com/playlist?list=PLkrzfEDjeYJn5B22H9HOWP3Kxxs-DkPSM&si=d_Ld2OKhGvpH48WO
+YT - Relaxing Piano Music 🎹🎶|https://youtu.be/6H7hXzjFoVU?si=nZTPREC9lnK1JJUG
+YT - Youtube Remix 📹🎶|https://youtube.com/playlist?list=PLeqTkIUlrZXlSNn3tcXAa-zbo95j0iN-0
+YT - Korean Drama OST 📹🎶|https://youtube.com/playlist?list=PLUge_o9AIFp4HuA-A3e3ZqENh63LuRRlQ
+YT - lofi hip hop radio beats 📹🎶|https://www.youtube.com/live/jfKfPfyJRdk?si=PnJIA9ErQIAw6-qd
+YT - Relaxing Piano Jazz Music 🎹🎶|https://youtu.be/85UEqRat6E4?si=jXQL1Yp2VP_G6NSn
diff --git a/config/waybar/ModulesCustom b/config/waybar/ModulesCustom
index 146ec275..f4c871f7 100644
--- a/config/waybar/ModulesCustom
+++ b/config/waybar/ModulesCustom
@@ -11,8 +11,9 @@
"format-alt-click": "click",
"interval": 3600,
"return-type": "json",
- "exec": "$HOME/.config/hypr/UserScripts/Weather.py",
+ //"exec": "$HOME/.config/hypr/UserScripts/Weather.py",
//"exec": "$HOME/.config/hypr/UserScripts/Weather.sh",
+ "exec": "$HOME/.config/hypr/UserScripts/WeatherWrap.sh",
//"exec-if": "ping wttr.in -c1",
"tooltip": true,
},
@@ -286,4 +287,4 @@
"format": "",
"tooltip": false
}
-} \ No newline at end of file
+}
diff --git a/config/waybar/ModulesGroups b/config/waybar/ModulesGroups
index 8d4453a2..30e47f16 100644
--- a/config/waybar/ModulesGroups
+++ b/config/waybar/ModulesGroups
@@ -89,7 +89,6 @@
},
"modules": [
"custom/power",
- "custom/nightlight",
"custom/lock",
"keyboard-state",
"custom/keyboard",
@@ -132,7 +131,6 @@
},
"modules": [
"custom/power",
- "custom/nightlight",
"custom/lock",
"custom/logout",
"custom/reboot"
diff --git a/config/waybar/ModulesWorkspaces b/config/waybar/ModulesWorkspaces
index 82a82869..5bdccb91 100644
--- a/config/waybar/ModulesWorkspaces
+++ b/config/waybar/ModulesWorkspaces
@@ -194,23 +194,25 @@
"class<tor browser>": " ",
"class<firefox-developer-edition>": "🦊 ",
- "class<kitty|konsole>": " ",
+ "class<kitty|konsole|[Aa]lacritty>": " ",
"class<kitty-dropterm>": " ",
"class<com.mitchellh.ghostty>": " ",
"class<org.wezfurlong.wezterm>": " ",
+ "class<Warp|warp|dev.warp.Warp|warp-terminal>": "󰰭 ",
"class<[Tt]hunderbird|[Tt]hunderbird-esr>": " ",
"class<eu.betterbird.Betterbird>": " ",
"title<.*gmail.*>": "󰊫 ",
"class<[Tt]elegram-desktop|org.telegram.desktop|io.github.tdesktop_x64.TDesktop>": " ",
- "class<discord|[Ww]ebcord|Vesktop>": " ",
+ "class<discord|discord-canary|[Ww]ebcord|[Vv]esktop|com.discordapp.Discord|dev.vencord.Vesktop>": " ",
+ "class<[Ss]ignal|signal-desktop|org.signal.Signal>": "󰍩 ",
+ "title<.*Signal.*>": "󰍩 ",
"title<.*whatsapp.*>": " ",
"title<.*zapzap.*>": " ",
"title<.*messenger.*>": " ",
"title<.*facebook.*>": " ",
- "title<.*reddit.*>": " ",
-
+ "title<.*Discord.*>": " ",
"title<.*ChatGPT.*>": "󰚩 ",
"title<.*deepseek.*>": "󰚩 ",
@@ -224,17 +226,20 @@
"title<.*Picture-in-Picture.*>": " ",
"title<.*youtube.*>": " ",
"class<vlc>": "󰕼 ",
+ "class<[Kk]denlive|org.kde.kdenlive>": "🎬 ",
+ "title<.*Kdenlive.*>": "🎬 ",
"title<.*cmus.*>": " ",
"class<[Ss]potify>": " ",
"class<Plex>": "󰚺 ",
"class<virt-manager>": " ",
"class<.virt-manager-wrapped>": " ",
+ "class<remote-viewer|virt-viewer>": " ",
"class<virtualbox manager>": "💽 ",
"title<virtualbox>": "💽 ",
- "class<remmina>": "🖥️ ",
+ "class<remmina|org.remmina.Remmina>": "🖥️ ",
- "class<VSCode|code-url-handler|code-oss|codium|codium-url-handler|VSCodium>": "󰨞 ",
+ "class<VSCode|code|code-url-handler|code-oss|codium|codium-url-handler|VSCodium>": "󰨞 ",
"class<dev.zed.Zed>": "󰵁",
"class<codeblocks>": "󰅩 ",
"title<.*github.*>": " ",
@@ -253,6 +258,7 @@
"class<polkit-gnome-authentication-agent-1>": "󰒃 ",
"class<nwg-look>": " ",
+ "class<nwg-displays>": " ",
"class<[Pp]avucontrol|org.pulseaudio.pavucontrol>": "󱡫 ",
"class<steam>": " ",
"class<thunar|nemo>": "󰝰 ",
@@ -263,6 +269,29 @@
"class<org.pipewire.Helvum>": "󰓃",
"class<localsend>":"",
"class<PrusaSlicer|UltiMaker-Cura|OrcaSlicer>": "󰹛",
+
+ "class<io.github.kolunmi.Bazaar>": " ",
+ "title<^Bazaar$>": " ",
+
+ "class<com.gabm.satty>": " ",
+ "title<^satty$>": " ",
+
+ "class<[Bb]ox[Bb]uddy|io.github.dvlv.boxbuddy|io.github.dvlv.BoxBuddy>": " ",
+ "title<.*BoxBuddy.*>": " ",
+
+ "title<Hyprland Keybinds>": " ",
+ "title<Niri Keybinds>": " ",
+ "title<BSPWM Keybinds>": " ",
+ "title<DWM Keybinds>": " ",
+ "title<Emacs Leader Keybinds>": " ",
+ "title<Kitty Configuration>": " ",
+ "title<WezTerm Configuration>": " ",
+ "title<Yazi Configuration>": " ",
+ "title<Cheatsheets Viewer>": " ",
+ "title<Documentation Viewer>": " ",
+ "title<^Wallpapers$>": " ",
+ "title<^Video Wallpapers$>": " ",
+ "title<^qs-wlogout$>": " ",
}
},
} \ No newline at end of file
diff --git a/copy.sh b/copy.sh
index d54402f3..b1cc6e1a 100755
--- a/copy.sh
+++ b/copy.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ #
clear
@@ -38,25 +38,25 @@ print_color() {
# Check /etc/os-release for Ubuntu or Debian and warn about Hyprland version requirement
if grep -iqE '^(ID_LIKE|ID)=.*(ubuntu|debian)' /etc/os-release >/dev/null 2>&1; then
printf "\n%.0s" {1..1}
- print_color $WARNING "\nThese Dotfiles are only supported on Hyprland 0.51.1 or greater. Do not install on older revisions.\n"
+ print_color $WARNING "\nThese Dotfiles are only supported on Hyprland v0.50 or greater. Do not install on older versions of Hyprland.\n"
while true; do
echo -n "${CAT} Do you want to continue anyway? (y/N): "
read _continue
_continue=$(echo "${_continue}" | tr '[:upper:]' '[:lower:]')
case "${_continue}" in
- y|yes)
- echo "${NOTE} Proceeding on Ubuntu/Debian by user confirmation."
- break
- ;;
- n|no|"")
- printf "\n%.0s" {1..1}
- echo "${INFO} Aborting per user choice. No changes made."
- printf "\n%.0s" {1..1}
- exit 1
- ;;
- *)
- echo "${WARN} Please answer 'y' or 'n'."
- ;;
+ y | yes)
+ echo "${NOTE} Proceeding on Ubuntu/Debian by user confirmation."
+ break
+ ;;
+ n | no | "")
+ printf "\n%.0s" {1..1}
+ echo "${INFO} Aborting per user choice. No changes made."
+ printf "\n%.0s" {1..1}
+ exit 1
+ ;;
+ *)
+ echo "${WARN} Please answer 'y' or 'n'."
+ ;;
esac
done
fi
@@ -111,8 +111,17 @@ fi
# Proper Polkit for NixOS
if hostnamectl | grep -q 'Operating System: NixOS'; then
echo "${INFO} NixOS Distro Detected. Setting up proper env's and configs." 2>&1 | tee -a "$LOG" || true
- sed -i -E '/^#?exec-once = \$scriptsDir\/Polkit-NixOS\.sh/s/^#//' config/hypr/UserConfigs/Startup_Apps.conf
- sed -i '/^exec-once = \$scriptsDir\/Polkit\.sh$/ s/^#*/#/' config/hypr/UserConfigs/Startup_Apps.conf
+ # Ensure NixOS polkit is enabled via overlay and default polkit is disabled via disable list
+ OVERLAY_SA="config/hypr/UserConfigs/Startup_Apps.conf"
+ DISABLE_SA="config/hypr/UserConfigs/Startup_Apps.disable"
+ mkdir -p "$(dirname "$OVERLAY_SA")"
+ touch "$OVERLAY_SA" "$DISABLE_SA"
+ if ! grep -qx 'exec-once = $scriptsDir/Polkit-NixOS.sh' "$OVERLAY_SA"; then
+ echo 'exec-once = $scriptsDir/Polkit-NixOS.sh' >>"$OVERLAY_SA"
+ fi
+ if ! grep -qx '\$scriptsDir/Polkit.sh' "$DISABLE_SA"; then
+ echo '$scriptsDir/Polkit.sh' >>"$DISABLE_SA"
+ fi
fi
# activating hyprcursor on env by checking if the directory ~/.icons/Bibata-Modern-Ice/hyprcursors exists
@@ -236,40 +245,53 @@ done
# Check if asusctl is installed and add rog-control-center on Startup
if command -v asusctl >/dev/null 2>&1; then
- sed -i '/^\s*#exec-once = rog-control-center/s/^#//' config/hypr/UserConfigs/Startup_Apps.conf
+ OVERLAY_SA="config/hypr/UserConfigs/Startup_Apps.conf"
+ mkdir -p "$(dirname "$OVERLAY_SA")"
+ touch "$OVERLAY_SA"
+ grep -qx 'exec-once = rog-control-center' "$OVERLAY_SA" || echo 'exec-once = rog-control-center' >>"$OVERLAY_SA"
fi
# Check if blueman-applet is installed and add blueman-applet on Startup
if command -v blueman-applet >/dev/null 2>&1; then
- sed -i '/^\s*#exec-once = blueman-applet/s/^#//' config/hypr/UserConfigs/Startup_Apps.conf
+ OVERLAY_SA="config/hypr/UserConfigs/Startup_Apps.conf"
+ mkdir -p "$(dirname "$OVERLAY_SA")"
+ touch "$OVERLAY_SA"
+ grep -qx 'exec-once = blueman-applet' "$OVERLAY_SA" || echo 'exec-once = blueman-applet' >>"$OVERLAY_SA"
fi
-# Check if ags is installed edit ags behaviour on configs
+# Check if ags is installed and enable it
if command -v ags >/dev/null 2>&1; then
- sed -i '/^\s*#exec-once = ags/s/^#//' config/hypr/UserConfigs/Startup_Apps.conf
+ echo "${INFO} AGS detected - enabling in startup and refresh scripts" 2>&1 | tee -a "$LOG"
+ OVERLAY_SA="config/hypr/UserConfigs/Startup_Apps.conf"
+ mkdir -p "$(dirname "$OVERLAY_SA")"
+ touch "$OVERLAY_SA"
+ grep -qx 'exec-once = ags' "$OVERLAY_SA" || echo 'exec-once = ags' >>"$OVERLAY_SA"
sed -i '/#ags -q && ags &/s/^#//' config/hypr/scripts/RefreshNoWaybar.sh
sed -i '/#ags -q && ags &/s/^#//' config/hypr/scripts/Refresh.sh
-
- # Uncomment the ags overview keybind
- sed -i '/^#bind = \$mainMod, A, exec, pkill rofi || true && ags -t '\''overview'\''/s/^#//' config/hypr/UserConfigs/UserKeybinds.conf
-
- # Comment the quickshell line if not already commented
- sed -i '/^\s*bind\s*=\s*\$mainMod,\s*A,\s*global,\s*quickshell:overviewToggle/{s/^\s*/#/}' config/hypr/UserConfigs/UserKeybinds.conf
fi
-# Check if quickshell is installed; edit quickshell behaviour on configs
+# Check if quickshell is installed and enable it
if command -v qs >/dev/null 2>&1; then
- sed -i '/^\s*#exec-once = qs/s/^#//' config/hypr/UserConfigs/Startup_Apps.conf
+ echo "${INFO} Quickshell detected - enabling in startup and refresh scripts" 2>&1 | tee -a "$LOG"
+ OVERLAY_SA="config/hypr/UserConfigs/Startup_Apps.conf"
+ mkdir -p "$(dirname "$OVERLAY_SA")"
+ touch "$OVERLAY_SA"
+ grep -qx 'exec-once = qs' "$OVERLAY_SA" || echo 'exec-once = qs' >>"$OVERLAY_SA"
sed -i '/#pkill qs && qs &/s/^#//' config/hypr/scripts/RefreshNoWaybar.sh
sed -i '/#pkill qs && qs &/s/^#//' config/hypr/scripts/Refresh.sh
+fi
- # Uncomment the quickshell keybind line
- sed -i "/^#bind = \$mainMod, A, global, quickshell:overviewToggle/s/^#//" config/hypr/UserConfigs/UserKeybinds.conf
-
- # Ensure the ags overview keybind is commented
- sed -i "/^\s*bind\s*=\s*\\\$mainMod,\s*A,\s*exec,\s*pkill rofi\s*||\s*true\s*&&\s*ags\s*-t\s*'overview'/{s/^\s*/#/}" config/hypr/UserConfigs/UserKeybinds.conf
+# Ensure layout-aware keybinds init runs on startup (adds to user overlay so it survives composes)
+OVERLAY_SA="config/hypr/UserConfigs/Startup_Apps.conf"
+mkdir -p "$(dirname "$OVERLAY_SA")"
+if ! grep -qx 'exec-once = \$scriptsDir/KeybindsLayoutInit.sh' "$OVERLAY_SA"; then
+ echo 'exec-once = $scriptsDir/KeybindsLayoutInit.sh' >>"$OVERLAY_SA"
+ echo "${INFO} Added KeybindsLayoutInit.sh to user Startup_Apps overlay" 2>&1 | tee -a "$LOG"
fi
+# Note: The SUPER+A keybind now uses OverviewToggle.sh which automatically
+# tries quickshell first and falls back to AGS, so both can be installed
+
printf "\n%.0s" {1..1}
# Checking if neovim or vim is installed and offer user if they want to make as default editor
@@ -392,11 +414,19 @@ while true; do
sed -i 's#^\(\s*\)\("format": "{:%a %d | %H:%M}",\) #\1//\2#g' config/waybar/Modules 2>&1 | tee -a "$LOG"
# for hyprlock
- sed -i 's/^\s*text = cmd\[update:1000\] echo "\$(date +"%H")"/# &/' config/hypr/hyprlock.conf 2>&1 | tee -a "$LOG"
- sed -i 's/^\(\s*\)# *text = cmd\[update:1000\] echo "\$(date +"%I")" #AM\/PM/\1 text = cmd\[update:1000\] echo "\$(date +"%I")" #AM\/PM/' config/hypr/hyprlock.conf 2>&1 | tee -a "$LOG"
+ HYPRLOCK_FILE="config/hypr/hyprlock.conf"
+ if [ ! -f "$HYPRLOCK_FILE" ] && [ -f "config/hypr/hyprlock-1080p.conf" ]; then
+ HYPRLOCK_FILE="config/hypr/hyprlock-1080p.conf"
+ fi
+ if [ -f "$HYPRLOCK_FILE" ]; then
+ sed -i 's/^\s*text = cmd\[update:1000\] echo "\$(date +"%H")"/# &/' "$HYPRLOCK_FILE" 2>&1 | tee -a "$LOG"
+ sed -i 's/^\(\s*\)# *text = cmd\[update:1000\] echo "\$(date +"%I")" #AM\/PM/\1 text = cmd\[update:1000\] echo "\$(date +"%I")" #AM\/PM/' "$HYPRLOCK_FILE" 2>&1 | tee -a "$LOG"
- sed -i 's/^\s*text = cmd\[update:1000\] echo "\$(date +"%S")"/# &/' config/hypr/hyprlock.conf 2>&1 | tee -a "$LOG"
- sed -i 's/^\(\s*\)# *text = cmd\[update:1000\] echo "\$(date +"%S %p")" #AM\/PM/\1 text = cmd\[update:1000\] echo "\$(date +"%S %p")" #AM\/PM/' config/hypr/hyprlock.conf 2>&1 | tee -a "$LOG"
+ sed -i 's/^\s*text = cmd\[update:1000\] echo "\$(date +"%S")"/# &/' "$HYPRLOCK_FILE" 2>&1 | tee -a "$LOG"
+ sed -i 's/^\(\s*\)# *text = cmd\[update:1000\] echo "\$(date +"%S %p")" #AM\/PM/\1 text = cmd\[update:1000\] echo "\$(date +"%S %p")" #AM\/PM/' "$HYPRLOCK_FILE" 2>&1 | tee -a "$LOG"
+ else
+ echo "${WARN} hyprlock template not found; skipping 12H lock format edits" 2>&1 | tee -a "$LOG"
+ fi
echo "${OK} 12H format set on waybar clocks succesfully." 2>&1 | tee -a "$LOG"
@@ -814,6 +844,41 @@ FILES_TO_RESTORE=(
"WindowRules.conf"
)
+# Helper to extract overlay (additions) and optional disables from a previous user file compared to vendor base
+compose_overlay_from_backup() {
+ local type="$1" # startup|windowrules
+ local base_file="$2"
+ local old_user_file="$3"
+ local new_user_file="$4"
+ local disable_file="$5"
+
+ mkdir -p "$(dirname "$new_user_file")"
+ : >"$new_user_file"
+ : >"$disable_file"
+
+ if [ "$type" = "startup" ]; then
+ # additions: exec-once lines present in old user but not in base
+ grep -E '^\s*exec-once\s*=' "$old_user_file" | sed -E 's/^\s+//;s/\s+$//' | sort -u >"$old_user_file.tmp.exec"
+ grep -E '^\s*exec-once\s*=' "$base_file" | sed -E 's/^\s+//;s/\s+$//' | sort -u >"$base_file.tmp.exec"
+ comm -23 "$old_user_file.tmp.exec" "$base_file.tmp.exec" >"$new_user_file"
+ # treat commented exec-once in old user as disables
+ grep -E '^\s*#\s*exec-once\s*=' "$old_user_file" \
+ | sed -E 's/^\s*#\s*exec-once\s*=\s*//' \
+ | sed -E 's/^\s+//;s/\s+$//' \
+ | grep -Ev '^\$scriptsDir/KeybindsLayoutInit\.sh$' \
+ | sort -u >"$disable_file"
+ rm -f "$old_user_file.tmp.exec" "$base_file.tmp.exec"
+ elif [ "$type" = "windowrules" ]; then
+ # additions
+ grep -E '^(windowrule|layerrule)\s*=' "$old_user_file" | sed -E 's/^\s+//;s/\s+$//' | sort -u >"$old_user_file.tmp.rules"
+ grep -E '^(windowrule|layerrule)\s*=' "$base_file" | sed -E 's/^\s+//;s/\s+$//' | sort -u >"$base_file.tmp.rules"
+ comm -23 "$old_user_file.tmp.rules" "$base_file.tmp.rules" >"$new_user_file"
+ # disables: lines commented in old user
+ grep -E '^\s*#\s*(windowrule|layerrule)\s*=' "$old_user_file" | sed -E 's/^\s*#\s*//' | sed -E 's/^\s+//;s/\s+$//' | sort -u >"$disable_file"
+ rm -f "$old_user_file.tmp.rules" "$base_file.tmp.rules"
+ fi
+}
+
DIRPATH="$HOME/.config/$DIRH"
BACKUP_DIR=$(get_backup_dirname)
BACKUP_DIR_PATH="$DIRPATH-backup-$BACKUP_DIR/UserConfigs"
@@ -830,14 +895,27 @@ if [ -d "$BACKUP_DIR_PATH" ]; then
NOTES for RESTORING PREVIOUS CONFIGS
█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█
- If you decide to restore your old configs, make sure to
- handle the updates or changes manually !!!
+ We now auto-migrate Startup_Apps and WindowRules by extracting
+ your additions into overlay files and optional disable lists.
+ This keeps new defaults while preserving your custom changes.
"
echo -e "${MAGENTA}Kindly Visit and check KooL's Hyprland-Dots GitHub page for the history of commits.${RESET}"
for FILE_NAME in "${FILES_TO_RESTORE[@]}"; do
BACKUP_FILE="$BACKUP_DIR_PATH/$FILE_NAME"
if [ -f "$BACKUP_FILE" ]; then
+ # Special handling for Startup_Apps.conf and WindowRules.conf
+ if [ "$FILE_NAME" = "Startup_Apps.conf" ]; then
+ compose_overlay_from_backup "startup" "$DIRPATH/configs/Startup_Apps.conf" "$BACKUP_FILE" "$DIRPATH/UserConfigs/Startup_Apps.conf" "$DIRPATH/UserConfigs/Startup_Apps.disable"
+ echo "${OK} - Migrated overlay for ${YELLOW}$FILE_NAME${RESET}" 2>&1 | tee -a "$LOG"
+ continue
+ fi
+ if [ "$FILE_NAME" = "WindowRules.conf" ]; then
+ compose_overlay_from_backup "windowrules" "$DIRPATH/configs/WindowRules.conf" "$BACKUP_FILE" "$DIRPATH/UserConfigs/WindowRules.conf" "$DIRPATH/UserConfigs/WindowRules.disable"
+ echo "${OK} - Migrated overlay for ${YELLOW}$FILE_NAME${RESET}" 2>&1 | tee -a "$LOG"
+ continue
+ fi
+
printf "\n${INFO} Found ${YELLOW}$FILE_NAME${RESET} in hypr backup...\n"
echo -n "${CAT} Do you want to restore ${YELLOW}$FILE_NAME${RESET} from backup? (y/N): "
read file_restore
@@ -855,6 +933,7 @@ if [ -d "$BACKUP_DIR_PATH" ]; then
done
fi
+
printf "\n%.0s" {1..1}
# Restoring previous UserScripts
@@ -1023,6 +1102,7 @@ printf "\n%.0s" {1..1}
echo "${MAGENTA}By default only a few wallpapers are copied${RESET}..."
while true; do
+ echo "${NOTE} A number of these wallpapers are AI generated or enhanced. Select (N/n) if this is an issue for you. "
echo -n "${CAT} Would you like to download additional wallpapers? ${WARN} This is 1GB in size (y/n): "
read WALL
@@ -1131,4 +1211,3 @@ printf "${INFO} However, it is ${MAGENTA}HIGHLY SUGGESTED${RESET} to logout and
printf "\n%.0s" {1..1}
printf "${SKY_BLUE}Thank you${RESET} for using ${MAGENTA}KooL's Hyprland Configuration${RESET}... ${YELLOW}ENJOY!!!${RESET}"
printf "\n%.0s" {1..3}
-
diff --git a/release.sh b/release.sh
index 78063ee1..e29eaa79 100755
--- a/release.sh
+++ b/release.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ #
# For downloading dots from releases
diff --git a/upgrade.sh b/upgrade.sh
index a47bd48b..07ee1f8b 100755
--- a/upgrade.sh
+++ b/upgrade.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ #
# for Semi-Manual upgrading your system.
# NOTE: requires rsync
@@ -196,7 +196,8 @@ if version_gt "$latest_version" "$stored_version"; then
chmod +x "$HOME/.config/hypr/scripts/"* 2>&1 | tee -a "$LOG"
chmod +x "$HOME/.config/hypr/UserScripts/"* 2>&1 | tee -a "$LOG"
# Set executable for initial-boot.sh
- chmod +x "$HOME/.config/hypr/initial-boot.sh" 2>&1 | tee -a "$LOG"
+ chmod +x "$HOME/.config/hypr/initial-boot.sh" 2>&1 | tee -a "$LOG"
+
else
echo "$MAGENTA Upgrade declined. No files or directories changed" 2>&1 | tee -a "$LOG"
fi
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage