[Development] What to expect from QIcon/the icon engine on screen changes

Elvis Stansvik elvstone at gmail.com
Sat Apr 6 10:42:16 CEST 2019


Den lör 6 apr. 2019 kl 10:40 skrev Elvis Stansvik <elvstone at gmail.com>:
>
> Hi all,
>
> I'm looking for someone who knows the inner workings of QIcon and the
> icon engines.
>
> In our application, we almost exclusively use SVG icons, and we use a
> single SVG file for each icon (no @2x versions) that we try to design
> to work reasonably well at all sizes, since we do not have the
> resources to make custom variations for each target size.
>
> We put these SVG icons into an XDG icon theme, that we ship inside the
> application resources (.qrc) in the expected XDG layout and with an
> icon theme index file. We can then use
> QIcon::fromTheme("our-app-some-icon") to reference an icon (either
> through the .ui file or in code).
>
> The problem we've run into is that when the application is launched in
> a mixed-DPI setup, for example a retina Mac laptop with an external
> lower-DPI monitor, the icons appear too large and get cropped. In

To clarify: This happens when the application is on the external
screen. On the retina screen it looks correct

> effect, it seems to always use the DPI of the primary screen (the
> built-in retina screen) when calculating the size of the pixmaps it
> generates for the icons.
>
> To work around this, we've had to put in special code in all of our
> widgets that use icons. The code reacts to screen change events (or
> changes to the underlying QWindow in some cases), and in that code, go
> through each and every one of our icons and do this monkey dance:
>
>         auto pixmap = someButton->icon().pixmap(someButton->iconSize());
>         pixmap.setDevicePixelRatio(window()->windowHandle()->screen()->devicePixelRatio());
>         someButton->setIcon(QIcon(pixmap));
>
> So essentially taking the pixmap out of the icon, set its DPR to that
> of the current screen, and then set that pixmap back on the icon.
>
> This "works", the icons now look correct on both the retina screen and
> the external one, and adjust themselves when the application is moved
> back and forth, or when the external monitor is activated/deactivated.
>
> But surely this kludge should not be necessary? We've provided Qt with
> an SVG, so it should be able to work out on its own that the screen
> has changed, and regenerate an appropriate pixmap in response to that?
>
> Some more details:
>
> - We are running with the Qt::AA_UseHighDpiPixmaps application
> attribute turned on. I'm not sure this is relevant for this issue
> though, because AFAIK that attribute is only about picking 2x versions
> of icons (we have a couple of those, where we have PNGs with 2x
> versions).
>
> - We are not running with Qt's built-in scaling activated, but relying
> on the Mac platform scaling (I'm not even sure Qt's built-in scaling
> is applicable on Mac). The application runs with
> NSHighResolutionCapable set to True in its Info.plist (which I also
> think is the default nowadays).
>
> - I have not investigated yet whether this problem also occurs on a
> mixed-DPI Linux setup, with Qt's high-dpi scaling activated. Nor have
> I checked if it happens on Windows using it's artificial "screen
> scaling" (we do not use Qt's built-in scaling on Windows either,
> trying to follow the advise in the docs to avoid that for new
> applications). So for now this is only about Mac retina + external
> monitor.
>
> Any advise on this would be highly appreciated, because the code
> required to re-trigger pixmap generation on screen changes is a real
> kludge all over our code base, and often it happens that we add
> buttons et.c. with icons, but forget to update this machinery.
>
> I'm not at the office at the moment, but can provide a little test
> program that mimics what we're doing on Monday.
>
> Thanks in advance,
> Elvis



More information about the Development mailing list