summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@digia.com>2014-05-06 17:24:23 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-05-15 15:31:07 +0200
commit6a61a00ddb21e79412e82069dfef50192bfd724d (patch)
treee922d83a1d27c4a00390d4f0e2a6c4b459c5a544 /src
parentf618dbdd04d1efa087dfa9a5aa792c315a5bc500 (diff)
Windows: Use new clipboard API for listening to changes.
The currently used clipboard chain API has various problems with non- responsive applications and requires checks for hung/debugged applications when sending on notifications. The new clipboard format listener API available from Windows Vista onwards requires less code and does not have these problems, however the change notifications now arrive asynchronously. Change the tst_qclipboard to be able to deal with asynchronous change notifications. Task-number: QTBUG-38670 Task-number: QTBUG-33492 Change-Id: I3c49e346a34310431c20f3051d12eaabf330a3ad Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.cpp40
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.h3
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h6
4 files changed, 47 insertions, 10 deletions
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp
index dcfeba12fa..e43b524aa8 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.cpp
+++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -145,7 +145,7 @@ static void cleanClipboardPostRoutine()
QWindowsClipboard *QWindowsClipboard::m_instance = 0;
QWindowsClipboard::QWindowsClipboard() :
- m_data(0), m_clipboardViewer(0), m_nextClipboardViewer(0)
+ m_data(0), m_clipboardViewer(0), m_nextClipboardViewer(0), m_formatListenerRegistered(false)
{
QWindowsClipboard::m_instance = this;
qAddPostRoutine(cleanClipboardPostRoutine);
@@ -178,20 +178,40 @@ void QWindowsClipboard::registerViewer()
m_clipboardViewer = QWindowsContext::instance()->
createDummyWindow(QStringLiteral("Qt5ClipboardView"), L"Qt5ClipboardView",
qClipboardViewerWndProc, WS_OVERLAPPED);
- m_nextClipboardViewer = SetClipboardViewer(m_clipboardViewer);
- qCDebug(lcQpaMime) << __FUNCTION__ << "m_clipboardViewer: " << m_clipboardViewer << "next: " << m_nextClipboardViewer;
+ // Try format listener API (Vista onwards) first.
+ if (QWindowsContext::user32dll.addClipboardFormatListener && QWindowsContext::user32dll.removeClipboardFormatListener) {
+ m_formatListenerRegistered = QWindowsContext::user32dll.addClipboardFormatListener(m_clipboardViewer);
+ if (!m_formatListenerRegistered)
+ qErrnoWarning("AddClipboardFormatListener() failed.");
+ }
+
+ if (!m_formatListenerRegistered)
+ m_nextClipboardViewer = SetClipboardViewer(m_clipboardViewer);
+
+ qCDebug(lcQpaMime) << __FUNCTION__ << "m_clipboardViewer:" << m_clipboardViewer
+ << "format listener:" << m_formatListenerRegistered
+ << "next:" << m_nextClipboardViewer;
}
void QWindowsClipboard::unregisterViewer()
{
if (m_clipboardViewer) {
- ChangeClipboardChain(m_clipboardViewer, m_nextClipboardViewer);
+ if (m_formatListenerRegistered) {
+ QWindowsContext::user32dll.removeClipboardFormatListener(m_clipboardViewer);
+ m_formatListenerRegistered = false;
+ } else {
+ ChangeClipboardChain(m_clipboardViewer, m_nextClipboardViewer);
+ m_nextClipboardViewer = 0;
+ }
DestroyWindow(m_clipboardViewer);
- m_clipboardViewer = m_nextClipboardViewer = 0;
+ m_clipboardViewer = 0;
}
}
+// ### FIXME: Qt 6: Remove the clipboard chain handling code and make the
+// format listener the default.
+
static bool isProcessBeingDebugged(HWND hwnd)
{
DWORD pid = 0;
@@ -232,6 +252,8 @@ void QWindowsClipboard::propagateClipboardMessage(UINT message, WPARAM wParam, L
bool QWindowsClipboard::clipboardViewerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
{
+ enum { wMClipboardUpdate = 0x031D };
+
*result = 0;
if (QWindowsContext::verbose)
qCDebug(lcQpaMime) << __FUNCTION__ << hwnd << message << QWindowsGuiEventDispatcher::windowsMessageName(message);
@@ -246,14 +268,16 @@ bool QWindowsClipboard::clipboardViewerWndProc(HWND hwnd, UINT message, WPARAM w
}
}
return true;
- case WM_DRAWCLIPBOARD: {
+ case wMClipboardUpdate: // Clipboard Format listener (Vista onwards)
+ case WM_DRAWCLIPBOARD: { // Clipboard Viewer Chain handling (up to XP)
const bool owned = ownsClipboard();
qCDebug(lcQpaMime) << "Clipboard changed owned " << owned;
emitChanged(QClipboard::Clipboard);
// clean up the clipboard object if we no longer own the clipboard
if (!owned && m_data)
releaseIData();
- propagateClipboardMessage(message, wParam, lParam);
+ if (!m_formatListenerRegistered)
+ propagateClipboardMessage(message, wParam, lParam);
}
return true;
case WM_DESTROY:
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.h b/src/plugins/platforms/windows/qwindowsclipboard.h
index 30bc0143f4..61c5967e98 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.h
+++ b/src/plugins/platforms/windows/qwindowsclipboard.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -88,6 +88,7 @@ private:
QWindowsOleDataObject *m_data;
HWND m_clipboardViewer;
HWND m_nextClipboardViewer;
+ bool m_formatListenerRegistered;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index ccff2d3e9f..63615dd4bf 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -191,7 +191,8 @@ QWindowsUser32DLL::QWindowsUser32DLL() :
updateLayeredWindowIndirect(0),
isHungAppWindow(0),
registerTouchWindow(0), unregisterTouchWindow(0),
- getTouchInputInfo(0), closeTouchInputHandle(0), setProcessDPIAware(0)
+ getTouchInputInfo(0), closeTouchInputHandle(0), setProcessDPIAware(0),
+ addClipboardFormatListener(0), removeClipboardFormatListener(0)
{
}
@@ -207,6 +208,11 @@ void QWindowsUser32DLL::init()
updateLayeredWindowIndirect = (UpdateLayeredWindowIndirect)(library.resolve("UpdateLayeredWindowIndirect"));
isHungAppWindow = (IsHungAppWindow)library.resolve("IsHungAppWindow");
setProcessDPIAware = (SetProcessDPIAware)library.resolve("SetProcessDPIAware");
+
+ if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) {
+ addClipboardFormatListener = (AddClipboardFormatListener)library.resolve("AddClipboardFormatListener");
+ removeClipboardFormatListener = (RemoveClipboardFormatListener)library.resolve("RemoveClipboardFormatListener");
+ }
}
bool QWindowsUser32DLL::initTouch()
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index d565a5feab..086b968255 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -94,6 +94,8 @@ struct QWindowsUser32DLL
typedef BOOL (WINAPI *UpdateLayeredWindowIndirect)(HWND, const UPDATELAYEREDWINDOWINFO *);
typedef BOOL (WINAPI *IsHungAppWindow)(HWND);
typedef BOOL (WINAPI *SetProcessDPIAware)();
+ typedef BOOL (WINAPI *AddClipboardFormatListener)(HWND);
+ typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND);
// Functions missing in Q_CC_GNU stub libraries.
SetLayeredWindowAttributes setLayeredWindowAttributes;
@@ -111,6 +113,10 @@ struct QWindowsUser32DLL
// Windows Vista onwards
SetProcessDPIAware setProcessDPIAware;
+
+ // Clipboard listeners, Windows Vista onwards
+ AddClipboardFormatListener addClipboardFormatListener;
+ RemoveClipboardFormatListener removeClipboardFormatListener;
};
struct QWindowsShell32DLL