Discussion:
High-dpi fixing for Qt 5.5
(too old to reply)
Sorvig Morten
2015-03-19 13:17:05 UTC
Permalink
Raw Message
Hi,

Those who have filed or are watching bugs related to high-dpi support in Qt may have noticed increased activity this week; we are running a small sprint to get things into shape for 5.5.

In case there issues that I’ve missed I would be interested in hearing about it. I can’t promise that everything will be fixed, but it will be at least put on the radar. (for simplicity assume that any bug without recent activity has gone unnoticed)

Thanks,
Morten
Daiwei Li
2015-03-20 23:16:55 UTC
Permalink
Raw Message
Hi Morten,

Do you know if auto-detection of scale factor on Windows is going to be
tackled again: https://codereview.qt-project.org/#/c/87716/?

There's no specific bug open for it besides being mentioned on the Windows
High DPI meta-bug: https://bugreports.qt.io/browse/QTBUG-38993, but perhaps
there should be.

Thanks,
Daiwei

On Thu, Mar 19, 2015 at 6:17 AM, Sorvig Morten <
Post by Sorvig Morten
Hi,
Those who have filed or are watching bugs related to high-dpi support in
Qt may have noticed increased activity this week; we are running a small
sprint to get things into shape for 5.5.
In case there issues that I’ve missed I would be interested in hearing
about it. I can’t promise that everything will be fixed, but it will be at
least put on the radar. (for simplicity assume that any bug without recent
activity has gone unnoticed)
Thanks,
Morten
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Sorvig Morten
2015-03-24 11:09:28 UTC
Permalink
Raw Message
Post by Daiwei Li
Hi Morten,
Do you know if auto-detection of scale factor on Windows is going to be tackled again: https://codereview.qt-project.org/#/c/87716/?
There's no specific bug open for it besides being mentioned on the Windows High DPI meta-bug: https://bugreports.qt.io/browse/QTBUG-38993, but perhaps there should be.
Hi Daiwei,

Short answer is that I don’t know. I’ll keep it in mind when I look at Windows support.

Morten
Till Oliver Knoll
2015-03-24 13:26:09 UTC
Permalink
Raw Message
Hi,
...
In case there issues that I’ve missed I would be interested in hearing about it. I can’t promise that everything will be fixed, but it will be at least put on the radar.
Hi Morten,

Not a bug by itself and hence a bit off-topic, but is there a way to detect "screen resolution changes" in some way? The use case is of course when an application window is moved from a Retina (HiDPI) screen to a non-Retina screen (or vice versa) (in a multi-monitor setup).

My knowledge of available "HiDPI" APIs is currently based on your (excellent) blog post, which does not seem to mention that use case:

http://blog.qt.io/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/

I could imagine that getting informed e.g. by the QDesktopWidget (or some other related "screen/resolution" class) whenever the application is "switched" (dragged) to another screen, and then querying the resolution of the new screen, could be a solution. However I currently do not see any corresponding signal in QDesktopWidget's API, nor anywhere else...

In the end I am not even sure whether I need to get informed about this event, since most drawing - and also the switch between Retina/non-Retina worlds - is handled for me already by Qt/underlying Core Graphics APIs. Even the Apple Developer docs mention that "Listening for NSWindowDidChangeBackingPropertiesNotification is something only a few apps [...] will need to do."

However my app probably /is/ one of those that "specialize in video or graphics work". I draw on a QGraphicsView(-scene) and have QGraphicsPixmapItems with a QPixmap behind them. I imagine that I have to be able to dynamically switch between the normal and the "@2x" version of those pixmaps, and have the QGraphicsView paint itself whenever such a "resolution change" is detected. Or so I imagine...

So I am basically looking for a "cross-platform" way to get notified in analogy to the Cocoa notification

NSWindowDidChangeBackingPropertiesNotification

See chapter "Handle Dynamic Changes in Window Resolution Only When You Must"

https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/CapturingScreenContents/CapturingScreenContents.html#//apple_ref/doc/uid/TP40012302-CH10-SW1


Or would I have access to this event (+ platform-specific code) in e.g. QWidget::nativeEvent (in the top-level QMainWindow)? The Apple docs talk about a "window delegate" (Cocoa code), to which I probably don't have (easy) access, at least not without modifying Qt's code itself - right? (I am not a Cocoa expert).


Is something like "detecting resolution changes" (otherwise) already possible, or is this on the "HiDPI Roadmap"?

Thanks, Oliver
Eddie Sutton
2015-03-24 13:39:46 UTC
Permalink
Raw Message
Post by Daiwei Li
http://blog.qt.io/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/ <http://blog.qt.io/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/>
Thanks for posting the excellent link. It may help me find a work-around for a Qt3D windows scaling issue that affects OS X and iOS as well.

Qt3D has issues with displaying the openGl rendering at 1/4 window size on the retina display. If Window is moved to external display it displays normally taking up the full window space..

