Skip to content

Commit 03979fc

Browse files
authored
Merge pull request #5900 from Textualize/input-mouse-release-fix
Input should release mouse on screen change
2 parents 629ffb5 + bf089e0 commit 03979fc

File tree

4 files changed

+19
-3
lines changed

4 files changed

+19
-3
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99

1010
### Fixed
1111

12-
- Fixed issue with the "transparent" CSS value not being transparent when set using python
12+
- Fixed issue with the "transparent" CSS value not being transparent when set using python https://github.com/Textualize/textual/pull/5890
13+
- Fixed issue with pushing screens when Input has mouse captured https://github.com/Textualize/textual/pull/5900
14+
15+
## Changed
16+
17+
- Widget.release_mouse will now only release the mouse, if it was captured by self https://github.com/Textualize/textual/pull/5900
1318

1419
## [3.5.0] - 2025-06-20
1520

src/textual/app.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2680,6 +2680,7 @@ async def _replace_screen(self, screen: Screen) -> Screen:
26802680
if not self.is_screen_installed(screen) and all(
26812681
screen not in stack for stack in self._screen_stacks.values()
26822682
):
2683+
self.capture_mouse(None)
26832684
await screen.remove()
26842685
self.log.system(f"{screen} REMOVED")
26852686
return screen
@@ -2736,6 +2737,7 @@ def push_screen(
27362737
else:
27372738
future = loop.create_future()
27382739

2740+
self.app.capture_mouse(None)
27392741
if self._screen_stack:
27402742
self.screen.post_message(events.ScreenSuspend())
27412743
self.screen.refresh()
@@ -2804,6 +2806,7 @@ def switch_screen(self, screen: Screen | str) -> AwaitComplete:
28042806
self.log.system(f"Screen {screen} is already current.")
28052807
return AwaitComplete.nothing()
28062808

2809+
self.app.capture_mouse(None)
28072810
top_screen = self._screen_stack.pop()
28082811

28092812
top_screen._pop_result_callback()

src/textual/widget.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4341,7 +4341,8 @@ def release_mouse(self) -> None:
43414341
43424342
Mouse events will only be sent when the mouse is over the widget.
43434343
"""
4344-
self.app.capture_mouse(None)
4344+
if self.app.mouse_captured is self:
4345+
self.app.capture_mouse(None)
43454346

43464347
def text_select_all(self) -> None:
43474348
"""Select the entire widget."""

src/textual/widgets/_input.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,12 +769,19 @@ async def _on_mouse_down(self, event: events.MouseDown) -> None:
769769
self._selecting = True
770770
self.capture_mouse()
771771

772-
async def _on_mouse_up(self, event: events.MouseUp) -> None:
772+
def _end_selecting(self) -> None:
773+
"""End selecting if it is currently active."""
773774
if self._selecting:
774775
self._selecting = False
775776
self.release_mouse()
776777
self._restart_blink()
777778

779+
async def _on_mouse_release(self, _event: events.MouseRelease) -> None:
780+
self._end_selecting()
781+
782+
async def _on_mouse_up(self, _event: events.MouseUp) -> None:
783+
self._end_selecting()
784+
778785
async def _on_mouse_move(self, event: events.MouseMove) -> None:
779786
if self._selecting:
780787
# As we drag the mouse, we update the end position of the selection,

0 commit comments

Comments
 (0)