Skip to content

Commit

Permalink
Fix fan charts on HiDPI screens
Browse files Browse the repository at this point in the history
Most DrawingArea-based widgets are fine, but the fan charts use a
backing image surface that is blitted when needed. On HiDPI displays,
this image surface is normal size, and thus everything ends up blurry
when scaled up.

Instead the backing surface should be scaled to match the display, and
also re-created if the display scale changes (e.g., if display settings
change, or the window is moved between displays with different
settings.)
  • Loading branch information
QuLogic authored and Nick-Hall committed Mar 22, 2024
1 parent 3765d51 commit 506a638
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 3 deletions.
20 changes: 19 additions & 1 deletion gramps/gui/widgets/fanchart.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ def __init__(self, dbstate, uistate, callback_popup=None):
self.set_can_focus(True)
self.connect("key-press-event", self.on_key_press)

self.connect("notify::scale-factor", self.on_notify_scale_factor)
self.connect("draw", self.on_draw)
self.add_events(
Gdk.EventMask.BUTTON_PRESS_MASK
Expand Down Expand Up @@ -295,6 +296,19 @@ def get_radiusinout_for_gen(self, generation):
"""
raise NotImplementedError

def on_notify_scale_factor(self, obj, pspec):
"""
Callback to redraw the fanchart if the display's scale factor changes.
"""
if not self.surface:
return
existing_scale = self.surface.get_device_scale()
if self.get_scale_factor() == existing_scale[0] == existing_scale[1]:
return
self.surface = None
self.draw()
self.queue_draw()

def on_draw(self, widget, ctx, scale=1.0):
"""
callback to draw the fanchart
Expand Down Expand Up @@ -1676,7 +1690,11 @@ def draw(self, ctx=None, scale=1.0):
self.set_size_request(max(size_w, size_w_a), max(size_h, size_h_a))
size_w = self.get_allocated_width()
size_h = self.get_allocated_height()
self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, size_w, size_h)
scale_factor = self.get_scale_factor()
self.surface = cairo.ImageSurface(
cairo.FORMAT_ARGB32, size_w * scale_factor, size_h * scale_factor
)
self.surface.set_device_scale(scale_factor, scale_factor)
ctx = cairo.Context(self.surface)
self.center_xy = self.center_xy_from_delta()
ctx.translate(*self.center_xy)
Expand Down
6 changes: 5 additions & 1 deletion gramps/gui/widgets/fanchart2way.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,11 @@ def draw(self, ctx=None, scale=1.0):
self.set_size_request(max(size_w, size_w_a), max(size_h, size_h_a))
size_w = self.get_allocated_width()
size_h = self.get_allocated_height()
self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, size_w, size_h)
scale_factor = self.get_scale_factor()
self.surface = cairo.ImageSurface(
cairo.FORMAT_ARGB32, size_w * scale_factor, size_h * scale_factor
)
self.surface.set_device_scale(scale_factor, scale_factor)
ctx = cairo.Context(self.surface)
self.center_xy = self.center_xy_from_delta()
ctx.translate(*self.center_xy)
Expand Down
6 changes: 5 additions & 1 deletion gramps/gui/widgets/fanchartdesc.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,11 @@ def draw(self, ctx=None, scale=1.0):
self.set_size_request(max(size_w, size_w_a), max(size_h, size_h_a))
size_w = self.get_allocated_width()
size_h = self.get_allocated_height()
self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, size_w, size_h)
scale_factor = self.get_scale_factor()
self.surface = cairo.ImageSurface(
cairo.FORMAT_ARGB32, size_w * scale_factor, size_h * scale_factor
)
self.surface.set_device_scale(scale_factor, scale_factor)
ctx = cairo.Context(self.surface)
self.center_xy = self.center_xy_from_delta()
ctx.translate(*self.center_xy)
Expand Down

0 comments on commit 506a638

Please sign in to comment.