diff options
Diffstat (limited to 'accounts/gkleen@sif/niri/default.nix')
-rw-r--r-- | accounts/gkleen@sif/niri/default.nix | 111 |
1 files changed, 110 insertions, 1 deletions
diff --git a/accounts/gkleen@sif/niri/default.nix b/accounts/gkleen@sif/niri/default.nix index bfc32254..ca2dfeff 100644 --- a/accounts/gkleen@sif/niri/default.nix +++ b/accounts/gkleen@sif/niri/default.nix | |||
@@ -89,7 +89,8 @@ let | |||
89 | active_output="$(jq -r '.[] | select(.is_focused) | .output' <<<"$workspaces_json")" | 89 | active_output="$(jq -r '.[] | select(.is_focused) | .output' <<<"$workspaces_json")" |
90 | active_workspace="$(jq -r '.[] | select(.is_focused) | .id' <<<"$workspaces_json")" | 90 | active_workspace="$(jq -r '.[] | select(.is_focused) | .id' <<<"$workspaces_json")" |
91 | 91 | ||
92 | workspace_json="$(jq -c --arg active_output "$active_output" 'map(select(.output == $active_output and .name == null)) | sort_by(.idx) | .[0]' <<<"$workspaces_json")" | 92 | history_json="$(socat STDIO UNIX-CONNECT:"$XDG_RUNTIME_DIR"/niri-workspace-history.sock)" |
93 | workspace_json="$(jq -c --arg active_output "$active_output" --argjson history "$history_json" 'map(select(.output == $active_output and .name == null)) | map({"value": ., "history_idx": ((. as $workspace | ($history[$active_output] | index($workspace | .id))) as $active_idx | if $active_idx then $active_idx else ($history[$active_output] | length) + 1 end)}) | sort_by(.history_idx, .value.idx) | map(.value) | .[0]' <<<"$workspaces_json")" | ||
93 | [[ -n $workspace_json && $workspace_json != null ]] || exit 0 | 94 | [[ -n $workspace_json && $workspace_json != null ]] || exit 0 |
94 | jq --arg active_workspace "$active_workspace" -c "$action" <<<"$workspace_json" | tee /dev/stderr | socat STDIO "$NIRI_SOCKET" | 95 | jq --arg active_workspace "$active_workspace" -c "$action" <<<"$workspace_json" | tee /dev/stderr | socat STDIO "$NIRI_SOCKET" |
95 | ''; | 96 | ''; |
@@ -156,6 +157,113 @@ in { | |||
156 | ]; | 157 | ]; |
157 | }; | 158 | }; |
158 | 159 | ||
160 | systemd.user.sockets.niri-workspace-history = { | ||
161 | Socket = { | ||
162 | ListenStream = "%t/niri-workspace-history.sock"; | ||
163 | SocketMode = "0600"; | ||
164 | }; | ||
165 | }; | ||
166 | systemd.user.services.niri-workspace-history = { | ||
167 | Unit = { | ||
168 | BindsTo = [ "niri.service" ]; | ||
169 | After = [ "niri.service" ]; | ||
170 | }; | ||
171 | Install = { | ||
172 | WantedBy = [ "niri.service" ]; | ||
173 | }; | ||
174 | Service = { | ||
175 | Type = "simple"; | ||
176 | Sockets = [ "niri-workspace-history.socket" ]; | ||
177 | ExecStart = pkgs.writers.writePython3 "niri-workspace-history" {} '' | ||
178 | import os | ||
179 | import socket | ||
180 | import json | ||
181 | import sys | ||
182 | from collections import defaultdict | ||
183 | from threading import Thread, Lock | ||
184 | from socketserver import StreamRequestHandler, ThreadingTCPServer | ||
185 | from contextlib import contextmanager | ||
186 | from io import TextIOWrapper | ||
187 | |||
188 | |||
189 | @contextmanager | ||
190 | def detaching(thing): | ||
191 | try: | ||
192 | yield thing | ||
193 | finally: | ||
194 | thing.detach() | ||
195 | |||
196 | |||
197 | workspace_history = defaultdict(list) | ||
198 | history_lock = Lock() | ||
199 | |||
200 | |||
201 | def monitor_niri(): | ||
202 | workspaces = list() | ||
203 | |||
204 | def focus_workspace(output, workspace): | ||
205 | global workspace_history, history_lock | ||
206 | |||
207 | with history_lock: | ||
208 | workspace_history[output] = [workspace] + [ws for ws in workspace_history[output] if ws != workspace] # noqa: E501 | ||
209 | print(json.dumps(workspace_history), file=sys.stderr) | ||
210 | |||
211 | sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) | ||
212 | sock.connect(os.environ["NIRI_SOCKET"]) | ||
213 | sock.send(b"\"EventStream\"\n") | ||
214 | for line in sock.makefile(buffering=1, encoding='utf-8'): | ||
215 | if line_json := json.loads(line): | ||
216 | if "WorkspacesChanged" in line_json: | ||
217 | workspaces = line_json["WorkspacesChanged"]["workspaces"] | ||
218 | for ws in workspaces: | ||
219 | if ws["is_focused"]: | ||
220 | focus_workspace(ws["output"], ws["id"]) | ||
221 | if "WorkspaceActivated" in line_json: | ||
222 | for ws in workspaces: | ||
223 | if ws["id"] != line_json["WorkspaceActivated"]["id"]: | ||
224 | continue | ||
225 | focus_workspace(ws["output"], ws["id"]) | ||
226 | break | ||
227 | |||
228 | |||
229 | class RequestHandler(StreamRequestHandler): | ||
230 | def handle(self): | ||
231 | global workspace_history, history_lock | ||
232 | |||
233 | with detaching(TextIOWrapper(self.wfile, encoding='utf-8', write_through=True)) as out: # noqa: E501 | ||
234 | with history_lock: | ||
235 | json.dump(workspace_history, out) | ||
236 | |||
237 | |||
238 | class Server(ThreadingTCPServer): | ||
239 | def __init__(self): | ||
240 | ThreadingTCPServer.__init__(self, ("", 8000), RequestHandler, bind_and_activate=False) # noqa: E501 | ||
241 | self.socket = socket.fromfd(3, self.address_family, self.socket_type) | ||
242 | |||
243 | |||
244 | def run_server(): | ||
245 | with Server() as server: | ||
246 | server.serve_forever() | ||
247 | |||
248 | |||
249 | niri = Thread(target=monitor_niri) | ||
250 | niri.daemon = True | ||
251 | niri.start() | ||
252 | |||
253 | server_thread = Thread(target=run_server) | ||
254 | server_thread.daemon = True | ||
255 | server_thread.start() | ||
256 | |||
257 | while True: | ||
258 | server_thread.join(timeout=0.5) | ||
259 | niri.join(timeout=0.5) | ||
260 | |||
261 | if not (niri.is_alive() and server_thread.is_alive()): | ||
262 | break | ||
263 | ''; | ||
264 | }; | ||
265 | }; | ||
266 | |||
159 | programs.niri.settings = { | 267 | programs.niri.settings = { |
160 | prefer-no-csd = true; | 268 | prefer-no-csd = true; |
161 | screenshot-path = "${config.home.homeDirectory}/screenshots"; | 269 | screenshot-path = "${config.home.homeDirectory}/screenshots"; |
@@ -209,6 +317,7 @@ in { | |||
209 | 317 | ||
210 | animations = { | 318 | animations = { |
211 | slowdown = 0.5; | 319 | slowdown = 0.5; |
320 | workspace-switch = null; | ||
212 | }; | 321 | }; |
213 | 322 | ||
214 | layout = { | 323 | layout = { |