Repository: Textualize/textual

Issue:
All TextAreas have blinking cursors after switching back to a previously selected tab
Example:

```
from textual.app import App, ComposeResult
from textual.widgets import TabbedContent, TabPane, TextArea

class TabbedTextAreaApp(App[None]):

    def compose(self) -> ComposeResult:
        with TabbedContent():
            for tab in ("one", "two"):
                with TabPane(f"{tab}.py"):
                    for _ in range(3):
                        yield TextArea(language="python")

if __name__ == "__main__":
    TabbedTextAreaApp().run()
```

To reproduce behavior: Start program, click on tab `two`, then click on `one`. Notice that all the text areas have blinking cursors.
A workaround I've done is to set `cursor_blink` to `False` and then back to `True` on `TabActivated`.

![Code_fxryGjsZcx](https://github.com/Textualize/textual/assets/15637422/d3250c84-40f0-40ef-9959-030547e0d029)

<!-- This is valid Markdown, please paste the following directly in to a GitHub issue -->
# Textual Diagnostics

## Versions

| Name    | Value  |
|---------|--------|
| Textual | 0.56.4 |
| Rich    | 13.7.1 |

## Python

| Name           | Value            |
|----------------|------------------|
| Version        | 3.8.10           |
| Implementation | CPython          |
| Compiler       | GCC 9.4.0        |
| Executable     | /usr/bin/python3 |

## Operating System

| Name    | Value                                        |
|---------|----------------------------------------------|
| System  | Linux                                        |
| Release | 4.4.0-19041-Microsoft                        |
| Version | #3996-Microsoft Thu Jan 18 16:36:00 PST 2024 |

## Terminal

| Name                 | Value           |
|----------------------|-----------------|
| Terminal Application | vscode (1.88.1) |
| TERM                 | xterm-256color  |
| COLORTERM            | truecolor       |
| FORCE_COLOR          | *Not set*       |
| NO_COLOR             | *Not set*       |

## Rich Console options

| Name           | Value                |
|----------------|----------------------|
| size           | width=203, height=31 |
| legacy_windows | False                |
| min_width      | 1                    |
| max_width      | 203                  |
| is_terminal    | True                 |
| encoding       | utf-8                |
| max_height     | 31                   |
| justify        | None                 |
| overflow       | None                 |
| no_wrap        | False                |
| highlight      | None                 |
| markup         | None                 |
| height         | None                 |




Discussion:
We found the following entry in the [FAQ](https://textual.textualize.io/FAQ/) which you may find helpful:


- [Why doesn't Textual look good on macOS?](https://textual.textualize.io/FAQ/#why-doesnt-textual-look-good-on-macos)

Feel free to close this issue if you found an answer in the FAQ. Otherwise, please give us a little time to review.

This is an automated reply, generated by [FAQtory](https://github.com/willmcgugan/faqtory)

Resolving patch:
diff --git a/src/textual/widgets/_text_area.py b/src/textual/widgets/_text_area.py
--- a/src/textual/widgets/_text_area.py
+++ b/src/textual/widgets/_text_area.py
@@ -1513,17 +1513,18 @@ async def _on_mouse_move(self, event: events.MouseMove) -> None:
 
     def _end_mouse_selection(self) -> None:
         """Finalize the selection that has been made using the mouse."""
-        self._selecting = False
-        self.release_mouse()
-        self.record_cursor_width()
-        self._restart_blink()
+        if self._selecting:
+            self._selecting = False
+            self.release_mouse()
+            self.record_cursor_width()
+            self._restart_blink()
 
     async def _on_mouse_up(self, event: events.MouseUp) -> None:
         """Finalize the selection that has been made using the mouse."""
         self._end_mouse_selection()
 
     async def _on_hide(self, event: events.Hide) -> None:
-        """Finalize the selection that has been made using the mouse when thew widget is hidden."""
+        """Finalize the selection that has been made using the mouse when the widget is hidden."""
         self._end_mouse_selection()
 
     async def _on_paste(self, event: events.Paste) -> None:


Test patch: