From ef54abae43db79792b40dfdca30ac0fa1b582354 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Tue, 29 Oct 2019 20:42:00 +0100 Subject: [PATCH] Windows QPA: Fix missing update when the display is sleeping If an item was updated while the display was in sleep mode then when the display came back from sleep it would not be updated. This change detects when the display returns from sleep and repaints the windows to ensure the updated items are presented. Fixes: QTBUG-76307 Change-Id: I5fff5209e8a5c359d06ba1df61944690e9475ea6 Reviewed-by: Friedemann Kleint --- .../platforms/windows/qwindowscontext.cpp | 58 +++++++++++++++++++ .../platforms/windows/qwindowscontext.h | 2 + .../platforms/windows/qwindowsintegration.cpp | 2 + 3 files changed, 62 insertions(+) diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 38b9823d6b..5c1b00a1c9 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -273,6 +273,8 @@ struct QWindowsContextPrivate { const HRESULT m_oleInitializeResult; QWindow *m_lastActiveWindow = nullptr; bool m_asyncExpose = false; + HPOWERNOTIFY m_powerNotification = nullptr; + HWND m_powerDummyWindow = nullptr; }; QWindowsContextPrivate::QWindowsContextPrivate() @@ -313,6 +315,13 @@ QWindowsContext::~QWindowsContext() #if QT_CONFIG(tabletevent) d->m_tabletSupport.reset(); // Destroy internal window before unregistering classes. #endif + + if (d->m_powerNotification) + UnregisterPowerSettingNotification(d->m_powerNotification); + + if (d->m_powerDummyWindow) + DestroyWindow(d->m_powerDummyWindow); + unregisterWindowClasses(); if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE) OleUninitialize(); @@ -380,6 +389,55 @@ bool QWindowsContext::initPointer(unsigned integrationOptions) return true; } +extern "C" LRESULT QT_WIN_CALLBACK qWindowsPowerWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message != WM_POWERBROADCAST || wParam != PBT_POWERSETTINGCHANGE) + return DefWindowProc(hwnd, message, wParam, lParam); + + static bool initialized = false; // ignore the initial change + if (!initialized) { + initialized = true; + return DefWindowProc(hwnd, message, wParam, lParam); + } + + auto setting = reinterpret_cast(lParam); + if (setting) { + auto data = reinterpret_cast(&setting->Data); + if (*data == 1) { + // Repaint the windows when returning from sleeping display mode. + const auto tlw = QGuiApplication::topLevelWindows(); + for (auto w : tlw) { + if (w->isVisible() && w->windowState() != Qt::WindowMinimized) { + if (auto tw = QWindowsWindow::windowsWindowOf(w)) { + if (HWND hwnd = tw->handle()) { + InvalidateRect(hwnd, nullptr, false); + } + } + } + } + } + } + return DefWindowProc(hwnd, message, wParam, lParam); +} + +bool QWindowsContext::initPowerNotificationHandler() +{ + if (d->m_powerNotification) + return false; + + d->m_powerDummyWindow = createDummyWindow(QStringLiteral("QtPowerDummyWindow"), L"QtPowerDummyWindow", qWindowsPowerWindowProc); + if (!d->m_powerDummyWindow) + return false; + + d->m_powerNotification = RegisterPowerSettingNotification(d->m_powerDummyWindow, &GUID_MONITOR_POWER_ON, DEVICE_NOTIFY_WINDOW_HANDLE); + if (!d->m_powerNotification) { + DestroyWindow(d->m_powerDummyWindow); + d->m_powerDummyWindow = nullptr; + return false; + } + return true; +} + void QWindowsContext::setTabletAbsoluteRange(int a) { #if QT_CONFIG(tabletevent) diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 4908f14629..04290379db 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -176,6 +176,8 @@ public: bool initTablet(unsigned integrationOptions); bool initPointer(unsigned integrationOptions); + bool initPowerNotificationHandler(); + int defaultDPI() const; QString registerWindowClass(const QWindow *w); diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 5c1fa00088..849e6cf2d0 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -256,6 +256,8 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList ¶mL m_context.initTouch(m_options); QPlatformCursor::setCapability(QPlatformCursor::OverrideCursor); + + m_context.initPowerNotificationHandler(); } QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()