-- ~/.config/hypr/hyprland.luaA ----------------------------------------------------- -- Variables (from variables.conf) ----------------------------------------------------- local copy = "wl-copy --trim-newline" local paste = "wl-paste" local launcher = "rofi -show run -p 'launch'" -- local clear = "cliphist list | head -n1 | cliphist delete" ----------------------------------------------------- -- Monitors (from monitors.conf) ----------------------------------------------------- hl.monitor({ output = "desc:Ancor Communications Inc ASUS VS228 E3LMTF071438", mode = "preferred", position = "0x0", scale = "1" }) -- DP-7, left hl.monitor({ output = "desc:Samsung Display Corp. 0x4193", mode = "preferred", position = "1920x0", scale = "2" }) -- eDP-1, center hl.monitor({ output = "desc:Ancor Communications Inc ASUS VS228 E3LMTF071391", mode = "preferred", position = "3360x0", scale = "1" }) -- DP-8, right hl.monitor({ output = "desc:Stargate Technology FHD", mode = "preferred", position = "auto", scale = "auto" }) -- portable monitor ----------------------------------------------------- -- Environment Variables (from env.conf) ----------------------------------------------------- hl.env("GDK_BACKEND", "wayland,x11,*") hl.env("GUI_ENABLE_WAYLAND", "1") hl.env("HYPRCURSOR_SIZE", "18") hl.env("QT_QPA_PLATFORM", "wayland;xcb") hl.env("QT_QPA_PLATFORMTHEME", "qt6ct") hl.env("QT_AUTO_SCREEN_SCALE_FACTOR", "1") hl.env("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1") hl.env("XCURSOR_SIZE", "18") hl.env("XDG_CURRENT_DESKTOP", "Hyprland") hl.env("XDG_SESSION_TYPE", "wayland") hl.env("XDG_SESSION_DESKTOP", "Hyprland") ----------------------------------------------------- -- Appearance & Input (from appearance.conf & input.conf) ----------------------------------------------------- hl.config({ general = { gaps_in = 1, gaps_out = 2, border_size = 2, col = { active_border = "rgba(fabd2f99)", inactive_border = "rgba(595959aa)", }, resize_on_border = false, allow_tearing = false, layout = "dwindle" }, decoration = { rounding = 10, rounding_power = 2, active_opacity = 1.0, inactive_opacity = 1.0, shadow = { enabled = true, range = 4, render_power = 3, color = "rgba(1a1a1aee)" }, blur = { enabled = true, size = 3, passes = 1, vibrancy = 0.1696 } }, animations = { enabled = true, bezier = { "easeOutQuint,0.23,1,0.32,1", "easeInOutCubic,0.65,0.05,0.36,1", "linear,0,0,1,1", "almostLinear,0.5,0.5,0.75,1.0", "quick,0.15,0,0.1,1" }, animation = { "global, 1, 10, default", "border, 1, 5.39, easeOutQuint", "windows, 1, 4.79, easeOutQuint", "windowsIn, 1, 4.1, easeOutQuint, popin 87%", "windowsOut, 1, 1.49, linear, popin 87%", "fadeIn, 1, 1.73, almostLinear", "fadeOut, 1, 1.46, almostLinear", "fade, 1, 3.03, quick", "layers, 1, 3.81, easeOutQuint", "layersIn, 1, 4, easeOutQuint, fade", "layersOut, 1, 1.5, linear, fade", "fadeLayersIn, 1, 1.79, almostLinear", "fadeLayersOut, 1, 1.39, almostLinear", "workspaces, 1, 1.94, almostLinear, fade", "workspacesIn, 1, 1.21, almostLinear, fade", "workspacesOut, 1, 1.94, almostLinear, fade" } }, dwindle = { preserve_split = true }, master = { new_status = "master" }, misc = { on_focus_under_fullscreen = 1, force_default_wallpaper = 0, disable_hyprland_logo = true }, input = { resolve_binds_by_sym = 1, kb_layout = "us, us", kb_variant = "colemak,", kb_options = "ctrl:nocaps, compose:ralt, grp:ctrls_toggle", follow_mouse = 1, sensitivity = 0, touchpad = { natural_scroll = false } }}) hl.device({ name = "epic-mouse-v1", sensitivity = -0.5 }) ----------------------------------------------------- -- Window Rules (from windowrules.conf) ----------------------------------------------------- -- XWayland dragging hl.window_rule({ no_focus = true, match = { xwayland = true, float = true, fullscreen = false, pin = false } }) -- Floating rules local float_class_regex = "(gcr-prompter|qt5ct|qt6ct|simple-scan|espanso|nm-applet)" local float_title_regex = "(\"HP Device Manager - Plug-in Installer\")" local float_regex = "(" .. float_class_regex .. "|" .. float_title_regex .. ")" hl.window_rule({ float = true, match = { class = float_class_regex } }) hl.window_rule({ float = true, match = { title = float_title_regex } }) -- Pin rules local pin_regex = "(gcr-prompter|nm-applet)" hl.window_rule({ pin = true, match = { class = pin_regex } }) -- Maximize everything else (fixed typo fioat_regex -> float_regex) hl.window_rule({ maximize = true, match = { class = "negative:" .. float_regex } }) -- Espanso on special hl.window_rule({ workspace = "special", match = { title = "Espanso Sync Tool" } }) -- App-specific workspaces local browsers = "(.*qutebrowser.*|.*[Ff]irefox.*)" local meeting = "(.*[Zz]oom.*)" hl.window_rule({ workspace = "name:shell", match = { class = ".*[Aa]lacritty.*" } }) hl.window_rule({ workspace = "name:browser silent", match = { class = browsers } }) hl.window_rule({ workspace = "name:jobs silent", match = { class = ".*[Vv]ivaldi-stable.*" } }) hl.window_rule({ workspace = "name:meeting silent", match = { class = meeting } }) ----------------------------------------------------- -- Workspaces (from workspaces.conf) ----------------------------------------------------- require("workspaces") ----------------------------------------------------- -- Keybindings & Macros (from keybindings.conf & macros.conf) ----------------------------------------------------- local bind = hl.bind local dsp = hl.dsp local fn = require("functions") bind("SUPER + Q", dsp.exec_cmd("hyprctl reload && killall -SIGUSR2 waybar && notify-send 'Hyprland' 'Config Reloaded' -u low -t 2000")) -- BUG FIX: SUPER + SHIFT + Q was bound to both tmux kill and uwsm stop. -- bind("SUPER + SHIFT + Q", dsp.exec_cmd("tmux kill-server")) bind("SUPER + SHIFT + Q", dsp.exec_cmd("killall -q signal-desktop; uwsm stop")) bind("CTRL + ALT + Delete", dsp.exec_cmd("bash ~/.config/hypr/scripts/sysmenu.sh")) bind("SUPER + L", dsp.exec_cmd("hyprlock")) bind("switch:Lid Switch", dsp.exec_cmd("hyprlock")) -- Screenshots (evaluated natively in Lua at keypress time) bind("CTRL + SHIFT + 3", function() local cmd = string.format("grim 'images/screenshots/%s_screenshot.png' && paplay ~/wav/camera.wav", os.date("%FT%H%M%S")) hl.dispatch(hl.dsp.exec_cmd(cmd)) end) bind("CTRL + SHIFT + 4", function() local cmd = string.format("slurp | grim -g - '%s_screenshot.png' && paplay ~/wav/camera.wav", os.date("%FT%H%M%S")) hl.dispatch(hl.dsp.exec_cmd(cmd)) end) -- App launchers using our custom Lua focusOrLaunch function bind("SUPER + return", function() fn.focusOrLaunch("alacritty", "Alacritty") end) bind("SUPER + SHIFT + A", function() fn.focusOrLaunch("slack", "Slack", "Slack") end) bind("SUPER + SHIFT + D", function() fn.focusOrLaunch("gnome-dictionary", "org.gnome.Dictionary", "org.gnome.Dictionary") end) bind("SUPER + G", function() fn.focusOrLaunch("vivaldi-stable", "vivaldi-stable", "vivaldi-stable") end) bind("SUPER + ALT + H", function() fn.focusOrLaunch("qutebrowser", "org.qutebrowser.qutebrowser") end) -- Windows 11 equivalent shortcuts bind("SUPER + S", dsp.exec_cmd(launcher)) -- Win+S for Search/Launcher bind("SUPER + R", dsp.exec_cmd(launcher)) -- Win+R for Run bind("SUPER + E", dsp.exec_cmd("nautilus")) -- Win+E for Explorer bind("SUPER + V", dsp.exec_cmd("cliphist list | rofi -dmenu -p 'paste' | cliphist decode | " .. copy .. " && " .. paste)) -- Win+V for Clipboard bind("SUPER + SHIFT + S", function() fn.focusOrLaunch("pavucontrol", "org.pulseaudio.pavucontrol", "org.pulseaudio.pavucontrol") end) -- Window control bind("SUPER + C", dsp.window.close()) bind("ALT + F4", dsp.window.close()) bind("SUPER + T", dsp.window.float({ action = "toggle" })) bind("SUPER + space", dsp.window.fullscreen({ mode = 1 })) -- Cycle Layouts local layouts = { "dwindle", "master", "scrolling" } local layout_icons = { dwindle = "", master = "", scrolling = "" } local layout_idx = 1 local function cycle_layout() layout_idx = (layout_idx % #layouts) + 1 local new_layout = layouts[layout_idx] hl.config({ general = { layout = new_layout } }) os.execute("echo '" .. layout_icons[new_layout] .. "' > /tmp/hypr_layout.txt") os.execute("pkill -RTMIN+8 waybar") end bind("SUPER + right", function() cycle_layout() end) bind("SUPER + left", function() cycle_layout() end) bind("SUPER + up", dsp.window.fullscreen({ mode = 1 })) bind("SUPER + down", hl.dsp.window.cycle_next()) -- XMonad-style cycle & Alt+Tab (using native dsp dispatchers) bind("SUPER + J", hl.dsp.window.cycle_next()) bind("SUPER + K", hl.dsp.window.cycle_next({ prev = true })) bind("ALT + Tab", hl.dsp.window.cycle_next()) bind("ALT + SHIFT + Tab", hl.dsp.window.cycle_next({ prev = true })) bind("SUPER + X", dsp.exec_cmd("dunstctl close")) bind("SUPER + Y", dsp.exec_cmd("dunstctl close-all")) -- Workspace control bind("SUPER + CTRL + right", function() hl.dispatch(hl.dsp.focus({ workspace = "m+1" })) end) bind("SUPER + CTRL + left", function() hl.dispatch(hl.dsp.focus({ workspace = "m-1" })) end) bind("SUPER + SHIFT + H", function() hl.dispatch(hl.dsp.focus({ workspace = "m-1" })) end) bind("SUPER + SHIFT + L", function() hl.dispatch(hl.dsp.focus({ workspace = "m+1" })) end) bind("SUPER + SHIFT + M", function() fn.mv2workspace() end) bind("SUPER + SHIFT + N", function() fn.createWorkspace() end) bind("SUPER + SHIFT + X", function() fn.deleteWorkspace() end) bind("SUPER + SHIFT + Z", function() fn.createWorkspace(fn.getActiveWorkspaceName()) end) bind("SUPER + SHIFT + left", function() fn.moveWorkspace(-1) end) bind("SUPER + SHIFT + right", function() fn.moveWorkspace(1) end) bind("SUPER + ALT + DOWN", function() fn.moveWorkspace(nil, "DP-8") end) -- Laptop keys bind("XF86MonBrightnessUp", dsp.exec_cmd("brightnessctl -- set +10%")) bind("XF86MonBrightnessDown", dsp.exec_cmd("brightnessctl -- set -10%")) -- Macros (uses fn.pasteText and native Lua os.time/os.date instead of bash scripts) bind("SUPER + CTRL + S", function() fn.pasteText(os.date("%F")) end) bind("SUPER + CTRL + N", function() fn.pasteText(os.date("%FT%T %z")) end) bind("SUPER + CTRL + Y", function() fn.pasteText(os.date("%F", os.time() - 86400)) end) bind("SUPER + CTRL + T", function() fn.pasteText(os.date("%F", os.time() + 86400)) end) -- Timetracker Macro bind("CTRL + SHIFT + S", function() fn.timetracker() end) -- Bitwarden Macro bind("SUPER + CTRL + 1", function() fn.pasteMacro("secret-tool lookup app bw") end) ----------------------------------------------------- -- Autostart (from autostart.conf) ----------------------------------------------------- hl.on("hyprland.start", function() hl.exec_cmd("dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP") hl.exec_cmd("hyprpolkitagent") hl.exec_cmd("uwsm app -- hypridle") hl.exec_cmd("uwsm app -- hyprpaper") hl.exec_cmd("uwsm app -- waybar") hl.exec_cmd("uwsm app -- espanso start") hl.exec_cmd("uwsm app -- dunst") hl.exec_cmd("nm-applet") hl.exec_cmd("signal-desktop") hl.exec_cmd("hp-systray") hl.exec_cmd("blueman-applet") hl.exec_cmd("wl-paste --watch cliphist store") hl.exec_cmd("wl-clip-persist --clipboard regular") hl.exec_cmd("qutebrowser") hl.exec_cmd("vivaldi-stable") hl.exec_cmd("alacritty") -- Start the battery low-level notifier hl.exec_cmd("bash ~/.config/hypr/scripts/battery-notify.sh") -- Randomize wallpapers after hyprpaper has time to start hl.exec_cmd("sleep 2 && hyprctl eval 'require(\"functions\").randomizeWallpaper()'") end)