Last active
November 1, 2025 13:54
-
-
Save rafrombrc/dea1458eb06eb8eda9a42e2723dc9946 to your computer and use it in GitHub Desktop.
Revisions
-
rafrombrc revised this gist
Oct 15, 2025 . 1 changed file with 0 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -127,10 +127,8 @@ def update_matched(win): print(f"floating title={win['title']}, app_id={win['app_id']}") float(win["id"]) if r.height != 0: set_height(win["id"], r.height) if r.width != 0: set_width(win["id"], r.width) -
rafrombrc revised this gist
Oct 15, 2025 . 1 changed file with 1 addition and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -71,9 +71,7 @@ def matches(self, window): # window-rule {} with one match that sets window size. # Rule([Match(title="Bitwarden", app_id="firefox")], # width=500, height=1000), ] -
rafrombrc created this gist
Oct 15, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,151 @@ #!/usr/bin/python3 """ Like open-float, but dynamically. Floats a window when it matches the rules. Some windows don't have the right title and app-id when they open, and only set them afterward. This script is like open-float for those windows. Usage: fill in the RULES array below, then run the script. """ from dataclasses import dataclass, field import json import os import re from socket import AF_UNIX, SHUT_WR, socket @dataclass(kw_only=True) class Match: title: str | None = None app_id: str | None = None def matches(self, window): if self.title is None and self.app_id is None: return False matched = True if self.title is not None: matched &= re.search(self.title, window["title"]) is not None if self.app_id is not None: matched &= re.search(self.app_id, window["app_id"]) is not None return matched @dataclass class Rule: match: list[Match] = field(default_factory=list) exclude: list[Match] = field(default_factory=list) width: int = 0 height: int = 0 def matches(self, window): if len(self.match) > 0 and not any(m.matches(window) for m in self.match): return False if any(m.matches(window) for m in self.exclude): return False return True # Write your rules here. One Rule() = one window-rule {}. RULES = [ # window-rule {} with one match. # Rule([Match(title="Bitwarden", app_id="firefox")]), # window-rule {} with one match and one exclude. # Rule( # [Match(title="rs")], # exclude=[Match(app_id="Alacritty")], # ), # window-rule {} with two matches. # Rule( # [ # Match(app_id="^foot$"), # Match(app_id="^mpv$"), # ] # ), # window-rule {} with one match that sets window size. # Rule([Match(title="Bitwarden", app_id="firefox")], # width=500, heigth=1000), Rule([Match(title="Extension.*Bitwarden", app_id="firefox")], width=500, height=1000), ] if len(RULES) == 0: print("fill in the RULES list, then run the script") exit() niri_socket = socket(AF_UNIX) niri_socket.connect(os.environ["NIRI_SOCKET"]) file = niri_socket.makefile("rw") _ = file.write('"EventStream"') file.flush() niri_socket.shutdown(SHUT_WR) windows = {} def send(request): with socket(AF_UNIX) as niri_socket: niri_socket.connect(os.environ["NIRI_SOCKET"]) file = niri_socket.makefile("rw") _ = file.write(json.dumps(request)) file.flush() def float(id: int): send({"Action": {"MoveWindowToFloating": {"id": id}}}) def set_height(id: int, height: int): send({"Action": {"SetWindowHeight": {"id": id, "change": {"SetFixed": height}}}}) def set_width(id: int, width: int): send({"Action": {"SetWindowWidth": {"id": id, "change": {"SetFixed": width}}}}) def update_matched(win): win["matched"] = False if existing := windows.get(win["id"]): win["matched"] = existing["matched"] matched_before = win["matched"] for r in RULES: matched = r.matches(win) if matched: # first match wins win["matched"] = matched break if win["matched"] and not matched_before: print(f"floating title={win['title']}, app_id={win['app_id']}") float(win["id"]) if r.height != 0: print(f"height={r.height}") set_height(win["id"], r.height) if r.width != 0: print(f"width={r.width}") set_width(win["id"], r.width) for line in file: event = json.loads(line) if changed := event.get("WindowsChanged"): for win in changed["windows"]: update_matched(win) windows = {win["id"]: win for win in changed["windows"]} elif changed := event.get("WindowOpenedOrChanged"): win = changed["window"] update_matched(win) windows[win["id"]] = win elif changed := event.get("WindowClosed"): del windows[changed["id"]]