From 8feb6d8fafe15a8f49e72561b71138c00f55136c Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Mon, 30 Mar 2020 19:49:16 -0400 Subject: [PATCH 1/3] Avoid triggering full dpi change if it's unchanged. This is essentially a revert of the `Text.get_window_extent` change to its dpi handling, but applies in _all_ cases. Depending on backend, we want to avoid this extraneous dpi change, because it can cause recursive event signals. For example, with GTK3, a resize will trigger its event loop, which eventually causes a re-draw. The re-draw would get to `Text.get_window_extent`, change the dpi (to the same value), and call `Figure.set_size_inches`, which would resize the window again. Depending on how much of the GTK event loop was processed, this may or may not trigger another draw, recursing again and again. Fixes #16934. --- lib/matplotlib/figure.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 69b22df4528d..299e893993f8 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -442,6 +442,9 @@ def _set_dpi(self, dpi, forward=True): forward : bool Passed on to `~.Figure.set_size_inches` """ + if dpi == self._dpi: + # We don't want to cause undue events in backends. + return self._dpi = dpi self.dpi_scale_trans.clear().scale(dpi) w, h = self.get_size_inches() From da078cac5f5938f1495db5954b5a160fdf72ae36 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Mon, 30 Mar 2020 21:23:18 -0400 Subject: [PATCH 2/3] gtk: Correctly resize canvas to intended size. Previously, it was the window that was resized to the intended size, thus making the canvas smaller by the toolbar height. Fixes #10083 for GTK3. Fixes #10566 for GTK3. --- lib/matplotlib/backends/backend_gtk3.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/backends/backend_gtk3.py b/lib/matplotlib/backends/backend_gtk3.py index 2f34248837dc..60537cf6443a 100644 --- a/lib/matplotlib/backends/backend_gtk3.py +++ b/lib/matplotlib/backends/backend_gtk3.py @@ -436,10 +436,21 @@ def set_window_title(self, title): def resize(self, width, height): """Set the canvas size in pixels.""" - #_, _, cw, ch = self.canvas.allocation - #_, _, ww, wh = self.window.allocation - #self.window.resize (width-cw+ww, height-ch+wh) - self.window.resize(width, height) + if self.toolbar: + toolbar_size = self.toolbar.size_request() + height += toolbar_size.height + if self.statusbar: + statusbar_size = self.statusbar.size_request() + height += statusbar_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) class NavigationToolbar2GTK3(NavigationToolbar2, Gtk.Toolbar): From 1a7cc4c83dcdb3602929acb60e2f6cc3cf221962 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 31 Mar 2020 01:25:21 -0400 Subject: [PATCH 3/3] Fix test_canvas_reinit. The figure is no longer set stale because `resize` is no longer called. There's no reason the figure should be stale until it's ready to be drawn, but we don't really need a whole main loop for this test. --- lib/matplotlib/tests/test_backend_qt.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/matplotlib/tests/test_backend_qt.py b/lib/matplotlib/tests/test_backend_qt.py index 1f4798e25498..2545c3c68923 100644 --- a/lib/matplotlib/tests/test_backend_qt.py +++ b/lib/matplotlib/tests/test_backend_qt.py @@ -271,4 +271,5 @@ def crashing_callback(fig, stale): fig.stale_callback = crashing_callback # this should not raise canvas = FigureCanvasQTAgg(fig) + fig.stale = True assert called