#!/usr/bin/env python3 # Return the dimensions of the current window[s] as selected in sway. # # Non-zero exitcode if something unexpected comes up. # # The printed dimensions will match the slup regex below: # /[0-9]+,[0-9]+ [0-9]+x[0-9]+/ import json import os from subprocess import run, PIPE from typing import Optional def get_sway_tree() -> dict: swaymsg = run([MSG_COMMAND, "-t", "get_tree"], stdout=PIPE) swaymsg.check_returncode() return json.loads(swaymsg.stdout) def format_window_coords(window: dict, rect: dict) -> str: if sum(window.values()) == 0: # Multiple windows selected x = rect["x"] y = rect["y"] w = rect["width"] h = rect["height"] elif window["y"] + window["height"] == rect["height"]: # Account for border x = rect["x"] + window["x"] y = rect["y"] w = window["width"] h = window["height"] - window["y"] else: x = rect["x"] + window["x"] y = rect["y"] + window["y"] w = window["width"] h = window["height"] return f"{x},{y} {w}x{h}" # Return dict indexing path to the first entry with "key" matching "val" # For example, it may return # ['nodes', 1, 'nodes', 1, 'nodes', 0, 'nodes', 0] # Which can then be used to index the original js: # js['nodes'][1]['nodes'][1]['nodes'][0]['nodes'][0][find_key] == find_val def trace_json_path(js, find_key, find_val) -> Optional[list]: if isinstance(js, dict): for key, val in js.items(): if key == find_key and val == find_val: return [] # Base case elif isinstance(val, list): trace = trace_json_path(val, find_key, find_val) if trace is not None: return [key] + trace elif isinstance(js, list): for i, item in enumerate(js): trace = trace_json_path(item, find_key, find_val) if trace is not None: return [i] + trace return None def focused_sway_area(): tree = get_sway_tree() trace = trace_json_path(tree, "focused", True) if trace is None: print("No focused window was found") exit(1) for i in trace: tree = tree[i] return format_window_coords(tree["window_rect"], tree["rect"]) if __name__ == "__main__": try: if "wayland" in os.environ["XDG_SESSION_TYPE"]: MSG_COMMAND = "swaymsg" else: MSG_COMMAND = "i3-msg" except KeyError: MSG_COMMAND = "i3-msg" print(focused_sway_area())