Jeroen: 'it scrolls out of screen automatically.' It did, with no input.
_gui_input only fires while the pointer is over the Control, so
_last_mouse_pos freezes at wherever it was last seen. Leaving the map ALWAYS
means crossing an edge, so the frozen value is always inside the 24px edge
margin — and the viewer went on believing the cursor was held there, panning
forever. Moving the mouse elsewhere could not stop it, because 'elsewhere'
generates no events this Control ever hears.
NOTIFICATION_MOUSE_EXIT now resets to the same (-1,-1) sentinel the field is
born with, making 'pointer is not over the map' and 'pointer has never been
over the map' the same state. Neither should scroll, and there was already a
test asserting the second case — the first had no equivalent.
Considered and rejected: reading get_local_mouse_position() live instead of
caching. It is arguably cleaner, but it cannot be injected in a headless test,
so it would have traded a bug for the inability to prove the fix — and the
existing edge-scroll suite drives _last_mouse_pos directly.
This also explains the drift I had blamed on the capture harness (T-1236):
same defect, and the harness was simply exercising it faithfully.
Client suite 1833 / 1807 passed / 0 failed / 26 skipped.
Co-Authored-By: Claude <noreply@anthropic.com>