Qt 4.8
qclipboard_win.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qclipboard.h"
43 
44 #ifndef QT_NO_CLIPBOARD
45 
46 #include "qapplication.h"
47 #include "qapplication_p.h"
48 #include "qeventloop.h"
49 #include "qwidget.h"
50 #include "qevent.h"
51 #include "qmime.h"
52 #include "qt_windows.h"
53 #include "qdnd_p.h"
54 #include <private/qwidget_p.h>
55 #include <private/qsystemlibrary_p.h>
56 
58 
59 #if defined(Q_OS_WINCE)
61 #include "qguifunctions_wince.h"
63 
64 HRESULT QtCeGetClipboard(IDataObject** obj);
65 HRESULT QtCeSetClipboard(IDataObject* obj);
66 void QtCeFlushClipboard();
67 
68 #define OleGetClipboard QtCeGetClipboard
69 #define OleSetClipboard QtCeSetClipboard
70 #define OleFlushClipboard QtCeFlushClipboard
71 
72 #endif
73 
74 typedef BOOL (WINAPI *PtrIsHungAppWindow)(HWND);
75 
77 
79 public:
82  {
83  }
84 
85  bool hasFormat_sys(const QString &mimetype) const;
86  QStringList formats_sys() const;
87  QVariant retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const;
88 };
89 
90 
92 {
93  IDataObject * pDataObj = 0;
94 
95  if (OleGetClipboard(&pDataObj) != S_OK && !pDataObj) // Sanity
96  return false;
97 
98  bool has = QWindowsMime::converterToMime(mime, pDataObj) != 0;
99 
100  pDataObj->Release();
101 
102  return has;
103 }
104 
106 {
107  QStringList fmts;
108  IDataObject * pDataObj = 0;
109 
110  if (OleGetClipboard(&pDataObj) != S_OK && !pDataObj) // Sanity
111  return QStringList();
112 
113  fmts = QWindowsMime::allMimesForFormats(pDataObj);
114 
115  pDataObj->Release();
116 
117  return fmts;
118 }
119 
121 {
122  QVariant result;
123  IDataObject * pDataObj = 0;
124 
125  if (OleGetClipboard(&pDataObj) != S_OK && !pDataObj) // Sanity
126  return result;
127 
128  QWindowsMime *converter = QWindowsMime::converterToMime(mimeType, pDataObj);
129 
130  if (converter)
131  result = converter->convertToMime(mimeType, pDataObj, type);
132 
133  pDataObj->Release();
134 
135  return result;
136 }
137 
138 class QClipboardData
139 {
140 public:
142  : iData(0)
143  , nextClipboardViewer(0)
144  {
145  clipBoardViewer = new QWidget();
146  clipBoardViewer->createWinId();
147  clipBoardViewer->setObjectName(QLatin1String("internal clipboard owner"));
148  // We don't need this internal widget to appear in QApplication::topLevelWidgets()
150  QWidgetPrivate::allWidgets->remove(clipBoardViewer);
151  }
152 
154  {
155  Q_ASSERT(clipBoardViewer->testAttribute(Qt::WA_WState_Created));
156  ChangeClipboardChain(clipBoardViewer->internalWinId(), nextClipboardViewer);
157  delete clipBoardViewer;
158  releaseIData();
159  }
160 
162  {
163  if (iData) {
164  delete iData->mimeData();
165  iData->releaseQt();
166  iData->Release();
167  iData = 0;
168  }
169  }
170 
175 };
176 
178 
180 {
181  if (ptrClipboardData == 0) {
182  ptrClipboardData = new QClipboardData;
183  // this needs to be done here to avoid recursion
185  ptrClipboardData->nextClipboardViewer = SetClipboardViewer(ptrClipboardData->clipBoardViewer->internalWinId());
186  }
187  return ptrClipboardData;
188 }
189 
190 static void cleanupClipboardData()
191 {
192  delete ptrClipboardData;
193  ptrClipboardData = 0;
194 }
195 
196 #if defined(Q_OS_WINCE)
197 HRESULT QtCeGetClipboard(IDataObject** obj)
198 {
199  HWND owner = ptrClipboardData->clipBoardViewer->internalWinId();
200  if (!OpenClipboard(owner))
201  return !S_OK;
202 
203  if (!IsClipboardFormatAvailable(CF_TEXT) && !IsClipboardFormatAvailable(CF_UNICODETEXT))
204  return !S_OK;
205 
206  HANDLE clipData = GetClipboardData(CF_TEXT);
207  QString clipText;
208  if (clipData == 0) {
209  clipData = GetClipboardData(CF_UNICODETEXT);
210  if (clipData != 0)
211  clipText = QString::fromWCharArray((wchar_t *)clipData);
212  } else {
213  clipText = QString::fromLatin1((const char*)clipData);
214  }
215 
216  QMimeData *mimeData = new QMimeData();
217  mimeData->setText(clipText);
218  QOleDataObject* data = new QOleDataObject(mimeData);
219  *obj = data;
220  CloseClipboard();
221  return S_OK;
222 }
223 
224 HRESULT QtCeSetClipboard(IDataObject* obj)
225 {
226  HWND owner = ptrClipboardData->clipBoardViewer->internalWinId();
227  if (!OpenClipboard(owner))
228  return !S_OK;
229 
230  bool result = false;
231  if (obj == 0) {
232  result = true;
233  EmptyClipboard();
234  CloseClipboard();
235  } else {
236  QOleDataObject* qobj = static_cast<QOleDataObject*>(obj);
237 
238  const QMimeData* data = qobj->mimeData();
239  if (data->hasText()) {
240  EmptyClipboard();
241  result = SetClipboardData(CF_UNICODETEXT, wcsdup(reinterpret_cast<const wchar_t *> (data->text().utf16()))) != NULL;
242  CloseClipboard();
243  result = true;
244  }
245  }
246  return result ? S_OK : !S_OK;
247 }
248 
250 #endif
251 
252 
253 
255 {
257 }
258 
259 void QClipboard::setMimeData(QMimeData *src, Mode mode)
260 {
261  if (mode != Clipboard)
262  return;
264 
265  if (!(d->iData && d->iData->mimeData() == src)) {
266  d->releaseIData();
267  d->iData = new QOleDataObject(src);
268  }
269 
270  if (OleSetClipboard(d->iData) != S_OK) {
271  d->releaseIData();
272  qErrnoWarning("QClipboard::setMimeData: Failed to set data on clipboard");
273  return;
274  }
275 #if defined(Q_OS_WINCE)
276  // As WinCE does not support notifications we send the signal here
277  // We will get no event when the clipboard changes outside...
278  emit dataChanged();
279  emit changed(Clipboard);
280 #endif
281 }
282 
283 void QClipboard::clear(Mode mode)
284 {
285  if (mode != Clipboard) return;
286 
288 
289  d->releaseIData();
290 
291  if (OleSetClipboard(0) != S_OK) {
292  qErrnoWarning("QClipboard::clear: Failed to clear data on clipboard");
293  return;
294  }
295 #if defined(Q_OS_WINCE)
296  // As WinCE does not support notifications we send the signal here
297  // We will get no event when the clipboard changes outside...
298  emit dataChanged();
299  emit changed(Clipboard);
300 #endif
301 }
302 
303 #if !defined(Q_OS_WINCE) && defined(Q_CC_MSVC)
304 static bool isProcessBeingDebugged(HWND hwnd)
305 {
306  DWORD pid = 0;
307  if (!GetWindowThreadProcessId(hwnd, &pid) || !pid)
308  return false;
309  const HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
310  if (!processHandle)
311  return false;
312  BOOL debugged = FALSE;
313  CheckRemoteDebuggerPresent(processHandle, &debugged);
314  CloseHandle(processHandle);
315  return debugged != FALSE;
316 }
317 #else // !defined(Q_OS_WINCE) && defined(Q_CC_MSVC)
318 static bool isProcessBeingDebugged(HWND) { return false; }
319 #endif // defined(Q_OS_WINCE) || !defined(Q_CC_MSVC)
320 
321 bool QClipboard::event(QEvent *e)
322 {
323  if (e->type() != QEvent::Clipboard)
324  return QObject::event(e);
325 
327 
328  MSG *m = (MSG *)((QClipboardEvent*)e)->data();
329  if (!m) {
330  // this is sent to render all formats at app shut down
331  if (ownsClipboard()) {
333  d->releaseIData();
334  }
335  return true;
336  }
337 
338  bool propagate = false;
339 
340  if (m->message == WM_CHANGECBCHAIN) {
341  if ((HWND)m->wParam == d->nextClipboardViewer)
342  d->nextClipboardViewer = (HWND)m->lParam;
343  else
344  propagate = true;
345  } else if (m->message == WM_DRAWCLIPBOARD) {
346  emitChanged(QClipboard::Clipboard);
347  if (!ownsClipboard() && d->iData)
348  // clean up the clipboard object if we no longer own the clipboard
349  d->releaseIData();
350  propagate = true;
351  }
352  if (propagate && d->nextClipboardViewer) {
353  if (ptrIsHungAppWindow == 0) {
354  QSystemLibrary library(QLatin1String("User32"));
355  ptrIsHungAppWindow = (PtrIsHungAppWindow)library.resolve("IsHungAppWindow");
356  }
358  qWarning("%s: Cowardly refusing to send clipboard message to hung application...", Q_FUNC_INFO);
360  // Also refuse if the process is being debugged, specifically, if it is
361  // displaying a runtime assert, which is not caught by isHungAppWindow().
362  qWarning("%s: Cowardly refusing to send clipboard message to application under debugger...", Q_FUNC_INFO);
363  } else {
364  SendMessage(d->nextClipboardViewer, m->message, m->wParam, m->lParam);
365  }
366  }
367 
368  return true;
369 }
370 
371 void QClipboard::connectNotify(const char *signal)
372 {
373  if (qstrcmp(signal,SIGNAL(dataChanged())) == 0) {
374  // ensure we are up and running but block signals so the dataChange signal
375  // is not emitted while being connected to.
376  bool blocked = blockSignals(true);
378  blockSignals(blocked);
379  Q_UNUSED(d);
380  }
381 }
382 
383 const QMimeData *QClipboard::mimeData(Mode mode) const
384 {
385  if (mode != Clipboard)
386  return 0;
387 
389  // sort cut for local copy / paste
390  if (ownsClipboard() && data->iData->mimeData())
391  return data->iData->mimeData();
392  return &data->watcher;
393 }
394 
395 bool QClipboard::supportsMode(Mode mode) const
396 {
397  return (mode == Clipboard);
398 }
399 
400 bool QClipboard::ownsMode(Mode mode) const
401 {
402  if (mode == Clipboard) {
404 #if !defined(Q_OS_WINCE)
405  return d->iData && OleIsCurrentClipboard(d->iData) == S_OK;
406 #else
407  return d->iData && GetClipboardOwner() == d->clipBoardViewer->internalWinId();
408 #endif
409  } else {
410  return false;
411  }
412 }
413 
415 {
416 }
417 
419 
420 #endif // QT_NO_CLIPBOARD
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
static QString fromWCharArray(const wchar_t *, int size=-1)
Returns a copy of the string, where the encoding of string depends on the size of wchar...
Definition: qstring.cpp:1019
The QWindowsMime class maps open-standard MIME to Window Clipboard formats.
Definition: qmime.h:79
Mode
This enum type is used to control which part of the system clipboard is used by QClipboard::mimeData(...
Definition: qclipboard.h:71
double d
Definition: qnumeric_p.h:62
void clear(Mode mode=Clipboard)
Clear the clipboard contents.
bool blockSignals(bool b)
If block is true, signals emitted by this object are blocked (i.e., emitting a signal will not invoke...
Definition: qobject.cpp:1406
QStringList formats_sys() const
int type
Definition: qmetatype.cpp:239
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
static QClipboardData * clipboardData()
bool event(QEvent *)
Reimplemented Function
void ownerDestroyed()
Internal cleanup for Windows.
#define WM_DRAWCLIPBOARD
static QStringList allMimesForFormats(IDataObject *pDataObj)
Definition: qmime_win.cpp:392
bool remove(const T &value)
Definition: qset.h:89
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
const char * mime
#define ChangeClipboardChain(a, b)
BOOL(WINAPI * PtrIsHungAppWindow)(HWND)
#define QT_END_INCLUDE_NAMESPACE
This macro is equivalent to QT_BEGIN_NAMESPACE.
Definition: qglobal.h:92
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
bool supportsMode(Mode mode) const
Returns true if the clipboard supports the clipboard mode speacified by mode; otherwise returns false...
QByteArray data(const QString &mimetype) const
Returns the data stored in the object in the format described by the MIME type specified by mimeType...
Definition: qmimedata.cpp:524
void setMimeData(QMimeData *data, Mode mode=Clipboard)
Sets the clipboard data to src.
The QString class provides a Unicode character string.
Definition: qstring.h:83
HRESULT QtCeSetClipboard(IDataObject *obj)
static QWidget * owner
bool ownsMode(Mode mode) const
Returns true if the clipboard supports the clipboard data speacified by mode; otherwise returns false...
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
virtual bool event(QEvent *)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition: qobject.cpp:1200
static void cleanupClipboardData()
#define SIGNAL(a)
Definition: qobjectdefs.h:227
static bool isProcessBeingDebugged(HWND)
QMimeData()
Constructs a new MIME data object with no data in it.
Definition: qmimedata.cpp:291
QWidget * clipBoardViewer
const QMimeData * mimeData(Mode mode=Clipboard) const
Returns a reference to a QMimeData representation of the current clipboard data.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
#define OleGetClipboard
QString text() const
Returns a plain text (MIME type text/plain) representation of the data.
Definition: qmimedata.cpp:364
bool testAttribute(Qt::WidgetAttribute) const
Returns true if attribute attribute is set on this widget; otherwise returns false.
Definition: qwidget.h:1041
bool hasFormat_sys(const QString &mimetype) const
#define emit
Definition: qobjectdefs.h:76
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
HRESULT QtCeGetClipboard(IDataObject **obj)
Q_CORE_EXPORT void qWarning(const char *,...)
Type
This enum type defines the types of variable that a QVariant can contain.
Definition: qvariant.h:95
#define FALSE
Synonym for false.
Definition: qglobal.h:1019
static PtrIsHungAppWindow ptrIsHungAppWindow
#define WM_CHANGECBCHAIN
void * HANDLE
Definition: qnamespace.h:1671
QOleDataObject * iData
The QMimeData class provides a container for data that records information about its MIME type...
Definition: qmimedata.h:57
static QWidgetSet * allWidgets
Definition: qwidget_p.h:715
QVariant retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const
Mode
Definition: qaudio.h:60
#define SetClipboardViewer(a)
struct tagMSG MSG
long HRESULT
const QMimeData * mimeData() const
Definition: qdnd_win.cpp:94
void * resolve(const char *symbol)
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
bool hasText() const
Returns true if the object can return plain text (MIME type text/plain); otherwise returns false...
Definition: qmimedata.cpp:389
#define OleSetClipboard
static QWindowsMime * converterToMime(const QString &mimeType, IDataObject *pDataObj)
Definition: qmime_win.cpp:365
void QtCeFlushClipboard()
friend class QWidget
Definition: qobject.h:329
WId internalWinId() const
Returns the window system identifier of the widget, or 0 if the widget is not created yet...
Definition: qwidget.h:244
#define QT_BEGIN_INCLUDE_NAMESPACE
This macro is equivalent to QT_END_NAMESPACE.
Definition: qglobal.h:91
void setText(const QString &text)
Sets text as the plain text (MIME type text/plain) used to represent the data.
Definition: qmimedata.cpp:377
virtual QVariant convertToMime(const QString &mimeType, IDataObject *pDataObj, QVariant::Type preferredType) const =0
Returns a QVariant containing the converted data for mimeType from pDataObj.
static QClipboardData * ptrClipboardData
The QClipboardEvent class provides the parameters used in a clipboard event.
Definition: qevent.h:695
int qstrcmp(const QByteArray &str1, const char *str2)
Definition: qbytearray.cpp:336
QClipboardWatcher watcher
#define OleFlushClipboard
The QEvent class is the base class of all event classes.
Definition: qcoreevent.h:56
Type type() const
Returns the event type.
Definition: qcoreevent.h:303
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
void connectNotify(const char *)
Internal optimization for Windows.
const ushort * utf16() const
Returns the QString as a &#39;\0\&#39;-terminated array of unsigned shorts.
Definition: qstring.cpp:5290
void qErrnoWarning(const char *msg,...)
Definition: qglobal.cpp:2954
#define Q_FUNC_INFO
Definition: qglobal.h:1871