From ecfa33e751115919ddb47a6f641a2b1842c96788 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 3 Jul 2018 08:24:42 +0200 Subject: Windows QPA: Work around intermittent clipboard copy failures Repeatedly attempt to open the clipboard in case it is opened by other applications. Task-number: QTBUG-27097 Change-Id: Ic1cfec0bb17e34f8c7f744add21a4431dae4f5b7 Reviewed-by: Andy Shaw --- .../platforms/windows/qwindowsclipboard.cpp | 11 +++++++- src/plugins/platforms/windows/qwindowscontext.cpp | 32 ++++++++++++++++++++++ src/plugins/platforms/windows/qwindowscontext.h | 2 ++ src/plugins/platforms/windows/windows.pri | 2 +- 4 files changed, 45 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp index 53f329422c..8b386da9f7 100644 --- a/src/plugins/platforms/windows/qwindowsclipboard.cpp +++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -318,7 +319,15 @@ void QWindowsClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode) m_data = new QWindowsOleDataObject(mimeData); } - const HRESULT src = OleSetClipboard(m_data); + HRESULT src = S_FALSE; + int attempts = 0; + for (; attempts < 3; ++attempts) { + src = OleSetClipboard(m_data); + if (src != CLIPBRD_E_CANT_OPEN || QWindowsContext::isSessionLocked()) + break; + QThread::msleep(100); + } + if (src != S_OK) { QString mimeDataFormats = mimeData ? mimeData->formats().join(QLatin1String(", ")) : QString(QStringLiteral("NULL")); diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 373758b49e..9bce72d853 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -86,6 +86,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -754,6 +755,37 @@ QWindowsWindow *QWindowsContext::findPlatformWindowAt(HWND parent, return result; } +bool QWindowsContext::isSessionLocked() +{ + bool result = false; + const DWORD sessionId = WTSGetActiveConsoleSessionId(); + if (sessionId != 0xFFFFFFFF) { + LPTSTR buffer = nullptr; + DWORD size = 0; +#if !defined(Q_CC_MINGW) + if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, + WTSSessionInfoEx, &buffer, &size) == TRUE + && size > 0) { + const WTSINFOEXW *info = reinterpret_cast(buffer); + result = info->Level == 1 && info->Data.WTSInfoExLevel1.SessionFlags == WTS_SESSIONSTATE_LOCK; + WTSFreeMemory(buffer); + } +#else // MinGW as of 7.3 does not have WTSINFOEXW in wtsapi32.h + // Retrieve the flags which are at offset 16 due to padding for 32/64bit alike. + if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, + WTS_INFO_CLASS(25), &buffer, &size) == TRUE + && size >= 20) { + const DWORD *p = reinterpret_cast(buffer); + const DWORD level = *p; + const DWORD sessionFlags = *(p + 4); + result = level == 1 && sessionFlags == 1; + WTSFreeMemory(buffer); + } +#endif // Q_CC_MINGW + } + return result; +} + QWindowsMimeConverter &QWindowsContext::mimeConverter() const { return d->m_mimeConverter; diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 622c729a10..19e9c26130 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -224,6 +224,8 @@ public: bool useRTLExtensions() const; QList possibleKeys(const QKeyEvent *e) const; + static bool isSessionLocked(); + QWindowsMimeConverter &mimeConverter() const; QWindowsScreenManager &screenManager(); QWindowsTabletSupport *tabletSupport() const; diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index c1d4e907d9..db06a6a2a3 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -7,7 +7,7 @@ qtConfig(opengl):!qtConfig(opengles2):!qtConfig(dynamicgl): LIBS *= -lopengl32 mingw: LIBS *= -luuid # For the dialog helpers: -LIBS += -lshlwapi -lshell32 -ladvapi32 +LIBS += -lshlwapi -lshell32 -ladvapi32 -lwtsapi32 DEFINES *= QT_NO_CAST_FROM_ASCII QT_NO_FOREACH -- cgit v1.2.3