-Ed
Post by Daiwei Li
Hi,
...
In case there issues that I’ve missed I would be interested in hearing about it. I can’t promise that everything will be fixed, but it will be at least put on the radar.
Hi Morten,
Not a bug by itself and hence a bit off-topic, but is there a way to detect "screen resolution changes" in some way? The use case is of course when an application window is moved from a Retina (HiDPI) screen to a non-Retina screen (or vice versa) (in a multi-monitor setup).
http://blog.qt.io/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/ <http://blog.qt.io/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/>
I could imagine that getting informed e.g. by the QDesktopWidget (or some other related "screen/resolution" class) whenever the application is "switched" (dragged) to another screen, and then querying the resolution of the new screen, could be a solution. However I currently do not see any corresponding signal in QDesktopWidget's API, nor anywhere else...
In the end I am not even sure whether I need to get informed about this event, since most drawing - and also the switch between Retina/non-Retina worlds - is handled for me already by Qt/underlying Core Graphics APIs. Even the Apple Developer docs mention that "Listening for NSWindowDidChangeBackingPropertiesNotification is something only a few apps [...] will need to do."
So I am basically looking for a "cross-platform" way to get notified in analogy to the Cocoa notification
NSWindowDidChangeBackingPropertiesNotification
See chapter "Handle Dynamic Changes in Window Resolution Only When You Must"
https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/CapturingScreenContents/CapturingScreenContents.html#//apple_ref/doc/uid/TP40012302-CH10-SW1 <https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/CapturingScreenContents/CapturingScreenContents.html#//apple_ref/doc/uid/TP40012302-CH10-SW1>
Or would I have access to this event (+ platform-specific code) in e.g. QWidget::nativeEvent (in the top-level QMainWindow)? The Apple docs talk about a "window delegate" (Cocoa code), to which I probably don't have (easy) access, at least not without modifying Qt's code itself - right? (I am not a Cocoa expert).
Is something like "detecting resolution changes" (otherwise) already possible, or is this on the "HiDPI Roadmap"?
Thanks, Oliver
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Till Oliver Knoll
2015-03-24 14:05:32 UTC
Permalink
Raw Message
Post by Eddie Sutton
Post by Till Oliver Knoll
http://blog.qt.io/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/
Thanks for posting the excellent link. It may help me find a work-around for a Qt3D windows scaling issue that affects OS X and iOS as well.
This, plus the Apple Developer docs may help as well, see "Enable OpenGL for High-Resolution Drawing"

https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/CapturingScreenContents/CapturingScreenContents.html#//apple_ref/doc/uid/TP40012302-CH10-SW1

"OpenGL is a pixel-based API. The NSOpenGLView class does not provide high-resolution surfaces by default. Because adding more pixels to renderbuffers has performance implications, you must explicitly opt in to support high-resolution screens.

You can opt in to high resolution by calling the method setWantsBestResolutionOpenGLSurface: when you initialize the view, and supplying YES as an argument:

[self setWantsBestResolutionOpenGLSurface:YES];

If you don't opt in, the system magnifies the rendered results."

/quote

Basically the docs say that OpenGL is a pixel-based drawing system, so any conversions between "points" and "pixels" needs to be done explicitly by the application itself, e.g. when resizing a window. And that you have to explicitly enable the "HiDPI" mode for the OpenGL context first.

How much that helps you to fix problems with the Qt3D module I can't say, but it is generally something you have to keep in mind when developing your own OpenGL based application (under OS X - on other OSes similar rules probably apply, too).

Cheers, Oliver
Agocs Laszlo
2015-03-24 14:46:38 UTC
Permalink
Raw Message
Because Qt 3D most likely misses a few multiplications by devicePixelRatio(). Probably easy to correct.

See http://www.qtdeveloperdays.com/sites/default/files/presentation_pdf/AgocsLaszlo_opengl_enablers_news.pdf#26

Best regards,
Laszlo

From: interest-bounces+laszlo.agocs=***@qt-project.org [mailto:interest-bounces+laszlo.agocs=***@qt-project.org] On Behalf Of Till Oliver Knoll
Sent: 24. mars 2015 15:06
To: Qt Project
Subject: Re: [Interest] High-dpi fixing for Qt 5.5
Post by Till Oliver Knoll
http://blog.qt.io/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/
Thanks for posting the excellent link. It may help me find a work-around for a Qt3D windows scaling issue that affects OS X and iOS as well.

This, plus the Apple Developer docs may help as well, see "Enable OpenGL for High-Resolution Drawing"

https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/CapturingScreenContents/CapturingScreenContents.html#//apple_ref/doc/uid/TP40012302-CH10-SW1

"OpenGL is a pixel-based API. The NSOpenGLView class does not provide high-resolution surfaces by default. Because adding more pixels to renderbuffers has performance implications, you must explicitly opt in to support high-resolution screens.

You can opt in to high resolution by calling the method setWantsBestResolutionOpenGLSurface: when you initialize the view, and supplying YES as an argument:

[self setWantsBestResolutionOpenGLSurface:YES];

If you don't opt in, the system magnifies the rendered results."

/quote

Basically the docs say that OpenGL is a pixel-based drawing system, so any conversions between "points" and "pixels" needs to be done explicitly by the application itself, e.g. when resizing a window. And that you have to explicitly enable the "HiDPI" mode for the OpenGL context first.

How much that helps you to fix problems with the Qt3D module I can't say, but it is generally something you have to keep in mind when developing your own OpenGL based application (under OS X - on other OSes similar rules probably apply, too).

Cheers, Oliver
Eddie Sutton
2015-03-24 15:14:40 UTC
Permalink
Raw Message
Thanks Laszlo for the nice presentation "News from the Graphics Stack: Improvements to the core OpenGL enablers in Qt 5.3 & 5.4”.

