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 <andy.shaw@qt.io>
bb10
Friedemann Kleint 2018-07-03 08:24:42 +02:00
parent 76c4a70499
commit ecfa33e751
4 changed files with 45 additions and 2 deletions

View File

@ -50,6 +50,7 @@
#include <QtCore/qdebug.h>
#include <QtCore/qmimedata.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qthread.h>
#include <QtCore/qvariant.h>
#include <QtCore/qurl.h>
@ -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"));

View File

@ -86,6 +86,7 @@
#include <windowsx.h>
#include <comdef.h>
#include <dbt.h>
#include <wtsapi32.h>
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<WTSINFOEXW *>(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<DWORD *>(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;

View File

@ -224,6 +224,8 @@ public:
bool useRTLExtensions() const;
QList<int> possibleKeys(const QKeyEvent *e) const;
static bool isSessionLocked();
QWindowsMimeConverter &mimeConverter() const;
QWindowsScreenManager &screenManager();
QWindowsTabletSupport *tabletSupport() const;

View File

@ -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