Details
-
Bug
-
Resolution: Done
-
P1: Critical
-
5.9.0
Description
I'm using QtWinMigrate within an MFC application. Since QT 5.9, all floating widgets (menu, popup, ...) have bad location: they are all stuck on top left of the screen whatever the position of the window is.
It is reproducible with the samples from QtWinMigrate.
I have identified that it's coming from this commit: https://github.com/qt/qtbase/commit/2ac50ac15621e303adbf6c35cbc2456f7ae5dd2f
The function QWindowsWindow::isEmbedded() is no longer recursive. Actually, QWinWidget from QtWinMigrate has the embedded flag. So prior to QT 5.9, for all its child widgets isEmbedded() returned true, which is not the case anymore. And this affect the mapToGlobal function.
Let's take a look at QWindow::mapToGlobal() function:
if (d->platformWindow && (d->platformWindow->isForeignWindow() || d->platformWindow->isEmbedded())) { return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapToGlobal(QHighDpi::toNativeLocalPosition(pos, this)), this); } return pos + d->globalPosition();
Prior to QT 5.9, for all children widgets, it goes inside the if statement. Now it's only working for the top widget QWinWidget. For the children it goes inside globalPosition().
The problem is that QWindowPrivate::globalPosition() never test the embedded flag so the returned point is expressed in coordinates relative to the top widget and not absolute to the screen (this transformation is done inside QWindowsGeometryHint::mapToGlobal -> ClientToScreen).
The solution I see is to modify the condition inside QWindowPrivate::globalPosition() to take in account the embedded flag:
if (pw && (pw->isForeignWindow() || pw->isEmbedded())) { // Use mapToGlobal() for foreign windows and embedded widgets like QWinWidget offset += p->mapToGlobal(QPoint(0, 0)); break; }
This fix worked for me and it makes sense since it's the same condition as in QWindow::mapToGlobal.