Hi,

Qt 5 has several approaches to attempting to size/scale a UI when moving 
between screens which have
different APIs.  There is a summary here:

https://vicrucann.github.io/tutorials/osg-qt-high-dpi/

The approaches available currently either

1) scale everything after rendering (eg with SetProcessDPIAware())
2) scale coordinates to screen metrics before rendering 
(QApplication::setAttribute(Qt::AA_EnableHighDpiScaling))

The first approach gives a blurry result because of up/down scaling and is not 
satisfying.

The second approach scales all coordinates, making it impossible to specify 'a 
one/two pixel border' without that getting scaled too. Additionally, the 
AA_EnableHighDpiScaling will only apply integer scaling, so on a screen with 
150% scaling, the widget is scaled to 200%.

Adding a floating-point based API would not be a solution because it would 
result in painting artefacts.  This is an important point.  An approach like 
that won't satisfy designers.  The approach in

https://codereview.qt-project.org/#/c/157174/

resolves a scaling issue but does not address painting artefacts.

So, we need to find flexible and imaginative solutions.

I've had a discussion on IRC with Morten, who worked on QUIP-8.  That QUIP 
doesn't (yet?) go as far as approaches to addressing the problem, so I am 
writing here to see if there is wider interest in the topic.  One of the points 
he made is that some users are happy with the current state of Qt APIs and 
behavior, or would be happy with downsampling after rendering (blurry).

I don't know how widespread that acceptance would be, but I've worked on 
several teams where it would not be acceptable.

The underlying problem is that the Qt APIs do not provide a way to specify the 
units to use in layouts AND to combine values with those units.  We need to be 
able to specify coordinates which will be scaled to an appropriate number of 
pixels on the screen, but also to be able to specify coordinates in exact 
pixels (common for things like having a 'one/two pixel border' etc).  Then, Qt 
should compute the actual number of pixels to paint based on the current screen.

The approach we discussed (this is only the ideas-stage, remember!) with Morten 
is to change APIs which specify layouts to use a new unit-sensitive coordinate 
type instead of int.  This new QCoordinate type stores values in both points 
and pixels and has a toPixels method which computes the required pixel value 
for the screen.

https://gist.github.com/anonymous/d08e0e79b05237a765e23849bbe2a78d

QCoordinates can be created with C++11 user-defined literal niftyness:

  auto coord = 34_pt + 4_px;

This also implies a requirement to have QSize/QPoint etc equivalents based on 
QCoordinate.  We haven't put much thought into this code duplicatation etc, 
focusing only on whether we can solve the problems with this approach (or 
another approach?) at all.

A disadvantage of the QCoordinate approach is that the values are not 
comparable to each other without a screen.  So operator<() can't be implemented 
for example, but a separate purposeful API would be needed for things like that.

One of the issues raised so far is that this QCoordinate stores only pixels and 
points, but not other units which may be wanted, such as physical units like 
centimeters.  Morten noted that there are not many known use-cases for such 
units and that they mean little if a projector is in use.

This is of course a Qt 6 change, and now is approximately the time to discuss 
Qt 6 changes.  I don't know if anyone will be in Berlin who wants to discuss 
this at QtCS.  Shout if you want to discuss this there and I'll see if I can go 
over for it.

Thanks,

Stephen.

_______________________________________________
Development mailing list
[email protected]
http://lists.qt-project.org/mailman/listinfo/development

Reply via email to