{ config, lib, pkgs, ... }: with lib; let cfg = config.mjallen.programs.hyprland; drawer = "nwg-drawer -fm nautilus -term kitty -mb 10 -mt 10 -ml 10 -mr 10 -pbuseicontheme -i ${cfg.iconThemeName}"; in { imports = [ ./options.nix ./theme.nix ]; config = mkIf cfg.enable { # Home packages home.packages = with pkgs; [ box64 brightnessctl ddcutil dunst egl-wayland file-roller glib gnome-calculator gnome-calendar gnome-disk-utility gnome-firmware gnome-firmware-updater gnome-font-viewer gnome-logs gnome-photos gnome-tweaks gnome-weather gsettings-desktop-schemas hyprcursor hyprland hyprpaper hyprshot hyprsysteminfo kdePackages.qtmultimedia libnotify libz mako meson nautilus networkmanagerapplet nomacs nwg-look overskride pamixer pavucontrol playerctl polkit polkit_gnome qt5.qtwayland qt6.qtwayland rofi waybar wayland-protocols wayland-utils waypaper wev wl-clipboard wlogout wlroots xdg-desktop-portal-hyprland xdg-desktop-portal-gtk xdg-desktop-portal-wlr xorg.xhost xsettingsd xwayland pkgs.mjallen.pipewire-python ]; # Session variables home.sessionVariables = { BROWSER = "${cfg.defaultApps.browser.pname}"; CLUTTER_BACKEND = "wayland"; EDITOR = "${cfg.defaultApps.editor.pname}"; VISUAL = "${cfg.defaultApps.visual.pname}"; ICON_THEME = cfg.iconThemeName; GTK_CSD = "0"; GTK_THEME = cfg.gtkThemeName; GTK_USE_PORTAL = "1"; HYPRCURSOR_THEME = config.home.pointerCursor.name; HYPRCURSOR_SIZE = config.home.pointerCursor.size; MOZ_ENABLE_WAYLAND = "1"; NIXOS_OZONE_WL = "1"; NIXOS_XDG_OPEN_USE_PORTAL = "1"; QT_AUTO_SCREEN_SCALE_FACTOR = "1"; QT_QPA_PLATFORM = "wayland-egl"; QT_QPA_PLATFORMTHEME = "gtk3"; QT_SCALE_FACTOR = "1"; QT_WAYLAND_DISABLE_WINDOWDECORATION = "1"; SDL_VIDEODRIVER = "wayland"; TERMINAL = "${cfg.defaultApps.terminal.pname}"; XCURSOR_THEME = config.home.pointerCursor.name; XCURSOR_SIZE = config.home.pointerCursor.size; XDG_CACHE_HOME = "\${HOME}/.cache"; XDG_CONFIG_HOME = "\${HOME}/.config"; XDG_CURRENT_DESKTOP = "Hyprland"; XDG_DATA_HOME = "\${HOME}/.local/share"; XDG_SESSION_DESKTOP = "Hyprland"; XDG_SESSION_TYPE = "wayland"; }; # Services services = { hyprpolkitagent.enable = true; hyprpaper = { enable = true; settings = { preload = [ "/run/wallpaper.jpg" ]; wallpaper = [ "DP-1, /run/wallpaper.jpg" "DP-2, /run/wallpaper.jpg" ]; splash = false; }; }; hypridle = { enable = true; settings = { general = { before_sleep_cmd = "loginctl lock-session"; # lock before suspend. after_sleep_cmd = "hyprctl dispatch dpms on"; # to avoid having to press a key twice to turn on the display. ignore_dbus_inhibit = false; lock_cmd = "pidof hyprlock || hyprlock"; # avoid starting multiple hyprlock instances. }; listener = [ # { # timeout = 300; # 5min # on-timeout = "brightnessctl -s set 10"; # set monitor backlight to minimum, avoid 0 on OLED monitor. # on-resume = "brightnessctl -r"; # monitor backlight restore. # } { timeout = 900; # 15 min on-timeout = "loginctl lock-session"; # lock screen when timeout has passed } { timeout = 930; # 15.5 min on-timeout = "hyprctl dispatch dpms off"; # screen off when timeout has passed on-resume = "hyprctl dispatch dpms on"; # screen on when activity is detected after timeout has fired. } { timeout = 3600; # 1hr on-timeout = "systemctl suspend"; # suspend pc } ]; }; }; }; # Programs programs = { vscode.profiles.default.userSettings."window"."titleBarStyle" = "custom"; hyprlock = { enable = true; settings = { background = [ { monitor = ""; path = "/run/wallpaper.jpg"; # supports png, jpg, webp (no animations, though) color = "rgba(25, 20, 20, 1.0)"; # all these options are taken from hyprland, see https://wiki.hyprland.org/Configuring/Variables/#blur for explanations blur_passes = "3"; # 0 disables blurring blur_size = "7"; noise = "0.0117"; contrast = "0.8916"; brightness = "0.8172"; vibrancy = "0.1696"; vibrancy_darkness = "0.0"; } ]; input-field = [ { size = "200, 50"; position = "0, -80"; monitor = "DP-1"; dots_center = true; fade_on_empty = true; font_color = "rgb(202, 211, 245)"; inner_color = "rgb(91, 96, 120)"; outer_color = "rgb(24, 25, 38)"; bothlock_color = -1; outline_thickness = 5; placeholder_text = ''Password...''; shadow_passes = 2; } ]; }; }; }; # Wayland configuration wayland.windowManager.hyprland = { enable = true; xwayland.enable = true; systemd.enable = true; plugins = with pkgs.hyprlandPlugins; [ # hyprgrass ]; settings = { "$mod" = "SUPER"; # Mouse # mouse_[up|down] - scroll wheel # middle_mouse - 274 # thumb_up - 276 # thumb_down - 275 # l -> locked, will also work when an input inhibitor (e.g. a lockscreen) is active. # r -> release, will trigger on release of a key. # e -> repeat, will repeat when held. # n -> non-consuming, key/mouse events will be passed to the active window in addition to triggering the dispatcher. # m -> mouse, see below. # t -> transparent, cannot be shadowed by other binds. # i -> ignore mods, will ignore modifiers. # s -> separate, will arbitrarily combine keys between each mod/key, see [Keysym combos](#keysym-combos) above. # d -> has description, will allow you to write a description for your bind. # p -> bypasses the app's requests to inhibit keybinds. # https://wiki.hyprland.org/Configuring/Binds/ # https://wiki.hyprland.org/Configuring/Binds/#mouse-buttons bind = [ "$mod, Return, exec, ${cfg.defaultApps.terminal.pname}" "$mod, SPACE, exec, wofi --show drun" ", xf86Search, exec, wofi --show drun" "$mod, Q, killactive, " "$mod, M, exec, wlogout --protocol layer-shell" "$mod, E, exec, ${cfg.defaultApps.fileExplorer.pname}" "$mod, V, togglefloating, " "$mod, D, exec, ${drawer}" "$mod, P, pseudo, " # dwindle "$mod, S, togglesplit, " # dwindle "$mod SHIFT, Q, exec, hyprlock" "$mod SHIFT, 4, exec, hyprshot -m region --clipboard-only" "$mod, F, fullscreen, 1" "$mod SHIFT, F, fullscreen, 0" "$mod SHIFT, E, exec, smile" "$mod, mouse:276, movecurrentworkspacetomonitor, ${cfg.display1.input}" "$mod, mouse:275, movecurrentworkspacetomonitor, ${cfg.display2.input}" # alt-tab between workspaces on active monitor "$mod, Tab, workspace, m+1" "$mod SHIFT, Tab, workspace, m-1" "$mod, h, movefocus, l" "$mod, l, movefocus, r" "$mod, k, movefocus, u" "$mod, j, movefocus, d" "$mod, 1, workspace, 1" "$mod, 2, workspace, 2" "$mod, 3, workspace, 3" "$mod, 4, workspace, 4" "$mod, 5, workspace, 5" "$mod, 6, workspace, 6" "$mod, 7, workspace, 7" "$mod, 8, workspace, 8" "$mod, 9, workspace, 9" "$mod, 0, workspace, 10" "$mod ALT, 1, movetoworkspace, 1" "$mod ALT, 2, movetoworkspace, 2" "$mod ALT, 3, movetoworkspace, 3" "$mod ALT, 4, movetoworkspace, 4" "$mod ALT, 5, movetoworkspace, 5" "$mod ALT, 6, movetoworkspace, 6" "$mod ALT, 7, movetoworkspace, 7" "$mod ALT, 8, movetoworkspace, 8" "$mod ALT, 9, movetoworkspace, 9" "$mod ALT, 0, movetoworkspace, discord" "$mod CTRL, l, resizeactive, 10 0" "$mod CTRL, h, resizeactive, -10 0" "$mod CTRL, k, resizeactive, 0 -10" "$mod CTRL, j, resizeactive, 0 10" "$mod SHIFT, l, movewindow, r" "$mod SHIFT, h, movewindow, l" "$mod SHIFT, k, movewindow, u" "$mod SHIFT, j, movewindow, d" "$mod, b, exec, ${cfg.defaultApps.browser.pname}" ]; bindm = [ # Move/resize windows with mod + LMB/RMB and dragging "$mod, mouse:272, movewindow" "$mod, mouse:273, resizewindow" # middle mouse will grab a window, mod + middle mouse will close it "$mod SHIFT, mouse:274, movewindow" ]; bindel = [ ", XF86AudioRaiseVolume, exec, wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%+" ", XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-" ]; bindl = [ ", XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle" ", XF86AudioPlay, exec, playerctl play-pause" ", XF86AudioPrev, exec, playerctl previous" ", XF86AudioNext, exec, playerctl next" ", XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle" ", XF86MonBrightnessUp, exec, brightnessctl set +5%" ", XF86MonBrightnessDown, exec, brightnessctl set 5%-" "$mod, XF86MonBrightnessUp, exec, brightnessctl -d kbd_backlight set +10%" "$mod, XF86MonBrightnessDown, exec, brightnessctl -d kbd_backlight set 10%-" ]; monitor = cfg.monitor; monitorv2 = cfg.monitorv2 or { }; render = { cm_fs_passthrough = 1; }; misc = { vrr = 1; force_default_wallpaper = 0; }; general = { gaps_in = 5; gaps_out = 10; border_size = 1; "col.active_border" = "rgb(8aadf4) rgb(24273A) rgb(24273A) rgb(8aadf4) 45deg"; "col.inactive_border" = "rgb(24273A) rgb(24273A) rgb(24273A) rgb(24273A) 45deg"; layout = "dwindle"; allow_tearing = true; }; decoration = { rounding = 10; blur = { enabled = true; size = 2; passes = 2; new_optimizations = true; xray = false; }; }; animations = { enabled = "yes"; bezier = [ "overshot, 0.05, 0.9, 0.1, 1.05" "smoothOut, 0.36, 0, 0.66, -0.56" "smoothIn, 0.25, 1, 0.5, 1" ]; animation = [ "windows, 1, 5, overshot, slide" "windowsOut, 1, 4, smoothOut, slide" "windowsMove, 1, 4, default" "border, 1, 10, default" "fade, 1, 10, smoothIn" "fadeDim, 1, 10, smoothIn" "workspaces, 1, 6, default" ]; }; dwindle = { pseudotile = "yes"; preserve_split = "yes"; }; workspace = cfg.workspace; windowrule = [ "float, title:(file_progress)" "float, title:(.*[Cc]onfirm.*)" "float, title:(.*[Dd]ialog.*)" "float, title:(.*[Dd]ownload.*)" "float, title:(.*[Nn]otification.*)" "float, title:(.*[Ee]rror.*)" "float, title:(.*[Ss]plash.*)" "float, title:(.*[Cc]onfirmreset.*)" "float, title:(.*[Ss]ign [Ii]n - .*)" "float, title:(.*[Oo]pen [Ff]ile.*)" "float, title:(.*branchdialog.*)" "float, class:(.*pavucontrol.*)" "move onscreen cursor 0% 0%, class:(.*pavucontrol.*)" "float, class:(.*[Oo]verskride.*)" "float, class:(.*FileRoller.*)" "float, class:(.*wlogout.*)" "idleinhibit stayfocused, title:(.*mpv.*)" "float, class:(.*nm-connection-editor.*)" "move onscreen cursor 0% 0%, class:(.*nm-connection-editor.*)" "float, title:(Media viewer)" "float, class:(it.mijorus.smile),title:(Smile)" "float, class:(.blueman-manager-wrapped)$,title:(Bluetooth Devices)" # Picture in picture windows "float, title:(.*Picture-in-Picture.*)" "pin, title::(.*Picture-in-Picture.*)" # discord/vesktop "workspace: name:discord, class:(.*vesktop)" "float, class:(.*vesktop),title:(.*Discord Popout.*)" "pin, class:(.*vesktop),title:(.*Discord Popout.*)" # Music "workspace: name:discord, class:(Apple Music.*)" # Steam "float, class:(.*[Ss]team), title:(.*[Ss]team.*)$" "workspace name:steam silent, class:(.*[Ss]team), title:(.*[Ss]team.*)$" "tile, class:(.*[Ss]team), title:(.*[Ss]team.*)$" "float, class:(.*steam),title:(.*Friends List.*)" # Code "pin, class:(.*codium.*),title:(Save As)" "float, class:(.*codium.*),title:(Save As)" "float, class:(xdg-desktop-portal-gtk),title:(Open Workspace from File)" # Game Tearing??? https://wiki.hypr.land/Configuring/Tearing/ "immediate, class:(.*gamescope)" # vmware # this tag will set the below options to the vdi window # this will have it auto open as a 2160x7680 window # and makes multi-monitor work "tag +horizonrdp, class:(.*[Hh]orizon-client),title:(USPS Next VDI)" "noanim, tag:horizonrdp" "noblur, tag:horizonrdp" "norounding, tag:horizonrdp" "noshadow, tag:horizonrdp" "immediate, tag:horizonrdp" "allowsinput, tag:horizonrdp" "noborder, tag:horizonrdp" "nodim, tag:horizonrdp" "nomaxsize, tag:horizonrdp" "renderunfocused, tag:horizonrdp" "idleinhibit, tag:horizonrdp" "float, tag:horizonrdp" # float the vmware window cause its annoying to use in fullscreen "float, class:(.*[Hh]orizon-client),title:([Oo]mnissa [Hh]orizon [Cc]lient)" "tag +waydroid, class:([Ww]aydroid.*)" "float, tag:waydroid" "pin, tag:waydroid" ] ++ cfg.windowRule; plugin = { # touch_gestures = { # # The default sensitivity is probably too low on tablet screens, # # I recommend turning it up to 4.0 # sensitivity = "4.0"; # # must be >= 3 # workspace_swipe_fingers = "3"; # # switching workspaces by swiping from an edge, this is separate from workspace_swipe_fingers # # and can be used at the same time # # possible values: l, r, u, or d # # to disable it set it to anything else # workspace_swipe_edge = "d"; # # in milliseconds # long_press_delay = "400"; # # resize windows by long-pressing on window borders and gaps. # # If general:resize_on_border is enabled, general:extend_border_grab_area is used for floating # # windows # resize_on_border_long_press = true; # # in pixels, the distance from the edge that is considered an edge # edge_margin = "10"; # # emulates touchpad swipes when swiping in a direction that does not trigger workspace swipe. # # ONLY triggers when finger count is equal to workspace_swipe_fingers # # # # might be removed in the future in favor of event hooks # emulate_touchpad_swipe = false; # experimental = { # # send proper cancel events to windows instead of hacky touch_up events, # # NOT recommended as it crashed a few times, once it's stabilized I'll make it the default # send_cancel = "0"; # }; # hyprgrass-bind = [ # # swipe left from right edge # ", edge:r:l, workspace, +1" # # swipe up from bottom edge # ", edge:d:u, exec, ${cfg.defaultApps.browser.pname}" # # swipe down from left edge # ", edge:l:d, exec, pactl set-sink-volume @DEFAULT_SINK@ -4%" # # swipe down with 4 fingers # ", swipe:4:d, killactive" # # swipe diagonally left and down with 3 fingers # # l (or r) must come before d and u # ", swipe:3:ld, exec, foot" # # tap with 3 fingers # ", tap:3, exec, foot" # # longpress can trigger mouse binds: # ", longpress:2, movewindow" # ", longpress:3, resizewindow" # ]; # }; }; # gestures = { # workspace_swipe = true; # workspace_swipe_cancel_ratio = "0.15"; # }; input = { kb_layout = "us"; kb_variant = ""; kb_model = ""; kb_options = ""; kb_rules = ""; numlock_by_default = true; follow_mouse = 1; touchpad = { clickfinger_behavior = 1; natural_scroll = "yes"; }; sensitivity = 0; # -1.0 - 1.0, 0 means no modification. }; experimental = { xx_color_management_v4 = true; }; debug = { full_cm_proto = true; disable_logs = true; disable_scale_checks = true; }; }; extraConfig = '' exec-once = dbus-update-activation-environment --systemd --all exec-once = systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP exec-once = /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 exec-once = xhost +SI:localuser:root exec-once = nwg-look -a exec-once = nwg-dock-hyprland -d '' + cfg.extraConfig or ''''; }; }; }