summaryrefslogtreecommitdiff
path: root/hypr
diff options
context:
space:
mode:
authorbh <qn+git@epicurus.dev>2026-05-21 23:07:20 +0800
committerbh <qn+git@epicurus.dev>2026-05-21 23:07:20 +0800
commitdfcfd94577a3f400bd2ffeabfdfea48c785a4c6b (patch)
tree36acaee16bac5e4e89d94d5acbeec3b84f775289 /hypr
parentf9d9afa727c46b1732eb504e06746bb0a57f52ab (diff)
hypr: converted to lua
Diffstat (limited to 'hypr')
-rw-r--r--hypr/.config/hypr/hyprland.conf312
-rw-r--r--hypr/.config/hypr/hyprland.lua356
2 files changed, 356 insertions, 312 deletions
diff --git a/hypr/.config/hypr/hyprland.conf b/hypr/.config/hypr/hyprland.conf
deleted file mode 100644
index 8e492e3..0000000
--- a/hypr/.config/hypr/hyprland.conf
+++ /dev/null
@@ -1,312 +0,0 @@
-# ██╗ ██╗██╗ ██╗██████╗ ██████╗ ██╗ ███████╗ ██████╗ ███╗ ██╗
-# ██║ ██║╚██╗ ██╔╝██╔══██╗██╔══██╗██║ ██╔════╝██╔═══██╗████╗ ██║
-# ███████║ ╚████╔╝ ██████╔╝██████╔╝██║ █████╗ ██║ ██║██╔██╗ ██║
-# ██╔══██║ ╚██╔╝ ██╔═══╝ ██╔══██╗██║ ██╔══╝ ██║ ██║██║╚██╗██║
-# ██║ ██║ ██║ ██║ ██║ ██║███████╗███████╗╚██████╔╝██║ ╚████║
-# ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═══╝
-#
-# █▄▄ █░█ ▀ █▀ █▀▀ █▀█ █▄░█ █▀▀ █ █▀▀ █▀▀ █▀█ █▀█ █░█ █▄█ █▀█ █▀█ █░░ ▄▀█ █▄░█ █▀▄
-# █▄█ █▀█ ░ ▄█ █▄▄ █▄█ █░▀█ █▀░ █ █▄▄ █▀░ █▄█ █▀▄ █▀█ ░█░ █▀▀ █▀▄ █▄▄ █▀█ █░▀█ █▄▀
-
-
-# ╔════════════════════════════════════════╗
-# ║ 🖥 MONITORS ║
-# ╚════════════════════════════════════════╝
-
-monitor=,preferred,auto,auto
-
-
-# ╔════════════════════════════════════════╗
-# ║ 📦 MY PROGRAMS ║
-# ╚════════════════════════════════════════╝
-
-$terminal = kitty
-$fileManager = dolphin
-$menu = rofi -modi drun -show drun -config ~/.config/rofi/rofidmenu.rasi
-$browser = firefox
-
-
-# ╔════════════════════════════════════════╗
-# ║ ⚡ AUTOSTART ║
-# ╚════════════════════════════════════════╝
-
-exec-once = kitty
-exec-once = kitty
-exec-once = quickshell
-exec-once = hyprpaper
-exec-once = dunst
-exec-once = wl-paste --type text --watch cliphist store
-exec-once = wl-paste --type image --watch cliphist store
-exec-once = wl-paste --primary --type text --watch cliphist -db-path ~/.cache/cliphist/primary.db store
-exec-once = wl-paste --primary --type image --watch cliphist -db-path ~/.cache/cliphist/primary.db store
-
-# ╔════════════════════════════════════════╗
-# ║ 🌿 ENVIRONMENT VARIABLES ║
-# ╚════════════════════════════════════════╝
-
-env = XCURSOR_THEME,Vimix-cursors
-env = XCURSOR_SIZE,24
-env = HYPRCURSOR_THEME,Vimix-cursors
-env = HYPRCURSOR_SIZE,24
-
-# 🎨 Toolkit theming
-env = GTK_THEME,Adwaita:dark
-env = QT_QPA_PLATFORMTHEME,qt6ct
-env = QT_QPA_PLATFORM,wayland;xcb
-env = QT_WAYLAND_DISABLE_WINDOWDECORATION,1
-env = QT_AUTO_SCREEN_SCALE_FACTOR,1
-
-
-# ╔════════════════════════════════════════╗
-# ║ ⌨ DEVICE ║
-# ╚════════════════════════════════════════╝
-device {
- name = at-translated-set-2-keyboard
- enabled = false
-}
-
-
-# ╔════════════════════════════════════════╗
-# ║ 🎨 LOOK AND FEEL ║
-# ╚════════════════════════════════════════╝
-
-# 🎨 Colors (ported from bspwm)
-$darkcyan = rgb(007575)
-$lightcyan = rgb(1ebaba)
-$lightercyan = rgb(19e0e0)
-$red = rgb(e55235)
-
-general {
- gaps_in = 3
- gaps_out = 3
-
- border_size = 1
-
- col.active_border = $lightercyan
- col.inactive_border = $darkcyan
-
- resize_on_border = false
- allow_tearing = false
- layout = scrolling
-}
-
-dwindle {
- preserve_split = true
- force_split = 2
- # pseudotile = true
- preserve_split = true
-}
-
-decoration {
- rounding = 0
-
- active_opacity = 1.0
- inactive_opacity = 1.0
-
- shadow {
- enabled = true
- range = 4
- render_power = 3
- color = rgba(1a1a1aee)
- }
-
- blur {
- enabled = true
- size = 0
- passes = 5
-
- ignore_opacity = false
- new_optimizations = true
- xray = false
- vibrancy = 0.1696
- }
-}
-
-animations {
- enabled = true
-
- bezier = myBezier, 0.05, 0.9, 0.1, 1.05
-
- animation = windows, 1, 7, myBezier
- animation = windowsOut, 1, 7, default, popin 80%
- animation = border, 1, 10, default
- animation = borderangle, 1, 8, default
- animation = fade, 1, 7, default
- animation = workspaces, 1, 4, default, slidefade
-}
-
-master {
- new_status = master
-}
-
-misc {
- force_default_wallpaper = 0
- disable_hyprland_logo = true
- focus_on_activate = true
- background_color = 0x000000
-}
-
-
-# ╔════════════════════════════════════════╗
-# ║ 🖱 INPUT ║
-# ╚════════════════════════════════════════╝
-
-input {
- # kb_layout = us,us,cn,jp,ru
- # kb_variant = dvorak,,wubi,,,
- # kb_model =
- # kb_options = grp:ctrl_shift_toggle
- # kb_rules =
- kb_layout = us
- kb_variant = dvp
-
- follow_mouse = 1
-
- sensitivity = 0
-
- touchpad {
- natural_scroll = false
- }
-}
-
-gestures {
- # workspace_swipe option does not exist in current Hyprland
-}
-
-device {
- name = epic-mouse-v1
- sensitivity = -0.5
-}
-
-
-# ╔════════════════════════════════════════╗
-# ║ ⌨ KEYBINDINGS ║
-# ╚════════════════════════════════════════╝
-
-# 🚀 Applications
-bind = SUPER, Return, exec, $terminal
-bind = SUPER ALT, Return, exec, kitty --class floating
-bind = SUPER, W, exec, $browser
-bind = SUPER, D, exec, $menu
-bind = SUPER, E, exec, emacs
-
-# 📜 Scripts
-bind = SUPER, V, exec, ~/Scripts/clipboard
-bind = SUPER SHIFT, V, exec, ~/Scripts/clipboard-primary
-bind = SUPER, R, exec, ~/Scripts/run
-bind = SUPER, S, exec, ~/Scripts/screenshot
-bind = SUPER SHIFT, S, exec, ~/Scripts/screenshot snip
-
-# 🪟 Window Management
-bind = SUPER SHIFT, C, killactive,
-bind = SUPER SHIFT, R, exec, hyprctl reload
-bind = SUPER, F, fullscreen, 0
-bind = SUPER, M, fullscreen, 1
-
-# 👁 Move Focus (Vim-style)
-bind = SUPER, H, movefocus, l
-bind = SUPER, L, movefocus, r
-bind = SUPER, K, movefocus, u
-bind = SUPER, J, movefocus, d
-
-# ↔ Swap Window (Vim-style)
-bind = SUPER SHIFT, H, swapwindow, l
-bind = SUPER SHIFT, L, swapwindow, r
-bind = SUPER SHIFT, K, swapwindow, u
-bind = SUPER SHIFT, J, swapwindow, d
-
-# ✂ Preselection / Split Direction (Ctrl+Super+hjkl)
-bind = SUPER CTRL, H, layoutmsg, preselect l
-bind = SUPER CTRL, L, layoutmsg, preselect r
-bind = SUPER CTRL, K, layoutmsg, preselect u
-bind = SUPER CTRL, J, layoutmsg, preselect d
-
-# 🔄 Swap with last window
-bind = SUPER CTRL, M, swapnext, prev
-
-# 🔢 Switch Workspaces (Dvorak layout keys)
-# Note: These keybinds match Dvorak layout from sxhkd config
-bind = SUPER, ampersand, workspace, 1 # 一
-bind = SUPER, bracketleft, workspace, 2 # 二
-bind = SUPER, braceleft, workspace, 3 # 三
-bind = SUPER, braceright, workspace, 4 # 四
-bind = SUPER, parenleft, workspace, 5 # 五
-bind = SUPER, equal, workspace, 6 # 六
-bind = SUPER, asterisk, workspace, 7 # 七
-bind = SUPER, parenright, workspace, 8 # 八
-bind = SUPER, plus, workspace, 9 # 九
-bind = SUPER, bracketright, workspace, 10 # 十
-bind = SUPER, exclam, workspace, 11
-bind = SUPER, numbersign, workspace, 12
-
-# 📦 Move to Workspace (Dvorak layout keys)
-bind = SUPER SHIFT, ampersand, movetoworkspace, 1
-bind = SUPER SHIFT, bracketleft, movetoworkspace, 2
-bind = SUPER SHIFT, braceleft, movetoworkspace, 3
-bind = SUPER SHIFT, braceright, movetoworkspace, 4
-bind = SUPER SHIFT, parenleft, movetoworkspace, 5
-bind = SUPER SHIFT, equal, movetoworkspace, 6
-bind = SUPER SHIFT, asterisk, movetoworkspace, 7
-bind = SUPER SHIFT, parenright, movetoworkspace, 8
-bind = SUPER SHIFT, plus, movetoworkspace, 9
-bind = SUPER SHIFT, bracketright, movetoworkspace, 10
-bind = SUPER SHIFT, exclam, movetoworkspace, 11
-bind = SUPER SHIFT, numbersign, movetoworkspace, 12
-
-# 🖱 Scroll Through Workspaces (mainMod + scroll)
-bind = SUPER, mouse_down, workspace, e+1
-bind = SUPER, mouse_up, workspace, e-1
-
-# 🖱 Move / Resize Windows (mainMod + LMB/RMB)
-bindm = SUPER, mouse:272, movewindow
-bindm = SUPER, mouse:273, resizewindow
-
-# 🎵 Media Keys
-bindel = , XF86AudioRaiseVolume, exec, pactl set-sink-volume @DEFAULT_SINK@ +5% && VOLUME=$(pactl get-sink-volume @DEFAULT_SINK@ | grep -Po '\d+%' | head -1) && dunstify " Volume: $VOLUME" -h int:value:"${VOLUME%\%}" -r 2593 -t 1000
-bindel = , XF86AudioLowerVolume, exec, pactl set-sink-volume @DEFAULT_SINK@ -5% && VOLUME=$(pactl get-sink-volume @DEFAULT_SINK@ | grep -Po '\d+%' | head -1) && dunstify " Volume: $VOLUME" -h int:value:"${VOLUME%\%}" -r 2593 -t 1000
-bindl = , XF86AudioMute, exec, ~/.config/hypr/scripts/mute
-
-
-# ╔════════════════════════════════════════╗
-# ║ 🪟 LAYER RULES ║
-# ╚════════════════════════════════════════╝
-
-layerrule = blur on, match:namespace notifications
-layerrule = ignore_alpha 0.59, match:namespace notifications
-layerrule = blur on, match:namespace rofi
-layerrule = ignore_alpha 0.5, match:namespace rofi
-layerrule = blur on, match:namespace quickshell*
-layerrule = ignore_alpha 0.5, match:namespace quickshell*
-
-
-# ╔════════════════════════════════════════╗
-# ║ 🗂 WINDOWS AND WORKSPACES ║
-# ╚════════════════════════════════════════╝
-
-# 🦊 Firefox → workspace 2
-windowrule = match:class ^(firefox)$, workspace 2
-
-# 📝 Emacs → workspace 3
-windowrule = match:class ^(Emacs)$, workspace 3
-
-# 🎈 Float windows with class "floating"
-windowrule = match:class ^(floating)$, float on
-
-# 💻 Dropdown terminal (yakuake-style)
-windowrule = match:class ^(quickshell-dropdown)$, float on
-windowrule = match:class ^(quickshell-dropdown)$, size 100% 40%
-windowrule = match:class ^(quickshell-dropdown)$, move 0 25
-
-# 🗂 Workspace Names (Chinese characters from bspwm)
-exec-once = hyprctl dispatch renameworkspace "1 一"
-exec-once = hyprctl dispatch renameworkspace "2 二"
-exec-once = hyprctl dispatch renameworkspace "3 三"
-exec-once = hyprctl dispatch renameworkspace "4 四"
-exec-once = hyprctl dispatch renameworkspace "5 五"
-exec-once = hyprctl dispatch renameworkspace "6 六"
-exec-once = hyprctl dispatch renameworkspace "7 七"
-exec-once = hyprctl dispatch renameworkspace "8 八"
-exec-once = hyprctl dispatch renameworkspace "9 九"
-exec-once = hyprctl dispatch renameworkspace "10 十"
-exec-once = hyprctl dispatch renameworkspace "11 ᚨ"
-exec-once = hyprctl dispatch renameworkspace "12 ᚠ"
diff --git a/hypr/.config/hypr/hyprland.lua b/hypr/.config/hypr/hyprland.lua
new file mode 100644
index 0000000..fee4537
--- /dev/null
+++ b/hypr/.config/hypr/hyprland.lua
@@ -0,0 +1,356 @@
+-- ██╗ ██╗██╗ ██╗██████╗ ██████╗ ██╗ ███████╗ ██████╗ ███╗ ██╗
+-- ██║ ██║╚██╗ ██╔╝██╔══██╗██╔══██╗██║ ██╔════╝██╔═══██╗████╗ ██║
+-- ███████║ ╚████╔╝ ██████╔╝██████╔╝██║ █████╗ ██║ ██║██╔██╗ ██║
+-- ██╔══██║ ╚██╔╝ ██╔═══╝ ██╔══██╗██║ ██╔══╝ ██║ ██║██║╚██╗██║
+-- ██║ ██║ ██║ ██║ ██║ ██║███████╗███████╗╚██████╔╝██║ ╚████║
+-- ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═══╝
+--
+-- █▄▄ █░█ ▀ █▀ █▀▀ █▀█ █▄░█ █▀▀ █ █▀▀ █▀▀ █▀█ █▀█ █░█ █▄█ █▀█ █▀█ █░░ ▄▀█ █▄░█ █▀▄
+-- █▄█ █▀█ ░ ▄█ █▄▄ █▄█ █░▀█ █▀░ █ █▄▄ █▀░ █▄█ █▀▄ █▀█ ░█░ █▀▀ █▀▄ █▄▄ █▀█ █░▀█ █▄▀
+
+
+-- ╔════════════════════════════════════════╗
+-- ║ 🖥 MONITORS ║
+-- ╚════════════════════════════════════════╝
+
+hl.monitor({
+ output = "",
+ mode = "preferred",
+ position = "auto",
+ scale = "auto",
+})
+
+
+-- ╔════════════════════════════════════════╗
+-- ║ 📦 MY PROGRAMS ║
+-- ╚════════════════════════════════════════╝
+
+local terminal = "kitty"
+local fileManager = "dolphin"
+local menu = "rofi -modi drun -show drun -config ~/.config/rofi/rofidmenu.rasi"
+local browser = "firefox"
+
+
+-- ╔════════════════════════════════════════╗
+-- ║ ⚡ AUTOSTART ║
+-- ╚════════════════════════════════════════╝
+
+hl.on("hyprland.start", function()
+ hl.exec_cmd("kitty")
+ hl.exec_cmd("kitty")
+ hl.exec_cmd("quickshell")
+ hl.exec_cmd("hyprpaper")
+ hl.exec_cmd("dunst")
+ hl.exec_cmd("wl-paste --type text --watch cliphist store")
+ hl.exec_cmd("wl-paste --type image --watch cliphist store")
+ hl.exec_cmd("wl-paste --primary --type text --watch cliphist -db-path ~/.cache/cliphist/primary.db store")
+ hl.exec_cmd("wl-paste --primary --type image --watch cliphist -db-path ~/.cache/cliphist/primary.db store")
+end)
+
+
+-- ╔════════════════════════════════════════╗
+-- ║ 🌿 ENVIRONMENT VARIABLES ║
+-- ╚════════════════════════════════════════╝
+
+hl.env("XCURSOR_THEME", "Vimix-cursors")
+hl.env("XCURSOR_SIZE", "24")
+hl.env("HYPRCURSOR_THEME", "Vimix-cursors")
+hl.env("HYPRCURSOR_SIZE", "24")
+
+-- Toolkit theming
+hl.env("GTK_THEME", "Adwaita:dark")
+hl.env("QT_QPA_PLATFORMTHEME", "qt6ct")
+hl.env("QT_QPA_PLATFORM", "wayland;xcb")
+hl.env("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1")
+hl.env("QT_AUTO_SCREEN_SCALE_FACTOR", "1")
+
+
+-- ╔════════════════════════════════════════╗
+-- ║ ⌨ DEVICE ║
+-- ╚════════════════════════════════════════╝
+
+hl.device({
+ name = "at-translated-set-2-keyboard",
+ enabled = false,
+})
+
+
+-- ╔════════════════════════════════════════╗
+-- ║ 🎨 LOOK AND FEEL ║
+-- ╚════════════════════════════════════════╝
+
+-- Colors (ported from bspwm)
+local darkcyan = "rgb(007575)"
+local lightcyan = "rgb(1ebaba)"
+local lightercyan = "rgb(19e0e0)"
+local red = "rgb(e55235)"
+
+hl.config({
+ general = {
+ gaps_in = 3,
+ gaps_out = 3,
+
+ border_size = 1,
+
+ col = {
+ active_border = lightercyan,
+ inactive_border = darkcyan,
+ },
+
+ resize_on_border = false,
+ allow_tearing = false,
+ layout = "scrolling",
+ },
+})
+
+hl.config({
+ dwindle = {
+ preserve_split = true,
+ force_split = 2,
+ },
+})
+
+hl.config({
+ decoration = {
+ rounding = 0,
+
+ active_opacity = 1.0,
+ inactive_opacity = 1.0,
+
+ shadow = {
+ enabled = true,
+ range = 4,
+ render_power = 3,
+ color = "rgba(1a1a1aee)",
+ },
+
+ blur = {
+ enabled = true,
+ size = 0,
+ passes = 5,
+ ignore_opacity = false,
+ new_optimizations = true,
+ xray = false,
+ vibrancy = 0.1696,
+ },
+ },
+})
+
+hl.config({
+ animations = {
+ enabled = true,
+ },
+})
+
+hl.curve("myBezier", { type = "bezier", points = { {0.05, 0.9}, {0.1, 1.05} } })
+
+hl.animation({ leaf = "windows", enabled = true, speed = 7, bezier = "myBezier" })
+hl.animation({ leaf = "windowsOut", enabled = true, speed = 7, bezier = "default", style = "popin 80%" })
+hl.animation({ leaf = "border", enabled = true, speed = 10, bezier = "default" })
+hl.animation({ leaf = "borderangle", enabled = true, speed = 8, bezier = "default" })
+hl.animation({ leaf = "fade", enabled = true, speed = 7, bezier = "default" })
+hl.animation({ leaf = "workspaces", enabled = true, speed = 4, bezier = "default", style = "slidefade" })
+
+hl.config({
+ master = {
+ new_status = "master",
+ },
+})
+
+hl.config({
+ misc = {
+ force_default_wallpaper = 0,
+ disable_hyprland_logo = true,
+ focus_on_activate = true,
+ background_color = 0x000000,
+ },
+})
+
+
+-- ╔════════════════════════════════════════╗
+-- ║ 🖱 INPUT ║
+-- ╚════════════════════════════════════════╝
+
+hl.config({
+ input = {
+ -- kb_layout = "us,us,cn,jp,ru",
+ -- kb_variant = "dvorak,,wubi,,,",
+ -- kb_model = "",
+ -- kb_options = "grp:ctrl_shift_toggle",
+ -- kb_rules = "",
+ kb_layout = "us",
+ kb_variant = "dvp",
+
+ follow_mouse = 1,
+
+ sensitivity = 0,
+
+ touchpad = {
+ natural_scroll = false,
+ },
+ },
+})
+
+-- gestures: workspace_swipe option does not exist in current Hyprland
+
+hl.device({
+ name = "epic-mouse-v1",
+ sensitivity = -0.5,
+})
+
+
+-- ╔════════════════════════════════════════╗
+-- ║ ⌨ KEYBINDINGS ║
+-- ╚════════════════════════════════════════╝
+
+-- Applications
+hl.bind("SUPER + Return", hl.dsp.exec_cmd(terminal))
+hl.bind("SUPER + ALT + Return", hl.dsp.exec_cmd("kitty --class floating"))
+hl.bind("SUPER + W", hl.dsp.exec_cmd(browser))
+hl.bind("SUPER + D", hl.dsp.exec_cmd(menu))
+hl.bind("SUPER + E", hl.dsp.exec_cmd("emacs"))
+
+-- Scripts
+hl.bind("SUPER + V", hl.dsp.exec_cmd("~/Scripts/clipboard"))
+hl.bind("SUPER + SHIFT + V", hl.dsp.exec_cmd("~/Scripts/clipboard-primary"))
+hl.bind("SUPER + R", hl.dsp.exec_cmd("~/Scripts/run"))
+hl.bind("SUPER + S", hl.dsp.exec_cmd("~/Scripts/screenshot"))
+hl.bind("SUPER + SHIFT + S", hl.dsp.exec_cmd("~/Scripts/screenshot snip"))
+
+-- Window Management
+hl.bind("SUPER + SHIFT + C", hl.dsp.window.close())
+hl.bind("SUPER + SHIFT + R", hl.dsp.exec_cmd("hyprctl reload"))
+hl.bind("SUPER + F", hl.dsp.window.fullscreen({ mode = 0 }))
+hl.bind("SUPER + M", hl.dsp.window.fullscreen({ mode = 1 }))
+
+-- Move Focus (Vim-style)
+hl.bind("SUPER + H", hl.dsp.focus({ direction = "left" }))
+hl.bind("SUPER + L", hl.dsp.focus({ direction = "right" }))
+hl.bind("SUPER + K", hl.dsp.focus({ direction = "up" }))
+hl.bind("SUPER + J", hl.dsp.focus({ direction = "down" }))
+
+-- Swap Window (Vim-style)
+hl.bind("SUPER + SHIFT + H", hl.dsp.window.swap({ direction = "left" }))
+hl.bind("SUPER + SHIFT + L", hl.dsp.window.swap({ direction = "right" }))
+hl.bind("SUPER + SHIFT + K", hl.dsp.window.swap({ direction = "up" }))
+hl.bind("SUPER + SHIFT + J", hl.dsp.window.swap({ direction = "down" }))
+
+-- Preselection / Split Direction (Ctrl+Super+hjkl)
+hl.bind("SUPER + CTRL + H", hl.dsp.layout("preselect l"))
+hl.bind("SUPER + CTRL + L", hl.dsp.layout("preselect r"))
+hl.bind("SUPER + CTRL + K", hl.dsp.layout("preselect u"))
+hl.bind("SUPER + CTRL + J", hl.dsp.layout("preselect d"))
+
+-- Swap with last window
+hl.bind("SUPER + CTRL + M", hl.dsp.window.swap({ prev = true }))
+
+-- Switch Workspaces (Dvorak layout keys)
+hl.bind("SUPER + ampersand", hl.dsp.focus({ workspace = 1 })) -- 一
+hl.bind("SUPER + bracketleft", hl.dsp.focus({ workspace = 2 })) -- 二
+hl.bind("SUPER + braceleft", hl.dsp.focus({ workspace = 3 })) -- 三
+hl.bind("SUPER + braceright", hl.dsp.focus({ workspace = 4 })) -- 四
+hl.bind("SUPER + parenleft", hl.dsp.focus({ workspace = 5 })) -- 五
+hl.bind("SUPER + equal", hl.dsp.focus({ workspace = 6 })) -- 六
+hl.bind("SUPER + asterisk", hl.dsp.focus({ workspace = 7 })) -- 七
+hl.bind("SUPER + parenright", hl.dsp.focus({ workspace = 8 })) -- 八
+hl.bind("SUPER + plus", hl.dsp.focus({ workspace = 9 })) -- 九
+hl.bind("SUPER + bracketright", hl.dsp.focus({ workspace = 10 })) -- 十
+hl.bind("SUPER + exclam", hl.dsp.focus({ workspace = 11 }))
+hl.bind("SUPER + numbersign", hl.dsp.focus({ workspace = 12 }))
+
+-- Move to Workspace (Dvorak layout keys)
+hl.bind("SUPER + SHIFT + ampersand", hl.dsp.window.move({ workspace = 1 }))
+hl.bind("SUPER + SHIFT + bracketleft", hl.dsp.window.move({ workspace = 2 }))
+hl.bind("SUPER + SHIFT + braceleft", hl.dsp.window.move({ workspace = 3 }))
+hl.bind("SUPER + SHIFT + braceright", hl.dsp.window.move({ workspace = 4 }))
+hl.bind("SUPER + SHIFT + parenleft", hl.dsp.window.move({ workspace = 5 }))
+hl.bind("SUPER + SHIFT + equal", hl.dsp.window.move({ workspace = 6 }))
+hl.bind("SUPER + SHIFT + asterisk", hl.dsp.window.move({ workspace = 7 }))
+hl.bind("SUPER + SHIFT + parenright", hl.dsp.window.move({ workspace = 8 }))
+hl.bind("SUPER + SHIFT + plus", hl.dsp.window.move({ workspace = 9 }))
+hl.bind("SUPER + SHIFT + bracketright", hl.dsp.window.move({ workspace = 10 }))
+hl.bind("SUPER + SHIFT + exclam", hl.dsp.window.move({ workspace = 11 }))
+hl.bind("SUPER + SHIFT + numbersign", hl.dsp.window.move({ workspace = 12 }))
+
+-- Scroll Through Workspaces (mainMod + scroll)
+hl.bind("SUPER + mouse_down", hl.dsp.focus({ workspace = "e+1" }))
+hl.bind("SUPER + mouse_up", hl.dsp.focus({ workspace = "e-1" }))
+
+-- Move / Resize Windows (mainMod + LMB/RMB)
+hl.bind("SUPER + mouse:272", hl.dsp.window.drag(), { mouse = true })
+hl.bind("SUPER + mouse:273", hl.dsp.window.resize(), { mouse = true })
+
+-- Media Keys
+hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd([[pactl set-sink-volume @DEFAULT_SINK@ +5% && VOLUME=$(pactl get-sink-volume @DEFAULT_SINK@ | grep -Po '\d+%' | head -1) && dunstify " Volume: $VOLUME" -h int:value:"${VOLUME%\%}" -r 2593 -t 1000]]), { repeating = true, locked = true })
+hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd([[pactl set-sink-volume @DEFAULT_SINK@ -5% && VOLUME=$(pactl get-sink-volume @DEFAULT_SINK@ | grep -Po '\d+%' | head -1) && dunstify " Volume: $VOLUME" -h int:value:"${VOLUME%\%}" -r 2593 -t 1000]]), { repeating = true, locked = true })
+hl.bind("XF86AudioMute", hl.dsp.exec_cmd("~/.config/hypr/scripts/mute"), { locked = true })
+
+
+-- ╔════════════════════════════════════════╗
+-- ║ 🪟 LAYER RULES ║
+-- ╚════════════════════════════════════════╝
+
+hl.layer_rule({
+ match = { namespace = "notifications" },
+ blur = true,
+ ignore_alpha = 0.59,
+})
+
+hl.layer_rule({
+ match = { namespace = "rofi" },
+ blur = true,
+ ignore_alpha = 0.5,
+})
+
+hl.layer_rule({
+ match = { namespace = "quickshell*" },
+ blur = true,
+ ignore_alpha = 0.5,
+})
+
+
+-- ╔════════════════════════════════════════╗
+-- ║ 🗂 WINDOWS AND WORKSPACES ║
+-- ╚════════════════════════════════════════╝
+
+-- Firefox -> workspace 2
+hl.window_rule({
+ match = { class = "^(firefox)$" },
+ workspace = 2,
+})
+
+-- Emacs -> workspace 3
+hl.window_rule({
+ match = { class = "^(Emacs)$" },
+ workspace = 3,
+})
+
+-- Float windows with class "floating"
+hl.window_rule({
+ match = { class = "^(floating)$" },
+ float = true,
+})
+
+-- Dropdown terminal (yakuake-style)
+hl.window_rule({
+ match = { class = "^(quickshell-dropdown)$" },
+ float = true,
+ size = "100% 40%",
+ move = "0 25",
+})
+
+-- Workspace Names (Chinese characters from bspwm)
+hl.on("hyprland.start", function()
+ hl.exec_cmd([[hyprctl dispatch renameworkspace "1 一"]])
+ hl.exec_cmd([[hyprctl dispatch renameworkspace "2 二"]])
+ hl.exec_cmd([[hyprctl dispatch renameworkspace "3 三"]])
+ hl.exec_cmd([[hyprctl dispatch renameworkspace "4 四"]])
+ hl.exec_cmd([[hyprctl dispatch renameworkspace "5 五"]])
+ hl.exec_cmd([[hyprctl dispatch renameworkspace "6 六"]])
+ hl.exec_cmd([[hyprctl dispatch renameworkspace "7 七"]])
+ hl.exec_cmd([[hyprctl dispatch renameworkspace "8 八"]])
+ hl.exec_cmd([[hyprctl dispatch renameworkspace "9 九"]])
+ hl.exec_cmd([[hyprctl dispatch renameworkspace "10 十"]])
+ hl.exec_cmd([[hyprctl dispatch renameworkspace "11 ᚨ"]])
+ hl.exec_cmd([[hyprctl dispatch renameworkspace "12 ᚠ"]])
+end)