2022-11-21 01:27:49 -07:00
|
|
|
#!/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
|
2023-04-28 22:14:43 -06:00
|
|
|
import os
|
2022-11-21 01:27:49 -07:00
|
|
|
from subprocess import run, PIPE
|
|
|
|
from typing import Optional
|
|
|
|
|
2023-04-28 22:14:43 -06:00
|
|
|
|
2022-11-21 01:27:49 -07:00
|
|
|
def get_sway_tree() -> dict:
|
2023-04-28 22:14:43 -06:00
|
|
|
swaymsg = run([MSG_COMMAND, "-t", "get_tree"], stdout=PIPE)
|
2022-11-21 01:27:49 -07:00
|
|
|
swaymsg.check_returncode()
|
|
|
|
return json.loads(swaymsg.stdout)
|
|
|
|
|
2023-04-28 22:14:43 -06:00
|
|
|
|
2022-11-21 01:27:49 -07:00
|
|
|
def format_window_coords(window: dict, rect: dict) -> str:
|
|
|
|
if sum(window.values()) == 0: # Multiple windows selected
|
2023-04-28 22:14:43 -06:00
|
|
|
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"]
|
2022-11-21 01:27:49 -07:00
|
|
|
else:
|
2023-04-28 22:14:43 -06:00
|
|
|
x = rect["x"] + window["x"]
|
|
|
|
y = rect["y"] + window["y"]
|
|
|
|
w = window["width"]
|
|
|
|
h = window["height"]
|
2022-11-21 01:27:49 -07:00
|
|
|
|
|
|
|
return f"{x},{y} {w}x{h}"
|
|
|
|
|
2023-04-28 22:14:43 -06:00
|
|
|
|
2022-11-21 01:27:49 -07:00
|
|
|
# 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
|
|
|
|
|
2023-04-28 22:14:43 -06:00
|
|
|
|
2022-11-21 01:27:49 -07:00
|
|
|
def focused_sway_area():
|
|
|
|
tree = get_sway_tree()
|
2023-04-28 22:14:43 -06:00
|
|
|
trace = trace_json_path(tree, "focused", True)
|
2022-11-21 01:27:49 -07:00
|
|
|
|
|
|
|
if trace is None:
|
2023-04-28 22:14:43 -06:00
|
|
|
print("No focused window was found")
|
2022-11-21 01:27:49 -07:00
|
|
|
exit(1)
|
|
|
|
|
|
|
|
for i in trace:
|
|
|
|
tree = tree[i]
|
2023-04-28 22:14:43 -06:00
|
|
|
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"
|
2022-11-21 01:27:49 -07:00
|
|
|
|
|
|
|
print(focused_sway_area())
|