From 0b3e476507a0ff87b5118af6099c806ea5713ab1 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 5 Apr 2026 12:20:58 +0700 Subject: [PATCH 1/9] move resize to timer --- src/textual/app.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/textual/app.py b/src/textual/app.py index 58ddb65cea..2ec2c517ca 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -876,6 +876,8 @@ def __init__( ) ) + self._resize_timer: Timer | None = None + def get_line_filters(self) -> Sequence[LineFilter]: """Get currently enabled line filters. @@ -4312,6 +4314,8 @@ async def _on_resize(self, event: events.Resize) -> None: event.stop() self._size = event.size self._resize_event = event + if self._resize_timer is None: + self._resize_timer = self.set_timer(1 / 120, self._check_resize) async def _on_app_focus(self, event: events.AppFocus) -> None: """App has focus.""" @@ -4977,9 +4981,12 @@ def _on_in_band_window_resize(self, message: messages.InBandWindowResize) -> Non self.supports_smooth_scrolling = message.enabled self.log.debug(message) - def _on_idle(self) -> None: + def _check_resize(self) -> None: """Send app resize events on idle, so we don't do more resizing that necessary.""" event = self._resize_event + if self._resize_timer is not None: + self._resize_timer.stop() + self._resize_timer = None if event is not None: self._resize_event = None self.screen.post_message(event) From f99137b1fd8ea2eb12b0df1f92b08baf36a59f51 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 5 Apr 2026 12:30:19 +0700 Subject: [PATCH 2/9] changelog --- CHANGELOG.md | 6 ++++++ src/textual/app.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a0fa25aa9..184a5554ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [8.2.3] - Unreleased + +### Changed + +- Reduce lag when resizing window, by moving resize from idle to a timer + ## [8.2.2] - 2026-04-03 ### Fixed diff --git a/src/textual/app.py b/src/textual/app.py index 2ec2c517ca..af49af7c29 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -4982,7 +4982,7 @@ def _on_in_band_window_resize(self, message: messages.InBandWindowResize) -> Non self.log.debug(message) def _check_resize(self) -> None: - """Send app resize events on idle, so we don't do more resizing that necessary.""" + """Send a resize event to screen(s) (invoked from `self._resize_timer`).""" event = self._resize_event if self._resize_timer is not None: self._resize_timer.stop() From 9cf38324bda5c16bd44c34f3db8e2633cdd8f4d0 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 5 Apr 2026 12:32:18 +0700 Subject: [PATCH 3/9] docstring --- src/textual/app.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/textual/app.py b/src/textual/app.py index af49af7c29..78fd915b51 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -877,6 +877,7 @@ def __init__( ) self._resize_timer: Timer | None = None + """Timer used to invoke screen resize.""" def get_line_filters(self) -> Sequence[LineFilter]: """Get currently enabled line filters. From c349351edf426ac2a69e93e72c9cb04239cb4cac Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 5 Apr 2026 12:50:15 +0700 Subject: [PATCH 4/9] test fixes --- src/textual/app.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/textual/app.py b/src/textual/app.py index 78fd915b51..31603a9f0e 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -4982,6 +4982,10 @@ def _on_in_band_window_resize(self, message: messages.InBandWindowResize) -> Non self.supports_smooth_scrolling = message.enabled self.log.debug(message) + def _on_idle(self) -> None: + if self._resize_event is not None: + self._check_resize() + def _check_resize(self) -> None: """Send a resize event to screen(s) (invoked from `self._resize_timer`).""" event = self._resize_event From 12a52d9e24f1d47eb680e814527fac6ee004e573 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 5 Apr 2026 12:57:45 +0700 Subject: [PATCH 5/9] check screen error --- src/textual/app.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/textual/app.py b/src/textual/app.py index 31603a9f0e..d31fdae4e6 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -4982,10 +4982,6 @@ def _on_in_band_window_resize(self, message: messages.InBandWindowResize) -> Non self.supports_smooth_scrolling = message.enabled self.log.debug(message) - def _on_idle(self) -> None: - if self._resize_event is not None: - self._check_resize() - def _check_resize(self) -> None: """Send a resize event to screen(s) (invoked from `self._resize_timer`).""" event = self._resize_event @@ -4993,6 +4989,11 @@ def _check_resize(self) -> None: self._resize_timer.stop() self._resize_timer = None if event is not None: + + try: + self.screen + except ScreenError: + return self._resize_event = None self.screen.post_message(event) for screen in self._background_screens: From ec5b43ae1cc2c49361f0d791a53dd047bce08369 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 5 Apr 2026 13:21:13 +0700 Subject: [PATCH 6/9] also resize on idle --- src/textual/app.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/textual/app.py b/src/textual/app.py index d31fdae4e6..d535fd5a68 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -4982,6 +4982,10 @@ def _on_in_band_window_resize(self, message: messages.InBandWindowResize) -> Non self.supports_smooth_scrolling = message.enabled self.log.debug(message) + def _on_idle(self) -> None: + if self._resize_event is not None: + self._check_resize() + def _check_resize(self) -> None: """Send a resize event to screen(s) (invoked from `self._resize_timer`).""" event = self._resize_event From 63fe6f0646e0f1401b990fb64f292d9646d01014 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 5 Apr 2026 15:22:58 +0700 Subject: [PATCH 7/9] check resize timer on idle --- src/textual/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/textual/app.py b/src/textual/app.py index d535fd5a68..aaf94e9064 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -4983,7 +4983,7 @@ def _on_in_band_window_resize(self, message: messages.InBandWindowResize) -> Non self.log.debug(message) def _on_idle(self) -> None: - if self._resize_event is not None: + if self._resize_event is not None and self._resize_timer is None: self._check_resize() def _check_resize(self) -> None: From 4b6579038979a90d1f4067d8e396f0af13e80f75 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 5 Apr 2026 15:33:24 +0700 Subject: [PATCH 8/9] ignore no size changes --- src/textual/app.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/textual/app.py b/src/textual/app.py index aaf94e9064..fc3d7cbd9f 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -4313,6 +4313,8 @@ async def _on_key(self, event: events.Key) -> None: async def _on_resize(self, event: events.Resize) -> None: event.stop() + if self._size is not None and self._size == event.size: + return self._size = event.size self._resize_event = event if self._resize_timer is None: From 2bbfbb7741470e8cf95c37476047b89787afaec5 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 5 Apr 2026 15:38:00 +0700 Subject: [PATCH 9/9] force initial resize --- src/textual/app.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/textual/app.py b/src/textual/app.py index fc3d7cbd9f..4f034ab1af 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -4313,10 +4313,14 @@ async def _on_key(self, event: events.Key) -> None: async def _on_resize(self, event: events.Resize) -> None: event.stop() - if self._size is not None and self._size == event.size: + self._resize_event = event + if self._size is None: + self._size = event.size + self._check_resize() + return + if self._size == event.size: return self._size = event.size - self._resize_event = event if self._resize_timer is None: self._resize_timer = self.set_timer(1 / 120, self._check_resize) @@ -4995,7 +4999,6 @@ def _check_resize(self) -> None: self._resize_timer.stop() self._resize_timer = None if event is not None: - try: self.screen except ScreenError: