{ config, pkgs, lib, ... }: with lib; with builtins; let cfg = config.jainawm; in { options.jainawm = { enable = mkOption { type = types.bool; default = false; }; terminal = { name = mkOption { type = types.str; default = "kitty"; }; package = mkOption { type = types.package; default = pkgs.kitty; }; binPath = mkOption { type = types.str; readOnly = true; }; }; fonts = let fontOption = mkOption { type = lib.hm.types.fontType; }; in { primary = fontOption; serif = fontOption; fixed = fontOption; wmOverlay = fontOption; }; catppuccin = mkOption { #type = types.attrs; default = import ./catppuccin/mocha.nix; description = '' Set of colors to use for theme configuration. ''; }; accents = { primary = mkOption { type = types.str; }; secondary = mkOption { type = types.str; }; }; wallpaper = mkOption { type = types.path; }; startup = mkOption { type = types.listOf (type.submodule { options = { enable = mkEnableOption "Enable the given startup command"; command = mkOption { type = types.str; }; always = mkOption { type = types.bool; default = false; descrioption = "If true, the command will be ran when the window manager is reset"; }; }; }); }; }; imports = [ ./jwm/sway.nix ./jwm/rofi.nix ./jwm/phelper.nix ./jwm/kanshi.nix ./jwm/waybar.nix ./jwm/ptray.nix ]; config = let cat = cfg.catppuccin; #front = getAttr cfg.selectedFront cfg.fronters; fonts = cfg.fonts; in mkIf cfg.enable { jainawm.terminal.binPath = "${cfg.terminal.package}/bin/${cfg.terminal.name}"; services.mako = { enable = true; anchor = "top-right"; height = 100; width = 500; padding = "10"; layer = "overlay"; font = "${fonts.primary.name} ${toString (fonts.primary.size + 1)}"; textColor = cat.text; backgroundColor = "${cat.surface0}cc"; progressColor = "over ${cat.surface2}cc"; borderColor = builtins.getAttr (lib.strings.toLower cfg.accents.primary) cat; borderRadius = 10; borderSize = 3; defaultTimeout = null; maxVisible = null; # groupBy = # iconPath = extraConfig = '' on-button-left=invoke-default-action on-touch=invoke-default-action on-button-right=dismiss [app-name="discord"] layer=overlay on-button-left=exec /usr/bin/env dropwinctl show discord && makoctl invoke -n "$id" && makoctl dismiss -n "$id" [app-name="JWM"] layer=overlay [app-name="JWM" category="audio" body~="1\([0-9][1-9]|[1-9][0-9]\)"] background-color=${cat.surface2}f8 progress-color=over ${cat.red}cc ''; }; #jainawm.wallpaper = front.wallpaper; jainawm.rofi.accents = mapAttrs (n: c: builtins.getAttr (lib.strings.toLower c) cat) cfg.accents; jainawm.rofi.font = fonts.wmOverlay; jainawm.ptray = { enable = true; items = { discord = { match_classes = [ "WebCord" "discord" ]; exec = "${pkgs.webcord}/bin/webcord --enable-features=UseOzonePlatform --ozone-platform=wayland --disable-gpu"; }; keepass = { match_classes = [ "org.keepassxc.KeePassXC" ]; exec = "${pkgs.keepassxc}/bin/keepassxc"; }; }; # drops = let # fx = [ # "opacity 0.97" # "floating enable" # "resize set 80ppt 80ppt" # "move position 10ppt -10" # "sticky enable" # ]; # in { # discord = { # match = [ "WebCord" "discord" ]; # start = "${pkgs.discord}/bin/discord"; # customization = fx; # }; # keepass = { # match = [ "org.keepassxc.KeePassXC" ]; # start = "${pkgs.keepassxc}/bin/keepassxc"; # customization = fx; # }; # matrix = { # match = [ "Element" ]; # start = "${element-desktop}/bin/element-desktop"; # customization = fx; # }; # }; }; #jainawm.rofi.accent = "#ff0000"; #jainawm.rofi.enable = true; #programs.waybar.style = builtins.readFile ./waybar/style.css; jainawm.kanshi.enable = true; jainawm.sway.enable = true; # TODO xdg.configFile."hypr/hyprpaper.conf".text = '' preload = ${cfg.wallpaper} wallpaper = ,${cfg.wallpaper} ''; home.activation."switch-hyprpaper-wallpaper" = lib.hm.dag.entryAfter [ "writeBoundary" ] '' export PATH="$PATH:${config.wayland.windowManager.hyprland.package}/bin:${pkgs.jq}/bin" for inst in $(ls ''${XDG_RUNTIME_DIR:-/run/user/$UID}/hypr); do $DRY_RUN_CMD hyprctl -i $inst hyprpaper preload ${cfg.wallpaper} || true (hyprctl monitors -j -i $inst | jq --raw-output '.[] | .name' || true) | \ xargs -I{} $DRY_RUN_CMD hyprctl -i $inst hyprpaper wallpaper '{},${cfg.wallpaper}' $DRY_RUN_CMD hyprctl -i $inst hyprpaper unload all || true done ''; xdg.configFile."eww/theme_cat.scss".text = concatStringsSep "\n" (mapAttrsToList (name: value: "$cat-${name}: ${value};") cfg.catppuccin); xdg.configFile."eww/theme_jwm.scss".text = '' @import "theme_cat" $jwm-accent: $cat-${lib.strings.toLower cfg.accents.primary}; $jwm-accent2: $cat-${lib.strings.toLower cfg.accents.secondary}; $jwm-accent-contrast: $cat-crust; ''; home.activation.reloadHyprland = lib.hm.dag.entryAfter [ "writeBoundary" ] '' export PATH="$PATH:${config.wayland.windowManager.hyprland.package}/bin" ls ''${XDG_RUNTIME_DIR:-/run/user/$UID}/hypr || true | \ xargs -I{} $DRY_RUN_CMD hyprctl reload -i {} ''; wayland.windowManager.hyprland.enable = true; #wayland.windowManager.hyprland.settings = { }; wayland.windowManager.hyprland.extraConfig = let removeHash = col: builtins.replaceStrings [ "#" ] [ "" ] col; getColor = name: removeHash (builtins.getAttr (lib.strings.toLower name) cfg.catppuccin); mainMod = "SUPER"; playerctl = "${pkgs.playerctl}/bin/playerctl --player strawberry"; hide-special = pkgs.writeShellScript "jwm-hyprland-hide-special" '' hyprctl monitors -j | jq -r '.[] | .specialWorkspace.name | select(. | length > 0) | .[8:]' \ | xargs -I{} hyprctl dispatcher togglespecialworkspace "{}" >/dev/null ''; rofi-emoji = let rofi-emoji-theme = '' element selected { background-color: rgba(0,0,0,0 %); border-color: ${cfg.rofi.accents.primary}ff; border: 2px; } element { children: ["element-text"]; } element-text { horizontal-align: 0.5; font: "${fonts.primary.name} 25"; margin: 0px; } listview { flow: horizontal; columns: 7; } ''; in pkgs.writeShellScript "rofi-emoji" '' ${config.programs.rofi.finalPackage}/bin/rofi \ -show emoji -modes emoji \ -emoji-format '{emoji}' \ -theme-str ${lib.strings.escapeShellArg rofi-emoji-theme} \ $@ ''; playerctlPrevOrScan = pkgs.writeScript "playerctlPrevOrScan" '' if [ "$(${playerctl} metadata --format '{{position}}')" -lt 10000000 ]; then ${playerctl} previous else ${playerctl} position 0 fi ''; in '' $mainMod = ${mainMod} # For all categories, see https://wiki.hyprland.org/Configuring/Variables/ input { kb_layout = us kb_variant = kb_model = kb_options = altwin:swap_lalt_lwin,altwin:menu_win kb_rules = follow_mouse = 1 touchpad { natural_scroll = yes } sensitivity = 0 # -1.0 - 1.0, 0 means no modification. } gestures { workspace_swipe = true workspace_swipe_fingers = 4 } general { col.active_border = rgba(${getColor cfg.accents.primary}ee) col.inactive_border = rgba(${removeHash cfg.catppuccin.surface0}aa) gaps_in = 10 gaps_out = 20 border_size = 2 layout = dwindle } decoration { rounding = 10 drop_shadow = yes shadow_range = 20 shadow_render_power = 2 col.shadow = rgba(000000ee) col.shadow_inactive = rgba(00000000) blur { size = 5 passes = 2 special = true } } layerrule = blur, rofi|notifications layerrule = ignorealpha 0.4, rofi|notifications animations { enabled = yes # Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more 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, 6, default animation = specialWorkspace, 1, 6, default, slidevert } dwindle { preserve_split = yes } gestures { workspace_swipe = on } bind = ${mainMod}, Return, exec, ${cfg.terminal.binPath} bind = ${mainMod}, D, exec, rofi -show drun bind = ${mainMod} SHIFT, S, exec, jwm screenshot-region binde = ${mainMod} SHIFT, Q, killactive, bind = ${mainMod} SHIFT, E, exit, bind = ${mainMod}, F, fullscreen, bind = ${mainMod}, Q, exec, ${hide-special} bindle = , XF86MonBrightnessUp, exec, jwm bright 5 bindle = , XF86MonBrightnessDown, exec, jwm bright -5 bindle = , XF86AudioRaiseVolume, exec, jwm vol 5 bindle = , XF86AudioLowerVolume, exec, jwm vol -5 bindl = , XF86AudioMute, exec, jwm vol toggle-mute bindl = , XF86AudioPlay, exec, ${playerctl} play-pause bindl = , XF86AudioNext, exec, ${playerctl} next bindl = , XF86AudioPrev, exec, ${playerctlPrevOrScan} bindl = ${mainMod} CTRL, right, exec, ${playerctl} next bindl = ${mainMod} CTRL, left, exec, ${playerctlPrevOrScan} bindl = , XF86AudioStop, exec, ${playerctl} stop # Move focus with mainMod + arrow keys bind = ${mainMod}, left, movefocus, l bind = ${mainMod}, down, movefocus, d bind = ${mainMod}, up, movefocus, u bind = ${mainMod}, right, movefocus, r bind = ${mainMod}, h, movefocus, l bind = ${mainMod}, j, movefocus, d bind = ${mainMod}, k, movefocus, u bind = ${mainMod}, l, movefocus, r # Move focused window with mainMod + Shift + direction keys bind = ${mainMod} SHIFT, left, moveWindowOrGroup, l bind = ${mainMod} SHIFT, down, moveWindowOrGroup, d bind = ${mainMod} SHIFT, up, moveWindowOrGroup, u bind = ${mainMod} SHIFT, right, moveWindowOrGroup, r bind = ${mainMod} SHIFT, h, moveWindowOrGroup, l bind = ${mainMod} SHIFT, j, moveWindowOrGroup, d bind = ${mainMod} SHIFT, k, moveWindowOrGroup, u bind = ${mainMod} SHIFT, l, moveWindowOrGroup, r # Switch workspaces with mainMod + [0-9] bind = ${mainMod}, 1, workspace, 1 bind = ${mainMod}, 2, workspace, 2 bind = ${mainMod}, 3, workspace, 3 bind = ${mainMod}, 4, workspace, 4 bind = ${mainMod}, 5, workspace, 5 bind = ${mainMod}, 6, workspace, 6 bind = ${mainMod}, 7, workspace, 7 bind = ${mainMod}, 8, workspace, 8 bind = ${mainMod}, 9, workspace, 9 bind = ${mainMod}, 0, workspace, 10 # Move active window to a workspace with mainMod + SHIFT + [0-9] bind = ${mainMod} SHIFT, 1, movetoworkspace, 1 bind = ${mainMod} SHIFT, 2, movetoworkspace, 2 bind = ${mainMod} SHIFT, 3, movetoworkspace, 3 bind = ${mainMod} SHIFT, 4, movetoworkspace, 4 bind = ${mainMod} SHIFT, 5, movetoworkspace, 5 bind = ${mainMod} SHIFT, 6, movetoworkspace, 6 bind = ${mainMod} SHIFT, 7, movetoworkspace, 7 bind = ${mainMod} SHIFT, 8, movetoworkspace, 8 bind = ${mainMod} SHIFT, 9, movetoworkspace, 9 bind = ${mainMod} SHIFT, 0, movetoworkspace, 10 # Scroll through existing workspaces with mainMod + scroll bind = ${mainMod}, mouse_down, workspace, e+1 bind = ${mainMod}, mouse_up, workspace, e-1 bind = ${mainMod}, TAB, workspace, e+1 bind = ${mainMod}, GRAVE, workspace, e-1 bind = ${mainMod} SHIFT, TAB, movetoworkspace, e+1 bind = ${mainMod} SHIFT, GRAVE, movetoworkspace, e-1 # Move/resize windows with mainMod + LMB/RMB and dragging bindm = ${mainMod}, mouse:272, movewindow bindm = ${mainMod}, mouse:273, resizewindow # Resize current window bind = ${mainMod}, R, submap, resize submap = resize binde =, left, resizeActive, -10 0 binde =, down, resizeActive, 0 10 binde =, up, resizeActive, 0 -10 binde =, right, resizeActive, 10 0 binde =, h, resizeActive, -10 0 binde =, j, resizeActive, 0 10 binde =, k, resizeActive, 0 -10 binde =, l, resizeActive, 10 0 bind=,escape,submap,reset bind=,return,submap,reset submap = reset # App Launcher bind = ${mainMod}, I, submap, app submap = app bind = , D, togglespecialworkspace, discord bind = , D, submap, reset bind = SHIFT, D, movetoworkspace, special:discord bind = SHIFT, D, submap, reset bind = , K, togglespecialworkspace, keepass bind = , K, submap, reset bind = SHIFT, K, movetoworkspace, special:keepass bind = SHIFT, K, submap, reset bind = , W, exec, jwm web-launcher bind = , W, submap, reset bind = , Return, submap, reset bind = , Escape, submap, reset submap = reset # OS commands bind = ${mainMod}, P, submap, command submap = command bind = , M, exec, jwm mic toggle-mute bind = , M, submap, reset bind = , S, exec, jwm switch-launcher bind = , S, submap, reset bind = , D, exec, jwm toggle-dwt bind = , D, submap, reset bind = , Return, submap, reset bind = , Escape, submap, reset submap = reset # Emoji bind = ${mainMod}, PERIOD, exec, ${rofi-emoji} -emoji-mode stdout | xargs wtype windowrule = noborder,^(steam_app_)(.*)$ windowrule = noblur,^(steam_app_)(.*)$ windowrulev2 = workspace special:discord,class:(WebCord) windowrulev2 = workspace special:keepass,class:(org.keepassxc.KeePassXC) source=~/.config/hypr/hyprland.conf.backup ''; #wayland.windowManager.hyprland = { # extraConfig = '' # source=~/.config/hypr/hyprland.conf.backup # ''; #enable = true; #}; #jainawm.sway.useFx = true; home.packages = with pkgs; [ playerctl hyprpaper ]; qt = { #enable = true; enable = false; platformTheme.name = "gtk"; }; gtk.enable = true; gtk.theme = { name = "Catppuccin-Mocha-Standard-${cfg.accents.primary}-Dark"; package = pkgs.catppuccin-gtk.override { accents = [ (lib.strings.toLower cfg.accents.primary) ]; variant = "mocha"; }; }; programs.swaylock.settings.image = "${cfg.wallpaper}"; #wayland.windowManager.sway.config.output."*".bg = "${front.wallpaper} fill"; # programs.rofi.theme = import ./rofi-theme.nix { # cat = cat; # front = front; # fonts = cfg.fonts; # lib = lib; # config = config; # }; }; }