{ config , lib , pkgs , inputs , ... } @ args: with lib; let cfg = config.my.programs.river; in { options.my.programs.river = { enable = mkEnableOption "river"; keyboardLayouts = mkOption { type = types.listOf types.str; description = "list of keyboard layouts"; default = [ "de" "us" ]; }; nvidiaSupport = mkEnableOption "nvidiaSupport"; }; config = mkIf cfg.enable { programs.river.enable = true; my = { programs = { wallpaper.enable = true; foot.enable = true; tofi.enable = true; }; wallpapers.enable = true; services = { dunst.enable = true; wallpaper = { enable = true; target = "river-session.target"; }; spotify-player.target = "river-session.target"; }; }; home-manager.users.moritz = { home.packages = with pkgs; [ rivercarro ]; services.kanshi = { enable = true; systemdTarget = "river-session.target"; }; wayland.windowManager.river = { enable = true; package = pkgs.river.overrideAttrs (old: { src = inputs.river; version = lib.my.mkVersionInput inputs.river; # HACK: to change wlroots to 0.17.x buildInputs = with pkgs; [ libGL libevdev libinput libxkbcommon pixman udev wayland-protocols wlroots_0_17 xorg.libX11 ]; }); settings = { border-width = 2; declare-mode = [ "locked" "normal" "passthrough" ]; map = { normal = { "Super Q" = "close"; "Super Return" = ''spawn "systemctl --user is-active --quiet foot && footclient --no-wait || foot"''; "Super+Shift Return" = "spawn foot"; "Super R" = ''spawn 'exec $(tofi-run --fuzzy-match=true)' ''; "Super W" = ''spawn "pkill -USR1 waybar"''; "Super+Shift R" = "spawn ~/.config/river/init"; # Focus view "Super J" = "focus-view next"; "Super K" = "focus-view previous"; # swap the focused view "Super+Shift J" = "swap next"; "Super+Shift K" = "swap previous"; # focus output "Super Period" = "focus-output next"; "Super Comma" = "focus-output previous"; # send to output "Super+Shift Period" = "send-to-output next"; "Super+Shift Comma" = "send-to-output previous"; # bump in layout stack "Super Z" = "zoom"; } // # tags ( let numbers = range 1 9; toTag = num: "$((1 << (${toString num} - 1)))"; mkMappings = num: let numStr = toString num; tag = toTag num; in [ # Super+Control+[1-9] to toggle focus of tag [0-8] { name = "Super ${numStr}"; value = "toggle-focused-tags ${tag}"; } # Super+Shift+Control+[1-9] to toggle tag [0-8] of focused view { name = "Super+Shift ${numStr}"; value = "toggle-view-tags ${tag}"; } ]; mappings = flatten (map mkMappings numbers); in listToAttrs mappings ); }; map-pointer = { normal = { "Super BTN_LEFT" = "move-view"; "Super BTN_RIGHT" = "resize-view"; "Super BTN_MIDDLE" = "toggle-float"; }; }; attach-mode = "bottom"; default-layout = "rivercarro"; focus-follows-cursor = "normal"; hide-cursor = { timeout = "1500"; when-typing = "enabled"; }; set-cursor-warp = "on-focus-change"; }; extraConfig = /* bash */ '' rivercarro_pid="$(pidof rivercarro)" if [[ -z $rivercarro_pid ]]; then rivercarro -inner-gaps 4 -outer-gaps 4 & fi ''; }; # add waybar as a status bar programs.waybar = { enable = true; # start using systemd service systemd = { enable = true; target = "river-session.target"; }; settings = { mainBar = { start_hidden = true; layer = "top"; position = "top"; height = 20; modules-left = [ "river/tags" ]; modules-center = [ "river/window" ]; modules-right = [ "network" "memory" "cpu" "battery" "clock" ]; }; }; style = '' #tags button.focused { color: #ffffff } ''; }; # lock screen after timeout programs.swaylock = { enable = true; settings = { color = "000000"; }; }; services.swayidle = { enable = true; events = [ { event = "before-sleep"; command = "${getExe pkgs.swaylock} -fF"; } { event = "lock"; command = "${getExe pkgs.swaylock} -fF"; } ]; timeouts = let lockTimeout = 10; in [ { timeout = lockTimeout * 60 - 10; command = "${pkgs.libnotify}/bin/notify-send 'Locking screen!'"; } { timeout = lockTimeout * 60 + 10; command = "${pkgs.systemd}/bin/loginctl lock-session"; } ]; systemdTarget = "river-session.target"; }; }; # adds pam module for swaylock security.pam.services.swaylock = { }; # add user packages for wayland and hyprland in particular users.users.moritz.packages = with pkgs; [ brightnessctl # control brightness grimblast # screenshot tool for hyprland pamixer # pulse audio cli playerctl # control media playback slurp # region select for wayland (for screensharing) wdisplays # manage monitors wl-clipboard # clipboard tool for wayland ]; # additional environment variables environment.sessionVariables = { XDG_CURRENT_DESKTOP = "river"; XDG_SESSION_TYPE = "wayland"; XDG_SESSION_DESKTOP = "river"; QT_AUTO_SCREEN_SCALE_FACTOR = "1"; QT_QPA_PLATFORM = "wayland;xcb"; QT_WAYLAND_DISABLE_WINDOWDECORATION = "1"; QT_QPA_PLATFORMTHEME = "qt5ct"; _JAVA_AWT_WM_NONEREPARENTING = "1"; } // (optionalAttrs cfg.nvidiaSupport { GBM_BACKEND = "nvidia-drm"; GDK_BACKEND = "wayland"; LIBVA_DRIVER_NAME = "nvidia"; MOZ_ENABLE_WAYLAND = "1"; WLR_DRM_DEVICES = "/dev/dri/card0"; WLR_DRM_NO_ATOMIC = "1"; WLR_NO_HARDWARE_CURSORS = "1"; XDG_CURRENT_DESKTOP = "river"; _GL_GSYNC_ALLOWED = "0"; __GLX_VENDOR_LIBRARY_NAME = "nvidia"; __GL_VRR_ALLOWED = "0"; }); services = { dbus.enable = true; # use pipewire (needed for screensharing) pipewire = { enable = true; alsa.enable = true; alsa.support32Bit = true; pulse.enable = true; }; xserver = { enable = true; displayManager = { lightdm.enable = true; autoLogin = { enable = true; user = "moritz"; }; defaultSession = "river"; }; }; }; security.rtkit.enable = true; home-manager.users.moritz.systemd.user.services = let units = [ "waybar" ]; mkAfter = _: { Unit = { After = [ "river-session.target" ]; Wants = [ "river-session.target" ]; }; }; in genAttrs units mkAfter; systemd.user.services = let units = [ "pipewire" "xdg-desktop-portal" "wireplumber" ]; mkAfter = _: { after = [ "river-session.target" ]; wants = [ "river-session.target" ]; }; in genAttrs units mkAfter; }; }