river: add module
This commit is contained in:
parent
517601b37c
commit
3dda8e795f
|
@ -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'.
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
212
modules/services/window-managers/river.nix
Normal file
212
modules/services/window-managers/river.nix
Normal 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" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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}"
|
||||
'';
|
||||
}
|
1
tests/modules/services/window-managers/river/default.nix
Normal file
1
tests/modules/services/window-managers/river/default.nix
Normal file
|
@ -0,0 +1 @@
|
|||
{ river-configuration = ./configuration.nix; }
|
67
tests/modules/services/window-managers/river/init
Executable file
67
tests/modules/services/window-managers/river/init
Executable 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"
|
||||
|
||||
|
Loading…
Reference in a new issue