Are related code samples available? Do you know if there be a 2015 Fall Qt Developer Days event in U.S.?

Qt3D documentation seems to be in the form of examples only. I am using these for clues on how to integrate Qt3D into an existing QWidget app.

The OpenGL learning resources are very much appreciated!

-Ed
Post by Agocs Laszlo
Because Qt 3D most likely misses a few multiplications by devicePixelRatio(). Probably easy to correct.
See http://www.qtdeveloperdays.com/sites/default/files/presentation_pdf/AgocsLaszlo_opengl_enablers_news.pdf#26 <http://www.qtdeveloperdays.com/sites/default/files/presentation_pdf/AgocsLaszlo_opengl_enablers_news.pdf#26>
Best regards,
Laszlo
Sent: 24. mars 2015 15:06
To: Qt Project
Subject: Re: [Interest] High-dpi fixing for Qt 5.5
http://blog.qt.io/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/ <http://blog.qt.io/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/>
Thanks for posting the excellent link. It may help me find a work-around for a Qt3D windows scaling issue that affects OS X and iOS as well.
This, plus the Apple Developer docs may help as well, see "Enable OpenGL for High-Resolution Drawing"
https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/CapturingScreenContents/CapturingScreenContents.html#//apple_ref/doc/uid/TP40012302-CH10-SW1 <https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/CapturingScreenContents/CapturingScreenContents.html#//apple_ref/doc/uid/TP40012302-CH10-SW1>
"OpenGL is a pixel-based API. The NSOpenGLView class does not provide high-resolution surfaces by default. Because adding more pixels to renderbuffers has performance implications, you must explicitly opt in to support high-resolution screens.
[self setWantsBestResolutionOpenGLSurface:YES];
If you don't opt in, the system magnifies the rendered results."
/quote
Basically the docs say that OpenGL is a pixel-based drawing system, so any conversions between "points" and "pixels" needs to be done explicitly by the application itself, e.g. when resizing a window. And that you have to explicitly enable the "HiDPI" mode for the OpenGL context first.
How much that helps you to fix problems with the Qt3D module I can't say, but it is generally something you have to keep in mind when developing your own OpenGL based application (under OS X - on other OSes similar rules probably apply, too).
Cheers, Oliver
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Till Oliver Knoll
2015-03-24 16:01:26 UTC
Permalink
Raw Message
Post by Agocs Laszlo
Because Qt 3D most likely misses a few multiplications by devicePixelRatio(). Probably easy to correct.
See http://www.qtdeveloperdays.com/sites/default/files/presentation_pdf/AgocsLaszlo_opengl_enablers_news.pdf#26
Hi Laszlo,

Thanks for the slides! They seem to contain the (partial) answer I was looking for: how to get notified when the screen (and hence possibly the resolution) changes.

For QWindow based applications the answer seems to be

http://doc.qt.io/qt-5/qwindow.html#screenChanged

For QWidget based applications however your slides suggest to "watch out for [...] ScreenChangeInternal event for QWidget". I assume this is "for Qt internal use only".

In fact I found a change (by you ;)) from about 6 months ago which seems to introduce that "ScreenChangeInternal" event:

https://qt.gitorious.org/qt/qtbase/commit/49194275e02a9d6373767d6485bd8ebeeb0abba5

"Unlike ordinary widgets, the ones that have OpenGL framebuffers must know about screen changes because the device pixel ratio may be different on the new screen. Add an internal event, ScreenChangeInternal, as the counterpart to WindowChangeInternal."


Is or will this event be exposed to the public QWidget API?


Again, I am not sure whether I need to care (on an application level) at all about this use case (switch between monitors/screens with different resolution), but I strongly assume so: I create QPixmaps as needed (using a QPainter) and store them ("cache") in the corresponding QGrapicsPixmapItem. So when the resolution changes I would re-create those QPixmaps with the desired resolution.

Then again, if I was to draw the QPixmap myself, I would use a QIcon (with the app attribute "Qt::AA_UseHighDpiPixmaps" enabled) to choose between the desired QPixmaps, as in:

QRect destinationRect = ...
QIcon icon = ...
painter.drawPixmap(destinationRect, icon.pixmap(destinationRect.size()));

