-
-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathflake.nix
More file actions
312 lines (290 loc) · 14.6 KB
/
flake.nix
File metadata and controls
312 lines (290 loc) · 14.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# SPDX-License-Identifier: GPL-3.0-or-later
#
# flake.nix — PlasmaZones Nix flake
#
# WHAT THIS FLAKE PROVIDES
# ────────────────────────
# packages.default / packages.plasmazones
# The PlasmaZones package built against this flake's pinned nixpkgs.
# Correct for `nix build` and `nix profile install`. See the WARNING
# below about the KWin IID constraint before installing this way.
#
# nixosModules.default
# A NixOS module (programs.plasmazones.enable = true). Builds the package
# against the *host* system's pkgs so the KWin plugin IID always matches.
# This is the recommended install path on NixOS.
#
# homeManagerModules.default
# A Home Manager module for per-user installs without NixOS. Also builds
# against the host's pkgs for the same IID reason.
#
# overlays.default
# A nixpkgs overlay that adds `pkgs.plasmazones`. Builds against the
# consumer's `final` pkgs — correct by construction.
#
# devShells.default
# A development shell with all build dependencies and debugging tools.
#
# THE KWIN IID CONSTRAINT (why "host pkgs" matters so much)
# ──────────────────────────────────────────────────────────
# PlasmaZones includes a KWin C++ effect plugin (kwin-effect/). KWin embeds
# its own version string in every plugin it loads as an IID (Interface
# Identifier). At runtime, KWin checks that the IID of any plugin it loads
# matches the running KWin's own version string *exactly* — even a patch
# version mismatch (6.6.4 vs 6.6.5) causes KWin to silently refuse the plugin.
#
# This means: the `kwin` package used to *compile* the plugin must be the
# same `kwin` the user is *running*. On a rolling nixos-unstable system,
# kwin moves often. If you use `nix profile install` (which pins to THIS
# flake's nixpkgs), and your system's kwin has since updated, the plugin
# will not load and zone overlays will not appear — but everything else works.
#
# SAFE INSTALL PATHS (use these):
# • NixOS module → builds against your system pkgs every rebuild ✓
# • Home Manager module → same ✓
# • overlay → same ✓
#
# RISKY INSTALL PATH (you're warned):
# • `nix profile install github:fuddlesworth/PlasmaZones`
# Works if the flake.lock kwin == your running kwin, breaks silently
# if they diverge. Re-run `nix flake update` + reinstall after any
# system plasma/kwin update to stay in sync.
{
description = "FancyZones-style window tiling and autotiling for KDE Plasma 6.6+";
inputs = {
# Track nixos-unstable for the most current KDE Frameworks and KWin packages.
# If you need a stable channel, use nixos-24.11 or later, but be aware that
# stable channels may lag behind upstream KDE releases.
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs = { self, nixpkgs }:
let
# The two Linux architectures PlasmaZones supports.
# macOS and Windows are not supported — PlasmaZones is Wayland/Linux-only.
supportedSystems = [ "x86_64-linux" "aarch64-linux" ];
# Helper: produce an attribute set { x86_64-linux = f "x86_64-linux"; ... }
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
# ── Core build function ────────────────────────────────────────────────
# mkPlasmaZones takes a nixpkgs `pkgs` instance and returns the built
# package. The caller is responsible for passing the RIGHT pkgs:
#
# • For NixOS/HM modules and overlays: pass the host's pkgs (the `pkgs`
# argument Nix injects into the module). This ensures the kwin package
# used for compilation matches the kwin the user is running.
#
# • For the flake's own `packages` output: we pass the flake's pinned
# nixpkgs, which is fine for CI and `nix build` but may misalign with
# a rolling system's kwin (see THE KWIN IID CONSTRAINT above).
#
# The actual build recipe lives in packaging/nix/package.nix. Keeping it
# separate makes it easy to callPackage from nixpkgs upstream later.
mkPlasmaZones = pkgs:
pkgs.callPackage ./packaging/nix/package.nix {
# Pass the repo root as the source. When building from a flake input,
# `self` is the root of the repository. When building from nixpkgs,
# this argument is overridden with a fetchFromGitHub derivation.
src = self;
};
in
{
# ── packages ────────────────────────────────────────────────────────────
# Exposed for `nix build`, `nix profile install`, and CI.
# Built against the flake's pinned nixpkgs — see the IID warning above.
packages = forAllSystems (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
default = mkPlasmaZones pkgs;
plasmazones = self.packages.${system}.default; # named alias
}
);
# ── checks ──────────────────────────────────────────────────────────────
# Run with `nix flake check`. Currently just verifies the package builds
# without C++ compilation errors. Tests are disabled in the package build
# (they need a Wayland compositor and cannot run in the Nix sandbox).
checks = forAllSystems (system: {
package = self.packages.${system}.default;
});
# ── NixOS module ────────────────────────────────────────────────────────
# Recommended install path on NixOS. Add to your configuration:
#
# inputs.plasmazones.url = "github:fuddlesworth/PlasmaZones";
#
# { inputs, ... }: {
# imports = [ inputs.plasmazones.nixosModules.default ];
# programs.plasmazones.enable = true;
# }
#
# After `nixos-rebuild switch`, enable the daemon for your user:
# systemctl --user enable --now plasmazones.service
#
# And (once, or after any Plasma update) refresh the KDE service cache:
# kbuildsycoca6 --noincremental
nixosModules.default = { config, lib, pkgs, ... }:
let
cfg = config.programs.plasmazones;
in
{
options.programs.plasmazones = {
enable = lib.mkEnableOption
"PlasmaZones window tiling for KDE Plasma 6.6+";
package = lib.mkOption {
type = lib.types.package;
# Build against the HOST's pkgs, not the flake's pinned pkgs.
# This is what keeps the KWin effect IID in sync with the running KWin.
default = mkPlasmaZones pkgs;
defaultText = lib.literalExpression
''pkgs.callPackage "${self}/packaging/nix/package.nix" { src = ${self}; }'';
description = ''
The PlasmaZones package to use. The default builds against the
host system's pkgs so the KWin effect plugin's IID matches the
running KWin binary. Override only if you know what you're doing.
'';
};
};
config = lib.mkIf cfg.enable {
# Install the package system-wide so all users can run it.
environment.systemPackages = [ cfg.package ];
# Refresh the KDE service database once at activation so the KCM
# (System Settings → Window Management → PlasmaZones) appears
# immediately after `nixos-rebuild switch` without requiring a logout.
#
# kbuildsycoca6 scans *.desktop files in XDG_DATA_DIRS and rebuilds
# the sycoca cache that KDE uses to discover plugins and services.
system.userActivationScripts.plasmazones-sycoca = {
text = ''
# Only run if kbuildsycoca6 is available (i.e. KDE is installed)
if command -v kbuildsycoca6 >/dev/null 2>&1; then
kbuildsycoca6 --noincremental 2>/dev/null || true
fi
'';
# Run after the package is deployed to $PATH
deps = [];
};
# The systemd user service is shipped by the package itself
# (installed to lib/systemd/user/plasmazones.service).
# Users start it with:
# systemctl --user enable --now plasmazones.service
#
# We intentionally do NOT auto-enable it here because:
# 1. The user may want to start it manually after configuring zones.
# 2. systemd.user services in NixOS modules affect all users on the
# system, but PlasmaZones is a per-user tool.
};
};
# ── Home Manager module ─────────────────────────────────────────────────
# For per-user installs without NixOS (e.g. on a non-NixOS distro with
# the Nix package manager, or when managing dotfiles with Home Manager).
#
# Add to your Home Manager configuration:
#
# inputs.plasmazones.url = "github:fuddlesworth/PlasmaZones";
#
# { inputs, ... }: {
# imports = [ inputs.plasmazones.homeManagerModules.default ];
# programs.plasmazones.enable = true;
# }
homeManagerModules.default = { config, lib, pkgs, ... }:
let
cfg = config.programs.plasmazones;
in
{
options.programs.plasmazones = {
enable = lib.mkEnableOption
"PlasmaZones window tiling for KDE Plasma 6.6+";
package = lib.mkOption {
type = lib.types.package;
default = mkPlasmaZones pkgs;
defaultText = lib.literalExpression
''pkgs.callPackage "${self}/packaging/nix/package.nix" { src = ${self}; }'';
description = ''
The PlasmaZones package to use. Built against the host's pkgs
so the KWin effect plugin IID matches the running KWin.
'';
};
};
config = lib.mkIf cfg.enable {
# Install the package into the user's profile.
home.packages = [ cfg.package ];
# Manage the plasmazonesd systemd user service via Home Manager.
# Home Manager writes the service unit and `systemctl --user daemon-reload`
# automatically during `home-manager switch`.
systemd.user.services.plasmazones = {
Unit = {
Description = "PlasmaZones Window Tiling Daemon";
# Start after the Wayland/graphical session is up.
# graphical-session.target is set by KDE's plasma-session.
PartOf = [ "graphical-session.target" ];
After = [ "graphical-session.target" ];
};
Service = {
# plasmazonesd is the daemon binary installed to $out/bin.
ExecStart = "${cfg.package}/bin/plasmazonesd";
# Restart on crash (not on clean exit — the user can stop it
# intentionally via `systemctl --user stop plasmazones`).
Restart = "on-failure";
RestartSec = 3;
};
# WantedBy graphical-session.target means `systemctl --user enable`
# makes it start automatically with the KDE session.
Install.WantedBy = [ "graphical-session.target" ];
};
};
};
# ── overlay ─────────────────────────────────────────────────────────────
# Adds `pkgs.plasmazones` to a nixpkgs instance.
# Use this if you manage nixpkgs yourself and want PlasmaZones as a
# regular package attribute:
#
# nixpkgs.overlays = [ inputs.plasmazones.overlays.default ];
# environment.systemPackages = [ pkgs.plasmazones ];
#
# `final` is the post-overlay pkgs — the host's current package set.
# Using `final` (not `prev`) is what keeps kwin in sync with the host.
overlays.default = final: prev: {
plasmazones = mkPlasmaZones final;
};
# ── devShell ─────────────────────────────────────────────────────────────
# A development environment with all build dependencies.
# Enter with: nix develop
#
# From inside the shell you can build manually:
# cmake -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON
# cmake --build build -j$(nproc)
#
# Or run the test suite (requires a running Wayland compositor):
# cmake --build build --target test
devShells = forAllSystems (system:
let
pkgs = nixpkgs.legacyPackages.${system};
# inputsFrom pulls in all nativeBuildInputs and buildInputs from
# the package derivation, giving the shell everything needed to build.
pz = self.packages.${system}.default;
in
{
default = pkgs.mkShell {
# Inherit the full build environment from the package derivation.
inputsFrom = [ pz ];
# Additional developer tools not needed for the build itself:
packages = with pkgs; [
# Debugger — step through C++ code in the daemon or effect plugin.
gdb
# C++ language server and formatter — for editor integration.
clang-tools # provides clangd + clang-format
# CMake LSP — useful with editors that support cmake-language-server.
cmake-language-server
# Qt-specific introspection tools.
pkgs.qt6.qttools # provides qdbus6, qmlformat, etc.
];
# Tell CMake to use Debug mode in the dev shell.
shellHook = ''
echo "PlasmaZones dev shell ready."
echo "Build: cmake -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON && cmake --build build"
echo "Test: cmake --build build --target test (requires running Wayland compositor)"
'';
};
}
);
};
}