Skip to content

Commit 1abbe8a

Browse files
authored
Fix TextArea cursor being visible before it has focus for first time (#4128)
* Fix TextArea cursor being visible before it has focus * Ensure cursor blink reactive can be toggled when the widget does and does not have focus, and responds correctly * Update the CHANGELOG * Update snapshots * Update command palette snapshot
1 parent 8036270 commit 1abbe8a

File tree

3 files changed

+82
-74
lines changed

3 files changed

+82
-74
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1717
- Fixed a crash in the TextArea when performing a backward replace https://github.com/Textualize/textual/pull/4126
1818
- Fixed selection not updating correctly when pasting while there's a non-zero selection https://github.com/Textualize/textual/pull/4126
1919
- Breaking change: `TextArea` will not use `Escape` to shift focus if the `tab_behaviour` is the default https://github.com/Textualize/textual/issues/4110
20+
- `TextArea` cursor will now be invisible before first focus https://github.com/Textualize/textual/pull/4128
21+
- Fix toggling `TextArea.cursor_blink` reactive when widget does not have focus https://github.com/Textualize/textual/pull/4128
2022

2123
### Added
2224

src/textual/widgets/_text_area.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ class TextArea(ScrollView, can_focus=True):
295295
soft_wrap: Reactive[bool] = reactive(True, init=False)
296296
"""True if text should soft wrap."""
297297

298-
_cursor_visible: Reactive[bool] = reactive(True, repaint=False, init=False)
298+
_cursor_visible: Reactive[bool] = reactive(False, repaint=False, init=False)
299299
"""Indicates where the cursor is in the blink cycle. If it's currently
300300
not visible due to blinking, this is False."""
301301

@@ -518,9 +518,13 @@ def _build_highlight_map(self) -> None:
518518
# Add the last line of the node range
519519
highlights[node_end_row].append((0, node_end_column, highlight_name))
520520

521-
def watch_has_focus(self, value: bool) -> None:
522-
self._cursor_visible = value
523-
super().watch_has_focus(value)
521+
def _watch_has_focus(self, focus: bool) -> None:
522+
self._cursor_visible = focus
523+
if focus:
524+
self._restart_blink()
525+
self.app.cursor_position = self.cursor_screen_offset
526+
else:
527+
self._pause_blink(visible=False)
524528

525529
def _watch_selection(
526530
self, previous_selection: Selection, selection: Selection
@@ -549,6 +553,14 @@ def _watch_selection(
549553
if previous_selection != selection:
550554
self.post_message(self.SelectionChanged(selection, self))
551555

556+
def _watch_cursor_blink(self, blink: bool) -> None:
557+
if not self.is_mounted:
558+
return None
559+
if blink and self.has_focus:
560+
self._restart_blink()
561+
else:
562+
self._pause_blink(visible=self.has_focus)
563+
552564
def _recompute_cursor_offset(self):
553565
"""Recompute the (x, y) coordinate of the cursor in the wrapped document."""
554566
self._cursor_offset = self.wrapped_document.location_to_offset(
@@ -1028,8 +1040,10 @@ def render_line(self, widget_y: int) -> Strip:
10281040
)
10291041

10301042
if cursor_row == line_index:
1031-
draw_cursor = not self.cursor_blink or (
1032-
self.cursor_blink and self._cursor_visible
1043+
draw_cursor = (
1044+
self.has_focus
1045+
and not self.cursor_blink
1046+
or (self.cursor_blink and self._cursor_visible)
10331047
)
10341048
if draw_matched_brackets:
10351049
matching_bracket_style = theme.bracket_matching_style if theme else None
@@ -1290,13 +1304,6 @@ def _on_mount(self, _: events.Mount) -> None:
12901304
pause=not (self.cursor_blink and self.has_focus),
12911305
)
12921306

1293-
def _on_blur(self, _: events.Blur) -> None:
1294-
self._pause_blink(visible=True)
1295-
1296-
def _on_focus(self, _: events.Focus) -> None:
1297-
self._restart_blink()
1298-
self.app.cursor_position = self.cursor_screen_offset
1299-
13001307
def _toggle_cursor_blink_visible(self) -> None:
13011308
"""Toggle visibility of the cursor for the purposes of 'cursor blink'."""
13021309
self._cursor_visible = not self._cursor_visible

0 commit comments

Comments
 (0)