[http://blog.qt.io/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/]

But since the QGraphicsPixmapItem is doing the drawing for me, I probably really need to get informed about resolution changes, and replace the pixmaps in the QGraphicsViewItem myself as needed (unless I am overseeing some other, simpler solution here). Or maybe if I would overwrite the QGraphicsPixmapItem::paint() method and use something like the above code... but that would almost defy the reason why I would use a QGraphicsPixmapItem in the first place... (I could derive from QGraphicsItem then directly instead).


Any thoughts or ideas?


Thanks, Oliver
Sorvig Morten
2015-03-25 13:01:09 UTC
Permalink
Raw Message
Post by Till Oliver Knoll
But since the QGraphicsPixmapItem is doing the drawing for me, I probably really need to get informed about resolution changes, and replace the pixmaps in the QGraphicsViewItem myself as needed (unless I am overseeing some other, simpler solution here). Or maybe if I would overwrite the QGraphicsPixmapItem::paint() method and use something like the above code... but that would almost defy the reason why I would use a QGraphicsPixmapItem in the first place... (I could derive from QGraphicsItem then directly instead).
This may be an accurate observation on the usefulness of QGraphicsPixmapItem when targeting multiple pixel densities.

To me QGraphicsPixmapItem::paint() looks like the right place to generate a new pixmap on demand - you should be able to check if painter->device()->devicePixelRatio() has changed since the previous draw call.

Morten
John Weeks
2015-03-25 16:21:22 UTC
Permalink
Raw Message
It looks to me like at present (Qt 5.4) the various devicePixelRatio() functions on Windows only return 1.0 or 2.0. But Windows systems can be at fractional ratios- will 5.5 address that?

It also appears that drawing a QPixmap or QImage with a fractional ratio actually works, but we can't discover that situation easily.

-John Weeks
WaveMetrics, Inc.
Sorvig Morten
2015-03-26 15:03:33 UTC
Permalink
Raw Message
Post by John Weeks
It looks to me like at present (Qt 5.4) the various devicePixelRatio() functions on Windows only return 1.0 or 2.0. But Windows systems can be at fractional ratios- will 5.5 address that?
It also appears that drawing a QPixmap or QImage with a fractional ratio actually works, but we can't discover that situation easily.
I don’t think we can officially support fractional ratios, in the sense that we can’t guarantee glitch-free graphics. Qt currently has one central int-based API (QPaintDevice:: devicePixelRatio()) which limits fractional ratio support.

That said, my personal opinion is that we should add QPaintDevice::devicePixelRatioF() and take a "best effort” approach at making it work. No guarantees that it actually will in all cases, though.

Morten
Sorvig Morten
2015-03-26 16:29:23 UTC
Permalink
Raw Message
Post by John Weeks
It looks to me like at present (Qt 5.4) the various devicePixelRatio() functions on Windows only return 1.0 or 2.0. But Windows systems can be at fractional ratios- will 5.5 address that?
Oops - I don’t think anything will change for 5.5, we’re talking 5.6 earliest for any Windows changes.

Morten
Till Oliver Knoll
2015-03-26 12:15:14 UTC
Permalink
Raw Message
Post by Sorvig Morten
But since the QGraphicsPixmapItem is doing the drawing for me, ...
...
To me QGraphicsPixmapItem::paint() looks like the right place to generate a new pixmap on demand - you should be able to check if painter->device()->devicePixelRatio() has changed since the previous draw call.
Exactly. Plus the (API) possibility for an application to provide the pixmaps in the required resolutions, e.g. in form of a "PixmapProvider".

QIcon for instance already has the possibility to provide a "high DPI" (aka "retina") version of a pixmap (resolution measured in "pixels"), given the desired size (measured in "points" - according to Apple lingo).

"QIcon::pixmap() has been modified to return a larger pixmap on high-dpi systems."

[http://blog.qt.io/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/]

So instead of just

QGraphicsPixmapItem::setPixmap()

(QPixmap currently represents/contains exactly one pixmap in a given resolution only)

we could (in addition) have

QGraphicsPixmapItem::setPixmapProvider()

where the new QPixmapProvider class would work in analogy to QIcon, that is, return a QPixmap of the proper resolution ("pixels") for a given logical size ("points").

Or add the possibility (and logic) to provide a QIcon to QGraphicsPixmapItem.

Or - somehow - extend QPixmap such that multiple pixmaps (with different resolutions) could be set/stored within - with the same logic like QIcon.

The last solution would probably be the best solution, from an API point of view: existing API such as QGraphicsPixmapItem::setPixmap could remain the same. Internally however they would simply make use of the new "HiDPI capabilities" of QPixmap.

And it just "sounds funny" to read

QGraphicsPixmapItem::setIcon

(setting a QPixmapProvider would be okay, but still confusing, since it would make the existing ::setPixmap somewhat redundant - except maybe if QPixmapProvider could inherit from QPixmap, but that sounds like a bad idea as well: a "Provider" is a "Provider", and not the "Product" itself...)


In any case, if

- QGraphicsPixmapItem was able to handle (changes in) HiDPI and
- there was a way to provide the pixmaps in the required resolutions ("@2x" etc.)

then there would be no need for an application to get informed about "resolution changes" - for that particular use case.


However it is my current understanding that QWindow based windows do get informed about screen changes, namely with

QWindow::screenChanged()

(in the corresponding slot the devicePixelRatio can then be queried and resources rebuilt on an "as-needed" basis).

For QWidget based windows there doesn't seem to be a corresponding signal (yet - as of Qt 5.4). Even though Laszlo seems to have added at least an internal signal (ScreenChangeInternal) 6 month ago (as mentioned previously).

I would argue that there would still be cases where it would be useful for a (top-level) QWidget to get informed as soon as it has been dragged to another screen ( >= 50% of its size is on the new screen).


Cheers,
Oliver
Elvis Stansvik
2018-03-02 14:37:04 UTC
Permalink
Raw Message
Post by Agocs Laszlo
Because Qt 3D most likely misses a few multiplications by
devicePixelRatio(). Probably easy to correct.
See
http://www.qtdeveloperdays.com/sites/default/files/presentation_pdf/AgocsLaszlo_opengl_enablers_news.pdf#26
Hi Laszlo,
Thanks for the slides! They seem to contain the (partial) answer I was
looking for: how to get notified when the screen (and hence possibly the
resolution) changes.
For QWindow based applications the answer seems to be
http://doc.qt.io/qt-5/qwindow.html#screenChanged
For QWidget based applications however your slides suggest to "watch out for
[...] ScreenChangeInternal event for QWidget". I assume this is "for Qt
internal use only".
In fact I found a change (by you ;)) from about 6 months ago which seems to
https://qt.gitorious.org/qt/qtbase/commit/49194275e02a9d6373767d6485bd8ebeeb0abba5
"Unlike ordinary widgets, the ones that have OpenGL framebuffers must know
about screen changes because the device pixel ratio may be different on the
new screen. Add an internal event, ScreenChangeInternal, as the counterpart
to WindowChangeInternal."
Is or will this event be exposed to the public QWidget API?
Sorry for necroposting, but I think this question went unanswered.

Anyone (Laszlo?) know if this API could be made public?

How can I (as application developer) get notified of screen changes of
non-QWindow-backed widgets?

Cheers,
Elvis
Post by Agocs Laszlo
Again, I am not sure whether I need to care (on an application level) at all
about this use case (switch between monitors/screens with different
resolution), but I strongly assume so: I create QPixmaps as needed (using a
QPainter) and store them ("cache") in the corresponding QGrapicsPixmapItem.
So when the resolution changes I would re-create those QPixmaps with the
desired resolution.
Then again, if I was to draw the QPixmap myself, I would use a QIcon (with
the app attribute "Qt::AA_UseHighDpiPixmaps" enabled) to choose between the
QRect destinationRect = ...
QIcon icon = ...
painter.drawPixmap(destinationRect, icon.pixmap(destinationRect.size()));
[http://blog.qt.io/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/]
But since the QGraphicsPixmapItem is doing the drawing for me, I probably
really need to get informed about resolution changes, and replace the
pixmaps in the QGraphicsViewItem myself as needed (unless I am overseeing
some other, simpler solution here). Or maybe if I would overwrite the
QGraphicsPixmapItem::paint() method and use something like the above code...
but that would almost defy the reason why I would use a QGraphicsPixmapItem
in the first place... (I could derive from QGraphicsItem then directly
instead).
Any thoughts or ideas?
Thanks, Oliver
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Nikos Chantziaras
2018-03-02 14:54:41 UTC
Permalink
Raw Message
Post by Elvis Stansvik
[...]
How can I (as application developer) get notified of screen changes of
non-QWindow-backed widgets?
There seems to be two ways to do this. One is using one of the QScreen
signals:

http://doc.qt.io/qt-5/qscreen.html

However, another one seems to be using QDesktopWidget signals:

http://doc.qt.io/qt-5/qdesktopwidget.html

QApplication has static functions to get the current QDesktopWidget, the
current QScreen primary screen and all screens. It also has signals to
get notified of screen changes.
Elvis Stansvik
2018-03-02 15:18:29 UTC
Permalink
Raw Message
Post by Nikos Chantziaras
Post by Elvis Stansvik
[...]
How can I (as application developer) get notified of screen changes of
non-QWindow-backed widgets?
There seems to be two ways to do this. One is using one of the QScreen
http://doc.qt.io/qt-5/qscreen.html
Hm, I should have made my question more clear.

The typical way I've seen is to connect to the screenChanged signal of
the closest ancestral QWindow (window()->windowHandle()).

But, I've found that it's not reliable for certain widgets/certain
platforms to do e.g:

QTimer::singleShot(0, [this]() {
connect(window()->windowHandle(), &QWindow::screenChanged,
this, &MyWidget::handleScreenChanged);
});

in my constructor, because depending on how the widget is constructed,
the parentage up to a top-level window may not have been established
yet, even if I do it in a single-shot timer like this.

So, what I should probably be doing is something like:

bool MyWidget::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::ScreenChangeInternal
|| event->type() == QEvent::WindowChangeInternal) {
if (window() && window()->windowHandle()) {
// Window or screen changed, and there is an ancestral
// QWindow I can use, for example to get the QScreen
// to look at it's DPI et.c.
}
}

return ParentClass::eventFilter(object, event);
}

