river: add module

This commit is contained in:
Gaetan Lepage 2023-08-11 11:09:54 +02:00 committed by Robert Helgesson
parent 517601b37c
commit 3dda8e795f
No known key found for this signature in database
GPG key ID: 96E745BD17AA17ED
7 changed files with 385 additions and 0 deletions

View file

@ -1414,6 +1414,14 @@ in {
A new module is available: 'programs.jetbrains-remote'
'';
}
{
time = "2024-02-21T23:01:27+00:00";
condition = hostPlatform.isLinux;
message = ''
A new module is available: 'wayland.windowManager.river'.
'';
}
];
};
}

View file

@ -364,6 +364,7 @@ let
./services/window-managers/i3-sway/i3.nix
./services/window-managers/i3-sway/sway.nix
./services/window-managers/i3-sway/swaynag.nix
./services/window-managers/river.nix
./services/window-managers/spectrwm.nix
./services/window-managers/xmonad.nix
./services/wlsunset.nix

View file

@ -0,0 +1,212 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) types;
cfg = config.wayland.windowManager.river;
# Systemd integration
variables = builtins.concatStringsSep " " cfg.systemd.variables;
extraCommands = builtins.concatStringsSep " "
(map (f: "&& ${f}") cfg.systemd.extraCommands);
systemdActivation = ''
exec "${pkgs.dbus}/bin/dbus-update-activation-environment --systemd ${variables} ${extraCommands}"
'';
toValue = val:
if lib.isString val || lib.isDerivation val then
toString val
else if true == val then
"enabled"
else if false == val then
"disabled"
else if lib.isInt val then
toString val
else if lib.isFloat val then
lib.strings.floatToString val
else
abort "unsupported type ${builtins.typeOf val}";
# Intermediary function that converts some value (attrs, str, ...) to one or several commands.
toArgs = path: value:
let
stringValue = lib.concatStringsSep " " (path ++ [ (toValue value) ]);
finalValue = if lib.isAttrs value then
toCommand path value
else if lib.isList value then
lib.lists.flatten (map (x: toArgs path x) value)
else if value == null then
[ ]
else
[ stringValue ];
in finalValue;
# toCommand :: [string] -> attrs -> [string]
# Recursive function that converts an attrs to a list of commands that can be written to the
# config file.
toCommand = basePath: attrs:
lib.concatLists (lib.mapAttrsToList
(key: value: let path = basePath ++ [ key ]; in toArgs path value) attrs);
in {
meta.maintainers = [ lib.maintainers.GaetanLepage ];
options.wayland.windowManager.river = {
enable = lib.mkEnableOption "the river window manager";
package = lib.mkPackageOption pkgs "river" {
nullable = true;
extraDescription = ''
Set to `null` to not add any river package to your path.
This should be done if you want to use the NixOS river module to install river.
'';
};
xwayland.enable = lib.mkEnableOption "XWayland" // { default = true; };
systemd = {
enable = lib.mkEnableOption null // {
default = true;
description = ''
Whether to enable {file}`river-session.target` on
river startup. This links to {file}`graphical-session.target`}.
Some important environment variables will be imported to systemd
and D-Bus user environment before reaching the target, including
- `DISPLAY`
- `WAYLAND_DISPLAY`
- `XDG_CURRENT_DESKTOP`
- `NIXOS_OZONE_WL`
- `XCURSOR_THEME`
- `XCURSOR_SIZE`
'';
};
variables = lib.mkOption {
type = types.listOf types.str;
default = [
"DISPLAY"
"WAYLAND_DISPLAY"
"XDG_CURRENT_DESKTOP"
"NIXOS_OZONE_WL"
"XCURSOR_THEME"
"XCURSOR_SIZE"
];
example = [ "-all" ];
description = ''
Environment variables to be imported in the systemd & D-Bus user
environment.
'';
};
extraCommands = lib.mkOption {
type = types.listOf types.str;
default = [
"systemctl --user stop river-session.target"
"systemctl --user start river-session.target"
];
description = "Extra commands to be run after D-Bus activation.";
};
};
extraSessionVariables = lib.mkOption {
type = types.attrs;
default = { };
description = "Extra session variables set when running the compositor.";
example = { MOZ_ENABLE_WAYLAND = "1"; };
};
settings = lib.mkOption {
type = let
valueType = with types;
nullOr (oneOf [
bool
int
float
str
path
(attrsOf valueType)
(listOf valueType)
]) // {
description = "River configuration value";
};
in valueType;
default = { };
description = "General settings given to `riverctl`.";
example = {
border-width = 2;
declare-mode = [ "locked" "normal" "passthrough" ];
map.normal."Alt Q" = "close";
input.pointer-foo-bar = {
accel-profile = "flat";
events = true;
pointer-accel = -0.3;
tap = false;
};
rule-add."-app-id" = {
"'bar'" = "csd";
"'float*'"."-title"."'foo'" = "float";
};
set-cursor-warp = "on-output-change";
set-repeat = "50 300";
xcursor-theme = "someGreatTheme 12";
spawn = [ "firefox" "'foot -a terminal'" ];
};
};
extraConfig = lib.mkOption {
type = types.lines;
default = "";
example = ''
rivertile -view-padding 6 -outer-padding 6 &
'';
description =
"Extra lines appended to {file}`$XDG_CONFIG_HOME/river/init`.";
};
};
config = lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "wayland.windowManager.river" pkgs
lib.platforms.linux)
];
home.packages = lib.optional (cfg.package != null) cfg.package
++ lib.optional cfg.xwayland.enable pkgs.xwayland;
# Configuration file ~/.config/river/init
xdg.configFile."river/init".source = pkgs.writeShellScript "init" (''
### This file was generated with Nix. Don't modify this file directly.
### SHELL VARIABLES ###
${config.lib.shell.exportAll cfg.extraSessionVariables}
### CONFIGURATION ###
${lib.concatStringsSep "\n" (toCommand [ "riverctl" ] cfg.settings)}
### EXTRA CONFIGURATION ###
${cfg.extraConfig}
'' + (lib.optionalString cfg.systemd.enable ''
### SYSTEMD INTEGRATION ###
${systemdActivation}
''));
# Systemd integration
systemd.user.targets.river-session = lib.mkIf cfg.systemd.enable {
Unit = {
Description = "river compositor session";
Documentation = [ "man:systemd.special(7)" ];
BindsTo = [ "graphical-session.target" ];
Wants = [ "graphical-session-pre.target" ];
After = [ "graphical-session-pre.target" ];
};
};
systemd.user.targets.tray = {
Unit = {
Description = "Home Manager System Tray";
Requires = [ "graphical-session-pre.target" ];
};
};
};
}

