This repository has no description
5.6 kB
152 lines
1{ ... }:
2{
3 flake.wrapperModules.noctalia-shell =
4 {
5 config,
6 lib,
7 ...
8 }:
9 let
10 pkgs = config.pkgs;
11 jsonFormat = pkgs.formats.json { };
12
13 sway-focus-workspace = pkgs.writeShellScript "sway-focus-workspace" ''
14 # Bring a workspace to the currently focused output
15 ws="$1"
16 current_output=$(${pkgs.sway}/bin/swaymsg -t get_workspaces \
17 | ${pkgs.jq}/bin/jq -r '.[] | select(.focused) | .output')
18 ${pkgs.sway}/bin/swaymsg "workspace $ws, move workspace to output $current_output"
19 '';
20
21 # Patch noctalia-shell for sway:
22 # - Use workspace name instead of number (activate() sends
23 # "workspace number <num>" which fails for named workspaces)
24 # - Show all workspaces on all screens (globalWorkspaces)
25 # - Bring workspace to current screen on click instead of jumping
26 swayPatched = pkgs.noctalia-shell.overrideAttrs (old: {
27 postInstall = (old.postInstall or "") + ''
28 substituteInPlace $out/share/noctalia-shell/Services/Compositor/SwayService.qml \
29 --replace-fail 'workspace.handle.activate();' \
30 'Quickshell.execDetached(["${sway-focus-workspace}", workspace.name]);' \
31 --replace-fail 'property bool initialized: false' \
32 'property bool globalWorkspaces: true
33 property bool initialized: false'
34 '';
35 });
36
37 declSettingsFile = jsonFormat.generate "noctalia-declarative-settings.json" config.settings;
38 in
39 {
40 _class = "wrapper";
41
42 options = {
43 settings = lib.mkOption {
44 type = jsonFormat.type;
45 default = { };
46 example = lib.literalExpression ''
47 {
48 hooks.enabled = true;
49 hooks.darkModeChange = "switch-theme $1";
50 }
51 '';
52 description = ''
53 Declarative noctalia settings. Deep-merged into the on-disk
54 `settings.json` on every start (declarative wins). Keys not
55 mentioned here remain user-mutable and survive across
56 invocations — only the fields you set are pinned.
57 '';
58 };
59
60 settingsPath = lib.mkOption {
61 type = lib.types.str;
62 default = ".config/noctalia/settings.json";
63 description = ''
64 Path to the noctalia settings file, relative to `$HOME`.
65 '';
66 };
67
68 settingsPatches = lib.mkOption {
69 type = lib.types.listOf lib.types.str;
70 default = [ ];
71 example = lib.literalExpression ''
72 [
73 # Force the Workspace bar widget to show workspace names.
74 ".bar.widgets.center |= map(if .id == \"Workspace\" then .labelMode = \"name\" else . end)"
75 ]
76 '';
77 description = ''
78 jq update expressions applied to `settings.json` on every start,
79 after the deep-merge of `settings`. Use these to pin individual
80 fields inside arrays (where deep-merge would replace the whole
81 array) without touching sibling entries.
82
83 Each string is passed as the filter to a separate `jq` invocation.
84 Patches run in order; if any patch fails the file is left
85 untouched.
86 '';
87 };
88
89 swayWorkspaceFix = lib.mkOption {
90 type = lib.types.bool;
91 default = true;
92 description = ''
93 Patch noctalia-shell so its workspace bar works on sway with
94 named/global workspaces and click-to-current-output. Applied
95 to the default package only; ignored if you override `package`.
96 '';
97 };
98 };
99
100 config.package = lib.mkDefault (
101 if config.swayWorkspaceFix then swayPatched else pkgs.noctalia-shell
102 );
103
104 config.extraPackages = [
105 pkgs.jq
106 pkgs.coreutils
107 ];
108
109 # On every start: merge declarative settings into the user's
110 # writable settings.json. User-edited keys outside the declarative
111 # set are preserved; declarative keys are overwritten each run.
112 config.preHook = ''
113 NOCTALIA_SETTINGS="$HOME/${config.settingsPath}"
114 mkdir -p "$(dirname "$NOCTALIA_SETTINGS")"
115 if [ ! -f "$NOCTALIA_SETTINGS" ]; then
116 echo '{}' > "$NOCTALIA_SETTINGS"
117 fi
118 NOCTALIA_TMP=$(mktemp "$NOCTALIA_SETTINGS.XXXXXX")
119 noctalia_merge_ok=1
120 if ! ${pkgs.jq}/bin/jq --slurpfile decl ${declSettingsFile} \
121 '. * $decl[0]' "$NOCTALIA_SETTINGS" > "$NOCTALIA_TMP"; then
122 noctalia_merge_ok=0
123 fi
124 ${lib.concatMapStringsSep "\n" (patch: ''
125 if [ "$noctalia_merge_ok" = 1 ]; then
126 NOCTALIA_TMP2=$(mktemp "$NOCTALIA_SETTINGS.XXXXXX")
127 if ${pkgs.jq}/bin/jq ${lib.escapeShellArg patch} "$NOCTALIA_TMP" > "$NOCTALIA_TMP2"; then
128 mv "$NOCTALIA_TMP2" "$NOCTALIA_TMP"
129 else
130 rm -f "$NOCTALIA_TMP2"
131 noctalia_merge_ok=0
132 fi
133 fi
134 '') config.settingsPatches}
135 if [ "$noctalia_merge_ok" = 1 ]; then
136 mv "$NOCTALIA_TMP" "$NOCTALIA_SETTINGS"
137 else
138 rm -f "$NOCTALIA_TMP"
139 echo "noctalia declarative settings merge failed; leaving settings.json untouched" >&2
140 fi
141 '';
142
143 config.meta.maintainers = [
144 {
145 name = "lassulus";
146 github = "lassulus";
147 githubId = 621375;
148 }
149 ];
150 config.meta.platforms = lib.platforms.linux;
151 };
152}