summaryrefslogtreecommitdiff
path: root/accounts/gkleen@sif
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2025-05-14 13:30:26 +0200
committerGregor Kleen <gkleen@yggdrasil.li>2025-05-14 13:30:26 +0200
commit5818cc9c1ecb5e0df7cb1aac154edf6d855ee986 (patch)
treed8b2b38d9d253b9da6fc692456d2e9ece88b6bff /accounts/gkleen@sif
parentf50a110e2120177d692b61493cb9c58f908cfff8 (diff)
downloadnixos-5818cc9c1ecb5e0df7cb1aac154edf6d855ee986.tar
nixos-5818cc9c1ecb5e0df7cb1aac154edf6d855ee986.tar.gz
nixos-5818cc9c1ecb5e0df7cb1aac154edf6d855ee986.tar.bz2
nixos-5818cc9c1ecb5e0df7cb1aac154edf6d855ee986.tar.xz
nixos-5818cc9c1ecb5e0df7cb1aac154edf6d855ee986.zip
...
Diffstat (limited to 'accounts/gkleen@sif')
-rw-r--r--accounts/gkleen@sif/niri/default.nix88
1 files changed, 49 insertions, 39 deletions
diff --git a/accounts/gkleen@sif/niri/default.nix b/accounts/gkleen@sif/niri/default.nix
index 7254b7ed..3f506d52 100644
--- a/accounts/gkleen@sif/niri/default.nix
+++ b/accounts/gkleen@sif/niri/default.nix
@@ -245,7 +245,7 @@ in {
245 Service = { 245 Service = {
246 Type = "simple"; 246 Type = "simple";
247 Sockets = [ "niri-workspace-history.socket" ]; 247 Sockets = [ "niri-workspace-history.socket" ];
248 ExecStart = pkgs.writers.writePython3 "niri-workspace-history" {} '' 248 ExecStart = pkgs.writers.writePython3 "niri-workspace-history" { flakeIgnore = ["E501"]; } ''
249 import os 249 import os
250 import socket 250 import socket
251 import json 251 import json
@@ -274,7 +274,7 @@ in {
274 274
275 def focus_workspace(output, workspace): 275 def focus_workspace(output, workspace):
276 with history_lock: 276 with history_lock:
277 workspace_history[output] = [workspace] + [ws for ws in workspace_history[output] if ws != workspace] # noqa: E501 277 workspace_history[output] = [workspace] + [ws for ws in workspace_history[output] if ws != workspace]
278 # print(json.dumps(workspace_history), file=sys.stderr) 278 # print(json.dumps(workspace_history), file=sys.stderr)
279 279
280 sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 280 sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
@@ -297,14 +297,14 @@ in {
297 297
298 class RequestHandler(StreamRequestHandler): 298 class RequestHandler(StreamRequestHandler):
299 def handle(self): 299 def handle(self):
300 with detaching(TextIOWrapper(self.wfile, encoding='utf-8', write_through=True)) as out: # noqa: E501 300 with detaching(TextIOWrapper(self.wfile, encoding='utf-8', write_through=True)) as out:
301 with history_lock: 301 with history_lock:
302 json.dump(workspace_history, out) 302 json.dump(workspace_history, out)
303 303
304 304
305 class Server(ThreadingTCPServer): 305 class Server(ThreadingTCPServer):
306 def __init__(self): 306 def __init__(self):
307 ThreadingTCPServer.__init__(self, ("", 8000), RequestHandler, bind_and_activate=False) # noqa: E501 307 ThreadingTCPServer.__init__(self, ("", 8000), RequestHandler, bind_and_activate=False)
308 self.socket = socket.fromfd(3, self.address_family, self.socket_type) 308 self.socket = socket.fromfd(3, self.address_family, self.socket_type)
309 309
310 310
@@ -349,45 +349,55 @@ in {
349 outputs = None 349 outputs = None
350 only = {'HDMI-A-1': {'bmr'}, 'eDP-1': {'vid'}} 350 only = {'HDMI-A-1': {'bmr'}, 'eDP-1': {'vid'}}
351 351
352 with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as cmd_sock, socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
353 cmd_sock.connect(os.environ["NIRI_SOCKET"])
354 with cmd_sock.makefile(mode='w', buffering=1, encoding='utf-8') as fh:
355 sock.connect(os.environ["NIRI_SOCKET"])
356 sock.send(b"\"EventStream\"\n")
357 for line in sock.makefile(buffering=1, encoding='utf-8'):
358 workspaces = None
359 if line_json := json.loads(line):
360 if "WorkspacesChanged" in line_json:
361 workspaces = line_json["WorkspacesChanged"]["workspaces"]
362
363 if workspaces is None:
364 continue
365 352
366 old_outputs = outputs 353 class Niri(socket.socket):
367 outputs = {ws["output"] for ws in workspaces} 354 def __init__(self):
368 if old_outputs is None: 355 super().__init__(socket.AF_UNIX, socket.SOCK_STREAM)
369 print("Initial outputs: {}".format(outputs), file=sys.stderr) 356 super().connect(os.environ["NIRI_SOCKET"])
370 continue 357 self.fh = super().makefile(mode='rw', buffering=1, encoding='utf-8')
358
359 def cmd(self, obj):
360 print(json.dumps(obj, separators=(',', ':')), flush=True, file=self.fh)
361
362 def event_stream(self):
363 self.cmd("EventStream")
364 return self.fh
371 365
372 new_outputs = outputs - old_outputs
373 if not new_outputs:
374 continue
375 print("New outputs: {}".format(new_outputs), file=sys.stderr)
376 366
377 relevant_workspaces = list(filter(lambda ws: (ws["name"] is not None) or (ws["active_window_id"] is not None), workspaces)) 367 with Niri() as niri, Niri().event_stream() as niri_stream:
378 target_output = next(iter(outputs - set(only.keys()))) 368 for line in niri_stream:
379 if not target_output: 369 workspaces = None
370 if line_json := json.loads(line):
371 if "WorkspacesChanged" in line_json:
372 workspaces = line_json["WorkspacesChanged"]["workspaces"]
373
374 if workspaces is None:
375 continue
376
377 old_outputs = outputs
378 outputs = {ws["output"] for ws in workspaces}
379 if old_outputs is None:
380 print("Initial outputs: {}".format(outputs), file=sys.stderr)
381 continue
382
383 new_outputs = outputs - old_outputs
384 if not new_outputs:
385 continue
386 print("New outputs: {}".format(new_outputs), file=sys.stderr)
387
388 relevant_workspaces = list(filter(lambda ws: (ws["name"] is not None) or (ws["active_window_id"] is not None), workspaces))
389 target_output = next(iter(outputs - set(only.keys())))
390 if not target_output:
391 continue
392 for ws in relevant_workspaces:
393 ws_ident = ws["name"] if ws["name"] is not None else (ws["output"], ws["idx"])
394 if ws["output"] not in set(only.keys()):
395 continue
396 if ws_ident in only[ws["output"]]:
380 continue 397 continue
381 for ws in relevant_workspaces: 398
382 ws_ident = ws["name"] if ws["name"] is not None else (ws["output"], ws["idx"]) 399 print("{} -> {}".format(ws_ident, target_output), file=sys.stderr)
383 if ws["output"] not in set(only.keys()): 400 niri.cmd({"Action": {"MoveWorkspaceToMonitor": {"reference": {"Id": ws["id"]}, "output": target_output}}})
384 continue
385 if ws_ident in only[ws["output"]]:
386 continue
387
388 print("{} -> {}".format(ws_ident, target_output), file=sys.stderr)
389 cmd = json.dumps({"Action": {"MoveWorkspaceToMonitor": {"reference": {"Id": ws["id"]}, "output": target_output}}}, separators=(',', ':'))
390 print(cmd, flush=True, file=fh)
391 ''; 401 '';
392 Restart = "on-failure"; 402 Restart = "on-failure";
393 RestartSec = 10; 403 RestartSec = 10;