View file

@ -260,6 +260,7 @@ in import nmtSrc {
./modules/services/window-managers/herbstluftwm
./modules/services/window-managers/hyprland
./modules/services/window-managers/i3
./modules/services/window-managers/river
./modules/services/window-managers/spectrwm
./modules/services/window-managers/sway
./modules/services/wlsunset

View file

@ -0,0 +1,95 @@
{ ... }:
{
wayland.windowManager.river = {
enable = true;
xwayland.enable = true;
extraSessionVariables = {
FOO = "foo";
BAR = "bar";
FOURTY_TWO = 42;
};
# systemdIntegration = true;
settings = {
attach-mode = "bottom";
background-color = "0x002b36";
border-color-focused = "0x93a1a1";
border-color-unfocused = "0x586e75";
border-color-urgent = "0xff0000";
border-width = 2;
csd-filter-add.app-id = [ "bar" "foo" ];
declare-mode = [ "locked" "normal" "passthrough" ];
default-layout = "rivertile";
float-filter-add.app-id = "mpd";
float-filter-add.title = "popup title with spaces";
focus-follows-cursor = "normal";
hide-cursor.timeout = 2;
hide-cursor.when-typing = true;
input.pointer-foo-bar = {
accel-profile = "flat";
events = true;
pointer-accel = -0.3;
tap = false;
};
keyboard-layout."-variant".colemak."-options"."altwin:swap_alt_wincaps:escapegrp:alt_shift_toggle" =
"us,de";
map.locked.None.XF86AudioLowerVolume.spawn = "'pamixer -d 5'";
map.locked.None.XF86AudioRaiseVolume.spawn = "'pamixer -i 5'";
map.normal."Alt E" = "toggle-fullscreen";
map.normal."Alt P" = "enter-mode passthrough";
map.normal."Alt Q" = "close";
map.normal."Alt Return" = "spawn foot";
map.normal."Alt T" = "toggle-float";
map.passthrough."Alt P" = "enter-mode normal";
map-pointer.normal."Alt BTN_LEFT" = "move-view";
map-pointer.normal."Super BTN_LEFT" = "move-view";
map-pointer.normal."Super BTN_MIDDLE" = "toggle-float";
map-pointer.normal."Super BTN_RIGHT" = "resize-view";
map-switch = {
locked = {
lid.open = "foo";
tablet.on = "foo";
};
normal = {
lid = {
close = "foo";
open = "foo";
};
tablet = {
off = "foo bar";
on = "foo";
};
};
};
rule-add."-app-id" = {
"'bar'" = "csd";
"'float*'"."-title"."'foo'" = "float";
};
set-cursor-warp = "on-output-change";
set-repeat = "50 300";
xcursor-theme = "someGreatTheme 12";
spawn = [ "firefox" "'foot -a terminal'" ];
};
extraConfig = ''
rivertile -view-padding 6 -outer-padding 6 &
some
extra config
'';
};
test.stubs = {
dbus = { };
river = { };
xwayland = { };
};
nmt.script = ''
riverInit=home-files/.config/river/init
assertFileExists "$riverInit"
assertFileIsExecutable "$riverInit"
normalizedConfig=$(normalizeStorePaths "$riverInit")
assertFileContent "$normalizedConfig" "${./init}"
'';
}

View file

@ -0,0 +1 @@
{ river-configuration = ./configuration.nix; }

View file

@ -0,0 +1,67 @@
#!/nix/store/00000000000000000000000000000000-bash/bin/bash
### This file was generated with Nix. Don't modify this file directly.
### SHELL VARIABLES ###
export BAR="bar"
export FOO="foo"
export FOURTY_TWO="42"
### CONFIGURATION ###
riverctl attach-mode bottom
riverctl background-color 0x002b36
riverctl border-color-focused 0x93a1a1
riverctl border-color-unfocused 0x586e75
riverctl border-color-urgent 0xff0000
riverctl border-width 2
riverctl csd-filter-add app-id bar
riverctl csd-filter-add app-id foo
riverctl declare-mode locked
riverctl declare-mode normal
riverctl declare-mode passthrough
riverctl default-layout rivertile
riverctl float-filter-add app-id mpd
riverctl float-filter-add title popup title with spaces
riverctl focus-follows-cursor normal
riverctl hide-cursor timeout 2
riverctl hide-cursor when-typing enabled
riverctl input pointer-foo-bar accel-profile flat
riverctl input pointer-foo-bar events enabled
riverctl input pointer-foo-bar pointer-accel -0.300000
riverctl input pointer-foo-bar tap disabled
riverctl keyboard-layout -variant colemak -options altwin:swap_alt_wincaps:escapegrp:alt_shift_toggle us,de
riverctl map locked None XF86AudioLowerVolume spawn 'pamixer -d 5'
riverctl map locked None XF86AudioRaiseVolume spawn 'pamixer -i 5'
riverctl map normal Alt E toggle-fullscreen
riverctl map normal Alt P enter-mode passthrough
riverctl map normal Alt Q close
riverctl map normal Alt Return spawn foot
riverctl map normal Alt T toggle-float
riverctl map passthrough Alt P enter-mode normal
riverctl map-pointer normal Alt BTN_LEFT move-view
riverctl map-pointer normal Super BTN_LEFT move-view
riverctl map-pointer normal Super BTN_MIDDLE toggle-float
riverctl map-pointer normal Super BTN_RIGHT resize-view
riverctl map-switch locked lid open foo
riverctl map-switch locked tablet on foo
riverctl map-switch normal lid close foo
riverctl map-switch normal lid open foo
riverctl map-switch normal tablet off foo bar
riverctl map-switch normal tablet on foo
riverctl rule-add -app-id 'bar' csd
riverctl rule-add -app-id 'float*' -title 'foo' float
riverctl set-cursor-warp on-output-change
riverctl set-repeat 50 300
riverctl spawn firefox
riverctl spawn 'foot -a terminal'
riverctl xcursor-theme someGreatTheme 12
### EXTRA CONFIGURATION ###
rivertile -view-padding 6 -outer-padding 6 &
some
extra config
### SYSTEMD INTEGRATION ###
exec "@dbus@/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY XDG_CURRENT_DESKTOP NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE && systemctl --user stop river-session.target && systemctl --user start river-session.target"