{ pkgs, ... }: { wayland.windowManager.sway = { enable = true; wrapperFeatures.gtk = true; # Fixes common issues with GTK 3 apps config = rec { modifier = "Mod4"; # Use kitty as default terminal terminal = "foot"; keybindings = { # Brightness Controls "XF86MonBrightnessDown" = "exec brightnessctl s 5%-"; "XF86MonBrightnessUp" = "exec brightnessctl s 5%+"; # Volume Controls "XF86AudioRaiseVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ +1%"; "XF86AudioLowerVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ -1%"; "XF86AudioMute" = "exec pactl set-sink-mute @DEFAULT_SINK@ toggle"; "Mod4+q" = "kill"; "Mod4+Return" = "exec foot"; "Mod4+Shift+q" = "kill"; "Mod4+d" = "exec wmenu-run"; "Mod4+Left" = "focus left"; "Mod4+Down" = "focus down"; "Mod4+Up" = "focus up"; "Mod4+Right" = "focus right"; "Mod4+Shift+Left" = "move left"; "Mod4+Shift+Down" = "move down"; "Mod4+Shift+Up" = "move up"; "Mod4+Shift+Right" = "move right"; "Mod4+b" = "splith"; "Mod4+v" = "splitv"; "Mod4+f" = "fullscreen toggle"; "Mod4+a" = "focus parent"; "Mod4+s" = "layout stacking"; "Mod4+w" = "layout tabbed"; "Mod4+e" = "layout toggle split"; "Mod4+Shift+space" = "floating toggle"; "Mod4+space" = "focus mode_toggle"; "Mod4+1" = "workspace number 1"; "Mod4+2" = "workspace number 2"; "Mod4+3" = "workspace number 3"; "Mod4+4" = "workspace number 4"; "Mod4+5" = "workspace number 5"; "Mod4+6" = "workspace number 6"; "Mod4+7" = "workspace number 7"; "Mod4+8" = "workspace number 8"; "Mod4+9" = "workspace number 9"; "Mod4+0" = "workspace number 10"; "Mod4+Shift+1" = "move container to workspace number 1"; "Mod4+Shift+2" = "move container to workspace number 2"; "Mod4+Shift+3" = "move container to workspace number 3"; "Mod4+Shift+4" = "move container to workspace number 4"; "Mod4+Shift+5" = "move container to workspace number 5"; "Mod4+Shift+6" = "move container to workspace number 6"; "Mod4+Shift+7" = "move container to workspace number 7"; "Mod4+Shift+8" = "move container to workspace number 8"; "Mod4+Shift+9" = "move container to workspace number 9"; "Mod4+Shift+0" = "move container to workspace number 10"; "Mod4+Shift+minus" = "move scratchpad"; "Mod4+minus" = "scratchpad show"; "Mod4+p" = "[app_id=\"trilium\"] scratchpad show, resize set 90 ppt 90 ppt, move position center"; "Mod4+g" = "exec glide-browser"; "Mod4+Shift+i" = "exec makoctl invoke && makoctl dismiss"; "Mod4+i" = "exec makoctl dismiss"; "Mod4+Shift+c" = "reload"; "Mod4+Shift+e" = "exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'"; "Mod4+r" = "mode resize"; "Mod4+c" = "[app_id=\"discord\"] scratchpad show, resize set 90 ppt 90 ppt, move position center"; "Mod4+j" = "[class=\"Jami\"] scratchpad show, resize set 90 ppt 90 ppt, move position center"; "Print" = "exec flameshot gui"; }; bars = [ { command = "${pkgs.waybar}/bin/waybar"; } ]; output = { eDP-1 = { scale = "1.25"; }; }; input = { "type:touchpad" = { # Enables or disables tap for specified input device. tap = "enabled"; # Enables or disables natural (inverted) scrolling for the specified input device. natural_scroll = "enabled"; # Enables or disables disable-while-typing for the specified input device. dwt = "disabled"; }; }; bindswitches = { "lid:on" = { reload = true; locked = true; action = "exec systemctl suspend-then-hibernate"; }; }; startup = [ # { command = "swaybg -i ~/.background-image -m fill"; } { command = "discord --enable-features=UseOzonePlatform --ozone-platform=wayland"; } { command = "trilium"; } { command = "jami"; } ]; window.commands = [ { criteria = { app_id = "discord"; }; command = "move scratchpad"; } { criteria = { app_id = "trilium"; }; command = "move scratchpad"; } { criteria = { class = "Jami"; }; command = "move scratchpad"; } ]; }; }; systemd.user.services.random-background = { Unit = { Description = "Universal Wallpaper Rotator (Images, GIFs, Videos)"; After = [ "graphical-session.target" ]; PartOf = [ "graphical-session.target" ]; }; Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { Type = "simple"; Restart = "on-failure"; RestartSec = 5; ExecStart = "${pkgs.writeShellScript "wallpaper-rotator" '' WALLPAPER_DIR="$HOME/wallpapers" INTERVAL=600 # Time in seconds between wallpaper changes (600 = 10 mins) # 1. Safely find Wayland and Sway sockets if [ -z "$WAYLAND_DISPLAY" ]; then shopt -s nullglob W_SOCKETS=("$XDG_RUNTIME_DIR"/wayland-[0-9]*) if [ ''${#W_SOCKETS[@]} -gt 0 ]; then export WAYLAND_DISPLAY=$(basename "''${W_SOCKETS[0]}") fi fi if [ -z "$SWAYSOCK" ]; then shopt -s nullglob S_SOCKETS=("$XDG_RUNTIME_DIR"/sway-ipc.*.sock) if [ ''${#S_SOCKETS[@]} -gt 0 ]; then export SWAYSOCK="''${S_SOCKETS[0]}" fi fi # State tracking for mpvpaper MPV_PID="" # Clean up mpvpaper gracefully if systemd stops the service cleanup() { if [ -n "$MPV_PID" ]; then kill $MPV_PID 2>/dev/null || true fi exit 0 } trap cleanup SIGINT SIGTERM # 2. Infinite rotation loop while true; do if [ ! -d "$WALLPAPER_DIR" ]; then echo "Wallpaper directory not found. Waiting..." ${pkgs.coreutils}/bin/sleep 60 continue fi # Find images, gifs, and videos MEDIA=$(${pkgs.findutils}/bin/find "$WALLPAPER_DIR" -type f \( \ -iname \*.jpg -o -iname \*.jpeg -o -iname \*.png -o \ -iname \*.mp4 -o -iname \*.webm -o -iname \*.mkv -o -iname \*.gif \ \) 2>/dev/null | ${pkgs.coreutils}/bin/shuf -n 1 || true) if [ -n "$MEDIA" ]; then echo "Selected: $MEDIA" EXT="''${MEDIA##*.}" EXT=$(echo "$EXT" | tr '[:upper:]' '[:lower:]') # Convert to lowercase # If it's a static image, use Sway directly (saves battery/RAM) if [[ "$EXT" == "jpg" || "$EXT" == "jpeg" || "$EXT" == "png" ]]; then if [ -n "$MPV_PID" ]; then kill $MPV_PID 2>/dev/null || true MPV_PID="" fi ${pkgs.sway}/bin/swaymsg output "*" bg "$MEDIA" fill # If it's a video/gif, use mpvpaper else if [ -n "$MPV_PID" ]; then kill $MPV_PID 2>/dev/null || true fi # Start mpvpaper in the background and record its process ID ${pkgs.mpvpaper}/bin/mpvpaper -o "loop no-audio" "*" "$MEDIA" & MPV_PID=$! fi else echo "No media found in $WALLPAPER_DIR." fi # Wait for the next rotation ${pkgs.coreutils}/bin/sleep $INTERVAL done ''}"; }; }; programs.waybar = { enable = true; style = ./waybar.css; settings = { mainBar = { layer = "top"; position = "bottom"; # Puts the bar at the bottom height = 30; # Define what goes where on the bar modules-left = [ "sway/workspaces" "sway/mode" ]; modules-center = [ "sway/window" ]; modules-right = [ "backlight" "pulseaudio" "battery" "clock" "tray" ]; backlight = { format = "{icon} {percent}%"; format-icons = [ "🌑" "🌘" "🌗" "🌖" "🌕" ]; }; pulseaudio = { format = "{icon} {volume}%"; format-muted = "🔇 Muted"; format-icons = { default = [ "🔈" "🔉" "🔊" ]; }; scroll-step = 1; on-click = "pactl set-sink-mute @DEFAULT_SINK@ toggle"; }; clock = { format = "{:%Y-%m-%d %H:%M}"; tooltip-format = "{:%Y %B}\n{calendar}"; }; battery = { states = { warning = 30; critical = 15; }; format = "{icon} {capacity}% ({time})"; format-charging = "⚡ {capacity}% ({time})"; format-plugged = "🔌 {capacity}% ({time})"; format-icons = [ "đŸĒĢ" "🔋" "🔋" "🔋" "🔋" ]; }; }; }; }; services.swayidle.events = { "before-sleep" = "${pkgs.swaylock}/bin/swaylock -fF"; }; services.swayidle.enable = true; # Configure Qt to use kvantum theming qt = { enable = true; platformTheme.name = "org.kde.breezedark.desktop"; style = { name = "org.kde.breezedark.desktop"; }; }; services.flameshot = { # Also installs/enables flameshot enable = true; settings = { General = { useGrimAdapter = true; # Stops warnings for using Grim disabledGrimWarning = true; uiColor = "#00ff73"; contrastUiColor = "#002f01"; drawColor = "#ff0000"; }; }; }; # Install packages for better Qt support and kvantum themes home.packages = with pkgs; [ kdePackages.breeze ]; # Environment variables for kvantum theming home.sessionVariables = { QT_QPA_PLATFORMTHEME = "org.kde.breezedark.desktop"; QT_STYLE_OVERRIDE = "org.kde.breezedark.desktop"; GTK_THEME = "Materia-dark-compact"; }; }