333 lines
14 KiB
Nix
333 lines
14 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
let
|
|
dotfiles = "${config.home.homeDirectory}/ndots/modules/home-manager/hyprland/hypr";
|
|
in
|
|
{
|
|
options.custom.hyprland.enable = lib.mkEnableOption "Hyprland user config";
|
|
|
|
config = lib.mkIf config.custom.hyprland.enable {
|
|
|
|
systemd.user.targets.hyprland-session = {
|
|
Unit = {
|
|
Description = "hyprland compositor session";
|
|
BindsTo = [ "graphical-session.target" ];
|
|
Wants = [ "graphical-session-pre.target" ];
|
|
After = [ "graphical-session-pre.target" ];
|
|
};
|
|
};
|
|
wayland.windowManager.hyprland.settings.input.numlock_by_default = true;
|
|
|
|
xdg.configFile."hypr/hyprland.lua".text = ''
|
|
local home = os.getenv("HOME")
|
|
local config_dir = home .. "/.config/hypr"
|
|
package.path = config_dir .. "/?.lua;" .. config_dir .. "/?/init.lua;" .. package.path
|
|
|
|
-- Monitors ----------------------------------------
|
|
hl.monitor({
|
|
output = "DP-1",
|
|
mode = "1920x1080@239.96Hz",
|
|
position = "1080x0",
|
|
scale = 1,
|
|
})
|
|
|
|
-- Looks ----------------------------------------
|
|
hl.env("HYPRCURSOR_THEME", "Bibata-Modern-Ice-Right")
|
|
hl.env("HYPRCURSOR_SIZE", "24")
|
|
|
|
hl.config({
|
|
input = {
|
|
kb_layout = "us,us",
|
|
kb_variant = ",intl",
|
|
kb_options = "grp:alt_shift_toggle",
|
|
},
|
|
general = {
|
|
gaps_in = 7,
|
|
gaps_out = 10,
|
|
border_size = 2,
|
|
col = {
|
|
active_border = "rgba(ebcc71ff)",
|
|
inactive_border = "rgba(54461eff)",
|
|
},
|
|
layout = "dwindle",
|
|
},
|
|
scrolling = {
|
|
fullscreen_on_one_column = true,
|
|
column_width = 0.95,
|
|
focus_fit_method = 0,
|
|
},
|
|
dwindle = {
|
|
preserve_split = true,
|
|
},
|
|
master = {
|
|
new_status = "slave",
|
|
allow_small_split = false,
|
|
special_scale_factor = 0.75,
|
|
mfact = 0.40,
|
|
orientation = "center",
|
|
new_on_top = true,
|
|
},
|
|
})
|
|
|
|
hl.device({
|
|
name = "8bitdo-retro-18-numpad-keyboard",
|
|
kb_options = "numpad:mac",
|
|
numlock_by_default = true,
|
|
})
|
|
|
|
hl.config({
|
|
decoration = {
|
|
rounding = 15,
|
|
rounding_power = 2,
|
|
active_opacity = 1.0,
|
|
inactive_opacity = 0.75,
|
|
fullscreen_opacity = 1.0,
|
|
blur = {
|
|
enabled = true,
|
|
size = 1,
|
|
passes = 2,
|
|
new_optimizations = true,
|
|
vibrancy = 0.5,
|
|
vibrancy_darkness = 0.2,
|
|
},
|
|
shadow = {
|
|
enabled = true,
|
|
range = 15,
|
|
render_power = 3,
|
|
color = "rgba(121212aa)",
|
|
},
|
|
},
|
|
})
|
|
|
|
hl.layer_rule({
|
|
name = "swaync-control-center-blur",
|
|
match = { namespace = "swaync-control-center" },
|
|
blur = true,
|
|
dim_around = true,
|
|
ignore_alpha = 0.5,
|
|
no_screen_share = true,
|
|
})
|
|
hl.layer_rule({
|
|
name = "swaync-notification-blur",
|
|
match = { namespace = "swaync-notification-window" },
|
|
blur = true,
|
|
ignore_alpha = 0.5,
|
|
no_screen_share = true,
|
|
})
|
|
|
|
-- Animations ----------------------------------------
|
|
hl.config({ animations = { enabled = true } })
|
|
|
|
-- Bezier curves
|
|
hl.curve("easeOutQuint", { type = "bezier", points = { { 0.23, 1 }, { 0.32, 1 } } })
|
|
hl.curve("easeInOutCubic", { type = "bezier", points = { { 0.65, 0.05 }, { 0.36, 1 } } })
|
|
hl.curve("linear", { type = "bezier", points = { { 0, 0 }, { 1, 1 } } })
|
|
hl.curve("almostLinear", { type = "bezier", points = { { 0.5, 0.5 }, { 0.75, 1 } } })
|
|
hl.curve("quick", { type = "bezier", points = { { 0.15, 0 }, { 0.1, 1 } } })
|
|
|
|
-- Animations
|
|
hl.animation({ leaf = "global", enabled = true, speed = 10, bezier = "default" })
|
|
hl.animation({ leaf = "border", enabled = true, speed = 5.39, bezier = "easeOutQuint" })
|
|
hl.animation({ leaf = "windows", enabled = true, speed = 4.79, bezier = "easeOutQuint" })
|
|
hl.animation({ leaf = "windowsIn", enabled = true, speed = 4.1, bezier = "easeOutQuint", style = "popin 95%" })
|
|
hl.animation({ leaf = "windowsOut", enabled = true, speed = 1.49, bezier = "linear", style = "popin 95%" })
|
|
hl.animation({ leaf = "fadeIn", enabled = true, speed = 1.73, bezier = "almostLinear" })
|
|
hl.animation({ leaf = "fadeOut", enabled = true, speed = 1.46, bezier = "almostLinear" })
|
|
hl.animation({ leaf = "fade", enabled = true, speed = 3.03, bezier = "quick" })
|
|
hl.animation({ leaf = "layers", enabled = true, speed = 3.81, bezier = "easeOutQuint" })
|
|
hl.animation({ leaf = "layersIn", enabled = true, speed = 4, bezier = "easeOutQuint", style = "fade" })
|
|
hl.animation({ leaf = "layersOut", enabled = true, speed = 1.5, bezier = "linear", style = "fade" })
|
|
hl.animation({ leaf = "fadeLayersIn", enabled = true, speed = 1.79, bezier = "almostLinear" })
|
|
hl.animation({ leaf = "fadeLayersOut", enabled = true, speed = 1.39, bezier = "almostLinear" })
|
|
hl.animation({ leaf = "workspaces", enabled = true, speed = 1.94, bezier = "almostLinear", style = "slidefade 10%" })
|
|
hl.animation({ leaf = "workspacesIn", enabled = true, speed = 1.21, bezier = "almostLinear", style = "slidefade 10%" })
|
|
hl.animation({ leaf = "workspacesOut", enabled = true, speed = 1.94, bezier = "almostLinear", style = "slidefade 10%" })
|
|
|
|
-- Autostart ----------------------------------------
|
|
hl.on("hyprland.start", function()
|
|
hl.exec_cmd("dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE")
|
|
hl.exec_cmd("systemctl --user start hyprland-session.target")
|
|
hl.exec_cmd("waybar")
|
|
hl.exec_cmd("hypridle")
|
|
hl.exec_cmd("swaync")
|
|
hl.exec_cmd("hyprctl setcursor Bibata-Modern-Ice-Right 24")
|
|
end)
|
|
|
|
-- Programs ----------------------------------------
|
|
local p = {
|
|
terminal = "alacritty",
|
|
file_manager = "thunar",
|
|
menu = "pkill rofi || " .. home .. "/.config/rofi/launchers/type-7/launcher.sh",
|
|
logout_menu = "wlogout -b 5 -T 400 -B 400",
|
|
toggle_notifications = "swaync-client -t -sw",
|
|
screen_ocr = home .. "/.local/bin/read-screen",
|
|
}
|
|
|
|
-- Binds ----------------------------------------
|
|
local mod = "SUPER"
|
|
local mod_shft = "SUPER + SHIFT"
|
|
local mod_ctrl = "SUPER + CTRL"
|
|
local mod_alt = "SUPER + ALT"
|
|
|
|
-- ---------- App launchers / global actions ----------
|
|
hl.bind(mod .. " + Return", hl.dsp.exec_cmd(p.terminal))
|
|
hl.bind(mod .. " + Q", hl.dsp.window.close())
|
|
hl.bind(mod_shft .. " + Q", hl.dsp.exec_cmd("killall zoom"))
|
|
hl.bind(mod .. " + E", hl.dsp.exec_cmd(p.file_manager))
|
|
hl.bind(mod .. " + V", hl.dsp.window.float({ action = "toggle" }))
|
|
hl.bind(mod .. " + F", hl.dsp.window.fullscreen())
|
|
hl.bind(mod .. " + M", hl.dsp.layout("togglesplit")) -- dwindle
|
|
hl.bind(mod .. " + N", hl.dsp.exec_cmd(p.toggle_notifications))
|
|
hl.bind(mod .. " + Space", hl.dsp.exec_cmd(p.menu))
|
|
hl.bind("CTRL + ALT + DELETE", hl.dsp.exec_cmd(p.logout_menu))
|
|
|
|
-- ---------- Focus movement (vim) ----------
|
|
hl.bind(mod .. " + H", hl.dsp.focus({ direction = "left" }))
|
|
hl.bind(mod .. " + L", hl.dsp.focus({ direction = "right" }))
|
|
hl.bind(mod .. " + K", hl.dsp.focus({ direction = "up" }))
|
|
hl.bind(mod .. " + J", hl.dsp.focus({ direction = "down" }))
|
|
|
|
-- ---------- Move window ----------
|
|
hl.bind(mod_shft .. " + H", hl.dsp.window.move({ direction = "left" }))
|
|
hl.bind(mod_shft .. " + L", hl.dsp.window.move({ direction = "right" }))
|
|
hl.bind(mod_shft .. " + K", hl.dsp.window.move({ direction = "up" }))
|
|
hl.bind(mod_shft .. " + J", hl.dsp.window.move({ direction = "down" }))
|
|
|
|
-- ---------- Splitratio (dwindle layoutmsg) ----------
|
|
hl.bind(mod .. " + comma", hl.dsp.layout("splitratio -0.1"))
|
|
hl.bind(mod .. " + period", hl.dsp.layout("splitratio 0.1"))
|
|
|
|
-- ---------- Workspaces (Y U I O P -> 1..5) ----------
|
|
local ws_keys = { Y = 1, U = 2, I = 3, O = 4, P = 5 }
|
|
for key, ws in pairs(ws_keys) do
|
|
hl.bind(mod .. " + " .. key, hl.dsp.focus({ workspace = ws }))
|
|
hl.bind(mod_shft .. " + " .. key, hl.dsp.window.move({ workspace = ws }))
|
|
end
|
|
|
|
-- ---------- Special workspace (scratchpad) ----------
|
|
hl.bind(mod .. " + S", hl.dsp.workspace.toggle_special("magic"))
|
|
hl.bind(mod_shft .. " + S", hl.dsp.window.move({ workspace = "special:magic" }))
|
|
|
|
-- ---------- Workspace scroll ----------
|
|
hl.bind(mod .. " + mouse_down", hl.dsp.focus({ workspace = "e+1" }))
|
|
hl.bind(mod .. " + mouse_up", hl.dsp.focus({ workspace = "e-1" }))
|
|
|
|
-- ---------- Mouse drag/resize ----------
|
|
hl.bind(mod .. " + mouse:272", hl.dsp.window.drag(), { mouse = true })
|
|
hl.bind(mod .. " + mouse:273", hl.dsp.window.resize(), { mouse = true })
|
|
|
|
-- ---------- Multimedia (locked + repeating) ----------
|
|
local el = { locked = true, repeating = true }
|
|
hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+"), el)
|
|
hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"), el)
|
|
hl.bind("XF86AudioMute", hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"), el)
|
|
hl.bind("XF86AudioMicMute", hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"), el)
|
|
hl.bind("XF86MonBrightnessUp", hl.dsp.exec_cmd("brightnessctl s 10%+"), el)
|
|
hl.bind("XF86MonBrightnessDown", hl.dsp.exec_cmd("brightnessctl s 10%-"), el)
|
|
|
|
-- ---------- Media (locked, no repeat) ----------
|
|
local l = { locked = true }
|
|
hl.bind("XF86AudioNext", hl.dsp.exec_cmd("playerctl next"), l)
|
|
hl.bind("XF86AudioPause", hl.dsp.exec_cmd("playerctl play-pause"), l)
|
|
hl.bind("XF86AudioPlay", hl.dsp.exec_cmd("playerctl play-pause"), l)
|
|
hl.bind("XF86AudioPrev", hl.dsp.exec_cmd("playerctl previous"), l)
|
|
|
|
-- ---------- Screenshots ----------
|
|
hl.bind(mod_shft .. " + 2", hl.dsp.exec_cmd("hyprshot -m output -m DP-1 -o ~/Pictures/Screenshots"))
|
|
hl.bind(mod_shft .. " + 3", hl.dsp.exec_cmd("hyprshot -m window -m active -o ~/Pictures/Screenshots"))
|
|
hl.bind(mod_shft .. " + 4", hl.dsp.exec_cmd("hyprshot -m region -o ~/Pictures/Screenshots"))
|
|
|
|
-- ---------- OBS Recording ----------
|
|
hl.bind(mod_shft .. " + 9", hl.dsp.exec_cmd("obs-cmd recording toggle"))
|
|
hl.bind(mod .. " + 9", hl.dsp.exec_cmd("obs-cmd recording toggle-pause"))
|
|
|
|
-- Disable animations on the screenshot selection layer
|
|
hl.layer_rule({
|
|
name = "no-anim-selection",
|
|
match = { namespace = "selection" },
|
|
no_anim = true,
|
|
})
|
|
|
|
hl.bind(mod_shft .. " + 0", hl.dsp.exec_cmd(p.screen_ocr))
|
|
|
|
-- ---------- Lock / suspend ----------
|
|
hl.bind(mod_alt .. " + L", hl.dsp.exec_cmd("hyprlock"))
|
|
hl.bind(mod .. " + ALT + CTRL + L", hl.dsp.exec_cmd("systemctl suspend"))
|
|
|
|
-- ---------- Waybar reload ----------
|
|
hl.bind(mod_alt .. " + R", hl.dsp.exec_cmd("/home/jpporta/.config/waybar/scripts/launch.sh"))
|
|
|
|
-- ---------- Dictation ----------
|
|
hl.bind(mod .. " + code:71", hl.dsp.exec_cmd("dictate-toggle"))
|
|
hl.bind(mod .. " + code:72", hl.dsp.exec_cmd("dictate-history"))
|
|
hl.bind(mod_shft .. " + code:71", hl.dsp.exec_cmd("dictate-toggle -c"))
|
|
-- ---------- misc ----------
|
|
hl.config({
|
|
misc = {
|
|
force_default_wallpaper = 0,
|
|
disable_hyprland_logo = true,
|
|
},
|
|
})
|
|
|
|
-- ---------- window rules ----------
|
|
-- Zoom Behave -----------
|
|
hl.window_rule({
|
|
match = { class = "^zoom$", title = "^annotate_toolbar$" },
|
|
float = true,
|
|
})
|
|
hl.window_rule({
|
|
match = { class = "^zoom$" },
|
|
no_blur = true,
|
|
border_size = 0,
|
|
no_initial_focus = true,
|
|
no_shadow = true,
|
|
})
|
|
|
|
-- Ignore maximize requests from apps.
|
|
hl.window_rule({
|
|
name = "Ignore Maximize Requests",
|
|
match = { class = ".*" },
|
|
suppress_event = "maximize",
|
|
})
|
|
|
|
-- Fix some dragging issues with XWayland.
|
|
hl.window_rule({
|
|
name = "XWayland Drag Fix",
|
|
match = {
|
|
xwayland = 1,
|
|
title = "^$",
|
|
class = "^$",
|
|
float = true,
|
|
fullscreen = false,
|
|
pin = false,
|
|
},
|
|
no_focus = true,
|
|
})
|
|
|
|
hl.window_rule({
|
|
name = "Pinentry Center",
|
|
match = { class = "^(pinentry-.*)$" },
|
|
float = true,
|
|
center = true,
|
|
stay_focused = true,
|
|
})
|
|
|
|
-- Picture-in-Picture: pinned floating mini-player in bottom-right quadrant.
|
|
hl.window_rule({
|
|
name = "PIP",
|
|
match = { title = "Picture-in-Picture" },
|
|
pin = 1,
|
|
float = 1,
|
|
size = "(monitor_w/4) (monitor_h/4)",
|
|
move = "(3*monitor_w/4)-22 (monitor_h-window_h-22)",
|
|
})
|
|
|
|
hl.env("QT_QPA_PLATFORMTHEME", "hyprqt6engine")
|
|
'';
|
|
};
|
|
}
|