@@ -11,134 +11,223 @@ |
| 11 | 11 | }; |
| 12 | 12 | |
| 13 | 13 | outputs = { self, nixpkgs, flake-utils, rust-overlay }: |
| 14 | | - flake-utils.lib.eachDefaultSystem (system: |
| 15 | | - let |
| 16 | | - pkgs = import nixpkgs { |
| 17 | | - inherit system; |
| 18 | | - overlays = [ rust-overlay.overlays.default ]; |
| 19 | | - }; |
| 20 | | - |
| 21 | | - # Build dependencies |
| 22 | | - buildDeps = with pkgs; [ |
| 23 | | - pkg-config |
| 24 | | - ]; |
| 25 | | - |
| 26 | | - # Runtime/library dependencies |
| 27 | | - libDeps = with pkgs; [ |
| 28 | | - # Wayland |
| 29 | | - wayland |
| 30 | | - wayland-protocols |
| 31 | | - |
| 32 | | - # For smithay-client-toolkit |
| 33 | | - libxkbcommon |
| 34 | | - |
| 35 | | - # TLS |
| 36 | | - openssl |
| 37 | | - |
| 38 | | - # GUI (Iced) dependencies |
| 39 | | - vulkan-loader |
| 40 | | - libGL |
| 41 | | - xorg.libX11 |
| 42 | | - xorg.libXcursor |
| 43 | | - xorg.libXrandr |
| 44 | | - xorg.libXi |
| 45 | | - ]; |
| 46 | | - |
| 47 | | - rustToolchain = pkgs.rust-bin.stable.latest.default.override { |
| 48 | | - extensions = [ "rust-src" "rust-analyzer" ]; |
| 49 | | - }; |
| 50 | | - in |
| 51 | | - { |
| 52 | | - # Development shell |
| 53 | | - devShells.default = pkgs.mkShell { |
| 54 | | - buildInputs = buildDeps ++ libDeps ++ [ |
| 55 | | - rustToolchain |
| 56 | | - ]; |
| 57 | | - |
| 58 | | - # Set up pkg-config paths |
| 59 | | - PKG_CONFIG_PATH = pkgs.lib.makeSearchPath "lib/pkgconfig" libDeps; |
| 60 | | - |
| 61 | | - # For wayland-scanner |
| 62 | | - WAYLAND_PROTOCOLS = "${pkgs.wayland-protocols}/share/wayland-protocols"; |
| 63 | | - |
| 64 | | - # Graphics library paths for GUI |
| 65 | | - LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath libDeps; |
| 66 | | - |
| 67 | | - shellHook = '' |
| 68 | | - echo "HyprKVM development shell" |
| 69 | | - echo "Rust: $(rustc --version)" |
| 70 | | - echo "" |
| 71 | | - echo "Run 'cargo build' to compile" |
| 72 | | - ''; |
| 73 | | - }; |
| 14 | + let |
| 15 | + # System-independent outputs |
| 16 | + systemIndependent = { |
| 17 | + # Home-manager module for easy service management |
| 18 | + homeManagerModules.default = { config, lib, pkgs, ... }: |
| 19 | + let |
| 20 | + cfg = config.services.hyprkvm; |
| 21 | + in { |
| 22 | + options.services.hyprkvm = { |
| 23 | + enable = lib.mkEnableOption "HyprKVM daemon"; |
| 24 | + |
| 25 | + package = lib.mkOption { |
| 26 | + type = lib.types.package; |
| 27 | + default = self.packages.${pkgs.system}.default; |
| 28 | + defaultText = lib.literalExpression "pkgs.hyprkvm"; |
| 29 | + description = "The HyprKVM package to use."; |
| 30 | + }; |
| 31 | + |
| 32 | + settings = lib.mkOption { |
| 33 | + type = lib.types.attrs; |
| 34 | + default = {}; |
| 35 | + description = '' |
| 36 | + Configuration for HyprKVM. Will be written to |
| 37 | + ~/.config/hyprkvm/hyprkvm.toml |
| 38 | + ''; |
| 39 | + example = lib.literalExpression '' |
| 40 | + { |
| 41 | + machines = { |
| 42 | + self_name = "my-machine"; |
| 43 | + neighbors = [ |
| 44 | + { name = "other-machine"; direction = "right"; address = "192.168.1.100:24850"; } |
| 45 | + ]; |
| 46 | + }; |
| 47 | + network = { |
| 48 | + listen_port = 24850; |
| 49 | + }; |
| 50 | + } |
| 51 | + ''; |
| 52 | + }; |
| 53 | + |
| 54 | + extraFlags = lib.mkOption { |
| 55 | + type = lib.types.listOf lib.types.str; |
| 56 | + default = []; |
| 57 | + description = "Extra command-line flags to pass to the daemon."; |
| 58 | + }; |
| 59 | + }; |
| 60 | + |
| 61 | + config = lib.mkIf cfg.enable { |
| 62 | + # Install the package |
| 63 | + home.packages = [ cfg.package ]; |
| 64 | + |
| 65 | + # Generate config file if settings provided |
| 66 | + xdg.configFile."hyprkvm/hyprkvm.toml" = lib.mkIf (cfg.settings != {}) { |
| 67 | + source = (pkgs.formats.toml {}).generate "hyprkvm.toml" cfg.settings; |
| 68 | + }; |
| 69 | + |
| 70 | + # Systemd user service |
| 71 | + systemd.user.services.hyprkvm = { |
| 72 | + Unit = { |
| 73 | + Description = "HyprKVM Daemon - Hyprland-native software KVM switch"; |
| 74 | + After = [ "graphical-session.target" ]; |
| 75 | + PartOf = [ "graphical-session.target" ]; |
| 76 | + }; |
| 77 | + |
| 78 | + Service = { |
| 79 | + Type = "simple"; |
| 80 | + ExecStart = "${cfg.package}/bin/hyprkvm daemon ${lib.concatStringsSep " " cfg.extraFlags}"; |
| 81 | + Restart = "on-failure"; |
| 82 | + RestartSec = 1; |
| 83 | + # Exit code 75 triggers restart for direction changes |
| 84 | + RestartForceExitStatus = [ 75 ]; |
| 85 | + Environment = [ "WAYLAND_DISPLAY=wayland-1" ]; |
| 86 | + }; |
| 87 | + |
| 88 | + Install = { |
| 89 | + WantedBy = [ "graphical-session.target" ]; |
| 90 | + }; |
| 91 | + }; |
| 92 | + }; |
| 93 | + }; |
| 74 | 94 | |
| 75 | | - # Package (without GUI for smaller binary) |
| 76 | | - packages.default = pkgs.rustPlatform.buildRustPackage { |
| 77 | | - pname = "hyprkvm"; |
| 78 | | - version = "0.5.1"; |
| 79 | | - src = ./.; |
| 95 | + # Alias for backwards compatibility |
| 96 | + homeManagerModules.hyprkvm = self.homeManagerModules.default; |
| 97 | + }; |
| 80 | 98 | |
| 81 | | - cargoLock = { |
| 82 | | - lockFile = ./Cargo.lock; |
| 99 | + # System-specific outputs (packages, devShells) |
| 100 | + systemSpecific = flake-utils.lib.eachDefaultSystem (system: |
| 101 | + let |
| 102 | + pkgs = import nixpkgs { |
| 103 | + inherit system; |
| 104 | + overlays = [ rust-overlay.overlays.default ]; |
| 83 | 105 | }; |
| 84 | 106 | |
| 85 | | - nativeBuildInputs = buildDeps; |
| 86 | | - buildInputs = libDeps; |
| 107 | + # Build dependencies |
| 108 | + buildDeps = with pkgs; [ |
| 109 | + pkg-config |
| 110 | + ]; |
| 87 | 111 | |
| 88 | | - # Builds both hyprkvm (daemon) and hyprkvm-ctl (CLI) |
| 89 | | - # buildRustPackage automatically installs all workspace binaries |
| 112 | + # Runtime/library dependencies |
| 113 | + libDeps = with pkgs; [ |
| 114 | + # Wayland |
| 115 | + wayland |
| 116 | + wayland-protocols |
| 117 | + |
| 118 | + # For smithay-client-toolkit |
| 119 | + libxkbcommon |
| 120 | + |
| 121 | + # TLS |
| 122 | + openssl |
| 123 | + |
| 124 | + # GUI (Iced) dependencies |
| 125 | + vulkan-loader |
| 126 | + libGL |
| 127 | + xorg.libX11 |
| 128 | + xorg.libXcursor |
| 129 | + xorg.libXrandr |
| 130 | + xorg.libXi |
| 131 | + ]; |
| 90 | 132 | |
| 91 | | - meta = with pkgs.lib; { |
| 92 | | - description = "Hyprland-native software KVM switch"; |
| 93 | | - longDescription = '' |
| 94 | | - HyprKVM enables seamless keyboard/mouse control transfer between |
| 95 | | - Linux machines running Hyprland. Move past your last workspace |
| 96 | | - to switch to another machine. |
| 133 | + rustToolchain = pkgs.rust-bin.stable.latest.default.override { |
| 134 | + extensions = [ "rust-src" "rust-analyzer" ]; |
| 135 | + }; |
| 136 | + in |
| 137 | + { |
| 138 | + # Development shell |
| 139 | + devShells.default = pkgs.mkShell { |
| 140 | + buildInputs = buildDeps ++ libDeps ++ [ |
| 141 | + rustToolchain |
| 142 | + ]; |
| 143 | + |
| 144 | + # Set up pkg-config paths |
| 145 | + PKG_CONFIG_PATH = pkgs.lib.makeSearchPath "lib/pkgconfig" libDeps; |
| 146 | + |
| 147 | + # For wayland-scanner |
| 148 | + WAYLAND_PROTOCOLS = "${pkgs.wayland-protocols}/share/wayland-protocols"; |
| 149 | + |
| 150 | + # Graphics library paths for GUI |
| 151 | + LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath libDeps; |
| 152 | + |
| 153 | + shellHook = '' |
| 154 | + echo "HyprKVM development shell" |
| 155 | + echo "Rust: $(rustc --version)" |
| 156 | + echo "" |
| 157 | + echo "Run 'cargo build' to compile" |
| 97 | 158 | ''; |
| 98 | | - homepage = "https://github.com/tenseleyFlow/hyprKVM"; |
| 99 | | - license = licenses.mit; |
| 100 | | - platforms = platforms.linux; |
| 101 | | - mainProgram = "hyprkvm"; |
| 102 | 159 | }; |
| 103 | | - }; |
| 104 | 160 | |
| 105 | | - # Package with GUI support |
| 106 | | - packages.gui = pkgs.rustPlatform.buildRustPackage { |
| 107 | | - pname = "hyprkvm"; |
| 108 | | - version = "0.5.1"; |
| 109 | | - src = ./.; |
| 110 | | - |
| 111 | | - cargoLock = { |
| 112 | | - lockFile = ./Cargo.lock; |
| 161 | + # Package (without GUI for smaller binary) |
| 162 | + packages.default = pkgs.rustPlatform.buildRustPackage { |
| 163 | + pname = "hyprkvm"; |
| 164 | + version = "0.5.1"; |
| 165 | + src = ./.; |
| 166 | + |
| 167 | + cargoLock = { |
| 168 | + lockFile = ./Cargo.lock; |
| 169 | + }; |
| 170 | + |
| 171 | + nativeBuildInputs = buildDeps; |
| 172 | + buildInputs = libDeps; |
| 173 | + |
| 174 | + # Builds both hyprkvm (daemon) and hyprkvm-ctl (CLI) |
| 175 | + # buildRustPackage automatically installs all workspace binaries |
| 176 | + |
| 177 | + meta = with pkgs.lib; { |
| 178 | + description = "Hyprland-native software KVM switch"; |
| 179 | + longDescription = '' |
| 180 | + HyprKVM enables seamless keyboard/mouse control transfer between |
| 181 | + Linux machines running Hyprland. Move past your last workspace |
| 182 | + to switch to another machine. |
| 183 | + ''; |
| 184 | + homepage = "https://github.com/tenseleyFlow/hyprKVM"; |
| 185 | + license = licenses.mit; |
| 186 | + platforms = platforms.linux; |
| 187 | + mainProgram = "hyprkvm"; |
| 188 | + }; |
| 113 | 189 | }; |
| 114 | 190 | |
| 115 | | - nativeBuildInputs = buildDeps ++ [ pkgs.makeWrapper ]; |
| 116 | | - buildInputs = libDeps; |
| 191 | + # Package with GUI support |
| 192 | + packages.gui = pkgs.rustPlatform.buildRustPackage { |
| 193 | + pname = "hyprkvm"; |
| 194 | + version = "0.5.1"; |
| 195 | + src = ./.; |
| 117 | 196 | |
| 118 | | - # Build with GUI feature |
| 119 | | - buildFeatures = [ "gui" ]; |
| 197 | + cargoLock = { |
| 198 | + lockFile = ./Cargo.lock; |
| 199 | + }; |
| 120 | 200 | |
| 121 | | - # Wrap binary to include graphics library paths |
| 122 | | - postInstall = '' |
| 123 | | - wrapProgram $out/bin/hyprkvm \ |
| 124 | | - --prefix LD_LIBRARY_PATH : ${pkgs.lib.makeLibraryPath libDeps} |
| 125 | | - ''; |
| 201 | + nativeBuildInputs = buildDeps ++ [ pkgs.makeWrapper ]; |
| 202 | + buildInputs = libDeps; |
| 126 | 203 | |
| 127 | | - meta = with pkgs.lib; { |
| 128 | | - description = "Hyprland-native software KVM switch (with GUI)"; |
| 129 | | - longDescription = '' |
| 130 | | - HyprKVM enables seamless keyboard/mouse control transfer between |
| 131 | | - Linux machines running Hyprland. Move past your last workspace |
| 132 | | - to switch to another machine. |
| 204 | + # Build with GUI feature |
| 205 | + buildFeatures = [ "gui" ]; |
| 133 | 206 | |
| 134 | | - This package includes the GUI configuration tool. |
| 207 | + # Wrap binary to include graphics library paths |
| 208 | + postInstall = '' |
| 209 | + wrapProgram $out/bin/hyprkvm \ |
| 210 | + --prefix LD_LIBRARY_PATH : ${pkgs.lib.makeLibraryPath libDeps} |
| 135 | 211 | ''; |
| 136 | | - homepage = "https://github.com/tenseleyFlow/hyprKVM"; |
| 137 | | - license = licenses.mit; |
| 138 | | - platforms = platforms.linux; |
| 139 | | - mainProgram = "hyprkvm"; |
| 212 | + |
| 213 | + meta = with pkgs.lib; { |
| 214 | + description = "Hyprland-native software KVM switch (with GUI)"; |
| 215 | + longDescription = '' |
| 216 | + HyprKVM enables seamless keyboard/mouse control transfer between |
| 217 | + Linux machines running Hyprland. Move past your last workspace |
| 218 | + to switch to another machine. |
| 219 | + |
| 220 | + This package includes the GUI configuration tool. |
| 221 | + ''; |
| 222 | + homepage = "https://github.com/tenseleyFlow/hyprKVM"; |
| 223 | + license = licenses.mit; |
| 224 | + platforms = platforms.linux; |
| 225 | + mainProgram = "hyprkvm"; |
| 226 | + }; |
| 140 | 227 | }; |
| 141 | | - }; |
| 142 | | - } |
| 143 | | - ); |
| 228 | + } |
| 229 | + ); |
| 230 | + in |
| 231 | + # Merge system-independent and system-specific outputs |
| 232 | + systemIndependent // systemSpecific; |
| 144 | 233 | } |