diff --git a/.config/hypr/edit_here/hyprland.conf.deprecated b/.config/hypr/edit_here/hyprland.conf.deprecated
new file mode 100644
index 00000000..02cfb93e
--- /dev/null
+++ b/.config/hypr/edit_here/hyprland.conf.deprecated
@@ -0,0 +1,16 @@
+# ==============================================================================
+# USER CONFIGURATION OVERLAY
+# ==============================================================================
+# This file sources all your custom configuration files.
+# Edit the specific files in 'source/' to apply your changes.
+# ==============================================================================
+
+source = ~/.config/hypr/edit_here/source/monitors.conf
+source = ~/.config/hypr/edit_here/source/keybinds.conf
+source = ~/.config/hypr/edit_here/source/appearance.conf
+source = ~/.config/hypr/edit_here/source/autostart.conf
+source = ~/.config/hypr/edit_here/source/plugins.conf
+source = ~/.config/hypr/edit_here/source/window_rules.conf
+source = ~/.config/hypr/edit_here/source/workspace_rules.conf
+source = ~/.config/hypr/edit_here/source/environment_variables.conf
+source = ~/.config/hypr/edit_here/source/input.conf
diff --git a/.config/hypr/edit_here/hyprland.lua b/.config/hypr/edit_here/hyprland.lua
new file mode 100644
index 00000000..feca3ada
--- /dev/null
+++ b/.config/hypr/edit_here/hyprland.lua
@@ -0,0 +1,18 @@
+-- =============================================================================
+-- USER CONFIGURATION OVERLAY
+-- =============================================================================
+-- This file sources all your custom configuration files.
+-- Edit the specific files in 'source/' to apply your changes.
+-- =============================================================================
+
+local src = os.getenv("HOME") .. "/.config/hypr/edit_here/source/"
+
+dofile(src .. "monitors.lua")
+dofile(src .. "keybinds.lua")
+dofile(src .. "appearance.lua")
+dofile(src .. "autostart.lua")
+dofile(src .. "plugins.lua")
+dofile(src .. "window_rules.lua")
+dofile(src .. "workspace_rules.lua")
+dofile(src .. "environment_variables.lua")
+dofile(src .. "input.lua")
diff --git a/.config/hypr/edit_here/source/appearance.conf.deprecated b/.config/hypr/edit_here/source/appearance.conf.deprecated
new file mode 100644
index 00000000..5e82d42c
--- /dev/null
+++ b/.config/hypr/edit_here/source/appearance.conf.deprecated
@@ -0,0 +1,157 @@
+# ==============================================================================
+# USER CONFIGURATION: appearance.conf
+# ==============================================================================
+# Add your custom settings for appearance here.
+# These will override or add to the defaults found in ~/.config/hypr/source/appearance.conf
+# This file can also be edited with dusky appearance from the rofi menu or from dusky control center
+# ==============================================================================
+
+# -------------------------------------------------------------------------------------------------
+# THEME SOURCE
+# -------------------------------------------------------------------------------------------------
+# Sourcing colors generated by Matugen
+source = ~/.config/matugen/generated/hyprland-colors.conf
+
+# -------------------------------------------------------------------------------------------------
+# 1. GENERAL APPEARANCE
+# Control gaps, borders, and layout behavior.
+# See: https://wiki.hyprland.org/Configuring/Variables/#general
+# -------------------------------------------------------------------------------------------------
+general {
+ # --- Gaps & Borders ---
+ gaps_in = 6 # Gap between windows
+ gaps_out = 12 # Gap between windows and monitor edges
+ gaps_workspaces = 0 # Gap between workspaces (when sliding)
+ border_size = 2 # Size of window borders
+
+ # --- Colors ---
+ # Uses variables from the sourced matugen file
+ col.active_border = $primary
+ col.inactive_border = $inverse_on_surface
+
+ # --- Behavior ---
+ # RESIZING: Set to true. This allows you to resize windows by clicking and dragging
+ # on the gaps/border area, rather than hitting the exact 2px pixel border.
+ resize_on_border = false
+
+ # TEARING: Allows lower latency in games.
+ # NOTE: To use this, you must also apply 'windowrulev2 = immediate, class:^(game_class)$'
+ allow_tearing = true
+
+ # Default layout engine
+ layout = dwindle
+
+ # --- Snapping ---
+ # Controls how floating windows snap to each other and edges
+ snap {
+ enabled = false
+ window_gap = 10 # Min gap (px) before snapping to another window
+ monitor_gap = 10 # Min gap (px) before snapping to monitor edge
+ border_overlap = false # If true, windows snap with overlapping borders
+ }
+}
+
+# -------------------------------------------------------------------------------------------------
+# 2. DECORATION
+# Shadows, Blur, Opacity, and Rounding.
+# See: https://wiki.hyprland.org/Configuring/Variables/#decoration
+# -------------------------------------------------------------------------------------------------
+decoration {
+ # --- Rounding ---
+ rounding = 6
+ rounding_power = 6.0
+
+ # --- Opacity ---
+ active_opacity = 0.8
+ inactive_opacity = 0.6
+ fullscreen_opacity = 1.0
+
+ # --- Dimming ---
+ dim_inactive = true
+ dim_strength = 0.2
+ dim_special = 0.8 # Stronger dimming for special workspace
+
+ # --- Shadows ---
+ # Enabled because your hardware (12700H) can easily handle it.
+ shadow {
+ enabled = true
+ range = 35
+ render_power = 2 # 1-4. Higher is faster falloff (sharper looking)
+ sharp = false # If true, renders a sharp shadow (retro style)
+ scale = 1.0 # Scale of the shadow (1.0 = window size)
+ color = rgba(1a1a1aee)
+ # color = $primary
+ # offset = 0 0 # Displaces shadow (x, y)
+ }
+
+ # --- Blur ---
+ # Enabled for aesthetic depth.
+ blur {
+ enabled = true
+ size = 4 # Radius
+ passes = 2 # Quality (2 is a good balance of perf/looks)
+ new_optimizations = true
+ ignore_opacity = true # Blurs behind transparent windows even if opacity is high
+ xray = true
+
+ # Texture & Quality
+ noise = 0.0217
+ contrast = 0.8916 # Contrast modulation for blur
+ brightness = 0.8172 # Brightness modulation for blur
+ vibrancy = 0.1696 # Saturation of blurred colors
+
+ # Specifics
+ popups = false # Whether to blur right-click menus/popups
+ }
+
+ # --- Shaders ---
+ # screen_shader = ~/.config/hypr/shaders/grayscale_advanced.glsl
+}
+
+# -------------------------------------------------------------------------------------------------
+# 3. ANIMATIONS
+# See: https://wiki.hyprland.org/Configuring/Animations/
+# -------------------------------------------------------------------------------------------------
+
+source = ~/.config/hypr/source/animations/active/active.conf
+
+# -------------------------------------------------------------------------------------------------
+# 4. LAYOUTS
+# -------------------------------------------------------------------------------------------------
+dwindle {
+ preserve_split = true
+ # smart_split = false # If true, splits based on mouse position.
+ # smart_resizing = false # If true, resizing direction is determined by mouse pos.
+}
+
+master {
+ new_status = master
+}
+
+# -------------------------------------------------------------------------------------------------
+# 5. MISCELLANEOUS & PERFORMANCE
+# See: https://wiki.hyprland.org/Configuring/Variables/#misc
+# -------------------------------------------------------------------------------------------------
+misc {
+ force_default_wallpaper = 1 # Set to 0 to enable the anime mascot
+ disable_hyprland_logo = true
+ disable_splash_rendering = true
+}
+
+# -------------------------------------------------------------------------------------------------
+# 6. BINDS (Visual specific)
+# -------------------------------------------------------------------------------------------------
+binds {
+ allow_pin_fullscreen = true
+}
+
+# debug {
+# overlay = true
+# }
+# -------------------------------------------------------------------------------------------------
+# 7. SMART GAPS (Single Window Override)
+# Applied automatically when only 1 window is tiled or fullscreened on a workspace.
+# -------------------------------------------------------------------------------------------------
+$single_window_gap = 10
+workspace = w[tv1], gapsout:$single_window_gap, gapsin:0
+workspace = f[1], gapsout:$single_window_gap, gapsin:0
diff --git a/.config/hypr/edit_here/source/appearance.lua b/.config/hypr/edit_here/source/appearance.lua
new file mode 100644
index 00000000..b0da19cd
--- /dev/null
+++ b/.config/hypr/edit_here/source/appearance.lua
@@ -0,0 +1,125 @@
+-- =============================================================================
+-- USER CONFIGURATION: appearance.lua
+-- =============================================================================
+-- Add your custom appearance settings here.
+-- These will override or add to the defaults found in
+-- ~/.config/hypr/source/appearance.lua
+-- This file can also be edited with:
+-- dusky appearance (from the Rofi menu or Dusky Control Center)
+-- =============================================================================
+
+local home = os.getenv("HOME")
+
+-- THEME SOURCE: Load colors generated by Matugen
+dofile(home .. "/.config/matugen/generated/hyprland-colors.lua")
+
+-- -------------------------------------------------------------------------------------------------
+-- 1. GENERAL APPEARANCE — override defaults
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ general = {
+ gaps_in = 6,
+ gaps_out = 12,
+ gaps_workspaces = 0,
+ border_size = 2,
+
+ -- Colors from Matugen (globals set by hyprland-colors.lua above)
+ col = {
+ active_border = primary,
+ inactive_border = inverse_on_surface,
+ },
+
+ resize_on_border = false,
+ allow_tearing = true,
+ layout = "dwindle",
+
+ snap = {
+ enabled = false,
+ window_gap = 10,
+ monitor_gap = 10,
+ border_overlap = false,
+ },
+ },
+})
+
+-- -------------------------------------------------------------------------------------------------
+-- 2. DECORATION
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ decoration = {
+ rounding = 6,
+ rounding_power = 6.0,
+
+ active_opacity = 0.8,
+ inactive_opacity = 0.6,
+ fullscreen_opacity = 1.0,
+
+ dim_inactive = true,
+ dim_strength = 0.2,
+ dim_special = 0.8,
+
+ shadow = {
+ enabled = true,
+ range = 35,
+ render_power = 2,
+ sharp = false,
+ scale = 1.0,
+ color = "rgba(1a1a1aee)",
+ },
+
+ blur = {
+ enabled = true,
+ size = 4,
+ passes = 2,
+ new_optimizations = true,
+ ignore_opacity = true,
+ xray = true,
+
+ noise = 0.0217,
+ contrast = 0.8916,
+ brightness = 0.8172,
+ vibrancy = 0.1696,
+
+ popups = false,
+ },
+ },
+})
+
+-- -------------------------------------------------------------------------------------------------
+-- 3. ANIMATIONS — load the currently active preset
+-- -------------------------------------------------------------------------------------------------
+dofile(home .. "/.config/hypr/source/animations/active/active.lua")
+
+-- -------------------------------------------------------------------------------------------------
+-- 4. LAYOUTS
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ dwindle = { preserve_split = true },
+ master = { new_status = "master" },
+})
+
+-- -------------------------------------------------------------------------------------------------
+-- 5. MISCELLANEOUS & PERFORMANCE
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ misc = {
+ force_default_wallpaper = 1,
+ disable_hyprland_logo = true,
+ disable_splash_rendering = true,
+ },
+})
+
+-- -------------------------------------------------------------------------------------------------
+-- 6. BINDS (Visual specific)
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ binds = { allow_pin_fullscreen = true },
+})
+
+-- -------------------------------------------------------------------------------------------------
+-- 7. SMART GAPS (Single Window Override)
+-- Applied automatically when only 1 window is tiled or fullscreened on a workspace.
+-- -------------------------------------------------------------------------------------------------
+local single_window_gap = 10
+hl.workspace_rule({ workspace = "w[tv1]", gaps_out = single_window_gap, gaps_in = 0 })
+hl.workspace_rule({ workspace = "f[1]", gaps_out = single_window_gap, gaps_in = 0 })
diff --git a/.config/hypr/edit_here/source/autostart.conf.deprecated b/.config/hypr/edit_here/source/autostart.conf.deprecated
new file mode 100644
index 00000000..3cbcd0cd
--- /dev/null
+++ b/.config/hypr/edit_here/source/autostart.conf.deprecated
@@ -0,0 +1,18 @@
+# ==============================================================================
+# USER CONFIGURATION: autostart.conf
+# ==============================================================================
+# Add your custom settings for autostart here.
+# These will override or add to the defaults found in ~/.config/hypr/source/autostart.conf
+# ==============================================================================
+
+# Set pipewire buffer size to 128
+exec-once = pw-metadata -n settings 0 clock.force-quantum 128
+
+# Autostart solaar
+exec-once = solaar --window=hide
+
+# Create the headless output (it will be HEADLESS-2 based on your logs)
+exec-once = hyprctl output create headless
+
+# Start Sunshine as a child process so it inherits the socket signature
+exec-once = bash -c "sleep 2 && sunshine"
diff --git a/.config/hypr/edit_here/source/autostart.lua b/.config/hypr/edit_here/source/autostart.lua
new file mode 100644
index 00000000..2a93f037
--- /dev/null
+++ b/.config/hypr/edit_here/source/autostart.lua
@@ -0,0 +1,30 @@
+-- =============================================================================
+-- USER CONFIGURATION: autostart.lua
+-- =============================================================================
+-- Add your custom autostart entries here.
+-- These will override or add to the defaults found in
+-- ~/.config/hypr/source/autostart.lua
+-- =============================================================================
+
+local home = os.getenv("HOME")
+
+-- Set pipewire buffer size to 128 (reduces audio latency)
+hl.on("hyprland.start", function()
+ hl.exec_cmd("pw-metadata -n settings 0 clock.force-quantum 128")
+end)
+
+-- Autostart solaar (Logitech peripheral manager) — hidden in tray
+hl.on("hyprland.start", function()
+ hl.exec_cmd("solaar --window=hide")
+end)
+
+-- Create a headless virtual output (used for Sunshine/Moonlight streaming)
+-- It will appear as HEADLESS-2 based on your monitor config
+hl.on("hyprland.start", function()
+ hl.exec_cmd("hyprctl output create headless")
+end)
+
+-- Start Sunshine as a child process so it inherits the Hyprland socket signature
+hl.on("hyprland.start", function()
+ hl.exec_cmd("bash -c 'sleep 2 && sunshine'")
+end)
diff --git a/.config/hypr/edit_here/source/default_apps.conf.deprecated b/.config/hypr/edit_here/source/default_apps.conf.deprecated
new file mode 100644
index 00000000..2dd2d795
--- /dev/null
+++ b/.config/hypr/edit_here/source/default_apps.conf.deprecated
@@ -0,0 +1,13 @@
+# ==============================================================================
+# USER CONFIGURATION: default_apps.conf
+# ==============================================================================
+# Override default applications here.
+# These variables are sourced at the very top of hyprland.conf so they
+# are available for use in all other configuration files.
+# ==============================================================================
+
+$terminal = kitty
+$fileManager = nemo
+$menu = rofi -show drun
+$browser = firefox
+$textEditor = gnome-text-editor
diff --git a/.config/hypr/edit_here/source/default_apps.lua b/.config/hypr/edit_here/source/default_apps.lua
new file mode 100644
index 00000000..d2d3d136
--- /dev/null
+++ b/.config/hypr/edit_here/source/default_apps.lua
@@ -0,0 +1,13 @@
+-- =============================================================================
+-- USER CONFIGURATION: default_apps.lua
+-- =============================================================================
+-- Override default applications here.
+-- These globals are set before all other config files load, so they are
+-- available everywhere.
+-- =============================================================================
+
+terminal = "kitty"
+fileManager = "nemo"
+menu = "rofi -show drun"
+browser = "firefox"
+textEditor = "gnome-text-editor"
diff --git a/.config/hypr/edit_here/source/environment_variables.conf.deprecated b/.config/hypr/edit_here/source/environment_variables.conf.deprecated
new file mode 100644
index 00000000..cd1830c4
--- /dev/null
+++ b/.config/hypr/edit_here/source/environment_variables.conf.deprecated
@@ -0,0 +1,8 @@
+# ==============================================================================
+# USER CONFIGURATION: environment_variables.conf
+# ==============================================================================
+# Add your custom settings for environment_variables here.
+# These will override or add to the defaults found in ~/.config/hypr/source/environment_variables.conf
+# NOTE: it's strongly advised to place your environment variables in the uwsm files in ~/.config/uwsm/{env,env-hyprland}
+# ==============================================================================
+
diff --git a/.config/hypr/edit_here/source/environment_variables.lua b/.config/hypr/edit_here/source/environment_variables.lua
new file mode 100644
index 00000000..5d8abf52
--- /dev/null
+++ b/.config/hypr/edit_here/source/environment_variables.lua
@@ -0,0 +1,11 @@
+-- =============================================================================
+-- USER CONFIGURATION: environment_variables.lua
+-- =============================================================================
+-- Add your custom environment variables here.
+-- These will override or add to the defaults found in
+-- ~/.config/hypr/source/environment_variables.lua
+--
+-- NOTE: It is strongly advised to place environment variables in UWSM files:
+-- ~/.config/uwsm/env (compositor-agnostic variables)
+-- ~/.config/uwsm/env-hyprland (Hyprland-specific variables)
+-- =============================================================================
diff --git a/.config/hypr/edit_here/source/input.conf.deprecated b/.config/hypr/edit_here/source/input.conf.deprecated
new file mode 100644
index 00000000..17878540
--- /dev/null
+++ b/.config/hypr/edit_here/source/input.conf.deprecated
@@ -0,0 +1,156 @@
+# ==============================================================================
+# USER CONFIGURATION: input.conf
+# ==============================================================================
+# Add your custom settings for input here.
+# These will override or add to the defaults found in ~/.config/hypr/source/input.conf
+# This file can also be edited with dusky input from the rofi menu or from dusky control center
+# ==============================================================================
+# -------------------------------------------------------------------------------------------------
+# 1. KEYBOARD & LANGUAGE
+# -------------------------------------------------------------------------------------------------
+input {
+ kb_layout = us
+
+ # TUI: Dropdown - Common options like "caps:escape", "grp:alt_shift_toggle"
+ # This is a high-value configuration for developers.
+ kb_options =
+
+ resolve_binds_by_sym = false
+ numlock_by_default = true
+
+ # TUI: Slider [10 - 100]
+ repeat_rate = 35
+
+ # TUI: Slider [100 - 1000]
+ repeat_delay = 250
+}
+
+# -------------------------------------------------------------------------------------------------
+# 2. MOUSE & POINTER ACCELERATION
+# -------------------------------------------------------------------------------------------------
+input {
+ # 0: Cursor movement doesn't change focus
+ # 1: Cursor movement changes focus to window under cursor (Default)
+ # 2: Detached focus (Click to focus keyboard, mouse follows independently)
+ # 3: Completely separate focus
+ follow_mouse = 1
+
+ # TUI: Slider [-1.0 to 1.0]
+ sensitivity = -0.4
+
+ # TUI: Dropdown [flat, adaptive, custom]
+ # "Adaptive" is generally better for touchpads/desktop use. "Flat" for gaming.
+ accel_profile = flat
+
+ # TUI: Toggle [true/false] - "Raw Input" for gamers.
+ # Bypasses most pointer settings. Critical for high-end mice.
+ force_no_accel = true
+
+ # TUI: Toggle [true/false]
+ left_handed = false
+
+ # TUI: Toggle [true/false] - Useful for preventing focus stealing
+ mouse_refocus = true
+}
+
+# -------------------------------------------------------------------------------------------------
+# 3. SCROLLING & TRACKBALLS
+# -------------------------------------------------------------------------------------------------
+input {
+ # TUI: Toggle [true/false] - "Natural Scrolling" (MacOS style) for mice
+ natural_scroll = false
+
+ # TUI: Dropdown [2fg, edge, on_button_down, no_scroll]
+ # Vital for trackball users.
+ scroll_method = 2fg
+
+ # Only relevant if scroll_method is on_button_down
+ scroll_button = 0
+ scroll_button_lock = false
+}
+
+# -------------------------------------------------------------------------------------------------
+# 4. TOUCHPAD
+# -------------------------------------------------------------------------------------------------
+input {
+ touchpad {
+ # TUI: Toggle [true/false]
+ natural_scroll = true
+
+ # TUI: Toggle [true/false] - "Disable while typing"
+ disable_while_typing = true
+
+ # TUI: Toggle [true/false] - "Tap to click"
+ tap-to-click = true
+
+ # TUI: Toggle [true/false] - "Mac-style Right Click"
+ # true = 2-finger click is right click usually.
+ # false = Physical click on bottom-right is right click.
+ clickfinger_behavior = false
+
+ # TUI: Toggle [true/false]
+ drag_lock = false
+ }
+}
+
+# -------------------------------------------------------------------------------------------------
+# 5. CURSOR BEHAVIOR & RENDERING
+# -------------------------------------------------------------------------------------------------
+cursor {
+ # TUI: Toggle [true/false] - Sync XCursor theme with GSettings
+ sync_gsettings_theme = true
+
+ # TUI: Dropdown [0, 1, 2] - CRITICAL for Nvidia/VMs
+ # 0 = Use HW cursors (Performance)
+ # 1 = Force SW cursors (Compatibility / Fixes disappearing cursor)
+ # 2 = Auto (Disable when tearing)
+ no_hardware_cursors = 2
+
+ # TUI: Dropdown [0, 1, 2] - Nvidia Specific optimization
+ # 0 = Off, 1 = On, 2 = Auto
+ use_cpu_buffer = 2
+
+ # TUI: Toggle [true/false] - Hides cursor when typing
+ # Great for "distraction free" coding.
+ hide_on_key_press = false
+
+ # TUI: Slider [0 - 60] - Hide cursor after X seconds of inactivity (0=never)
+ inactive_timeout = 0
+
+ # TUI: Dropdown [0, 1, 2] - Workflow Preference
+ # 0 = Disabled (Cursor stays put)
+ # 1 = Enabled (Cursor moves to center of focused window)
+ # 2 = Force
+ warp_on_change_workspace = 0
+
+ # TUI: Dropdown [0, 1, 2] - Gaming / VRR Specific
+ # Prevents framerate spikes in VRR games by pausing cursor updates
+ # 0 = Off, 1 = On, 2 = Auto
+ no_break_fs_vrr = 2
+
+ # TUI: Slider [1.0 - 5.0] - Accessibility / Presentation
+ # Sets the zoom level for the magnifier.
+ zoom_factor = 1.0
+}
+
+# -------------------------------------------------------------------------------------------------
+# 6. GESTURE PHYSICS (Tuning)
+# -------------------------------------------------------------------------------------------------
+# Note: The actual actions are in the dispatchers below.
+# This block controls the "feel" of the swipes.
+gestures {
+ # TUI: Slider [100 - 1000] - "Swipe Distance"
+ workspace_swipe_distance = 300
+
+ # TUI: Slider [0.0 - 1.0] - "Swipe Cancellation Threshold"
+ workspace_swipe_cancel_ratio = 0.5
+
+ # TUI: Toggle [true/false] - "Invert Swipe Direction"
+ workspace_swipe_invert = true
+
+ # TUI: Toggle [true/false] - "Swipe to Create New Workspace"
+ workspace_swipe_create_new = true
+
+ # TUI: Toggle [true/false] - "Swipe Forever" (Don't clamp at neighbors)
+ workspace_swipe_forever = false
+}
diff --git a/.config/hypr/edit_here/source/input.lua b/.config/hypr/edit_here/source/input.lua
new file mode 100644
index 00000000..33c241ae
--- /dev/null
+++ b/.config/hypr/edit_here/source/input.lua
@@ -0,0 +1,82 @@
+-- =============================================================================
+-- USER CONFIGURATION: input.lua
+-- =============================================================================
+-- Add your custom input settings here.
+-- These will override or add to the defaults found in
+-- ~/.config/hypr/source/input.lua
+-- This file can also be edited with:
+-- dusky input (from the Rofi menu or Dusky Control Center)
+-- =============================================================================
+
+-- -------------------------------------------------------------------------------------------------
+-- 1. KEYBOARD & LANGUAGE
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ input = {
+ kb_layout = "us",
+ kb_options = "", -- e.g. "caps:escape", "grp:alt_shift_toggle"
+
+ resolve_binds_by_sym = false,
+ numlock_by_default = true,
+ repeat_rate = 35,
+ repeat_delay = 250,
+
+ -- -----------------------------------------------------------------
+ -- 2. MOUSE & POINTER ACCELERATION
+ -- -----------------------------------------------------------------
+ follow_mouse = 1,
+ sensitivity = -0.2,
+ accel_profile = "flat",
+ force_no_accel = true,
+ left_handed = false,
+ mouse_refocus = true,
+
+ -- -----------------------------------------------------------------
+ -- 3. SCROLLING & TRACKBALLS
+ -- -----------------------------------------------------------------
+ natural_scroll = false,
+ scroll_method = "2fg",
+ scroll_button = 0,
+ scroll_button_lock = false,
+
+ -- -----------------------------------------------------------------
+ -- 4. TOUCHPAD
+ -- -----------------------------------------------------------------
+ touchpad = {
+ natural_scroll = true,
+ disable_while_typing = true,
+ tap_to_click = true,
+ clickfinger_behavior = false,
+ drag_lock = false,
+ },
+ },
+})
+
+-- -------------------------------------------------------------------------------------------------
+-- 5. CURSOR BEHAVIOR & RENDERING
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ cursor = {
+ sync_gsettings_theme = true,
+ no_hardware_cursors = 2,
+ use_cpu_buffer = 2,
+ hide_on_key_press = false,
+ inactive_timeout = 0,
+ warp_on_change_workspace = 0,
+ no_break_fs_vrr = 2,
+ zoom_factor = 1.0,
+ },
+})
+
+-- -------------------------------------------------------------------------------------------------
+-- 6. GESTURE PHYSICS (Tuning)
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ gestures = {
+ workspace_swipe_distance = 300,
+ workspace_swipe_cancel_ratio = 0.5,
+ workspace_swipe_invert = true,
+ workspace_swipe_create_new = true,
+ workspace_swipe_forever = false,
+ },
+})
diff --git a/.config/hypr/edit_here/source/keybinds.conf.deprecated b/.config/hypr/edit_here/source/keybinds.conf.deprecated
new file mode 100644
index 00000000..9a76fae0
--- /dev/null
+++ b/.config/hypr/edit_here/source/keybinds.conf.deprecated
@@ -0,0 +1,39 @@
+# ==============================================================================
+# USER CONFIGURATION: keybinds.conf
+# ==============================================================================
+# Add your custom settings for keybinds here.
+# These will override or add to the defaults found in ~/.config/hypr/source/keybinds.conf
+# This file can also be edited with dusky keybinds manager from the rofi menu or from dusky control center
+# ==============================================================================
+
+# Auto-generated by FM Switcher
+bindd = $mainMod, E, File Manager, exec, uwsm-app $fileManager
+
+# Auto-generated by Browser Switcher
+bindd = $mainMod, W, Launch Browser, exec, uwsm-app -- $browser
+
+# Auto-generated by Text Editor Switcher
+bindd = $mainMod, R, Open Text Editor, exec, uwsm-app $textEditor
+
+# Auto-generated by Terminal Switcher
+bindd = $mainMod, Q, Launch Terminal, exec, uwsm-app -- $terminal
+
+# -- TERMINAL-CLIPBOARD-START --
+unbind = $mainMod, V
+bindd = $mainMod, V, Clipboard History, exec, $scripts/clipboard/close_terminal_clipboard.sh uwsm-app -- kitty --class terminal_clipboard.sh -e "$scripts/clipboard/terminal_clipboard.sh"
+# -- TERMINAL-CLIPBOARD-END --
+
+# =========================================
+# GAMING MODE (Submap Passthrough)
+# =========================================
+# Press Super + F12 to disable all Hyprland binds.
+bind = $mainMod, F12, submap, clean
+
+# This starts the "clean" submap where no other binds exist
+submap = clean
+
+# The ONLY keybind that works in this state is the one to exit it
+bind = $mainMod, F12, submap, reset
+
+# This resets back to the global Hyprland binds
+submap = reset
diff --git a/.config/hypr/edit_here/source/keybinds.lua b/.config/hypr/edit_here/source/keybinds.lua
new file mode 100644
index 00000000..ce760051
--- /dev/null
+++ b/.config/hypr/edit_here/source/keybinds.lua
@@ -0,0 +1,44 @@
+-- =============================================================================
+-- USER CONFIGURATION: keybinds.lua
+-- =============================================================================
+-- Add your custom keybinds here.
+-- These will override or add to the defaults found in
+-- ~/.config/hypr/source/keybinds.lua
+-- This file can also be edited with:
+-- dusky keybinds manager (from the Rofi menu or Dusky Control Center)
+-- =============================================================================
+
+local mainMod = "SUPER"
+local home = os.getenv("HOME")
+
+-- App variables come from edit_here/source/default_apps.lua (loaded first)
+
+-- Auto-generated by FM Switcher
+hl.bind(mainMod .. " + E", hl.dsp.exec_cmd("uwsm-app " .. fileManager), { description = "File Manager" })
+
+-- Auto-generated by Browser Switcher
+hl.bind(mainMod .. " + W", hl.dsp.exec_cmd("uwsm-app -- " .. browser), { description = "Launch Browser" })
+
+-- Auto-generated by Text Editor Switcher
+hl.bind(mainMod .. " + R", hl.dsp.exec_cmd("uwsm-app " .. textEditor), { description = "Open Text Editor" })
+
+-- Auto-generated by Terminal Switcher
+hl.bind(mainMod .. " + Q", hl.dsp.exec_cmd("uwsm-app -- " .. terminal), { description = "Launch Terminal" })
+
+-- Override the base clipboard bind: terminal-based clipboard manager
+-- First remove the base bind (rofi clipboard), then set the terminal one:
+hl.unbind(mainMod .. " + V")
+hl.bind(mainMod .. " + V",
+ hl.dsp.exec_cmd(home .. "/user_scripts/clipboard/close_terminal_clipboard.sh uwsm-app -- kitty --class terminal_clipboard.sh -e " .. home .. "/user_scripts/clipboard/terminal_clipboard.sh"),
+ { description = "Clipboard History" })
+
+-- =========================================
+-- GAMING MODE (Submap Passthrough)
+-- =========================================
+-- Press Super + F12 to disable all Hyprland binds.
+hl.bind(mainMod .. " + F12", hl.dsp.submap("clean"))
+
+hl.define_submap("clean", function()
+ -- The ONLY keybind that works in this state is the one to exit it
+ hl.bind(mainMod .. " + F12", hl.dsp.submap("reset"))
+end)
diff --git a/.config/hypr/edit_here/source/monitors.conf.deprecated b/.config/hypr/edit_here/source/monitors.conf.deprecated
new file mode 100644
index 00000000..dbda65d8
--- /dev/null
+++ b/.config/hypr/edit_here/source/monitors.conf.deprecated
@@ -0,0 +1,11 @@
+# Generated by Dusky Monitor Wizard on 20260321_114029
+
+# Global Settings
+debug {
+ vfr = true
+}
+
+# Monitor Rules
+monitor = DP-1, 1920x1080@144.00, 0x0, 1
+
+monitor = HEADLESS-2, disable
diff --git a/.config/hypr/edit_here/source/monitors.lua b/.config/hypr/edit_here/source/monitors.lua
new file mode 100644
index 00000000..76d368fc
--- /dev/null
+++ b/.config/hypr/edit_here/source/monitors.lua
@@ -0,0 +1,7 @@
+
+-- Global Settings
+hl.config({ debug = { vfr = true } })
+
+-- Monitor Rules
+hl.monitor({ output = "DP-1", mode = "1920x1080@144.00", position = "0x0", scale = 1.00, bitdepth = 10 })
+hl.monitor({ output = "HEADLESS-2", disabled = true })
diff --git a/.config/hypr/edit_here/source/plugins.conf.deprecated b/.config/hypr/edit_here/source/plugins.conf.deprecated
new file mode 100644
index 00000000..8d4b2e89
--- /dev/null
+++ b/.config/hypr/edit_here/source/plugins.conf.deprecated
@@ -0,0 +1,7 @@
+# ==============================================================================
+# USER CONFIGURATION: plugins.conf
+# ==============================================================================
+# Add your custom settings for plugins here.
+# These will override or add to the defaults found in ~/.config/hypr/source/plugins.conf
+# ==============================================================================
+
diff --git a/.config/hypr/edit_here/source/plugins.lua b/.config/hypr/edit_here/source/plugins.lua
new file mode 100644
index 00000000..31fab932
--- /dev/null
+++ b/.config/hypr/edit_here/source/plugins.lua
@@ -0,0 +1,7 @@
+-- =============================================================================
+-- USER CONFIGURATION: plugins.lua
+-- =============================================================================
+-- Add your custom plugin settings here.
+-- These will override or add to the defaults found in
+-- ~/.config/hypr/source/plugins.lua
+-- =============================================================================
diff --git a/.config/hypr/edit_here/source/window_rules.conf.deprecated b/.config/hypr/edit_here/source/window_rules.conf.deprecated
new file mode 100644
index 00000000..bdb3588f
--- /dev/null
+++ b/.config/hypr/edit_here/source/window_rules.conf.deprecated
@@ -0,0 +1,10 @@
+# ==============================================================================
+# USER CONFIGURATION: window_rules.conf
+# ==============================================================================
+# Add your custom settings for window_rules here.
+# These will override or add to the defaults found in ~/.config/hypr/source/window_rules.conf
+# ==============================================================================
+
+# force emulators to bypass tiling and hit fullscreen immediately
+windowrule = match:class ^(com.libretro.RetroArch)$, fullscreen on, idle_inhibit always
+windowrule = match:class ^(info.cemu.Cemu)$, fullscreen on, idle_inhibit always
diff --git a/.config/hypr/edit_here/source/window_rules.lua b/.config/hypr/edit_here/source/window_rules.lua
new file mode 100644
index 00000000..06a6ad33
--- /dev/null
+++ b/.config/hypr/edit_here/source/window_rules.lua
@@ -0,0 +1,25 @@
+-- =============================================================================
+-- USER CONFIGURATION: window_rules.lua
+-- =============================================================================
+-- Add your custom window rules here.
+-- These will override or add to the defaults found in
+-- ~/.config/hypr/source/window_rules.lua
+-- =============================================================================
+
+hl.config({
+ layerrule = {
+ -- Disable selection-tool animation during area screenshots
+ "noanim, ^selection$"
+ },
+
+ windowrulev2 = {
+ -- Force emulators to bypass tiling and hit fullscreen immediately
+ "fullscreen, class:^(com.libretro.RetroArch)$",
+ "fullscreen, class:^(info.cemu.Cemu)$",
+
+ -- If that truncated 'i>' was 'idleinhibit focus', you just add
+ -- another string for the same class like this:
+ "idleinhibit focus, class:^(com.libretro.RetroArch)$",
+ "idleinhibit focus, class:^(info.cemu.Cemu)$"
+ }
+})
diff --git a/.config/hypr/edit_here/source/workspace_rules.conf.deprecated b/.config/hypr/edit_here/source/workspace_rules.conf.deprecated
new file mode 100644
index 00000000..3f0cbbc1
--- /dev/null
+++ b/.config/hypr/edit_here/source/workspace_rules.conf.deprecated
@@ -0,0 +1,82 @@
+# ==============================================================================
+# USER CONFIGURATION: workspace_rules.conf
+# ==============================================================================
+# Add your custom rules for workspace here.
+# These will override or add to the defaults found in :
+# ~/.config/hypr/source/workspace_rules.conf
+#
+# This file can also be edited with dusky workspace manager tui,
+# which can be found in dusky control center
+# ==============================================================================
+# USER CONFIGURATION: workspace_rules.conf
+# Managed by Dusky TUI - Granular Matrix v4.4.1
+# ==============================================================================
+
+# --- Global Rules ---
+$global_layout = dwindle
+workspace = r[11-99], layout:$global_layout
+
+# --- Ephemeral Global Override (Resets on reboot) ---
+$ephemeral_layout = monocle
+$ephemeral_enabled = false
+
+# --- Individual Workspaces (1-10) ---
+$ws1_layout = dwindle
+$ws1_persistent = false
+$ws1_master_orient = left
+$ws1_scroll_dir = right
+workspace = 1, layout:$ws1_layout, persistent:$ws1_persistent, layoutopt:orientation:$ws1_master_orient, layoutopt:direction:$ws1_scroll_dir
+
+$ws2_layout = dwindle
+$ws2_persistent = false
+$ws2_master_orient = left
+$ws2_scroll_dir = right
+workspace = 2, layout:$ws2_layout, persistent:$ws2_persistent, layoutopt:orientation:$ws2_master_orient, layoutopt:direction:$ws2_scroll_dir
+
+$ws3_layout = dwindle
+$ws3_persistent = false
+$ws3_master_orient = left
+$ws3_scroll_dir = right
+workspace = 3, layout:$ws3_layout, persistent:$ws3_persistent, layoutopt:orientation:$ws3_master_orient, layoutopt:direction:$ws3_scroll_dir
+
+$ws4_layout = dwindle
+$ws4_persistent = false
+$ws4_master_orient = left
+$ws4_scroll_dir = right
+workspace = 4, layout:$ws4_layout, persistent:$ws4_persistent, layoutopt:orientation:$ws4_master_orient, layoutopt:direction:$ws4_scroll_dir
+
+$ws5_layout = dwindle
+$ws5_persistent = false
+$ws5_master_orient = left
+$ws5_scroll_dir = right
+workspace = 5, layout:$ws5_layout, persistent:$ws5_persistent, layoutopt:orientation:$ws5_master_orient, layoutopt:direction:$ws5_scroll_dir
+
+$ws6_layout = dwindle
+$ws6_persistent = false
+$ws6_master_orient = left
+$ws6_scroll_dir = right
+workspace = 6, layout:$ws6_layout, persistent:$ws6_persistent, layoutopt:orientation:$ws6_master_orient, layoutopt:direction:$ws6_scroll_dir
+
+$ws7_layout = dwindle
+$ws7_persistent = false
+$ws7_master_orient = left
+$ws7_scroll_dir = right
+workspace = 7, layout:$ws7_layout, persistent:$ws7_persistent, layoutopt:orientation:$ws7_master_orient, layoutopt:direction:$ws7_scroll_dir
+
+$ws8_layout = dwindle
+$ws8_persistent = false
+$ws8_master_orient = left
+$ws8_scroll_dir = right
+workspace = 8, layout:$ws8_layout, persistent:$ws8_persistent, layoutopt:orientation:$ws8_master_orient, layoutopt:direction:$ws8_scroll_dir
+
+$ws9_layout = dwindle
+$ws9_persistent = false
+$ws9_master_orient = left
+$ws9_scroll_dir = right
+workspace = 9, layout:$ws9_layout, persistent:$ws9_persistent, layoutopt:orientation:$ws9_master_orient, layoutopt:direction:$ws9_scroll_dir
+
+$ws10_layout = dwindle
+$ws10_persistent = false
+$ws10_master_orient = left
+$ws10_scroll_dir = right
+workspace = 10, layout:$ws10_layout, persistent:$ws10_persistent, layoutopt:orientation:$ws10_master_orient, layoutopt:direction:$ws10_scroll_dir
diff --git a/.config/hypr/edit_here/source/workspace_rules.lua b/.config/hypr/edit_here/source/workspace_rules.lua
new file mode 100644
index 00000000..a07b3b58
--- /dev/null
+++ b/.config/hypr/edit_here/source/workspace_rules.lua
@@ -0,0 +1,40 @@
+-- =============================================================================
+-- USER CONFIGURATION: workspace_rules.lua
+-- =============================================================================
+-- Add your custom workspace rules here.
+-- These will override or add to the defaults found in:
+-- ~/.config/hypr/source/workspace_rules.lua
+--
+-- Managed by Dusky TUI - Granular Matrix v4.4.1
+-- =============================================================================
+
+-- --- Global Rules ---
+local global_layout = "dwindle"
+hl.workspace_rule({ workspace = "r[11-99]", layout = global_layout })
+
+-- --- Ephemeral Global Override (Resets on reboot) ---
+-- local ephemeral_layout = "monocle"
+-- local ephemeral_enabled = false
+
+-- --- Individual Workspaces (1-10) ---
+local ws = {
+ { layout = "dwindle", persistent = false, master_orient = "left", scroll_dir = "right" },
+ { layout = "dwindle", persistent = false, master_orient = "left", scroll_dir = "right" },
+ { layout = "dwindle", persistent = false, master_orient = "left", scroll_dir = "right" },
+ { layout = "dwindle", persistent = false, master_orient = "left", scroll_dir = "right" },
+ { layout = "dwindle", persistent = false, master_orient = "left", scroll_dir = "right" },
+ { layout = "dwindle", persistent = false, master_orient = "left", scroll_dir = "right" },
+ { layout = "dwindle", persistent = false, master_orient = "left", scroll_dir = "right" },
+ { layout = "dwindle", persistent = false, master_orient = "left", scroll_dir = "right" },
+ { layout = "dwindle", persistent = false, master_orient = "left", scroll_dir = "right" },
+ { layout = "dwindle", persistent = false, master_orient = "left", scroll_dir = "right" },
+}
+
+for i, w in ipairs(ws) do
+ hl.workspace_rule({
+ workspace = tostring(i),
+ layout = w.layout,
+ persistent = w.persistent,
+ layout_opts = { orientation = w.master_orient, direction = w.scroll_dir },
+ })
+end
diff --git a/.config/hypr/hyprland.conf b/.config/hypr/hyprland.conf
deleted file mode 100644
index cc9fa24a..00000000
--- a/.config/hypr/hyprland.conf
+++ /dev/null
@@ -1,78 +0,0 @@
-source = ~/.config/hypr/edit_here/source/default_apps.conf
-
-
-
-
-
-# DO NOT EDIT THIS FILE, if you want to configure something, edit the file
-# at this location. ~/.config/hypr/edit_here/
-
-
-
-
-
-# -----------------------------------------------------
-# HYPRLAND MAIN CONFIGURATION
-# -----------------------------------------------------
-# User: [dusky]
-# System: UWSM Managed
-# -----------------------------------------------------
-
-# 1. MONITORS
-# Must be first. Everything (workspaces, scaling, bar positioning)
-# depends on the physical layout being established.
-source = ~/.config/hypr/source/monitors.conf
-
-# 2. PROGRAMS & ENVIRONMENT
-# (Note: Most ENV vars are handled by `~/.config/uwsm/env` files)
-# If you have Hyprland-specific vars that UWSM shouldn't see, put them here.
-# This is also a good place to define $terminal, $fileManager, etc.
-# I am assuming 'permissions.conf' contains Polkit agents or specific envs.
-source = ~/.config/hypr/source/permissions.conf
-
-# 3. PLUGINS
-# Plugins must be loaded before "Appearance" or "Keybinds" if those files
-# reference plugin-specific variables or dispatchers.
-# source = ~/.config/hypr/source/plugins.conf
-
-# 4. INPUT DEVICES
-# Keyboard layouts, mouse sensitivity, and touchpad gestures.
-# Loaded early so keybinds can map correctly to devices if needed.
-source = ~/.config/hypr/source/input.conf
-
-
-# 5. APPEARANCE
-# General settings, decorations (rounding, blur), animations, and colors.
-source = ~/.config/hypr/source/appearance.conf
-
-# 6. WINDOW RULES & WORKSPACES
-# Defines how windows behave (floating, tiling, opacity) before they are opened.
-source = ~/.config/hypr/source/window_rules.conf
-
-# 7. KEYBINDINGS
-# Binds actions to keys. Loaded after everything else so all dispatchers
-# (plugin or standard) and rules are available.
-source = ~/.config/hypr/source/keybinds.conf
-
-# 8. AUTOSTART
-# Since you use UWSM, ensure this file uses `exec-once = uwsm-app -- ...`
-# We load this LATE so that when apps launch, the monitors, inputs,
-# and window rules are already fully applied.
-source = ~/.config/hypr/source/autostart.conf
-
-# 9. Environment Variables.
-source = ~/.config/hypr/source/environment_variables.conf
-
-# 10. Workspace Rules
-source = ~/.config/hypr/source/workspace_rules.conf
-
-# -----------------------------------------------------
-# LOCAL OVERRIDES (GIT IGNORED)
-# -----------------------------------------------------
-# This file is for machine-specific settings (e.g., a specific monitor
-# setup for work vs home) or testing changes without committing them.
-# It is loaded LAST to overwrite any setting above.
-
-
-# Source User Custom Config Overlay
-source = ~/.config/hypr/edit_here/hyprland.conf
diff --git a/.config/hypr/hyprland.lua b/.config/hypr/hyprland.lua
new file mode 100644
index 00000000..619d0167
--- /dev/null
+++ b/.config/hypr/hyprland.lua
@@ -0,0 +1,53 @@
+local home = os.getenv("HOME")
+local hypr = home .. "/.config/hypr"
+local src = hypr .. "/source"
+
+-- =============================================================================
+-- HYPRLAND MAIN CONFIGURATION — Lua entry point
+-- =============================================================================
+-- User: [dusky]
+-- System: UWSM Managed
+--
+-- DO NOT EDIT THIS FILE. Configure in: ~/.config/hypr/edit_here/
+-- =============================================================================
+
+-- Default apps — sourced first so $terminal / $browser etc. are available
+-- to every subsequent file.
+dofile(hypr .. "/edit_here/source/default_apps.lua")
+
+-- 1. MONITORS — must be first; everything (workspaces, scaling, bars)
+-- depends on the physical layout being established.
+dofile(src .. "/monitors.lua")
+
+-- 2. PERMISSIONS / ECOSYSTEM
+dofile(src .. "/permissions.lua")
+
+-- 3. PLUGINS (uncomment if you use hyprpm-managed plugins)
+-- dofile(src .. "/plugins.lua")
+
+-- 4. INPUT DEVICES — keyboard, mouse, touchpad, gestures
+dofile(src .. "/input.lua")
+
+-- 5. APPEARANCE — gaps, borders, decorations, animations, colors
+dofile(src .. "/appearance.lua")
+
+-- 6. WINDOW RULES & LAYER RULES
+dofile(src .. "/window_rules.lua")
+
+-- 7. KEYBINDINGS — loaded after rules so all dispatchers are available
+dofile(src .. "/keybinds.lua")
+
+-- 8. AUTOSTART — uses uwsm-app wrappers; loaded late so monitor/input/rules
+-- are already applied when apps launch.
+dofile(src .. "/autostart.lua")
+
+-- 9. ENVIRONMENT VARIABLES
+dofile(src .. "/environment_variables.lua")
+
+-- 10. WORKSPACE RULES
+dofile(src .. "/workspace_rules.lua")
+
+-- =============================================================================
+-- USER OVERRIDES — loaded last to take priority over everything above
+-- =============================================================================
+dofile(hypr .. "/edit_here/hyprland.lua")
diff --git a/.config/hypr/source/animations/active/active.conf.deprecated b/.config/hypr/source/animations/active/active.conf.deprecated
new file mode 100644
index 00000000..0d78374f
--- /dev/null
+++ b/.config/hypr/source/animations/active/active.conf.deprecated
@@ -0,0 +1,42 @@
+# -----------------------------------------------------
+# FLUID Dusky: The "Showcase" Edition
+# -----------------------------------------------------
+# Tuned daily driving: Slower, cinematic, and
+# perfectly fluid.
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # Goes past the target (1.1) and snaps back.
+ # Used for: Windows opening, Rofi, Workspaces.
+ bezier = overshot, 0.05, 0.9, 0.1, 1.1
+ # Standard ease-out. No bounce, just a clean stop.
+ # Used for: Fading opacity.
+ bezier = fluid, 0.25, 1, 0, 1
+ # A slightly tighter curve than fluid, good for closing things.
+ # Used for: Windows closing.
+ bezier = snap, 0.5, 0.9, 0.1, 1.05
+ # Starts fast, decelerates very slowly.
+ # Used for: Sliding menus and closing layers.
+ bezier = menu_decel, 0.1, 1, 0, 1
+ # Constant speed, no acceleration.
+ # Used for: Border color cycling.
+ bezier = liner, 1, 1, 1, 1
+
+ # -- Window Animations --
+ animation = windowsIn, 1, 7, overshot, popin 80%
+ animation = windowsOut, 1, 5, snap, popin 80%
+ animation = windowsMove, 1, 7, overshot, slide
+ animation = border, 1, 2, liner
+ animation = borderangle, 1, 40, liner, once
+ animation = fade, 1, 5, fluid
+ animation = layersIn, 1, 6, overshot, popin 70%
+ # Layers Close (specifidcally a fix for screenshots)
+ animation = layersOut, 0, 0, menu_decel, slide
+ animation = fadeLayersIn, 1, 5, menu_decel
+ animation = fadeLayersOut, 1, 4, menu_decel
+ animation = workspaces, 1, 8, overshot, slide
+ animation = specialWorkspace, 1, 8, overshot, slidevert
+
+}
diff --git a/.config/hypr/source/animations/active/active.lua b/.config/hypr/source/animations/active/active.lua
new file mode 100644
index 00000000..9b374f16
--- /dev/null
+++ b/.config/hypr/source/animations/active/active.lua
@@ -0,0 +1,23 @@
+-- -----------------------------------------------------
+-- FAST PRESET: High Performance / Low Latency (Horizontal)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+hl.curve("linear", { type = "bezier", points = { {0, 0}, {1, 1} } })
+hl.curve("md3_decel", { type = "bezier", points = { {0.05, 0.7}, {0.1, 1} } })
+hl.curve("instant", { type = "bezier", points = { {0, 1}, {0, 1} } })
+
+-- Windows: Instant snap with barely visible deceleration (~30ms)
+hl.animation({ leaf = "windows", enabled = true, speed = 2, bezier = "md3_decel", style = "slide" })
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 2, bezier = "md3_decel", style = "slide" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 2, bezier = "md3_decel", style = "slide" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 2, bezier = "md3_decel", style = "slide" })
+-- Border: Instant feedback
+hl.animation({ leaf = "border", enabled = true, speed = 1, bezier = "linear" })
+hl.animation({ leaf = "fade", enabled = true, speed = 2, bezier = "md3_decel" })
+-- Layers: Snappy but not jarring
+hl.animation({ leaf = "layers", enabled = true, speed = 2, bezier = "md3_decel", style = "slide" })
+-- Workspaces: Fast horizontal slide (~200ms)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 2.5, bezier = "md3_decel", style = "slide" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 2.5, bezier = "md3_decel", style = "slidevert" })
diff --git a/.config/hypr/source/animations/disable.conf.deprecated b/.config/hypr/source/animations/disable.conf.deprecated
new file mode 100644
index 00000000..23143da4
--- /dev/null
+++ b/.config/hypr/source/animations/disable.conf.deprecated
@@ -0,0 +1,8 @@
+
+# // ▄▀█ █▄░█ █ █▀▄▀█ ▄▀█ ▀█▀ █ █▀█ █▄░█
+# // █▀█ █░▀█ █ █░▀░█ █▀█ ░█░ █ █▄█ █░▀█
+
+# See https://wiki.hyprland.org/Configuring/Animations/
+
+animations:enabled=false
+
diff --git a/.config/hypr/source/animations/disable.lua b/.config/hypr/source/animations/disable.lua
new file mode 100644
index 00000000..d08163c6
--- /dev/null
+++ b/.config/hypr/source/animations/disable.lua
@@ -0,0 +1,4 @@
+-- ANIMATION DISABLED PRESET
+-- See https://wiki.hypr.land/Configuring/Animations/
+
+hl.config({ animations = { enabled = false } })
diff --git a/.config/hypr/source/animations/fade.conf.deprecated b/.config/hypr/source/animations/fade.conf.deprecated
new file mode 100644
index 00000000..0e9c33a2
--- /dev/null
+++ b/.config/hypr/source/animations/fade.conf.deprecated
@@ -0,0 +1,43 @@
+# -----------------------------------------------------
+# FADE PRESET: Pure Opacity / Ethereal
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- Curves for Fading ---
+ bezier = sine, 0.5, 0.5, 0.5, 0.5
+ bezier = sharpFade, 0.33, 1, 0.68, 1
+ bezier = linear, 0, 0, 1, 1
+
+ # --- Animation Configs ---
+
+ # Windows: THE FIX
+ # Windows don't have a 'fade' style.
+ # We set them to 'popin 100%' (no scaling) and make them fast (but not instant,
+ # or the fade might be skipped).
+ # The actual visual "fade" is handled by the 'animation = fade' line below.
+ animation = windows, 1, 3, sharpFade, popin 100%
+ animation = windowsIn, 1, 3, sharpFade, popin 100%
+ animation = windowsOut, 1, 3, sharpFade, popin 100%
+
+ # Windows Move: Needs to slide to feel natural
+ animation = windowsMove, 1, 4, sine, slide
+
+ # Border: Pulse effect
+ animation = border, 1, 5, sine
+ animation = fade, 1, 5, sine
+
+ # Layers (Waybar, etc.): Dissolve in
+ # 'fade' IS valid for layers
+ animation = layers, 1, 4, sharpFade, fade
+ animation = layersIn, 1, 4, sharpFade, fade
+ animation = layersOut, 1, 2, sharpFade, fade
+ animation = fadeLayersIn, 1, 3, sharpFade
+ animation = fadeLayersOut, 1, 2, sharpFade
+
+ # Workspaces: Cross-Dissolve
+ # 'fade' IS valid for workspaces
+ animation = workspaces, 1, 6, sine, fade
+ animation = specialWorkspace, 1, 6, sine, fade
+}
diff --git a/.config/hypr/source/animations/fade.lua b/.config/hypr/source/animations/fade.lua
new file mode 100644
index 00000000..7dee8df9
--- /dev/null
+++ b/.config/hypr/source/animations/fade.lua
@@ -0,0 +1,28 @@
+-- -----------------------------------------------------
+-- FADE PRESET: Pure Opacity / Ethereal
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+hl.curve("sine", { type = "bezier", points = { {0.5, 0.5}, {0.5, 0.5} } })
+hl.curve("sharpFade", { type = "bezier", points = { {0.33, 1}, {0.68, 1} } })
+hl.curve("linear", { type = "bezier", points = { {0, 0}, {1, 1} } })
+
+-- Windows: popin 100% (no scaling) so the actual visual fade comes from 'fade'
+hl.animation({ leaf = "windows", enabled = true, speed = 3, bezier = "sharpFade", style = "popin 100%" })
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 3, bezier = "sharpFade", style = "popin 100%" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 3, bezier = "sharpFade", style = "popin 100%" })
+-- Windows Move: Needs to slide to feel natural
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 4, bezier = "sine", style = "slide" })
+-- Border: Pulse effect
+hl.animation({ leaf = "border", enabled = true, speed = 5, bezier = "sine" })
+hl.animation({ leaf = "fade", enabled = true, speed = 5, bezier = "sine" })
+-- Layers: Dissolve in
+hl.animation({ leaf = "layers", enabled = true, speed = 4, bezier = "sharpFade", style = "fade" })
+hl.animation({ leaf = "layersIn", enabled = true, speed = 4, bezier = "sharpFade", style = "fade" })
+hl.animation({ leaf = "layersOut", enabled = true, speed = 2, bezier = "sharpFade", style = "fade" })
+hl.animation({ leaf = "fadeLayersIn", enabled = true, speed = 3, bezier = "sharpFade" })
+hl.animation({ leaf = "fadeLayersOut", enabled = true, speed = 2, bezier = "sharpFade" })
+-- Workspaces: Cross-Dissolve
+hl.animation({ leaf = "workspaces", enabled = true, speed = 6, bezier = "sine", style = "fade" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 6, bezier = "sine", style = "fade" })
diff --git a/.config/hypr/source/animations/horizontal_bounce.conf.deprecated b/.config/hypr/source/animations/horizontal_bounce.conf.deprecated
new file mode 100644
index 00000000..7913f496
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_bounce.conf.deprecated
@@ -0,0 +1,31 @@
+# -----------------------------------------------------
+# POP PRESET: Bouncy, Gelatinous, Fun
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- Bouncy Curves ---
+ # High bounce (1.6 = 60% overshoot). Very exaggerated.
+ bezier = jelly, 0.1, 0.9, 0.1, 1.3
+ bezier = bounce, 0.1, 1.5, 0.2, 1.1
+
+ # --- Animation Configs ---
+
+ # Windows: They pop in from the center like bubbles
+ animation = windowsIn, 1, 6, jelly, popin 60%
+ animation = windowsOut, 1, 4, bounce, popin 60%
+ animation = windowsMove, 1, 6, jelly, slide
+
+ # Border
+ animation = border, 1, 10, jelly
+ animation = fade, 1, 5, jelly
+
+ # Layers
+ animation = layers, 1, 6, jelly, popin 10%
+
+ # Workspaces: Trampoline effect
+ animation = workspaces, 1, 7, jelly, slide
+ animation = specialWorkspace, 1, 7, jelly, slidevert
+
+}
diff --git a/.config/hypr/source/animations/horizontal_bounce.lua b/.config/hypr/source/animations/horizontal_bounce.lua
new file mode 100644
index 00000000..e4000553
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_bounce.lua
@@ -0,0 +1,22 @@
+-- -----------------------------------------------------
+-- POP PRESET: Bouncy, Gelatinous, Fun (Horizontal)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- High bounce (1.3 = 30% overshoot). Very exaggerated.
+hl.curve("jelly", { type = "bezier", points = { {0.1, 0.9}, {0.1, 1.3} } })
+hl.curve("bounce", { type = "bezier", points = { {0.1, 1.5}, {0.2, 1.1} } })
+
+-- Windows: Pop in from the center like bubbles
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 6, bezier = "jelly", style = "popin 60%" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 4, bezier = "bounce", style = "popin 60%" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 6, bezier = "jelly", style = "slide" })
+-- Border
+hl.animation({ leaf = "border", enabled = true, speed = 10, bezier = "jelly" })
+hl.animation({ leaf = "fade", enabled = true, speed = 5, bezier = "jelly" })
+-- Layers
+hl.animation({ leaf = "layers", enabled = true, speed = 6, bezier = "jelly", style = "popin 10%" })
+-- Workspaces: Trampoline effect (horizontal)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 7, bezier = "jelly", style = "slide" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 7, bezier = "jelly", style = "slidevert" })
diff --git a/.config/hypr/source/animations/horizontal_dusky.conf.deprecated b/.config/hypr/source/animations/horizontal_dusky.conf.deprecated
new file mode 100644
index 00000000..0d78374f
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_dusky.conf.deprecated
@@ -0,0 +1,42 @@
+# -----------------------------------------------------
+# FLUID Dusky: The "Showcase" Edition
+# -----------------------------------------------------
+# Tuned daily driving: Slower, cinematic, and
+# perfectly fluid.
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # Goes past the target (1.1) and snaps back.
+ # Used for: Windows opening, Rofi, Workspaces.
+ bezier = overshot, 0.05, 0.9, 0.1, 1.1
+ # Standard ease-out. No bounce, just a clean stop.
+ # Used for: Fading opacity.
+ bezier = fluid, 0.25, 1, 0, 1
+ # A slightly tighter curve than fluid, good for closing things.
+ # Used for: Windows closing.
+ bezier = snap, 0.5, 0.9, 0.1, 1.05
+ # Starts fast, decelerates very slowly.
+ # Used for: Sliding menus and closing layers.
+ bezier = menu_decel, 0.1, 1, 0, 1
+ # Constant speed, no acceleration.
+ # Used for: Border color cycling.
+ bezier = liner, 1, 1, 1, 1
+
+ # -- Window Animations --
+ animation = windowsIn, 1, 7, overshot, popin 80%
+ animation = windowsOut, 1, 5, snap, popin 80%
+ animation = windowsMove, 1, 7, overshot, slide
+ animation = border, 1, 2, liner
+ animation = borderangle, 1, 40, liner, once
+ animation = fade, 1, 5, fluid
+ animation = layersIn, 1, 6, overshot, popin 70%
+ # Layers Close (specifidcally a fix for screenshots)
+ animation = layersOut, 0, 0, menu_decel, slide
+ animation = fadeLayersIn, 1, 5, menu_decel
+ animation = fadeLayersOut, 1, 4, menu_decel
+ animation = workspaces, 1, 8, overshot, slide
+ animation = specialWorkspace, 1, 8, overshot, slidevert
+
+}
diff --git a/.config/hypr/source/animations/horizontal_dusky.lua b/.config/hypr/source/animations/horizontal_dusky.lua
new file mode 100644
index 00000000..e6448c67
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_dusky.lua
@@ -0,0 +1,32 @@
+-- -----------------------------------------------------
+-- FLUID Dusky: The "Showcase" Edition (Horizontal)
+-- -----------------------------------------------------
+-- Tuned daily driving: Slower, cinematic, and
+-- perfectly fluid.
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- Goes past the target (1.1) and snaps back.
+hl.curve("overshot", { type = "bezier", points = { {0.05, 0.9}, {0.1, 1.1} } })
+-- Standard ease-out. No bounce, just a clean stop.
+hl.curve("fluid", { type = "bezier", points = { {0.25, 1}, {0, 1} } })
+-- A slightly tighter curve than fluid, good for closing things.
+hl.curve("snap", { type = "bezier", points = { {0.5, 0.9}, {0.1, 1.05} } })
+-- Starts fast, decelerates very slowly.
+hl.curve("menu_decel", { type = "bezier", points = { {0.1, 1}, {0, 1} } })
+-- Constant speed, no acceleration.
+hl.curve("liner", { type = "bezier", points = { {1, 1}, {1, 1} } })
+
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 7, bezier = "overshot", style = "popin 80%" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 5, bezier = "snap", style = "popin 80%" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 7, bezier = "overshot", style = "slide" })
+hl.animation({ leaf = "border", enabled = true, speed = 2, bezier = "liner" })
+hl.animation({ leaf = "borderangle", enabled = true, speed = 40, bezier = "liner", style = "once" })
+hl.animation({ leaf = "fade", enabled = true, speed = 5, bezier = "fluid" })
+hl.animation({ leaf = "layersIn", enabled = true, speed = 6, bezier = "overshot", style = "popin 70%" })
+hl.animation({ leaf = "layersOut", enabled = false, speed = 0 })
+hl.animation({ leaf = "fadeLayersIn", enabled = true, speed = 5, bezier = "menu_decel" })
+hl.animation({ leaf = "fadeLayersOut", enabled = true, speed = 4, bezier = "menu_decel" })
+hl.animation({ leaf = "workspaces", enabled = true, speed = 8, bezier = "overshot", style = "slide" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 8, bezier = "overshot", style = "slidevert" })
diff --git a/.config/hypr/source/animations/horizontal_exagurated.conf.deprecated b/.config/hypr/source/animations/horizontal_exagurated.conf.deprecated
new file mode 100644
index 00000000..7c3d56b7
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_exagurated.conf.deprecated
@@ -0,0 +1,31 @@
+# -----------------------------------------------------
+# GELATIN PRESET: Maximum Wobble
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- The "Boing" Curve ---
+ # 1.7 overshoot is absolutely ridiculous.
+ bezier = boing, 0.4, 0.8, 0.2, 1.7
+ # A curve that dips below zero for "anticipation"
+ bezier = slingshot, 0.4, -0.4, 0, 1.2
+
+ # --- Animation Configs ---
+
+ # Windows: They pull back (slingshot) then fly in and wobble (boing)
+ animation = windowsIn, 1, 8, boing, popin 10%
+ animation = windowsOut, 1, 8, boing, popin 80%
+ animation = windowsMove, 1, 8, boing, slide
+
+ # Border: Even the borders pulse
+ animation = border, 1, 10, boing
+ animation = fade, 1, 5, boing
+
+ # Layers: Your Waybar will look like it's made of rubber
+ animation = layers, 1, 10, boing, slide
+
+ # Workspaces: The entire screen is a trampoline
+ animation = workspaces, 1, 10, boing, slide
+ animation = specialWorkspace, 1, 10, boing, slidevert
+}
diff --git a/.config/hypr/source/animations/horizontal_exagurated.lua b/.config/hypr/source/animations/horizontal_exagurated.lua
new file mode 100644
index 00000000..bae8615e
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_exagurated.lua
@@ -0,0 +1,23 @@
+-- -----------------------------------------------------
+-- GELATIN PRESET: Maximum Wobble (Horizontal)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- 1.7 overshoot is absolutely ridiculous.
+hl.curve("boing", { type = "bezier", points = { {0.4, 0.8}, {0.2, 1.7} } })
+-- A curve that dips below zero for "anticipation"
+hl.curve("slingshot", { type = "bezier", points = { {0.4, -0.4}, {0, 1.2} } })
+
+-- Windows: Pull back (slingshot) then fly in and wobble (boing)
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 8, bezier = "boing", style = "popin 10%" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 8, bezier = "boing", style = "popin 80%" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 8, bezier = "boing", style = "slide" })
+-- Border: Even the borders pulse
+hl.animation({ leaf = "border", enabled = true, speed = 10, bezier = "boing" })
+hl.animation({ leaf = "fade", enabled = true, speed = 5, bezier = "boing" })
+-- Layers: Rubber Waybar
+hl.animation({ leaf = "layers", enabled = true, speed = 10, bezier = "boing", style = "slide" })
+-- Workspaces: The entire screen is a trampoline (horizontal)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 10, bezier = "boing", style = "slide" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 10, bezier = "boing", style = "slidevert" })
diff --git a/.config/hypr/source/animations/horizontal_fast.conf.deprecated b/.config/hypr/source/animations/horizontal_fast.conf.deprecated
new file mode 100644
index 00000000..5715a3a4
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_fast.conf.deprecated
@@ -0,0 +1,34 @@
+# -----------------------------------------------------
+# FAST PRESET: High Performance / Low Latency
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- Linear / Sharp Curves ---
+ bezier = linear, 0, 0, 1, 1
+ bezier = md3_decel, 0.05, 0.7, 0.1, 1
+ bezier = instant, 0, 1, 0, 1
+
+ # --- Animation Configs ---
+
+ # Windows: Instant snap with barely visible deceleration
+ # Duration 2 = ~30ms. Blink and you miss it.
+ animation = windows, 1, 2, md3_decel, slide
+ animation = windowsIn, 1, 2, md3_decel, slide
+ animation = windowsOut, 1, 2, md3_decel, slide
+ animation = windowsMove, 1, 2, md3_decel, slide
+
+ # Border: Instant feedback
+ animation = border, 1, 1, linear
+ animation = fade, 1, 2, md3_decel
+
+ # Layers: Snappy but not jarring
+ animation = layers, 1, 2, md3_decel, slide
+
+ # Workspaces: Fast vertical slide (200ms)
+ # Enough context to see the movement, fast enough not to wait.
+ animation = workspaces, 1, 2.5, md3_decel, slide
+ animation = specialWorkspace, 1, 2.5, md3_decel, slidevert
+
+}
diff --git a/.config/hypr/source/animations/horizontal_fast.lua b/.config/hypr/source/animations/horizontal_fast.lua
new file mode 100644
index 00000000..9b374f16
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_fast.lua
@@ -0,0 +1,23 @@
+-- -----------------------------------------------------
+-- FAST PRESET: High Performance / Low Latency (Horizontal)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+hl.curve("linear", { type = "bezier", points = { {0, 0}, {1, 1} } })
+hl.curve("md3_decel", { type = "bezier", points = { {0.05, 0.7}, {0.1, 1} } })
+hl.curve("instant", { type = "bezier", points = { {0, 1}, {0, 1} } })
+
+-- Windows: Instant snap with barely visible deceleration (~30ms)
+hl.animation({ leaf = "windows", enabled = true, speed = 2, bezier = "md3_decel", style = "slide" })
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 2, bezier = "md3_decel", style = "slide" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 2, bezier = "md3_decel", style = "slide" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 2, bezier = "md3_decel", style = "slide" })
+-- Border: Instant feedback
+hl.animation({ leaf = "border", enabled = true, speed = 1, bezier = "linear" })
+hl.animation({ leaf = "fade", enabled = true, speed = 2, bezier = "md3_decel" })
+-- Layers: Snappy but not jarring
+hl.animation({ leaf = "layers", enabled = true, speed = 2, bezier = "md3_decel", style = "slide" })
+-- Workspaces: Fast horizontal slide (~200ms)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 2.5, bezier = "md3_decel", style = "slide" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 2.5, bezier = "md3_decel", style = "slidevert" })
diff --git a/.config/hypr/source/animations/horizontal_hallucination.conf.deprecated b/.config/hypr/source/animations/horizontal_hallucination.conf.deprecated
new file mode 100644
index 00000000..f9cbffb6
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_hallucination.conf.deprecated
@@ -0,0 +1,45 @@
+# -----------------------------------------------------
+# TRIP PRESET: Psychedelic, Wavy, Disorienting
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- The "Hallucination" Curves ---
+ # Starts by going backwards (-0.55), shoots way past target (1.55), then settles.
+ # This creates a massive "wobble" effect.
+ bezier = hallucination, 0.68, -0.55, 0.265, 1.55
+
+ # Slow, lazy wave for fading
+ bezier = dream, 0.4, 0, 0.2, 1
+
+ # Constant rotation
+ bezier = linear, 0, 0, 1, 1
+
+ # --- Animation Configs ---
+
+ # Windows: The "Breathing" Effect
+ # They shrink first, then explode in. Duration 9 makes it slow and deliberate.
+ animation = windowsIn, 1, 9, hallucination, popin 0%
+ animation = windowsOut, 1, 9, hallucination, popin 0%
+
+ # Windows Move: Swimming through syrup
+ animation = windowsMove, 1, 9, hallucination, slide
+
+ # Border: THE SPIN
+ # This makes your border colors rotate infinitely.
+ # (Requires gradient borders in 'general' settings to be visible)
+ animation = border, 1, 10, dream
+ animation = borderangle, 1, 100, linear, loop
+
+ # Fade: Long, slow dissolves
+ animation = fade, 1, 10, dream
+
+ # Layers: Drifting in from the void
+ animation = layers, 1, 8, dream, popin 50%
+
+ # Workspaces: The "Warp Tunnel"
+ # slidefade 80% creates a massive ghosting trail effect when switching.
+ animation = workspaces, 1, 12, dream, slidefade 80%
+ animation = specialWorkspace, 1, 12, dream, slidevertfade 80%
+}
diff --git a/.config/hypr/source/animations/horizontal_hallucination.lua b/.config/hypr/source/animations/horizontal_hallucination.lua
new file mode 100644
index 00000000..47c08312
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_hallucination.lua
@@ -0,0 +1,28 @@
+-- -----------------------------------------------------
+-- TRIP PRESET: Psychedelic, Wavy, Disorienting (Horizontal)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- Starts backwards (-0.55), shoots past target (1.55), then settles.
+hl.curve("hallucination", { type = "bezier", points = { {0.68, -0.55}, {0.265, 1.55} } })
+-- Slow, lazy wave for fading
+hl.curve("dream", { type = "bezier", points = { {0.4, 0}, {0.2, 1} } })
+-- Constant rotation
+hl.curve("linear", { type = "bezier", points = { {0, 0}, {1, 1} } })
+
+-- Windows: The "Breathing" Effect
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 9, bezier = "hallucination", style = "popin 0%" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 9, bezier = "hallucination", style = "popin 0%" })
+-- Windows Move: Swimming through syrup
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 9, bezier = "hallucination", style = "slide" })
+-- Border: THE SPIN
+hl.animation({ leaf = "border", enabled = true, speed = 10, bezier = "dream" })
+hl.animation({ leaf = "borderangle", enabled = true, speed = 100, bezier = "linear", style = "loop" })
+-- Fade: Long, slow dissolves
+hl.animation({ leaf = "fade", enabled = true, speed = 10, bezier = "dream" })
+-- Layers: Drifting in from the void
+hl.animation({ leaf = "layers", enabled = true, speed = 8, bezier = "dream", style = "popin 50%" })
+-- Workspaces: The "Warp Tunnel" (horizontal)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 12, bezier = "dream", style = "slidefade 80%" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 12, bezier = "dream", style = "slidevertfade 80%" })
diff --git a/.config/hypr/source/animations/horizontal_mechanical.conf.deprecated b/.config/hypr/source/animations/horizontal_mechanical.conf.deprecated
new file mode 100644
index 00000000..24e80ef9
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_mechanical.conf.deprecated
@@ -0,0 +1,33 @@
+# -----------------------------------------------------
+# RIGID PRESET: Mechanical, Stiff, Precision
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- Hard Curves ---
+ # The "Block" - constant speed then instant stop.
+ bezier = hard, 0, 1, 0, 1
+ # The "Piston" - fast acceleration, hard brake.
+ bezier = piston, 0.5, 0, 0.5, 1
+
+ # --- Animation Configs ---
+
+ # Windows: Slide in like metal plates
+ # No popin (scaling), just pure sliding.
+ animation = windows, 1, 4, hard, slide
+ animation = windowsMove, 1, 4, piston, slide
+
+ # Borders: Instant snap (flashing)
+ animation = border, 1, 1, hard
+ animation = fade, 1, 2, hard
+
+ # Layers: Mechanical entry
+ animation = layers, 1, 3, hard, slide
+
+ # Workspaces: Hydraulic Lift
+ # Slidevert with zero fade. It looks like a physical machine moving.
+ animation = workspaces, 1, 5, hard, slide
+ animation = specialWorkspace, 1, 5, hard, slidevert
+
+}
diff --git a/.config/hypr/source/animations/horizontal_mechanical.lua b/.config/hypr/source/animations/horizontal_mechanical.lua
new file mode 100644
index 00000000..6de84776
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_mechanical.lua
@@ -0,0 +1,22 @@
+-- -----------------------------------------------------
+-- RIGID PRESET: Mechanical, Stiff, Precision (Horizontal)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- The "Block" - constant speed then instant stop.
+hl.curve("hard", { type = "bezier", points = { {0, 1}, {0, 1} } })
+-- The "Piston" - fast acceleration, hard brake.
+hl.curve("piston", { type = "bezier", points = { {0.5, 0}, {0.5, 1} } })
+
+-- Windows: Slide in like metal plates (no popin/scaling, pure sliding)
+hl.animation({ leaf = "windows", enabled = true, speed = 4, bezier = "hard", style = "slide" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 4, bezier = "piston", style = "slide" })
+-- Borders: Instant snap (flashing)
+hl.animation({ leaf = "border", enabled = true, speed = 1, bezier = "hard" })
+hl.animation({ leaf = "fade", enabled = true, speed = 2, bezier = "hard" })
+-- Layers: Mechanical entry
+hl.animation({ leaf = "layers", enabled = true, speed = 3, bezier = "hard", style = "slide" })
+-- Workspaces: Hydraulic Press (horizontal)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 5, bezier = "hard", style = "slide" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 5, bezier = "hard", style = "slidevert" })
diff --git a/.config/hypr/source/animations/horizontal_minimal.conf.deprecated b/.config/hypr/source/animations/horizontal_minimal.conf.deprecated
new file mode 100644
index 00000000..9403d3a1
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_minimal.conf.deprecated
@@ -0,0 +1,37 @@
+animations {
+ enabled = true
+
+ # --------------------------------------------------------
+ # Bezier Curves
+ # --------------------------------------------------------
+ bezier = pro, 0.05, 0.9, 0.1, 1.0
+ bezier = snap, 0.05, 0.9, 0.1, 1.05
+
+ # --------------------------------------------------------
+ # Application Windows (Speed: 3 - Relaxed/Clear)
+ # --------------------------------------------------------
+ animation = windows, 1, 3, snap, popin 80%
+ animation = windowsOut, 1, 3, snap, popin 80%
+ animation = windowsMove, 1, 3, snap
+
+ # --------------------------------------------------------
+ # UI Layers: Rofi, Waybar (Speed: 2 - Snappy)
+ # --------------------------------------------------------
+ # This '2' is the key. It makes layers faster than windows.
+ # We use 'slide' generally, but can override direction in layer rules.
+ animation = layers, 1, 2, pro, slide
+ animation = fade, 1, 2, pro
+
+ # fix for screenshot gray capture
+ animation = layersOut, 0, 0,
+
+ animation = border, 1, 3, pro
+
+ # --------------------------------------------------------
+ # Workspaces (vertical Slide)
+ # --------------------------------------------------------
+ animation = workspaces, 1, 3, pro, slide
+
+ # Special Workspace (Scratchpad)
+ animation = specialWorkspace, 1, 3, pro, slidevert
+}
diff --git a/.config/hypr/source/animations/horizontal_minimal.lua b/.config/hypr/source/animations/horizontal_minimal.lua
new file mode 100644
index 00000000..1997e52c
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_minimal.lua
@@ -0,0 +1,22 @@
+-- -----------------------------------------------------
+-- MINIMAL PRESET: Clean & Snappy (Horizontal)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+hl.curve("pro", { type = "bezier", points = { {0.05, 0.9}, {0.1, 1.0} } })
+hl.curve("snap", { type = "bezier", points = { {0.05, 0.9}, {0.1, 1.05} } })
+
+-- Application Windows
+hl.animation({ leaf = "windows", enabled = true, speed = 3, bezier = "snap", style = "popin 80%" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 3, bezier = "snap", style = "popin 80%" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 3, bezier = "snap" })
+-- UI Layers: Rofi, Waybar
+hl.animation({ leaf = "layers", enabled = true, speed = 2, bezier = "pro", style = "slide" })
+hl.animation({ leaf = "fade", enabled = true, speed = 2, bezier = "pro" })
+-- Fix for screenshot gray capture
+hl.animation({ leaf = "layersOut", enabled = false, speed = 0 })
+hl.animation({ leaf = "border", enabled = true, speed = 3, bezier = "pro" })
+-- Workspaces (horizontal slide)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 3, bezier = "pro", style = "slide" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 3, bezier = "pro", style = "slidevert" })
diff --git a/.config/hypr/source/animations/horizontal_rage.conf.deprecated b/.config/hypr/source/animations/horizontal_rage.conf.deprecated
new file mode 100644
index 00000000..ce1aa523
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_rage.conf.deprecated
@@ -0,0 +1,35 @@
+# -----------------------------------------------------
+# SLAP PRESET: Aggressive, Instant Impact
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- The "Impact" Curve ---
+ # Starts at 0, goes straight to 1. No easing.
+ bezier = linear, 0, 0, 1, 1
+ # Accelerate only
+ bezier = accel, 1, 0, 1, 0.5
+
+ # --- Animation Configs ---
+
+ # Windows: Fast entry (3), hard stop.
+ animation = windowsIn, 1, 3, accel, slide
+ # Windows Out: They drop like rocks.
+ animation = windowsOut, 1, 3, accel, slide
+
+ # Windows Move: Zero smoothing.
+ animation = windowsMove, 1, 2, linear, slide
+
+ # Border
+ animation = border, 1, 1, linear
+ animation = fade, 1, 2, linear
+
+ # Layers
+ animation = layers, 1, 2, accel, slide
+
+ # Workspaces: Fast vertical slam
+ animation = workspaces, 1, 3, accel, slide
+ animation = specialWorkspace, 1, 3, accel, slidevert
+
+}
diff --git a/.config/hypr/source/animations/horizontal_rage.lua b/.config/hypr/source/animations/horizontal_rage.lua
new file mode 100644
index 00000000..9b241add
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_rage.lua
@@ -0,0 +1,24 @@
+-- -----------------------------------------------------
+-- SLAP PRESET: Aggressive, Instant Impact (Horizontal)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- Starts at 0, goes straight to 1. No easing.
+hl.curve("linear", { type = "bezier", points = { {0, 0}, {1, 1} } })
+-- Accelerate only
+hl.curve("accel", { type = "bezier", points = { {1, 0}, {1, 0.5} } })
+
+-- Windows: Fast entry (3), hard stop.
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 3, bezier = "accel", style = "slide" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 3, bezier = "accel", style = "slide" })
+-- Windows Move: Zero smoothing.
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 2, bezier = "linear", style = "slide" })
+-- Border
+hl.animation({ leaf = "border", enabled = true, speed = 1, bezier = "linear" })
+hl.animation({ leaf = "fade", enabled = true, speed = 2, bezier = "linear" })
+-- Layers
+hl.animation({ leaf = "layers", enabled = true, speed = 2, bezier = "accel", style = "slide" })
+-- Workspaces: Fast horizontal slam
+hl.animation({ leaf = "workspaces", enabled = true, speed = 3, bezier = "accel", style = "slide" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 3, bezier = "accel", style = "slidevert" })
diff --git a/.config/hypr/source/animations/horizontal_slowmotion.conf.deprecated b/.config/hypr/source/animations/horizontal_slowmotion.conf.deprecated
new file mode 100644
index 00000000..8dca35a2
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_slowmotion.conf.deprecated
@@ -0,0 +1,28 @@
+# -----------------------------------------------------
+# DRAMA PRESET: Slow Motion Cinematic
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- The "Suspense" Curve ---
+ # Starts incredibly slow, rushes in the middle, slows down again.
+ bezier = slowmo, 0.85, 0, 0.15, 1
+
+ # --- Animation Configs ---
+
+ # Windows: 15 (approx 1.5 seconds). It feels like forever.
+ animation = windows, 1, 15, slowmo, slide
+ animation = windowsMove, 1, 15, slowmo, slide
+
+ # Border: A slow, ominous color change
+ animation = border, 1, 20, slowmo
+ animation = fade, 1, 20, slowmo
+
+ # Layers
+ animation = layers, 1, 12, slowmo, slide
+
+ # Workspaces: A grand, sweeping scene transition
+ animation = workspaces, 1, 20, slowmo, slide
+ animation = specialWorkspace, 1, 20, slowmo, slidevert
+}
diff --git a/.config/hypr/source/animations/horizontal_slowmotion.lua b/.config/hypr/source/animations/horizontal_slowmotion.lua
new file mode 100644
index 00000000..e2b42762
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_slowmotion.lua
@@ -0,0 +1,20 @@
+-- -----------------------------------------------------
+-- DRAMA PRESET: Slow Motion Cinematic (Horizontal)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- Starts incredibly slow, rushes in the middle, slows down again.
+hl.curve("slowmo", { type = "bezier", points = { {0.85, 0}, {0.15, 1} } })
+
+-- Windows: ~1.5 seconds. It feels like forever.
+hl.animation({ leaf = "windows", enabled = true, speed = 15, bezier = "slowmo", style = "slide" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 15, bezier = "slowmo", style = "slide" })
+-- Border: A slow, ominous color change
+hl.animation({ leaf = "border", enabled = true, speed = 20, bezier = "slowmo" })
+hl.animation({ leaf = "fade", enabled = true, speed = 20, bezier = "slowmo" })
+-- Layers
+hl.animation({ leaf = "layers", enabled = true, speed = 12, bezier = "slowmo", style = "slide" })
+-- Workspaces: Grand, sweeping scene transition (horizontal)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 20, bezier = "slowmo", style = "slide" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 20, bezier = "slowmo", style = "slidevert" })
diff --git a/.config/hypr/source/animations/horizontal_vertical_air.conf.deprecated b/.config/hypr/source/animations/horizontal_vertical_air.conf.deprecated
new file mode 100644
index 00000000..b418a0d3
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_vertical_air.conf.deprecated
@@ -0,0 +1,33 @@
+# -----------------------------------------------------
+# AIR PRESET: Floaty, Soft, Ethereal
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- Soft Curves ---
+ # Slow start, slow end. Like a feather falling.
+ bezier = soft, 0.3, 0.3, 0.2, 1
+ bezier = softIn, 0.4, 0, 1, 1
+
+ # --- Animation Configs ---
+
+ # Windows: Drift in with opacity changes
+ # slidefade 15% gives it that "ghost" tail effect
+ animation = windowsIn, 1, 8, soft, slidefade 15%
+ animation = windowsOut, 1, 8, softIn, slidefade 15%
+ animation = windowsMove, 1, 8, soft, slidefade 15%
+
+ # Border & Fade: Very slow transition
+ animation = border, 1, 10, soft
+ animation = fade, 1, 10, soft
+
+ # Layers: Gentle drift
+ animation = layers, 1, 6, soft, slidefade 10%
+
+ # Workspaces: The "Elevator in the Clouds"
+ # Long duration (10), vertical slide with heavy fade.
+ animation = workspaces, 1, 10, soft, slidefade 40%
+ animation = specialWorkspace, 1, 10, soft, slidefadevert 40%
+
+}
diff --git a/.config/hypr/source/animations/horizontal_vertical_air.lua b/.config/hypr/source/animations/horizontal_vertical_air.lua
new file mode 100644
index 00000000..5048f1d5
--- /dev/null
+++ b/.config/hypr/source/animations/horizontal_vertical_air.lua
@@ -0,0 +1,23 @@
+-- -----------------------------------------------------
+-- AIR PRESET: Floaty, Soft, Ethereal (Horizontal)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- Slow start, slow end. Like a feather falling.
+hl.curve("soft", { type = "bezier", points = { {0.3, 0.3}, {0.2, 1} } })
+hl.curve("softIn", { type = "bezier", points = { {0.4, 0}, {1, 1} } })
+
+-- Windows: Drift in with opacity changes
+-- slidefade 15% gives it that "ghost" tail effect
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 8, bezier = "soft", style = "slidefade 15%" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 8, bezier = "softIn", style = "slidefade 15%" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 8, bezier = "soft", style = "slidefade 15%" })
+-- Border & Fade: Very slow transition
+hl.animation({ leaf = "border", enabled = true, speed = 10, bezier = "soft" })
+hl.animation({ leaf = "fade", enabled = true, speed = 10, bezier = "soft" })
+-- Layers: Gentle drift
+hl.animation({ leaf = "layers", enabled = true, speed = 6, bezier = "soft", style = "slidefade 10%" })
+-- Workspaces: Elevator in the Clouds (horizontal with heavy fade)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 10, bezier = "soft", style = "slidefade 40%" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 10, bezier = "soft", style = "slidefadevert 40%" })
diff --git a/.config/hypr/source/animations/vertical_bounce.conf.deprecated b/.config/hypr/source/animations/vertical_bounce.conf.deprecated
new file mode 100644
index 00000000..56227495
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_bounce.conf.deprecated
@@ -0,0 +1,31 @@
+# -----------------------------------------------------
+# POP PRESET: Bouncy, Gelatinous, Fun
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- Bouncy Curves ---
+ # High bounce (1.6 = 60% overshoot). Very exaggerated.
+ bezier = jelly, 0.1, 0.9, 0.1, 1.3
+ bezier = bounce, 0.1, 1.5, 0.2, 1.1
+
+ # --- Animation Configs ---
+
+ # Windows: They pop in from the center like bubbles
+ animation = windowsIn, 1, 6, jelly, popin 60%
+ animation = windowsOut, 1, 4, bounce, popin 60%
+ animation = windowsMove, 1, 6, jelly, slide
+
+ # Border
+ animation = border, 1, 10, jelly
+ animation = fade, 1, 5, jelly
+
+ # Layers
+ animation = layers, 1, 6, jelly, popin 10%
+
+ # Workspaces: Trampoline effect
+ animation = workspaces, 1, 7, jelly, slidevert
+ animation = specialWorkspace, 1, 7, jelly, slide
+
+}
diff --git a/.config/hypr/source/animations/vertical_bounce.lua b/.config/hypr/source/animations/vertical_bounce.lua
new file mode 100644
index 00000000..84be7337
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_bounce.lua
@@ -0,0 +1,22 @@
+-- -----------------------------------------------------
+-- POP PRESET: Bouncy, Gelatinous, Fun (Vertical)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- High bounce (1.3 = 30% overshoot). Very exaggerated.
+hl.curve("jelly", { type = "bezier", points = { {0.1, 0.9}, {0.1, 1.3} } })
+hl.curve("bounce", { type = "bezier", points = { {0.1, 1.5}, {0.2, 1.1} } })
+
+-- Windows: Pop in from the center like bubbles
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 6, bezier = "jelly", style = "popin 60%" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 4, bezier = "bounce", style = "popin 60%" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 6, bezier = "jelly", style = "slide" })
+-- Border
+hl.animation({ leaf = "border", enabled = true, speed = 10, bezier = "jelly" })
+hl.animation({ leaf = "fade", enabled = true, speed = 5, bezier = "jelly" })
+-- Layers
+hl.animation({ leaf = "layers", enabled = true, speed = 6, bezier = "jelly", style = "popin 10%" })
+-- Workspaces: Trampoline effect (vertical)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 7, bezier = "jelly", style = "slidevert" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 7, bezier = "jelly", style = "slide" })
diff --git a/.config/hypr/source/animations/vertical_dusky.conf.deprecated b/.config/hypr/source/animations/vertical_dusky.conf.deprecated
new file mode 100644
index 00000000..afa80af9
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_dusky.conf.deprecated
@@ -0,0 +1,42 @@
+# -----------------------------------------------------
+# FLUID Dusky: The "Showcase" Edition
+# -----------------------------------------------------
+# Tuned daily driving: Slower, cinematic, and
+# perfectly fluid.
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # Goes past the target (1.1) and snaps back.
+ # Used for: Windows opening, Rofi, Workspaces.
+ bezier = overshot, 0.05, 0.9, 0.1, 1.1
+ # Standard ease-out. No bounce, just a clean stop.
+ # Used for: Fading opacity.
+ bezier = fluid, 0.25, 1, 0, 1
+ # A slightly tighter curve than fluid, good for closing things.
+ # Used for: Windows closing.
+ bezier = snap, 0.5, 0.9, 0.1, 1.05
+ # Starts fast, decelerates very slowly.
+ # Used for: Sliding menus and closing layers.
+ bezier = menu_decel, 0.1, 1, 0, 1
+ # Constant speed, no acceleration.
+ # Used for: Border color cycling.
+ bezier = liner, 1, 1, 1, 1
+
+ # -- Window Animations --
+ animation = windowsIn, 1, 7, overshot, popin 80%
+ animation = windowsOut, 1, 5, snap, popin 80%
+ animation = windowsMove, 1, 7, overshot, slide
+ animation = border, 1, 2, liner
+ animation = borderangle, 1, 40, liner, once
+ animation = fade, 1, 5, fluid
+ animation = layersIn, 1, 6, overshot, popin 70%
+ # Layers Close (specifidcally a fix for screenshots)
+ animation = layersOut, 0, 0, menu_decel, slide
+ animation = fadeLayersIn, 1, 5, menu_decel
+ animation = fadeLayersOut, 1, 4, menu_decel
+ animation = workspaces, 1, 8, overshot, slidevert
+ animation = specialWorkspace, 1, 8, overshot, slide
+
+}
diff --git a/.config/hypr/source/animations/vertical_dusky.lua b/.config/hypr/source/animations/vertical_dusky.lua
new file mode 100644
index 00000000..4fcbdd59
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_dusky.lua
@@ -0,0 +1,33 @@
+-- -----------------------------------------------------
+-- FLUID Dusky: The "Showcase" Edition (Vertical)
+-- -----------------------------------------------------
+-- Tuned daily driving: Slower, cinematic, and
+-- perfectly fluid.
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- Goes past the target (1.1) and snaps back.
+hl.curve("overshot", { type = "bezier", points = { {0.05, 0.9}, {0.1, 1.1} } })
+-- Standard ease-out. No bounce, just a clean stop.
+hl.curve("fluid", { type = "bezier", points = { {0.25, 1}, {0, 1} } })
+-- A slightly tighter curve than fluid, good for closing things.
+hl.curve("snap", { type = "bezier", points = { {0.5, 0.9}, {0.1, 1.05} } })
+-- Starts fast, decelerates very slowly.
+hl.curve("menu_decel", { type = "bezier", points = { {0.1, 1}, {0, 1} } })
+-- Constant speed, no acceleration.
+hl.curve("liner", { type = "bezier", points = { {1, 1}, {1, 1} } })
+
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 7, bezier = "overshot", style = "popin 80%" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 5, bezier = "snap", style = "popin 80%" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 7, bezier = "overshot", style = "slide" })
+hl.animation({ leaf = "border", enabled = true, speed = 2, bezier = "liner" })
+hl.animation({ leaf = "borderangle", enabled = true, speed = 40, bezier = "liner", style = "once" })
+hl.animation({ leaf = "fade", enabled = true, speed = 5, bezier = "fluid" })
+hl.animation({ leaf = "layersIn", enabled = true, speed = 6, bezier = "overshot", style = "popin 70%" })
+hl.animation({ leaf = "layersOut", enabled = false, speed = 0 })
+hl.animation({ leaf = "fadeLayersIn", enabled = true, speed = 5, bezier = "menu_decel" })
+hl.animation({ leaf = "fadeLayersOut", enabled = true, speed = 4, bezier = "menu_decel" })
+-- Vertical workspaces
+hl.animation({ leaf = "workspaces", enabled = true, speed = 8, bezier = "overshot", style = "slidevert" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 8, bezier = "overshot", style = "slide" })
diff --git a/.config/hypr/source/animations/vertical_exagurated.conf.deprecated b/.config/hypr/source/animations/vertical_exagurated.conf.deprecated
new file mode 100644
index 00000000..2480e0aa
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_exagurated.conf.deprecated
@@ -0,0 +1,31 @@
+# -----------------------------------------------------
+# GELATIN PRESET: Maximum Wobble
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- The "Boing" Curve ---
+ # 1.7 overshoot is absolutely ridiculous.
+ bezier = boing, 0.4, 0.8, 0.2, 1.7
+ # A curve that dips below zero for "anticipation"
+ bezier = slingshot, 0.4, -0.4, 0, 1.2
+
+ # --- Animation Configs ---
+
+ # Windows: They pull back (slingshot) then fly in and wobble (boing)
+ animation = windowsIn, 1, 8, boing, popin 10%
+ animation = windowsOut, 1, 8, boing, popin 80%
+ animation = windowsMove, 1, 8, boing, slide
+
+ # Border: Even the borders pulse
+ animation = border, 1, 10, boing
+ animation = fade, 1, 5, boing
+
+ # Layers: Your Waybar will look like it's made of rubber
+ animation = layers, 1, 10, boing, slide
+
+ # Workspaces: The entire screen is a trampoline
+ animation = workspaces, 1, 10, boing, slidevert
+ animation = specialWorkspace, 1, 10, boing, slide
+}
diff --git a/.config/hypr/source/animations/vertical_exagurated.lua b/.config/hypr/source/animations/vertical_exagurated.lua
new file mode 100644
index 00000000..f97a4f40
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_exagurated.lua
@@ -0,0 +1,20 @@
+-- -----------------------------------------------------
+-- GELATIN PRESET: Maximum Wobble (Vertical)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- 1.7 overshoot is absolutely ridiculous.
+hl.curve("boing", { type = "bezier", points = { {0.4, 0.8}, {0.2, 1.7} } })
+-- A curve that dips below zero for "anticipation"
+hl.curve("slingshot", { type = "bezier", points = { {0.4, -0.4}, {0, 1.2} } })
+
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 8, bezier = "boing", style = "popin 10%" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 8, bezier = "boing", style = "popin 80%" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 8, bezier = "boing", style = "slide" })
+hl.animation({ leaf = "border", enabled = true, speed = 10, bezier = "boing" })
+hl.animation({ leaf = "fade", enabled = true, speed = 5, bezier = "boing" })
+hl.animation({ leaf = "layers", enabled = true, speed = 10, bezier = "boing", style = "slide" })
+-- Workspaces: Trampoline (vertical)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 10, bezier = "boing", style = "slidevert" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 10, bezier = "boing", style = "slide" })
diff --git a/.config/hypr/source/animations/vertical_fast.conf.deprecated b/.config/hypr/source/animations/vertical_fast.conf.deprecated
new file mode 100644
index 00000000..0ec25724
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_fast.conf.deprecated
@@ -0,0 +1,34 @@
+# -----------------------------------------------------
+# FAST PRESET: High Performance / Low Latency
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- Linear / Sharp Curves ---
+ bezier = linear, 0, 0, 1, 1
+ bezier = md3_decel, 0.05, 0.7, 0.1, 1
+ bezier = instant, 0, 1, 0, 1
+
+ # --- Animation Configs ---
+
+ # Windows: Instant snap with barely visible deceleration
+ # Duration 2 = ~30ms. Blink and you miss it.
+ animation = windows, 1, 2, md3_decel, slide
+ animation = windowsIn, 1, 2, md3_decel, slide
+ animation = windowsOut, 1, 2, md3_decel, slide
+ animation = windowsMove, 1, 2, md3_decel, slide
+
+ # Border: Instant feedback
+ animation = border, 1, 1, linear
+ animation = fade, 1, 2, md3_decel
+
+ # Layers: Snappy but not jarring
+ animation = layers, 1, 2, md3_decel, slide
+
+ # Workspaces: Fast vertical slide (200ms)
+ # Enough context to see the movement, fast enough not to wait.
+ animation = workspaces, 1, 2.5, md3_decel, slidevert
+ animation = specialWorkspace, 1, 2.5, md3_decel, slide
+
+}
diff --git a/.config/hypr/source/animations/vertical_fast.lua b/.config/hypr/source/animations/vertical_fast.lua
new file mode 100644
index 00000000..6e147521
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_fast.lua
@@ -0,0 +1,23 @@
+-- -----------------------------------------------------
+-- FAST PRESET: High Performance / Low Latency (Vertical)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+hl.curve("linear", { type = "bezier", points = { {0, 0}, {1, 1} } })
+hl.curve("md3_decel", { type = "bezier", points = { {0.05, 0.7}, {0.1, 1} } })
+hl.curve("instant", { type = "bezier", points = { {0, 1}, {0, 1} } })
+
+-- Windows: Instant snap with barely visible deceleration (~30ms)
+hl.animation({ leaf = "windows", enabled = true, speed = 2, bezier = "md3_decel", style = "slide" })
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 2, bezier = "md3_decel", style = "slide" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 2, bezier = "md3_decel", style = "slide" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 2, bezier = "md3_decel", style = "slide" })
+-- Border: Instant feedback
+hl.animation({ leaf = "border", enabled = true, speed = 1, bezier = "linear" })
+hl.animation({ leaf = "fade", enabled = true, speed = 2, bezier = "md3_decel" })
+-- Layers: Snappy but not jarring
+hl.animation({ leaf = "layers", enabled = true, speed = 2, bezier = "md3_decel", style = "slide" })
+-- Workspaces: Fast vertical slide (~200ms)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 2.5, bezier = "md3_decel", style = "slidevert" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 2.5, bezier = "md3_decel", style = "slide" })
diff --git a/.config/hypr/source/animations/vertical_hallucination.conf.deprecated b/.config/hypr/source/animations/vertical_hallucination.conf.deprecated
new file mode 100644
index 00000000..b2193ef2
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_hallucination.conf.deprecated
@@ -0,0 +1,45 @@
+# -----------------------------------------------------
+# TRIP PRESET: Psychedelic, Wavy, Disorienting
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- The "Hallucination" Curves ---
+ # Starts by going backwards (-0.55), shoots way past target (1.55), then settles.
+ # This creates a massive "wobble" effect.
+ bezier = hallucination, 0.68, -0.55, 0.265, 1.55
+
+ # Slow, lazy wave for fading
+ bezier = dream, 0.4, 0, 0.2, 1
+
+ # Constant rotation
+ bezier = linear, 0, 0, 1, 1
+
+ # --- Animation Configs ---
+
+ # Windows: The "Breathing" Effect
+ # They shrink first, then explode in. Duration 9 makes it slow and deliberate.
+ animation = windowsIn, 1, 9, hallucination, popin 0%
+ animation = windowsOut, 1, 9, hallucination, popin 0%
+
+ # Windows Move: Swimming through syrup
+ animation = windowsMove, 1, 9, hallucination, slide
+
+ # Border: THE SPIN
+ # This makes your border colors rotate infinitely.
+ # (Requires gradient borders in 'general' settings to be visible)
+ animation = border, 1, 10, dream
+ animation = borderangle, 1, 100, linear, loop
+
+ # Fade: Long, slow dissolves
+ animation = fade, 1, 10, dream
+
+ # Layers: Drifting in from the void
+ animation = layers, 1, 8, dream, popin 50%
+
+ # Workspaces: The "Warp Tunnel"
+ # slidefade 80% creates a massive ghosting trail effect when switching.
+ animation = workspaces, 1, 12, dream, slidevertfade 80%
+ animation = specialWorkspace, 1, 12, dream, slidefade 80%
+}
diff --git a/.config/hypr/source/animations/vertical_hallucination.lua b/.config/hypr/source/animations/vertical_hallucination.lua
new file mode 100644
index 00000000..94c8513a
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_hallucination.lua
@@ -0,0 +1,23 @@
+-- -----------------------------------------------------
+-- TRIP PRESET: Psychedelic, Wavy, Disorienting (Vertical)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- Starts backwards (-0.55), shoots past target (1.55), then settles.
+hl.curve("hallucination", { type = "bezier", points = { {0.68, -0.55}, {0.265, 1.55} } })
+-- Slow, lazy wave for fading
+hl.curve("dream", { type = "bezier", points = { {0.4, 0}, {0.2, 1} } })
+-- Constant rotation
+hl.curve("linear", { type = "bezier", points = { {0, 0}, {1, 1} } })
+
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 9, bezier = "hallucination", style = "popin 0%" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 9, bezier = "hallucination", style = "popin 0%" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 9, bezier = "hallucination", style = "slide" })
+hl.animation({ leaf = "border", enabled = true, speed = 10, bezier = "dream" })
+hl.animation({ leaf = "borderangle", enabled = true, speed = 100, bezier = "linear", style = "loop" })
+hl.animation({ leaf = "fade", enabled = true, speed = 10, bezier = "dream" })
+hl.animation({ leaf = "layers", enabled = true, speed = 8, bezier = "dream", style = "popin 50%" })
+-- Workspaces: The "Warp Tunnel" (vertical)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 12, bezier = "dream", style = "slidevertfade 80%" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 12, bezier = "dream", style = "slidefade 80%" })
diff --git a/.config/hypr/source/animations/vertical_mechanical.conf.deprecated b/.config/hypr/source/animations/vertical_mechanical.conf.deprecated
new file mode 100644
index 00000000..25b6ed3c
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_mechanical.conf.deprecated
@@ -0,0 +1,33 @@
+# -----------------------------------------------------
+# RIGID PRESET: Mechanical, Stiff, Precision
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- Hard Curves ---
+ # The "Block" - constant speed then instant stop.
+ bezier = hard, 0, 1, 0, 1
+ # The "Piston" - fast acceleration, hard brake.
+ bezier = piston, 0.5, 0, 0.5, 1
+
+ # --- Animation Configs ---
+
+ # Windows: Slide in like metal plates
+ # No popin (scaling), just pure sliding.
+ animation = windows, 1, 4, hard, slide
+ animation = windowsMove, 1, 4, piston, slide
+
+ # Borders: Instant snap (flashing)
+ animation = border, 1, 1, hard
+ animation = fade, 1, 2, hard
+
+ # Layers: Mechanical entry
+ animation = layers, 1, 3, hard, slide
+
+ # Workspaces: Hydraulic Lift
+ # Slidevert with zero fade. It looks like a physical machine moving.
+ animation = workspaces, 1, 5, hard, slidevert
+ animation = specialWorkspace, 1, 5, hard, slide
+
+}
diff --git a/.config/hypr/source/animations/vertical_mechanical.lua b/.config/hypr/source/animations/vertical_mechanical.lua
new file mode 100644
index 00000000..ee6aa151
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_mechanical.lua
@@ -0,0 +1,19 @@
+-- -----------------------------------------------------
+-- RIGID PRESET: Mechanical, Stiff, Precision (Vertical)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- The "Block" - constant speed then instant stop.
+hl.curve("hard", { type = "bezier", points = { {0, 1}, {0, 1} } })
+-- The "Piston" - fast acceleration, hard brake.
+hl.curve("piston", { type = "bezier", points = { {0.5, 0}, {0.5, 1} } })
+
+hl.animation({ leaf = "windows", enabled = true, speed = 4, bezier = "hard", style = "slide" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 4, bezier = "piston", style = "slide" })
+hl.animation({ leaf = "border", enabled = true, speed = 1, bezier = "hard" })
+hl.animation({ leaf = "fade", enabled = true, speed = 2, bezier = "hard" })
+hl.animation({ leaf = "layers", enabled = true, speed = 3, bezier = "hard", style = "slide" })
+-- Workspaces: Hydraulic Lift (vertical)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 5, bezier = "hard", style = "slidevert" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 5, bezier = "hard", style = "slide" })
diff --git a/.config/hypr/source/animations/vertical_minimal.conf.deprecated b/.config/hypr/source/animations/vertical_minimal.conf.deprecated
new file mode 100644
index 00000000..f3060ad1
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_minimal.conf.deprecated
@@ -0,0 +1,37 @@
+animations {
+ enabled = true
+
+ # --------------------------------------------------------
+ # Bezier Curves
+ # --------------------------------------------------------
+ bezier = pro, 0.05, 0.9, 0.1, 1.0
+ bezier = snap, 0.05, 0.9, 0.1, 1.05
+
+ # --------------------------------------------------------
+ # Application Windows (Speed: 3 - Relaxed/Clear)
+ # --------------------------------------------------------
+ animation = windows, 1, 3, snap, popin 80%
+ animation = windowsOut, 1, 3, snap, popin 80%
+ animation = windowsMove, 1, 3, snap
+
+ # --------------------------------------------------------
+ # UI Layers: Rofi, Waybar (Speed: 2 - Snappy)
+ # --------------------------------------------------------
+ # This '2' is the key. It makes layers faster than windows.
+ # We use 'slide' generally, but can override direction in layer rules.
+ animation = layers, 1, 2, pro, slide
+ animation = fade, 1, 2, pro
+
+ # fix for screenshot gray capture
+ animation = layersOut, 0, 0,
+
+ animation = border, 1, 3, pro
+
+ # --------------------------------------------------------
+ # Workspaces (vertical Slide)
+ # --------------------------------------------------------
+ animation = workspaces, 1, 3, pro, slidevert
+
+ # Special Workspace (Scratchpad)
+ animation = specialWorkspace, 1, 3, pro, slide
+}
diff --git a/.config/hypr/source/animations/vertical_minimal.lua b/.config/hypr/source/animations/vertical_minimal.lua
new file mode 100644
index 00000000..cee2740d
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_minimal.lua
@@ -0,0 +1,22 @@
+-- -----------------------------------------------------
+-- MINIMAL PRESET: Clean & Snappy (Vertical)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+hl.curve("pro", { type = "bezier", points = { {0.05, 0.9}, {0.1, 1.0} } })
+hl.curve("snap", { type = "bezier", points = { {0.05, 0.9}, {0.1, 1.05} } })
+
+-- Application Windows
+hl.animation({ leaf = "windows", enabled = true, speed = 3, bezier = "snap", style = "popin 80%" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 3, bezier = "snap", style = "popin 80%" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 3, bezier = "snap" })
+-- UI Layers: Rofi, Waybar
+hl.animation({ leaf = "layers", enabled = true, speed = 2, bezier = "pro", style = "slide" })
+hl.animation({ leaf = "fade", enabled = true, speed = 2, bezier = "pro" })
+-- Fix for screenshot gray capture
+hl.animation({ leaf = "layersOut", enabled = false, speed = 0 })
+hl.animation({ leaf = "border", enabled = true, speed = 3, bezier = "pro" })
+-- Workspaces (vertical slide)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 3, bezier = "pro", style = "slidevert" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 3, bezier = "pro", style = "slide" })
diff --git a/.config/hypr/source/animations/vertical_rage.conf.deprecated b/.config/hypr/source/animations/vertical_rage.conf.deprecated
new file mode 100644
index 00000000..afc8f744
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_rage.conf.deprecated
@@ -0,0 +1,35 @@
+# -----------------------------------------------------
+# SLAP PRESET: Aggressive, Instant Impact
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- The "Impact" Curve ---
+ # Starts at 0, goes straight to 1. No easing.
+ bezier = linear, 0, 0, 1, 1
+ # Accelerate only
+ bezier = accel, 1, 0, 1, 0.5
+
+ # --- Animation Configs ---
+
+ # Windows: Fast entry (3), hard stop.
+ animation = windowsIn, 1, 3, accel, slide
+ # Windows Out: They drop like rocks.
+ animation = windowsOut, 1, 3, accel, slide
+
+ # Windows Move: Zero smoothing.
+ animation = windowsMove, 1, 2, linear, slide
+
+ # Border
+ animation = border, 1, 1, linear
+ animation = fade, 1, 2, linear
+
+ # Layers
+ animation = layers, 1, 2, accel, slide
+
+ # Workspaces: Fast vertical slam
+ animation = workspaces, 1, 3, accel, slidevert
+ animation = specialWorkspace, 1, 3, accel, slide
+
+}
diff --git a/.config/hypr/source/animations/vertical_rage.lua b/.config/hypr/source/animations/vertical_rage.lua
new file mode 100644
index 00000000..8f0f60bc
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_rage.lua
@@ -0,0 +1,20 @@
+-- -----------------------------------------------------
+-- SLAP PRESET: Aggressive, Instant Impact (Vertical)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- Starts at 0, goes straight to 1. No easing.
+hl.curve("linear", { type = "bezier", points = { {0, 0}, {1, 1} } })
+-- Accelerate only
+hl.curve("accel", { type = "bezier", points = { {1, 0}, {1, 0.5} } })
+
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 3, bezier = "accel", style = "slide" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 3, bezier = "accel", style = "slide" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 2, bezier = "linear", style = "slide" })
+hl.animation({ leaf = "border", enabled = true, speed = 1, bezier = "linear" })
+hl.animation({ leaf = "fade", enabled = true, speed = 2, bezier = "linear" })
+hl.animation({ leaf = "layers", enabled = true, speed = 2, bezier = "accel", style = "slide" })
+-- Workspaces: Fast vertical slam
+hl.animation({ leaf = "workspaces", enabled = true, speed = 3, bezier = "accel", style = "slidevert" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 3, bezier = "accel", style = "slide" })
diff --git a/.config/hypr/source/animations/vertical_slowmotion.conf.deprecated b/.config/hypr/source/animations/vertical_slowmotion.conf.deprecated
new file mode 100644
index 00000000..cdbdbb5b
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_slowmotion.conf.deprecated
@@ -0,0 +1,28 @@
+# -----------------------------------------------------
+# DRAMA PRESET: Slow Motion Cinematic
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- The "Suspense" Curve ---
+ # Starts incredibly slow, rushes in the middle, slows down again.
+ bezier = slowmo, 0.85, 0, 0.15, 1
+
+ # --- Animation Configs ---
+
+ # Windows: 15 (approx 1.5 seconds). It feels like forever.
+ animation = windows, 1, 15, slowmo, slide
+ animation = windowsMove, 1, 15, slowmo, slide
+
+ # Border: A slow, ominous color change
+ animation = border, 1, 20, slowmo
+ animation = fade, 1, 20, slowmo
+
+ # Layers
+ animation = layers, 1, 12, slowmo, slide
+
+ # Workspaces: A grand, sweeping scene transition
+ animation = workspaces, 1, 20, slowmo, slidevert
+ animation = specialWorkspace, 1, 20, slowmo, slide
+}
diff --git a/.config/hypr/source/animations/vertical_slowmotion.lua b/.config/hypr/source/animations/vertical_slowmotion.lua
new file mode 100644
index 00000000..9c03d6c2
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_slowmotion.lua
@@ -0,0 +1,20 @@
+-- -----------------------------------------------------
+-- DRAMA PRESET: Slow Motion Cinematic (Vertical)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- Starts incredibly slow, rushes in the middle, slows down again.
+hl.curve("slowmo", { type = "bezier", points = { {0.85, 0}, {0.15, 1} } })
+
+-- Windows: ~1.5 seconds. It feels like forever.
+hl.animation({ leaf = "windows", enabled = true, speed = 15, bezier = "slowmo", style = "slide" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 15, bezier = "slowmo", style = "slide" })
+-- Border: A slow, ominous color change
+hl.animation({ leaf = "border", enabled = true, speed = 20, bezier = "slowmo" })
+hl.animation({ leaf = "fade", enabled = true, speed = 20, bezier = "slowmo" })
+-- Layers
+hl.animation({ leaf = "layers", enabled = true, speed = 12, bezier = "slowmo", style = "slide" })
+-- Workspaces: Grand, sweeping scene transition (vertical)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 20, bezier = "slowmo", style = "slidevert" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 20, bezier = "slowmo", style = "slide" })
diff --git a/.config/hypr/source/animations/vertical_vertical_air.conf.deprecated b/.config/hypr/source/animations/vertical_vertical_air.conf.deprecated
new file mode 100644
index 00000000..e26aee6f
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_vertical_air.conf.deprecated
@@ -0,0 +1,33 @@
+# -----------------------------------------------------
+# AIR PRESET: Floaty, Soft, Ethereal
+# -----------------------------------------------------
+
+animations {
+ enabled = true
+
+ # --- Soft Curves ---
+ # Slow start, slow end. Like a feather falling.
+ bezier = soft, 0.3, 0.3, 0.2, 1
+ bezier = softIn, 0.4, 0, 1, 1
+
+ # --- Animation Configs ---
+
+ # Windows: Drift in with opacity changes
+ # slidefade 15% gives it that "ghost" tail effect
+ animation = windowsIn, 1, 8, soft, slidefade 15%
+ animation = windowsOut, 1, 8, softIn, slidefade 15%
+ animation = windowsMove, 1, 8, soft, slidefade 15%
+
+ # Border & Fade: Very slow transition
+ animation = border, 1, 10, soft
+ animation = fade, 1, 10, soft
+
+ # Layers: Gentle drift
+ animation = layers, 1, 6, soft, slidefade 10%
+
+ # Workspaces: The "Elevator in the Clouds"
+ # Long duration (10), vertical slide with heavy fade.
+ animation = workspaces, 1, 10, soft, slidefadevert 40%
+ animation = specialWorkspace, 1, 10, soft, slidefade 40%
+
+}
diff --git a/.config/hypr/source/animations/vertical_vertical_air.lua b/.config/hypr/source/animations/vertical_vertical_air.lua
new file mode 100644
index 00000000..6e7d1f30
--- /dev/null
+++ b/.config/hypr/source/animations/vertical_vertical_air.lua
@@ -0,0 +1,22 @@
+-- -----------------------------------------------------
+-- AIR PRESET: Floaty, Soft, Ethereal (Vertical)
+-- -----------------------------------------------------
+
+hl.config({ animations = { enabled = true } })
+
+-- Slow start, slow end. Like a feather falling.
+hl.curve("soft", { type = "bezier", points = { {0.3, 0.3}, {0.2, 1} } })
+hl.curve("softIn", { type = "bezier", points = { {0.4, 0}, {1, 1} } })
+
+-- Windows: Drift in with opacity changes
+hl.animation({ leaf = "windowsIn", enabled = true, speed = 8, bezier = "soft", style = "slidefade 15%" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 8, bezier = "softIn", style = "slidefade 15%" })
+hl.animation({ leaf = "windowsMove", enabled = true, speed = 8, bezier = "soft", style = "slidefade 15%" })
+-- Border & Fade: Very slow transition
+hl.animation({ leaf = "border", enabled = true, speed = 10, bezier = "soft" })
+hl.animation({ leaf = "fade", enabled = true, speed = 10, bezier = "soft" })
+-- Layers: Gentle drift
+hl.animation({ leaf = "layers", enabled = true, speed = 6, bezier = "soft", style = "slidefade 10%" })
+-- Workspaces: Elevator in the Clouds (vertical)
+hl.animation({ leaf = "workspaces", enabled = true, speed = 10, bezier = "soft", style = "slidefadevert 40%" })
+hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 10, bezier = "soft", style = "slidefade 40%" })
diff --git a/.config/hypr/source/appearance.conf b/.config/hypr/source/appearance.conf.deprecated
similarity index 100%
rename from .config/hypr/source/appearance.conf
rename to .config/hypr/source/appearance.conf.deprecated
diff --git a/.config/hypr/source/appearance.lua b/.config/hypr/source/appearance.lua
new file mode 100644
index 00000000..d2b6a3b7
--- /dev/null
+++ b/.config/hypr/source/appearance.lua
@@ -0,0 +1,146 @@
+-- =============================================================================
+-- APPEARANCE — Base Configuration
+-- =============================================================================
+-- DO NOT EDIT THIS FILE.
+-- Configure appearance in ~/.config/hypr/edit_here/source/appearance.lua
+-- which is loaded last and overrides these defaults.
+-- =============================================================================
+
+-- -------------------------------------------------------------------------------------------------
+-- 1. GENERAL APPEARANCE
+-- Control gaps, borders, and layout behavior.
+-- See: https://wiki.hypr.land/Configuring/Variables/#general
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ general = {
+ -- Gaps & Borders
+ gaps_in = 6, -- Gap between windows
+ gaps_out = 12, -- Gap between windows and monitor edges
+ gaps_workspaces = 0, -- Gap between workspaces (when sliding)
+ border_size = 2, -- Size of window borders
+
+ -- Behavior
+ -- resize_on_border: allows resizing by dragging on the gap/border area
+ resize_on_border = false,
+
+ -- allow_tearing: lower latency in games
+ -- NOTE: also set 'windowrule immediate' on the game class
+ allow_tearing = true,
+
+ -- Default layout engine
+ layout = "dwindle",
+
+ -- Snapping: controls how floating windows snap to each other and edges
+ snap = {
+ enabled = false,
+ window_gap = 10, -- min gap (px) before snapping to another window
+ monitor_gap = 10, -- min gap (px) before snapping to monitor edge
+ border_overlap = false,
+ },
+ },
+})
+
+-- -------------------------------------------------------------------------------------------------
+-- 2. DECORATION
+-- Shadows, Blur, Opacity, and Rounding.
+-- See: https://wiki.hypr.land/Configuring/Variables/#decoration
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ decoration = {
+ -- Rounding
+ rounding = 6,
+ rounding_power = 6.0,
+
+ -- Opacity
+ active_opacity = 0.95,
+ inactive_opacity = 0.8,
+ fullscreen_opacity = 1.0,
+
+ -- Dimming
+ dim_inactive = false,
+ dim_strength = 0.2,
+ dim_special = 0.8, -- stronger dimming for special workspace
+
+ -- Shadows
+ shadow = {
+ enabled = true,
+ range = 35,
+ render_power = 2, -- 1-4; higher = faster falloff (sharper)
+ sharp = false,
+ scale = 1.0,
+ color = "rgba(1a1a1aee)",
+ },
+
+ -- Blur
+ blur = {
+ enabled = true,
+ size = 4, -- radius
+ passes = 2, -- quality (2 = good perf/looks balance)
+ new_optimizations = true,
+ ignore_opacity = true, -- blur behind transparent windows
+ xray = true,
+
+ -- Texture & Quality
+ noise = 0.0217,
+ contrast = 0.8916,
+ brightness = 0.8172,
+ vibrancy = 0.1696,
+
+ -- Specifics
+ popups = false, -- whether to blur right-click menus/popups
+ },
+
+ -- screen_shader = home .. "/.config/hypr/shaders/grayscale_advanced.glsl"
+ },
+})
+
+-- -------------------------------------------------------------------------------------------------
+-- 3. ANIMATIONS
+-- The active animation preset is sourced from the animations directory.
+-- See: https://wiki.hypr.land/Configuring/Animations/
+-- (Overridden in edit_here/source/appearance.lua to load the user's chosen preset)
+-- -------------------------------------------------------------------------------------------------
+dofile(os.getenv("HOME") .. "/.config/hypr/source/animations/active/active.lua")
+
+-- -------------------------------------------------------------------------------------------------
+-- 4. LAYOUTS
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ dwindle = {
+ preserve_split = true,
+ -- smart_split = false,
+ -- smart_resizing = false,
+ },
+ master = {
+ new_status = "master",
+ },
+})
+
+-- -------------------------------------------------------------------------------------------------
+-- 5. MISCELLANEOUS & PERFORMANCE
+-- See: https://wiki.hypr.land/Configuring/Variables/#misc
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ misc = {
+ force_default_wallpaper = 1, -- set to 0 to enable the anime mascot
+ disable_hyprland_logo = true,
+ disable_splash_rendering = true,
+ },
+})
+
+-- -------------------------------------------------------------------------------------------------
+-- 6. BINDS (Visual specific)
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ binds = {
+ allow_pin_fullscreen = true,
+ },
+})
+
+-- -------------------------------------------------------------------------------------------------
+-- 7. SMART GAPS (Single Window Override)
+-- Applied automatically when only 1 window is tiled or fullscreened on a workspace.
+-- -------------------------------------------------------------------------------------------------
+local single_window_gap = 10
+hl.workspace_rule({ workspace = "w[tv1]", gaps_out = single_window_gap, gaps_in = 0 })
+hl.workspace_rule({ workspace = "f[1]", gaps_out = single_window_gap, gaps_in = 0 })
diff --git a/.config/hypr/source/autostart.conf b/.config/hypr/source/autostart.conf.deprecated
similarity index 100%
rename from .config/hypr/source/autostart.conf
rename to .config/hypr/source/autostart.conf.deprecated
diff --git a/.config/hypr/source/autostart.lua b/.config/hypr/source/autostart.lua
new file mode 100644
index 00000000..6c085274
--- /dev/null
+++ b/.config/hypr/source/autostart.lua
@@ -0,0 +1,33 @@
+-- =============================================================================
+-- AUTOSTART — Base Services
+-- =============================================================================
+-- Optimized for: Arch Linux | Hyprland | UWSM
+-- Wrap all apps in 'uwsm-app --' so systemd tracks them properly.
+-- =============================================================================
+
+local home = os.getenv("HOME")
+
+-- --- BACKGROUND SERVICES ---
+
+-- Wallpaper engine
+hl.on("hyprland.start", function() hl.exec_cmd("uwsm-app -- awww-daemon") end)
+
+-- hypridle is managed via its systemd service — no exec-once needed.
+
+-- --- CLIPBOARD MANAGER ---
+hl.on("hyprland.start", function()
+ hl.exec_cmd("uwsm-app -- wl-paste --type text --watch cliphist store")
+ hl.exec_cmd("uwsm-app -- wl-paste --type image --watch cliphist store")
+ hl.exec_cmd("uwsm-app -- wl-clip-persist --clipboard regular")
+end)
+
+-- --- OPTIONAL / USER INTERFACE ---
+hl.on("hyprland.start", function()
+ hl.exec_cmd("uwsm-app -- " .. home .. "/user_scripts/waybar/waybar_autostart.sh")
+end)
+
+-- --- SLOW APP LAUNCH FIX — propagate environment to systemd and dbus ---
+hl.on("hyprland.start", function()
+ hl.exec_cmd("systemctl --user import-environment $(env | cut -d'=' -f 1)")
+ hl.exec_cmd("dbus-update-activation-environment --systemd --all")
+end)
diff --git a/.config/hypr/source/environment_variables.conf b/.config/hypr/source/environment_variables.conf.deprecated
similarity index 100%
rename from .config/hypr/source/environment_variables.conf
rename to .config/hypr/source/environment_variables.conf.deprecated
diff --git a/.config/hypr/source/environment_variables.lua b/.config/hypr/source/environment_variables.lua
new file mode 100644
index 00000000..35d1a5ea
--- /dev/null
+++ b/.config/hypr/source/environment_variables.lua
@@ -0,0 +1,12 @@
+-- =============================================================================
+-- ENVIRONMENT VARIABLES
+-- =============================================================================
+-- NOTE: It is strongly advised to place environment variables in UWSM files:
+-- ~/.config/uwsm/env (compositor-agnostic variables)
+-- ~/.config/uwsm/env-hyprland (Hyprland-specific variables)
+--
+-- This file only sets the single variable required to suppress a Hyprland
+-- startup warning.
+-- =============================================================================
+
+hl.env("XDG_CURRENT_DESKTOP", "Hyprland")
diff --git a/.config/hypr/source/input.conf b/.config/hypr/source/input.conf.deprecated
similarity index 100%
rename from .config/hypr/source/input.conf
rename to .config/hypr/source/input.conf.deprecated
diff --git a/.config/hypr/source/input.lua b/.config/hypr/source/input.lua
new file mode 100644
index 00000000..7aacbef0
--- /dev/null
+++ b/.config/hypr/source/input.lua
@@ -0,0 +1,127 @@
+-- =============================================================================
+-- INPUT — Base Configuration
+-- =============================================================================
+-- DO NOT EDIT THIS FILE.
+-- Configure input in ~/.config/hypr/edit_here/source/input.lua
+-- which is loaded last and overrides these defaults.
+-- =============================================================================
+
+-- -------------------------------------------------------------------------------------------------
+-- 1. KEYBOARD & LANGUAGE
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ input = {
+ kb_layout = "us",
+ kb_options = "", -- e.g. "caps:escape", "grp:alt_shift_toggle"
+
+ resolve_binds_by_sym = false,
+ numlock_by_default = true,
+
+ repeat_rate = 35, -- [10-100]
+ repeat_delay = 250, -- [100-1000]
+
+ -- -----------------------------------------------------------------
+ -- 2. MOUSE & POINTER ACCELERATION
+ -- -----------------------------------------------------------------
+
+ -- 0 = cursor movement doesn't change focus
+ -- 1 = cursor movement changes focus (default)
+ -- 2 = detached focus (click to focus keyboard, mouse follows independently)
+ -- 3 = completely separate focus
+ follow_mouse = 1,
+
+ sensitivity = 0, -- [-1.0 to 1.0]
+ accel_profile = "adaptive", -- flat | adaptive | custom
+ force_no_accel = false, -- "raw input" — bypasses most pointer settings
+ left_handed = false,
+ mouse_refocus = true,
+
+ -- -----------------------------------------------------------------
+ -- 3. SCROLLING & TRACKBALLS
+ -- -----------------------------------------------------------------
+ natural_scroll = false,
+ scroll_method = "2fg", -- 2fg | edge | on_button_down | no_scroll
+ scroll_button = 0,
+ scroll_button_lock = false,
+
+ -- -----------------------------------------------------------------
+ -- 4. TOUCHPAD
+ -- -----------------------------------------------------------------
+ touchpad = {
+ natural_scroll = true,
+ disable_while_typing = true,
+ tap_to_click = true,
+ clickfinger_behavior = false,
+ drag_lock = false,
+ },
+ },
+})
+
+-- -------------------------------------------------------------------------------------------------
+-- 5. CURSOR BEHAVIOR & RENDERING
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ cursor = {
+ sync_gsettings_theme = true,
+
+ -- 0 = HW cursors (performance)
+ -- 1 = force SW cursors (compatibility / fixes disappearing cursor)
+ -- 2 = auto (disable when tearing)
+ no_hardware_cursors = 2,
+
+ -- Nvidia specific optimization — 0 = off, 1 = on, 2 = auto
+ use_cpu_buffer = 2,
+
+ hide_on_key_press = false,
+ inactive_timeout = 0, -- hide cursor after X seconds (0 = never)
+
+ -- 0 = disabled, 1 = move to center of focused window, 2 = force
+ warp_on_change_workspace = 0,
+
+ -- VRR-specific — 0 = off, 1 = on, 2 = auto
+ no_break_fs_vrr = 2,
+
+ zoom_factor = 1.0, -- [1.0 - 5.0] magnifier zoom level
+ },
+})
+
+-- -------------------------------------------------------------------------------------------------
+-- 6. GESTURE PHYSICS (Tuning)
+-- -------------------------------------------------------------------------------------------------
+hl.config({
+ gestures = {
+ workspace_swipe_distance = 300,
+ workspace_swipe_cancel_ratio = 0.5,
+ workspace_swipe_invert = true,
+ workspace_swipe_create_new = true,
+ workspace_swipe_forever = false,
+ },
+})
+
+-- -------------------------------------------------------------------------------------------------
+-- 7. GESTURE BINDINGS
+-- -------------------------------------------------------------------------------------------------
+
+-- 3-finger up swipe → hyprexpo toggle
+hl.gesture({ fingers = 3, direction = "up", action = function() hl.exec_cmd("hyprctl dispatch hyprexpo:expo toggle") end })
+
+-- 3-finger left swipe (unbound — customize in edit_here)
+-- hl.gesture({ fingers = 3, direction = "left", action = function() end })
+
+-- 3-finger down swipe → mute audio
+hl.gesture({ fingers = 3, direction = "down", action = function() hl.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle") end })
+
+-- 3-finger right swipe → play/pause
+hl.gesture({ fingers = 3, direction = "right", action = function() hl.exec_cmd("playerctl play-pause") end })
+
+-- 4-finger horizontal → brightness
+hl.gesture({ fingers = 4, direction = "left", action = function() hl.exec_cmd("brightnessctl -e4 -n2 set 10%-") end })
+hl.gesture({ fingers = 4, direction = "right", action = function() hl.exec_cmd("brightnessctl -e4 -n2 set 10%+") end })
+
+-- 4-finger vertical → volume
+hl.gesture({ fingers = 4, direction = "up", action = function() hl.exec_cmd("wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 10%+") end })
+hl.gesture({ fingers = 4, direction = "down", action = function() hl.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 10%-") end })
+
+-- 3-finger pinch → lock screen / screenshot
+hl.gesture({ fingers = 3, direction = "pinchout", action = function() hl.exec_cmd("hyprlock --immediate") end })
+hl.gesture({ fingers = 3, direction = "pinchin", action = function() hl.exec_cmd("slurp | grim -g - - | swappy -f -") end })
diff --git a/.config/hypr/source/keybinds.conf b/.config/hypr/source/keybinds.conf.deprecated
similarity index 100%
rename from .config/hypr/source/keybinds.conf
rename to .config/hypr/source/keybinds.conf.deprecated
diff --git a/.config/hypr/source/keybinds.lua b/.config/hypr/source/keybinds.lua
new file mode 100644
index 00000000..a87acd70
--- /dev/null
+++ b/.config/hypr/source/keybinds.lua
@@ -0,0 +1,278 @@
+-- =============================================================================
+-- KEYBINDINGS
+-- =============================================================================
+-- DO NOT EDIT THIS FILE.
+-- Add or override keybinds in ~/.config/hypr/edit_here/source/keybinds.lua
+--
+-- Application launcher binds (SUPER+Q/W/E/R) are intentionally left to the
+-- user's edit_here file, so they can pick their preferred apps.
+-- =============================================================================
+
+local mainMod = "SUPER"
+local home = os.getenv("HOME")
+local scripts = home .. "/user_scripts"
+
+-- Accessibility: enable anti-aliasing bypass for cursor zoom
+hl.config({ cursor = { zoom_disable_aa = true } })
+
+-- =============================================================================
+-- 2. APPLICATION LAUNCHERS (UWSM Wrapped)
+-- =============================================================================
+
+-- Launchers for Q/W/E/R are in edit_here/source/keybinds.lua (app-dependent)
+
+-- Menus
+hl.bind("ALT + SPACE", hl.dsp.exec_cmd("pkill rofi; rofi -show drun -run-command 'uwsm app -- {cmd}'"), { description = "Launch Menu for Apps" })
+hl.bind("CTRL + SHIFT + SPACE",hl.dsp.exec_cmd("uwsm-app -- pkill rofi; " .. home .. "/user_scripts/rofi/keybindings.sh"), { description = "Show Keybinds" })
+hl.bind(mainMod .. " + CTRL + SPACE", hl.dsp.exec_cmd("uwsm-app -- pkill rofi; " .. scripts .. "/rofi/emoji.sh"), { description = "Search Emojis" })
+hl.bind(mainMod .. " + CTRL + SHIFT + SPACE", hl.dsp.exec_cmd("uwsm-app -- pkill rofi; " .. scripts .. "/rofi/calculator.sh"), { description = "Calculator" })
+hl.bind(mainMod .. " + SHIFT + SPACE", hl.dsp.exec_cmd("uwsm-app -- pkill rofi; " .. scripts .. "/rofi/rofi_theme.sh"), { description = "Matugen Theme Config" })
+hl.bind("CTRL + SPACE", hl.dsp.exec_cmd("uwsm-app -- pkill rofi; " .. scripts .. "/rofi/rofi_wallpaper_selctor.sh"), { description = "Rofi Wallpaper Selector" })
+hl.bind(mainMod .. " + SPACE", hl.dsp.exec_cmd("gdbus call --session --dest com.github.dusky.controlcenter --object-path /com/github/dusky/controlcenter --method org.freedesktop.Application.Activate '{}'"), { description = "System Menu" })
+hl.bind("CTRL + ALT + SPACE", hl.dsp.exec_cmd("uwsm-app -- pkill rofi; " .. scripts .. "/rofi/dusky_glance.sh"), { description = "Dusky Glance" })
+
+-- Rofi Powermenu
+hl.bind("ALT + SHIFT + SPACE", hl.dsp.exec_cmd("uwsm-app -- pkill rofi; rofi -show power-menu -modi power-menu:" .. scripts .. "/rofi/powermenu.sh"), { description = "Power Menu" })
+
+-- System Monitor (btop)
+hl.bind("CTRL + SHIFT + escape", hl.dsp.exec_cmd("uwsm-app -- " .. terminal .. " --class btop -e btop"), { description = "System Monitor" })
+
+-- --- System Utilities ---
+hl.bind("ALT + 1", hl.dsp.exec_cmd("uwsm-app -- " .. terminal .. " --class wifitui -e wifitui"), { description = "Wi-Fi Manager" })
+hl.bind("ALT + 2", hl.dsp.exec_cmd("uwsm-app -- blueman-manager"), { description = "Bluetooth Manager" })
+hl.bind("ALT + 3", hl.dsp.exec_cmd("uwsm-app -- pavucontrol"), { description = "Audio Mixer" })
+hl.bind("ALT + 4", hl.dsp.exec_cmd("uwsm-app -- waypaper"), { description = "Wallpaper App" })
+hl.bind(mainMod .. " + apostrophe", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/theme_matugen/theme_ctl.sh next"), { description = "Cycle Next Wallpaper" })
+hl.bind(mainMod .. " + SHIFT + apostrophe", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/rofi/rofi_wallpaper_selctor.sh --next-fav"), { description = "Cycle Fav Wallpaper" })
+
+-- Drive Locking/Unlocking (Browser)
+hl.bind("ALT + 5", hl.dsp.exec_cmd("uwsm-app -- " .. terminal .. " -e " .. scripts .. "/drives/drive_manager.sh unlock browser"), { description = "Unlock Browser" })
+hl.bind("ALT + SHIFT + 5", hl.dsp.exec_cmd("uwsm-app -- " .. terminal .. " -e " .. scripts .. "/drives/drive_manager.sh lock browser"), { locked = true, description = "Lock Browser" })
+
+-- =============================================================================
+-- PASSTHROUGH / GAME MODE (disables all other keybinds)
+-- =============================================================================
+-- Enter passthrough: show notification then switch submap
+hl.bind("ALT + 6",
+ hl.dsp.exec_cmd("notify-send -u critical -t 3000 'Passthrough Enabled' 'Press ALT+6 to exit'; hyprctl dispatch submap passthrough"),
+ { locked = true, description = "Disable Game Mode (Disable Keybinds)" })
+
+hl.define_submap("passthrough", function()
+ -- Only bind active inside passthrough: exit key
+ hl.bind("ALT + 6",
+ hl.dsp.exec_cmd("notify-send -u low -t 2000 'Passthrough Disabled' 'Keybinds restored'; hyprctl dispatch submap reset"),
+ { locked = true, description = "Game Mode (Enable Keybinds)" })
+end)
+
+-- --- Display Management (ASUS TUF F15) ---
+hl.bind("ALT + 7", hl.dsp.exec_cmd("hyprctl keyword monitor eDP-1,1920x1080@48,0x0,1.6 && sleep 2 && hyprctl keyword misc:vrr 0"), { locked = true, description = "Set Refresh rate to 48Hz Asus Tuf" })
+hl.bind("ALT + 8", hl.dsp.exec_cmd("hyprctl keyword monitor eDP-1,1920x1080@144,0x0,1.6 && sleep 2 && hyprctl keyword misc:vrr 1"), { locked = true, description = "Set Refresh rate to 144Hz Asus Tuf" })
+
+-- --- Screen Rotate ---
+hl.bind("CTRL + ALT + R", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/hypr/screen_rotate.sh -90"), { locked = true, description = "Rotate Screen Clockwise" })
+hl.bind("CTRL + ALT + SHIFT + R", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/hypr/screen_rotate.sh +90"), { locked = true, description = "Rotate Screen Anti-Clockwise" })
+
+-- --- Screen DPMS toggle ---
+hl.bind("ALT + F7", hl.dsp.exec_cmd("sleep 1 && hyprctl dispatch dpms off"), { locked = true, description = "Screen Off DPMS" })
+hl.bind("ALT + F8", hl.dsp.exec_cmd("hyprctl dispatch dpms on"), { locked = true, description = "Screen On DPMS" })
+
+-- Waybar
+hl.bind("ALT + 9", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/waybar/waybar_autostart.sh"), { description = "Start Waybar for 1 Min" })
+hl.bind("ALT + 0", hl.dsp.exec_cmd("pkill waybar"), { locked = true, description = "Kill Waybar" })
+hl.bind(mainMod .. " + ALT + W", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/waybar/dusky_waybars.sh --toggle"), { description = "Waybar Swap Configs" })
+hl.bind(mainMod .. " + ALT + SHIFT + W", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/waybar/dusky_waybars.sh --back_toggle"), { description = "Waybar Swap Configs (Back)" })
+
+-- wlogout
+hl.bind("ALT + F4", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/wlogout/wlogout_scale.sh"), { description = "Logout Menu" })
+
+-- Hyprland Reload
+hl.bind("ALT + R", hl.dsp.exec_cmd("hyprctl reload"), { locked = true, description = "Reload Hyprland" })
+
+-- Dusky QuickPanel (Sliders)
+hl.bind("ALT + V", hl.dsp.exec_cmd("gdbus call --session --dest org.dusky.quickpanal --object-path /org/dusky/quickpanal --method org.freedesktop.Application.Activate '{}'"), { description = "Dusky QuickPanel" })
+
+-- =============================================================================
+-- 3. CUSTOM SCRIPTS & UTILITIES
+-- =============================================================================
+
+-- ASUS Hardware: Fan & Keyboard Light Control
+hl.bind("XF86Launch3", hl.dsp.exec_cmd("uwsm-app -- " .. terminal .. " --class asusctl.sh -e sudo " .. scripts .. "/asus/asusctl.sh"), { description = "ASUS Control" })
+
+-- Display Scale Adjustment
+hl.bind(mainMod .. " + F", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/hypr/adjust_scale.py +"), { locked = true, repeating = true, description = "Scale Up" })
+hl.bind(mainMod .. " + SHIFT + F", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/hypr/adjust_scale.py -"), { locked = true, repeating = true, description = "Scale Down" })
+
+-- Performance: Process Terminator
+hl.bind(mainMod .. " + semicolon", hl.dsp.exec_cmd("uwsm-app -- " .. terminal .. " --class performance.sh -e " .. scripts .. "/performance/services_and_process_terminator.sh"), { description = "Kill Process" })
+
+-- wayclick script
+hl.bind(mainMod .. " + U", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/wayclick/dusky_wayclick.sh"), { description = "Key Press Sound" })
+hl.bind(mainMod .. " + SHIFT + U", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/mako_osd/dusky_keys/dusky_keys.sh"), { description = "OSD Key Presses" })
+
+-- Opacity & Blur Toggles
+hl.bind(mainMod .. " + ALT + period", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/hypr/hypr_blur_opacity_shadow_toggle.sh"), { locked = true, description = "Toggle Blur/Opacity" })
+hl.bind(mainMod .. " + period", hl.dsp.window.set_prop({ prop = "opaque", value = "toggle" }), { locked = true, description = "Toggle Per-Window Opacity" })
+hl.bind(mainMod .. " + comma", hl.dsp.window.set_prop({ prop = "no_blur", value = "toggle" }), { locked = true, description = "Toggle Per-Window Blur" })
+
+-- --- Accessibility: Zoom ---
+hl.bind("SUPER + equal", hl.dsp.exec_cmd("sh -c \"hyprctl keyword cursor:zoom_factor \\\"$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {print $2 * 1.25}')\\\"\""), { repeating = true, description = "Zoom In" })
+hl.bind("SUPER + minus", hl.dsp.exec_cmd("sh -c \"hyprctl keyword cursor:zoom_factor \\\"$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {val = $2 / 1.25; if (val < 1.0) val = 1.0; print val}')\\\"\""), { repeating = true, description = "Zoom Out" })
+hl.bind("SUPER + BACKSPACE", hl.dsp.exec_cmd("hyprctl keyword cursor:zoom_factor 1.0"), { locked = true, description = "Reset Zoom" })
+
+-- Hyprshade (Visual Filters)
+hl.bind(mainMod .. " + ALT + S", hl.dsp.exec_cmd("uwsm-app -- pkill rofi; " .. scripts .. "/rofi/shader_menu.sh"), { description = "Shader Menu" })
+hl.bind(mainMod .. " + ALT + X", hl.dsp.exec_cmd("hyprshade off"), { locked = true, description = "Disable Shader" })
+hl.bind(mainMod .. " + ALT + V", hl.dsp.exec_cmd("hyprshade on vibrance"), { locked = true, description = "Vibrant Shader" })
+
+-- Hyprland Animations Rofi Menu
+hl.bind(mainMod .. " + ALT + A", hl.dsp.exec_cmd("uwsm-app -- pkill rofi; rofi -show animations -modi 'animations:" .. scripts .. "/rofi/hypr_anim.sh'"), { description = "Animation Rofi Menu" })
+
+-- --- Clipboard & Screenshot ---
+
+-- Rofi Clipboard
+hl.bind(mainMod .. " + V", hl.dsp.exec_cmd("uwsm-app -- pkill rofi; rofi -modi 'clipboard:" .. scripts .. "/rofi/rofi_cliphist.sh' -show clipboard"), { description = "Clipboard History" })
+
+hl.bind(mainMod .. " + B", hl.dsp.exec_cmd("pkill hyprpicker || hyprpicker -a"), { description = "Color Picker" })
+
+-- Screenshots
+hl.bind(mainMod .. " + S", hl.dsp.exec_cmd(scripts .. "/images/dusky_screenshot.sh --region --freeze --no-notify"), { description = "Quick Screenshot" })
+hl.bind("SHIFT + Print", hl.dsp.exec_cmd("grim - | wl-copy && notify-send 'Fullscreen Screenshot in Clipboard'"), { locked = true, description = "Full Screen Quick Screenshot" })
+hl.bind(mainMod .. " + SHIFT + S", hl.dsp.exec_cmd(scripts .. "/images/dusky_screenshot.sh --region --freeze --annotate --no-notify --tool arrow"), { description = "Screenshot and Annotation" })
+hl.bind("Print", hl.dsp.exec_cmd("pgrep -x swappy || (grim - | uwsm-app -- satty -f -)"), { description = "Fullscreen Screenshot and Annotation" })
+hl.bind("SHIFT + CTRL + ALT + SPACE", hl.dsp.exec_cmd("uwsm-app -- pkill rofi; " .. scripts .. "/rofi/dusky_rofi_screenshot.sh"), { description = "Dusky Screenshoter" })
+
+-- Google Image Search
+hl.bind(mainMod .. " + G", hl.dsp.exec_cmd(scripts .. "/google_image_search/google_image_search.sh"), { description = "Image Search (Select and search)" })
+
+-- OCR (Tesseract)
+hl.bind(mainMod .. " + T", hl.dsp.exec_cmd("pgrep tesseract || (slurp | grim -g - - | tesseract stdin stdout -l eng | wl-copy)"), { description = "OCR Selection" })
+hl.bind(mainMod .. " + SHIFT + T", hl.dsp.exec_cmd("grim - | tesseract stdin stdout -l eng | wl-copy"), { description = "OCR Fullscreen" })
+
+-- Ollama Sidebar
+hl.bind(mainMod .. " + ALT + O", hl.dsp.exec_cmd("uwsm-app -- " .. terminal .. " --class ollama_terminal.sh -e " .. scripts .. "/llm/ollama_terminal.sh"), { description = "AI LLM Ollama Chat" })
+
+-- Music Recognition
+hl.bind(mainMod .. " + ALT + M", hl.dsp.exec_cmd("uwsm-app -- " .. terminal .. " --hold --class music_recognition.sh -e " .. scripts .. "/music/music_recognition.sh"), { description = "Music Recognition aka Shazam" })
+
+-- --- AI & Voice Tools ---
+hl.bind(mainMod .. " + O", hl.dsp.exec_cmd("wl-copy \"$(wl-paste -p)\" && uwsm-app -- " .. scripts .. "/tts_stt/dusky_kokoro/trigger.sh"), { description = "TTS Kokoro GPU" })
+hl.bind(mainMod .. " + SHIFT + O", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/audio/router/TTS_VC.sh"), { description = "TTS VC" })
+hl.bind(mainMod .. " + I", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/tts_stt/dusky_parakeet/trigger.sh"), { description = "STT Parakeet GPU" })
+
+-- =============================================================================
+-- NOTIFICATION ACTIONS (MAKO + ROFI)
+-- =============================================================================
+hl.bind(mainMod .. " + N", hl.dsp.exec_cmd("uwsm-app -- pkill rofi; " .. scripts .. "/rofi/rofi_mako.sh"), { description = "Notification History" })
+hl.bind(mainMod .. " + ALT + D", hl.dsp.exec_cmd("makoctl dismiss -a"), { locked = true, description = "Clear Screen Notifications" })
+hl.bind(mainMod .. " + ALT + F", hl.dsp.exec_cmd("makoctl menu -- rofi -dmenu -p 'Action: '"), { description = "Interact with Current Notification" })
+
+-- --- Screen Lock ---
+hl.bind(mainMod .. " + M", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/hyprlock/lock.sh"), { description = "Lock Screen" })
+
+-- =============================================================================
+-- 4. WINDOW MANAGEMENT
+-- =============================================================================
+hl.bind(mainMod .. " + C", hl.dsp.window.close(), { description = "Close Window" })
+hl.bind(mainMod .. " + A", hl.dsp.window.fullscreen({ mode = "fullscreen" }), { description = "Window Fullscreen" })
+hl.bind(mainMod .. " + SHIFT + A", hl.dsp.window.fullscreen({ mode = "maximized" }), { description = "Window Maximize" })
+hl.bind(mainMod .. " + X", hl.dsp.window.pin(), { description = "Pin Window" })
+hl.bind(mainMod .. " + Y", hl.dsp.layout("togglesplit"), { description = "Toggle Window Split" })
+hl.bind(mainMod .. " + SHIFT + D", hl.dsp.window.pseudo(), { description = "Toggle Pseudo" })
+
+-- Smart Float: Toggle float → Resize to 90% → Center
+hl.bind(mainMod .. " + D",
+ hl.dsp.exec_cmd("if hyprctl -j activewindow | jq -e '.floating | not'; then hyprctl --batch 'dispatch togglefloating; dispatch resizeactive exact 90% 90%; dispatch centerwindow'; else hyprctl dispatch togglefloating; fi"),
+ { description = "Toggle Float" })
+
+-- --- Focus Movement (hold-repeatable) ---
+hl.bind(mainMod .. " + h", hl.dsp.focus({ direction = "l" }), { repeating = true, description = "Focus Left" })
+hl.bind(mainMod .. " + l", hl.dsp.focus({ direction = "r" }), { repeating = true, description = "Focus Right" })
+hl.bind(mainMod .. " + k", hl.dsp.focus({ direction = "u" }), { repeating = true, description = "Focus Up" })
+hl.bind(mainMod .. " + j", hl.dsp.focus({ direction = "d" }), { repeating = true, description = "Focus Down" })
+
+-- --- Window Movement (hold-repeatable) ---
+hl.bind(mainMod .. " + SHIFT + h", hl.dsp.window.move({ direction = "l" }), { repeating = true, description = "Move Left" })
+hl.bind(mainMod .. " + SHIFT + l", hl.dsp.window.move({ direction = "r" }), { repeating = true, description = "Move Right" })
+hl.bind(mainMod .. " + SHIFT + k", hl.dsp.window.move({ direction = "u" }), { repeating = true, description = "Move Up" })
+hl.bind(mainMod .. " + SHIFT + j", hl.dsp.window.move({ direction = "d" }), { repeating = true, description = "Move Down" })
+
+-- --- Window Resizing (hold-repeatable) ---
+hl.bind(mainMod .. " + right", hl.dsp.window.resize({ x = 30, y = 0, relative = true }), { repeating = true, description = "Resize Width +" })
+hl.bind(mainMod .. " + left", hl.dsp.window.resize({ x = -30, y = 0, relative = true }), { repeating = true, description = "Resize Width -" })
+hl.bind(mainMod .. " + up", hl.dsp.window.resize({ x = 0, y = -30, relative = true }), { repeating = true, description = "Resize Height -" })
+hl.bind(mainMod .. " + down", hl.dsp.window.resize({ x = 0, y = 30, relative = true }), { repeating = true, description = "Resize Height +" })
+
+-- =============================================================================
+-- 5. WORKSPACE MANAGEMENT (Context-Aware / Banked)
+-- =============================================================================
+
+local ws_script = home .. "/user_scripts/hypr/multi_monitor_workspace.sh"
+
+-- Switch to Workspace (Context Relative)
+for i = 1, 10 do
+ local key = i % 10
+ hl.bind(mainMod .. " + " .. key, hl.dsp.exec_cmd(ws_script .. " workspace " .. i), { description = "Switch To Context " .. i })
+ hl.bind(mainMod .. " + SHIFT + " .. key, hl.dsp.exec_cmd(ws_script .. " movetoworkspace " .. i), { description = "Move To Context " .. i })
+ hl.bind(mainMod .. " + ALT + " .. key, hl.dsp.exec_cmd(ws_script .. " movetoworkspacesilent " .. i), { description = "Silent Move To Context " .. i })
+end
+
+-- --- Back and forth with last workspace ---
+hl.bind(mainMod .. " + TAB", hl.dsp.focus({ workspace = "previous" }), { repeating = true, description = "Last Workspace" })
+
+-- Cycle Workspaces
+hl.bind("ALT + SHIFT + TAB", hl.dsp.focus({ workspace = "e-1" }), { repeating = true, description = "Cycle Backward" })
+hl.bind(mainMod .. " + SHIFT + TAB", hl.dsp.focus({ workspace = "e+1" }), { repeating = true, description = "Cycle Next WS" })
+
+-- Special Workspace (Scratchpad)
+hl.bind(mainMod .. " + Z", hl.dsp.workspace.toggle_special("magic"), { description = "Toggle Scratchpad" })
+hl.bind(mainMod .. " + SHIFT + Z", hl.dsp.window.move({ workspace = "special:magic" }), { description = "Move to Scratchpad" })
+
+-- Special Workspace for Spotify
+hl.bind(mainMod .. " + SHIFT + M", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/spotify/spotify_toggle.sh"))
+
+-- =============================================================================
+-- 6. MOUSE BINDINGS
+-- =============================================================================
+hl.bind(mainMod .. " + mouse:272", hl.dsp.window.drag(), { mouse = true, description = "Move Window" })
+hl.bind(mainMod .. " + mouse:273", hl.dsp.window.resize(), { mouse = true, description = "Resize Window" })
+
+-- =============================================================================
+-- 7. HARDWARE & MEDIA KEYS
+-- =============================================================================
+
+-- Volume
+hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --vol-up 5"), { locked = true, repeating = true, description = "Volume up" })
+hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --vol-down 5"), { locked = true, repeating = true, description = "Volume down" })
+hl.bind("XF86AudioMute", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --vol-mute"), { locked = true, repeating = true, description = "Mute" })
+hl.bind("XF86AudioMicMute", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --mic-mute"), { locked = true, repeating = true, description = "Mute microphone" })
+
+-- Brightness
+hl.bind("XF86MonBrightnessUp", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --bright-up 5"), { locked = true, repeating = true, description = "Brightness up" })
+hl.bind("XF86MonBrightnessDown", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --bright-down 5"), { locked = true, repeating = true, description = "Brightness down" })
+
+-- Precise Adjustments (Alt Modifier)
+hl.bind("ALT + XF86AudioRaiseVolume", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --vol-up 1"), { locked = true, repeating = true, description = "Volume up precise" })
+hl.bind("ALT + XF86AudioLowerVolume", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --vol-down 1"), { locked = true, repeating = true, description = "Volume down precise" })
+hl.bind("ALT + XF86MonBrightnessUp", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --bright-up 1"), { locked = true, repeating = true, description = "Brightness up precise" })
+hl.bind("ALT + XF86MonBrightnessDown", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --bright-down 1"), { locked = true, repeating = true, description = "Brightness down precise" })
+
+-- Keyboard Backlight
+hl.bind("XF86KbdBrightnessUp", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --kbd-bright-up 10"), { locked = true, repeating = true, description = "Keyboard Brightness up" })
+hl.bind("XF86KbdBrightnessDown", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --kbd-bright-down 10"), { locked = true, repeating = true, description = "Keyboard Brightness down" })
+
+-- Player Controls (routed through script for OSD feedback)
+hl.bind("XF86AudioNext", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --next"), { locked = true, description = "Next track" })
+hl.bind("XF86AudioPrev", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --prev"), { locked = true, description = "Previous track" })
+hl.bind("XF86AudioPlay", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --play-pause"), { locked = true, description = "Play" })
+hl.bind("XF86AudioPause", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --play-pause"), { locked = true, description = "Pause" })
+hl.bind("XF86AudioStop", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --stop"), { locked = true, description = "Stop" })
+hl.bind(mainMod .. " + P", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --play-pause"), { locked = true, description = "Toggle Pause" })
+
+-- Custom Audio/Mic Switching Scripts
+hl.bind("ALT + P", hl.dsp.exec_cmd(scripts .. "/mako_osd/osd_router/osd_router.sh --vol-mute"), { locked = true, description = "Mute Audio" })
+hl.bind("ALT + M", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/audio/mono_audio_pipewire.py"), { locked = true, description = "Mono Audio Toggle" })
+hl.bind("ALT + O", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/audio/audio_switch.sh"), { locked = true, description = "Switch Audio Output" })
+hl.bind("ALT + I", hl.dsp.exec_cmd("uwsm-app -- " .. scripts .. "/audio/mic_switch.sh"), { locked = true, description = "Switch Mic Input" })
+
+-- Calculator
+hl.bind("XF86Calculator", hl.dsp.exec_cmd("uwsm-app -- gnome-calculator"), { description = "Calculator" })
diff --git a/.config/hypr/source/monitors.conf b/.config/hypr/source/monitors.conf.deprecated
similarity index 100%
rename from .config/hypr/source/monitors.conf
rename to .config/hypr/source/monitors.conf.deprecated
diff --git a/.config/hypr/source/monitors.lua b/.config/hypr/source/monitors.lua
new file mode 100644
index 00000000..daf84da3
--- /dev/null
+++ b/.config/hypr/source/monitors.lua
@@ -0,0 +1,11 @@
+-- =============================================================================
+-- MONITORS — Base Configuration
+-- =============================================================================
+-- DO NOT EDIT THIS FILE.
+-- Configure your monitors in ~/.config/hypr/edit_here/source/monitors.lua
+-- which is loaded last and overrides these defaults.
+-- =============================================================================
+
+-- Fallback: auto-detect all connected monitors with preferred mode
+-- This is intentionally minimal; actual setup lives in edit_here.
+hl.monitor({ output = "", mode = "preferred", position = "auto", scale = 1 })
diff --git a/.config/hypr/source/permissions.conf b/.config/hypr/source/permissions.conf.deprecated
similarity index 100%
rename from .config/hypr/source/permissions.conf
rename to .config/hypr/source/permissions.conf.deprecated
diff --git a/.config/hypr/source/permissions.lua b/.config/hypr/source/permissions.lua
new file mode 100644
index 00000000..b41881fe
--- /dev/null
+++ b/.config/hypr/source/permissions.lua
@@ -0,0 +1,24 @@
+-- =============================================================================
+-- SYSTEM PERMISSIONS ("HARDENED MODE")
+-- =============================================================================
+-- By default, Hyprland allows apps to capture the screen via standard portals.
+-- Uncomment the ecosystem block ONLY if you want to lock down your system and
+-- manually whitelist every app that needs screen access.
+--
+-- hl.config({ ecosystem = { enforce_permissions = true } })
+-- =============================================================================
+
+-- --- Whitelist (only active if ecosystem enforcement is enabled above) ---
+
+-- Allow standard screenshot tools
+hl.permission({ binary = "/usr/(bin|local/bin)/grim", type = "screencopy", mode = "allow" })
+hl.permission({ binary = "/usr/(bin|local/bin)/slurp", type = "screencopy", mode = "allow" })
+
+-- Allow the Portal (CRITICAL: this is what OBS uses)
+hl.permission({ binary = "/usr/(lib|libexec|lib64)/xdg-desktop-portal-hyprland", type = "screencopy", mode = "allow" })
+
+-- Allow Waybar (for workspace/window info modules)
+hl.permission({ binary = "/usr/bin/waybar", type = "screencopy", mode = "allow" })
+
+-- Hyprpm (plugin manager)
+hl.permission({ binary = "/usr/(bin|local/bin)/hyprpm", type = "plugin", mode = "allow" })
diff --git a/.config/hypr/source/plugins.conf b/.config/hypr/source/plugins.conf.deprecated
similarity index 100%
rename from .config/hypr/source/plugins.conf
rename to .config/hypr/source/plugins.conf.deprecated
diff --git a/.config/hypr/source/plugins.lua b/.config/hypr/source/plugins.lua
new file mode 100644
index 00000000..9ae05bbf
--- /dev/null
+++ b/.config/hypr/source/plugins.lua
@@ -0,0 +1,23 @@
+-- =============================================================================
+-- PLUGINS CONFIGURATION
+-- =============================================================================
+-- Hyprland plugins: reloads your plugins on start
+-- Manage plugins with: hyprpm add / enable / disable / update
+-- =============================================================================
+
+-- Reload all installed/enabled hyprpm plugins on startup
+hl.on("hyprland.start", function()
+ hl.exec_cmd("hyprpm reload")
+end)
+
+-- hyprexpo plugin configuration
+-- (only takes effect if hyprexpo is installed via hyprpm)
+if hl.plugin and hl.plugin.hyprexpo then
+ hl.plugin.hyprexpo.configure({
+ columns = 3,
+ gap_size = 5,
+ bg_col = "rgb(111111)",
+ workspace_method = "first 1", -- [center/first] [workspace]
+ gesture_distance = 300, -- how far is the "max" for the gesture
+ })
+end
diff --git a/.config/hypr/source/window_rules.conf b/.config/hypr/source/window_rules.conf.deprecated
similarity index 98%
rename from .config/hypr/source/window_rules.conf
rename to .config/hypr/source/window_rules.conf.deprecated
index 42646461..ae4f0a3a 100644
--- a/.config/hypr/source/window_rules.conf
+++ b/.config/hypr/source/window_rules.conf.deprecated
@@ -1278,6 +1278,47 @@ windowrule {
center = on
}
+#--- WireGuard terminal windows ---
+windowrule {
+ name = dusky_wg_new
+ match:class = ^(dusky_wg_new)$
+ float = on
+ size = 700 480
+ center = on
+}
+
+windowrule {
+ name = dusky_wg_setup
+ match:class = ^(dusky_wg_setup)$
+ float = on
+ size = 700 420
+ center = on
+}
+
+windowrule {
+ name = dusky_wg_status
+ match:class = ^(dusky_wg_status)$
+ float = on
+ size = 720 400
+ center = on
+}
+
+windowrule {
+ name = dusky_wg_edit
+ match:class = ^(dusky_wg_edit)$
+ float = on
+ size = 700 420
+ center = on
+}
+
+windowrule {
+ name = dusky_wg_delete
+ match:class = ^(dusky_wg_delete)$
+ float = on
+ size = 500 200
+ center = on
+}
+
#--- music recognition script---
windowrule {
name = music_recognition.sh
diff --git a/.config/hypr/source/window_rules.lua b/.config/hypr/source/window_rules.lua
new file mode 100644
index 00000000..b4e16466
--- /dev/null
+++ b/.config/hypr/source/window_rules.lua
@@ -0,0 +1,393 @@
+-- =============================================================================
+-- WINDOW RULES & LAYER RULES
+-- =============================================================================
+-- DO NOT EDIT THIS FILE.
+-- Add custom rules in ~/.config/hypr/edit_here/source/window_rules.lua
+-- =============================================================================
+
+-- -----------------------------------------------------------------------------
+-- GLOBAL / XWAYLAND SETTINGS
+-- -----------------------------------------------------------------------------
+hl.config({ xwayland = { force_zero_scaling = true } })
+
+-- -----------------------------------------------------------------------------
+-- APPLICATION-SPECIFIC FLOATS & VISUALS
+-- -----------------------------------------------------------------------------
+
+--— Firefox: Float "About" Dialog —
+hl.window_rule({ name = "float-firefox-about", match = { title = "^(About Mozilla Firefox)$" }, float = true })
+
+--— Firefox: Float "Library" Window —
+hl.window_rule({ name = "float-firefox-library", match = { class = "^(firefox)$", title = "^(Library)$" }, float = true })
+
+--— Firefox: YouTube Full Opacity —
+hl.window_rule({ name = "opaque-firefox-youtube", match = { class = "^(firefox)$", title = ".*YouTube.*" }, opaque = true })
+
+--— Firefox: Figma Full Opacity —
+hl.window_rule({ name = "opaque-firefox-figma", match = { class = "^(firefox)$", title = ".*Figma.*" }, opaque = true })
+
+--— Firefox: Pixabay Full Opacity —
+hl.window_rule({ name = "opaque-firefox-pixabay", match = { class = "^(firefox)$", title = ".*Pixabay.*" }, opaque = true })
+
+--— MPV: Always Float & Small —
+hl.window_rule({ name = "float-mpv", match = { class = "^(mpv)$" }, float = true, opaque = true, size = "640 360", center = true })
+
+--— Wine/Proton: Hide empty tray windows —
+hl.window_rule({ name = "xembedsniproxy", match = { class = "^$", title = "^$" }, opacity = "0.0 override 0.0 override", no_blur = true })
+
+-- -----------------------------------------------------------------------------
+-- QBITTORRENT: Floating Logic (Layered Approach)
+-- -----------------------------------------------------------------------------
+
+-- 1. Default Policy: Float ALL qBittorrent windows
+hl.window_rule({ name = "float_qbittorrent_all", match = { class = "^(org.qbittorrent.qBittorrent)$" }, float = true, center = true, size = "650 450" })
+
+-- 2. Exception: Force the Main Window to Tile
+hl.window_rule({ name = "tile_qbittorrent_main", match = { class = "^(org.qbittorrent.qBittorrent)$", title = "^(qBittorrent v).*$" }, float = false })
+
+-- -----------------------------------------------------------------------------
+-- GAMES AND GAME LAUNCHERS
+-- -----------------------------------------------------------------------------
+hl.window_rule({ name = "PrismLauncher", match = { class = "org.prismlauncher.PrismLauncher" }, float = true })
+hl.window_rule({ name = "Minecraft", match = { class = "com.mojang.minecraft.java-edition" }, opaque = true })
+hl.window_rule({ name = "Tetr.io", match = { class = "tetrio-desktop" }, opaque = true })
+hl.window_rule({ name = "SuperTuxKart", match = { class = "supertuxkart" }, opaque = true })
+hl.window_rule({ name = "ROBLOX", match = { class = "org.vinegarhq.Sober" }, opaque = true })
+
+-- -----------------------------------------------------------------------------
+-- STEAM
+-- -----------------------------------------------------------------------------
+hl.window_rule({ name = "steam-general", match = { class = "^(steam)$" }, float = true, opaque = true })
+hl.window_rule({ name = "steam-main-window", match = { class = "^(steam)$", title = "^(Steam)$" }, size = "1100 600", center = true })
+hl.window_rule({ name = "steam-friends", match = { class = "^(steam)$", title = "^(Friends List)$" }, size = "460 580" })
+hl.window_rule({ name = "steam-idle", match = { class = "^(steam)$" }, idle_inhibit = "fullscreen" })
+
+-- -----------------------------------------------------------------------------
+-- SHOW ME THE KEY (Key Visualizer)
+-- -----------------------------------------------------------------------------
+hl.window_rule({
+ name = "showmethekey-floating",
+ match = { class = "^(showmethekey-gtk)$", title = "^(Floating Window - Show Me The Key)$" },
+ float = true,
+ pin = true,
+ size = "470 50",
+ move = "((monitor_w-window_w)/2) (monitor_h-window_h-20)",
+ no_dim = true,
+ border_size = 0,
+ opaque = true,
+})
+
+-- -----------------------------------------------------------------------------
+-- COMMON DESKTOP / GNOME / QT UTILITIES
+-- -----------------------------------------------------------------------------
+hl.window_rule({ name = "uGet", match = { title = "^(uGet)$" }, float = true, size = "889 505", center = true })
+hl.window_rule({ name = "float-calculator", match = { class = "^(org.gnome.Calculator)$" }, float = true, size = "360 616", center = true })
+hl.window_rule({ name = "gnome-camera", match = { class = "^(org.gnome.Snapshot)$" }, float = true, size = "528 298", center = true })
+hl.window_rule({ name = "float-cameractrls", match = { class = "^(hu.irl.cameractrls)$", title = "^(/dev/.*)$" }, float = true, size = "624 353", center = true })
+hl.window_rule({ name = "float-loupe", match = { class = "^(org.gnome.Loupe)$" }, float = true, size = "900 600", center = true, opaque = true })
+hl.window_rule({ name = "float-clocks", match = { class = "^(org.gnome.clocks)$" }, float = true, size = "602 297", center = true })
+hl.window_rule({ name = "gparted", match = { class = "^(GParted)$" }, float = true, size = "652 431", center = true })
+hl.window_rule({ name = "grsync", match = { class = "^(grsync)$" }, float = true, size = "650 458", center = true })
+hl.window_rule({ name = "float-blueman", match = { class = "^(blueman-manager)$" }, float = true, size = "530 313", center = true })
+hl.window_rule({ name = "handbrake", match = { class = "^(fr.handbrake.ghb)$" }, float = true, size = "970 698", center = true })
+hl.window_rule({ name = "seahorse", match = { class = "^(org.gnome.seahorse.Application)$" }, float = true, size = "827 632", center = true })
+hl.window_rule({ name = "bluetui", match = { class = "^(bluetui)$" }, float = true, size = "551 362", center = true })
+hl.window_rule({ name = "airmon_ng", match = { class = "^(airmon_ng.sh)$" }, float = true, size = "775 450", center = true })
+hl.window_rule({ name = "iphone_vnc", match = { class = "^(iphone_vnc.sh)$" }, float = true, size = "650 423", center = true })
+hl.window_rule({ name = "btrfs_stats", match = { class = "^(btrfs_zstd_compression_stats.sh)$" }, float = true, size = "650 423", center = true })
+hl.window_rule({ name = "tailscale_setup", match = { class = "^(tailscale_setup)$" }, float = true, size = "782 676", center = true })
+hl.window_rule({ name = "tailscale_remove", match = { class = "^(tailscale_uninstall)$" }, float = true, size = "775 450", center = true })
+hl.window_rule({ name = "kew", match = { class = "^(kew)$" }, float = true, size = "652 576", center = true })
+hl.window_rule({ name = "file_manager_switcher", match = { class = "^(235_file_manager_switch.sh)$" }, float = true, size = "634 445", center = true })
+hl.window_rule({ name = "browser_switcher", match = { class = "^(236_browser_switcher.sh)$" }, float = true, size = "634 445", center = true })
+hl.window_rule({ name = "text_editor_switch",match = { class = "^(237_text_editer_switcher.sh)$" }, float = true, size = "634 445", center = true })
+hl.window_rule({ name = "terminal_switcher", match = { class = "^(238_terminal_switcher.sh)$" }, float = true, size = "634 445", center = true })
+hl.window_rule({ name = "plugin_manager", match = { class = "^(356_dusky_plugin_manager.sh)$" }, float = true, size = "772 554", center = true })
+hl.window_rule({ name = "ftp_setup", match = { class = "^(250_ftp_arch.sh)$" }, float = true, size = "652 576", center = true })
+hl.window_rule({ name = "hosts_block", match = { class = "^(325_hosts_files_block.sh)$" }, float = true, size = "780 548", center = true })
+hl.window_rule({ name = "locale_tui", match = { class = "^(locale_tui.sh)$" }, float = true, size = "780 548", center = true })
+hl.window_rule({ name = "mako_tui_glance", match = { class = "^(glance_mako_tui.sh)$" }, float = true, size = "780 548", center = true })
+hl.window_rule({ name = "change_ftp_dir", match = { class = "^(change_ftp_directory_server.sh)$" }, float = true, size = "652 576", center = true })
+hl.window_rule({ name = "arp_scan", match = { class = "^(arp_scan.sh)$" }, float = true, size = "652 576", center = true })
+hl.window_rule({ name = "openssh_setup", match = { class = "^(02_openssh_setup.sh)$" }, float = true, size = "652 576", center = true })
+hl.window_rule({ name = "clipboard_persist", match = { class = "^(390_clipboard_persistance.sh)$" }, float = true, size = "805 323", center = true })
+hl.window_rule({ name = "cache_purge", match = { class = "^(cache_purge.sh)$" }, float = true, size = "589 529", center = true })
+hl.window_rule({ name = "mouse_btn_reverse", match = { class = "^(mouse_button_reverse.sh)$" }, float = true, size = "589 529", center = true })
+hl.window_rule({ name = "git_config", match = { class = "^(300_git_config.sh)$" }, float = true, size = "726 389", center = true })
+hl.window_rule({ name = "new_github_repo", match = { class = "^(305_new_github_repo_to_backup.sh)$" }, float = true, size = "726 689", center = true })
+hl.window_rule({ name = "relink_github", match = { class = "^(310_reconnect_and_push_new_changes_to_github.sh)$" }, float = true, size = "726 689", center = true })
+hl.window_rule({ name = "io_monitor", match = { class = "^(io_monitor.sh)$" }, float = true, size = "960 300", center = true })
+hl.window_rule({ name = "terminal_clipboard",match = { class = "^(terminal_clipboard.sh)$" }, float = true, no_anim = true, size = "840 520", center = true })
+hl.window_rule({ name = "asusctl", match = { class = "^(asusctl.sh)$" }, float = true, size = "789 534", center = true })
+hl.window_rule({ name = "nvim_reset", match = { class = "^(01_reset_neovim.sh)$" }, float = true, size = "730 454", center = true })
+hl.window_rule({ name = "cli_plugins", match = { class = "^(02_cli_plugins_download.sh)$" }, float = true, size = "730 454", center = true })
+hl.window_rule({ name = "nvim_manager", match = { class = "^(dusky_neovim_manager.sh)$" }, float = true, size = "532 475", center = true })
+hl.window_rule({ name = "paru_optional", match = { class = "^(090_paru_packages_optional%.sh)$" }, float = true, size = "831 572" })
+hl.window_rule({ name = "zram_config", match = { class = "^(205_zram_configuration.sh)$" }, float = true, size = "907 377", center = true })
+hl.window_rule({ name = "limine_setup", match = { class = "^(01_limine_setup.sh)$" }, float = true, size = "730 454", center = true })
+hl.window_rule({ name = "snapper_subvol", match = { class = "^(02_snapper_isolation_subvolume.sh)$" }, float = true, size = "730 454", center = true })
+hl.window_rule({ name = "snapper_hooks", match = { class = "^(03_snapper_pacman_hooks.sh)$" }, float = true, size = "730 454", center = true })
+hl.window_rule({ name = "swappiness", match = { class = "^(210_zram_optimize_swappiness%.sh)$" }, float = true, size = "938 500", center = true })
+hl.window_rule({ name = "gpu_env", match = { class = "^(000_configure_uwsm_gpu%.sh)$" }, float = true, size = "702 492", center = true })
+hl.window_rule({ name = "wayclick_setup", match = { class = "^(dusky_wayclick.sh)$" }, float = true, size = "831 572" })
+hl.window_rule({ name = "wayclick_tui", match = { class = "^(dusky_tui_wayclick.sh)$" }, float = true, size = "780 510" })
+hl.window_rule({ name = "wayclick_sounds", match = { class = "^(wayclick_soundpacks_download.sh)$" }, float = true, size = "580 810" })
+hl.window_rule({ name = "tty_autologin", match = { class = "^(285_tty_autologin.sh)$" }, float = true, size = "730 454", center = true })
+hl.window_rule({ name = "dusky_monitor", match = { class = "^(dusky_monitor.sh)$" }, float = true, size = "802 469", center = true })
+hl.window_rule({ name = "dusky_keybinds", match = { class = "^(dusky_keybinds.sh)$" }, float = true, size = "(monitor_w*0.9) (monitor_h*0.9)", move = "(monitor_w*0.05) (monitor_h*0.05)" })
+hl.window_rule({ name = "dusky_appearances", match = { class = "^(dusky_appearances.sh)$" }, float = true, size = "781 507", center = true })
+hl.window_rule({ name = "dusky_workspace", match = { class = "^(dusky_workspace_manager.sh)$" }, float = true, size = "781 507", center = true })
+hl.window_rule({ name = "dusky_matugen", match = { class = "^(dusky_matugen_presets.sh)$" }, float = true, size = "820 620", center = true })
+hl.window_rule({ name = "dusky_input", match = { class = "^(dusky_input.sh)$" }, float = true, size = "781 507", center = true })
+hl.window_rule({ name = "tui_mako", match = { class = "^(tui_mako.sh)$" }, float = true, size = "781 507", center = true })
+hl.window_rule({ name = "dusky_gsettings", match = { class = "^(dusky_gsettings.sh)$" }, float = true, size = "781 507", center = true })
+hl.window_rule({ name = "dconf_editor", match = { class = "^(ca%.desrt%.dconf-editor)$" }, float = true, size = "979 642" })
+hl.window_rule({ name = "dusky_power", match = { class = "^(dusky_power.sh)$" }, float = true, size = "790 530", center = true })
+hl.window_rule({ name = "dusky_battery", match = { class = "^(dusky_battery_notify.sh)$" }, float = true, size = "790 530", center = true })
+hl.window_rule({ name = "battery_service", match = { class = "^(135_battery_notify_service.sh)$" }, float = true, size = "504 501", center = true })
+hl.window_rule({ name = "dusky_hypridle", match = { class = "^(dusky_hypridle.sh)$" }, float = true, size = "784 529", center = true })
+hl.window_rule({ name = "fastfetch", match = { class = "^(fastfetch)$" }, float = true, size = "943 393", center = true })
+hl.window_rule({ name = "dusky_winrules", match = { class = "^(dusky_window_rules.sh)$" }, float = true, size = "1000 750", center = true })
+hl.window_rule({ name = "dysk", match = { class = "^(dysk)$" }, float = true, size = "1005 298", center = true })
+hl.window_rule({ name = "performance", match = { class = "^(performance.sh)$" }, float = true, size = "566 569", center = true })
+
+-- Kokoro TTS: Floating corner widget
+hl.window_rule({
+ name = "kokoro",
+ match = { class = "^(kokoro)$" },
+ float = true,
+ pin = true,
+ size = "254 90",
+ move = "(monitor_w-window_w-8) (monitor_h-window_h-8)",
+ no_dim = true,
+ opaque = true,
+})
+
+hl.window_rule({ name = "kokoro_installer", match = { class = "^(kokoro_installer.sh)$" }, float = true, pin = true, size = "876 601" })
+hl.window_rule({ name = "parakeet_installer", match = { class = "^(parakeet_installer.sh)$" }, float = true, pin = true, size = "876 601" })
+hl.window_rule({ name = "peaclock", match = { class = "^(peaclock)$" }, float = true, size = "406 179", center = true })
+hl.window_rule({ name = "wifitui", match = { class = "^(wifitui)$" }, float = true, size = "596 318", center = true })
+hl.window_rule({ name = "dusky_network", match = { class = "^(dusky_network.sh)$" }, float = true, size = "741 579", center = true })
+hl.window_rule({ name = "tray_tui", match = { class = "^(tray-tui)$" }, float = true, size = "791 488", center = true })
+hl.window_rule({ name = "cava", match = { class = "^(cava)$" }, float = true, size = "791 488", center = true })
+hl.window_rule({ name = "htop", match = { class = "^(htop)$" }, float = true, size = "1080 607", center = true })
+hl.window_rule({ name = "dgop", match = { class = "^(dgop)$" }, float = true, size = "1080 607", center = true })
+hl.window_rule({ name = "btop", match = { class = "^(btop)$" }, float = true, size = "1080 607", center = true })
+hl.window_rule({ name = "nvim", match = { class = "^(nvim)$" }, float = true, size = "455 549", center = true })
+
+-- GNOME Text Editor: large editor for hypr config
+hl.window_rule({ name = "gnome-text-editor", match = { class = "^(org.gnome.TextEditor)$" },
+ float = true, size = "(monitor_w*0.65) (monitor_h*0.92)", move = "(monitor_w*0.05) (monitor_h*0.05)", center = true })
+
+hl.window_rule({ name = "errands", match = { title = "^(Errands)$" }, float = true, size = "519 614", center = true })
+hl.window_rule({ name = "backups", match = { class = "^(thunar)$", title = "^(dusky_backups - Thunar)$" }, float = true, size = "(monitor_w*0.5612) (monitor_h*0.8)", center = true })
+hl.window_rule({ name = "yazi_backup", match = { class = "^(yazi)$", title = "^(Backup Viewer)$" }, float = true, size = "(monitor_w*0.6283) (monitor_h*0.8600)", center = true })
+
+-- Dusky Control Center
+hl.window_rule({
+ name = "dusky_control_center",
+ match = { title = "^(Dusky Control Center)$", class = "^(com.github.dusky.controlcenter)$" },
+ float = true,
+ animation = "slide down",
+ size = "(monitor_w*0.50) (monitor_h*0.92)",
+ center = true,
+})
+
+-- Dusky QuickPanel (sliders)
+hl.window_rule({
+ name = "dusky_quickpanal",
+ match = { title = "^(dusky_quickpanal.py)$", class = "^(org.dusky.quickpanal)$" },
+ float = true,
+ animation = "slide right",
+ no_dim = true,
+ rounding = 20,
+ move = "(monitor_w-window_w-20) (monitor_h-window_h-20)",
+ border_size = 0,
+})
+
+hl.window_rule({ name = "audiorouter-popup", match = { class = "^(dev%.audiorouter%.popup)$" }, float = true, center = true, size = "(monitor_w*0.4557) (monitor_h*0.9324)" })
+hl.window_rule({ name = "disks", match = { title = "^(Disks)$", class = "^(org.gnome.DiskUtility)$" }, float = true, size = "890 512", center = true })
+hl.window_rule({ name = "baobab", match = { class = "^(org.gnome.baobab)$" }, float = true, size = "1152 648", center = true })
+hl.window_rule({ name = "thunar_rename", match = { class = "Thunar", title = "^Rename.*$" }, float = true })
+
+hl.window_rule({ name = "sysbench", match = { class = "^(sysbench_benchmark.sh)$" }, float = true, size = "567 658", center = true })
+hl.window_rule({ name = "ntfs_fix", match = { class = "^(ntfs_fix.sh)$" }, float = true, size = "766 485", center = true })
+hl.window_rule({ name = "power_saver", match = { class = "^(power_saver.sh)$" }, float = true, size = "737 628", center = true })
+hl.window_rule({ name = "power_saver_off", match = { class = "^(power_saver_off.sh)$" }, float = true, size = "568 456", center = true })
+hl.window_rule({ name = "aur_fallback", match = { class = "^(080_aur_paru_fallback_yay.sh)$" }, float = true, size = "567 658", center = true })
+hl.window_rule({ name = "warp_setup", match = { class = "^(085_warp.sh)$" }, float = true, size = "567 658", center = true })
+hl.window_rule({ name = "preload_config", match = { class = "^(335_preload_config.sh)$" }, float = true, size = "889 669", center = true })
+hl.window_rule({ name = "sddm_setup", match = { class = "^(465_sddm_setup.sh)$" }, float = true, size = "889 669", center = true })
+hl.window_rule({ name = "update_dusky", match = { class = "^(update_dusky.sh)$" }, float = true, size = "1192 710", center = true })
+hl.window_rule({ name = "system_update", match = { class = "^(system_update.sh)$" }, float = true, pin = true, size = "1192 710", center = true })
+
+hl.window_rule({ name = "ORCHESTRA", match = { class = "^(ORCHESTRA.sh)$" }, float = true, size = "(monitor_w*0.9) (monitor_h*0.9)", move = "(monitor_w*0.05) (monitor_h*0.05)" })
+hl.window_rule({ name = "deploy_dotfiles", match = { class = "^(deploy_dotfiles.sh)$" }, float = true, size = "(monitor_w*0.9) (monitor_h*0.9)", move = "(monitor_w*0.05) (monitor_h*0.05)" })
+hl.window_rule({ name = "restore_stash", match = { class = "^(restore_stash.sh)$" }, float = true, size = "1192 710", center = true })
+hl.window_rule({ name = "send_logs", match = { class = "^(send_logs.sh)$" }, float = true, size = "500 250", center = true })
+hl.window_rule({ name = "about_dusky", match = { class = "^(about_dusky.sh)$" }, float = true, size = "503 264", center = true })
+
+-- Ollama sidebar: left-edge slide panel
+hl.window_rule({
+ name = "ollama_sidebar",
+ match = { class = "^(ollama_terminal.sh)$" },
+ float = true,
+ size = "(monitor_w*0.28) (monitor_h*0.88)",
+ animation = "slide left",
+ rounding = 9,
+ move = "(monitor_w*0.038) (monitor_h*0.5 - window_h*0.5)",
+})
+
+hl.window_rule({ name = "dusky_service_toggle", match = { class = "^(dusky_service_toggle.sh)$" }, float = true, size = "840 598", center = true })
+
+-- WireGuard terminal windows
+hl.window_rule({ name = "dusky_wg_new", match = { class = "^(dusky_wg_new)$" }, float = true, size = "700 480", center = true })
+hl.window_rule({ name = "dusky_wg_setup", match = { class = "^(dusky_wg_setup)$" }, float = true, size = "700 420", center = true })
+hl.window_rule({ name = "dusky_wg_status", match = { class = "^(dusky_wg_status)$" }, float = true, size = "720 400", center = true })
+hl.window_rule({ name = "dusky_wg_edit", match = { class = "^(dusky_wg_edit)$" }, float = true, size = "700 420", center = true })
+hl.window_rule({ name = "dusky_wg_delete", match = { class = "^(dusky_wg_delete)$" }, float = true, size = "500 200", center = true })
+
+hl.window_rule({ name = "music_recognition", match = { class = "^(music_recognition.sh)$" }, float = true, size = "409 147", center = true })
+hl.window_rule({ name = "hyprlock_switcher", match = { class = "^(dusky_hyprlock_switcher.sh)$" }, float = true, size = "821 508", center = true })
+hl.window_rule({ name = "dusky_waybars", match = { class = "^(dusky_waybars.sh)$" }, float = true, size = "780 510", center = true })
+hl.window_rule({ name = "float-zathura", match = { class = "^(org.pwmt.zathura)$" }, float = true, size = "655 526", center = true })
+hl.window_rule({ name = "float-waypaper", match = { class = "^(waypaper)$" }, float = true, size = "786 492", center = true })
+hl.window_rule({ name = "float-share-picker", match = { class = "^(hyprland-share-picker)$" }, float = true, size = "500 300", center = true })
+hl.window_rule({ name = "float-nwg-look", match = { class = "^(nwg-look)$" }, float = true, size = "627 464", center = true })
+hl.window_rule({ name = "float-kvantum", match = { class = "^(kvantummanager)$" }, float = true, size = "585 512", center = true })
+hl.window_rule({ name = "float-qt6ct", match = { class = "^(qt6ct)$" }, float = true, size = "700 609", center = true })
+hl.window_rule({ name = "float-qt5ct", match = { class = "^(qt5ct)$" }, float = true, size = "636 665", center = true })
+hl.window_rule({ name = "float-guifetch", match = { class = "^(guifetch)$" }, float = true, size = "800 500", center = true })
+hl.window_rule({ name = "float-pavucontrol", match = { class = "^(pavucontrol|org.pulseaudio.pavucontrol)$" }, float = true, size = "643 422", center = true })
+hl.window_rule({ name = "float-nm-editor", match = { class = "^(nm-connection-editor)$" }, float = true, size = "432 423", center = true })
+
+hl.window_rule({ name = "float_vm_viewer", match = { class = "^(virt-manager)$", title = "^(.* on QEMU/KVM)$" },
+ float = true, center = true, size = "1043 634" })
+
+-- satty (annotation tool)
+hl.window_rule({ name = "satty", match = { class = "^(com%.gabm%.satty)$" },
+ center = true, float = true, opaque = true, animation = "slide down", size = "1115 624" })
+
+-- -----------------------------------------------------------------------------
+-- PICTURE-IN-PICTURE (PiP) & PINNED WINDOWS
+-- -----------------------------------------------------------------------------
+
+-- PiP: bottom-right corner, pinned
+hl.window_rule({
+ name = "pip-global",
+ match = { title = "^([Pp]icture[-\\s]?[Ii]n[-\\s]?[Pp]icture)(.*)$" },
+ float = true,
+ pin = true,
+ size = "248 140",
+ move = "(monitor_w-window_w-20) (monitor_h-window_h-20)",
+ no_dim = true,
+ opaque = true,
+})
+
+-- Pinned Window Styling: green border for any pinned window
+hl.window_rule({
+ name = "style-pinned-windows",
+ match = { pin = true },
+ no_dim = true,
+ border_color = "rgb(328E6E)",
+ border_size = 2,
+ animation = "slide down",
+})
+
+-- -----------------------------------------------------------------------------
+-- GLOBAL WINDOW BEHAVIORS
+-- -----------------------------------------------------------------------------
+
+-- Persistent Size: floating windows remember their size on reopen
+hl.window_rule({ name = "global-persistent-size", match = { float = true }, persistent_size = true })
+
+-- Prevent Maximize Events: force apps to respect tiling/floating rules
+hl.window_rule({ name = "global-suppress-maximize", match = { class = ".*" }, suppress_event = "maximize" })
+
+-- -----------------------------------------------------------------------------
+-- XWAYLAND / PHANTOM WINDOW FIX
+-- -----------------------------------------------------------------------------
+-- Invisible XWayland tooltips/drag-previews that steal focus
+hl.window_rule({
+ name = "fix-xwayland-phantom",
+ match = { class = "^$", title = "^$", xwayland = true, float = true, fullscreen = false, pin = false },
+ no_focus = true,
+})
+
+-- -----------------------------------------------------------------------------
+-- FULLSCREEN & VISUAL STYLING
+-- -----------------------------------------------------------------------------
+hl.window_rule({
+ name = "style-fullscreen",
+ match = { fullscreen = true },
+ border_color = "rgb(E2971F)",
+ border_size = 4,
+ rounding = 0,
+})
+
+-- -----------------------------------------------------------------------------
+-- COMMON DIALOGS / FILE PICKERS
+-- -----------------------------------------------------------------------------
+
+-- Title-based dialogs
+hl.window_rule({
+ name = "float-dialogs-title",
+ match = { title = "^(Open|Open File|Select a File|Choose wallpaper|Open Folder|Save As|Library|File Upload|Authentication Required|Add Folder to Workspace|Choose Files|Confirm to replace files|File Operation Progress)(.*)$|^(.*dialog.*)$" },
+ float = true,
+ center = true,
+ size = "816 537",
+})
+
+-- Class-based dialogs
+hl.window_rule({
+ name = "float-dialogs-class",
+ match = { class = "^(org.gnome.FileRoller|[Xx]dg-desktop-portal-gtk|.*dialog.*)$" },
+ float = true,
+ center = true,
+ size = "816 537",
+})
+
+-- -----------------------------------------------------------------------------
+-- LAYER RULES (rofi, mako, wlogout, waybar)
+-- Check layers with: hyprctl layers
+-- -----------------------------------------------------------------------------
+
+-- Rofi: blur + dim backdrop
+hl.layer_rule({ name = "blur-rofi", match = { namespace = "rofi" }, blur = true, dim_around = true, ignore_alpha = 0.0 })
+
+-- Mako (notifications)
+hl.layer_rule({ name = "mako", match = { namespace = "notifications" }, blur = true, ignore_alpha = 0.0 })
+
+-- wlogout
+hl.layer_rule({ name = "wlogout", match = { namespace = "logout_dialog" }, blur = true, ignore_alpha = 0.0 })
+
+-- slurp screenshot selection: no blur, no animation
+hl.layer_rule({ name = "selection", match = { namespace = "selection" }, blur = false, no_anim = true })
+
+-- Waybar: blur + xray
+hl.layer_rule({ name = "waybar_blur", match = { namespace = "waybar" }, blur = true, blur_popups = true, xray = true, ignore_alpha = 0.54 })
+
+-- -----------------------------------------------------------------------------
+-- SPECIAL WORKSPACE: magic (scratchpad)
+-- -----------------------------------------------------------------------------
+hl.workspace_rule({ workspace = "special:magic", gaps_out = 20, gaps_in = 6 })
+
+hl.window_rule({
+ name = "style-magic-workspace",
+ match = { workspace = "special:magic" },
+ border_color = primary, -- 'primary' is set by appearance.lua → hyprland-colors.lua
+ border_size = 1,
+})
+
+-- -----------------------------------------------------------------------------
+-- GLOBAL MISC CONFIG (focus/fullscreen behavior)
+-- -----------------------------------------------------------------------------
+hl.config({
+ misc = {
+ -- 0 = do nothing, 1 = overlay new window, 2 = unfullscreen
+ on_focus_under_fullscreen = 2,
+ -- Force new windows to spawn on the current workspace
+ initial_workspace_tracking = 1,
+ focus_on_activate = true,
+ },
+})
diff --git a/.config/hypr/source/workspace_rules.conf b/.config/hypr/source/workspace_rules.conf.deprecated
similarity index 100%
rename from .config/hypr/source/workspace_rules.conf
rename to .config/hypr/source/workspace_rules.conf.deprecated
diff --git a/.config/hypr/source/workspace_rules.lua b/.config/hypr/source/workspace_rules.lua
new file mode 100644
index 00000000..344230f9
--- /dev/null
+++ b/.config/hypr/source/workspace_rules.lua
@@ -0,0 +1,13 @@
+-- =============================================================================
+-- WORKSPACE RULES — Base Configuration
+-- =============================================================================
+-- DO NOT EDIT THIS FILE.
+-- Configure workspace rules in ~/.config/hypr/edit_here/source/workspace_rules.lua
+-- which is loaded last and overrides these defaults.
+-- =============================================================================
+--
+-- IMMUTABLE BASE — Do not edit manually.
+-- Standard workspace rules (1-10) and the global fallback (11-99) are strictly
+-- managed by the Dusky TUI Variable-Proxy Engine.
+-- (The user configuration is sourced via edit_here/hyprland.lua at the end of
+-- the main entry point to ensure user priority.)
diff --git a/.config/matugen/config.toml b/.config/matugen/config.toml
index 20197b0b..a44f8f38 100644
--- a/.config/matugen/config.toml
+++ b/.config/matugen/config.toml
@@ -65,6 +65,11 @@ post_hook = '''
input_path = '~/.config/matugen/templates/hyprland-colors.conf'
output_path = '~/.config/matugen/generated/hyprland-colors.conf'
+[templates.hyprland_lua]
+input_path = '~/.config/matugen/templates/hyprland-colors.lua'
+output_path = '~/.config/matugen/generated/hyprland-colors.lua'
+post_hook = 'hyprctl reload || :'
+
[templates.hyprlock]
input_path = '~/.config/matugen/templates/hyprlock-colors.conf'
output_path = '~/.config/matugen/generated/hyprlock-colors.conf'
@@ -130,14 +135,14 @@ ln -nfs "$HOME/.config/matugen/generated/opencode.json" "$HOME/.config/opencode/
pkill -SIGUSR1 -x kitty || :
'''
-# [templates.vscode]
-# input_path = '~/.config/matugen/templates/vscode.json'
-# output_path = '~/.config/matugen/generated/vscode.json'
-# post_hook = '''
-# if command -v vscodium >/dev/null 2>&1; then
-# ln -nfs "$HOME/.config/matugen/generated/vscode.json" "$HOME/.config/VSCodium/User/settings.json"
-# fi
-# '''
+[templates.vscode]
+input_path = '~/.config/matugen/templates/vscode.json'
+output_path = '~/.config/matugen/generated/vscode.json'
+post_hook = '''
+ if command -v code >/dev/null 2>&1; then
+ ln -nfs "$HOME/.config/matugen/generated/vscode.json" "$HOME/.config/Code/User/settings.json"
+ fi
+'''
# [templates.alacritty]
# input_path = '~/.config/matugen/templates/alacritty.toml'
@@ -166,12 +171,12 @@ post_hook = '''
ln -nfs "$HOME/.config/matugen/generated/yazi-theme.toml" "$HOME/.config/yazi/theme.toml"
'''
-# [templates.zathura]
-# input_path = '~/.config/matugen/templates/zathura-colors'
-# output_path = '~/.config/matugen/generated/zathura-colors'
-# post_hook = '''
-# ln -nfs "$HOME/.config/matugen/generated/zathura-colors" "$HOME/.config/zathura/zathurarc"
-# '''
+[templates.zathura]
+input_path = '~/.config/matugen/templates/zathura-colors'
+output_path = '~/.config/matugen/generated/zathura-colors'
+post_hook = '''
+ln -nfs "$HOME/.config/matugen/generated/zathura-colors" "$HOME/.config/zathura/zathurarc"
+'''
# [templates.starship]
# input_path = '~/.config/matugen/templates/starship-colors.toml'
@@ -214,15 +219,15 @@ post_hook = '''
fi
'''
-# [templates.vesktop]
-# input_path = '~/.config/matugen/templates/midnight-discord.css'
-# output_path = '~/.config/matugen/generated/midnight-discord.css'
-# post_hook = '''
-# if command -v vesktop >/dev/null 2>&1; then
-# mkdir -p "$HOME/.config/vesktop/themes/"
-# ln -nfs "$HOME/.config/matugen/generated/midnight-discord.css" "$HOME/.config/vesktop/themes/midnight-discord.css"
-# fi
-# '''
+[templates.vesktop]
+input_path = '~/.config/matugen/templates/midnight-discord.css'
+output_path = '~/.config/matugen/generated/midnight-discord.css'
+post_hook = '''
+if command -v vesktop >/dev/null 2>&1; then
+ mkdir -p "$HOME/.config/vesktop/themes/"
+ ln -nfs "$HOME/.config/matugen/generated/midnight-discord.css" "$HOME/.config/vesktop/themes/midnight-discord.css"
+fi
+'''
# [templates.beeper]
# input_path = '~/.config/matugen/templates/beeper.css'
@@ -234,16 +239,16 @@ post_hook = '''
# fi
# '''
-# [templates.spicetify]
-# input_path = '~/.config/matugen/templates/spotify-colors.ini'
-# output_path = '~/.config/matugen/generated/spotify-colors.ini'
-# post_hook = '''
-# if command -v spicetify >/dev/null 2>&1 && [ -d "$HOME/.config/spicetify/Themes/Comfy" ]; then
-# ln -nfs "$HOME/.config/matugen/generated/spotify-colors.ini" "$HOME/.config/spicetify/Themes/Comfy/color.ini"
-# spicetify apply -n || :
-# hyprctl dispatch sendshortcut "CTRL_SHIFT, R, class:^(Spotify)$" || :
-# fi
-# '''
+[templates.spicetify]
+input_path = '~/.config/matugen/templates/spotify-colors.ini'
+output_path = '~/.config/matugen/generated/spotify-colors.ini'
+post_hook = '''
+if command -v spicetify >/dev/null 2>&1 && [ -d "$HOME/.config/spicetify/Themes/Comfy" ]; then
+ ln -nfs "$HOME/.config/matugen/generated/spotify-colors.ini" "$HOME/.config/spicetify/Themes/Comfy/color.ini"
+ spicetify apply -n || :
+ hyprctl dispatch sendshortcut "CTRL SHIFT, R, class:^(spotify)$" || :
+fi
+'''
# [templates.steam]
# input_path = '~/.config/matugen/templates/steam.css'
@@ -286,12 +291,12 @@ post_hook = '''
systemctl --user restart dusky.service || :
'''
-[templates.dusky_quickpanal]
+[templates.dusky_sliders]
input_path = '/dev/null'
output_path = '/dev/null'
post_hook = '''
- systemctl --user reset-failed dusky_quickpanal.service || :
- systemctl --user restart dusky_quickpanal.service || :
+ systemctl --user reset-failed dusky_sliders.service || :
+ systemctl --user restart dusky_sliders.service || :
'''
@@ -319,8 +324,26 @@ post_hook = '''
# '''
[templates.firefox_websites]
-input_path = '~/.config/matugen/templates/firefox_websites.css'
+input_path = '~/.config/matugen/templates/firefox_websites.css'
output_path = '~/.config/matugen/generated/firefox_websites.css'
-post_hook = '''
- ln -nfs "/home/dusk/.config/matugen/generated/firefox_websites.css" "/home/dusk/.config/mozilla/firefox/tox6bnxb.default-release/chrome/colors.css"
+post_hook = '''
+ ln -nfs "$HOME/.config/matugen/generated/firefox_websites.css" "$HOME/.mozilla/firefox/nnnsdkhm.default-release/chrome/colors.css"
+'''
+
+[templates.zen]
+input_path = '~/.config/matugen/templates/zen-matugen.css'
+output_path = '~/.config/zen/u8q2ykl6.Default (release)/chrome/matugen-colors.css'
+
+[templates.sddm_sync]
+input_path = '~/.config/matugen/templates/colors.css'
+output_path = '~/.config/matugen/generated/sddm-sync-check'
+post_hook = 'printf "%s" "{{image}}" > /tmp/sddm-sync-pending'
+
+[templates.razer]
+input_path = '~/.config/matugen/templates/razer_sync.sh'
+output_path = '~/.config/matugen/generated/razer_sync.sh'
+post_hook = '''
+ if command -v polychromatic-cli >/dev/null 2>&1; then
+ bash ~/.config/matugen/generated/razer_sync.sh || :
+ fi
'''
diff --git a/.config/matugen/templates/hyprland-colors.lua b/.config/matugen/templates/hyprland-colors.lua
new file mode 100644
index 00000000..276f83fb
--- /dev/null
+++ b/.config/matugen/templates/hyprland-colors.lua
@@ -0,0 +1,8 @@
+-- Generated by Matugen — do not edit manually.
+-- Source image: {{image}}
+-- Regenerate by running: theme_ctl refresh
+
+image = "{{image}}"
+<* for name, value in colors *>
+{{name}} = "rgba({{value.default.hex_stripped}}ff)"
+<* endfor *>
diff --git a/.config/matugen/templates/razer_sync.sh b/.config/matugen/templates/razer_sync.sh
new file mode 100644
index 00000000..aa4409d8
--- /dev/null
+++ b/.config/matugen/templates/razer_sync.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+# Sync active theme color to Razer keyboard via Polychromatic.
+# Set RAZER_DEVICE to match your device name (polychromatic-cli --list-devices).
+# Skips silently if polychromatic-cli is not installed or no device is found.
+
+RAZER_DEVICE="${RAZER_DEVICE:-Razer Huntsman Mini}"
+command -v polychromatic-cli >/dev/null 2>&1 || exit 0
+
+# Stealing the light theme's primary color for maximum physical LED saturation and brightness
+polychromatic-cli -n "$RAZER_DEVICE" -o static -c "{{colors.primary.light.hex}}" || :
diff --git a/.config/waybar/01_horizontal_block/config.jsonc b/.config/waybar/01_horizontal_block/config.jsonc
new file mode 100644
index 00000000..3fc881fa
--- /dev/null
+++ b/.config/waybar/01_horizontal_block/config.jsonc
@@ -0,0 +1,284 @@
+//horizontal_block
+
+{
+ "layer": "top",
+ "exclusive": true,
+ "reload_style_on_change": true,
+ "position": "top",
+ "spacing": 4,
+ "height": 40,
+ "margin-top": 6,
+ "margin-left": 10,
+ "margin-right": 10,
+ "margin-bottom": 0,
+
+ // --- MODULE LAYOUT ---
+ "modules-left": [
+ "custom/launcher",
+ "clock",
+ "custom/weather",
+ "custom/inhibit-suspend",
+ "custom/updates",
+ "custom/notification",
+ "custom/theme-toggle",
+ "custom/net-speed",
+ "tray"
+ ],
+
+ "modules-center": [
+ "hyprland/workspaces"
+ ],
+
+ "modules-right": [
+ "mpris",
+ "network",
+ "bluetooth",
+ "pulseaudio#output",
+ "backlight",
+ "cpu",
+ "memory",
+ "battery",
+ "custom/power"
+ ],
+
+ // --- MODULE CONFIGURATION ---
+
+ "custom/launcher": {
+ "format": "",
+ "on-click": "python3 ~/user_scripts/dusky_system/control_center/dusky_control_center.py",
+ "tooltip-format": "Control Center"
+ },
+
+ "clock": {
+ "format": "{:%I:%M %p}",
+ "format-alt": " {:%A, %B %d}",
+ "tooltip-format": "{calendar}",
+ "on-click-right": "uwsm-app -- gnome-clocks",
+ "on-click-middle": "uwsm-app -- kitty --class peaclock -e peaclock",
+ "calendar": {
+ "mode": "month",
+ "mode-mon-col": 3,
+ "weeks-pos": "right",
+ "on-scroll": 1,
+ "format": {
+ "months": "{}",
+ "days": "{}",
+ "weeks": "W{}",
+ "weekdays": "{}",
+ "today": " {} "
+ }
+ }
+ },
+
+ "custom/weather": {
+ "format": "{}",
+ "exec": "curl -s 'wttr.in/?format=%c%t' | head -c 15",
+ "interval": 1800,
+ "tooltip-format": "Weather Conditions"
+ },
+
+ "custom/inhibit-suspend": {
+ "format": "{}",
+ "exec": "if pgrep -x 'hypridle' > /dev/null; then echo '{\"text\": \"\", \"tooltip\": \"Idle enabled. Click to disable.\", \"class\": \"enabled\"}'; else echo '{\"text\": \"\", \"tooltip\": \"Idle disabled. Click to enable.\", \"class\": \"disabled\"}'; fi",
+ "return-type": "json",
+ "interval": 5,
+ "signal": 9,
+ "on-click": "uwsm-app -- ~/user_scripts/waybar/toggle_hypridle.sh",
+ "escape": true
+ },
+
+ "custom/updates": {
+ "format": " {}",
+ "exec": "checkupdates 2>/dev/null | wc -l || echo 0",
+ "interval": 3600,
+ "on-click": "kitty sh -c 'command -v yay >/dev/null && yay || paru'",
+ "tooltip-format": "System Updates"
+ },
+
+ "custom/notification": {
+ "format": "{icon}",
+ "format-icons": {
+ "notification": "",
+ "none": "",
+ "dnd-notification": "",
+ "dnd-none": "",
+ "inhibited-notification": "",
+ "inhibited-none": "",
+ "dnd-inhibited-notification": "",
+ "dnd-inhibited-none": ""
+ },
+ "return-type": "json",
+ "exec-if": "which makoctl",
+ "exec": "~/user_scripts/waybar/mako.sh",
+ "on-click": "~/user_scripts/rofi/rofi_mako.sh",
+ "on-click-right": "makoctl mode -t do-not-disturb && pkill -RTMIN+8 waybar",
+ "signal": 8,
+ "escape": true,
+ "tooltip-format": "Notifications\n\n LMB Toggle Panel\n RMB Do Not Disturb"
+ },
+
+ "custom/theme-toggle": {
+ "format": "",
+ "tooltip-format": "Theme Controls\n\n LMB Dark Mode\n RMB Light Mode\n MMB Wallpaper",
+ "on-click": "uwsm-app -- ~/user_scripts/theme_matugen/theme_ctl.sh set --mode dark",
+ "on-click-right": "uwsm-app -- ~/user_scripts/theme_matugen/theme_ctl.sh set --mode light",
+ "on-click-middle": "uwsm-app -- waypaper"
+ },
+
+ "tray": {
+ "icon-size": 15,
+ "spacing": 6,
+ "show-passive-items": true
+ },
+
+ "hyprland/workspaces": {
+ "on-click": "activate",
+ "format": "{icon}",
+ "format-window-separator": " ",
+ "window-rewrite-default": "",
+ "window-rewrite": {
+ "class": "",
+ "class": "",
+ "class": "",
+ "class": "",
+ "class": "",
+ "class": "",
+ "class": "",
+ "class": ""
+ },
+ "persistent-workspaces": {
+ "*": 5
+ },
+ "on-scroll-up": "hyprctl dispatch workspace e-1",
+ "on-scroll-down": "hyprctl dispatch workspace e+1"
+ },
+
+ "mpris": {
+ "format": "{player_icon} {title}",
+ "format-paused": "{status_icon} {title}",
+ "format-stopped": "",
+ "max-length": 25,
+ "player-icons": {
+ "default": "",
+ "mpv": "",
+ "spotify": "",
+ "firefox": ""
+ },
+ "status-icons": {
+ "paused": ""
+ },
+ "tooltip-format": "{player} - {artist}\n{title}\n{album}",
+ "on-click": "playerctl play-pause",
+ "on-scroll-up": "playerctl next",
+ "on-scroll-down": "playerctl previous"
+ },
+
+ "custom/net-speed": {
+ "exec": "$HOME/user_scripts/waybar/network/network_meter_calling.sh --horizontal",
+ "return-type": "json",
+ "format": "{}",
+ "interval": 1,
+ "tooltip": true
+ },
+
+ "network": {
+ "format-wifi": "",
+ "format-ethernet": "",
+ "format-disconnected": "",
+ "format-linked": "",
+ "tooltip-format-wifi": " {essid}\n {signalStrength}%\n {ipaddr}",
+ "tooltip-format-ethernet": " Ethernet\n {ipaddr}",
+ "tooltip-format-disconnected": " Disconnected",
+ "on-click": "uwsm-app -- kitty --class wifitui -e wifitui"
+ },
+
+ "bluetooth": {
+ "format": "",
+ "format-disabled": "",
+ "format-connected": " {num_connections}",
+ "format-connected-battery": " {device_battery_percentage}%",
+ "tooltip-format": "{controller_alias}\n{controller_address}\n\n{device_enumerate}",
+ "tooltip-format-connected": "{controller_alias}\n\n{device_enumerate}",
+ "tooltip-format-enumerate-connected": " {device_alias}",
+ "tooltip-format-enumerate-connected-battery": " {device_alias} ({device_battery_percentage}%)",
+ "on-click": "uwsm-app -- blueman-manager",
+ "on-click-right": "uwsm-app -- kitty --class bluetui -e bluetui"
+ },
+
+ "pulseaudio#output": {
+ "format": "{icon} {volume}%",
+ "format-muted": "",
+ "format-bluetooth": " {volume}%",
+ "format-bluetooth-muted": "",
+ "format-icons": {
+ "headphone": "",
+ "hands-free": "",
+ "headset": "",
+ "phone": "",
+ "portable": "",
+ "car": "",
+ "default": ["", "", ""]
+ },
+ "on-click": "uwsm-app -- pavucontrol",
+ "on-click-right": "uwsm-app -- kitty --class cava -e cava",
+ "on-click-middle": "pactl set-sink-mute @DEFAULT_SINK@ toggle",
+ "on-scroll-up": "pactl set-sink-volume @DEFAULT_SINK@ +5%",
+ "on-scroll-down": "pactl set-sink-volume @DEFAULT_SINK@ -5%",
+ "tooltip-format": "{desc}\nVolume: {volume}%\n\nLMB: Pavucontrol\nRMB: Cava\nMMB: Mute Toggle\nScroll: Volume",
+ "scroll-step": 5,
+ "max-volume": 150
+ },
+
+ "backlight": {
+ "format": "{icon} {percent}",
+ "tooltip-format": "Brightness: {percent}%\n\n LMB Brightness\n RMB Night Light\n MMB Shaders",
+ "on-click": "uwsm-app -- ~/user_scripts/sliders/dusky_sliders.py",
+ "on-click-right": "uwsm-app -- ~/user_scripts/sliders/dusky_sliders.py",
+ "on-click-middle": "uwsm-app -- ~/user_scripts/rofi/shader_menu.sh",
+ "on-scroll-up": "brightnessctl set +5%",
+ "on-scroll-down": "brightnessctl set 5%-",
+ "format-icons": ["", "", ""]
+ },
+
+ "cpu": {
+ "interval": 2,
+ "format": " {usage}%",
+ "on-click": "kitty -e btop",
+ "states": {
+ "warning": 70,
+ "critical": 90
+ }
+ },
+
+ "memory": {
+ "interval": 2,
+ "format": " {percentage}%",
+ "on-click": "uwsm-app -- kitty --class io_monitor.sh -e $HOME/user_scripts/drives/io_monitor.sh",
+ "states": {
+ "warning": 70,
+ "critical": 90
+ }
+ },
+
+ "battery": {
+ "states": {
+ "good": 80,
+ "warning": 30,
+ "critical": 15
+ },
+ "on-click": "uwsm-app -- kitty --class power_saver.sh --hold -e $HOME/user_scripts/battery/power_saving/power_saver.sh",
+ "on-click-right": "uwsm-app -- kitty --class dusky_hypridle.sh -e $HOME/user_scripts/hypridle/dusky_hypridle.sh",
+ "format": "{icon} {capacity}%",
+ "format-charging": " {capacity}%",
+ "format-plugged": " {capacity}%",
+ "format-full": " Full",
+ "tooltip-format": "{timeTo}\n\n Health: {health}%\n Power: {power:.2f}W",
+ "format-icons": ["", "", "", "", "", "", "", "", "", "", ""]
+ },
+
+ "custom/power": {
+ "format": "⏻",
+ "on-click": "uwsm-app -- ~/user_scripts/wlogout/wlogout_scale.sh",
+ "tooltip-format": "Power Menu"
+ }
+}
diff --git a/.zshrc b/.zshrc
deleted file mode 100644
index cd11873d..00000000
--- a/.zshrc
+++ /dev/null
@@ -1,768 +0,0 @@
-# =============================================================================
-# ~/.zshrc - Zsh Configuration
-#
-# This configuration is structured for clarity and performance.
-# Sections are ordered logically:
-# 1. Environment Variables & Path
-# 2. History Configuration
-# 3. Completion System
-# 4. Keybindings (Vi-Mode)
-# 5. Aliases and Functions
-# 6. Plugin & Prompt Initialization
-# 7. Auto login INTO UWSM HYPRLAND WITH TTY1
-# =============================================================================
-
-# Exit early if not interactive
-[[ -o interactive ]] || return
-
-# -----------------------------------------------------------------------------
-# [1] ENVIRONMENT VARIABLES & PATH
-# -----------------------------------------------------------------------------
-# Set core applications and configure the system's search path for executables.
-# These are fundamental for defining your work environment.
-
-# Set the default terminal emulator.
-export TERMINAL='kitty'
-# Set the default web browser.
-#export BROWSER='firefox'
-
-# Set the default editor (Critical for TTY/SSH/Yazi)
-export EDITOR='nvim'
-export VISUAL='nvim'
-
-# --- Compilation Optimization ---
-# 1. Parallelism: Use ALL available processing units.
-# $(nproc) dynamically counts cores on any machine this runs on.
-export MAKEFLAGS="-j$(nproc)"
-
-# --- Pyenv (Python Version Management) ---
-# Initializes pyenv to manage multiple Python versions.
-
-## export PYENV_ROOT="$HOME/.pyenv"
-## export PATH="$PYENV_ROOT/bin:$PATH"
-## if command -v pyenv 1>/dev/null 2>&1; then
-## eval "$(pyenv init --path)"
-## eval "$(pyenv init -)"
-## fi
-
-# Configure the path where Zsh looks for commands.
-# Uncomment and modify if you have local binaries (e.g., in ~/.local/bin).
-# export PATH="$HOME/.local/bin:$PATH"
-
-# -----------------------------------------------------------------------------
-# [2] HISTORY CONFIGURATION
-# -----------------------------------------------------------------------------
-# Configure how Zsh records and manages your command history. Robust history
-# settings are crucial for an efficient workflow.
-
-# Set the number of history lines to keep in memory during the session.
-HISTSIZE=50000
-# Set the number of history lines to save in the history file (~/.zsh_history).
-SAVEHIST=25000
-# Specify the location of the history file.
-HISTFILE=~/.zsh_history
-
-# Use `setopt` to fine-tune history behavior.
-setopt APPEND_HISTORY # Append new history entries instead of overwriting.
-setopt INC_APPEND_HISTORY # Write history to file immediately after command execution.
-setopt SHARE_HISTORY # Share history between all concurrent shell sessions.
-setopt HIST_EXPIRE_DUPS_FIRST # When trimming history, delete duplicates first.
-setopt HIST_IGNORE_DUPS # Don't record an entry that was just recorded again.
-setopt HIST_IGNORE_SPACE # Ignore commands starting with space.
-setopt HIST_VERIFY # Expand history (!!) into the buffer, don't run immediately.
-
-# -----------------------------------------------------------------------------
-# [3] COMPLETION SYSTEM
-# -----------------------------------------------------------------------------
-
-setopt EXTENDED_GLOB # Enable extended globbing features (e.g., `^` for negation).
-
-# Optimized initialization: Only regenerate cache once every 24 hours.
-autoload -Uz compinit
-local zcompdump="${ZDOTDIR:-$HOME}/.zcompdump"
-local dump_cache=($zcompdump(#qN.mh-24)) # Array expansion forces glob evaluation without subshells
-
-if (( ${#dump_cache} )); then
- compinit -C # Trust the fresh cache, skip checks (FAST)
-else
- compinit # Cache is old or missing, regenerate it (SLOW)
- # Explicitly touch the file to reset the timer
- touch "$zcompdump"
-fi
-
-# Style the completion menu.
-# ':completion:*' is a pattern that applies to all completion widgets.
-zstyle ':completion:*' menu select # Enable menu selection on the first Tab press.
-zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}" # Colorize the completion menu using LS_COLORS.
-zstyle ':completion:*:descriptions' format '%B%d%b' # Format descriptions for clarity (bold).
-zstyle ':completion:*' group-name '' # Group completions by type without showing group names.
-zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' # Case-insensitive matching.
-
-# -----------------------------------------------------------------------------
-# [4] KEYBINDINGS & SHELL OPTIONS
-# -----------------------------------------------------------------------------
-# Define keybindings and enable various shell options for a better user experience.
-
-# --- Vi Mode Keybindings ---
-# Enables the use of Vim-like keybindings in the shell for modal editing.
-bindkey -v
-# Set the timeout for ambiguous key sequences (in centiseconds).
-# 1 = 10ms, making the transition to normal mode in Vi mode practically instantaneous.
-export KEYTIMEOUT=1
-
-# --- Neovim Integration ---
-# Press 'v' in normal mode to edit the current command in Neovim.
-autoload -U edit-command-line
-zle -N edit-command-line
-bindkey -M vicmd v edit-command-line
-
-# --- Search History with Up/Down ---
-# If you type "git" and press Up, it finds the last "git" command.
-autoload -U history-search-end
-zle -N history-beginning-search-backward-end history-search-end
-zle -N history-beginning-search-forward-end history-search-end
-bindkey "${terminfo[kcuu1]:-^[[A}" history-beginning-search-backward-end
-bindkey "${terminfo[kcud1]:-^[[B}" history-beginning-search-forward-end
-
-# --- General Shell Options (`setopt`) ---
-setopt INTERACTIVE_COMMENTS # Allow comments (like this one) in an interactive shell.
-setopt GLOB_DOTS # Include dotfiles (e.g., .config) in globbing results.
-setopt NO_CASE_GLOB # Perform case-insensitive globbing.
-setopt AUTO_PUSHD # Automatically push directories onto the directory stack.
-setopt PUSHD_IGNORE_DUPS # Don't push duplicate directories onto the stack.
-
-
-# -----------------------------------------------------------------------------
-# [5] ALIASES & FUNCTIONS
-# -----------------------------------------------------------------------------
-# Define shortcuts (aliases) and small scripts (functions) to reduce typing
-# and streamline common tasks.
-
-# --- Aliases ---
-
-# alias ls='ls --color=auto' # Always use color for `ls`.
-# alias la='ls -A' # List all entries except for . and ..
-# alias ll='ls -alF' # List all files in long format.
-# alias l='ls -CF' # List entries by columns.
-
-# Safety First
-alias cp='cp -iv'
-alias mv='mv -iv'
-alias rm='rm -I'
-alias ln='ln -v'
-
-alias disk_usage='sudo btrfs filesystem usage /' # The TRUTH about BTRFS space
-alias df='df -hT' # Show filesystem types
-
-# VNC iphone daemon.
-alias iphone_vnc='~/user_scripts/networking/iphone_vnc.sh'
-
-# wifi security
-alias wifi_security='~/user_scripts/networking/ax201_wifi_testing.sh'
-
-#Theme Switcher
-alias darkmode='~/user_scripts/theme_matugen/matugen_config.sh --mode dark'
-alias lightmode='~/user_scripts/theme_matugen/matugen_config.sh --mode light'
-
-#submit logs
-alias sendlogs='~/user_scripts/arch_setup_scripts/send_logs.sh --auto'
-
-# update dusky
-alias update_dusky='~/user_scripts/update_dusky/update_dusky.sh'
-
-# update dusky reset
-alias dusky_force_sync_github='~/user_scripts/update_dusky/dusky_force_sync_github.sh'
-
-# Check if eza is installed
-if command -v eza >/dev/null; then
- alias ls='eza --icons --group-directories-first'
- alias ll='eza --icons --group-directories-first -l --git'
- alias la='eza --icons --group-directories-first -la --git'
- alias lt='eza --icons --group-directories-first --tree --level=2'
-else
- # Fallback to standard ls if eza is missing
- alias ls='ls --color=auto'
- alias ll='ls -lh'
- alias la='ls -A'
-fi
-
-alias diff='delta --side-by-side'
-alias grep='grep --color=auto'
-alias egrep='egrep --color=auto'
-alias fgrep='fgrep --color=auto'
-
-#alias cat='bat'
-
-#alias for using gdu instead of ncdu
-alias ncdu='gdu'
-
-#alias for disk io realtime.
-alias io_drives='~/user_scripts/drives/io_monitor.sh'
-
-# 1. Base Bare Repo Alias
-# (Defined first for logical clarity, though strictly not required by Zsh)
-alias git_dusky='/usr/bin/git --git-dir=$HOME/dusky/ --work-tree=$HOME'
-
-# 2. Add List Alias (FIXED with Subshell)
-# The ( ) runs this specific command inside $HOME so the paths match,
-# but it DOES NOT change your actual terminal directory.
-alias git_dusky_add_list='(cd $HOME && git_dusky add --pathspec-from-file=.git_dusky_list)'
-
-# 3. Alias for discarding all local changes (both staged and unstaged) and revert the state of tracked files to exactly match the last commit (HEAD), this is a destructive operation. (DANGER ZONE)
-alias git_dusky_restore='echo "git --git-dir=$HOME/dusky/ --work-tree=$HOME reset --hard HEAD" && git_dusky reset --hard HEAD'
-
-# 4. Delta/Diff Alias
-alias gitdelta='git_dusky_add_list && git_dusky diff HEAD'
-
-# 5. Lazygit Bare Repo Alias
-alias lazygit_dusky='lazygit --git-dir=$HOME/dusky/ --work-tree=$HOME'
-
-# unlock block_devices
-alias unlock='$HOME/user_scripts/drives/drive_manager.sh unlock'
-
-# lock block_devices
-alias lock='$HOME/user_scripts/drives/drive_manager.sh lock'
-
-
-# Battery stats
-
-batstat() {
- # Isolate shell options for predictable execution
- emulate -L zsh
-
- local bat="" target="" mode="static" output_format="human"
- local arg d dev_type cap stat curr volt power
- float watts=0.0
-
- # The Architect-Grade Help Page
- _show_help() {
- printf "\e[1;34m::\e[0m \e[1mbatstat\e[0m - Zero-fork battery monitor\n\n"
- printf "\e[1mUSAGE:\e[0m\n"
- printf " batstat [COMMAND] [FORMAT] [TARGET]\n\n"
- printf "\e[1mCOMMANDS:\e[0m\n"
- printf " \e[32mhelp\e[0m Show this help page (default with no args)\n"
- printf " \e[32mstatic\e[0m Print the current battery stats once and exit\n"
- printf " \e[32mlive\e[0m Run a flicker-free, 1-second updating TUI\n\n"
- printf "\e[1mFORMATS (Static mode only):\e[0m\n"
- printf " \e[32mhuman\e[0m Standard readable output (default)\n"
- printf " \e[32mjson\e[0m Output as a JSON object (for Waybar/Eww integration)\n"
- printf " \e[32mterse\e[0m Raw values only: \n\n"
- printf "\e[1mTARGET:\e[0m\n"
- printf " Optional battery name (e.g., BAT1, macsmc-battery).\n"
- printf " If omitted, auto-detects the first available battery natively.\n\n"
- printf "\e[1mEXAMPLES:\e[0m\n"
- printf " batstat live\n"
- printf " batstat static json\n"
- printf " batstat terse static BAT1\n"
- }
-
- # Trigger help if absolutely no arguments are passed
- if (( $# == 0 )); then
- _show_help
- return 0
- fi
-
- # Order-independent argument parser
- for arg in "$@"; do
- case "$arg" in
- help|-h|--help) _show_help; return 0 ;;
- live) mode="live" ;;
- static) mode="static" ;;
- json) output_format="json" ;;
- terse) output_format="terse" ;;
- human) output_format="human" ;;
- *) target="$arg" ;; # Unrecognized flags are assumed to be battery targets
- esac
- done
-
- # Hardware Detection: Target specific battery or find the first one natively
- if [[ -n "$target" && -d "/sys/class/power_supply/$target" ]]; then
- bat="/sys/class/power_supply/$target"
- else
- # (N) prevents failure if the directory is completely empty
- for d in /sys/class/power_supply/*(N); do
- if [[ -f "$d/type" ]]; then
- read -r dev_type < "$d/type" 2>/dev/null
- if [[ "$dev_type" == "Battery" ]]; then
- bat="$d"
- break
- fi
- fi
- done
- fi
-
- if [[ -z "$bat" ]]; then
- printf "Error: No battery detected in /sys/class/power_supply/\n" >&2
- return 1
- fi
-
- # Core Logic: True Zero-Fork
- _get_bat_stats() {
- read -r cap < "$bat/capacity" 2>/dev/null
- read -r stat < "$bat/status" 2>/dev/null
-
- cap=${cap:-"N/A"}
- stat=${stat:-"Unknown"}
-
- # Native Zsh floating-point arithmetic
- if [[ -f "$bat/power_now" ]]; then
- read -r power < "$bat/power_now" 2>/dev/null
- (( watts = ${power:-0} / 1000000.0 ))
- elif [[ -f "$bat/current_now" && -f "$bat/voltage_now" ]]; then
- read -r curr < "$bat/current_now" 2>/dev/null
- read -r volt < "$bat/voltage_now" 2>/dev/null
- (( watts = (${curr:-0} * ${volt:-0}) / 1000000000000.0 ))
- fi
-
- # Route the output format
- if [[ "$output_format" == "json" ]]; then
- printf '{"capacity": "%s", "power_w": %.2f, "status": "%s"}' "$cap" "$watts" "$stat"
- elif [[ "$output_format" == "terse" ]]; then
- printf "%s %.2f %s" "$cap" "$watts" "$stat"
- else
- printf "Capacity: %s%% | Power Draw: %.2f W (%s)" "$cap" "$watts" "$stat"
- fi
- }
-
- # Execution Engine
- if [[ "$mode" == "live" ]]; then
- # UX Guardrail: Prevent JSON/Terse spam in the live TUI
- if [[ "$output_format" != "human" ]]; then
- printf "Warning: '%s' format is meant for static scripts. Forcing 'human' output for live TUI.\n" "$output_format" >&2
- output_format="human"
- sleep 1.5
- fi
-
- printf "\e[?25l" # Hide cursor
-
- # Zsh native 'always' block guarantees clean teardown
- {
- while true; do
- printf "\r\e[K"
- _get_bat_stats
- sleep 1
- done
- } always {
- printf "\e[?25h\n" # Restore cursor and drop a clean newline
- }
- else
- _get_bat_stats
- printf "\n"
- fi
-}
-
-
-# Weather query via wttr.in
-# Usage: wthr [location]
-# use with "-s" flag to only get one line.
-wthr() {
- # Check if the first argument is '-s' (short)
- if [[ "$1" == "-s" ]]; then
- shift # Remove the -s from arguments
- local location="${(j:+:)@}"
- curl "wttr.in/${location}?format=%c+%t"
- else
- local location="${(j:+:)@}"
- curl "wttr.in/${location}"
- fi
-}
-
-
-# for troubleshoting scripts
-source ~/.config/zshrc/logs
-source ~/.config/zshrc/logs_old
-
-# share zram1 directory with waydroid at pictures point inside waydroid
-# Function to remount Waydroid pictures to ZRAM
-waydroid_bind() {
- local target="$HOME/.local/share/waydroid/data/media/0/Pictures"
- local source="/mnt/zram1"
-
- # 1. Attempt to unmount recursively.
- # 2>/dev/null silences the error if it's not mounted.
- # || true ensures the script doesn't abort if you have 'set -e' active or strict chaining.
- sudo umount -R "$target" 2>/dev/null || true
-
- # 2. Perform the bind mount
- # We check if the source exists first to avoid mounting nothing.
- if [[ -d "$source" ]]; then
- sudo mount --bind "$source" "$target"
- echo "Successfully bound $source to Waydroid Pictures."
- else
- echo "Error: Source $source does not exist."
- return 1
- fi
-}
-
-# ===
-# use `command sudo nvim ...` to escape the funtion if you ever dont want sudoedit to be used.
-# ===
-# sudo edit nvim sudoedit
-# Function to intercept 'sudo nvim' and convert it to 'sudoedit'
-sudo() {
- # Check if we are trying to run nvim
- if [[ "$1" == "nvim" ]]; then
- shift # Remove 'nvim'
-
- # Check if there are actually files to edit
- if [[ $# -eq 0 ]]; then
- echo "Error: sudoedit requires a filename."
- return 1
- fi
-
- # Pass the filenames to sudoedit
- command sudoedit "$@"
- else
- # Run standard sudo for everything else
- command sudo "$@"
- fi
-}
-
-# YAZI
-#change the current working directory when exiting Yazi
-
-function y() {
- local tmp="$(mktemp -t "yazi-cwd.XXXXXX")" cwd
- yazi "$@" --cwd-file="$tmp"
- if cwd="$(cat -- "$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then
- builtin cd -- "$cwd"
- fi
- rm -f -- "$tmp"
-}
-
-# --- sysbench benchmark ---
-alias run_sysbench='~/user_scripts/performance/sysbench_benchmark.sh'
-
-# --- nvidia vfio bind/unbind ---
-alias nvidia_bind='~/user_scripts/nvidia_passthrough/nvidia_vfio_bind_unbind.sh --bind'
-alias nvidia_unbind='~/user_scripts/nvidia_passthrough/nvidia_vfio_bind_unbind.sh --unbind'
-
-#-- LM- Studio--
-llm() {
- /mnt/media/Documents/do_not_delete_linux/appimages/LM-Studio*(om[1]) "$@"
-}
-# The (om[1]) glob qualifier picks the most recently modified file (newest first)
-
-# --- Functions ---
-# Creates a directory and changes into it.
-mkcd() {
- mkdir -p "$1" && cd "$1"
-}
-
-# --- Windows 10 KVM Manager ---
-# HOW TO USE
-# Start VM: win start
-# Open Looking Glass: win view
-# Do both (One-click gaming): win launch
-# Kill it: win kill
-
-win() {
- local vm="win10"
- local shm_file="/dev/shm/looking-glass"
- local lg_cmd="looking-glass-client -f ${shm_file} -m KEY_F6"
-
- # Helper for colored output
- local p_info() { echo -e "\e[34m[WIN10]\e[0m $1"; }
- local p_err() { echo -e "\e[31m[ERROR]\e[0m $1"; }
-
- case "$1" in
- start)
- p_info "Starting VM..."
- sudo virsh start "$vm"
- ;;
- stop|shutdown)
- p_info "Sending shutdown signal..."
- sudo virsh shutdown "$vm"
- ;;
- kill|destroy)
- p_info "Forcefully destroying VM..."
- sudo virsh destroy "$vm"
- ;;
- reboot)
- p_info "Rebooting VM..."
- sudo virsh reboot "$vm"
- ;;
- view|lg|show)
- if [ -f "$shm_file" ]; then
- p_info "Launching Looking Glass..."
- eval "$lg_cmd"
- else
- p_err "Looking Glass SHM file not found. Is the VM running?"
- fi
- ;;
- # --- Advanced Options ---
- launch|play)
- # Starts VM and waits for Looking Glass to be ready
- p_info "Two birds one stone: Starting VM and waiting for Looking Glass..."
- sudo virsh start "$vm" 2>/dev/null
-
- p_info "Waiting for Shared Memory..."
- # Efficient bash wait loop (timeout after 30s)
- local timeout=30
- while [ ! -f "$shm_file" ] && [ $timeout -gt 0 ]; do
- sleep 1
- ((timeout--))
- done
-
- if [ -f "$shm_file" ]; then
- p_info "Ready! Launching Client..."
- eval "$lg_cmd"
- else
- p_err "Timed out waiting for VM graphics."
- fi
- ;;
- status)
- sudo virsh domstate "$vm"
- ;;
- edit)
- sudo virsh edit "$vm"
- ;;
- *)
- echo "Usage: win {start|shutdown|destroy|reboot|view|launch|status|edit}"
- ;;
- esac
-}
-
-# --- Auto-Completion for 'win' ---
-# This makes hitting 'tab' show your options
-_win_completion() {
- local -a commands
- commands=('start' 'shutdown' 'destroy' 'reboot' 'view' 'launch' 'status' 'edit')
- _describe 'command' commands
-}
-compdef _win_completion win
-
-
-# =============================================================================
-# Pacman/Expac Utility: Unified Package Querying (Platinum Edition)
-# Usage: pkg [count]
-# =============================================================================
-
-# DRY Header Helper — defined once at source time.
-# Args: $1 = title string, $2 = count integer
-_pkg_header() {
- print -P "\n%F{blue}::%f %B${1}%b (Top ${2})"
- print -P "%F{238}------------------------------------------------------------%f"
- # Precisely aligned header: 19 chars (Date) + 2 spaces + 8 chars (Size) + 2 spaces + Package
- print -P "%F{242}INSTALL DATE SIZE PACKAGE%f"
- print -P "%F{238}------------------------------------------------------------%f"
-}
-
-pkg() {
- # 1. Dependency Validation
- if (( ! $+commands[expac] )); then
- print -u2 -P "\n%F{red}✖ Error:%f 'expac' is not installed."
- print -u2 -P " Please install it first: %F{cyan}sudo pacman -S expac%f\n"
- return 1
- fi
-
- # 2. State Initialization
- local target="all"
- local metric=""
- local -i count=20
- local -i show_help=0
-
- if (( $# == 0 )); then
- show_help=1
- fi
-
- # 3. Argument Tokenizer: Case-insensitive, order-agnostic
- for arg in "$@"; do
- case "${arg:l}" in
- help|-h|--help)
- show_help=1
- ;;
- explicit|user)
- target="explicit"
- ;;
- all)
- target="all"
- ;;
- hogs|size)
- metric="size"
- ;;
- new|recent|latest)
- metric="new"
- ;;
- old|ancient)
- metric="old"
- ;;
- *)
- if [[ "$arg" =~ ^[1-9][0-9]*$ ]]; then
- count="$arg"
- else
- print -u2 -P "\n%F{red}✖ Error:%f Unknown argument or invalid count: '%F{yellow}$arg%f'"
- print -u2 -P " Run %F{green}pkg help%f for usage details.\n"
- return 1
- fi
- ;;
- esac
- done
-
- # 4. Help Menu Overlay
- if (( show_help )); then
- print -P "\n%F{blue}::%f %Bpkg%b — Advanced Package Query Tool"
- print -P "%F{238}------------------------------------------------------------%f"
- print -P "%F{green}Usage:%f pkg [target] [metric] [count]"
- print -P " %F{242}(Arguments can be provided in ANY order)%f\n"
-
- print -P "%BTargets:%b (Default: all)"
- print -P " %F{cyan}all%f - System-wide packages (includes dependencies)"
- print -P " %F{cyan}explicit%f, %F{cyan}user%f - Only packages you explicitly installed\n"
-
- print -P "%BMetrics:%b (Default: size)"
- print -P " %F{cyan}size%f, %F{cyan}hogs%f - Sort by installed size (largest first)"
- print -P " %F{cyan}new%f, %F{cyan}recent%f, %F{cyan}latest%f - Sort by installation date (newest first)"
- print -P " %F{cyan}old%f, %F{cyan}ancient%f - Sort by installation date (oldest first)\n"
-
- print -P "%BExamples:%b"
- print -P " %F{yellow}pkg explicit new 20%f # Top 20 most recently explicitly installed"
- print -P " %F{yellow}pkg 50 size%f # Top 50 largest packages overall"
- print -P " %F{yellow}pkg old%f # Top 20 oldest packages overall\n"
- return 0
- fi
-
- # Set default metric
- [[ -z "$metric" ]] && metric="size"
-
- # 5. Dynamic Pipeline Construction
- # We lock expac to ALWAYS output: Date | Size(bytes) | Name
- local -a expac_args=(--timefmt='%Y-%m-%d %H:%M:%S' '%l|%m|%n')
- local -a sort_cmd
- local title_metric=""
-
- # We sort against specific pipe-delimited columns (-t '|')
- case "$metric" in
- size)
- title_metric="Largest"
- sort_cmd=(sort -t '|' -k2 -rn) # Sort numerically by column 2 (Size)
- ;;
- new)
- title_metric="Newest"
- sort_cmd=(sort -t '|' -k1 -r) # Sort reverse-chronologically by column 1 (Date)
- ;;
- old)
- title_metric="Oldest"
- sort_cmd=(sort -t '|' -k1) # Sort chronologically by column 1 (Date)
- ;;
- esac
-
- local title_full=""
- if [[ "$target" == "explicit" ]]; then
- title_full="${title_metric} Explicitly Installed Packages"
- else
- title_full="${title_metric} Installed Packages (Overall)"
- fi
-
- # 6. Core Execution Pipeline
- _pkg_header "$title_full" "$count"
-
- # Raw ANSI color injection via Awk stream processing
- # $1 = Date(Grey), $2 = Size(Yellow), $3 = Name(Bold Arch Blue)
- local awk_color='{ printf "\033[38;5;246m%s\033[0m \033[38;5;220m%s\033[0m \033[1;38;5;39m%s\033[0m\n", $1, $2, $3 }'
-
- # Notice the `numfmt --padding=8`. This guarantees right-alignment of sizes (e.g. ' 4.8GiB') without needing `column`
- if [[ "$target" == "explicit" ]]; then
- pacman -Qeq | expac "${expac_args[@]}" - 2>/dev/null | "${sort_cmd[@]}" | head -n "$count" | numfmt --to=iec-i --suffix=B --field=2 --delimiter='|' --padding=8 | awk -F '|' "$awk_color"
- else
- expac "${expac_args[@]}" 2>/dev/null | "${sort_cmd[@]}" | head -n "$count" | numfmt --to=iec-i --suffix=B --field=2 --delimiter='|' --padding=8 | awk -F '|' "$awk_color"
- fi
-
- print ""
-}
-
-# Native Zsh tab-completion — proper named function, unambiguously correct.
-_pkg() {
- _arguments \
- "1:command:(hogs size all explicit user new recent latest old ancient help)" \
- "2:count: "
-}
-compdef _pkg pkg
-
-# -----------------------------------------------------------------------------
-# [6] PLUGINS & PROMPT INITIALIZATION
-# -----------------------------------------------------------------------------
-# Self-Healing Cache:
-# 1. Checks if the static init file exists.
-# 2. Checks if the binary (starship/fzf) has been updated (is newer than the cache).
-# 3. Regenerates the cache automatically if needed.
-
-# --- Starship Prompt ---
-# Define paths
-_starship_cache="$HOME/.starship-init.zsh"
-_starship_bin="$(command -v starship)"
-
-# Only proceed if starship is actually installed
-if [[ -n "$_starship_bin" ]]; then
- if [[ ! -f "$_starship_cache" || "$_starship_bin" -nt "$_starship_cache" ]]; then
- starship init zsh --print-full-init >! "$_starship_cache"
- fi
- source "$_starship_cache"
-fi
-
-# --- Fuzzy Finder (fzf) ---
-_fzf_cache="$HOME/.fzf-init.zsh"
-_fzf_bin="$(command -v fzf)"
-
-if [[ -n "$_fzf_bin" ]];
-then
- # Check if fzf supports the --zsh flag
-if $_fzf_bin --zsh > /dev/null 2>&1; then
- if [[ ! -f "$_fzf_cache" || "$_fzf_bin" -nt "$_fzf_cache" ]]; then
- $_fzf_bin --zsh >! "$_fzf_cache"
- fi
- source "$_fzf_cache"
- else
- # Fallback for older fzf versions
- if [[ -f ~/.fzf.zsh ]]; then
- source ~/.fzf.zsh
- fi
- fi
-fi
-
-
-# -- Zoxide (Cached) --
-_zoxide_cache="$HOME/.zoxide-init.zsh"
-_zoxide_bin="$(command -v zoxide)"
-
-if [[ -n "$_zoxide_bin" ]]; then
- if [[ ! -f "$_zoxide_cache" || "$_zoxide_bin" -nt "$_zoxide_cache" ]]; then
- "$_zoxide_bin" init zsh >! "$_zoxide_cache"
- fi
- source "$_zoxide_cache"
-fi
-unset _zoxide_cache _zoxide_bin
-
-
-# --- Autosuggestions ---
-if [ -f /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh ]; then
- # Config MUST be set before sourcing
- ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=60'
- source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
-fi
-
-# --- Syntax Highlighting (Must be last) ---
-if [[ -f "/usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" ]]; then
- source "/usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh"
-fi
-
-
-
-# Cleanup variables to keep environment clean
-unset _starship_cache _starship_bin _fzf_cache _fzf_bin
-
-# -----------------------------------------------------------------------------
-# [7] Auto login INTO UWSM HYPRLAND WITH TTY1
-# -----------------------------------------------------------------------------
-
-# Check if we are on tty1 and no display server is running
-# Using native $TTY and $WAYLAND_DISPLAY variables avoids the overhead of spawning $(tty) subshells
-if [[ -z "$DISPLAY" && -z "$WAYLAND_DISPLAY" && "$TTY" == "/dev/tty1" ]]; then
- if uwsm check may-start; then
- exec uwsm start hyprland.desktop
- fi
-fi
-
-# =============================================================================
-# End of ~/.zshrc
-# =============================================================================
diff --git a/Documents/pensive/.obsidian/snippets/matugen-theme.css b/Documents/pensive/.obsidian/snippets/matugen-theme.css
deleted file mode 120000
index 0551d8af..00000000
--- a/Documents/pensive/.obsidian/snippets/matugen-theme.css
+++ /dev/null
@@ -1 +0,0 @@
-/home/dusk/.config/matugen/generated/obsidian-theme.css
\ No newline at end of file
diff --git a/user_scripts/arch_setup_scripts/scripts/235_file_manager_switch.sh b/user_scripts/arch_setup_scripts/scripts/235_file_manager_switch.sh
index 5b11ed19..445d360d 100755
--- a/user_scripts/arch_setup_scripts/scripts/235_file_manager_switch.sh
+++ b/user_scripts/arch_setup_scripts/scripts/235_file_manager_switch.sh
@@ -48,7 +48,7 @@ declare -ra FM_CATALOG=(
)
# Paths
-declare -r CONF_VARS="${HOME}/.config/hypr/edit_here/source/default_apps.conf"
+declare -r CONF_VARS="${HOME}/.config/hypr/edit_here/source/default_apps.lua"
declare -r CONF_BINDS="${HOME}/.config/hypr/edit_here/source/keybinds.conf"
declare -r STATE_FILE="${HOME}/.config/dusky/settings/filemanager_switch"
@@ -175,7 +175,7 @@ switch_file_manager() {
return 1
fi
- # 2. Update Variable (default_apps.conf)
+ # 2. Update Variable (default_apps.lua)
if [[ ! -f "$CONF_VARS" ]]; then
log_action 1 "Config not found: $CONF_VARS"
return 1
@@ -184,49 +184,16 @@ switch_file_manager() {
local new_vars
new_vars=$(awk -v val="$target" '
BEGIN { found=0 }
- /^[\t ]*\$fileManager[\t ]*=/ {
- print "$fileManager = " val
+ /^[\t ]*fileManager[\t ]*=/ {
+ print "fileManager = \"" val "\""
found=1
next
}
{ print }
- END { if(!found) print "$fileManager = " val }
+ END { if(!found) print "fileManager = \"" val "\"" }
' "$CONF_VARS")
atomic_write "$CONF_VARS" "$new_vars"
- # 3. Update Keybind (keybinds.conf)
- if [[ ! -f "$CONF_BINDS" ]]; then
- log_action 1 "Keybinds not found: $CONF_BINDS"
- return 1
- fi
-
- local exec_cmd
- if [[ "$t_type" == "1" ]]; then
- exec_cmd="uwsm-app -- \$terminal -e \$fileManager"
- else
- exec_cmd="uwsm-app \$fileManager"
- fi
-
- local new_binds
- new_binds=$(awk -v new_cmd="$exec_cmd" '
- BEGIN { found=0 }
- /bindd[ \t]*=.*,[ \t]*File Manager[ \t]*,/ {
- split($0, parts, ",")
- printf "%s,%s,%s, exec, %s\n", parts[1], parts[2], parts[3], new_cmd
- found=1
- next
- }
- { print }
- END {
- if(!found) {
- print ""
- print "# Auto-generated by FM Switcher"
- print "bindd = $mainMod, E, File Manager, exec, " new_cmd
- }
- }
- ' "$CONF_BINDS")
- atomic_write "$CONF_BINDS" "$new_binds"
-
# 4. Update MIME Defaults
if command -v xdg-mime &>/dev/null; then
xdg-mime default "$t_desktop" inode/directory 2>/dev/null || true
@@ -246,7 +213,7 @@ switch_file_manager() {
detect_current() {
# Robust grep/cut to find current variable
if [[ -f "$CONF_VARS" ]]; then
- CURRENT_FM_KEY=$(grep -m1 '^[[:space:]]*\$fileManager[[:space:]]*=' "$CONF_VARS" | cut -d'=' -f2 | tr -d ' "' || echo "unknown")
+ CURRENT_FM_KEY=$(grep -m1 '^[[:space:]]*fileManager[[:space:]]*=' "$CONF_VARS" | cut -d'=' -f2 | tr -d ' "' || echo "unknown")
CURRENT_FM_KEY="${CURRENT_FM_KEY//[[:space:]]/}"
# Safe check for empty strings under set -e
diff --git a/user_scripts/arch_setup_scripts/scripts/236_browser_switcher.sh b/user_scripts/arch_setup_scripts/scripts/236_browser_switcher.sh
index 26deec82..67cefa74 100755
--- a/user_scripts/arch_setup_scripts/scripts/236_browser_switcher.sh
+++ b/user_scripts/arch_setup_scripts/scripts/236_browser_switcher.sh
@@ -39,7 +39,7 @@ declare -ra BROWSER_CATALOG=(
)
# Paths
-declare -r CONF_VARS="${HOME}/.config/hypr/edit_here/source/default_apps.conf"
+declare -r CONF_VARS="${HOME}/.config/hypr/edit_here/source/default_apps.lua"
declare -r CONF_BINDS="${HOME}/.config/hypr/edit_here/source/keybinds.conf"
declare -r STATE_FILE="${HOME}/.config/dusky/settings/browser_switch"
@@ -166,7 +166,7 @@ switch_browser() {
return 1
fi
- # 2. Update Variable (default_apps.conf)
+ # 2. Update Variable (default_apps.lua)
if [[ ! -f "$CONF_VARS" ]]; then
log_action 1 "Config not found: $CONF_VARS"
return 1
@@ -175,49 +175,16 @@ switch_browser() {
local new_vars
new_vars=$(awk -v val="$target" '
BEGIN { found=0 }
- /^[\t ]*\$browser[\t ]*=/ {
- print "$browser = " val
+ /^[\t ]*browser[\t ]*=/ {
+ print "browser = \"" val "\""
found=1
next
}
{ print }
- END { if(!found) print "$browser = " val }
+ END { if(!found) print "browser = \"" val "\"" }
' "$CONF_VARS")
atomic_write "$CONF_VARS" "$new_vars"
- # 3. Update Keybind (keybinds.conf)
- if [[ ! -f "$CONF_BINDS" ]]; then
- log_action 1 "Keybinds not found: $CONF_BINDS"
- return 1
- fi
-
- local exec_cmd
- if [[ "$t_type" == "1" ]]; then
- exec_cmd="uwsm-app -- \$terminal -e \$browser"
- else
- exec_cmd="uwsm-app -- \$browser"
- fi
-
- local new_binds
- new_binds=$(awk -v new_cmd="$exec_cmd" '
- BEGIN { found=0 }
- /bindd[ \t]*=.*,[ \t]*Launch Browser[ \t]*,/ {
- split($0, parts, ",")
- printf "%s,%s,%s, exec, %s\n", parts[1], parts[2], parts[3], new_cmd
- found=1
- next
- }
- { print }
- END {
- if(!found) {
- print ""
- print "# Auto-generated by Browser Switcher"
- print "bindd = $mainMod, W, Launch Browser, exec, " new_cmd
- }
- }
- ' "$CONF_BINDS")
- atomic_write "$CONF_BINDS" "$new_binds"
-
# 4. Update MIME Defaults
if command -v xdg-mime &>/dev/null; then
xdg-mime default "$t_desktop" x-scheme-handler/http 2>/dev/null || true
@@ -246,7 +213,7 @@ switch_browser() {
detect_current() {
# Robust grep/cut to find current variable
if [[ -f "$CONF_VARS" ]]; then
- CURRENT_BROWSER_KEY=$(grep -m1 '^[[:space:]]*\$browser[[:space:]]*=' "$CONF_VARS" | cut -d'=' -f2 | tr -d ' "' || echo "unknown")
+ CURRENT_BROWSER_KEY=$(grep -m1 '^[[:space:]]*browser[[:space:]]*=' "$CONF_VARS" | cut -d'=' -f2 | tr -d ' "' || echo "unknown")
CURRENT_BROWSER_KEY="${CURRENT_BROWSER_KEY//[[:space:]]/}"
# Safe check for empty strings under set -e
diff --git a/user_scripts/arch_setup_scripts/scripts/237_text_editer_switcher.sh b/user_scripts/arch_setup_scripts/scripts/237_text_editer_switcher.sh
index e210b5ae..e0a69396 100755
--- a/user_scripts/arch_setup_scripts/scripts/237_text_editer_switcher.sh
+++ b/user_scripts/arch_setup_scripts/scripts/237_text_editer_switcher.sh
@@ -48,7 +48,7 @@ declare -ra EDITOR_CATALOG=(
)
# Paths
-declare -r CONF_VARS="${HOME}/.config/hypr/edit_here/source/default_apps.conf"
+declare -r CONF_VARS="${HOME}/.config/hypr/edit_here/source/default_apps.lua"
declare -r CONF_BINDS="${HOME}/.config/hypr/edit_here/source/keybinds.conf"
declare -r STATE_FILE="${HOME}/.config/dusky/settings/texteditor_switch"
@@ -175,7 +175,7 @@ switch_text_editor() {
return 1
fi
- # 2. Update Variable (default_apps.conf)
+ # 2. Update Variable (default_apps.lua)
if [[ ! -f "$CONF_VARS" ]]; then
log_action 1 "Config not found: $CONF_VARS"
return 1
@@ -184,49 +184,16 @@ switch_text_editor() {
local new_vars
new_vars=$(awk -v val="$target" '
BEGIN { found=0 }
- /^[\t ]*\$textEditor[\t ]*=/ {
- print "$textEditor = " val
+ /^[\t ]*textEditor[\t ]*=/ {
+ print "textEditor = \"" val "\""
found=1
next
}
{ print }
- END { if(!found) print "$textEditor = " val }
+ END { if(!found) print "textEditor = \"" val "\"" }
' "$CONF_VARS")
atomic_write "$CONF_VARS" "$new_vars"
- # 3. Update Keybind (keybinds.conf)
- if [[ ! -f "$CONF_BINDS" ]]; then
- log_action 1 "Keybinds not found: $CONF_BINDS"
- return 1
- fi
-
- local exec_cmd
- if [[ "$t_type" == "1" ]]; then
- exec_cmd="uwsm-app -- \$terminal --class $target -e \$textEditor"
- else
- exec_cmd="uwsm-app \$textEditor"
- fi
-
- local new_binds
- new_binds=$(awk -v new_cmd="$exec_cmd" '
- BEGIN { found=0 }
- /bindd[ \t]*=.*,[ \t]*Open Text Editor[ \t]*,/ {
- split($0, parts, ",")
- printf "%s,%s,%s, exec, %s\n", parts[1], parts[2], parts[3], new_cmd
- found=1
- next
- }
- { print }
- END {
- if(!found) {
- print ""
- print "# Auto-generated by Text Editor Switcher"
- print "bindd = $mainMod, R, Open Text Editor, exec, " new_cmd
- }
- }
- ' "$CONF_BINDS")
- atomic_write "$CONF_BINDS" "$new_binds"
-
# 4. Update MIME Defaults
if command -v xdg-mime &>/dev/null; then
xdg-mime default "$t_desktop" text/plain 2>/dev/null || true
@@ -246,7 +213,7 @@ switch_text_editor() {
detect_current() {
# Robust grep/cut to find current variable
if [[ -f "$CONF_VARS" ]]; then
- CURRENT_EDITOR_KEY=$(grep -m1 '^[[:space:]]*\$textEditor[[:space:]]*=' "$CONF_VARS" | cut -d'=' -f2 | tr -d ' "' || echo "unknown")
+ CURRENT_EDITOR_KEY=$(grep -m1 '^[[:space:]]*textEditor[[:space:]]*=' "$CONF_VARS" | cut -d'=' -f2 | tr -d ' "' || echo "unknown")
CURRENT_EDITOR_KEY="${CURRENT_EDITOR_KEY//[[:space:]]/}"
# Safe check for empty strings under set -e
diff --git a/user_scripts/arch_setup_scripts/scripts/238_terminal_switcher.sh b/user_scripts/arch_setup_scripts/scripts/238_terminal_switcher.sh
index 92eaa13c..36e5bcd1 100755
--- a/user_scripts/arch_setup_scripts/scripts/238_terminal_switcher.sh
+++ b/user_scripts/arch_setup_scripts/scripts/238_terminal_switcher.sh
@@ -37,7 +37,7 @@ declare -ra TERM_CATALOG=(
)
# Paths
-declare -r CONF_VARS="${HOME}/.config/hypr/edit_here/source/default_apps.conf"
+declare -r CONF_VARS="${HOME}/.config/hypr/edit_here/source/default_apps.lua"
declare -r CONF_BINDS="${HOME}/.config/hypr/edit_here/source/keybinds.conf"
declare -r STATE_FILE="${HOME}/.config/dusky/settings/terminal_switch"
@@ -162,7 +162,7 @@ switch_terminal() {
return 1
fi
- # 2. Update Variable (default_apps.conf)
+ # 2. Update Variable (default_apps.lua)
if [[ ! -f "$CONF_VARS" ]]; then
log_action 1 "Config not found: $CONF_VARS"
return 1
@@ -171,43 +171,16 @@ switch_terminal() {
local new_vars
new_vars=$(awk -v val="$target" '
BEGIN { found=0 }
- /^[\t ]*\$terminal[\t ]*=/ {
- print "$terminal = " val
+ /^[\t ]*terminal[\t ]*=/ {
+ print "terminal = \"" val "\""
found=1
next
}
{ print }
- END { if(!found) print "$terminal = " val }
+ END { if(!found) print "terminal = \"" val "\"" }
' "$CONF_VARS")
atomic_write "$CONF_VARS" "$new_vars"
- # 3. Update Keybind (keybinds.conf)
- if [[ ! -f "$CONF_BINDS" ]]; then
- log_action 1 "Keybinds not found: $CONF_BINDS"
- return 1
- fi
-
- local exec_cmd="uwsm-app -- \$terminal"
- local new_binds
- new_binds=$(awk -v new_cmd="$exec_cmd" '
- BEGIN { found=0 }
- /bindd[ \t]*=.*,[ \t]*Launch Terminal[ \t]*,/ {
- split($0, parts, ",")
- printf "%s,%s,%s, exec, %s\n", parts[1], parts[2], parts[3], new_cmd
- found=1
- next
- }
- { print }
- END {
- if(!found) {
- print ""
- print "# Auto-generated by Terminal Switcher"
- print "bindd = $mainMod, Q, Launch Terminal, exec, " new_cmd
- }
- }
- ' "$CONF_BINDS")
- atomic_write "$CONF_BINDS" "$new_binds"
-
# 4. Update State Files
local legacy_state="false"
[[ "$target" == "kitty" ]] && legacy_state="true"
@@ -221,7 +194,7 @@ switch_terminal() {
detect_current() {
if [[ -f "$CONF_VARS" ]]; then
- CURRENT_TERM_KEY=$(grep -m1 '^[[:space:]]*\$terminal[[:space:]]*=' "$CONF_VARS" | cut -d'=' -f2 | tr -d ' "' || echo "unknown")
+ CURRENT_TERM_KEY=$(grep -m1 '^[[:space:]]*terminal[[:space:]]*=' "$CONF_VARS" | cut -d'=' -f2 | tr -d ' "' || echo "unknown")
CURRENT_TERM_KEY="${CURRENT_TERM_KEY//[[:space:]]/}"
if [[ -z "$CURRENT_TERM_KEY" ]]; then
diff --git a/user_scripts/dusky_system/control_center/dusky_config.yaml b/user_scripts/dusky_system/control_center/dusky_config.yaml
index 135f1662..957ed3c4 100644
--- a/user_scripts/dusky_system/control_center/dusky_config.yaml
+++ b/user_scripts/dusky_system/control_center/dusky_config.yaml
@@ -186,7 +186,7 @@ pages:
icon: view-refresh-symbolic
on_press:
type: exec
- command: hyprctl reload
+ command: sh -c 'hyprctl reload && hyprctl notify 1 2000 0 " Config reloaded"'
terminal: false
- type: grid_card
properties:
@@ -980,12 +980,12 @@ pages:
enabled:
type: exec
command: kitty --class power_saver.sh --title "Enable Power Saver" --hold
- sh -c "$HOME/user_scripts/battery/power_saving/power_saver.sh"
+ sh -c "$HOME/user_scripts/battery/power_saver.sh --enable"
terminal: false
disabled:
type: exec
- command: kitty --class power_saver_off.sh --title "Disable Power Saver"
- --hold sh -c "$HOME/user_scripts/battery/power_saving_off/power_saver_off.sh"
+ command: kitty --class power_saver.sh --title "Disable Power Saver" --hold
+ sh -c "$HOME/user_scripts/battery/power_saver.sh --disable"
terminal: false
- type: button
properties:
@@ -1685,7 +1685,7 @@ pages:
button_text: "File"
on_press:
type: exec
- command: gnome-text-editor "$HOME/.config/hypr/edit_here/hyprland.conf"
+ command: gnome-text-editor "$HOME/.config/hypr/edit_here/hyprland.lua"
terminal: false
- type: navigation
@@ -1708,7 +1708,7 @@ pages:
button_text: "File"
on_press:
type: exec
- command: gnome-text-editor "$HOME/.config/hypr/edit_here/source/keybinds.conf"
+ command: gnome-text-editor "$HOME/.config/hypr/edit_here/source/keybinds.lua"
- icon: input-keyboard-symbolic
button_text: "TUI"
style: suggested
@@ -1725,7 +1725,7 @@ pages:
button_text: "File"
on_press:
type: exec
- command: gnome-text-editor "$HOME/.config/hypr/edit_here/source/input.conf"
+ command: gnome-text-editor "$HOME/.config/hypr/edit_here/source/input.lua"
- icon: input-mouse-symbolic
button_text: "TUI"
style: suggested
@@ -1760,12 +1760,12 @@ pages:
- type: button
properties:
title: User Environment
- description: ~/.config/hypr/edit_here/source/environment_variables.conf
+ description: ~/.config/hypr/edit_here/source/environment_variables.lua
icon: text-x-script-symbolic
button_text: "File"
on_press:
type: exec
- command: gnome-text-editor "$HOME/.config/hypr/edit_here/source/environment_variables.conf"
+ command: gnome-text-editor "$HOME/.config/hypr/edit_here/source/environment_variables.lua"
- type: button
properties:
title: UWSM Global
@@ -1805,7 +1805,7 @@ pages:
button_text: "File"
on_press:
type: exec
- command: gnome-text-editor "$HOME/.config/hypr/edit_here/source/monitors.conf"
+ command: gnome-text-editor "$HOME/.config/hypr/edit_here/source/monitors.lua"
- icon: video-display-symbolic
button_text: "TUI"
style: suggested
@@ -1822,7 +1822,7 @@ pages:
button_text: "File"
on_press:
type: exec
- command: gnome-text-editor "$HOME/.config/hypr/edit_here/source/window_rules.conf"
+ command: gnome-text-editor "$HOME/.config/hypr/edit_here/source/window_rules.lua"
- icon: application-x-addon-symbolic
button_text: "TUI"
style: suggested
@@ -1850,7 +1850,7 @@ pages:
button_text: "File"
on_press:
type: exec
- command: gnome-text-editor "$HOME/.config/hypr/edit_here/source/appearance.conf"
+ command: gnome-text-editor "$HOME/.config/hypr/edit_here/source/appearance.lua"
- icon: applications-graphics-symbolic
button_text: "TUI"
style: suggested
@@ -1867,7 +1867,7 @@ pages:
button_text: "File"
on_press:
type: exec
- command: gnome-text-editor "$HOME/.config/hypr/edit_here/source/workspace_rules.conf"
+ command: gnome-text-editor "$HOME/.config/hypr/edit_here/source/workspace_rules.lua"
- icon: applications-graphics-symbolic
button_text: "TUI"
style: suggested
@@ -1928,7 +1928,7 @@ pages:
interval: 5
on_change:
type: exec
- command: "ln -sf $HOME/.config/waybar/{value}/config.jsonc $HOME/.config/waybar/config.jsonc; ln -sf $HOME/.config/waybar/{value}/style.css $HOME/.config/waybar/style.css; killall -SIGUSR2 waybar"
+ command: "ln -sf $HOME/.config/waybar/{value}/config.jsonc $HOME/.config/waybar/config.jsonc; ln -sf $HOME/.config/waybar/{value}/style.css $HOME/.config/waybar/style.css; $HOME/user_scripts/waybar/waybar_autostart.sh"
- type: section
properties:
@@ -2131,53 +2131,53 @@ pages:
items:
- type: button
properties:
- title: Hyprland.conf
+ title: Hyprland.lua
button_text: "View"
on_press:
type: exec
- command: gnome-text-editor "$HOME/.config/hypr/hyprland.conf"
+ command: gnome-text-editor "$HOME/.config/hypr/hyprland.lua"
- type: button
properties:
title: Environment Variables
button_text: "View"
on_press:
type: exec
- command: gnome-text-editor "$HOME/.config/hypr/source/environment_variables.conf"
+ command: gnome-text-editor "$HOME/.config/hypr/source/environment_variables.lua"
- type: button
properties:
title: Appearance
button_text: "View"
on_press:
type: exec
- command: gnome-text-editor "$HOME/.config/hypr/source/appearance.conf"
+ command: gnome-text-editor "$HOME/.config/hypr/source/appearance.lua"
- type: button
properties:
title: Autostart
button_text: "View"
on_press:
type: exec
- command: gnome-text-editor "$HOME/.config/hypr/source/autostart.conf"
+ command: gnome-text-editor "$HOME/.config/hypr/source/autostart.lua"
- type: button
properties:
title: Keybinds
button_text: "View"
on_press:
type: exec
- command: gnome-text-editor "$HOME/.config/hypr/source/keybinds.conf"
+ command: gnome-text-editor "$HOME/.config/hypr/source/keybinds.lua"
- type: button
properties:
title: Window Rules
button_text: "View"
on_press:
type: exec
- command: gnome-text-editor "$HOME/.config/hypr/source/window_rules.conf"
+ command: gnome-text-editor "$HOME/.config/hypr/source/window_rules.lua"
- type: button
properties:
title: Input
button_text: "View"
on_press:
type: exec
- command: gnome-text-editor "$HOME/.config/hypr/source/input.conf"
+ command: gnome-text-editor "$HOME/.config/hypr/source/input.lua"
- id: keybinds
title: Keybinds
@@ -2888,6 +2888,13 @@ pages:
value:
type: exec
command: hyprctl version | grep Hyprland | awk '{print $2}'
+ - type: label
+ properties:
+ title: Config Mode
+ icon: text-x-script
+ value:
+ type: exec
+ command: "test -f $HOME/.config/hypr/hyprland.lua && echo 'Lua' || echo 'Legacy'"
- type: section
properties:
title: System Information
diff --git a/user_scripts/hypr/adjust_scale.py b/user_scripts/hypr/adjust_scale.py
index 3995676c..9a0168fa 100755
--- a/user_scripts/hypr/adjust_scale.py
+++ b/user_scripts/hypr/adjust_scale.py
@@ -10,7 +10,7 @@
# --- Immutable Configuration ---
CONFIG_DIR = Path.home() / ".config/hypr/edit_here/source"
-CONFIG_FILE = CONFIG_DIR / "monitors.conf"
+CONFIG_FILE = CONFIG_DIR / "monitors.lua"
NOTIFY_TAG = "hypr_scale_adjust"
MIN_LOGICAL_WIDTH = 640
MIN_LOGICAL_HEIGHT = 360
@@ -99,7 +99,7 @@ def compute_next_scale(current: float, direction: str, phys_w: int, phys_h: int)
return max(candidates)
def update_config_atomically(monitor_name: str, new_scale: float) -> None:
- """Updates the config via state machine and strict POSIX atomic replacement."""
+ """Updates hl.monitor() scale in monitors.lua via strict POSIX atomic replacement."""
if not CONFIG_FILE.exists():
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
CONFIG_FILE.touch()
@@ -111,64 +111,28 @@ def update_config_atomically(monitor_name: str, new_scale: float) -> None:
found = False
log_debug(f"Updating config: {monitor_name} -> {new_scale:g}")
- # 1. Process V2 Blocks
- def v2_replacer(match: re.Match) -> str:
+ def lua_replacer(match: re.Match) -> str:
nonlocal found
- block = match.group(0)
- if re.search(rf"^\s*output\s*=\s*{re.escape(monitor_name)}\b", block, re.MULTILINE):
- if re.search(r"^\s*scale\s*=.*", block, re.MULTILINE):
- block = re.sub(r"(^\s*scale\s*=).*$", rf"\1 {new_scale:g}", block, flags=re.MULTILINE)
- else:
- block = re.sub(r"(\s*)\}$", rf"\1 scale = {new_scale:g}\n}}", block)
- found = True
- return block
-
- config_text = re.sub(r"monitorv2\s*\{[^}]*\}", v2_replacer, config_text)
+ line = match.group(0)
+ if f'output = "{monitor_name}"' not in line:
+ return line
+ found = True
+ updated = re.sub(r'(\bscale\s*=\s*)[0-9.]+', rf'\g<1>{new_scale:g}', line)
+ if updated != line:
+ return updated
+ # No scale field yet — insert before closing })
+ return re.sub(r'(\s*\}\s*\)\s*)$', rf', scale = {new_scale:g}\1', line)
+
+ config_text = re.sub(r'^.*hl\.monitor\s*\(.*$', lua_replacer, config_text, flags=re.MULTILINE)
- # 2. Process V1 Rules
- if not found:
- def v1_replacer(match: re.Match) -> str:
- nonlocal found
- mon_name = match.group(2).strip()
-
- if mon_name == monitor_name:
- found = True
- remainder = match.group(3)
- comment = ""
-
- # FIX: Dynamically capture the comment and all preceding whitespace to preserve formatting
- c_match = re.search(r'(\s*#.*)', remainder)
- if c_match:
- comment = c_match.group(1)
- remainder = remainder[:c_match.start()]
-
- parts = remainder.split(",")
- if len(parts) == 2:
- if "disable" in parts[1].strip():
- parts = ["", " preferred", " auto", f" {new_scale:g}"]
- else:
- parts.extend([" auto", f" {new_scale:g}"])
- elif len(parts) == 3:
- parts.append(f" {new_scale:g}")
- elif len(parts) >= 4:
- parts[3] = f" {new_scale:g}"
-
- return f"{match.group(1)}{match.group(2)}{','.join(parts)}{comment}"
- return match.group(0)
-
- config_text = re.sub(r"^(\s*monitor\s*=\s*)([^,\n]+)(,.*)$", v1_replacer, config_text, flags=re.MULTILINE)
-
- # 3. Append entirely new rule
if not found:
log_info(f"Appending new entry for: {monitor_name}")
- config_text += f"\nmonitor = {monitor_name}, preferred, auto, {new_scale:g}\n"
+ config_text += f'\nhl.monitor({{ output = "{monitor_name}", mode = "preferred", position = "auto", scale = {new_scale:g} }})\n'
- # 4. Strict POSIX Atomic Write
- fd, temp_path = tempfile.mkstemp(dir=real_path.parent, prefix=".monitors.conf.tmp.")
+ fd, temp_path = tempfile.mkstemp(dir=real_path.parent, prefix=".monitors.lua.tmp.")
try:
with os.fdopen(fd, 'w') as temp_file:
temp_file.write(config_text)
-
os.chmod(temp_path, real_path.stat().st_mode)
os.replace(temp_path, real_path)
except Exception as e:
@@ -192,21 +156,21 @@ def main():
notify("Monitor Scale", f"Limit Reached: {current_scale:g}", "normal")
return
- # Write the target scale to disk
update_config_atomically(mon_name, new_scale)
log_info(f"Applying scale {new_scale:g} via hyprctl reload")
subprocess.run(["hyprctl", "reload"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
- # State Verification: Deterministic polling to prevent async race conditions
+ # Poll for Hyprland to apply the new scale. Sleep first so we don't race
+ # the reload — querying immediately almost always returns the old value.
actual_scale = current_scale
- for _ in range(25): # Poll every 100ms for up to 2.5 seconds
- time.sleep(0.1)
+ time.sleep(0.3)
+ for _ in range(22): # Poll every 100ms for up to ~2.5 seconds total
_, _, _, polled_scale = get_active_monitor(mon_name)
if abs(polled_scale - current_scale) > 0.000001:
actual_scale = polled_scale
break
- actual_scale = polled_scale
+ time.sleep(0.1)
# Verify if Wayland accepted the request or clamped it due to hardware limits
if abs(actual_scale - new_scale) > 0.000001:
diff --git a/user_scripts/hypr/dusky_appearances.sh b/user_scripts/hypr/dusky_appearances.sh
index a85fb2a4..c5245fe9 100755
--- a/user_scripts/hypr/dusky_appearances.sh
+++ b/user_scripts/hypr/dusky_appearances.sh
@@ -14,7 +14,7 @@ shopt -s extglob
# ▼ USER CONFIGURATION (EDIT THIS SECTION) ▼
# =============================================================================
-declare -r CONFIG_FILE="${HOME}/.config/hypr/edit_here/source/appearance.conf"
+declare -r CONFIG_FILE="${HOME}/.config/hypr/edit_here/source/appearance.lua"
declare -r APP_TITLE="Dusky Appearances"
declare -r APP_VERSION="v7.8.0"
@@ -33,23 +33,22 @@ declare -ra TABS=("Layout" "Decoration" "Blur" "Shadow" "Snap")
# Item Registration
register_items() {
# Tab 0: Layout & General
- register 0 "Gaps In" "gaps_in|int||0|100|1" "6"
- register 0 "Gaps Out" "gaps_out|int||0|100|1" "12"
+ register 0 "Gaps In" "gaps_in|int|general|0|100|1" "6"
+ register 0 "Gaps Out" "gaps_out|int|general|0|100|1" "12"
register 0 "Gaps Workspaces" "gaps_workspaces|int|general|0|100|1" "0"
- register 0 "Border Size" "border_size|int||0|10|1" "2"
+ register 0 "Border Size" "border_size|int|general|0|10|1" "2"
register 0 "Resize on Border" "resize_on_border|bool|general|||" "false"
register 0 "Allow Tearing" "allow_tearing|bool|general|||" "true"
- register 0 "Single Window Gap" '$single_window_gap|int||0|100|1' "10"
# Tab 1: Decoration
- register 1 "Rounding" "rounding|int||0|30|1" "6"
- register 1 "Rounding Power" "rounding_power|float||0.0|10.0|0.1" "6.0"
- register 1 "Active Opacity" "active_opacity|float||0.1|1.0|0.05" "1.0"
- register 1 "Inactive Opacity" "inactive_opacity|float||0.1|1.0|0.05" "1.0"
- register 1 "Fullscreen Opacity" "fullscreen_opacity|float||0.1|1.0|0.05" "1.0"
- register 1 "Dim Inactive" "dim_inactive|bool||||" "true"
- register 1 "Dim Strength" "dim_strength|float||0.0|1.0|0.05" "0.2"
- register 1 "Dim Special" "dim_special|float||0.0|1.0|0.05" "0.8"
+ register 1 "Rounding" "rounding|int|decoration|0|30|1" "6"
+ register 1 "Rounding Power" "rounding_power|float|decoration|0.0|10.0|0.1" "6.0"
+ register 1 "Active Opacity" "active_opacity|float|decoration|0.1|1.0|0.05" "1.0"
+ register 1 "Inactive Opacity" "inactive_opacity|float|decoration|0.1|1.0|0.05" "1.0"
+ register 1 "Fullscreen Opacity" "fullscreen_opacity|float|decoration|0.1|1.0|0.05" "1.0"
+ register 1 "Dim Inactive" "dim_inactive|bool|decoration|||" "true"
+ register 1 "Dim Strength" "dim_strength|float|decoration|0.0|1.0|0.05" "0.2"
+ register 1 "Dim Special" "dim_special|float|decoration|0.0|1.0|0.05" "0.8"
# Tab 2: Blur
register 2 "Blur Enabled" "enabled|bool|blur|||" "false"
@@ -68,8 +67,7 @@ register_items() {
register 3 "Shadow Power" "render_power|int|shadow|1|4|1" "2"
register 3 "Shadow Sharp" "sharp|bool|shadow|||" "false"
register 3 "Shadow Scale" "scale|float|shadow|0.0|1.1|0.05" "1.0"
- register 3 "Shadow Ignore Win" "ignore_window|bool|shadow|||" "true"
- register 3 "Shadow Color" 'color|cycle|shadow|rgba(1a1a1aee),$primary||' 'rgba(1a1a1aee)'
+ register 3 "Shadow Color" 'color|cycle|shadow|rgba(1a1a1aee)||' 'rgba(1a1a1aee)'
# Tab 4: Snap
register 4 "Snap Enabled" "enabled|bool|snap|||" "false"
@@ -80,7 +78,7 @@ register_items() {
# Post-Write Hook
post_write_action() {
- : # Reload command here, e.g.: hyprctl reload &>/dev/null || :
+ hyprctl reload &>/dev/null || :
}
# =============================================================================
@@ -202,17 +200,18 @@ populate_config_cache() {
fi
done < <(LC_ALL=C awk '
BEGIN { depth = 0 }
- /^[[:space:]]*#/ { next }
+ /^[[:space:]]*--/ { next }
{
line = $0
# Strip inline comments for structural parsing so "}" in comments doesn'"'"'t break blocks
clean = line
- sub(/[[:space:]]+#.*$/, "", clean)
+ sub(/[[:space:]]+--.*$/, "", clean)
tmpline = clean
- while (match(tmpline, /[a-zA-Z0-9_.:-]+[[:space:]]*\{/)) {
+ # Lua tables use "name = {" syntax; conf uses "name {"
+ while (match(tmpline, /[a-zA-Z0-9_.:-]+[[:space:]]*(=[[:space:]]*)?\{/)) {
block_str = substr(tmpline, RSTART, RLENGTH)
- sub(/[[:space:]]*\{/, "", block_str)
+ sub(/[[:space:]]*(=[[:space:]]*)?\{/, "", block_str)
depth++
block_stack[depth] = block_str
tmpline = substr(tmpline, RSTART + RLENGTH)
@@ -225,8 +224,12 @@ populate_config_cache() {
gsub(/^[[:space:]]+|[[:space:]]+$/, "", key)
gsub(/^[[:space:]]+|[[:space:]]+$/, "", val)
# Strip trailing inline comment from value
- sub(/[[:space:]]+#.*$/, "", val)
+ sub(/[[:space:]]+--.*$/, "", val)
gsub(/^[[:space:]]+|[[:space:]]+$/, "", val)
+ # Strip trailing comma (Lua table syntax)
+ sub(/,$/, "", val)
+ # Strip surrounding double-quotes (Lua string values)
+ if (val ~ /^".*"$/) val = substr(val, 2, length(val) - 2)
if (key != "") {
current_block = (depth > 0) ? block_stack[depth] : ""
print key "|" current_block "=" val
@@ -266,13 +269,14 @@ write_value_to_file() {
{
line = $0
clean = line
- sub(/^[[:space:]]*#.*/, "", clean)
- sub(/[[:space:]]+#.*$/, "", clean)
+ sub(/^[[:space:]]*--.*/, "", clean)
+ sub(/[[:space:]]+--.*$/, "", clean)
tmpline = clean
- while (match(tmpline, /[a-zA-Z0-9_.:-]+[[:space:]]*\{/)) {
+ # Lua tables use "name = {" syntax; conf uses "name {"
+ while (match(tmpline, /[a-zA-Z0-9_.:-]+[[:space:]]*(=[[:space:]]*)?\{/)) {
block_str = substr(tmpline, RSTART, RLENGTH)
- sub(/[[:space:]]*\{/, "", block_str)
+ sub(/[[:space:]]*(=[[:space:]]*)?\{/, "", block_str)
depth++
block_stack[depth] = block_str
if (do_block && block_str == target_block && !in_target) {
@@ -311,7 +315,19 @@ write_value_to_file() {
match(rest, /^[[:space:]]*/)
space_after = substr(rest, RSTART, RLENGTH)
- print before_eq space_after new_value
+ # Detect trailing comma and surrounding quotes from the original value
+ old_val = substr(rest, RSTART + RLENGTH)
+ sub(/[[:space:]]+--.*$/, "", old_val)
+ gsub(/^[[:space:]]+|[[:space:]]+$/, "", old_val)
+ was_trailing = (old_val ~ /,$/) ? 1 : 0
+ sub(/,$/, "", old_val)
+ was_quoted = (old_val ~ /^".*"$/) ? 1 : 0
+
+ out_val = new_value
+ if (was_quoted && !(new_value ~ /^".*"$/)) out_val = "\"" new_value "\""
+ trailing = was_trailing ? "," : ""
+
+ print before_eq space_after out_val trailing
replaced = 1
} else {
print line
diff --git a/user_scripts/hypr/dusky_input.sh b/user_scripts/hypr/dusky_input.sh
index 5b96ba92..a7691195 100755
--- a/user_scripts/hypr/dusky_input.sh
+++ b/user_scripts/hypr/dusky_input.sh
@@ -26,7 +26,7 @@ shopt -s extglob
# ▼ USER CONFIGURATION (EDIT THIS SECTION) ▼
# =============================================================================
-declare -r CONFIG_FILE="${HOME}/.config/hypr/edit_here/source/input.conf"
+declare -r CONFIG_FILE="${HOME}/.config/hypr/edit_here/source/input.lua"
declare -r APP_TITLE="Dusky Input"
declare -r APP_VERSION="v5.4.0 (Hardened)"
@@ -63,7 +63,7 @@ register_items() {
# Tab 2: Touchpad (Block: 'touchpad')
register 2 "TP Nat Scroll" 'natural_scroll|bool|touchpad|||' "true"
- register 2 "Tap to Click" 'tap-to-click|bool|touchpad|||' "true"
+ register 2 "Tap to Click" 'tap_to_click|bool|touchpad|||' "true"
register 2 "Disable While Typing" 'disable_while_typing|bool|touchpad|||' "true"
register 2 "Clickfinger Behav" 'clickfinger_behavior|bool|touchpad|||' "false"
register 2 "Drag Lock" 'drag_lock|bool|touchpad|||' "false"
@@ -87,7 +87,7 @@ register_items() {
# Post-Write Hook
post_write_action() {
- : # Reload command here, e.g.: hyprctl reload &>/dev/null || :
+ hyprctl reload &>/dev/null || :
}
# =============================================================================
@@ -210,17 +210,18 @@ populate_config_cache() {
fi
done < <(LC_ALL=C awk '
BEGIN { depth = 0 }
- /^[[:space:]]*#/ { next }
+ /^[[:space:]]*--/ { next }
{
line = $0
# Strip inline comments for structural parsing so "}" in comments doesn'"'"'t break blocks
clean = line
- sub(/[[:space:]]+#.*$/, "", clean)
+ sub(/[[:space:]]+--.*$/, "", clean)
tmpline = clean
- while (match(tmpline, /[a-zA-Z0-9_.:-]+[[:space:]]*\{/)) {
+ # Lua tables use "name = {" syntax; conf uses "name {"
+ while (match(tmpline, /[a-zA-Z0-9_.:-]+[[:space:]]*(=[[:space:]]*)?\{/)) {
block_str = substr(tmpline, RSTART, RLENGTH)
- sub(/[[:space:]]*\{/, "", block_str)
+ sub(/[[:space:]]*(=[[:space:]]*)?\{/, "", block_str)
depth++
block_stack[depth] = block_str
tmpline = substr(tmpline, RSTART + RLENGTH)
@@ -233,8 +234,12 @@ populate_config_cache() {
gsub(/^[[:space:]]+|[[:space:]]+$/, "", key)
gsub(/^[[:space:]]+|[[:space:]]+$/, "", val)
# Strip trailing inline comment from value
- sub(/[[:space:]]+#.*$/, "", val)
+ sub(/[[:space:]]+--.*$/, "", val)
gsub(/^[[:space:]]+|[[:space:]]+$/, "", val)
+ # Strip trailing comma (Lua table syntax)
+ sub(/,$/, "", val)
+ # Strip surrounding double-quotes (Lua string values)
+ if (val ~ /^".*"$/) val = substr(val, 2, length(val) - 2)
if (key != "") {
current_block = (depth > 0) ? block_stack[depth] : ""
print key "|" current_block "=" val
@@ -274,13 +279,14 @@ write_value_to_file() {
{
line = $0
clean = line
- sub(/^[[:space:]]*#.*/, "", clean)
- sub(/[[:space:]]+#.*$/, "", clean)
+ sub(/^[[:space:]]*--.*/, "", clean)
+ sub(/[[:space:]]+--.*$/, "", clean)
tmpline = clean
- while (match(tmpline, /[a-zA-Z0-9_.:-]+[[:space:]]*\{/)) {
+ # Lua tables use "name = {" syntax; conf uses "name {"
+ while (match(tmpline, /[a-zA-Z0-9_.:-]+[[:space:]]*(=[[:space:]]*)?\{/)) {
block_str = substr(tmpline, RSTART, RLENGTH)
- sub(/[[:space:]]*\{/, "", block_str)
+ sub(/[[:space:]]*(=[[:space:]]*)?\{/, "", block_str)
depth++
block_stack[depth] = block_str
if (do_block && block_str == target_block && !in_target) {
@@ -316,7 +322,19 @@ write_value_to_file() {
match(rest, /^[[:space:]]*/)
space_after = substr(rest, RSTART, RLENGTH)
- print before_eq space_after new_value
+ # Detect trailing comma and surrounding quotes from the original value
+ old_val = substr(rest, RSTART + RLENGTH)
+ sub(/[[:space:]]+--.*$/, "", old_val)
+ gsub(/^[[:space:]]+|[[:space:]]+$/, "", old_val)
+ was_trailing = (old_val ~ /,$/) ? 1 : 0
+ sub(/,$/, "", old_val)
+ was_quoted = (old_val ~ /^".*"$/) ? 1 : 0
+
+ out_val = new_value
+ if (was_quoted && !(new_value ~ /^".*"$/)) out_val = "\"" new_value "\""
+ trailing = was_trailing ? "," : ""
+
+ print before_eq space_after out_val trailing
replaced = 1
} else {
print line
diff --git a/user_scripts/hypr/dusky_keybinds.sh b/user_scripts/hypr/dusky_keybinds.sh
index e724c565..8797f0c4 100755
--- a/user_scripts/hypr/dusky_keybinds.sh
+++ b/user_scripts/hypr/dusky_keybinds.sh
@@ -47,14 +47,14 @@ readonly BRIGHT_WHITE=$'\033[0;97m'
readonly DIM=$'\033[2m'
# --- Paths ---
-readonly SOURCE_CONF="${HOME}/.config/hypr/source/keybinds.conf"
-readonly CUSTOM_CONF="${HOME}/.config/hypr/edit_here/source/keybinds.conf"
+readonly SOURCE_CONF="${HOME}/.config/hypr/source/keybinds.lua"
+readonly CUSTOM_CONF="${HOME}/.config/hypr/edit_here/source/keybinds.lua"
readonly LOCK_FILE="${CUSTOM_CONF}.lock"
# --- Sentinels ---
readonly CREATE_MARKER_ID="__CREATE_NEW_BIND__"
readonly SOURCE_INFO_MARKER="__SOURCE_DIRECTIVE_INFO__"
-readonly EMPTY_BIND_TEMPLATE="bindd = "
+readonly EMPTY_BIND_TEMPLATE="hl.bind(\"MOD + KEY\", hl.dsp.dispatch(\"ARG\"), { description = \"DESC\" })"
# --- Dispatchers (populated at runtime if possible, otherwise fallback) ---
declare -a KNOWN_DISPATCHERS=(
@@ -165,11 +165,11 @@ _is_comment_or_blank() {
}
_is_bind_directive() {
- [[ "$1" =~ ^[[:space:]]*(bind[a-z]*|unbind)[[:space:]]*= ]]
+ [[ "$1" =~ ^[[:space:]]*hl\.(bind|unbind)[[:space:]]*\( ]]
}
_is_unbind() {
- [[ "$1" =~ ^[[:space:]]*unbind[[:space:]]*= ]]
+ [[ "$1" =~ ^[[:space:]]*hl\.unbind[[:space:]]*\( ]]
}
_is_submap_directive() {
@@ -194,14 +194,20 @@ _extract_mods_key() {
local -n _emk_mods="$1"
local -n _emk_key="$2"
local content="$3"
-
- _emk_mods="${content%%,*}"
- local remainder="${content#*,}"
-
- if [[ "$remainder" == "$content" ]]; then
- _emk_key=""
+
+ # content is everything after hl.bind( or hl.unbind(
+ local binding="${content%%,*}"
+ binding="${binding#*\"}"
+ binding="${binding%%\"*}"
+
+ if [[ "$binding" == *"+"* ]]; then
+ _emk_mods="${binding%%+*}"
+ _emk_key="${binding##*+}"
+ _emk_mods="${_emk_mods%%[[:space:]]}"
+ _emk_key="${_emk_key##[[:space:]]}"
else
- _emk_key="${remainder%%,*}"
+ _emk_mods=""
+ _emk_key="$binding"
fi
_trim _emk_mods "$_emk_mods"
@@ -237,14 +243,9 @@ _extract_field() {
_extract_dispatcher() {
local bind_type="$1"
local content="$2"
- local flags="${bind_type#bind}"
-
- local dispatcher_idx=2
- if [[ "$flags" == *d* ]]; then
- dispatcher_idx=3
- fi
-
- _extract_field "$content" "$dispatcher_idx"
+ local disp="${content#*hl.dsp.}"
+ disp="${disp%%(*}"
+ printf "%s" "$disp"
}
_validate_dispatcher() {
@@ -859,7 +860,7 @@ main() {
if [[ "$origin" == "CUST" ]]; then
printf ' Remove custom entry from %s\n' "$CUSTOM_CONF"
else
- printf ' Append "unbind = %s, %s" to %s\n' "$del_mods" "$del_key" "$CUSTOM_CONF"
+ printf ' Append "hl.unbind(\"%s + %s\")" to %s\n' "$del_mods" "$del_key" "$CUSTOM_CONF"
fi
read -r -p "Press Enter to continue..."
continue
@@ -909,7 +910,7 @@ main() {
if [[ -n "$bind_submap" ]]; then
printf 'submap = %s\n' "$bind_submap"
fi
- printf 'unbind = %s, %s\n' "$del_mods" "$del_key"
+ printf 'hl.unbind(\"%s + %s\")\n' "$del_mods" "$del_key"
if [[ -n "$bind_submap" ]]; then
printf 'submap = reset\n'
fi
@@ -1129,7 +1130,7 @@ main() {
if _exists_in_source "$orig_mods" "$orig_key" "$bind_submap"; then
local nk_m="$orig_mods" nk_k="$orig_key"
_normalize_bind_parts nk_m nk_k
- unbind_map["${nk_m}|${nk_k}"]="unbind = ${orig_mods}, ${orig_key}"
+ unbind_map["${nk_m}|${nk_k}"]="hl.unbind(\"${orig_mods} + ${orig_key}\")"
fi
fi
@@ -1137,7 +1138,7 @@ main() {
if _exists_in_source "$new_mods" "$new_key" "$bind_submap"; then
local nk_m="$new_mods" nk_k="$new_key"
_normalize_bind_parts nk_m nk_k
- unbind_map["${nk_m}|${nk_k}"]="unbind = ${new_mods}, ${new_key}"
+ unbind_map["${nk_m}|${nk_k}"]="hl.unbind(\"${new_mods} + ${new_key}\")"
fi
# Build newline-delimited string for display
diff --git a/user_scripts/hypr/dusky_monitor.sh b/user_scripts/hypr/dusky_monitor.sh
index 2ba4f750..115f4adb 100755
--- a/user_scripts/hypr/dusky_monitor.sh
+++ b/user_scripts/hypr/dusky_monitor.sh
@@ -26,7 +26,7 @@ export LC_NUMERIC=C
declare -r APP_TITLE="DUSKY MONITOR WIZARD v4.0.0"
declare -r APP_SUBTITLE="Hyprland Edition"
-declare -r TARGET_CONFIG="${HOME}/.config/hypr/edit_here/source/monitors.conf"
+declare -r TARGET_CONFIG="${HOME}/.config/hypr/edit_here/source/monitors.lua"
declare -r BACKUP_DIR="/tmp/dusky_backups"
declare -r DEBUG_LOG="/tmp/dusky_debug.log"
@@ -225,6 +225,9 @@ refresh_hardware() {
local vfr_status
vfr_status=$(hyprctl getoption debug:vfr -j 2>/dev/null | jq -r '.int' 2>/dev/null) || vfr_status="1"
+ if [[ "$vfr_status" == "null" || -z "$vfr_status" || ! "$vfr_status" =~ ^[0-9]+$ ]]; then
+ vfr_status="1"
+ fi
GLB_VFR=$vfr_status
local json
@@ -238,7 +241,7 @@ refresh_hardware() {
extracted=$(printf '%s' "$json" | jq -r '
.[] | [
.name,
- .description,
+ (.description | if . == "" then "Unknown" else . end),
(.disabled // false | tostring),
(.width | tostring),
(.height | tostring),
@@ -247,7 +250,7 @@ refresh_hardware() {
(.transform | tostring),
(.x | tostring),
(.y | tostring),
- ((.availableModes // []) | join(" ")),
+ ((.availableModes // []) | if length == 0 then "-" else join(" ") end),
(.vrr // false | tostring),
(.currentFormat // "XRGB8888")
] | @tsv
@@ -356,26 +359,22 @@ save_config() {
timestamp=$(date +%Y%m%d_%H%M%S)
if [[ -f "$TARGET_CONFIG" ]]; then
- cp -- "$TARGET_CONFIG" "${BACKUP_DIR}/monitors_${timestamp}.conf" 2>/dev/null || true
+ cp -- "$TARGET_CONFIG" "${BACKUP_DIR}/monitors_${timestamp}.lua" 2>/dev/null || true
fi
- _SAVE_TMPFILE=$(mktemp "${config_dir}/monitors.conf.XXXXXX")
-
- local batch_cmd=""
+ _SAVE_TMPFILE=$(mktemp "${config_dir}/monitors.lua.XXXXXX")
{
- printf '# Generated by Dusky Monitor Wizard on %s\n' "$timestamp"
- printf '\n# Global Settings\n'
+ printf '-- Generated by Dusky Monitor Wizard on %s\n' "$timestamp"
+ printf '\n-- Global Settings\n'
if (( GLB_VFR == 1 )); then
- printf 'debug {\n vfr = true\n}\n'
- batch_cmd+="keyword debug:vfr 1 ; "
+ printf 'hl.config({ debug = { vfr = true } })\n'
else
- printf 'debug {\n vfr = false\n}\n'
- batch_cmd+="keyword debug:vfr 0 ; "
+ printf 'hl.config({ debug = { vfr = false } })\n'
fi
- printf '\n# Monitor Rules\n'
+ printf '\n-- Monitor Rules\n'
local name
for name in "${MON_LIST[@]}"; do
local identifier="$name"
@@ -384,8 +383,7 @@ save_config() {
fi
if [[ "${MON_ENABLED["$name"]}" == "false" ]]; then
- printf 'monitor = %s, disable\n' "$identifier"
- batch_cmd+="keyword monitor ${identifier},disable ; "
+ printf 'hl.monitor({ output = "%s", disabled = true })\n' "$identifier"
continue
fi
@@ -398,15 +396,13 @@ save_config() {
local bit=${MON_BITDEPTH["$name"]}
local mirror=${MON_MIRROR["$name"]}
- local rule_args="${identifier}, ${res}, ${x}x${y}, ${scale}"
- (( transform != 0 )) && rule_args+=", transform, ${transform}"
- [[ -n "$mirror" ]] && rule_args+=", mirror, ${mirror}"
- (( bit == 10 )) && rule_args+=", bitdepth, 10"
- (( vrr > 0 )) && rule_args+=", vrr, ${vrr}"
-
- printf 'monitor = %s\n' "$rule_args"
- local clean_args="${rule_args//, /,}"
- batch_cmd+="keyword monitor ${clean_args} ; "
+ printf 'hl.monitor({ output = "%s", mode = "%s", position = "%sx%s", scale = %s' \
+ "$identifier" "$res" "$x" "$y" "$scale"
+ (( transform != 0 )) && printf ', transform = %d' "$transform"
+ [[ -n "$mirror" ]] && printf ', mirror = "%s"' "$mirror"
+ (( bit == 10 )) && printf ', bitdepth = 10'
+ (( vrr > 0 )) && printf ', vrr = %d' "$vrr"
+ printf ' })\n'
done
} > "$_SAVE_TMPFILE"
@@ -421,9 +417,7 @@ save_config() {
# CRITICAL FIX: Use cat > target to preserve symlinks/inodes (Pattern from Template)
if cat "$_SAVE_TMPFILE" > "$TARGET_CONFIG"; then
printf '\n%sApplying settings...%s\n' "$C_CYAN" "$C_RESET"
- if [[ -n "$batch_cmd" ]]; then
- hyprctl --batch "$batch_cmd" >/dev/null 2>&1 || true
- fi
+ hyprctl reload >/dev/null 2>&1 || true
log_debug "Saved and applied."
rm -f -- "$_SAVE_TMPFILE" 2>/dev/null || :
_SAVE_TMPFILE=""
diff --git a/user_scripts/hypr/dusky_window_rules.sh b/user_scripts/hypr/dusky_window_rules.sh
index c1a67a03..c00987c5 100755
--- a/user_scripts/hypr/dusky_window_rules.sh
+++ b/user_scripts/hypr/dusky_window_rules.sh
@@ -10,7 +10,7 @@ shopt -s extglob
export LC_NUMERIC=C
# --- Configuration ---
-declare -r TARGET_FILE="${HOME}/.config/hypr/edit_here/source/window_rules.conf"
+declare -r TARGET_FILE="${HOME}/.config/hypr/edit_here/source/window_rules.lua"
declare -r APP_TITLE="Dusky Window Rule Generator"
declare -r APP_VERSION="v4.5 (Engine v3.9.1)"
@@ -165,43 +165,42 @@ scan_windows() {
safe_title=$(escape_regex "$title")
safe_name=$(sanitize_name "$initialClass")
- # Build Block
- rule_block="${C_DIVIDER}# -----------------------------------------------------${C_RESET}"$'\n'
- rule_block+="# ${title}"$'\n'
-
- rule_block+="${C_GREEN}windowrule {${C_RESET}"$'\n'
- rule_block+=" name = ${safe_name}"$'\n'
- rule_block+=" match:class = ^(${safe_class})$"$'\n'
- rule_block+=" ${C_COMMENT}# match:title = ^(${safe_title})\$${C_RESET}"$'\n'
-
- rule_block+=" float = on"$'\n'
- rule_block+=" ${C_COMMENT}# pin = on${C_RESET}"$'\n'
-
- rule_block+=" size = ${w_w} ${w_h}"$'\n'
- rule_block+=" ${C_COMMENT}# size = (monitor_w*${r_w}) (monitor_h*${r_h})${C_RESET}"$'\n'
-
- rule_block+=" move = ${local_x} ${local_y}"$'\n'
- rule_block+=" ${C_COMMENT}# move = (monitor_w*${r_x}) (monitor_h*${r_y})${C_RESET}"$'\n'
- rule_block+=" ${C_COMMENT}# move = (monitor_w-window_w-20) (monitor_h-window_h-20)${C_RESET}"$'\n'
- rule_block+=" ${C_COMMENT}# center = on${C_RESET}"$'\n'
-
- rule_block+=$'\n'" ${C_COMMENT}# --- Visuals & Effects ---${C_RESET}"$'\n'
- rule_block+=" ${C_COMMENT}# opacity [active] [inactive]${C_RESET}"$'\n'
- rule_block+=" ${C_COMMENT}# opacity = 0.9 0.9${C_RESET}"$'\n'
- rule_block+=" ${C_COMMENT}# animation = popin${C_RESET}"$'\n'
- rule_block+=" ${C_COMMENT}# rounding = 10${C_RESET}"$'\n'
- rule_block+=" ${C_COMMENT}# border_color = rgb(ff0000)${C_RESET}"$'\n'
- rule_block+=" ${C_COMMENT}# no_blur = on${C_RESET}"$'\n'
- rule_block+=" ${C_COMMENT}# no_shadow = on${C_RESET}"$'\n'
- rule_block+=" ${C_COMMENT}# no_dim = on${C_RESET}"$'\n'
- rule_block+=" ${C_COMMENT}# opaque = on${C_RESET}"$'\n'
- rule_block+=" ${C_COMMENT}# dim_around = on${C_RESET}"$'\n'
-
- rule_block+=$'\n'" ${C_COMMENT}# --- Placement ---${C_RESET}"$'\n'
- rule_block+=" ${C_COMMENT}# workspace = 2${C_RESET}"$'\n'
- rule_block+=" ${C_COMMENT}# monitor = DP-1${C_RESET}"$'\n'
-
- rule_block+="${C_GREEN}}${C_RESET}"$'\n'
+ # Build Block (Lua format)
+ rule_block="${C_DIVIDER}-- ---------------------------------------------------${C_RESET}"$'\n'
+ rule_block+="-- ${title}"$'\n'
+
+ rule_block+="${C_GREEN}hl.window_rule({${C_RESET}"$'\n'
+ rule_block+=" name = \"${safe_name}\","$'\n'
+ rule_block+=" match = { class = \"^(${safe_class})\$\" },"$'\n'
+ rule_block+=" ${C_COMMENT}-- match = { title = \"^(${safe_title})\$\" },${C_RESET}"$'\n'
+
+ rule_block+=" float = true,"$'\n'
+ rule_block+=" ${C_COMMENT}-- pin = true,${C_RESET}"$'\n'
+
+ rule_block+=" size = \"${w_w} ${w_h}\","$'\n'
+ rule_block+=" ${C_COMMENT}-- size = \"(monitor_w*${r_w}) (monitor_h*${r_h})\",${C_RESET}"$'\n'
+
+ rule_block+=" move = \"${local_x} ${local_y}\","$'\n'
+ rule_block+=" ${C_COMMENT}-- move = \"(monitor_w*${r_x}) (monitor_h*${r_y})\",${C_RESET}"$'\n'
+ rule_block+=" ${C_COMMENT}-- move = \"(monitor_w-window_w-20) (monitor_h-window_h-20)\",${C_RESET}"$'\n'
+ rule_block+=" ${C_COMMENT}-- center = true,${C_RESET}"$'\n'
+
+ rule_block+=$'\n'" ${C_COMMENT}-- --- Visuals & Effects ---${C_RESET}"$'\n'
+ rule_block+=" ${C_COMMENT}-- opacity = \"0.9 override 0.9 override\",${C_RESET}"$'\n'
+ rule_block+=" ${C_COMMENT}-- anim_style = \"popin\",${C_RESET}"$'\n'
+ rule_block+=" ${C_COMMENT}-- rounding = 10,${C_RESET}"$'\n'
+ rule_block+=" ${C_COMMENT}-- border_color = \"rgb(ff0000)\",${C_RESET}"$'\n'
+ rule_block+=" ${C_COMMENT}-- no_blur = true,${C_RESET}"$'\n'
+ rule_block+=" ${C_COMMENT}-- no_shadow = true,${C_RESET}"$'\n'
+ rule_block+=" ${C_COMMENT}-- no_dim = true,${C_RESET}"$'\n'
+ rule_block+=" ${C_COMMENT}-- opaque = true,${C_RESET}"$'\n'
+ rule_block+=" ${C_COMMENT}-- dim_around = true,${C_RESET}"$'\n'
+
+ rule_block+=$'\n'" ${C_COMMENT}-- --- Placement ---${C_RESET}"$'\n'
+ rule_block+=" ${C_COMMENT}-- workspace = 2,${C_RESET}"$'\n'
+ rule_block+=" ${C_COMMENT}-- monitor = \"DP-1\",${C_RESET}"$'\n'
+
+ rule_block+="${C_GREEN}})"$'\n'"${C_RESET}"
WINDOW_TITLES+=("${title:0:60}")
WINDOW_CLASSES+=("$initialClass")
diff --git a/user_scripts/hypr/dusky_workspace_manager.sh b/user_scripts/hypr/dusky_workspace_manager.sh
index 60b52aae..c6510db5 100755
--- a/user_scripts/hypr/dusky_workspace_manager.sh
+++ b/user_scripts/hypr/dusky_workspace_manager.sh
@@ -20,7 +20,7 @@ shopt -s extglob
declare -r HYPR_DIR="${HOME}/.config/hypr"
declare -r EDIT_DIR="${HYPR_DIR}/edit_here/source"
-declare -r CONFIG_FILE="${EDIT_DIR}/workspace_rules.conf"
+declare -r CONFIG_FILE="${EDIT_DIR}/workspace_rules.lua"
declare -r APP_TITLE="Dusky Workspace Manager"
declare -r APP_VERSION="v4.4.1 (Production)"
@@ -43,16 +43,16 @@ register_items() {
local i
for i in {1..10}; do
register 0 "Workspace $i" "ws_${i}|menu||||" ""
- register_child "ws_${i}" "Layout" "\$ws${i}_layout|cycle||dwindle,master,monocle,scrolling||" "dwindle"
- register_child "ws_${i}" "Persistent" "\$ws${i}_persistent|bool||||" "false"
- register_child "ws_${i}" "Master Orient" "\$ws${i}_master_orient|cycle||left,right,top,bottom,center||" "left"
- register_child "ws_${i}" "Scroll Dir" "\$ws${i}_scroll_dir|cycle||right,left,up,down||" "right"
+ register_child "ws_${i}" "Layout" "ws${i}_layout|cycle||dwindle,master,monocle,scrolling||" "dwindle"
+ register_child "ws_${i}" "Persistent" "ws${i}_persistent|bool||||" "false"
+ register_child "ws_${i}" "Master Orient" "ws${i}_master_orient|cycle||left,right,top,bottom,center||" "left"
+ register_child "ws_${i}" "Scroll Dir" "ws${i}_scroll_dir|cycle||right,left,up,down||" "right"
done
# Tab 1: Global Rules & Temporary Overrides
- register 1 "Temp Global Override Layout" '$ephemeral_layout|cycle||dwindle,master,monocle,scrolling||' "monocle"
- register 1 "Temp Global Override State" '$ephemeral_enabled|bool||||' "false"
- register 1 "Fallback Layout (WS 11+)" '$global_layout|cycle||dwindle,master,monocle,scrolling||' "dwindle"
+ register 1 "Temp Global Override Layout" 'ephemeral_layout|cycle||dwindle,master,monocle,scrolling||' "monocle"
+ register 1 "Temp Global Override State" 'ephemeral_enabled|bool||||' "false"
+ register 1 "Fallback Layout (WS 11+)" 'global_layout|cycle||dwindle,master,monocle,scrolling||' "dwindle"
}
# --- CHANGE 1 of 4: post_write_action sets flag instead of blocking ---
@@ -66,12 +66,12 @@ _flush_reload() {
_NEEDS_RELOAD=0
if command -v hyprctl &>/dev/null; then
- local eph_val="${CONFIG_CACHE['$ephemeral_enabled|']:-false}"
- local eph_layout="${CONFIG_CACHE['$ephemeral_layout|']:-dwindle}"
+ local eph_val="${CONFIG_CACHE['ephemeral_enabled|']:-false}"
+ local eph_layout="${CONFIG_CACHE['ephemeral_layout|']:-dwindle}"
(
hyprctl reload || true
if [[ "$eph_val" == "true" ]]; then
- hyprctl keyword workspace "r[1-99], layout:$eph_layout" || true
+ hyprctl eval "hl.workspace_rule({workspace='r[1-99]',layout='${eph_layout}'})" || true
fi
) /dev/null &
disown 2>/dev/null || :
@@ -152,37 +152,55 @@ log_err() {
printf '%s[ERROR]%s %s\n' "$C_RED" "$C_RESET" "$1" >&2
}
+_generate_workspace_config() {
+ local i
+ {
+ printf '-- ============================================================================\n'
+ printf '-- USER CONFIGURATION: workspace_rules.lua\n'
+ printf '-- Managed by Dusky TUI - Granular Matrix v4.4.1\n'
+ printf '-- WARNING: Edit via the TUI. Manual edits may be overwritten on format change.\n'
+ printf '-- ============================================================================\n\n'
+
+ printf '-- Global layout for workspaces 11+\n'
+ printf 'global_layout = "dwindle"\n\n'
+
+ printf '-- Ephemeral global override (applied at runtime, not persisted across reboot)\n'
+ printf 'ephemeral_layout = "monocle"\n'
+ printf 'ephemeral_enabled = false\n\n'
+
+ printf '-- Per-workspace settings (workspaces 1-10)\n'
+ for i in {1..10}; do
+ printf 'ws%d_layout = "dwindle"\n' "$i"
+ printf 'ws%d_persistent = false\n' "$i"
+ printf 'ws%d_master_orient = "left"\n' "$i"
+ printf 'ws%d_scroll_dir = "right"\n' "$i"
+ done
+ printf '\n'
+
+ printf '-- Apply global fallback rule\n'
+ printf 'hl.workspace_rule({ workspace = "r[11-99]", layout = global_layout })\n\n'
+
+ printf '-- Apply per-workspace rules\n'
+ printf 'for i, w in ipairs({\n'
+ for i in {1..10}; do
+ printf ' { layout = ws%d_layout, persistent = ws%d_persistent, layout_opts = { orientation = ws%d_master_orient, direction = ws%d_scroll_dir } },\n' \
+ "$i" "$i" "$i" "$i"
+ done
+ printf '}) do\n'
+ printf ' hl.workspace_rule({ workspace = tostring(i), layout = w.layout, persistent = w.persistent, layout_opts = w.layout_opts })\n'
+ printf 'end\n'
+ } > "${CONFIG_FILE}"
+}
+
ensure_config_exists() {
if [[ ! -d "${EDIT_DIR}" ]]; then
mkdir -p -- "${EDIT_DIR}"
fi
-
- # Auto-heal: Rebuild template if missing or empty
- if [[ ! -f "${CONFIG_FILE}" || ! -s "${CONFIG_FILE}" ]]; then
- {
- printf '# ==============================================================================\n'
- printf '# USER CONFIGURATION: workspace_rules.conf\n'
- printf '# Managed by Dusky TUI - Granular Matrix v4.4.1\n'
- printf '# ==============================================================================\n\n'
-
- printf '# --- Global Rules ---\n'
- printf '$global_layout = dwindle\n'
- printf 'workspace = r[11-99], layout:$global_layout\n\n'
-
- printf '# --- Ephemeral Global Override (Resets on reboot) ---\n'
- printf '$ephemeral_layout = monocle\n'
- printf '$ephemeral_enabled = false\n\n'
-
- printf '# --- Individual Workspaces (1-10) ---\n'
- local i
- for i in {1..10}; do
- printf '$ws%d_layout = dwindle\n' "$i"
- printf '$ws%d_persistent = false\n' "$i"
- printf '$ws%d_master_orient = left\n' "$i"
- printf '$ws%d_scroll_dir = right\n' "$i"
- printf 'workspace = %d, layout:$ws%d_layout, persistent:$ws%d_persistent, layoutopt:orientation:$ws%d_master_orient, layoutopt:direction:$ws%d_scroll_dir\n\n' "$i" "$i" "$i" "$i" "$i"
- done
- } > "${CONFIG_FILE}"
+
+ # Rebuild if missing, empty, or not in TUI-managed variable format (e.g. old conf or array format)
+ if [[ ! -f "${CONFIG_FILE}" || ! -s "${CONFIG_FILE}" ]] || \
+ ! grep -qF 'ws1_layout' "${CONFIG_FILE}" 2>/dev/null; then
+ _generate_workspace_config
fi
}
@@ -267,16 +285,16 @@ populate_config_cache() {
fi
done < <(LC_ALL=C awk '
BEGIN { depth = 0 }
- /^[[:space:]]*#/ { next }
+ /^[[:space:]]*--/ { next }
{
line = $0
clean = line
- sub(/[[:space:]]+#.*$/, "", clean)
+ sub(/[[:space:]]+--.*$/, "", clean)
tmpline = clean
- while (match(tmpline, /[a-zA-Z0-9_.:-]+[[:space:]]*\{/)) {
+ while (match(tmpline, /[a-zA-Z0-9_.:-]+[[:space:]]*(=[[:space:]]*)?\{/)) {
block_str = substr(tmpline, RSTART, RLENGTH)
- sub(/[[:space:]]*\{/, "", block_str)
+ sub(/[[:space:]]*(=[[:space:]]*)?\{/, "", block_str)
depth++
block_stack[depth] = block_str
tmpline = substr(tmpline, RSTART + RLENGTH)
@@ -288,8 +306,11 @@ populate_config_cache() {
val = substr(clean, eq_pos + 1)
gsub(/^[[:space:]]+|[[:space:]]+$/, "", key)
gsub(/^[[:space:]]+|[[:space:]]+$/, "", val)
- sub(/[[:space:]]+#.*$/, "", val)
+ sub(/[[:space:]]+--.*$/, "", val)
gsub(/^[[:space:]]+|[[:space:]]+$/, "", val)
+ # Strip trailing comma and surrounding quotes (Lua syntax)
+ sub(/,$/, "", val)
+ if (val ~ /^".*"$/) val = substr(val, 2, length(val) - 2)
if (key != "") {
current_block = (depth > 0) ? block_stack[depth] : ""
print key "|" current_block "=" val
@@ -331,13 +352,13 @@ write_value_to_file() {
{
line = $0
clean = line
- sub(/^[[:space:]]*#.*/, "", clean)
- sub(/[[:space:]]+#.*$/, "", clean)
+ sub(/^[[:space:]]*--.*/, "", clean)
+ sub(/[[:space:]]+--.*$/, "", clean)
tmpline = clean
- while (match(tmpline, /[a-zA-Z0-9_.:-]+[[:space:]]*\{/)) {
+ while (match(tmpline, /[a-zA-Z0-9_.:-]+[[:space:]]*(=[[:space:]]*)?\{/)) {
block_str = substr(tmpline, RSTART, RLENGTH)
- sub(/[[:space:]]*\{/, "", block_str)
+ sub(/[[:space:]]*(=[[:space:]]*)?\{/, "", block_str)
depth++
block_stack[depth] = block_str
if (do_block && block_str == target_block && !in_target) {
@@ -364,15 +385,25 @@ write_value_to_file() {
}
if (do_replace) {
- match(line, /^[[:space:]]*/)
- leading = substr(line, RSTART, RLENGTH)
eq = index(line, "=")
before_eq = substr(line, 1, eq)
rest = substr(line, eq + 1)
match(rest, /^[[:space:]]*/)
space_after = substr(rest, RSTART, RLENGTH)
- print before_eq space_after new_value
+ # Detect trailing comma and surrounding quotes from the original value
+ old_val = substr(rest, RSTART + RLENGTH)
+ sub(/[[:space:]]+--.*$/, "", old_val)
+ gsub(/^[[:space:]]+|[[:space:]]+$/, "", old_val)
+ was_trailing = (old_val ~ /,$/) ? 1 : 0
+ sub(/,$/, "", old_val)
+ was_quoted = (old_val ~ /^".*"$/) ? 1 : 0
+
+ out_val = new_value
+ if (was_quoted && !(new_value ~ /^".*"$/)) out_val = "\"" new_value "\""
+ trailing = was_trailing ? "," : ""
+
+ print before_eq space_after out_val trailing
replaced = 1
} else {
print line
diff --git a/user_scripts/hypr/hypr_blur_opacity_shadow_toggle.sh b/user_scripts/hypr/hypr_blur_opacity_shadow_toggle.sh
index dcda8ad1..ce241eb0 100755
--- a/user_scripts/hypr/hypr_blur_opacity_shadow_toggle.sh
+++ b/user_scripts/hypr/hypr_blur_opacity_shadow_toggle.sh
@@ -142,9 +142,9 @@ get_current_blur_state() {
[[ -L "${CONFIG_FILE}" ]] && actual_config=$(realpath -m "${CONFIG_FILE}")
state=$(awk '
- /^[[:space:]]*blur[[:space:]]*\{/ { in_block = 1; next }
- in_block && /^[[:space:]]*enabled[[:space:]]*=[[:space:]]*true/ { found = "on" }
- in_block && /^[[:space:]]*enabled[[:space:]]*=[[:space:]]*false/ { found = "off" }
+ /^[[:space:]]*blur[[:space:]]*=[[:space:]]*\{/ { in_block = 1; next }
+ in_block && /^[[:space:]]*enabled[[:space:]]*=[[:space:]]*true,?/ { found = "on" }
+ in_block && /^[[:space:]]*enabled[[:space:]]*=[[:space:]]*false,?/ { found = "off" }
in_block && /\}/ { in_block = 0 }
END { print (found ? found : "off") }
' "$actual_config" 2>/dev/null) || state="off"
@@ -281,24 +281,8 @@ fi
# --- Apply Changes at Runtime ---
-declare -a HYPR_CMDS=(
- "decoration:blur:enabled ${NEW_ENABLED}"
- "decoration:shadow:enabled ${NEW_ENABLED}"
- "decoration:active_opacity ${NEW_ACTIVE}"
- "decoration:inactive_opacity ${NEW_INACTIVE}"
-)
-
-hypr_errors=0
-for cmd in "${HYPR_CMDS[@]}"; do
- # shellcheck disable=SC2086
- if ! hyprctl keyword $cmd &>/dev/null; then
- ((hypr_errors++)) || true
- fi
-done
-
-if ((hypr_errors > 0)); then
- printf 'Warning: %d hyprctl command(s) failed. Is Hyprland running?\n' "$hypr_errors" >&2
-fi
+hyprctl eval "hl.config({decoration={blur={enabled=${NEW_ENABLED}},shadow={enabled=${NEW_ENABLED}},active_opacity=${NEW_ACTIVE},inactive_opacity=${NEW_INACTIVE}}})" &>/dev/null \
+ || printf 'Warning: hl.config() failed. Is Hyprland running?\n' >&2
# Reload dynamic daemons
if command -v makoctl &>/dev/null; then
@@ -315,3 +299,6 @@ fi
notify "$NOTIFY_MSG"
exit 0
+
+
+exit 0
diff --git a/user_scripts/hypr/hypr_lua_proxy.py b/user_scripts/hypr/hypr_lua_proxy.py
new file mode 100644
index 00000000..735dcda1
--- /dev/null
+++ b/user_scripts/hypr/hypr_lua_proxy.py
@@ -0,0 +1,138 @@
+#!/usr/bin/env python3
+"""
+hypr_lua_proxy.py — Hyprland IPC command-socket proxy for Lua config mode.
+
+Waybar (and other tools) send old-style dispatch strings like:
+ dispatch workspace 2
+ dispatch togglespecialworkspace magic
+
+In Lua config mode, Hyprland evaluates the body as Lua, so those fail.
+This proxy translates dispatches into valid Lua expressions before forwarding.
+
+The event socket (.socket2.sock) is handled separately by socat in
+waybar_autostart.sh — pure pass-through needs no Python overhead.
+
+Usage:
+ Launched by waybar_autostart.sh which sets HYPRLAND_INSTANCE_SIGNATURE
+ to point waybar at the proxy directory instead of the real socket.
+"""
+
+import asyncio
+import os
+import re
+import sys
+from contextlib import suppress
+
+# Real Hyprland socket directory
+REAL_SIG = os.environ["HYPRLAND_INSTANCE_SIGNATURE"]
+RUNTIME = os.environ.get("XDG_RUNTIME_DIR", f"/run/user/{os.getuid()}")
+REAL_DIR = f"{RUNTIME}/hypr/{REAL_SIG}"
+
+# Proxy socket directory (predictable name, not session-specific)
+PROXY_DIR = f"{RUNTIME}/hypr/lua_proxy"
+
+
+# ---------------------------------------------------------------------------
+# Dispatch translation table
+# ---------------------------------------------------------------------------
+
+def translate(raw: str) -> str:
+ """Translate one old-style dispatch string to Lua, or return unchanged."""
+ s = raw.strip()
+
+ # dispatch workspace
+ m = re.match(r"^dispatch\s+workspace\s+(.+)$", s)
+ if m:
+ t = m.group(1).strip()
+ if re.match(r"^-?\d+$", t):
+ return f"dispatch hl.dsp.focus({{workspace={t}}})"
+ return f'dispatch hl.dsp.focus({{workspace="{t}"}})'
+
+ # dispatch movetoworkspace
+ m = re.match(r"^dispatch\s+movetoworkspace\s+(.+)$", s)
+ if m:
+ t = m.group(1).strip()
+ if re.match(r"^-?\d+$", t):
+ return f"dispatch hl.dsp.window.move({{workspace={t}}})"
+ return f'dispatch hl.dsp.window.move({{workspace="{t}"}})'
+
+ # dispatch movetoworkspacesilent
+ m = re.match(r"^dispatch\s+movetoworkspacesilent\s+(.+)$", s)
+ if m:
+ t = m.group(1).strip()
+ if re.match(r"^-?\d+$", t):
+ return f"dispatch hl.dsp.window.move({{workspace={t}, silent=true}})"
+ return f'dispatch hl.dsp.window.move({{workspace="{t}", silent=true}})'
+
+ # dispatch togglespecialworkspace [name]
+ m = re.match(r"^dispatch\s+togglespecialworkspace\s*(.*)$", s)
+ if m:
+ name = m.group(1).strip()
+ if name:
+ return f'dispatch hl.dsp.workspace.toggle_special("{name}")'
+ return "dispatch hl.dsp.workspace.toggle_special()"
+
+ return raw # pass through unchanged
+
+
+# ---------------------------------------------------------------------------
+# Command socket proxy (.socket.sock) — request/response, translates dispatches
+# ---------------------------------------------------------------------------
+
+async def handle_command(
+ reader: asyncio.StreamReader, writer: asyncio.StreamWriter
+) -> None:
+ try:
+ data = await asyncio.wait_for(reader.read(4096), timeout=2.0)
+
+ cmd = data.decode("utf-8", errors="replace")
+ out = translate(cmd)
+
+ real_reader, real_writer = await asyncio.open_unix_connection(
+ f"{REAL_DIR}/.socket.sock"
+ )
+ try:
+ real_writer.write(out.encode("utf-8"))
+ real_writer.write_eof()
+ await real_writer.drain()
+
+ try:
+ resp = await asyncio.wait_for(real_reader.read(65536), timeout=0.5)
+ except asyncio.TimeoutError:
+ resp = b""
+ finally:
+ real_writer.close()
+ with suppress(Exception):
+ await real_writer.wait_closed()
+
+ writer.write(resp)
+ await writer.drain()
+ except Exception as e:
+ print(f"[proxy] command error: {e}", file=sys.stderr)
+ finally:
+ with suppress(Exception):
+ writer.close()
+ with suppress(Exception):
+ await writer.wait_closed()
+
+
+# ---------------------------------------------------------------------------
+# Entry point — command socket only; event socket handled by socat
+# ---------------------------------------------------------------------------
+
+async def main() -> None:
+ os.makedirs(PROXY_DIR, exist_ok=True)
+
+ sock_path = f"{PROXY_DIR}/.socket.sock"
+ with suppress(FileNotFoundError):
+ os.unlink(sock_path)
+
+ server = await asyncio.start_unix_server(handle_command, sock_path)
+ print(f"[proxy] command socket: {sock_path}", file=sys.stderr)
+
+ async with server:
+ await server.serve_forever()
+
+
+if __name__ == "__main__":
+ asyncio.run(main())
diff --git a/user_scripts/hypr/monitor/adjust_scale.sh b/user_scripts/hypr/monitor/adjust_scale.sh
index 985c9718..40e3de3b 100755
--- a/user_scripts/hypr/monitor/adjust_scale.sh
+++ b/user_scripts/hypr/monitor/adjust_scale.sh
@@ -64,12 +64,12 @@ trim() {
# --- Initialization ---
init_config_file() {
- if [[ -f "${CONFIG_DIR}/monitors.conf" ]]; then
- CONFIG_FILE="${CONFIG_DIR}/monitors.conf"
- log_debug "Selected config: monitors.conf"
+ if [[ -f "${CONFIG_DIR}/monitors.lua" ]]; then
+ CONFIG_FILE="${CONFIG_DIR}/monitors.lua"
+ log_debug "Selected config: monitors.lua"
else
- CONFIG_FILE="${CONFIG_DIR}/monitors.conf"
- log_debug "Creating new config: monitors.conf"
+ CONFIG_FILE="${CONFIG_DIR}/monitors.lua"
+ log_debug "Creating new config: monitors.lua"
mkdir -p -- "${CONFIG_DIR}"
: > "$CONFIG_FILE"
fi
diff --git a/user_scripts/hypr/monitor/dusky_monitor_old.sh b/user_scripts/hypr/monitor/dusky_monitor_old.sh
index beeed881..4c7dc977 100755
--- a/user_scripts/hypr/monitor/dusky_monitor_old.sh
+++ b/user_scripts/hypr/monitor/dusky_monitor_old.sh
@@ -21,8 +21,8 @@ trap cleanup EXIT
readonly CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/edit_here"
readonly BACKUP_DIR="/tmp/hypr-wizard-backups"
-CONFIG_FILE="${CONFIG_DIR}/monitors.conf"
-[[ -f "${CONFIG_DIR}/source/monitors.conf" ]] && CONFIG_FILE="${CONFIG_DIR}/source/monitors.conf"
+CONFIG_FILE="${CONFIG_DIR}/monitors.lua"
+[[ -f "${CONFIG_DIR}/source/monitors.lua" ]] && CONFIG_FILE="${CONFIG_DIR}/source/monitors.lua"
# ANSI color codes
readonly C_R=$'\e[0m' C_RED=$'\e[31m' C_GRN=$'\e[32m' C_YLW=$'\e[33m'
diff --git a/user_scripts/hypr/monitor/dusky_monitor_relatively_old.sh b/user_scripts/hypr/monitor/dusky_monitor_relatively_old.sh
index b04b3e9e..9771f0bc 100755
--- a/user_scripts/hypr/monitor/dusky_monitor_relatively_old.sh
+++ b/user_scripts/hypr/monitor/dusky_monitor_relatively_old.sh
@@ -12,7 +12,7 @@ readonly VERSION="7.4.5"
readonly CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/edit_here"
# Backups stored in volatile /tmp (cleared on reboot)
readonly BACKUP_DIR="/tmp/hypr-wizard-backups"
-readonly CONFIG_FILE="${CONFIG_DIR}/source/monitors.conf"
+readonly CONFIG_FILE="${CONFIG_DIR}/source/monitors.lua"
readonly MAX_BACKUPS=20
# ANSI Colors & Styling
diff --git a/user_scripts/hypr/multi_monitor_workspace.sh b/user_scripts/hypr/multi_monitor_workspace.sh
index ad89988e..86df9b0e 100755
--- a/user_scripts/hypr/multi_monitor_workspace.sh
+++ b/user_scripts/hypr/multi_monitor_workspace.sh
@@ -47,11 +47,41 @@ fi
# --- 6. Dispatch Logic ---
+# Translate old-style dispatcher + target into a Lua expression for Hyprland's
+# Lua config mode. hyprctl dispatch evaluates the body as Lua.
+lua_dispatch() {
+ local disp="$1"
+ local tgt="$2"
+ local lua_tgt
+
+ # Numeric targets are unquoted; named/relative targets are quoted strings.
+ if [[ "${tgt}" =~ ^-?[0-9]+$ ]]; then
+ lua_tgt="${tgt}"
+ else
+ lua_tgt="\"${tgt}\""
+ fi
+
+ case "${disp}" in
+ workspace)
+ exec hyprctl dispatch "hl.dsp.focus({workspace=${lua_tgt}})"
+ ;;
+ movetoworkspace)
+ exec hyprctl dispatch "hl.dsp.window.move({workspace=${lua_tgt}})"
+ ;;
+ movetoworkspacesilent)
+ exec hyprctl dispatch "hl.dsp.window.move({workspace=${lua_tgt}, silent=true})"
+ ;;
+ *)
+ exec hyprctl dispatch "${disp}" "${tgt}"
+ ;;
+ esac
+}
+
# Case A: Pass-Through (Relative, Special, Named)
# If the target is NOT a pure positive integer (contains chars, +, -, or is empty),
-# we pass it directly to Hyprland without doing math.
+# we pass it directly without doing math.
if [[ ! "${target}" =~ ^[0-9]+$ ]]; then
- exec hyprctl dispatch "${dispatcher}" "${target}"
+ lua_dispatch "${dispatcher}" "${target}"
fi
# Case B: Banked Navigation (Pure Integer)
@@ -69,4 +99,4 @@ fi
final_target=$(( (bank_base * 10) + target ))
# Execute and replace process
-exec hyprctl dispatch "${dispatcher}" "${final_target}"
+lua_dispatch "${dispatcher}" "${final_target}"
diff --git a/user_scripts/hypr/screen_rotate.sh b/user_scripts/hypr/screen_rotate.sh
index a3fde241..5703af40 100755
--- a/user_scripts/hypr/screen_rotate.sh
+++ b/user_scripts/hypr/screen_rotate.sh
@@ -20,8 +20,8 @@ readonly C_RESET=$'\e[0m'
# 2. Config Paths (Strictly ordered by priority for modular setups)
# ------------------------------------------------------------------------------
readonly CONFIG_FILES=(
- "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/edit_here/source/monitors.conf"
- "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/source/monitors.conf"
+ "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/edit_here/source/monitors.lua"
+ "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/source/monitors.lua"
)
# 3. Exit Handling
@@ -44,6 +44,7 @@ die() {
# 4. Privilege & Dependency Checks
# ------------------------------------------------------------------------------
command -v jq &> /dev/null || die "'jq' is missing. Install: sudo pacman -S jq"
+command -v python3 &> /dev/null || die "'python3' is missing."
command -v hyprctl &> /dev/null || die "'hyprctl' is missing."
[[ $EUID -ne 0 ]] || die "Root detected. Run as standard user for socket access."
@@ -78,69 +79,88 @@ IFS=' ' read -r NAME CURRENT_TRANSFORM FALLBACK_WIDTH FALLBACK_HEIGHT FALLBACK_R
# Calculate new transform safely
NEW_TRANSFORM=$(( (CURRENT_TRANSFORM + DIRECTION + 4) % 4 ))
-# 7. Surgical Config Parsing (Source of Truth for Parameters)
+# 7. Locate config file
# ------------------------------------------------------------------------------
-BASE_RULE=""
-RULE_SOURCE="IPC Fallback"
-
+CONF_FILE=""
for conf in "${CONFIG_FILES[@]}"; do
if [[ -f "$conf" ]]; then
- # Use awk to find the last line defining this monitor (last-definition-wins,
- # matching Hyprland's own config semantics)
- matched_line=$(awk -v mon="$NAME" '
- $0 ~ "^[[:space:]]*monitor[[:space:]]*=[[:space:]]*" mon "[[:space:]]*," {
- line = $0
- }
- END { if (line != "") print line }
- ' "$conf")
-
- if [[ -n "$matched_line" ]]; then
- # Strip inline comments
- matched_line="${matched_line%%#*}"
-
- # Bash native regex to extract everything after the equals sign
- if [[ "$matched_line" =~ ^[[:space:]]*monitor[[:space:]]*=[[:space:]]*(.*)$ ]]; then
- BASE_RULE="${BASH_REMATCH[1]}"
- # Strip any resulting trailing whitespace efficiently
- BASE_RULE="${BASE_RULE%"${BASE_RULE##*[![:space:]]}"}"
- RULE_SOURCE="$conf"
- break
- fi
- fi
+ CONF_FILE="$conf"
+ break
fi
done
-# 8. Payload Assembly
-# ------------------------------------------------------------------------------
-if [[ -n "$BASE_RULE" ]]; then
- # STRATEGY A: Config Injection
- # Strip any existing 'transform, X' pairs surgically using sed to prevent duplicates
- CLEAN_RULE=$(sed -E 's/,[[:space:]]*transform[[:space:]]*,[[:space:]]*[0-7]//g' <<< "$BASE_RULE")
-
- # Append the new transform to the pristine config string
- FINAL_PAYLOAD="${CLEAN_RULE}, transform, ${NEW_TRANSFORM}"
-else
- # STRATEGY B: IPC Reconstruction (Failsafe for transient/hot-plugged displays)
- # Rebuild the string using exact values, avoiding 'preferred, auto' completely
- FINAL_PAYLOAD="${NAME}, ${FALLBACK_WIDTH}x${FALLBACK_HEIGHT}@${FALLBACK_REFRESH}, ${FALLBACK_X}x${FALLBACK_Y}, ${FALLBACK_SCALE}, transform, ${NEW_TRANSFORM}"
+if [[ -z "$CONF_FILE" ]]; then
+ # No config exists yet — create one at the primary edit_here location
+ CONF_FILE="${CONFIG_FILES[0]}"
+ mkdir -p "$(dirname "$CONF_FILE")"
fi
-# 9. Execution
+# 8. Update monitors.lua with new transform and reload
# ------------------------------------------------------------------------------
-printf '%s[INFO]%s Target: %s%s%s\n' "$C_BLUE" "$C_RESET" "$C_BOLD" "$NAME" "$C_RESET"
-printf '%s[INFO]%s Source: %s\n' "$C_BLUE" "$C_RESET" "$RULE_SOURCE"
-printf '%s[INFO]%s Payload: %s\n' "$C_YELLOW" "$C_RESET" "$FINAL_PAYLOAD"
-
-if hyprctl keyword monitor "$FINAL_PAYLOAD" > /dev/null; then
+printf '%s[INFO]%s Target: %s%s%s | Transform: %d -> %d\n' \
+ "$C_BLUE" "$C_RESET" "$C_BOLD" "$NAME" "$C_RESET" "$CURRENT_TRANSFORM" "$NEW_TRANSFORM"
+printf '%s[INFO]%s Config: %s\n' "$C_BLUE" "$C_RESET" "$CONF_FILE"
+
+python3 - "$CONF_FILE" "$NAME" "$NEW_TRANSFORM" <<'PYEOF' \
+ || die "Failed to update monitors.lua"
+import sys, re, os, tempfile
+
+conf_path, mon_name, new_transform = sys.argv[1], sys.argv[2], sys.argv[3]
+
+try:
+ with open(conf_path, 'r') as f:
+ text = f.read()
+except FileNotFoundError:
+ text = ''
+
+found = False
+
+def replacer(m):
+ global found
+ line = m.group(0)
+ if f'output = "{mon_name}"' not in line:
+ return line
+ found = True
+ # Remove first, then insert — reversing order would cause the removal regex
+ # to eat the value just inserted, leaving no transform field at all.
+ line = re.sub(r',\s*transform\s*=\s*\d+', '', line)
+ line = re.sub(r'(\s*\}\s*\)\s*)$', f', transform = {new_transform}\\1', line)
+ return line
+
+text = re.sub(r'^.*hl\.monitor\s*\(.*$', replacer, text, flags=re.MULTILINE)
+
+if not found:
+ text += f'\nhl.monitor({{ output = "{mon_name}", mode = "preferred", position = "auto", scale = 1, transform = {new_transform} }})\n'
+
+try:
+ orig_mode = os.stat(conf_path).st_mode
+except FileNotFoundError:
+ orig_mode = 0o644
+
+fd, tmp = tempfile.mkstemp(dir=os.path.dirname(conf_path), prefix='.monitors.lua.tmp.')
+try:
+ with os.fdopen(fd, 'w') as f:
+ f.write(text)
+ os.chmod(tmp, orig_mode)
+ os.replace(tmp, conf_path)
+except Exception as e:
+ os.remove(tmp)
+ sys.stderr.write(f'Atomic write failed: {e}\n')
+ sys.exit(1)
+PYEOF
+
+# 9. Apply via reload
+# ------------------------------------------------------------------------------
+if hyprctl reload > /dev/null; then
printf '%s[SUCCESS]%s Rotation applied: %d -> %d\n' "$C_GREEN" "$C_RESET" "$CURRENT_TRANSFORM" "$NEW_TRANSFORM"
if command -v notify-send &> /dev/null; then
notify-send -a 'System' 'Display Rotated' \
- "$(printf 'Monitor: %s\nTransform: %d\nSource: %s' "$NAME" "$NEW_TRANSFORM" "${RULE_SOURCE##*/}")" \
+ "$(printf 'Monitor: %s\nTransform: %d' "$NAME" "$NEW_TRANSFORM")" \
-h string:x-canonical-private-synchronous:display-rotate
fi
else
- die "Hyprland rejected the monitor payload."
+ die "hyprctl reload failed."
fi
trap - EXIT
diff --git a/user_scripts/images/dusky_screenshot.sh b/user_scripts/images/dusky_screenshot.sh
index 3ecb418c..5d9bd848 100755
--- a/user_scripts/images/dusky_screenshot.sh
+++ b/user_scripts/images/dusky_screenshot.sh
@@ -101,7 +101,7 @@ freeze_screen() {
if (( FREEZE )); then
hyprpicker -r -z >/dev/null 2>&1 &
FREEZE_PID=$!
- sleep 0.12
+ sleep 0.12
fi
}
diff --git a/user_scripts/rofi/hypr_anim.sh b/user_scripts/rofi/hypr_anim.sh
index d1632106..f4d9da91 100755
--- a/user_scripts/rofi/hypr_anim.sh
+++ b/user_scripts/rofi/hypr_anim.sh
@@ -15,9 +15,9 @@ set -o pipefail
readonly CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}"
readonly ANIM_DIR="$CONFIG_DIR/hypr/source/animations"
readonly LINK_DIR="$ANIM_DIR/active"
-readonly DEST_FILE="$LINK_DIR/active.conf"
+readonly DEST_FILE="$LINK_DIR/active.lua"
readonly STATE_FILE="$CONFIG_DIR/dusky/settings/dusky_animiation"
-readonly FALLBACK_ANIM="horizontal_dusky.conf"
+readonly FALLBACK_ANIM="horizontal_dusky.lua"
# Visual Assets (Nerd Fonts)
readonly ICON_ACTIVE="" # Checkmark
@@ -153,13 +153,13 @@ if [[ ! -d "$ANIM_DIR" ]]; then
exit 0
fi
-# Gather .conf files safely
+# Gather .lua files safely
shopt -s nullglob
-files=("$ANIM_DIR"/*.conf)
+files=("$ANIM_DIR"/*.lua)
shopt -u nullglob
if [[ ${#files[@]} -eq 0 ]]; then
- printf '%s\0icon\x1f%s\x1finfo\x1fignore\n' "No .conf files found" "$ICON_ERROR"
+ printf '%s\0icon\x1f%s\x1finfo\x1fignore\n' "No .lua files found" "$ICON_ERROR"
exit 0
fi
diff --git a/user_scripts/rofi/keybindings.sh b/user_scripts/rofi/keybindings.sh
index 66533d74..f142e21c 100755
--- a/user_scripts/rofi/keybindings.sh
+++ b/user_scripts/rofi/keybindings.sh
@@ -313,6 +313,13 @@ main() {
selected_line=${records[selected_index]}
IFS=$DELIM read -r _ dispatcher argument <<< "$selected_line"
+ # In Lua config mode all binds are stored as __lua + internal ID; the ID
+ # is an opaque per-session index and cannot be replayed via hyprctl dispatch.
+ if [[ "$dispatcher" == "__lua" ]]; then
+ hyprctl notify 1 2500 0 " Press the key combination to trigger this bind" 2>/dev/null || true
+ exit 0
+ fi
+
if [[ -n $argument ]]; then
hyprctl dispatch "$dispatcher" "$argument" || die "Failed to dispatch: $dispatcher $argument"
else
diff --git a/user_scripts/rofi/rofi_mako.sh b/user_scripts/rofi/rofi_mako.sh
index 4f7485ab..c09597b0 100755
--- a/user_scripts/rofi/rofi_mako.sh
+++ b/user_scripts/rofi/rofi_mako.sh
@@ -119,7 +119,7 @@ case $ROFI_EXIT in
# 2. Fallback for expired history items (Brings app to front safely)
if [[ -n "$SELECTED_APP" && "$SELECTED_APP" != "notify-send" && "$SELECTED_APP" != "mako" ]]; then
# Grouped and backgrounded cleanly to prevent Rofi/Hyprland hanging
- { gtk-launch "$SELECTED_APP" || hyprctl dispatch exec "$SELECTED_APP"; } >/dev/null 2>&1 &
+ { gtk-launch "$SELECTED_APP" || uwsm-app -- "$SELECTED_APP"; } >/dev/null 2>&1 &
fi
fi
diff --git a/user_scripts/rofi/shader_menu.sh b/user_scripts/rofi/shader_menu.sh
index 153083de..5e5a61b2 100755
--- a/user_scripts/rofi/shader_menu.sh
+++ b/user_scripts/rofi/shader_menu.sh
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
#
-# Hyprshade Selector - Interactive shader picker with live preview
-# Requires: rofi, hyprshade, flock
+# Hyprland Shader Selector - Interactive shader picker with live preview
+# Requires: rofi, hyprctl, flock, python3
#
set -o errexit
@@ -63,7 +63,7 @@ check_dependencies() {
local -a missing=()
local cmd
- for cmd in rofi hyprshade flock; do
+ for cmd in rofi hyprctl flock python3; do
command -v "$cmd" >/dev/null 2>&1 || missing+=("$cmd")
done
@@ -83,12 +83,22 @@ write_latest_token() {
apply_shader_sync() {
local shader="${1:-off}"
-
- if [[ "$shader" == "off" ]]; then
- hyprshade off
- else
- hyprshade on "$shader"
+ local shader_path=""
+
+ if [[ "$shader" != "off" ]]; then
+ # Resolve full path — check user shaders first, then system
+ if [[ -f "${HOME}/.config/hypr/shaders/${shader}.glsl" ]]; then
+ shader_path="${HOME}/.config/hypr/shaders/${shader}.glsl"
+ elif [[ -f "/usr/share/hyprshade/shaders/${shader}.glsl" ]]; then
+ shader_path="/usr/share/hyprshade/shaders/${shader}.glsl"
+ else
+ err "Shader file not found: ${shader}"
+ return 1
+ fi
fi
+
+ # hl.config() is the Lua-mode equivalent of hyprctl keyword
+ hyprctl eval "hl.config({decoration={screen_shader='${shader_path}'}})" >/dev/null 2>&1
}
queue_preview() {
@@ -174,15 +184,28 @@ init() {
trap 'exit 143' TERM
trap 'exit 129' HUP
- current_output=$(hyprshade current 2>/dev/null || true)
- ORIGINAL_SHADER=$(trim "$current_output")
- [[ -z "$ORIGINAL_SHADER" ]] && ORIGINAL_SHADER="off"
-
- if ! ls_output=$(hyprshade ls 2>/dev/null); then
- err "Failed to list shaders"
- exit 1
+ # Get current shader via hyprctl (Lua-mode compatible)
+ local current_path
+ current_path=$(hyprctl -j getoption decoration:screen_shader 2>/dev/null \
+ | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('str',''))" 2>/dev/null || true)
+ current_path=$(trim "$current_path")
+ if [[ -n "$current_path" && "$current_path" != "[[EMPTY]]" ]]; then
+ ORIGINAL_SHADER=$(basename "$current_path" .glsl)
+ else
+ ORIGINAL_SHADER="off"
fi
+ # List shaders from user and system dirs
+ local -a shader_dirs=("${HOME}/.config/hypr/shaders" "/usr/share/hyprshade/shaders")
+ ls_output=""
+ for dir in "${shader_dirs[@]}"; do
+ [[ -d "$dir" ]] || continue
+ while IFS= read -r f; do
+ ls_output+="$(basename "$f" .glsl)"$'\n'
+ done < <(find "$dir" -maxdepth 1 -name "*.glsl" | sort)
+ done
+ [[ -n "$ls_output" ]] || { err "No shaders found"; exit 1; }
+
SHADERS=("off")
while IFS= read -r line; do
diff --git a/user_scripts/spotify/spotify_toggle.sh b/user_scripts/spotify/spotify_toggle.sh
index 5c7f82a3..96fe1933 100755
--- a/user_scripts/spotify/spotify_toggle.sh
+++ b/user_scripts/spotify/spotify_toggle.sh
@@ -3,8 +3,8 @@
# Check if spotify process is running
if pgrep -x "spotify" >/dev/null; then
# If running, just toggle the special workspace
- hyprctl dispatch movetoworkspacesilent "special:music,class:^(Spotify)$"
- hyprctl dispatch togglespecialworkspace music
+ hyprctl dispatch "hl.dsp.window.move({workspace='special:music', window='class:^(Spotify)$', silent=true})"
+ hyprctl dispatch "hl.dsp.workspace.toggle_special('music')"
else
# If not running, launch it
spotify &
diff --git a/user_scripts/waybar/dusky_waybars.sh b/user_scripts/waybar/dusky_waybars.sh
index 9dddd0dc..dac1ed23 100755
--- a/user_scripts/waybar/dusky_waybars.sh
+++ b/user_scripts/waybar/dusky_waybars.sh
@@ -33,7 +33,7 @@ readonly CONFIG_ROOT="${HOME}/.config/waybar"
readonly APP_TITLE="Dusky Waybar Manager"
readonly APP_VERSION="v4.8.1"
-readonly -a UWSM_CMD=(uwsm-app -- waybar)
+readonly -a UWSM_CMD=(systemd-run --user --setenv=HYPRLAND_INSTANCE_SIGNATURE=lua_proxy -- waybar)
declare -ri MAX_DISPLAY_ROWS=14
declare -ri BOX_WIDTH=76
diff --git a/user_scripts/waybar/waybar_autostart.sh b/user_scripts/waybar/waybar_autostart.sh
index 9a7c2163..135e1671 100755
--- a/user_scripts/waybar/waybar_autostart.sh
+++ b/user_scripts/waybar/waybar_autostart.sh
@@ -11,6 +11,8 @@ set -euo pipefail
# --- Constants ---
readonly APP_NAME="waybar"
readonly TIMEOUT_SEC=5
+readonly PROXY_SCRIPT="$HOME/user_scripts/hypr/hypr_lua_proxy.py"
+readonly PROXY_SIG="lua_proxy"
# --- Terminal-Aware Colors (stderr detection) ---
if [[ -t 2 ]]; then
@@ -32,12 +34,13 @@ log_success() { printf '%s[OK]%s %s\n' "${C_GREEN}" "${C_RESET}" "$*" >&2; }
log_err() { printf '%s[ERROR]%s %s\n' "${C_RED}" "${C_RESET}" "$*" >&2; }
# --- Fallback Strategy ---
-# Note: As discovered, this method may not cure the "workspace inheritance"
+# Note: As discovered, this method may not cure the "workspace inheritance"
# bug, but it ensures Waybar launches if systemd is broken.
launch_fallback() {
log_info "Attempting fallback launch (setsid)..."
(
unset XDG_ACTIVATION_TOKEN DESKTOP_STARTUP_ID
+ export HYPRLAND_INSTANCE_SIGNATURE="${PROXY_SIG}"
setsid "${APP_NAME}" "$@" /dev/null 2>&1 &
)
log_success "${APP_NAME} launched (fallback mode)."
@@ -79,6 +82,54 @@ else
log_info "No running instance found."
fi
+# --- Lua IPC Proxy ---
+# Command socket: Python proxy translates old-style "dispatch workspace N"
+# into valid Lua expressions before forwarding to the real Hyprland socket.
+# Event socket: socat pure pass-through (C-level, zero Python overhead).
+PROXY_CMD_SOCK="${XDG_RUNTIME_DIR}/hypr/${PROXY_SIG}/.socket.sock"
+PROXY_EVT_SOCK="${XDG_RUNTIME_DIR}/hypr/${PROXY_SIG}/.socket2.sock"
+
+# Retry hyprctl until the real instance is discoverable (race-safe)
+REAL_DIR=""
+for (( i = 0; i < 50; i++ )); do
+ _sig=$(hyprctl instances -j 2>/dev/null \
+ | python3 -c 'import json,sys; print(json.load(sys.stdin)[0]["instance"])' 2>/dev/null || true)
+ if [[ -n "${_sig}" && -S "${XDG_RUNTIME_DIR}/hypr/${_sig}/.socket2.sock" ]]; then
+ REAL_DIR="${XDG_RUNTIME_DIR}/hypr/${_sig}"
+ break
+ fi
+ sleep 0.1
+done
+[[ -n "${REAL_DIR}" ]] || { log_err "Could not locate real Hyprland socket — proxy aborted."; exit 1; }
+
+log_info "Restarting Lua IPC proxy..."
+
+# Stop and fully clear any previous proxy units before re-creating them
+systemctl --user stop hypr-lua-proxy hypr-socat-proxy 2>/dev/null || true
+systemctl --user reset-failed hypr-lua-proxy hypr-socat-proxy 2>/dev/null || true
+
+# Ensure proxy directory exists before socat tries to bind into it
+mkdir -p "${XDG_RUNTIME_DIR}/hypr/lua_proxy"
+
+# Command socket — Python in its own persistent systemd unit
+systemd-run --user --quiet --unit="hypr-lua-proxy" \
+ -- python3 "${PROXY_SCRIPT}" 2>/dev/null || true
+
+# Event socket — socat in its own persistent systemd unit
+systemd-run --user --quiet --unit="hypr-socat-proxy" \
+ -- socat \
+ "UNIX-LISTEN:${PROXY_EVT_SOCK},fork,unlink-early" \
+ "UNIX-CONNECT:${REAL_DIR}/.socket2.sock" \
+ 2>/dev/null || true
+
+for (( i = 0; i < 30; i++ )); do
+ [[ -S "${PROXY_CMD_SOCK}" && -S "${PROXY_EVT_SOCK}" ]] && break
+ sleep 0.1
+done
+[[ -S "${PROXY_CMD_SOCK}" && -S "${PROXY_EVT_SOCK}" ]] \
+ && log_success "Lua proxy sockets ready." \
+ || log_err "Lua proxy socket(s) not ready — workspace clicks may be broken."
+
# --- Launch Sequence ---
log_info "Starting ${APP_NAME}..."
@@ -88,7 +139,9 @@ if command -v systemd-run >/dev/null 2>&1; then
unit_name="${APP_NAME}-mgr-${EPOCHSECONDS}-$$"
# '--' separates options from the command to prevent flag injection
- if systemd-run --user --quiet --unit="${unit_name}" -- "${APP_NAME}" "$@" >/dev/null 2>&1; then
+ if systemd-run --user --quiet --unit="${unit_name}" \
+ --setenv=HYPRLAND_INSTANCE_SIGNATURE="${PROXY_SIG}" \
+ -- "${APP_NAME}" "$@" >/dev/null 2>&1; then
log_success "${APP_NAME} launched via systemd unit: ${unit_name}"
else
log_err "systemd-run failed; attempting fallback."
diff --git a/user_scripts/wlogout/dusky_session.sh b/user_scripts/wlogout/dusky_session.sh
index 8aada693..cd3f70e8 100755
--- a/user_scripts/wlogout/dusky_session.sh
+++ b/user_scripts/wlogout/dusky_session.sh
@@ -26,7 +26,7 @@ if [[ -d "$STATE_DIR" ]]; then
fi
# 2. Reset workspace (visually cleaner for next boot, non-fatal)
-hyprctl dispatch workspace 1 >/dev/null 2>&1 || :
+hyprctl dispatch "hl.dsp.focus({workspace=1})" >/dev/null 2>&1 || :
# 3. Smart teardown logic
# Safely check if UWSM is installed, then ask UWSM if it is actively managing the session
@@ -86,7 +86,7 @@ else
# Execute final action
if [[ "$ACTION" == "logout" ]]; then
- exec hyprctl dispatch exit
+ exec hyprctl dispatch "hl.dsp.exit()"
else
exec systemctl "$ACTION" --no-wall
fi