Windows QPA: Fix resize loops when moving fixed size windows between screens
Postpone the screen change until the DPI changed event in case a move between screens with different DPI is detected. Task-number: QTBUG-65580 Change-Id: I356f144b243d7d1ce7feabf0434c3f534b903965 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io> Reviewed-by: Andre de la Rocha <andre.rocha@qt.io>
parent
d2fd9b1b98
commit
7eed1e40d4
|
|
@ -1322,17 +1322,24 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
|
|||
#endif
|
||||
} break;
|
||||
case QtWindows::DpiChangedEvent: {
|
||||
if (!resizeOnDpiChanged(platformWindow->window()))
|
||||
return false;
|
||||
platformWindow->setFlag(QWindowsWindow::WithinDpiChanged);
|
||||
const RECT *prcNewWindow = reinterpret_cast<RECT *>(lParam);
|
||||
qCDebug(lcQpaWindows) << __FUNCTION__ << "WM_DPICHANGED"
|
||||
<< platformWindow->window() << *prcNewWindow;
|
||||
SetWindowPos(hwnd, nullptr, prcNewWindow->left, prcNewWindow->top,
|
||||
prcNewWindow->right - prcNewWindow->left,
|
||||
prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
platformWindow->clearFlag(QWindowsWindow::WithinDpiChanged);
|
||||
return true;
|
||||
// Try to apply the suggested size first and then notify ScreenChanged
|
||||
// so that the resize event sent from QGuiApplication incorporates it
|
||||
// WM_DPICHANGED is sent with a size that avoids resize loops (by
|
||||
// snapping back to the previous screen, see QTBUG-65580).
|
||||
const bool doResize = resizeOnDpiChanged(platformWindow->window());
|
||||
if (doResize) {
|
||||
platformWindow->setFlag(QWindowsWindow::WithinDpiChanged);
|
||||
platformWindow->updateFullFrameMargins();
|
||||
const auto prcNewWindow = reinterpret_cast<RECT *>(lParam);
|
||||
qCDebug(lcQpaWindows) << __FUNCTION__ << "WM_DPICHANGED"
|
||||
<< platformWindow->window() << *prcNewWindow;
|
||||
SetWindowPos(hwnd, nullptr, prcNewWindow->left, prcNewWindow->top,
|
||||
prcNewWindow->right - prcNewWindow->left,
|
||||
prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
platformWindow->clearFlag(QWindowsWindow::WithinDpiChanged);
|
||||
}
|
||||
platformWindow->checkForScreenChanged(QWindowsWindow::FromDpiChange);
|
||||
return doResize;
|
||||
}
|
||||
#if QT_CONFIG(sessionmanager)
|
||||
case QtWindows::QueryEndSessionApplicationEvent: {
|
||||
|
|
|
|||
|
|
@ -1861,28 +1861,41 @@ void QWindowsWindow::handleResized(int wParam)
|
|||
}
|
||||
}
|
||||
|
||||
void QWindowsWindow::checkForScreenChanged()
|
||||
static inline bool equalDpi(const QDpi &d1, const QDpi &d2)
|
||||
{
|
||||
if (parent())
|
||||
return qFuzzyCompare(d1.first, d2.first) && qFuzzyCompare(d1.second, d2.second);
|
||||
}
|
||||
|
||||
void QWindowsWindow::checkForScreenChanged(ScreenChangeMode mode)
|
||||
{
|
||||
if (parent() || QWindowsScreenManager::isSingleScreen())
|
||||
return;
|
||||
|
||||
QPlatformScreen *currentScreen = screen();
|
||||
const auto &screenManager = QWindowsContext::instance()->screenManager();
|
||||
const QWindowsScreen *newScreen = screenManager.screenForHwnd(m_data.hwnd);
|
||||
if (newScreen != nullptr && newScreen != currentScreen) {
|
||||
qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
|
||||
<< ' ' << window() << " \"" << currentScreen->name()
|
||||
<< "\"->\"" << newScreen->name() << '"';
|
||||
updateFullFrameMargins();
|
||||
setFlag(SynchronousGeometryChangeEvent);
|
||||
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
|
||||
const QWindowsScreen *newScreen =
|
||||
QWindowsContext::instance()->screenManager().screenForHwnd(m_data.hwnd);
|
||||
if (newScreen == nullptr || newScreen == currentScreen)
|
||||
return;
|
||||
// For screens with different DPI: postpone until WM_DPICHANGE
|
||||
if (mode == FromGeometryChange
|
||||
&& !equalDpi(currentScreen->logicalDpi(), newScreen->logicalDpi())) {
|
||||
return;
|
||||
}
|
||||
qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
|
||||
<< ' ' << window() << " \"" << currentScreen->name()
|
||||
<< "\"->\"" << newScreen->name() << '"';
|
||||
if (mode == FromGeometryChange)
|
||||
setFlag(SynchronousGeometryChangeEvent);
|
||||
updateFullFrameMargins();
|
||||
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
|
||||
}
|
||||
|
||||
void QWindowsWindow::handleGeometryChange()
|
||||
{
|
||||
const QRect previousGeometry = m_data.geometry;
|
||||
m_data.geometry = geometry_sys();
|
||||
if (testFlag(WithinDpiChanged))
|
||||
return; // QGuiApplication will send resize
|
||||
QWindowSystemInterface::handleGeometryChange(window(), m_data.geometry);
|
||||
// QTBUG-32121: OpenGL/normal windows (with exception of ANGLE) do not receive
|
||||
// expose events when shrinking, synthesize.
|
||||
|
|
|
|||
|
|
@ -334,7 +334,8 @@ public:
|
|||
void alertWindow(int durationMs = 0);
|
||||
void stopAlertWindow();
|
||||
|
||||
void checkForScreenChanged();
|
||||
enum ScreenChangeMode { FromGeometryChange, FromDpiChange };
|
||||
void checkForScreenChanged(ScreenChangeMode mode = FromGeometryChange);
|
||||
|
||||
static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes);
|
||||
void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch);
|
||||
|
|
|
|||
Loading…
Reference in New Issue