But then I'm relying on internal events (QEvent::ScreenChangeInternal
and QEvent::WindowChangeInternal).
Post by Nikos Chantziaras
http://doc.qt.io/qt-5/qdesktopwidget.html
QApplication has static functions to get the current QDesktopWidget, the
current QScreen primary screen and all screens. It also has signals to get
notified of screen changes.
AFAIK that only gives me the primary screen, and notification about
when the primary screen changes, not the screen my widget is on or
notifications when that changes.

Elvis
Post by Nikos Chantziaras
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Elvis Stansvik
2018-03-02 15:21:23 UTC
Permalink
Raw Message
Post by Elvis Stansvik
Post by Nikos Chantziaras
Post by Elvis Stansvik
[...]
How can I (as application developer) get notified of screen changes of
non-QWindow-backed widgets?
There seems to be two ways to do this. One is using one of the QScreen
http://doc.qt.io/qt-5/qscreen.html
Hm, I should have made my question more clear.
The typical way I've seen is to connect to the screenChanged signal of
the closest ancestral QWindow (window()->windowHandle()).
But, I've found that it's not reliable for certain widgets/certain
QTimer::singleShot(0, [this]() {
connect(window()->windowHandle(), &QWindow::screenChanged,
this, &MyWidget::handleScreenChanged);
});
in my constructor, because depending on how the widget is constructed,
the parentage up to a top-level window may not have been established
yet, even if I do it in a single-shot timer like this.
I should clarify this: What I mean is that I've seen situations when
window()->windowHandle() is 0 here, even if the widget is constructed
with a full parentage up to a top-level widget.

