diff --git a/modules/home/hyprland.nix b/modules/home/hyprland.nix index def6785..9fb0d63 100644 --- a/modules/home/hyprland.nix +++ b/modules/home/hyprland.nix @@ -6,9 +6,14 @@ }: let cfg = config.northstar.home.hyprland; + noctaliaAutostart = lib.optionalString config.programs.noctalia-shell.enable '' + hl.on("hyprland.start", function() + hl.exec_cmd("noctalia-shell") + end) + ''; in { - options.northstar.home.hyprland.enable = lib.mkEnableOption "Hyprland Home Manager configuration"; + options.northstar.home.hyprland.enable = lib.mkEnableOption "Hyprland Lua configuration"; config = lib.mkIf cfg.enable { home.packages = with pkgs; [ @@ -16,184 +21,178 @@ in playerctl ]; - wayland.windowManager.hyprland = { - enable = true; - package = null; - portalPackage = null; - configType = "lua"; - - settings = { - "$terminal" = "kitty"; - "$fileManager" = "kitty -e yazi"; - "$menu" = "fuzzel"; - "$mainMod" = "SUPER"; - - monitor = [ - ",preferred,auto,1.20" - ]; - - exec-once = lib.optionals config.programs.noctalia-shell.enable [ - "noctalia-shell" - ]; - - env = [ - "XCURSOR_SIZE,20" - "HYPRCURSOR_SIZE,20" - ]; - - general = { - gaps_in = 3; - gaps_out = 10; - border_size = 2; - "col.active_border" = "rgba(33ccffee) rgba(00ff99ee) 45deg"; - "col.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" - "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 = { - pseudotile = true; - preserve_split = true; - }; - - master = { - new_status = "master"; - }; - - misc = { - force_default_wallpaper = 0; - disable_hyprland_logo = true; - }; - - input = { - kb_layout = "us"; - kb_variant = ""; - kb_model = ""; - kb_options = ""; - kb_rules = ""; - follow_mouse = 1; - sensitivity = 0; - - touchpad = { - natural_scroll = false; - }; - }; - - gesture = [ - "3, horizontal, workspace" - ]; - - bind = [ - "$mainMod, Q, exec, $terminal" - "$mainMod, C, killactive," - "$mainMod, M, exit," - "$mainMod, E, exec, $fileManager" - "$mainMod, V, togglefloating," - "$mainMod, R, exec, $menu" - "$mainMod, P, pseudo," - "$mainMod, J, layoutmsg, togglesplit" - "$mainMod, left, movefocus, l" - "$mainMod, right, movefocus, r" - "$mainMod, up, movefocus, u" - "$mainMod, down, movefocus, d" - "$mainMod, 1, workspace, 1" - "$mainMod, 2, workspace, 2" - "$mainMod, 3, workspace, 3" - "$mainMod, 4, workspace, 4" - "$mainMod, 5, workspace, 5" - "$mainMod, 6, workspace, 6" - "$mainMod, 7, workspace, 7" - "$mainMod, 8, workspace, 8" - "$mainMod, 9, workspace, 9" - "$mainMod, 0, workspace, 10" - "$mainMod SHIFT, 1, movetoworkspace, 1" - "$mainMod SHIFT, 2, movetoworkspace, 2" - "$mainMod SHIFT, 3, movetoworkspace, 3" - "$mainMod SHIFT, 4, movetoworkspace, 4" - "$mainMod SHIFT, 5, movetoworkspace, 5" - "$mainMod SHIFT, 6, movetoworkspace, 6" - "$mainMod SHIFT, 7, movetoworkspace, 7" - "$mainMod SHIFT, 8, movetoworkspace, 8" - "$mainMod SHIFT, 9, movetoworkspace, 9" - "$mainMod SHIFT, 0, movetoworkspace, 10" - "$mainMod, S, togglespecialworkspace, magic" - "$mainMod SHIFT, S, movetoworkspace, special:magic" - "$mainMod, mouse_down, workspace, e+1" - "$mainMod, mouse_up, workspace, e-1" - ]; - - bindm = [ - "$mainMod, mouse:272, movewindow" - "$mainMod, mouse:273, resizewindow" - ]; - - bindel = [ - ",XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+" - ",XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-" - ",XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle" - ",XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle" - ",XF86MonBrightnessUp, exec, brightnessctl -e4 -n2 set 5%+" - ",XF86MonBrightnessDown, exec, brightnessctl -e4 -n2 set 5%-" - ]; - - bindl = [ - ", XF86AudioNext, exec, playerctl next" - ", XF86AudioPause, exec, playerctl play-pause" - ", XF86AudioPlay, exec, playerctl play-pause" - ", XF86AudioPrev, exec, playerctl previous" - ]; - }; - }; + xdg.configFile."hypr/hyprland.lua".text = '' + -- Managed by Northstar. Hyprland 0.55+ loads this before hyprland.conf. + -- Based on Hyprland's default Lua example, with Noctalia owning shell and wallpapers. + + hl.monitor({ + output = "", + mode = "preferred", + position = "auto", + scale = 1.20, + }) + + local terminal = "kitty" + local fileManager = "kitty -e yazi" + local menu = "fuzzel" + local mainMod = "SUPER" + + hl.env("XCURSOR_SIZE", "20") + hl.env("HYPRCURSOR_SIZE", "20") + + hl.on("hyprland.start", function() + hl.exec_cmd("dbus-update-activation-environment --systemd DISPLAY HYPRLAND_INSTANCE_SIGNATURE WAYLAND_DISPLAY XDG_CURRENT_DESKTOP XDG_SESSION_TYPE && systemctl --user stop hyprland-session.target && systemctl --user start hyprland-session.target") + end) + + ${noctaliaAutostart} + + hl.config({ + general = { + gaps_in = 3, + gaps_out = 10, + border_size = 2, + col = { + active_border = { colors = { "rgba(33ccffee)", "rgba(00ff99ee)" }, angle = 45 }, + 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 = 0xee1a1a1a, + }, + blur = { + enabled = true, + size = 3, + passes = 1, + vibrancy = 0.1696, + }, + }, + animations = { + enabled = true, + }, + dwindle = { + preserve_split = true, + pseudotile = true, + }, + master = { + new_status = "master", + }, + misc = { + force_default_wallpaper = 0, + disable_hyprland_logo = true, + }, + input = { + kb_layout = "us", + kb_variant = "", + kb_model = "", + kb_options = "", + kb_rules = "", + follow_mouse = 1, + sensitivity = 0, + touchpad = { + natural_scroll = false, + }, + }, + }) + + 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 } } }) + hl.curve("easy", { type = "spring", mass = 1, stiffness = 71.2633, dampening = 15.8273644 }) + + 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, spring = "easy" }) + hl.animation({ leaf = "windowsIn", enabled = true, speed = 4.1, spring = "easy", style = "popin 87%" }) + hl.animation({ leaf = "windowsOut", enabled = true, speed = 1.49, bezier = "linear", style = "popin 87%" }) + 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 = "fade" }) + hl.animation({ leaf = "workspacesIn", enabled = true, speed = 1.21, bezier = "almostLinear", style = "fade" }) + hl.animation({ leaf = "workspacesOut", enabled = true, speed = 1.94, bezier = "almostLinear", style = "fade" }) + hl.animation({ leaf = "zoomFactor", enabled = true, speed = 7, bezier = "quick" }) + + hl.gesture({ + fingers = 3, + direction = "horizontal", + action = "workspace", + }) + + hl.bind(mainMod .. " + Q", hl.dsp.exec_cmd(terminal)) + hl.bind(mainMod .. " + C", hl.dsp.window.close()) + hl.bind(mainMod .. " + M", hl.dsp.exit()) + hl.bind(mainMod .. " + E", hl.dsp.exec_cmd(fileManager)) + hl.bind(mainMod .. " + V", hl.dsp.window.float({ action = "toggle" })) + hl.bind(mainMod .. " + R", hl.dsp.exec_cmd(menu)) + hl.bind(mainMod .. " + P", hl.dsp.window.pseudo()) + hl.bind(mainMod .. " + J", hl.dsp.layout("togglesplit")) + + hl.bind(mainMod .. " + left", hl.dsp.focus({ direction = "left" })) + hl.bind(mainMod .. " + right", hl.dsp.focus({ direction = "right" })) + hl.bind(mainMod .. " + up", hl.dsp.focus({ direction = "up" })) + hl.bind(mainMod .. " + down", hl.dsp.focus({ direction = "down" })) + + for i = 1, 10 do + local key = i % 10 + hl.bind(mainMod .. " + " .. key, hl.dsp.focus({ workspace = i })) + hl.bind(mainMod .. " + SHIFT + " .. key, hl.dsp.window.move({ workspace = i })) + end + + hl.bind(mainMod .. " + S", hl.dsp.workspace.toggle_special("magic")) + hl.bind(mainMod .. " + SHIFT + S", hl.dsp.window.move({ workspace = "special:magic" })) + + hl.bind(mainMod .. " + mouse_down", hl.dsp.focus({ workspace = "e+1" })) + hl.bind(mainMod .. " + mouse_up", hl.dsp.focus({ workspace = "e-1" })) + hl.bind(mainMod .. " + mouse:272", hl.dsp.window.drag(), { mouse = true }) + hl.bind(mainMod .. " + mouse:273", hl.dsp.window.resize(), { mouse = true }) + + hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd("wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+"), { locked = true, repeating = true }) + hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"), { locked = true, repeating = true }) + hl.bind("XF86AudioMute", hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"), { locked = true, repeating = true }) + hl.bind("XF86AudioMicMute", hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"), { locked = true, repeating = true }) + hl.bind("XF86MonBrightnessUp", hl.dsp.exec_cmd("brightnessctl -e4 -n2 set 5%+"), { locked = true, repeating = true }) + hl.bind("XF86MonBrightnessDown", hl.dsp.exec_cmd("brightnessctl -e4 -n2 set 5%-"), { locked = true, repeating = true }) + hl.bind("XF86AudioNext", hl.dsp.exec_cmd("playerctl next"), { locked = true }) + hl.bind("XF86AudioPause", hl.dsp.exec_cmd("playerctl play-pause"), { locked = true }) + hl.bind("XF86AudioPlay", hl.dsp.exec_cmd("playerctl play-pause"), { locked = true }) + hl.bind("XF86AudioPrev", hl.dsp.exec_cmd("playerctl previous"), { locked = true }) + + hl.window_rule({ + name = "suppress-maximize-events", + match = { class = ".*" }, + suppress_event = "maximize", + }) + + hl.window_rule({ + name = "fix-xwayland-drags", + match = { + class = "^$", + title = "^$", + xwayland = true, + float = true, + fullscreen = false, + pin = false, + }, + no_focus = true, + }) + ''; }; }