{ config, lib, flakePath, pkgs, swayfx, ... }: let inherit (pkgs.stdenv.hostPlatform) isLinux; fonts = { names = ["IBM Plex Sans" "Symbols Nerd Font"]; size = 16.0; }; commonConfig = {wayland ? false}: rec { modifier = "Mod4"; focus.wrapping = "no"; focus.mouseWarping = if wayland then "container" else true; startup = [ { command = "${lib.getExe pkgs.autotiling} -l2"; always = true; } { command = "${lib.getExe pkgs._1password-gui} --silent"; } { command = "${pkgs.volnoti}/bin/volnoti"; } ]; workspaceAutoBackAndForth = true; terminal = "wezterm start --always-new-process"; menu = ""; defaultWorkspace = "$ws1"; keybindings = let mod = modifier; modMove = "${mod}+Shift"; modFocus = "${mod}+Ctrl"; hyper = "Mod4+Mod1+Shift+Ctrl"; gopass = lib.getExe pkgs.unstable.gopass; rofi = lib.getExe config.programs.rofi.package; thunar = lib.getExe pkgs.xfce.thunar; xargs = "${lib.getExe pkgs.findutils}/bin/xargs"; xdotool = lib.getExe pkgs.xdotool; screenshot = if wayland then "${lib.getExe pkgs.sway-contrib.grimshot} copy area" else "${pkgs.flameshot}/bin/flameshot gui"; playerctl = lib.getExe pkgs.playerctl; wpctl = pkgs.wireplumber + "/bin/wpctl"; volnotify = pkgs.writeShellScript "volnotify" '' volumeRaw=$(wpctl get-volume @DEFAULT_AUDIO_SINK@ | head -n1) volume=$(echo $volumeRaw | sed 's/Volume: //' | awk '{printf "%.0f\n", $1 * 100}') if [[ "$volumeRaw" =~ "MUTED" ]]; then volnoti-show -m else volnoti-show $volume fi ''; gopassRofi = pkgs.writeShellScript "gopass-rofi" '' ${gopass} ls --flat | \ ${rofi} -dmenu -dpi $dpi | \ ${xargs} --no-run-if-empty ${gopass} show -o | \ ${xdotool} type --clearmodifiers --file - ''; in { "${mod}+Shift+b" = "border none"; "${mod}+b" = "border pixel 2"; "${mod}+n" = "border normal"; # reload the configuration file "${mod}+Shift+r" = "reload"; # kill focused window "${mod}+Shift+q" = "kill"; # Start Applications "${mod}+Shift+Return" = "exec ${terminal}"; "${mod}+e" = "exec --no-startup-id ${thunar}"; "${mod}+Ctrl+x" = "exec --no-startup-id ${lib.getExe pkgs.xorg.xkill}"; # TODO: replace xdotool with wayland equivalent "${hyper}+space" = "exec --no-startup-id ${gopassRofi}"; "${hyper}+p" = "exec --no-startup-id ${screenshot}"; # change focus "${modFocus}+h" = "focus left"; "${modFocus}+j" = "focus down"; "${modFocus}+k" = "focus up"; "${modFocus}+l" = "focus right"; "${modFocus}+Left" = "focus left"; "${modFocus}+Down" = "focus down"; "${modFocus}+Up" = "focus up"; "${modFocus}+Right" = "focus right"; # move focus "${modMove}+h" = "move left"; "${modMove}+j" = "move down"; "${modMove}+k" = "move up"; "${modMove}+l" = "move right"; "${modMove}+Left" = "move left"; "${modMove}+Down" = "move down"; "${modMove}+Up" = "move up"; "${modMove}+Right" = "move right"; # move workspaces across monitors "${modMove}+greater" = "move workspace to output right"; "${modMove}+less" = "move workspace to output left"; # split orientation "${mod}+q" = "split toggle"; # toggle fullscreen mode for the focused container "${mod}+f" = "fullscreen toggle"; # change container layout (stacked, tabbed, toggle split) "${mod}+s" = "layout toggle"; # toggle tiling / floating "${mod}+Shift+d" = "floating toggle"; # change focus between tiling / floating windows "${mod}+d" = "focus mode_toggle"; # toggle sticky "${mod}+Shift+s" = "sticky toggle"; # focus the parent container "${mod}+a" = "focus parent"; # move the currently focused window to the scratchpad "${mod}+Shift+Tab" = "move scratchpad"; # Show the next scratchpad window or hide the focused scratchpad window. # If there are multiple scratchpad windows, this command cycles through them. "${mod}+Tab" = "scratchpad show"; "${mod}+m" = "[class=\"discord\"] scratchpad show"; # switch to workspace "${modFocus}+1" = "workspace $ws1"; "${modFocus}+2" = "workspace $ws2"; "${modFocus}+3" = "workspace $ws3"; "${modFocus}+4" = "workspace $ws4"; "${modFocus}+5" = "workspace $ws5"; "${modFocus}+6" = "workspace $ws6"; "${modFocus}+7" = "workspace $ws7"; "${modFocus}+8" = "workspace $ws8"; "${modFocus}+9" = "workspace $ws9"; "${modFocus}+0" = "workspace $ws10"; # Move to workspace with focused container "${modMove}+1" = "move container to workspace $ws1; workspace $ws1"; "${modMove}+2" = "move container to workspace $ws2; workspace $ws2"; "${modMove}+3" = "move container to workspace $ws3; workspace $ws3"; "${modMove}+4" = "move container to workspace $ws4; workspace $ws4"; "${modMove}+5" = "move container to workspace $ws5; workspace $ws5"; "${modMove}+6" = "move container to workspace $ws6; workspace $ws6"; "${modMove}+7" = "move container to workspace $ws7; workspace $ws7"; "${modMove}+8" = "move container to workspace $ws8; workspace $ws8"; "${modMove}+9" = "move container to workspace $ws9; workspace $ws9"; "${modMove}+0" = "move container to workspace $ws10; workspace $ws10"; # rofi instead of drun "${mod}+space" = "exec --no-startup-id ${rofi} -show drun -dpi $dpi"; # 1password "${mod}+Shift+space" = "exec ${lib.getExe pkgs._1password-gui} --quick-access"; # audio "XF86AudioRaiseVolume" = "exec --no-startup-id ${wpctl} set-volume @DEFAULT_AUDIO_SINK@ 5%+ -l 1.0 && ${volnotify}"; "XF86AudioLowerVolume" = "exec --no-startup-id ${wpctl} set-volume @DEFAULT_AUDIO_SINK@ 5%- -l 1.0 && ${volnotify}"; "XF86AudioMute" = "exec --no-startup-id ${wpctl} set-mute @DEFAULT_AUDIO_SINK@ toggle && ${volnotify}"; "XF86AudioNext" = "exec --no-startup-id ${playerctl} next"; "XF86AudioPrev" = "exec --no-startup-id ${playerctl} previous"; "XF86AudioPause" = "exec --no-startup-id ${playerctl} play-pause"; # modes "${mod}+r" = "mode \"resize\""; "${mod}+p" = "mode \"power: (l)ock, (e)xit, (r)eboot, (s)uspend, (h)ibernate, (S)hut off\""; }; modes = { "power: (l)ock, (e)xit, (r)eboot, (s)uspend, (h)ibernate, (S)hut off" = let lock = if wayland then "swaylock" else "i3lock"; msg = if wayland then "swaymsg" else "i3-msg"; in { l = "exec --no-startup-id ${lock} --color 000000, mode \"default\""; e = "exec --no-startup-id ${msg} exit, mode \"default\""; r = "exec --no-startup-id systemctl reboot, mode \"default\""; s = "exec --no-startup-id systemctl suspend, mode \"default\""; h = "exec --no-startup-id systemctl hibernate, mode \"default\""; "Shift+s" = "exec --no-startup-id systemctl poweroff, mode \"default\""; Escape = "mode default"; Return = "mode default"; }; resize = { Escape = "mode default"; Return = "mode default"; h = "resize shrink width 10 px or 10 ppt"; j = "resize grow height 10 px or 10 ppt"; k = "resize shrink height 10 px or 10 ppt"; l = "resize grow width 10 px or 10 ppt"; R = "resize set 50 ppt 50 ppt"; }; }; inherit fonts; bars = [ { mode = "hide"; # use waybar if wayland command = lib.mkIf wayland "${lib.getExe config.programs.waybar.package}"; position = "top"; workspaceNumbers = false; inherit fonts; colors = { background = "#000000"; focusedWorkspace = { background = "#F5C2E7"; text = "#000000"; border = "#F5C2E7"; }; activeWorkspace = { background = "#CBA6F7"; text = "#000000"; border = "#CBA6F7"; }; inactiveWorkspace = { background = "#000000"; text = "#CDD6F4"; border = "#000000"; }; }; } ]; colors = rec { focused = { background = "#000000"; border = "#F5C2E7"; childBorder = "#F5C2E7"; text = "#CDD6F4"; indicator = "#F5C2E7"; }; urgent = { background = "#000000"; border = "#F38BA8"; childBorder = "#F38BA8"; text = "#CDD6F4"; indicator = "#F38BA8"; }; unfocused = { background = "#000000"; border = "#CBA6F7"; childBorder = "#CBA6F7"; text = "#CDD6F4"; indicator = "#CBA6F7"; }; focusedInactive = unfocused; placeholder = unfocused; }; window = { titlebar = false; hideEdgeBorders = "none"; border = 2; }; gaps = { inner = 5; outer = 2; }; }; commonExtraConfig = '' title_align center set $ws1 1:Ⅰ set $ws2 2:Ⅱ set $ws3 3:Ⅲ set $ws4 4:Ⅳ set $ws5 5:Ⅴ set $ws6 6:Ⅵ set $ws7 7:Ⅶ set $ws8 8:Ⅷ set $ws9 9:Ⅸ set $ws10 10:Ⅹ # floating sticky for_window [class="1Password"] floating enable sticky enable border pixel 1 for_window [window_role="PictureInPicture"] floating enable sticky enable border pixel 1 # floating for_window [class="GParted"] floating enable for_window [title="(?i)SteamTinkerLaunch"] floating enable for_window [title="Blender Render"] floating enable # general WM role settings for_window [title="splash"] floating enable for_window [urgent=latest] focus for_window [window_role="pop-up"] floating enable for_window [window_role="task_dialog"] floating enable # apps for_window [class="Pavucontrol"] floating enable for_window [class="Yad" title="Authentication"] floating enable for_window [class="jetbrains*" title="Welcome*"] floating enable for_window [title="File Transfer*"] floating enable for_window [title="Steam Guard*"] floating enable # keep apps in scratchpad for_window [class="discord"] move scratchpad sticky set $mode_gaps Gaps: (o)uter, (i)nner set $mode_gaps_outer Outer Gaps: +|-|0 (local), Shift + +|-|0 (global) set $mode_gaps_inner Inner Gaps: +|-|0 (local), Shift + +|-|0 (global) bindsym ${(commonConfig {}).modifier}+Shift+g mode "$mode_gaps" mode "$mode_gaps" { bindsym o mode "$mode_gaps_outer" bindsym i mode "$mode_gaps_inner" bindsym Return mode "$mode_gaps" bindsym Escape mode "default" } mode "$mode_gaps_outer" { bindsym plus gaps outer current plus 5 bindsym minus gaps outer current minus 5 bindsym 0 gaps outer current set 0 bindsym Shift+plus gaps outer all plus 5 bindsym Shift+minus gaps outer all minus 5 bindsym Shift+0 gaps outer all set 0 bindsym Return mode "$mode_gaps" bindsym Escape mode "default" } mode "$mode_gaps_inner" { bindsym plus gaps inner current plus 5 bindsym minus gaps inner current minus 5 bindsym 0 gaps inner current set 0 bindsym Shift+plus gaps inner all plus 5 bindsym Shift+minus gaps inner all minus 5 bindsym Shift+0 gaps inner all set 0 bindsym Return mode "$mode_gaps" bindsym Escape mode "default" } ''; in { fonts.fontconfig.enable = true; home = lib.mkIf isLinux { packages = with pkgs; [ arandr blueberry flameshot pavucontrol sway-contrib.grimshot volnoti xclip ]; }; services = lib.mkIf isLinux { darkman = { enable = true; config = { lat = 48.210033; lng = 16.363449; useGeoclue = false; }; }; dunst.enable = true; gnome-keyring = { enable = true; components = ["secrets"]; }; picom = { enable = false; package = pkgs.nur.repos.nekowinston.picom-ft-labs; fade = false; backend = "glx"; vSync = true; shadow = true; settings = { animations = true; animation-exclude = [ "window_type = 'dock'" "window_type = 'desktop'" ]; animation-for-open-window = "zoom"; animation-for-unmap-window = "zoom"; animation-for-prev-tag = "zoom"; animation-for-next-tag = "zoom"; enable-fading-prev-tag = true; enable-fading-next-tag = true; blur.method = "dual_kawase"; blur-background-exclude = [ "window_type = 'dock'" "window_type = 'desktop'" "_NET_WM_NAME@:s *?= 'Discover Voice'" "_NET_WM_NAME@:s *?= 'Discover Text'" ]; }; }; screen-locker = { enable = false; inactiveInterval = 5; lockCmd = "${lib.getExe pkgs.i3lock} -n -c 000000"; }; udiskie.enable = true; }; # https://github.com/nix-community/home-manager/issues/2064 systemd = lib.mkIf isLinux { user.targets.tray.Unit = { Description = "Home Manager System Tray"; Requires = ["graphical-session-pre.target"]; }; }; xsession = lib.mkIf isLinux { enable = true; profilePath = "${config.xdg.configHome}/profile"; scriptPath = "${config.xdg.cacheHome}/X11/xsession"; windowManager.i3 = { enable = true; package = pkgs.unstable.i3; config = commonConfig {wayland = false;} // { startup = [ { command = "${lib.getExe pkgs.flameshot}"; } ]; }; extraConfig = '' set_from_resource $dpi Xft.dpi 140 ${commonExtraConfig} ''; }; }; wayland.windowManager.sway = lib.mkIf isLinux { enable = true; package = swayfx; config = commonConfig {wayland = true;} // { input."type:keyboard" = { xkb_options = "ctrl:nocaps"; }; output = { "*" = { scale = "2"; bg = "${flakePath}/home/wallpapers/dhm_1610.png fill #171320"; }; }; startup = [ { command = "wl-paste -t text --watch clipman store"; } ]; }; extraConfig = '' ${commonExtraConfig} shadows on shadow_color #00000099 shadow_blur_radius 10 corner_radius 5 smart_corner_radius on ''; systemdIntegration = true; wrapperFeatures = { base = true; gtk = true; }; }; }