Elvis
Post by Elvis Stansvik
bool MyWidget::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::ScreenChangeInternal
|| event->type() == QEvent::WindowChangeInternal) {
if (window() && window()->windowHandle()) {
// Window or screen changed, and there is an ancestral
// QWindow I can use, for example to get the QScreen
// to look at it's DPI et.c.
}
}
return ParentClass::eventFilter(object, event);
}
But then I'm relying on internal events (QEvent::ScreenChangeInternal
and QEvent::WindowChangeInternal).
Post by Nikos Chantziaras
http://doc.qt.io/qt-5/qdesktopwidget.html
QApplication has static functions to get the current QDesktopWidget, the
current QScreen primary screen and all screens. It also has signals to get
notified of screen changes.
AFAIK that only gives me the primary screen, and notification about
when the primary screen changes, not the screen my widget is on or
notifications when that changes.
Elvis
Post by Nikos Chantziaras
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Martins, Sérgio
2018-03-02 15:26:03 UTC
Permalink
Raw Message
Post by Elvis Stansvik
Post by Elvis Stansvik
Post by Nikos Chantziaras
Post by Elvis Stansvik
[...]
How can I (as application developer) get notified of screen changes of
non-QWindow-backed widgets?
There seems to be two ways to do this. One is using one of the QScreen
http://doc.qt.io/qt-5/qscreen.html
Hm, I should have made my question more clear.
The typical way I've seen is to connect to the screenChanged signal of
the closest ancestral QWindow (window()->windowHandle()).
But, I've found that it's not reliable for certain widgets/certain
QTimer::singleShot(0, [this]() {
connect(window()->windowHandle(), &QWindow::screenChanged,
this, &MyWidget::handleScreenChanged);
});
in my constructor, because depending on how the widget is constructed,
the parentage up to a top-level window may not have been established
yet, even if I do it in a single-shot timer like this.
I should clarify this: What I mean is that I've seen situations when
window()->windowHandle() is 0 here, even if the widget is constructed
with a full parentage up to a top-level widget.
Hi,

Call QWidget::create() on your top-level constructor, and it will ensure
it it has a QWindow


Regards,
--
Sérgio Martins | ***@kdab.com | Senior Software Engineer
Klarälvdalens Datakonsult AB, a KDAB Group company
Tel: Sweden (HQ) +46-563-540090, USA +1-866-777-KDAB(5322)
KDAB - The Qt, C++ and OpenGL Experts
Elvis Stansvik
2018-03-02 16:16:43 UTC
Permalink
Raw Message
Post by Elvis Stansvik
Post by Elvis Stansvik
Post by Nikos Chantziaras
Post by Elvis Stansvik
[...]
How can I (as application developer) get notified of screen changes of
non-QWindow-backed widgets?
There seems to be two ways to do this. One is using one of the QScreen
http://doc.qt.io/qt-5/qscreen.html
Hm, I should have made my question more clear.
The typical way I've seen is to connect to the screenChanged signal of
the closest ancestral QWindow (window()->windowHandle()).
But, I've found that it's not reliable for certain widgets/certain
QTimer::singleShot(0, [this]() {
connect(window()->windowHandle(), &QWindow::screenChanged,
this, &MyWidget::handleScreenChanged);
});
in my constructor, because depending on how the widget is constructed,
the parentage up to a top-level window may not have been established
yet, even if I do it in a single-shot timer like this.
I should clarify this: What I mean is that I've seen situations when
window()->windowHandle() is 0 here, even if the widget is constructed
with a full parentage up to a top-level widget.
Hi,
Call QWidget::create() on your top-level constructor, and it will ensure it
it has a QWindow
Thanks, that's one way of doing it, but reading further, it seems
QWidget delays doing this for a reason. E.g. see the docs for
Qt::AA_ImmediateWidgetCreation, which I could also use to tell Qt to
call create(..) immediately during construction. That attribute is due
to be removed in Qt 6 though.

I don't think I like the idea of jumping the gun on QWidget here and
calling create(..) myself.

Surely there must be some way to reliably know when a widget is moved
to another screen (or anoter top-level window), short of hooking up to
internal events?

