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 <Friedemann.Kleint@qt.io>
This commit is contained in:
Andre de la Rocha 2019-10-29 20:42:00 +01:00
parent 3916b8a28b
commit ef54abae43
3 changed files with 62 additions and 0 deletions

View File

@ -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<const POWERBROADCAST_SETTING *>(lParam);
if (setting) {
auto data = reinterpret_cast<const DWORD *>(&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)

View File

@ -176,6 +176,8 @@ public:
bool initTablet(unsigned integrationOptions);
bool initPointer(unsigned integrationOptions);
bool initPowerNotificationHandler();
int defaultDPI() const;
QString registerWindowClass(const QWindow *w);

View File

@ -256,6 +256,8 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList &paramL
m_context.initTouch(m_options);
QPlatformCursor::setCapability(QPlatformCursor::OverrideCursor);
m_context.initPowerNotificationHandler();
}
QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()