Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/crutchcorn/hearthspace. A spatial Linux desktop for persistent, local-first computing.
Something went wrong. Try again.
4.0 kB · 123 lines
Python
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124"""Observed shell and canvas-map pointer targets in compositor coordinates."""
import math
from .control import ControlErrorfrom .daily_checks import a11yfrom .input import BUTTONS, Inputfrom .shell_surfaces import corner_surface, observed_status
SHELL = "//*[@role='application' and @name='hearthspace-shell']"MINIMAP = f"({SHELL}//*[@showing='true' and starts-with(@name,'Canvas minimap:')])[1]"WINDOW_FIELDS = ( "id", "canvas_x", "canvas_y", "content_width", "content_height", "maximized", "fullscreen", "presentation_output",)
def window_geometry(status): return { item["id"]: {key: item.get(key) for key in WINDOW_FIELDS} for item in status["windows"] }
def map_image(smoke): return smoke.until( "accessible live canvas minimap", lambda: a11y(smoke, "find", MINIMAP)["elements"], )[0]
def selector(name, *, role=None): role_filter = f"@role='{role}' and " if role else "" return f"({SHELL}//*[{role_filter}@showing='true' and @name='{name}'])[1]"
def button_center(bounds, output, surface=None): # AccessKit reports physical coordinates local to each Wayland surface. # Compositor status supplies the actual global logical surface placement. if not bounds or any( not math.isfinite(bounds.get(key, float("nan"))) for key in ("x", "y", "width", "height") ): raise ControlError("shell button has no finite observed bounds") if bounds["width"] <= 0 or bounds["height"] <= 0: raise ControlError("shell button has empty observed bounds") if not math.isfinite(output["scale"]) or output["scale"] <= 0: raise ControlError("output has no usable scale") surface = surface or { "x": output["logical_x"], "y": output["logical_y"], "width": output["logical_width"], "height": 48, } x = (bounds["x"] + bounds["width"] / 2) / output["scale"] y = (bounds["y"] + bounds["height"] / 2) / output["scale"] if not (0 <= x < surface["width"] and 0 <= y < surface["height"]): raise ControlError("observed button center lies outside its shell surface") return x + surface["x"], y + surface["y"]
def map_surface(smoke): status = smoke.control.status() maps = status.get("canvas_maps", []) if len(maps) != 1: raise ControlError("canvas-map acceptance requires one mapped popover") surface = maps[0] output = next( (item for item in status["outputs"] if item["name"] == surface["output"]), None, ) if output is None: raise ControlError("canvas map has no matching output") return surface, output
def click(smoke, name, *, on_press=None): target = selector(name, role="button") elements = smoke.until( f"observed shell {name} button", lambda: a11y(smoke, "find", target)["elements"], ) if name == "Canvas map": status = observed_status(smoke) outputs = status["outputs"] if len(outputs) != 1: raise ControlError("canvas-map acceptance requires one active output") output, surface = outputs[0], corner_surface(status, "canvas") else: surface, output = map_surface(smoke) point = button_center(elements[0].get("bounds"), output, surface) smoke.record( "shell-pointer-target", selector=target, elements=elements, point=point ) with Input(smoke.control) as inputs: inputs.motion(*point) inputs.down("pointer-button", BUTTONS["left"]) if on_press: on_press() inputs.up("pointer-button", BUTTONS["left"])
def opened(smoke): return smoke.until( "canvas map mapped", lambda: smoke.control.status().get("canvas_maps") )
def closed(smoke): smoke.until( "canvas map dismissed", lambda: not smoke.control.status().get("canvas_maps") )
def close(smoke): click(smoke, "Close canvas map") closed(smoke)