changeset 33376:a8ce25c80695 stable

Correctly scale figure position on screen with DPI scaling. * libgui/graphics/Figure.cc (Figure::Figure): Set device pixel ratio (> 1 for high DPI screens) early on in constructor of Figure. * libinterp/corefcn/graphics.cc (figure::properties::get_boundingbox, figure::properties::bbox2position): Respect device pixel ratio in conversion of "position" property to Qt screen pixel coordinates. See: https://octave.discourse.group/t/5466
author Markus Mützel <markus.muetzel@gmx.de>
date Sat, 06 Apr 2024 14:43:10 +0200
parents 31225b5d494d
children d7e4a4e1a8fb 0d1a3c2ad9c6
files libgui/graphics/Figure.cc libinterp/corefcn/graphics.cc
diffstat 2 files changed, 26 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/graphics/Figure.cc	Mon Apr 08 17:08:51 2024 +0200
+++ b/libgui/graphics/Figure.cc	Sat Apr 06 14:43:10 2024 +0200
@@ -130,6 +130,8 @@
 
   figure::properties& fp = properties<figure> ();
 
+  fp.set___device_pixel_ratio__ (win->devicePixelRatio ());
+
   // Adjust figure position
   m_innerRect = boundingBoxToRect (fp.get_boundingbox (true));
   m_outerRect = boundingBoxToRect (fp.get_boundingbox (false));
--- a/libinterp/corefcn/graphics.cc	Mon Apr 08 17:08:51 2024 +0200
+++ b/libinterp/corefcn/graphics.cc	Sat Apr 06 14:43:10 2024 +0200
@@ -3906,6 +3906,22 @@
 Matrix
 figure::properties::get_boundingbox (bool internal, const Matrix&) const
 {
+#if defined (__APPLE__) && defined (__MACH__)
+  // On macOS with Retina display, it looks like we'd need to divide the
+  // "__device_pixel_ratio__" (reported by Qt) by the "backingScaleFactor":
+  // https://developer.apple.com/documentation/appkit/nswindow/1419459-backingscalefactor
+  // It might also be that we'd need to multiply the screensize (in pixels) by
+  // the "backingScaleFactor" instead.
+  // Afaict, that factor is only available via an Objective-C-API.
+  // FIXME: Check how to get that from C++.
+  // As a workaround, assume that we are either on a display prior to Retina
+  // scaling where "__device_pixel_ratio__" and "backingScaleFactor" are both
+  // 1, or we are on a Retina display where both are probably 2. The latter
+  // might not always be the case.
+  double dpr = 1.0;
+#else
+  double dpr = get___device_pixel_ratio__ ();
+#endif
   Matrix screen_size = screen_size_pixels ();
   Matrix pos = (internal ?
                 get_position ().matrix_value () :
@@ -3915,7 +3931,7 @@
 
   pos(0)--;
   pos(1)--;
-  pos(1) = screen_size(1) - pos(1) - pos(3);
+  pos(1) = screen_size(1) / dpr - pos(1) - pos(3);
 
   return pos;
 }
@@ -3923,10 +3939,16 @@
 Matrix
 figure::properties::bbox2position (const Matrix& bb) const
 {
+#if defined (__APPLE__) && defined (__MACH__)
+  // FIXME: See comment in figure::properties::get_boundingbox.
+  double dpr = 1.0;
+#else
+  double dpr = get___device_pixel_ratio__ ();
+#endif
   Matrix screen_size = screen_size_pixels ();
   Matrix pos = bb;
 
-  pos(1) = screen_size(1) - pos(1) - pos(3);
+  pos(1) = screen_size(1) - (pos(1) + pos(3)) * dpr;
   pos(1)++;
   pos(0)++;
   pos = convert_position (pos, "pixels", get_units (), screen_size);
@@ -3937,7 +3959,6 @@
 figure::properties::set_boundingbox (const Matrix& bb, bool internal,
                                      bool do_notify_toolkit)
 {
-  Matrix screen_size = screen_size_pixels ();
   Matrix pos = bbox2position (bb);
 
   if (internal)