Skip to content

Conversation

@veeceey
Copy link

@veeceey veeceey commented Feb 8, 2026

Summary

Fixes #6349 - The mouse pointer (cursor) style becomes "sticky" when a modal screen containing a Button is dismissed. The cursor remains as a pointing-hand instead of reverting to the default arrow.

Root cause: Two issues contributed:

  1. Stale mouse_over reference: update_pointer_shape() used app.mouse_over without checking whether the widget belonged to the current screen. After a screen dismiss, mouse_over could still reference a widget from the removed screen (e.g., a Button with pointer: pointer style), causing the stale pointer shape to persist.

  2. Missing pointer refresh on screen resume: _on_screen_resume did not re-send the pointer shape to the terminal. Since _pointer_shape is a reactive var, the watcher only fires on value changes. If the resumed screen already had _pointer_shape="default", no escape sequence was emitted -- so the terminal kept showing the dismissed screen's pointer shape.

Fix:

  • Guard update_pointer_shape() against stale cross-screen mouse_over references by checking if the widget is an ancestor of the current screen.
  • Force-send the pointer shape escape sequence in _on_screen_resume after recalculating the correct shape, regardless of whether the reactive value changed.

Test plan

  • Added regression test test_pointer_shape_restored_on_screen_dismiss that reproduces the exact scenario from the issue (push modal with Button, hover over button, dismiss, verify pointer resets)
  • Existing test_pointer_shape test continues to pass
  • All test_app.py tests pass (27/27)
  • All test_screens.py and test_modal.py tests pass (20/20)

🤖 Generated with Claude Code

When a modal screen with a Button (which uses `pointer: pointer` CSS)
was dismissed, the cursor remained as a pointing-hand instead of
reverting to the default arrow. Two issues contributed to this:

1. `update_pointer_shape()` used `app.mouse_over` without checking if
   the widget belonged to the current screen. After a screen dismiss,
   `mouse_over` could still reference a widget from the removed screen,
   causing the stale pointer style to persist.

2. `_on_screen_resume` did not re-send the pointer shape to the
   terminal. Since `_pointer_shape` is a reactive `var`, the watcher
   only fires on value changes. If the resumed screen already had
   `_pointer_shape="default"`, no escape sequence was sent.

The fix guards `update_pointer_shape` against stale cross-screen
`mouse_over` references, and forces the pointer shape escape sequence
to be re-sent whenever a screen resumes.

Fixes Textualize#6349

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pointer style can become sticky on screen removal

1 participant