Elvis
Regards,
--
Klarälvdalens Datakonsult AB, a KDAB Group company
Tel: Sweden (HQ) +46-563-540090, USA +1-866-777-KDAB(5322)
KDAB - The Qt, C++ and OpenGL Experts
John Weeks
2018-03-02 17:05:04 UTC
Permalink
Raw Message
Do it in the showEvent()?
Post by Elvis Stansvik
Post by Elvis Stansvik
Post by Elvis Stansvik
Post by Nikos Chantziaras
Post by Elvis Stansvik
[...]
How can I (as application developer) get notified of screen changes of
non-QWindow-backed widgets?
There seems to be two ways to do this. One is using one of the QScreen
http://doc.qt.io/qt-5/qscreen.html
Hm, I should have made my question more clear.
The typical way I've seen is to connect to the screenChanged signal of
the closest ancestral QWindow (window()->windowHandle()).
But, I've found that it's not reliable for certain widgets/certain
QTimer::singleShot(0, [this]() {
connect(window()->windowHandle(), &QWindow::screenChanged,
this, &MyWidget::handleScreenChanged);
});
in my constructor, because depending on how the widget is constructed,
the parentage up to a top-level window may not have been established
yet, even if I do it in a single-shot timer like this.
I should clarify this: What I mean is that I've seen situations when
window()->windowHandle() is 0 here, even if the widget is constructed
with a full parentage up to a top-level widget.
Hi,
Call QWidget::create() on your top-level constructor, and it will ensure it
it has a QWindow
Thanks, that's one way of doing it, but reading further, it seems
QWidget delays doing this for a reason. E.g. see the docs for
Qt::AA_ImmediateWidgetCreation, which I could also use to tell Qt to
call create(..) immediately during construction. That attribute is due
to be removed in Qt 6 though.
I don't think I like the idea of jumping the gun on QWidget here and
calling create(..) myself.
Surely there must be some way to reliably know when a widget is moved
to another screen (or anoter top-level window), short of hooking up to
internal events?
Elvis
Regards,
--
Klarälvdalens Datakonsult AB, a KDAB Group company
Tel: Sweden (HQ) +46-563-540090, USA +1-866-777-KDAB(5322)
KDAB - The Qt, C++ and OpenGL Experts
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
-Johnm Weeks
Elvis Stansvik
2018-03-02 17:28:30 UTC
Permalink
Raw Message
Den 2 mars 2018 6:05 em skrev "John Weeks" <***@wavemetrics.com>:

Do it in the showEvent()?


Hum, that's a good idea, thanks. I guess the parentage up to a top level
widget will always have been established by then, and that top level window
will always have a windowHandle()?

I guess in my event handler I should also check if the window() has changed
since the last time, and if it has, disconnect and reconnect to the
windowHandle() of the new window().

Curious to know if anyone else is using this approach (showEvent) for
reliable screen change detection.

In any case, how come QWidget itself doesn't have a screenChanged? This
seems to be more complicated than it has to be.

Elvis
Post by Elvis Stansvik
Post by Elvis Stansvik
Post by Elvis Stansvik
Post by Nikos Chantziaras
Post by Elvis Stansvik
[...]
How can I (as application developer) get notified of screen changes of
non-QWindow-backed widgets?
There seems to be two ways to do this. One is using one of the QScreen
http://doc.qt.io/qt-5/qscreen.html
Hm, I should have made my question more clear.
The typical way I've seen is to connect to the screenChanged signal of
the closest ancestral QWindow (window()->windowHandle()).
But, I've found that it's not reliable for certain widgets/certain
QTimer::singleShot(0, [this]() {
connect(window()->windowHandle(), &QWindow::screenChanged,
this, &MyWidget::handleScreenChanged);
});
in my constructor, because depending on how the widget is constructed,
the parentage up to a top-level window may not have been established
yet, even if I do it in a single-shot timer like this.
I should clarify this: What I mean is that I've seen situations when
window()->windowHandle() is 0 here, even if the widget is constructed
with a full parentage up to a top-level widget.
Hi,
Call QWidget::create() on your top-level constructor, and it will ensure it
it has a QWindow
Thanks, that's one way of doing it, but reading further, it seems
QWidget delays doing this for a reason. E.g. see the docs for
Qt::AA_ImmediateWidgetCreation, which I could also use to tell Qt to
call create(..) immediately during construction. That attribute is due
to be removed in Qt 6 though.
I don't think I like the idea of jumping the gun on QWidget here and
calling create(..) myself.
Surely there must be some way to reliably know when a widget is moved
to another screen (or anoter top-level window), short of hooking up to
internal events?
Elvis
Regards,
--
KlarÀlvdalens Datakonsult AB, a KDAB Group company
Tel: Sweden (HQ) +46-563-540090, USA +1-866-777-KDAB(5322)
KDAB - The Qt, C++ and OpenGL Experts
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
-Johnm Weeks
Elvis Stansvik
2018-03-02 17:30:49 UTC
Permalink
Raw Message
Den 2 mars 2018 6:28 em skrev "Elvis Stansvik" <***@gmail.com>:

Den 2 mars 2018 6:05 em skrev "John Weeks" <***@wavemetrics.com>:

Do it in the showEvent()?


Hum, that's a good idea, thanks. I guess the parentage up to a top level
widget will always have been established by then, and that top level window
will always have a windowHandle()?

I guess in my event handler I should also check if the window() has changed
since the last time, and if it has, disconnect and reconnect to the
windowHandle() of the new window().


Also interested in if the windowHandle() can change underneath the
window(). If it can I guess I need to detect that as well.

Elvis


Curious to know if anyone else is using this approach (showEvent) for
reliable screen change detection.

In any case, how come QWidget itself doesn't have a screenChanged? This
seems to be more complicated than it has to be.

