"""Where the mini timer appears. Two mechanisms, because one is not enough: * **X11** — the application may place its own window, so the computed point is applied directly. * **Wayland** — it may not: a client cannot position an xdg-toplevel, and setting `x`/`y` is quietly ignored. KWin *can* place it, through the same window rule that already forces "keep above", so the point is written there. The geometry maths is a pure function so it can be checked without a screen. """ from __future__ import annotations from dataclasses import dataclass CORNERS = ( "top-left", "top-centre", "top-right", "bottom-left", "bottom-centre", "bottom-right", "centre", "remember", ) # What the settings page shows, in the order it shows them. CORNER_LABELS = { "top-left": "Top left", "top-centre": "Top centre", "top-right": "Top right", "bottom-left": "Bottom left", "bottom-centre": "Bottom centre", "bottom-right": "Bottom right", "centre": "Centre of the screen", "remember": "Where I last dragged it", } @dataclass(frozen=True, slots=True) class Rect: """A screen's usable area — panels and docks already taken off.""" x: int y: int width: int height: int def point_for(corner: str, screen: Rect, size: tuple[int, int], margin: int = 24) -> tuple[int, int]: """Top-left point that puts a `size` window in `corner` of `screen`.""" width, height = size margin = max(0, margin) vertical, _, horizontal = corner.partition("-") if corner == "centre": vertical, horizontal = "centre", "centre" if horizontal == "left": x = screen.x + margin elif horizontal == "right": x = screen.x + screen.width - width - margin else: # centre x = screen.x + (screen.width - width) // 2 if vertical == "top": y = screen.y + margin elif vertical == "bottom": y = screen.y + screen.height - height - margin else: # centre y = screen.y + (screen.height - height) // 2 # Never place it off-screen, however small the screen or large the margin. x = max(screen.x, min(x, screen.x + max(screen.width - width, 0))) y = max(screen.y, min(y, screen.y + max(screen.height - height, 0))) return int(x), int(y)