[Development] Patch for dynamic updates to the screen's DPI settings

Jan Kundrát jkt at flaska.net
Tue Oct 23 03:08:42 CEST 2012


Dear Qt developers,
I got a new toy at work -- a 27" LCD with some crazy resolution
(2560x1440 IIRC), i,e. its pixel density is roughly 109 PPI. The LCD I
use at home has got a 94 PPI grid. I frequently move my laptop between
these two places and I have yet to make my KDE 4.9 use fonts which look
great no matter which display I switched to at runtime. The current
state is driving me nuts; I have to constantly adjust the font size in
KDE's preferences *and* restart the applications afterwards, so that
they pick up the new font preferences. That's not the first thing I want
to do when I get to work in the morning.

It looks like Qt 4.8.3 doesn't provide dynamic updates to the DPI value
to the applications. The attached patch does just that; it simply
updates the value which is returned by QX11Info::appDpiX() and appDpiY
when XRandR informs about new geometry. No fancy signalling is done.

The results are actually pretty funny; it looks like a QTreeView would
use the new font size only for text items whose font previously did not
fit the column width while those which fit will remain in the previous
size; there are also no changes to stuff like height of the menu bars,
the layouts won't change, and so on. On the other hand, it's now enough
to reopen the current file in Qt Creator and the font size reflects the
new DPI.

I don't know anything about Qt internals (and I suspect that this is not
exactly an area a newcomer should dive into), so I'll appreciate some
pointers about what else would need changing in order for dynamic DPI to
work. Or is this a futile attempt which is doomed to failure anyway? Are
there any chances of getting this accepted, eventually?

How to test this:

- apply the patch, build QtGui
- run `xdpyinfo | grep dots` to remember your current DPI
- run `xrandr --dpi 150` to see huge letters (on most displays)
- run `xrandr --dpi number-from-step-one` to get back to your default

With kind regards,
Jan

-- 
Trojita, a fast e-mail client -- http://trojita.flaska.net/
-------------- next part --------------
--- src/gui/kernel/qapplication_x11.cpp.orig	2012-09-11 03:36:51.000000000 +0200
+++ src/gui/kernel/qapplication_x11.cpp	2012-10-23 02:54:28.686976576 +0200
@@ -1629,6 +1629,23 @@
 }
 #endif
 
+static void calculate_dpi_values(const int screen, int &dpiX, int &dpiY)
+{
+    int widthMM = DisplayWidthMM(X11->display, screen);
+    if (widthMM != 0) {
+        dpiX = (DisplayWidth(X11->display, screen) * 254 + widthMM * 5) / (widthMM * 10);
+    } else {
+        dpiX = 72;
+    }
+
+    int heightMM = DisplayHeightMM(X11->display, screen);
+    if (heightMM != 0) {
+        dpiY = (DisplayHeight(X11->display, screen) * 254 + heightMM * 5) / (heightMM * 10);
+    } else {
+        dpiY = 72;
+    }
+}
+
 // ### This should be static but it isn't because of the friend declaration
 // ### in qpaintdevice.h which then should have a static too but can't have
 // ### it because "storage class specifiers invalid in friend function
@@ -1912,19 +1929,7 @@
             screen->ref = 1; // ensures it doesn't get deleted
             screen->screen = s;
 
-            int widthMM = DisplayWidthMM(X11->display, s);
-            if (widthMM != 0) {
-                screen->dpiX = (DisplayWidth(X11->display, s) * 254 + widthMM * 5) / (widthMM * 10);
-            } else {
-                screen->dpiX = 72;
-            }
-
-            int heightMM = DisplayHeightMM(X11->display, s);
-            if (heightMM != 0) {
-                screen->dpiY = (DisplayHeight(X11->display, s) * 254 + heightMM * 5) / (heightMM * 10);
-            } else {
-                screen->dpiY = 72;
-            }
+            calculate_dpi_values(s, screen->dpiX, screen->dpiY);
 
             X11->argbVisuals[s] = 0;
             X11->argbColormaps[s] = 0;
@@ -3438,6 +3443,10 @@
         QSize oldSize(w->size());
         w->data->crect.setWidth(DisplayWidth(X11->display, scr));
         w->data->crect.setHeight(DisplayHeight(X11->display, scr));
+        
+        QX11InfoData *screen = X11->screens + scr;
+        calculate_dpi_values(scr, screen->dpiX, screen->dpiY);
+
         QResizeEvent e(w->size(), oldSize);
         QApplication::sendEvent(w, &e);
         if (w != desktop)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 259 bytes
Desc: OpenPGP digital signature
URL: <http://lists.qt-project.org/pipermail/development/attachments/20121023/f6633b5e/attachment.sig>


More information about the Development mailing list