74 lines
2.3 KiB
Python
74 lines
2.3 KiB
Python
|
#!/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
|
||
|
from subprocess import run, PIPE
|
||
|
from typing import Optional
|
||
|
|
||
|
def get_sway_tree() -> dict:
|
||
|
swaymsg = run(["swaymsg", "-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__':
|
||
|
print(focused_sway_area())
|