From fbf5477c809a3b0990ee0139401b652ecce201c7 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell <tcaswell@gmail.com> Date: Wed, 20 Oct 2021 18:03:14 -0400 Subject: [PATCH] Backport PR #21212: Fix set_size_inches on HiDPI and also GTK4 --- lib/matplotlib/backend_bases.py | 9 +++++++-- lib/matplotlib/backends/backend_gtk3.py | 2 ++ lib/matplotlib/backends/backend_gtk4.py | 15 +++++---------- lib/matplotlib/backends/backend_qt.py | 6 ++++-- lib/matplotlib/figure.py | 3 +-- 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 0f5949445775..312cb649dc81 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1760,7 +1760,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``.""" @@ -2813,7 +2818,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 662d1028658e..e1d006436263 100644 --- a/lib/matplotlib/backends/backend_gtk3.py +++ b/lib/matplotlib/backends/backend_gtk3.py @@ -413,6 +413,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 2a589ee691a3..dcc97a1dec5c 100644 --- a/lib/matplotlib/backends/backend_gtk4.py +++ b/lib/matplotlib/backends/backend_gtk4.py @@ -374,18 +374,13 @@ 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 + 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): diff --git a/lib/matplotlib/backends/backend_qt.py b/lib/matplotlib/backends/backend_qt.py index 908e2affad31..d8c0caadd1fd 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 418948eea5e0..2454776370d0 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -2657,10 +2657,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):