Skip to content

Fix set_size_inches on HiDPI and also GTK4 #21212

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions lib/matplotlib/backend_bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is on FigureCanvasBase, but it's actually unused. I will modify the docstring for FigureManagerBase.resize, and mark this one unused.

"""
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``."""
Expand Down Expand Up @@ -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)")
Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_gtk3.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 5 additions & 10 deletions lib/matplotlib/backends/backend_gtk4.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,18 +373,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):
Expand Down
6 changes: 4 additions & 2 deletions lib/matplotlib/backends/backend_qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 1 addition & 2 deletions lib/matplotlib/figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, this always returned 1 since the attribute was renamed, so the resize was always in physical pixels.

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):
Expand Down