From 4b5328d4170feb962abea779f24796c971e3422b Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 28 Sep 2021 02:35:11 -0400 Subject: [PATCH 1/2] GTK4: Fix forward application of set_size_inches --- lib/matplotlib/backends/backend_gtk4.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/lib/matplotlib/backends/backend_gtk4.py b/lib/matplotlib/backends/backend_gtk4.py index 6ddcaaa18bbb..1a0179c5f189 100644 --- a/lib/matplotlib/backends/backend_gtk4.py +++ b/lib/matplotlib/backends/backend_gtk4.py @@ -374,17 +374,10 @@ def set_window_title(self, title): def resize(self, width, height): """Set the canvas size in pixels.""" if self.toolbar: - toolbar_size = self.toolbar.size_request() - height += toolbar_size.height + min_size, nat_size = self.toolbar.get_preferred_size() + height += nat_size.height canvas_size = self.canvas.get_allocation() - if canvas_size.width == canvas_size.height == 1: - # A canvas size of (1, 1) cannot exist in most cases, because - # window decorations would prevent such a small window. This call - # must be before the window has been mapped and widgets have been - # sized, so just change the window's starting size. - self.window.set_default_size(width, height) - else: - self.window.resize(width, height) + self.window.set_default_size(width, height) class NavigationToolbar2GTK4(_NavigationToolbar2GTK, Gtk.Box): From 986982682c63cce978555af97c490af36cab9e53 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 28 Sep 2021 02:36:36 -0400 Subject: [PATCH 2/2] Fix set_size_inches on HiDPI screens This passes physical pixels to the backend, as it will be more accurate due to the int-cast. Fixes #21090 --- lib/matplotlib/backend_bases.py | 9 +++++++-- lib/matplotlib/backends/backend_gtk3.py | 2 ++ lib/matplotlib/backends/backend_gtk4.py | 2 ++ lib/matplotlib/backends/backend_qt.py | 6 ++++-- lib/matplotlib/figure.py | 3 +-- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 38d408ba02c6..1793d9fa8eb5 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1762,7 +1762,12 @@ def blit(self, bbox=None): """Blit the canvas in bbox (default entire canvas).""" def resize(self, w, h): - """Set the canvas size in pixels.""" + """ + UNUSED: Set the canvas size in pixels. + + Certain backends may implement a similar method internally, but this is + not a requirement of, nor is it used by, Matplotlib itself. + """ def draw_event(self, renderer): """Pass a `DrawEvent` to all functions connected to ``draw_event``.""" @@ -2815,7 +2820,7 @@ def full_screen_toggle(self): pass def resize(self, w, h): - """For GUI backends, resize the window (in pixels).""" + """For GUI backends, resize the window (in physical pixels).""" @_api.deprecated( "3.4", alternative="self.canvas.callbacks.process(event.name, event)") diff --git a/lib/matplotlib/backends/backend_gtk3.py b/lib/matplotlib/backends/backend_gtk3.py index bca921f03794..aad634314cf9 100644 --- a/lib/matplotlib/backends/backend_gtk3.py +++ b/lib/matplotlib/backends/backend_gtk3.py @@ -421,6 +421,8 @@ def set_window_title(self, title): def resize(self, width, height): """Set the canvas size in pixels.""" + width = int(width / self.canvas.device_pixel_ratio) + height = int(height / self.canvas.device_pixel_ratio) if self.toolbar: toolbar_size = self.toolbar.size_request() height += toolbar_size.height diff --git a/lib/matplotlib/backends/backend_gtk4.py b/lib/matplotlib/backends/backend_gtk4.py index 1a0179c5f189..fd2b44e3f27e 100644 --- a/lib/matplotlib/backends/backend_gtk4.py +++ b/lib/matplotlib/backends/backend_gtk4.py @@ -373,6 +373,8 @@ def set_window_title(self, title): def resize(self, width, height): """Set the canvas size in pixels.""" + width = int(width / self.canvas.device_pixel_ratio) + height = int(height / self.canvas.device_pixel_ratio) if self.toolbar: min_size, nat_size = self.toolbar.get_preferred_size() height += nat_size.height diff --git a/lib/matplotlib/backends/backend_qt.py b/lib/matplotlib/backends/backend_qt.py index 6bb1f82c0f24..d836ca84c356 100644 --- a/lib/matplotlib/backends/backend_qt.py +++ b/lib/matplotlib/backends/backend_qt.py @@ -589,8 +589,10 @@ def _get_toolbar(self, canvas, parent): return toolbar def resize(self, width, height): - # these are Qt methods so they return sizes in 'virtual' pixels - # so we do not need to worry about dpi scaling here. + # The Qt methods return sizes in 'virtual' pixels so we do need to + # rescale from physical to logical pixels. + width = int(width / self.canvas.device_pixel_ratio) + height = int(height / self.canvas.device_pixel_ratio) extra_width = self.window.width() - self.canvas.width() extra_height = self.window.height() - self.canvas.height() self.canvas.resize(width, height) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 5f212043c6c9..ffbb486a139d 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -2658,10 +2658,9 @@ def set_size_inches(self, w, h=None, forward=True): if forward: canvas = getattr(self, 'canvas') if canvas is not None: - dpi_ratio = getattr(canvas, '_dpi_ratio', 1) manager = getattr(canvas, 'manager', None) if manager is not None: - manager.resize(*(size * self.dpi / dpi_ratio).astype(int)) + manager.resize(*(size * self.dpi).astype(int)) self.stale = True def get_size_inches(self):