"""The virtual monitor half: a headless Hyprland output sized to the tablet.""" import json import re import shutil import subprocess import sys import time from pathlib import Path def run(cmd, timeout=2): try: return subprocess.run(cmd, capture_output=True, text=True, timeout=timeout).stdout.strip() except (OSError, subprocess.TimeoutExpired): return "" def tablet_resolution(cfg: dict, adb=None) -> str: res = cfg.get("display", {}).get("resolution", "auto") if res != "auto": return res read = adb or (lambda: run(["adb", "shell", "wm", "size"])) m = re.search(r"(\d+)x(\d+)", read()) if not m: sys.exit("Could not read the tablet resolution; set display.resolution in the config") w, h = sorted(map(int, m.groups()), reverse=True) return f"{w}x{h}" def hypr_lua(cfg: dict) -> bool: mode = cfg.get("hyprland", "auto") if mode == "auto": return (Path.home() / ".config/hypr/hyprland.lua").is_file() return mode == "lua" def setup_display(cfg: dict, run_cmd=None) -> None: run_cmd = run_cmd or run d = cfg.get("display", {}) mon = d.get("name", "TAB") monitors = json.loads(run_cmd(["hyprctl", "monitors", "-j"]) or "[]") if not any(m["name"] == mon for m in monitors): run_cmd(["hyprctl", "output", "create", "headless", mon]) time.sleep(1) mode = f"{tablet_resolution(cfg)}@{d.get('refresh', 60)}" pos = d.get("position", "auto-right") scale = d.get("scale", 1) if hypr_lua(cfg): run_cmd(["hyprctl", "eval", f'hl.monitor({{output="{mon}", mode="{mode}", position="{pos}", scale={scale}}})']) else: run_cmd(["hyprctl", "keyword", "monitor", f"{mon},{mode},{pos},{scale}"]) tool = shutil.which("awww") or shutil.which("swww") if d.get("wallpaper", True) and tool: others = [m["name"] for m in monitors if m["name"] != mon] for line in run_cmd([tool, "query"]).splitlines(): if others and others[0] in line and "image: " in line: run_cmd([tool, "img", "-o", mon, line.split("image: ", 1)[1]], timeout=10) break print(f"{mon}: {mode} at {pos}")