gatelock: make fit/scroll geometry tests immune to a real WM
Some checks are pending
gatelock pre-commit / pre-commit (push) Waiting to run
gatelock tests / test (3.10) (push) Waiting to run
gatelock tests / test (3.11) (push) Waiting to run
gatelock tests / test (3.12) (push) Waiting to run
palette drift / palette (push) Waiting to run

Under i3 (not Xvfb), a managed tk.Tk() toplevel's geometry() request
was silently rewritten to the tiled pane size instead of the
requested WxH, so the content never actually overflowed and every
assertion built on "does this overflow" failed -- 11 tests across
test_fitcheck.py/test_scrollable.py. Fix: overrideredirect the
throwaway root, matching how every production lock window is already
built and for the identical reason (a WM must not be able to rewrite
geometry a fit/scroll check depends on).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018M5gKyYzxWG6QkCaj1wWfk
This commit is contained in:
Krzysztof Rudnicki 2026-08-21 13:00:20 +02:00
parent 24abb22de0
commit 7e7c34a073
3 changed files with 17 additions and 1 deletions

View File

@ -109,6 +109,13 @@ def _measure(
"""Render the screen once and read its height back."""
root = tk.Tk()
try:
# A managed window has its geometry rewritten wholesale by a real
# window manager -- confirmed under i3, which tiled this to the pane
# size instead of the requested width/height, silently measuring the
# wrong resolution. Production lock windows are overrideredirect for
# exactly this reason; the throwaway root here must match so the
# measurement is honest regardless of what WM is running the check.
root.overrideredirect(boolean=True)
root.geometry(f"{width}x{height}+0+0")
root.update_idletasks()
surface = ScrollableSurface(root, config or LockConfig(), center_when_fits=True)

View File

@ -35,6 +35,12 @@ _TALL = 60
def surface() -> tk.Misc:
"""A 400x200 viewport holding 20 stacked entries -- deliberately taller."""
root = tk.Tk()
# A managed window has its geometry rewritten wholesale by a real window
# manager (i3 confirmed: a plain geometry() request came back tiled to
# the pane size instead of 400x200, so nothing ever overflowed and every
# scroll assertion in this file failed against a real WM session) --
# exactly the reason production lock windows are overrideredirect too.
root.overrideredirect(boolean=True)
root.geometry(f"400x{_VIEWPORT_H}+0+0")
# No window manager under Xvfb, so the toplevel must claim X input focus
# before any synthetic key event is delivered anywhere.
@ -203,6 +209,9 @@ def test_a_surface_without_a_scrollbar_still_scrolls() -> None:
"""``show_scrollbar=False`` removes the affordance, not the mechanism."""
root = tk.Tk()
try:
# See the `surface` fixture above for why this must be
# overrideredirect under a real WM.
root.overrideredirect(boolean=True)
root.geometry(f"400x{_VIEWPORT_H}+0+0")
root.focus_force()
root.update_idletasks()

View File

@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "gatelock"
version = "0.7.0"
version = "0.7.1"
description = "Shared per-output lock-window + HMAC log-integrity backend for blocking-overlay apps"
requires-python = ">=3.10"
dependencies = [] # pure stdlib — tkinter is bundled with Python