Elvis
Post by Elvis Stansvik
Post by Elvis Stansvik
Post by Elvis Stansvik
Post by Nikos Chantziaras
Post by Elvis Stansvik
[...]
How can I (as application developer) get notified of screen changes of
non-QWindow-backed widgets?
There seems to be two ways to do this. One is using one of the QScreen
http://doc.qt.io/qt-5/qscreen.html
Hm, I should have made my question more clear.
The typical way I've seen is to connect to the screenChanged signal of
the closest ancestral QWindow (window()->windowHandle()).
But, I've found that it's not reliable for certain widgets/certain
QTimer::singleShot(0, [this]() {
connect(window()->windowHandle(), &QWindow::screenChanged,
this, &MyWidget::handleScreenChanged);
});
in my constructor, because depending on how the widget is constructed,
the parentage up to a top-level window may not have been established
yet, even if I do it in a single-shot timer like this.
I should clarify this: What I mean is that I've seen situations when
window()->windowHandle() is 0 here, even if the widget is constructed
with a full parentage up to a top-level widget.
Hi,
Call QWidget::create() on your top-level constructor, and it will ensure it
it has a QWindow
Thanks, that's one way of doing it, but reading further, it seems
QWidget delays doing this for a reason. E.g. see the docs for
Qt::AA_ImmediateWidgetCreation, which I could also use to tell Qt to
call create(..) immediately during construction. That attribute is due
to be removed in Qt 6 though.
I don't think I like the idea of jumping the gun on QWidget here and
calling create(..) myself.
Surely there must be some way to reliably know when a widget is moved
to another screen (or anoter top-level window), short of hooking up to
internal events?
Elvis
Regards,
--
KlarÀlvdalens Datakonsult AB, a KDAB Group company
Tel: Sweden (HQ) +46-563-540090, USA +1-866-777-KDAB(5322)
KDAB - The Qt, C++ and OpenGL Experts
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
-Johnm Weeks

Sorvig Morten
2015-03-25 12:45:52 UTC
Permalink
Raw Message
Post by Till Oliver Knoll
[self setWantsBestResolutionOpenGLSurface:YES];
If you don't opt in, the system magnifies the rendered results."
Note that Qt opts in for you and calls the above API. Disabling it will most likely work around the “rendering to one quarter of the screen” issue. If you grep for “setWantsBestResolutionOpenGLSurface” in the Qt sources then your Qt version may have an environment variable to toggle it.

Morten
Sorvig Morten
2015-03-25 12:40:22 UTC
Permalink
Raw Message
Post by Daiwei Li
Post by Sorvig Morten
Hi,
...
In case there issues that I’ve missed I would be interested in hearing about it. I can’t promise that everything will be fixed, but it will be at least put on the radar.
Hi Morten,
Not a bug by itself and hence a bit off-topic, but is there a way to detect "screen resolution changes" in some way? The use case is of course when an application window is moved from a Retina (HiDPI) screen to a non-Retina screen (or vice versa) (in a multi-monitor setup).
http://blog.qt.io/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/
I could imagine that getting informed e.g. by the QDesktopWidget (or some other related "screen/resolution" class) whenever the application is "switched" (dragged) to another screen, and then querying the resolution of the new screen, could be a solution. However I currently do not see any corresponding signal in QDesktopWidget's API, nor anywhere else…
[I see there has been other replies which covers this, so there’s probably some duplicate information here.]

The current approach is that application windows will be repainted at screen change time; The window's devicePixelRatio() accessor will then return the correct value for the new screen and the app will draw at the correct pixel density.
Post by Daiwei Li
In the end I am not even sure whether I need to get informed about this event, since most drawing - and also the switch between Retina/non-Retina worlds - is handled for me already by Qt/underlying Core Graphics APIs. Even the Apple Developer docs mention that "Listening for NSWindowDidChangeBackingPropertiesNotification is something only a few apps [...] will need to do."
Pixmaps caches are indeed a special case: you need to factor in the target devicePixelRatio when creating the caches:

qreal dpr = window->devicePixelRatio(); // or painter->device()->devicePixelRatio()
QPixmap cache(size * dpr);
cache.setDevicePixelRatio(dpr); // iff you want scale any QPainters opened on the pixmap.

(this is a recurring pattern and may deserve its own API at some point)
Post by Daiwei Li
So I am basically looking for a "cross-platform" way to get notified in analogy to the Cocoa notification
NSWindowDidChangeBackingPropertiesNotification
See chapter "Handle Dynamic Changes in Window Resolution Only When You Must"
https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/CapturingScreenContents/CapturingScreenContents.html#//apple_ref/doc/uid/TP40012302-CH10-SW1
Looks like the desktop platforms (XCB, OS X and Windows) emit QWindow::screenChanged now. I think the best place to handle the pixel density change is still the repaint, that way you create new graphics at the correct time.

Morten
Stanislav Baiduzhyi
2015-03-27 06:48:52 UTC
Permalink
Raw Message
Post by Sorvig Morten
Hi,
Those who have filed or are watching bugs related to high-dpi support in Qt
may have noticed increased activity this week; we are running a small
sprint to get things into shape for 5.5.
In case there issues that I’ve missed I would be interested in hearing about
it. I can’t promise that everything will be fixed, but it will be at least
put on the radar. (for simplicity assume that any bug without recent
activity has gone unnoticed)
Hi Morten,

This one is the most annoying for me:
https://bugreports.qt.io/browse/QTBUG-43753
--
Regards,
Stas
Loading...