utils/gatelock/gatelock
Krzysztof kuhy Rudnicki d82107ab9a gatelock: bind the wheel per descendant in ScrollableSurface
Wheel-over-text did not scroll. Tk dispatches through *bindtags*, not the
parent chain -- a child's tags are (itself, its class, the toplevel, "all") --
so binding <Button-4>/<Button-5> on `content` was never consulted for an event
over a Label sitting on top of it. Content that fills its viewport covers that
frame completely, which is every screen this class exists for, so the mouse
wheel was dead exactly where a user points it.

Found while retiring leetcode-guard's hand-rolled _scrollable, which got this
right by accident: it used bind_all, which works but installs the handler on
every widget in the application, including other windows' scroll regions.
Binding per descendant inside the existing _track_focus walk keeps it scoped,
and reuses that walk's WeakSet so a repaint cannot stack duplicate handlers.

Verified both directions under xvfb (Button-5 scrolls down, Button-4 back up)
from an event generated on a Label, not on the canvas.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U4Rj3s7K2qzrLNgJqqPhno
2026-08-15 14:12:30 +02:00
..
tests gatelock: bind the wheel per descendant in ScrollableSurface 2026-08-15 14:12:30 +02:00
__init__.py gatelock: add shared button, heading/row and WidgetGroup 2026-08-14 23:54:52 +02:00
_arbiter.py gatelock v0.2.0: per-output locking, monotonic recovery, N-app arbitration 2026-07-25 14:30:03 +02:00
_density.py gatelock 0.4.0: the viewport moves for the user and nobody else 2026-08-03 15:50:51 +02:00
_detect.py gatelock v0.2.0: per-output locking, monotonic recovery, N-app arbitration 2026-07-25 14:30:03 +02:00
_escape.py gatelock: extract the shared escape-hatch core 2026-07-25 15:35:20 +02:00
_fitcheck.py gatelock 0.4.0: the viewport moves for the user and nobody else 2026-08-03 15:50:51 +02:00
_guards.py gatelock v0.2.0: per-output locking, monotonic recovery, N-app arbitration 2026-07-25 14:30:03 +02:00
_keyboard.py Make lock surfaces keyboard-operable and safe on a 768px screen 2026-07-30 16:01:15 +02:00
_outputs.py gatelock v0.2.0: per-output locking, monotonic recovery, N-app arbitration 2026-07-25 14:30:03 +02:00
_recovery.py gatelock 0.4.1: re-focus a surface that comes back after a blip 2026-08-12 22:13:46 +02:00
_root.py Initial gatelock: shared lock-window + HMAC log-integrity backend 2026-06-19 17:39:44 +02:00
_scrollable.py gatelock: bind the wheel per descendant in ScrollableSurface 2026-08-15 14:12:30 +02:00
_surfaces.py gatelock v0.2.0: per-output locking, monotonic recovery, N-app arbitration 2026-07-25 14:30:03 +02:00
_vt.py Initial gatelock: shared lock-window + HMAC log-integrity backend 2026-06-19 17:39:44 +02:00
_window.py gatelock 0.4.1: re-focus a surface that comes back after a blip 2026-08-12 22:13:46 +02:00
log_integrity.py Initial gatelock: shared lock-window + HMAC log-integrity backend 2026-06-19 17:39:44 +02:00
widget_group.py gatelock: add shared button, heading/row and WidgetGroup 2026-08-14 23:54:52 +02:00
widgets.py gatelock: add shared button, heading/row and WidgetGroup 2026-08-14 23:54:52 +02:00