aboutsummaryrefslogtreecommitdiffstats
path: root/modules/by-name/ri/river
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xmodules/by-name/ri/river/init_base.sh5
-rw-r--r--modules/by-name/ri/river/keymap.nix192
-rw-r--r--modules/by-name/ri/river/module.nix95
-rw-r--r--modules/by-name/ri/river/river-start/package.nix (renamed from pkgs/by-name/ri/river-start/package.nix)4
-rwxr-xr-xmodules/by-name/ri/river/river-start/river-start.sh (renamed from pkgs/by-name/ri/river-start/river-start.sh)3
5 files changed, 281 insertions, 18 deletions
diff --git a/modules/by-name/ri/river/init_base.sh b/modules/by-name/ri/river/init_base.sh
index b92f59e0..edd7827f 100755
--- a/modules/by-name/ri/river/init_base.sh
+++ b/modules/by-name/ri/river/init_base.sh
@@ -10,8 +10,9 @@
# You should have received a copy of the License along with this program.
# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
-# NOTE: Keep this in sync with the file from `river-start` <2025-02-03>
-RIVER_LOG_FILE="$HOME/.local/share/river/log"
+RIVER_LOG_FILE="$HOME/.cache/river/init-log"
+
+echo >"$RIVER_LOG_FILE"
err_fail() {
if ! "$@"; then
diff --git a/modules/by-name/ri/river/keymap.nix b/modules/by-name/ri/river/keymap.nix
new file mode 100644
index 00000000..897d11df
--- /dev/null
+++ b/modules/by-name/ri/river/keymap.nix
@@ -0,0 +1,192 @@
+{
+ lib,
+ pkgs,
+ libraries,
+ config,
+ ...
+}: let
+ index2tag = input: builtins.toString (libraries.base.pow 2 (input - 1));
+
+ mkTagCommand = name: index: [name (index2tag index)];
+ mkSpawn' = pkg: binaryName: args: further: (further
+ // (let
+ maybeSpace =
+ if args == ""
+ then ""
+ else " ";
+ maybeQuote =
+ if args == ""
+ then ""
+ else "\"";
+ in {
+ command = [
+ "spawn"
+ "${lib.getExe pkgs.notify-run} \"${lib.getExe' pkg binaryName}\"${maybeSpace}${maybeQuote}${args}${maybeQuote}"
+ ];
+
+ description = "${binaryName}${maybeSpace}${args}";
+ }));
+
+ mkSpawn = pkg: args: further: (mkSpawn' pkg pkg.meta.mainProgram args further);
+
+ setMode = path: {
+ command = [
+ "enter-mode"
+ (builtins.concatStringsSep "" path)
+ ];
+ };
+
+ cfg = config.soispha.programs.river;
+ inherit (config.soispha.services.mpd.mpc) mppPackage;
+in {
+ soispha.programs.river.init.mappings.keymap = lib.mkIf cfg.enable (lib.fixedPoints.fix
+ (self: {
+ "<LEFT_SUPER>" = {
+ # Spawn standard programs
+ "r" = {
+ "a" = mkSpawn' pkgs.foot "footclient" "" {};
+ "b" = mkSpawn pkgs.tskm "open select" {once = true;};
+ "k" = mkSpawn pkgs.keepassxc "" {once = true;};
+ # "s" = mkSpawn pkgs.signal-desktop "" {once = true;};
+ "p" = mkSpawn pkgs.screenshot_persistent "" {once = true;};
+ "i" = mkSpawn pkgs.anki "" {once = true;};
+ };
+
+ # Client changes
+ "c" = {
+ "F" = setMode ["<LEFT_META>" "f"];
+
+ "f" = ["toggle-fullscreen"];
+ "c" = ["close"];
+ " " = ["toggle-float"];
+ "<ENTER>" = ["zoom"];
+ };
+
+ # This is a fill in for <Super-L>, as that is otherwise nearly impossible to input.
+ "l" = self."<LEFT_SUPER>".x.l;
+
+ # River compositor control.
+ "x" = {
+ "q" = ["exit"];
+ "l" = mkSpawn pkgs.lock "" {once = true;};
+ "h" = mkSpawn pkgs.systemd-toggle "--user i3bar-river.service" {once = true;};
+ };
+
+ # Media control
+ "m" = {
+ "u" = mkSpawn' pkgs.wireplumber "wpctl" "set-volume @DEFAULT_SINK@ 5%+" {};
+ "d" = mkSpawn' pkgs.wireplumber "wpctl" "set-volume @DEFAULT_SINK@ 5%-" {};
+ "m" = mkSpawn' pkgs.wireplumber "wpctl" "set-mute @DEFAULT_SINK@ toggle" {};
+ "n" = mkSpawn mppPackage "next" {};
+ "p" = mkSpawn mppPackage "prev" {};
+ "t" = mkSpawn mppPackage "toggle" {};
+ "g" = mkSpawn' pkgs.mpdpopm "mpdpopm" "rating inc" {once = true;};
+ "b" = mkSpawn' pkgs.mpdpopm "mpdpopm" "rating decr" {once = true;};
+ };
+
+ # Select tags for view.
+ "v" = {
+ "c" = setMode ["<LEFT_META>" "c"];
+ "f" = setMode ["<LEFT_META>" "f"];
+
+ "t" = ["swap" "next"];
+ "n" = ["swap" "previous"];
+ "T" = ["send-to-output" "next"];
+ "N" = ["send-to-output" "previous"];
+
+ "0" = ["set-view-tags" (builtins.toString ((libraries.base.pow 2 32) - 1))];
+ "p" = ["send-to-previous-tags"];
+
+ "1" = mkTagCommand "set-view-tags" 1;
+ "2" = mkTagCommand "set-view-tags" 2;
+ "3" = mkTagCommand "set-view-tags" 3;
+ "4" = mkTagCommand "set-view-tags" 4;
+ "5" = mkTagCommand "set-view-tags" 5;
+ "6" = mkTagCommand "set-view-tags" 6;
+ "7" = mkTagCommand "set-view-tags" 7;
+ "8" = mkTagCommand "set-view-tags" 8;
+ "9" = mkTagCommand "set-view-tags" 9;
+
+ # Add tags to view.
+ "a" = {
+ "1" = mkTagCommand "toggle-view-tags" 1;
+ "2" = mkTagCommand "toggle-view-tags" 2;
+ "3" = mkTagCommand "toggle-view-tags" 3;
+ "4" = mkTagCommand "toggle-view-tags" 4;
+ "5" = mkTagCommand "toggle-view-tags" 5;
+ "6" = mkTagCommand "toggle-view-tags" 6;
+ "7" = mkTagCommand "toggle-view-tags" 7;
+ "8" = mkTagCommand "toggle-view-tags" 8;
+ "9" = mkTagCommand "toggle-view-tags" 9;
+ };
+ };
+
+ # Select tags to focus,
+ # and change focus
+ "f" = {
+ "c" = setMode ["<LEFT_META>" "c"];
+ "v" = setMode ["<LEFT_META>" "v"];
+
+ "t" = ["focus-view" "next"];
+ "n" = ["focus-view" "previous"];
+ "T" = ["focus-output" "next"];
+ "N" = ["focus-output" "previous"];
+
+ "0" = ["set-focused-tags" (builtins.toString ((libraries.base.pow 2 32) - 1))];
+ "p" = ["focus-previous-tags"];
+
+ "1" = mkTagCommand "set-focused-tags" 1;
+ "2" = mkTagCommand "set-focused-tags" 2;
+ "3" = mkTagCommand "set-focused-tags" 3;
+ "4" = mkTagCommand "set-focused-tags" 4;
+ "5" = mkTagCommand "set-focused-tags" 5;
+ "6" = mkTagCommand "set-focused-tags" 6;
+ "7" = mkTagCommand "set-focused-tags" 7;
+ "8" = mkTagCommand "set-focused-tags" 8;
+ "9" = mkTagCommand "set-focused-tags" 9;
+ };
+ };
+
+ # Screen locking
+ "<Super-l>" = self."<LEFT_SUPER>".x.l;
+
+ # Audio
+ "<MEDIA_RAISEVOLUME>" =
+ self."<LEFT_SUPER>".m.u
+ // {
+ allow_locked = true;
+ };
+ "<MEDIA_LOWERVOLUME>" =
+ self."<LEFT_SUPER>".m.d
+ // {
+ allow_locked = true;
+ };
+ "<MEDIA_MUTEVOLUME>" =
+ self."<LEFT_SUPER>".m.m
+ // {
+ allow_locked = true;
+ };
+ "<MEDIA_TRACKNEXT>" =
+ self."<LEFT_SUPER>".m.n
+ // {
+ allow_locked = true;
+ };
+ "<MEDIA_TRACKPREVIOUS>" =
+ self."<LEFT_SUPER>".m.p
+ // {
+ allow_locked = true;
+ };
+ "<MEDIA_PLAY>" =
+ self."<LEFT_SUPER>".m.t
+ // {
+ allow_locked = true;
+ };
+
+ # Mouse
+ "<Alt-<MOUSE_LEFT>>" = ["move-view"];
+ "<Alt-<MOUSE_RIGHT>>" = ["resize-view"];
+
+ # Screenshot
+ "<PRINTSCREEN>" = self."<LEFT_SUPER>".r.p;
+ }));
+}
diff --git a/modules/by-name/ri/river/module.nix b/modules/by-name/ri/river/module.nix
index 63e25f62..f9ecea0f 100644
--- a/modules/by-name/ri/river/module.nix
+++ b/modules/by-name/ri/river/module.nix
@@ -10,14 +10,16 @@
{
config,
lib,
- qmk_firmware,
system,
pkgs,
+ externalBinaries,
...
}: let
cfg = config.soispha.programs.river;
esa = lib.strings.escapeShellArg;
- riverctl = lib.getExe' pkgs.river "riverctl";
+ riverctl = lib.getExe' cfg.package "riverctl";
+
+ river-start = pkgs.callPackage ./river-start/package.nix {};
mkOutputFlags = output: flags: let
expandedFlags = builtins.concatStringsSep " " (lib.attrsets.mapAttrsToList (flag: value: "--${esa flag} ${esa value}") flags);
@@ -33,13 +35,27 @@
else builtins.map esa input
);
in "err_fail ${program} &";
- longRunningPrograms = builtins.concatStringsSep "\n" (builtins.map mkLrProgram cfg.init.backgroundStart);
+ longRunningPrograms =
+ builtins.concatStringsSep "\n" (builtins.map mkLrProgram
+ cfg.init.autoStart);
keymapFormat = pkgs.formats.json {};
+ keymapGenerate = name: value:
+ pkgs.runCommandLocal "mk-${name}-and-check" {
+ nativeBuildInputs = [pkgs.river-mk-keymap];
+ preferLocalBuild = true;
+
+ env = {
+ JSON_FILE = keymapFormat.generate name value;
+ };
+ } ''
+ river-mk-keymap --keymap "$JSON_FILE" init --dry-run;
+ cp "$JSON_FILE" "$out"
+ '';
keymappings = ''
err_fail ${riverctl} keyboard-layout ${esa cfg.init.mappings.layout}
- err_fail ${lib.getExe pkgs.river-mk-keymap} ${keymapFormat.generate "keys.json" cfg.init.mappings.keymap}
+ err_fail ${lib.getExe pkgs.river-mk-keymap} --keymap ${keymapGenerate "keys.json" cfg.init.mappings.keymap} init
'';
mkRule = {
@@ -72,6 +88,8 @@ in {
options.soispha.programs.river = {
enable = lib.mkEnableOption "river";
+ package = lib.mkPackageOption pkgs "river-classic" {};
+
unicodeInput = {
enable = lib.mkEnableOption "udev rules for rawhid based unicode input";
};
@@ -147,12 +165,14 @@ in {
'';
};
- backgroundStart = lib.mkOption {
- type = lib.types.listOf (lib.types.either lib.types.package (lib.types.listOf lib.types.str));
- description = "List of programs to start in the background";
+ autoStart = lib.mkOption {
+ type =
+ lib.types.listOf (lib.types.either lib.types.package (lib.types.listOf
+ lib.types.str));
+ description = "List of programs to be started at river start";
example = ''
[
- pkgs.gammastep
+ ''${lib.getExe pkgs.foot}
]
'';
};
@@ -175,10 +195,25 @@ in {
};
};
+ imports = [
+ ./keymap.nix
+ ];
+
config = lib.mkIf cfg.enable {
- services.udev.packages = lib.mkIf cfg.unicodeInput.enable [qmk_firmware.packages.${system}.qmk_unicode_type];
+ services.udev.packages = lib.mkIf cfg.unicodeInput.enable [externalBinaries.qmk_firmware.packages.${system}.qmk_unicode_type];
home-manager.users.soispha = {
+ xdg.desktopEntries."river" = {
+ name = "river";
+ exec = lib.getExe river-start;
+ comment = "A non-monolithic Wayland compositor";
+
+ settings = {
+ X-DesktopNames = "river";
+ Type = "Application";
+ };
+ };
+
home.sessionVariables = {
WM = "river";
XDG_CURRENT_DESKTOP = "river";
@@ -193,7 +228,8 @@ in {
};
home.packages = [
- pkgs.river-start
+ river-start
+ pkgs.sw
];
xdg.configFile."river/init" = {
@@ -203,14 +239,49 @@ in {
# ${text}
${other_stuff}
'';
+
+ sessionVars =
+ (builtins.attrNames config.environment.sessionVariables)
+ ++ (builtins.attrNames config.home-manager.users.soispha.home.sessionVariables)
+ ++ [
+ "WAYLAND_DISPLAY"
+ "DISPLAY"
+ "XDG_RUNTIME_DIR"
+ ];
+
+ part = acc: vars: let
+ firstTen = lib.lists.take 5 vars;
+ in
+ if firstTen == []
+ then acc
+ else part (acc ++ [firstTen]) (lib.lists.removePrefix firstTen vars);
+
+ partedSessionVars = part [] sessionVars;
+
+ mkEnvSet = prefix: vars: let
+ stringVars = builtins.concatStringsSep " " vars;
+ in ''err_fail ${riverctl} spawn "${prefix} ${stringVars}"'';
+
+ dbusEnvs =
+ builtins.map
+ (mkEnvSet "${lib.getExe' pkgs.dbus "dbus-update-activation-environment"} --verbose --systemd")
+ partedSessionVars;
+ systemdUserEnvs =
+ builtins.map
+ (mkEnvSet "systemctl --user --verbose import-environment")
+ partedSessionVars;
in
builtins.readFile ./init_base.sh
+
# bash
mkHeading "Environment variables" ''
- err_fail ${riverctl} spawn "${lib.getExe' pkgs.dbus "dbus-update-activation-environment"} --verbose --systemd SEATD_SOCK DISPLAY WAYLAND_DISPLAY DESKTOP_SESSION=river XDG_CURRENT_DESKTOP=river"
export XDG_CURRENT_DESKTOP=river DESKTOP_SESSION=river;
''
+ + mkHeading "Informing dbus about changed env-vars" (builtins.concatStringsSep "\n" dbusEnvs)
+ + mkHeading "Informing systemd user about changed env-vars" (builtins.concatStringsSep "\n" systemdUserEnvs)
+ + mkHeading "Starting graphical-session-target" ''
+ err_fail systemctl --user start nixos-fake-graphical-session.target
+ ''
+ mkHeading "Key Mappings" keymappings
+ mkHeading "Rules" ruleSetup
+ mkHeading "General Settings" generalSettings
@@ -219,7 +290,7 @@ in {
+ mkHeading "Background services" longRunningPrograms
+ mkHeading "Layout Setup" ''
err_fail ${riverctl} default-layout rivertile
- ${lib.getExe' pkgs.river "rivertile"} -main-ratio 0.5 -view-padding 1 -outer-padding 0
+ ${lib.getExe' cfg.package "rivertile"} -main-ratio 0.5 -view-padding 1 -outer-padding 0
'';
};
};
diff --git a/pkgs/by-name/ri/river-start/package.nix b/modules/by-name/ri/river/river-start/package.nix
index 10957cc0..3ae204b7 100644
--- a/pkgs/by-name/ri/river-start/package.nix
+++ b/modules/by-name/ri/river/river-start/package.nix
@@ -9,13 +9,13 @@
# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
{
writeShellApplication,
- river,
+ river-classic,
}:
writeShellApplication {
name = "river-start";
text = builtins.readFile ./river-start.sh;
runtimeInputs = [
- river
+ river-classic
];
meta = {
mainProgram = "river-start";
diff --git a/pkgs/by-name/ri/river-start/river-start.sh b/modules/by-name/ri/river/river-start/river-start.sh
index e3a4adcb..55eddfcf 100755
--- a/pkgs/by-name/ri/river-start/river-start.sh
+++ b/modules/by-name/ri/river/river-start/river-start.sh
@@ -10,8 +10,7 @@
# You should have received a copy of the License along with this program.
# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
-# NOTE: Keep this in sync with the file from `base_init.sh` <2025-02-03>
-RIVER_LOG_FILE="$HOME/.local/share/river/log"
+RIVER_LOG_FILE="$HOME/.cache/river/wm-log"
[ -d "$(dirname "$RIVER_LOG_FILE")" ] || mkdir --parents "$(dirname "$RIVER_LOG_FILE")"