summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJørgen Lind <jorgen.lind@nokia.com>2010-12-28 14:44:47 (GMT)
committerJørgen Lind <jorgen.lind@nokia.com>2011-01-04 14:18:29 (GMT)
commitc33402ff531c1667305907963c221b88dd168691 (patch)
treefb48a430f76a5f8ebf327a1747094d8d8d233066
parent1097310a4ff0bda0f3c5a0204c42ed40035e6dbf (diff)
downloadQt-c33402ff531c1667305907963c221b88dd168691.zip
Qt-c33402ff531c1667305907963c221b88dd168691.tar.gz
Qt-c33402ff531c1667305907963c221b88dd168691.tar.bz2
Copy/Paste in testlite and also added QTestLiteStaticInfo
which is a class to resolve atoms etc.
-rw-r--r--src/plugins/platforms/testlite/qtestliteclipboard.cpp519
-rw-r--r--src/plugins/platforms/testlite/qtestliteclipboard.h52
-rw-r--r--src/plugins/platforms/testlite/qtestliteintegration.cpp13
-rw-r--r--src/plugins/platforms/testlite/qtestliteintegration.h4
-rw-r--r--src/plugins/platforms/testlite/qtestlitemime.cpp362
-rw-r--r--src/plugins/platforms/testlite/qtestlitemime.h42
-rw-r--r--src/plugins/platforms/testlite/qtestlitescreen.cpp133
-rw-r--r--src/plugins/platforms/testlite/qtestlitescreen.h16
-rw-r--r--src/plugins/platforms/testlite/qtestlitestaticinfo.cpp417
-rw-r--r--src/plugins/platforms/testlite/qtestlitestaticinfo.h371
-rw-r--r--src/plugins/platforms/testlite/qtestlitewindow.cpp36
-rw-r--r--src/plugins/platforms/testlite/testlite.pro10
12 files changed, 1899 insertions, 76 deletions
diff --git a/src/plugins/platforms/testlite/qtestliteclipboard.cpp b/src/plugins/platforms/testlite/qtestliteclipboard.cpp
new file mode 100644
index 0000000..fdd6d30
--- /dev/null
+++ b/src/plugins/platforms/testlite/qtestliteclipboard.cpp
@@ -0,0 +1,519 @@
+#include "qtestliteclipboard.h"
+
+#include "qtestlitescreen.h"
+#include "qtestlitemime.h"
+
+#include <private/qapplication_p.h>
+
+#include <QtCore/QDebug>
+
+const int QTestLiteClipboard::clipboard_timeout = 5000;
+
+QTestLiteClipboard::QTestLiteClipboard(QTestLiteScreen *screen)
+ : QPlatformClipboard()
+ , m_screen(screen)
+ , m_xClipboard(0)
+ , m_clientClipboard(0)
+ , m_xSelection(0)
+ , m_clientSelection(0)
+ , m_requestor(XNone)
+ , m_owner(XNone)
+{
+}
+
+const QMimeData * QTestLiteClipboard::mimeData(QClipboard::Mode mode) const
+{
+ if (mode == QClipboard::Clipboard) {
+ if (!m_xClipboard) {
+ QTestLiteClipboard *that = const_cast<QTestLiteClipboard *>(this);
+ that->m_xClipboard = new QTestLiteMime(mode,that);
+ }
+ Window clipboardOwner = XGetSelectionOwner(screen()->display(),QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIPBOARD));
+ if (clipboardOwner == owner()) {
+ return m_clientClipboard;
+ } else {
+ return m_xClipboard;
+ }
+ }
+ return 0;
+}
+
+void QTestLiteClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
+{
+ Atom modeAtom;
+ QMimeData **d;
+ switch (mode) {
+ case QClipboard::Selection:
+ modeAtom = XA_PRIMARY;
+ d = &m_clientSelection;
+ break;
+
+ case QClipboard::Clipboard:
+ modeAtom = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIPBOARD);
+ d = &m_clientClipboard;
+ break;
+
+ default:
+ qWarning("QClipboard::setMimeData: unsupported mode '%d'", mode);
+ return;
+ }
+
+ Window newOwner;
+
+ if (! data) { // no data, clear clipboard contents
+ newOwner = XNone;
+ } else {
+ newOwner = owner();
+
+ *d = data;
+ }
+
+ XSetSelectionOwner(m_screen->display(), modeAtom, newOwner, CurrentTime);
+
+ if (XGetSelectionOwner(m_screen->display(), modeAtom) != newOwner) {
+// qWarning("QClipboard::setData: Cannot set X11 selection owner for %s",
+// xdndAtomToString(atom).data());
+ *d = 0;
+ return;
+ }
+
+}
+
+QTestLiteScreen * QTestLiteClipboard::screen() const
+{
+ return m_screen;
+}
+
+Window QTestLiteClipboard::requestor() const
+{
+ if (!m_requestor) {
+ int x = 0, y = 0, w = 3, h = 3;
+ QTestLiteClipboard *that = const_cast<QTestLiteClipboard *>(this);
+ Window window = XCreateSimpleWindow(m_screen->display(), m_screen->rootWindow(),
+ x, y, w, h, 0 /*border_width*/,
+ m_screen->blackPixel(), m_screen->whitePixel());
+ that->setRequestor(window);
+ }
+ return m_requestor;
+}
+
+void QTestLiteClipboard::setRequestor(Window window)
+{
+ if (m_requestor != XNone) {
+ XDestroyWindow(m_screen->display(),m_requestor);
+ }
+ m_requestor = window;
+}
+
+Window QTestLiteClipboard::owner() const
+{
+ if (!m_owner) {
+ int x = 0, y = 0, w = 3, h = 3;
+ QTestLiteClipboard *that = const_cast<QTestLiteClipboard *>(this);
+ Window window = XCreateSimpleWindow(m_screen->display(), m_screen->rootWindow(),
+ x, y, w, h, 0 /*border_width*/,
+ m_screen->blackPixel(), m_screen->whitePixel());
+ that->setOwner(window);
+ }
+ return m_owner;
+}
+
+void QTestLiteClipboard::setOwner(Window window)
+{
+ if (m_owner != XNone){
+ XDestroyWindow(m_screen->display(),m_owner);
+ }
+ m_owner = window;
+}
+
+Atom QTestLiteClipboard::sendTargetsSelection(QMimeData *d, Window window, Atom property)
+{
+ QVector<Atom> types;
+ QStringList formats = QInternalMimeData::formatsHelper(d);
+ for (int i = 0; i < formats.size(); ++i) {
+ QList<Atom> atoms = QTestLiteMime::xdndMimeAtomsForFormat(screen()->display(),formats.at(i));
+ for (int j = 0; j < atoms.size(); ++j) {
+ if (!types.contains(atoms.at(j)))
+ types.append(atoms.at(j));
+ }
+ }
+ types.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TARGETS));
+ types.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::MULTIPLE));
+ types.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TIMESTAMP));
+ types.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::SAVE_TARGETS));
+
+ XChangeProperty(screen()->display(), window, property, XA_ATOM, 32,
+ PropModeReplace, (uchar *) types.data(), types.size());
+ return property;
+}
+
+Atom QTestLiteClipboard::sendSelection(QMimeData *d, Atom target, Window window, Atom property)
+{
+ Atom atomFormat = target;
+ int dataFormat = 0;
+ QByteArray data;
+
+ QString fmt = QTestLiteMime::xdndMimeAtomToString(screen()->display(), target);
+ if (fmt.isEmpty()) { // Not a MIME type we have
+ qDebug() << "QClipboard: send_selection(): converting to type '%s' is not supported" << fmt.data();
+ return XNone;
+ }
+ qDebug() << "QClipboard: send_selection(): converting to type '%s'" << fmt.data();
+
+ if (QTestLiteMime::xdndMimeDataForAtom(screen()->display(),target, d, &data, &atomFormat, &dataFormat)) {
+
+ // don't allow INCR transfers when using MULTIPLE or to
+ // Motif clients (since Motif doesn't support INCR)
+ static Atom motif_clip_temporary = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIP_TEMPORARY);
+ bool allow_incr = property != motif_clip_temporary;
+
+ // X_ChangeProperty protocol request is 24 bytes
+ const int increment = (XMaxRequestSize(screen()->display()) * 4) - 24;
+ if (data.size() > increment && allow_incr) {
+ long bytes = data.size();
+ XChangeProperty(screen()->display(), window, property,
+ QTestLiteStaticInfo::atom(QTestLiteStaticInfo::INCR), 32, PropModeReplace, (uchar *) &bytes, 1);
+
+// (void)new QClipboardINCRTransaction(window, property, atomFormat, dataFormat, data, increment);
+ qDebug() << "not implemented INCRT just YET!";
+ return property;
+ }
+
+ // make sure we can perform the XChangeProperty in a single request
+ if (data.size() > increment)
+ return XNone; // ### perhaps use several XChangeProperty calls w/ PropModeAppend?
+ int dataSize = data.size() / (dataFormat / 8);
+ // use a single request to transfer data
+ XChangeProperty(screen()->display(), window, property, atomFormat,
+ dataFormat, PropModeReplace, (uchar *) data.data(),
+ dataSize);
+ }
+ return property;
+}
+
+void QTestLiteClipboard::handleSelectionRequest(XEvent *xevent)
+{
+ XSelectionRequestEvent *req = &xevent->xselectionrequest;
+
+ if (requestor() && req->requestor == requestor()) {
+ qDebug() << "This should be caught before";
+ return;
+ }
+
+ XEvent event;
+ event.xselection.type = SelectionNotify;
+ event.xselection.display = req->display;
+ event.xselection.requestor = req->requestor;
+ event.xselection.selection = req->selection;
+ event.xselection.target = req->target;
+ event.xselection.property = XNone;
+ event.xselection.time = req->time;
+
+ QMimeData *d;
+ if (req->selection == XA_PRIMARY) {
+ d = m_clientSelection;
+ } else if (req->selection == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIPBOARD)) {
+ d = m_clientClipboard;
+ } else {
+ qWarning("QClipboard: Unknown selection '%lx'", req->selection);
+ XSendEvent(screen()->display(), req->requestor, False, NoEventMask, &event);
+ return;
+ }
+
+ if (!d) {
+ qWarning("QClipboard: Cannot transfer data, no data available");
+ XSendEvent(screen()->display(), req->requestor, False, NoEventMask, &event);
+ return;
+ }
+
+ Atom xa_targets = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TARGETS);
+ Atom xa_multiple = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::MULTIPLE);
+ Atom xa_timestamp = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TIMESTAMP);
+
+ struct AtomPair { Atom target; Atom property; } *multi = 0;
+ Atom multi_type = XNone;
+ int multi_format = 0;
+ int nmulti = 0;
+ int imulti = -1;
+ bool multi_writeback = false;
+
+ if (req->target == xa_multiple) {
+ QByteArray multi_data;
+ if (req->property == XNone
+ || !clipboardReadProperty(req->requestor, req->property, false, &multi_data,
+ 0, &multi_type, &multi_format)
+ || multi_format != 32) {
+ // MULTIPLE property not formatted correctly
+ XSendEvent(screen()->display(), req->requestor, False, NoEventMask, &event);
+ return;
+ }
+ nmulti = multi_data.size()/sizeof(*multi);
+ multi = new AtomPair[nmulti];
+ memcpy(multi,multi_data.data(),multi_data.size());
+ imulti = 0;
+ }
+
+ for (; imulti < nmulti; ++imulti) {
+ Atom target;
+ Atom property;
+
+ if (multi) {
+ target = multi[imulti].target;
+ property = multi[imulti].property;
+ } else {
+ target = req->target;
+ property = req->property;
+ if (property == XNone) // obsolete client
+ property = target;
+ }
+
+ Atom ret = XNone;
+ if (target == XNone || property == XNone) {
+ ;
+ } else if (target == xa_timestamp) {
+// if (d->timestamp != CurrentTime) {
+ XChangeProperty(screen()->display(), req->requestor, property, XA_INTEGER, 32,
+ PropModeReplace, CurrentTime, 1);
+ ret = property;
+// } else {
+// qWarning("QClipboard: Invalid data timestamp");
+// }
+ } else if (target == xa_targets) {
+ ret = sendTargetsSelection(d, req->requestor, property);
+ } else {
+ ret = sendSelection(d, target, req->requestor, property);
+ }
+
+ if (nmulti > 0) {
+ if (ret == XNone) {
+ multi[imulti].property = XNone;
+ multi_writeback = true;
+ }
+ } else {
+ event.xselection.property = ret;
+ break;
+ }
+ }
+
+ if (nmulti > 0) {
+ if (multi_writeback) {
+ // according to ICCCM 2.6.2 says to put None back
+ // into the original property on the requestor window
+ XChangeProperty(screen()->display(), req->requestor, req->property, multi_type, 32,
+ PropModeReplace, (uchar *) multi, nmulti * 2);
+ }
+
+ delete [] multi;
+ event.xselection.property = req->property;
+ }
+
+ // send selection notify to requestor
+ XSendEvent(screen()->display(), req->requestor, False, NoEventMask, &event);
+}
+
+static inline int maxSelectionIncr(Display *dpy)
+{ return XMaxRequestSize(dpy) > 65536 ? 65536*4 : XMaxRequestSize(dpy)*4 - 100; }
+
+bool QTestLiteClipboard::clipboardReadProperty(Window win, Atom property, bool deleteProperty, QByteArray *buffer, int *size, Atom *type, int *format) const
+{
+ int maxsize = maxSelectionIncr(screen()->display());
+ ulong bytes_left; // bytes_after
+ ulong length; // nitems
+ uchar *data;
+ Atom dummy_type;
+ int dummy_format;
+ int r;
+
+ if (!type) // allow null args
+ type = &dummy_type;
+ if (!format)
+ format = &dummy_format;
+
+ // Don't read anything, just get the size of the property data
+ r = XGetWindowProperty(screen()->display(), win, property, 0, 0, False,
+ AnyPropertyType, type, format,
+ &length, &bytes_left, &data);
+ if (r != Success || (type && *type == XNone)) {
+ buffer->resize(0);
+ return false;
+ }
+ XFree((char*)data);
+
+ int offset = 0, buffer_offset = 0, format_inc = 1, proplen = bytes_left;
+
+ switch (*format) {
+ case 8:
+ default:
+ format_inc = sizeof(char) / 1;
+ break;
+
+ case 16:
+ format_inc = sizeof(short) / 2;
+ proplen *= sizeof(short) / 2;
+ break;
+
+ case 32:
+ format_inc = sizeof(long) / 4;
+ proplen *= sizeof(long) / 4;
+ break;
+ }
+
+ int newSize = proplen;
+ buffer->resize(newSize);
+
+ bool ok = (buffer->size() == newSize);
+
+ if (ok && newSize) {
+ // could allocate buffer
+
+ while (bytes_left) {
+ // more to read...
+
+ r = XGetWindowProperty(screen()->display(), win, property, offset, maxsize/4,
+ False, AnyPropertyType, type, format,
+ &length, &bytes_left, &data);
+ if (r != Success || (type && *type == XNone))
+ break;
+
+ offset += length / (32 / *format);
+ length *= format_inc * (*format) / 8;
+
+ // Here we check if we get a buffer overflow and tries to
+ // recover -- this shouldn't normally happen, but it doesn't
+ // hurt to be defensive
+ if ((int)(buffer_offset + length) > buffer->size()) {
+ length = buffer->size() - buffer_offset;
+
+ // escape loop
+ bytes_left = 0;
+ }
+
+ memcpy(buffer->data() + buffer_offset, data, length);
+ buffer_offset += length;
+
+ XFree((char*)data);
+ }
+
+ if (*format == 8 && *type == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)) {
+ // convert COMPOUND_TEXT to a multibyte string
+ XTextProperty textprop;
+ textprop.encoding = *type;
+ textprop.format = *format;
+ textprop.nitems = buffer_offset;
+ textprop.value = (unsigned char *) buffer->data();
+
+ char **list_ret = 0;
+ int count;
+ if (XmbTextPropertyToTextList(screen()->display(), &textprop, &list_ret,
+ &count) == Success && count && list_ret) {
+ offset = buffer_offset = strlen(list_ret[0]);
+ buffer->resize(offset);
+ memcpy(buffer->data(), list_ret[0], offset);
+ }
+ if (list_ret) XFreeStringList(list_ret);
+ }
+ }
+
+ // correct size, not 0-term.
+ if (size)
+ *size = buffer_offset;
+
+ if (deleteProperty)
+ XDeleteProperty(screen()->display(), win, property);
+
+ XFlush(screen()->display());
+
+ return ok;
+}
+
+QByteArray QTestLiteClipboard::clipboardReadIncrementalProperty(Window win, Atom property, int nbytes, bool nullterm)
+{
+ XEvent event;
+
+ QByteArray buf;
+ QByteArray tmp_buf;
+ bool alloc_error = false;
+ int length;
+ int offset = 0;
+
+ if (nbytes > 0) {
+ // Reserve buffer + zero-terminator (for text data)
+ // We want to complete the INCR transfer even if we cannot
+ // allocate more memory
+ buf.resize(nbytes+1);
+ alloc_error = buf.size() != nbytes+1;
+ }
+
+ for (;;) {
+ XFlush(screen()->display());
+ if (!screen()->waitForClipboardEvent(win,PropertyNotify,&event,clipboard_timeout))
+ break;
+ if (event.xproperty.atom != property ||
+ event.xproperty.state != PropertyNewValue)
+ continue;
+ if (clipboardReadProperty(win, property, true, &tmp_buf, &length, 0, 0)) {
+ if (length == 0) { // no more data, we're done
+ if (nullterm) {
+ buf.resize(offset+1);
+ buf[offset] = '\0';
+ } else {
+ buf.resize(offset);
+ }
+ return buf;
+ } else if (!alloc_error) {
+ if (offset+length > (int)buf.size()) {
+ buf.resize(offset+length+65535);
+ if (buf.size() != offset+length+65535) {
+ alloc_error = true;
+ length = buf.size() - offset;
+ }
+ }
+ memcpy(buf.data()+offset, tmp_buf.constData(), length);
+ tmp_buf.resize(0);
+ offset += length;
+ }
+ } else {
+ break;
+ }
+ }
+
+ // timed out ... create a new requestor window, otherwise the requestor
+ // could consider next request to be still part of this timed out request
+ setRequestor(0);
+
+ return QByteArray();
+}
+
+QByteArray QTestLiteClipboard::getDataInFormat(Atom modeAtom, Atom fmtatom)
+{
+ QByteArray buf;
+
+ Window win = requestor();
+
+ XSelectInput(screen()->display(), win, NoEventMask); // don't listen for any events
+
+ XDeleteProperty(screen()->display(), win, QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_QT_SELECTION));
+ XConvertSelection(screen()->display(), modeAtom, fmtatom, QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_QT_SELECTION), win, CurrentTime);
+ XSync(screen()->display(), false);
+
+ XEvent xevent;
+ if (!screen()->waitForClipboardEvent(win,SelectionNotify,&xevent,clipboard_timeout) ||
+ xevent.xselection.property == XNone) {
+ return buf;
+ }
+
+ Atom type;
+ XSelectInput(screen()->display(), win, PropertyChangeMask);
+
+ if (clipboardReadProperty(win, QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_QT_SELECTION), true, &buf, 0, &type, 0)) {
+ if (type == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::INCR)) {
+ int nbytes = buf.size() >= 4 ? *((int*)buf.data()) : 0;
+ buf = clipboardReadIncrementalProperty(win, QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_QT_SELECTION), nbytes, false);
+ }
+ }
+
+ XSelectInput(screen()->display(), win, NoEventMask);
+
+
+ return buf;
+}
diff --git a/src/plugins/platforms/testlite/qtestliteclipboard.h b/src/plugins/platforms/testlite/qtestliteclipboard.h
new file mode 100644
index 0000000..31e42b7
--- /dev/null
+++ b/src/plugins/platforms/testlite/qtestliteclipboard.h
@@ -0,0 +1,52 @@
+#ifndef QTESTLITECLIPBOARD_H
+#define QTESTLITECLIPBOARD_H
+
+#include <QPlatformClipboard>
+#include "qtestlitestaticinfo.h"
+
+class QTestLiteScreen;
+class QTestLiteMime;
+class QTestLiteClipboard : public QPlatformClipboard
+{
+public:
+ QTestLiteClipboard(QTestLiteScreen *screen);
+
+ const QMimeData *mimeData(QClipboard::Mode mode) const;
+ void setMimeData(QMimeData *data, QClipboard::Mode mode);
+
+ QTestLiteScreen *screen() const;
+
+ Window requestor() const;
+ void setRequestor(Window window);
+
+ Window owner() const;
+
+ void handleSelectionRequest(XEvent *event);
+
+ bool clipboardReadProperty(Window win, Atom property, bool deleteProperty, QByteArray *buffer, int *size, Atom *type, int *format) const;
+ QByteArray clipboardReadIncrementalProperty(Window win, Atom property, int nbytes, bool nullterm);
+
+ QByteArray getDataInFormat(Atom modeAtom, Atom fmtatom);
+
+private:
+ void setOwner(Window window);
+
+ Atom sendTargetsSelection(QMimeData *d, Window window, Atom property);
+ Atom sendSelection(QMimeData *d, Atom target, Window window, Atom property);
+
+ QTestLiteScreen *m_screen;
+
+ QTestLiteMime *m_xClipboard;
+ QMimeData *m_clientClipboard;
+
+ QTestLiteMime *m_xSelection;
+ QMimeData *m_clientSelection;
+
+ Window m_requestor;
+ Window m_owner;
+
+ static const int clipboard_timeout;
+
+};
+
+#endif // QTESTLITECLIPBOARD_H
diff --git a/src/plugins/platforms/testlite/qtestliteintegration.cpp b/src/plugins/platforms/testlite/qtestliteintegration.cpp
index fc2a89c..537e22a 100644
--- a/src/plugins/platforms/testlite/qtestliteintegration.cpp
+++ b/src/plugins/platforms/testlite/qtestliteintegration.cpp
@@ -47,6 +47,7 @@
#include "qtestlitewindow.h"
#include "qgenericunixfontdatabase.h"
#include "qtestlitescreen.h"
+#include "qtestliteclipboard.h"
#ifndef QT_NO_OPENGL
#include <GL/glx.h>
@@ -60,6 +61,7 @@ QT_BEGIN_NAMESPACE
QTestLiteIntegration::QTestLiteIntegration(bool useOpenGL)
: mUseOpenGL(useOpenGL)
, mFontDb(new QGenericUnixFontDatabase())
+ , mClipboard(0)
{
mPrimaryScreen = new QTestLiteScreen();
mScreens.append(mPrimaryScreen);
@@ -114,6 +116,16 @@ QPlatformFontDatabase *QTestLiteIntegration::fontDatabase() const
return mFontDb;
}
+QPlatformClipboard * QTestLiteIntegration::clipboard() const
+{
+ //Use lazy init since clipboard needs QTestliteScreen
+ if (!mClipboard) {
+ QTestLiteIntegration *that = const_cast<QTestLiteIntegration *>(this);
+ that->mClipboard = new QTestLiteClipboard(mPrimaryScreen);
+ }
+ return mClipboard;
+}
+
bool QTestLiteIntegration::hasOpenGL() const
{
#ifndef QT_NO_OPENGL
@@ -123,4 +135,5 @@ bool QTestLiteIntegration::hasOpenGL() const
return false;
}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/testlite/qtestliteintegration.h b/src/plugins/platforms/testlite/qtestliteintegration.h
index 37d09f5..320cf00 100644
--- a/src/plugins/platforms/testlite/qtestliteintegration.h
+++ b/src/plugins/platforms/testlite/qtestliteintegration.h
@@ -48,7 +48,7 @@
#include <QtGui/QPlatformIntegration>
#include <QtGui/QPlatformScreen>
-#include <QtGui/private/qt_x11_p.h>
+#include "qtestlitestaticinfo.h"
QT_BEGIN_NAMESPACE
@@ -68,6 +68,7 @@ public:
QList<QPlatformScreen *> screens() const { return mScreens; }
QPlatformFontDatabase *fontDatabase() const;
+ QPlatformClipboard *clipboard() const;
bool hasOpenGL() const;
@@ -76,6 +77,7 @@ private:
QTestLiteScreen *mPrimaryScreen;
QList<QPlatformScreen *> mScreens;
QPlatformFontDatabase *mFontDb;
+ QPlatformClipboard *mClipboard;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/testlite/qtestlitemime.cpp b/src/plugins/platforms/testlite/qtestlitemime.cpp
new file mode 100644
index 0000000..6261383
--- /dev/null
+++ b/src/plugins/platforms/testlite/qtestlitemime.cpp
@@ -0,0 +1,362 @@
+#include "qtestlitemime.h"
+
+#include "qtestlitestaticinfo.h"
+#include "qtestlitescreen.h"
+
+#include <QtCore/QTextCodec>
+
+QTestLiteMime::QTestLiteMime(QClipboard::Mode mode, QTestLiteClipboard *clipboard)
+ : QInternalMimeData(), m_clipboard(clipboard)
+{
+ switch (mode) {
+ case QClipboard::Selection:
+ modeAtom = XA_PRIMARY;
+ break;
+
+ case QClipboard::Clipboard:
+ modeAtom = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIPBOARD);
+ break;
+
+ default:
+ qWarning("QTestLiteMime: Internal error: Unsupported clipboard mode");
+ break;
+ }
+}
+
+QTestLiteMime::~QTestLiteMime()
+{
+}
+
+bool QTestLiteMime::empty() const
+{
+ Window win = XGetSelectionOwner(m_clipboard->screen()->display(), modeAtom);
+
+ return win == XNone;
+}
+
+QStringList QTestLiteMime::formats_sys() const
+{
+ if (empty())
+ return QStringList();
+
+ if (!formatList.count()) {
+ // get the list of targets from the current clipboard owner - we do this
+ // once so that multiple calls to this function don't require multiple
+ // server round trips...
+
+ format_atoms = m_clipboard->getDataInFormat(modeAtom,QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TARGETS));
+
+ if (format_atoms.size() > 0) {
+ Atom *targets = (Atom *) format_atoms.data();
+ int size = format_atoms.size() / sizeof(Atom);
+
+ for (int i = 0; i < size; ++i) {
+ if (targets[i] == 0)
+ continue;
+
+ QStringList formatsForAtom = xdndMimeFormatsForAtom(m_clipboard->screen()->display(),targets[i]);
+ for (int j = 0; j < formatsForAtom.size(); ++j) {
+ if (!formatList.contains(formatsForAtom.at(j)))
+ formatList.append(formatsForAtom.at(j));
+ }
+ }
+ }
+ }
+
+ return formatList;
+}
+
+bool QTestLiteMime::hasFormat_sys(const QString &format) const
+{
+ QStringList list = formats();
+ return list.contains(format);
+}
+
+QVariant QTestLiteMime::retrieveData_sys(const QString &fmt, QVariant::Type requestedType) const
+{
+ if (fmt.isEmpty() || empty())
+ return QByteArray();
+
+ (void)formats(); // trigger update of format list
+
+ QList<Atom> atoms;
+ Atom *targets = (Atom *) format_atoms.data();
+ int size = format_atoms.size() / sizeof(Atom);
+ for (int i = 0; i < size; ++i)
+ atoms.append(targets[i]);
+
+ QByteArray encoding;
+ Atom fmtatom = xdndMimeAtomForFormat(m_clipboard->screen()->display(),fmt, requestedType, atoms, &encoding);
+
+ if (fmtatom == 0)
+ return QVariant();
+
+ return xdndMimeConvertToFormat(m_clipboard->screen()->display(),fmtatom, m_clipboard->getDataInFormat(modeAtom,fmtatom), fmt, requestedType, encoding);
+}
+
+
+QString QTestLiteMime::xdndMimeAtomToString(Display *display, Atom a)
+{
+ if (!a) return 0;
+
+ if (a == XA_STRING || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING)) {
+ return "text/plain"; // some Xdnd clients are dumb
+ }
+ char *atom = XGetAtomName(display, a);
+ QString result = QString::fromLatin1(atom);
+ XFree(atom);
+ return result;
+}
+
+Atom QTestLiteMime::xdndMimeStringToAtom(Display *display, const QString &mimeType)
+{
+ if (mimeType.isEmpty())
+ return 0;
+ return XInternAtom(display, mimeType.toLatin1().constData(), False);
+}
+
+QStringList QTestLiteMime::xdndMimeFormatsForAtom(Display *display, Atom a)
+{
+ QStringList formats;
+ if (a) {
+ QString atomName = xdndMimeAtomToString(display, a);
+ formats.append(atomName);
+
+ // special cases for string type
+ if (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING)
+ || a == XA_STRING
+ || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT)
+ || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT))
+ formats.append(QLatin1String("text/plain"));
+
+ // special cases for uris
+ if (atomName == QLatin1String("text/x-moz-url"))
+ formats.append(QLatin1String("text/uri-list"));
+
+ // special case for images
+ if (a == XA_PIXMAP)
+ formats.append(QLatin1String("image/ppm"));
+ }
+ return formats;
+}
+
+bool QTestLiteMime::xdndMimeDataForAtom(Display *display, Atom a, QMimeData *mimeData, QByteArray *data, Atom *atomFormat, int *dataFormat)
+{
+ bool ret = false;
+ *atomFormat = a;
+ *dataFormat = 8;
+ QString atomName = xdndMimeAtomToString(display, a);
+ if (QInternalMimeData::hasFormatHelper(atomName, mimeData)) {
+ *data = QInternalMimeData::renderDataHelper(atomName, mimeData);
+ if (atomName == QLatin1String("application/x-color"))
+ *dataFormat = 16;
+ ret = true;
+ } else {
+ if ((a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING)
+ || a == XA_STRING
+ || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT)
+ || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT))
+ && QInternalMimeData::hasFormatHelper(QLatin1String("text/plain"), mimeData)) {
+ if (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING)){
+ *data = QInternalMimeData::renderDataHelper(QLatin1String("text/plain"), mimeData);
+ ret = true;
+ } else if (a == XA_STRING) {
+ *data = QString::fromUtf8(QInternalMimeData::renderDataHelper(
+ QLatin1String("text/plain"), mimeData)).toLocal8Bit();
+ ret = true;
+ } else if (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT)
+ || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)) {
+ // the ICCCM states that TEXT and COMPOUND_TEXT are in the
+ // encoding of choice, so we choose the encoding of the locale
+ QByteArray strData = QString::fromUtf8(QInternalMimeData::renderDataHelper(
+ QLatin1String("text/plain"), mimeData)).toLocal8Bit();
+ char *list[] = { strData.data(), NULL };
+
+ XICCEncodingStyle style = (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT))
+ ? XCompoundTextStyle : XStdICCTextStyle;
+ XTextProperty textprop;
+ if (list[0] != NULL
+ && XmbTextListToTextProperty(display, list, 1, style,
+ &textprop) == Success) {
+ *atomFormat = textprop.encoding;
+ *dataFormat = textprop.format;
+ *data = QByteArray((const char *) textprop.value, textprop.nitems * textprop.format / 8);
+ ret = true;
+
+ XFree(textprop.value);
+ }
+ }
+ } else if (atomName == QLatin1String("text/x-moz-url") &&
+ QInternalMimeData::hasFormatHelper(QLatin1String("text/uri-list"), mimeData)) {
+ QByteArray uri = QInternalMimeData::renderDataHelper(
+ QLatin1String("text/uri-list"), mimeData).split('\n').first();
+ QString mozUri = QString::fromLatin1(uri, uri.size());
+ mozUri += QLatin1Char('\n');
+ *data = QByteArray(reinterpret_cast<const char *>(mozUri.utf16()), mozUri.length() * 2);
+ ret = true;
+ } else if ((a == XA_PIXMAP || a == XA_BITMAP) && mimeData->hasImage()) {
+ QPixmap pm = qvariant_cast<QPixmap>(mimeData->imageData());
+ if (a == XA_BITMAP && pm.depth() != 1) {
+ QImage img = pm.toImage();
+ img = img.convertToFormat(QImage::Format_MonoLSB);
+ pm = QPixmap::fromImage(img);
+ }
+// QDragManager *dm = QDragManager::self();
+// if (dm) {
+// Pixmap handle = pm.handle();
+// *data = QByteArray((const char *) &handle, sizeof(Pixmap));
+// dm->xdndMimeTransferedPixmap[dm->xdndMimeTransferedPixmapIndex] = pm;
+// dm->xdndMimeTransferedPixmapIndex =
+// (dm->xdndMimeTransferedPixmapIndex + 1) % 2;
+// ret = true;
+// }
+ }
+ }
+ return ret && data != 0;
+}
+
+QList<Atom> QTestLiteMime::xdndMimeAtomsForFormat(Display *display, const QString &format)
+{
+ QList<Atom> atoms;
+ atoms.append(xdndMimeStringToAtom(display, format));
+
+ // special cases for strings
+ if (format == QLatin1String("text/plain")) {
+ atoms.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING));
+ atoms.append(XA_STRING);
+ atoms.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT));
+ atoms.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT));
+ }
+
+ // special cases for uris
+ if (format == QLatin1String("text/uri-list")) {
+ atoms.append(xdndMimeStringToAtom(display,QLatin1String("text/x-moz-url")));
+ }
+
+ //special cases for images
+ if (format == QLatin1String("image/ppm"))
+ atoms.append(XA_PIXMAP);
+ if (format == QLatin1String("image/pbm"))
+ atoms.append(XA_BITMAP);
+
+ return atoms;
+}
+
+QVariant QTestLiteMime::xdndMimeConvertToFormat(Display *display, Atom a, const QByteArray &data, const QString &format, QVariant::Type requestedType, const QByteArray &encoding)
+{
+ QString atomName = xdndMimeAtomToString(display,a);
+ if (atomName == format)
+ return data;
+
+ if (!encoding.isEmpty()
+ && atomName == format + QLatin1String(";charset=") + QString::fromLatin1(encoding)) {
+
+ if (requestedType == QVariant::String) {
+ QTextCodec *codec = QTextCodec::codecForName(encoding);
+ if (codec)
+ return codec->toUnicode(data);
+ }
+
+ return data;
+ }
+
+ // special cases for string types
+ if (format == QLatin1String("text/plain")) {
+ if (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING))
+ return QString::fromUtf8(data);
+ if (a == XA_STRING)
+ return QString::fromLatin1(data);
+ if (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT)
+ || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT))
+ // #### might be wrong for COMPUND_TEXT
+ return QString::fromLocal8Bit(data, data.size());
+ }
+
+ // special case for uri types
+ if (format == QLatin1String("text/uri-list")) {
+ if (atomName == QLatin1String("text/x-moz-url")) {
+ // we expect this as utf16 <url><space><title>
+ // the first part is a url that should only contain ascci char
+ // so it should be safe to check that the second char is 0
+ // to verify that it is utf16
+ if (data.size() > 1 && data.at(1) == 0)
+ return QString::fromRawData((const QChar *)data.constData(),
+ data.size() / 2).split(QLatin1Char('\n')).first().toLatin1();
+ }
+ }
+
+ // special cas for images
+ if (format == QLatin1String("image/ppm")) {
+ if (a == XA_PIXMAP && data.size() == sizeof(Pixmap)) {
+// Pixmap xpm = *((Pixmap*)data.data());
+// if (!xpm)
+// return QByteArray();
+// QPixmap qpm = QPixmap::fromX11Pixmap(xpm);
+// QImageWriter imageWriter;
+// imageWriter.setFormat("PPMRAW");
+// QImage imageToWrite = qpm.toImage();
+// QBuffer buf;
+// buf.open(QIODevice::WriteOnly);
+// imageWriter.setDevice(&buf);
+// imageWriter.write(imageToWrite);
+// return buf.buffer();
+ return QVariant();
+ }
+ }
+ return QVariant();
+}
+
+Atom QTestLiteMime::xdndMimeAtomForFormat(Display *display, const QString &format, QVariant::Type requestedType, const QList<Atom> &atoms, QByteArray *requestedEncoding)
+{
+ requestedEncoding->clear();
+
+ // find matches for string types
+ if (format == QLatin1String("text/plain")) {
+ if (atoms.contains(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING)))
+ return QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING);
+ if (atoms.contains(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)))
+ return QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT);
+ if (atoms.contains(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT)))
+ return QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT);
+ if (atoms.contains(XA_STRING))
+ return XA_STRING;
+ }
+
+ // find matches for uri types
+ if (format == QLatin1String("text/uri-list")) {
+ Atom a = xdndMimeStringToAtom(display,format);
+ if (a && atoms.contains(a))
+ return a;
+ a = xdndMimeStringToAtom(display,QLatin1String("text/x-moz-url"));
+ if (a && atoms.contains(a))
+ return a;
+ }
+
+ // find match for image
+ if (format == QLatin1String("image/ppm")) {
+ if (atoms.contains(XA_PIXMAP))
+ return XA_PIXMAP;
+ }
+
+ // for string/text requests try to use a format with a well-defined charset
+ // first to avoid encoding problems
+ if (requestedType == QVariant::String
+ && format.startsWith(QLatin1String("text/"))
+ && !format.contains(QLatin1String("charset="))) {
+
+ QString formatWithCharset = format;
+ formatWithCharset.append(QLatin1String(";charset=utf-8"));
+
+ Atom a = xdndMimeStringToAtom(display,formatWithCharset);
+ if (a && atoms.contains(a)) {
+ *requestedEncoding = "utf-8";
+ return a;
+ }
+ }
+
+ Atom a = xdndMimeStringToAtom(display,format);
+ if (a && atoms.contains(a))
+ return a;
+
+ return 0;
+}
diff --git a/src/plugins/platforms/testlite/qtestlitemime.h b/src/plugins/platforms/testlite/qtestlitemime.h
new file mode 100644
index 0000000..e5ed7b0
--- /dev/null
+++ b/src/plugins/platforms/testlite/qtestlitemime.h
@@ -0,0 +1,42 @@
+#ifndef QTESTLITEMIME_H
+#define QTESTLITEMIME_H
+
+#include <private/qdnd_p.h>
+
+#include <QtGui/QClipboard>
+
+#include "qtestliteintegration.h"
+#include "qtestliteclipboard.h"
+
+class QTestLiteMime : public QInternalMimeData {
+ Q_OBJECT
+public:
+ QTestLiteMime(QClipboard::Mode mode, QTestLiteClipboard *clipboard);
+ ~QTestLiteMime();
+ bool empty() const;
+
+ static QList<Atom> xdndMimeAtomsForFormat(Display *display, const QString &format);
+ static QString xdndMimeAtomToString(Display *display, Atom a);
+ static bool xdndMimeDataForAtom(Display *display, Atom a, QMimeData *mimeData, QByteArray *data, Atom *atomFormat, int *dataFormat);
+ static QStringList xdndMimeFormatsForAtom(Display *display, Atom a);
+ static Atom xdndMimeStringToAtom(Display *display, const QString &mimeType);
+
+ static QVariant xdndMimeConvertToFormat(Display *display, Atom a, const QByteArray &data, const QString &format, QVariant::Type requestedType, const QByteArray &encoding);
+ static Atom xdndMimeAtomForFormat(Display *display, const QString &format, QVariant::Type requestedType, const QList<Atom> &atoms, QByteArray *requestedEncoding);
+
+
+protected:
+ virtual bool hasFormat_sys(const QString &mimetype) const;
+ virtual QStringList formats_sys() const;
+
+ QVariant retrieveData_sys(const QString &mimetype, QVariant::Type type) const;
+
+
+private:
+ QTestLiteClipboard *m_clipboard;
+ Atom modeAtom;
+ mutable QStringList formatList;
+ mutable QByteArray format_atoms;
+};
+
+#endif // QTESTLITEMIME_H
diff --git a/src/plugins/platforms/testlite/qtestlitescreen.cpp b/src/plugins/platforms/testlite/qtestlitescreen.cpp
index c0f696d..2ae7028 100644
--- a/src/plugins/platforms/testlite/qtestlitescreen.cpp
+++ b/src/plugins/platforms/testlite/qtestlitescreen.cpp
@@ -44,9 +44,16 @@
#include "qtestlitecursor.h"
#include "qtestlitewindow.h"
#include "qtestlitekeyboard.h"
+#include "qtestlitestaticinfo.h"
+#include "qtestliteclipboard.h"
#include <QtCore/QDebug>
#include <QtCore/QSocketNotifier>
+#include <QtCore/QElapsedTimer>
+
+#include <private/qapplication_p.h>
+
+#include <X11/extensions/Xfixes.h>
QT_BEGIN_NAMESPACE
@@ -183,11 +190,10 @@ qDebug() << "qt_x_errhandler" << err->error_code;
QTestLiteScreen::QTestLiteScreen()
: mFormat(QImage::Format_RGB32)
- , mWmProtocolsAtom(0)
- , mWmDeleteWindowAtom(0)
{
char *display_name = getenv("DISPLAY");
mDisplay = XOpenDisplay(display_name);
+ mDisplayName = QString::fromLocal8Bit(display_name);
if (!mDisplay) {
fprintf(stderr, "Cannot connect to X server: %s\n",
display_name);
@@ -204,6 +210,7 @@ QTestLiteScreen::QTestLiteScreen()
XSynchronize(mDisplay, true);
mScreen = DefaultScreen(mDisplay);
+ XSelectInput(mDisplay,rootWindow(), KeymapStateMask | EnterWindowMask | LeaveWindowMask | PropertyChangeMask);
int width = DisplayWidth(mDisplay, mScreen);
int height = DisplayHeight(mDisplay, mScreen);
mGeometry = QRect(0,0,width,height);
@@ -221,11 +228,6 @@ QTestLiteScreen::QTestLiteScreen()
QSocketNotifier *sock = new QSocketNotifier(xSocketNumber, QSocketNotifier::Read, this);
connect(sock, SIGNAL(activated(int)), this, SLOT(eventDispatcher()));
- mWmProtocolsAtom = XInternAtom (mDisplay, "WM_PROTOCOLS", False);
- mWmDeleteWindowAtom = XInternAtom (mDisplay, "WM_DELETE_WINDOW", False);
-
- mWmMotifHintAtom = XInternAtom(mDisplay, "_MOTIF_WM_HINTS\0", False);
-
mCursor = new QTestLiteCursor(this);
mKeyboard = new QTestLiteKeyboard(this);
}
@@ -243,9 +245,6 @@ QTestLiteScreen::~QTestLiteScreen()
#undef KeyRelease
#endif
-//Q_GUI_EXPORT extern Atom wmProtocolsAtom;
-//Q_GUI_EXPORT extern Atom wmDeleteWindowAtom;
-
bool QTestLiteScreen::handleEvent(XEvent *xe)
{
int quit = false;
@@ -254,28 +253,17 @@ bool QTestLiteScreen::handleEvent(XEvent *xe)
if (widget) {
xw = static_cast<QTestLiteWindow *>(widget->platformWindow());
}
- if (!xw) {
-#ifdef MYX11_DEBUG
- qWarning() << "Unknown window" << hex << xe->xany.window << "received event" << xe->type;
-#endif
- return quit;
- }
+ Atom wmProtocolsAtom = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::WM_PROTOCOLS);
+ Atom wmDeleteWindowAtom = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::WM_DELETE_WINDOW);
switch (xe->type) {
case ClientMessage:
- if (xe->xclient.format == 32 && xe->xclient.message_type == wmProtocolsAtom()) {
+ if (xe->xclient.format == 32 && xe->xclient.message_type == wmProtocolsAtom) {
Atom a = xe->xclient.data.l[0];
- if (a == wmDeleteWindowAtom())
+ if (a == wmDeleteWindowAtom)
xw->handleCloseEvent();
-#ifdef MYX11_DEBUG
- qDebug() << "ClientMessage WM_PROTOCOLS" << a;
-#endif
}
-#ifdef MYX11_DEBUG
- else
- qDebug() << "ClientMessage" << xe->xclient.format << xe->xclient.message_type;
-#endif
break;
case Expose:
@@ -289,15 +277,18 @@ bool QTestLiteScreen::handleEvent(XEvent *xe)
break;
case ButtonPress:
- xw->mousePressEvent(&xe->xbutton);
+ if (xw)
+ xw->mousePressEvent(&xe->xbutton);
break;
case ButtonRelease:
- xw->handleMouseEvent(QEvent::MouseButtonRelease, &xe->xbutton);
+ if (xw)
+ xw->handleMouseEvent(QEvent::MouseButtonRelease, &xe->xbutton);
break;
case MotionNotify:
- xw->handleMouseEvent(QEvent::MouseMove, &xe->xbutton);
+ if (xw)
+ xw->handleMouseEvent(QEvent::MouseMove, &xe->xbutton);
break;
case XKeyPress:
@@ -309,20 +300,39 @@ bool QTestLiteScreen::handleEvent(XEvent *xe)
break;
case EnterNotify:
- xw->handleEnterEvent();
+ if (xw)
+ xw->handleEnterEvent();
break;
case LeaveNotify:
- xw->handleLeaveEvent();
+ if (xw)
+ xw->handleLeaveEvent();
break;
case XFocusIn:
- xw->handleFocusInEvent();
+ if (xw)
+ xw->handleFocusInEvent();
break;
case XFocusOut:
- xw->handleFocusOutEvent();
+ if (xw)
+ xw->handleFocusOutEvent();
+ break;
+
+ case PropertyNotify:
+ break;
+
+ case SelectionClear:
+ qDebug() << "Selection Clear!!!";
+ break;
+ case SelectionRequest:
+ handleSelectionRequest(xe);
break;
+ case SelectionNotify:
+ qDebug() << "Selection Notify!!!!";
+
+ break;
+
default:
#ifdef MYX11_DEBUG
@@ -330,9 +340,43 @@ bool QTestLiteScreen::handleEvent(XEvent *xe)
#endif
break;
}
+
return quit;
}
+static Bool checkForClipboardEvents(Display *, XEvent *e, XPointer)
+{
+ Atom clipboard = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIPBOARD);
+ return ((e->type == SelectionRequest && (e->xselectionrequest.selection == XA_PRIMARY
+ || e->xselectionrequest.selection == clipboard))
+ || (e->type == SelectionClear && (e->xselectionclear.selection == XA_PRIMARY
+ || e->xselectionclear.selection == clipboard)));
+}
+
+bool QTestLiteScreen::waitForClipboardEvent(Window win, int type, XEvent *event, int timeout)
+{
+ QElapsedTimer timer;
+ timer.start();
+ do {
+ if (XCheckTypedWindowEvent(mDisplay,win,type,event))
+ return true;
+
+ // process other clipboard events, since someone is probably requesting data from us
+ XEvent e;
+ if (XCheckIfEvent(mDisplay, &e, checkForClipboardEvents, 0))
+ handleEvent(&e);
+
+ XFlush(mDisplay);
+
+ // sleep 50 ms, so we don't use up CPU cycles all the time.
+ struct timeval usleep_tv;
+ usleep_tv.tv_sec = 0;
+ usleep_tv.tv_usec = 50000;
+ select(0, 0, 0, 0, &usleep_tv);
+ } while (timer.elapsed() < timeout);
+ return false;
+}
+
void QTestLiteScreen::eventDispatcher()
{
ulong marker = XNextRequest(mDisplay);
@@ -409,29 +453,16 @@ int QTestLiteScreen::xScreenNumber() const
return mScreen;
}
-Atom QTestLiteScreen::wmProtocolsAtom() const
-{
- return mWmProtocolsAtom;
-}
-
-Atom QTestLiteScreen::wmDeleteWindowAtom() const
-{
- return mWmDeleteWindowAtom;
-}
-
-void QTestLiteScreen::setWmDeleteWindowAtom(Atom newDeleteWindowAtom)
-{
- mWmDeleteWindowAtom = newDeleteWindowAtom;
-}
-
-Atom QTestLiteScreen::atomForMotifWmHints() const
+QTestLiteKeyboard * QTestLiteScreen::keyboard() const
{
- return mWmMotifHintAtom;
+ return mKeyboard;
}
-QTestLiteKeyboard * QTestLiteScreen::keyboard() const
+void QTestLiteScreen::handleSelectionRequest(XEvent *event)
{
- return mKeyboard;
+ QPlatformIntegration *integration = QApplicationPrivate::platformIntegration();
+ QTestLiteClipboard *clipboard = static_cast<QTestLiteClipboard *>(integration->clipboard());
+ clipboard->handleSelectionRequest(event);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/testlite/qtestlitescreen.h b/src/plugins/platforms/testlite/qtestlitescreen.h
index 9a1a510..860a67c 100644
--- a/src/plugins/platforms/testlite/qtestlitescreen.h
+++ b/src/plugins/platforms/testlite/qtestlitescreen.h
@@ -58,6 +58,8 @@ public:
~QTestLiteScreen();
+ QString displayName() const { return mDisplayName; }
+
QRect geometry() const { return mGeometry; }
int depth() const { return mDepth; }
QImage::Format format() const { return mFormat; }
@@ -68,6 +70,8 @@ public:
unsigned long whitePixel() { return WhitePixel(mDisplay, mScreen); }
bool handleEvent(XEvent *xe);
+ bool waitForClipboardEvent(Window win, int type, XEvent *event, int timeout);
+
QImage grabWindow(Window window, int x, int y, int w, int h);
static QTestLiteScreen *testLiteScreenForWidget(QWidget *widget);
@@ -75,18 +79,15 @@ public:
Display *display() const;
int xScreenNumber() const;
- Atom wmProtocolsAtom() const;
- Atom wmDeleteWindowAtom() const;
- void setWmDeleteWindowAtom(Atom newDeleteWindowAtom);
-
- Atom atomForMotifWmHints() const;
-
QTestLiteKeyboard *keyboard() const;
public slots:
void eventDispatcher();
private:
+
+ void handleSelectionRequest(XEvent *event);
+ QString mDisplayName;
QRect mGeometry;
QSize mPhysicalSize;
int mDepth;
@@ -96,9 +97,6 @@ private:
Display * mDisplay;
int mScreen;
- Atom mWmProtocolsAtom;
- Atom mWmDeleteWindowAtom;
- Atom mWmMotifHintAtom;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/testlite/qtestlitestaticinfo.cpp b/src/plugins/platforms/testlite/qtestlitestaticinfo.cpp
new file mode 100644
index 0000000..20d73a2
--- /dev/null
+++ b/src/plugins/platforms/testlite/qtestlitestaticinfo.cpp
@@ -0,0 +1,417 @@
+#include "qtestlitestaticinfo.h"
+#include "qtestlitescreen.h"
+
+#include <qplatformdefs.h>
+
+#include <QtGui/private/qapplication_p.h>
+#include <QtCore/QBuffer>
+#include <QtCore/QLibrary>
+
+#include <QDebug>
+
+#ifndef QT_NO_XFIXES
+#include <X11/extensions/Xfixes.h>
+#endif // QT_NO_XFIXES
+
+static const char * x11_atomnames = {
+ // window-manager <-> client protocols
+ "WM_PROTOCOLS\0"
+ "WM_DELETE_WINDOW\0"
+ "WM_TAKE_FOCUS\0"
+ "_NET_WM_PING\0"
+ "_NET_WM_CONTEXT_HELP\0"
+ "_NET_WM_SYNC_REQUEST\0"
+ "_NET_WM_SYNC_REQUEST_COUNTER\0"
+
+ // ICCCM window state
+ "WM_STATE\0"
+ "WM_CHANGE_STATE\0"
+
+ // Session management
+ "WM_CLIENT_LEADER\0"
+ "WM_WINDOW_ROLE\0"
+ "SM_CLIENT_ID\0"
+
+ // Clipboard
+ "CLIPBOARD\0"
+ "INCR\0"
+ "TARGETS\0"
+ "MULTIPLE\0"
+ "TIMESTAMP\0"
+ "SAVE_TARGETS\0"
+ "CLIP_TEMPORARY\0"
+ "_QT_SELECTION\0"
+ "_QT_CLIPBOARD_SENTINEL\0"
+ "_QT_SELECTION_SENTINEL\0"
+ "CLIPBOARD_MANAGER\0"
+
+ "RESOURCE_MANAGER\0"
+
+ "_XSETROOT_ID\0"
+
+ "_QT_SCROLL_DONE\0"
+ "_QT_INPUT_ENCODING\0"
+
+ "_MOTIF_WM_HINTS\0"
+
+ "DTWM_IS_RUNNING\0"
+ "ENLIGHTENMENT_DESKTOP\0"
+ "_DT_SAVE_MODE\0"
+ "_SGI_DESKS_MANAGER\0"
+
+ // EWMH (aka NETWM)
+ "_NET_SUPPORTED\0"
+ "_NET_VIRTUAL_ROOTS\0"
+ "_NET_WORKAREA\0"
+
+ "_NET_MOVERESIZE_WINDOW\0"
+ "_NET_WM_MOVERESIZE\0"
+
+ "_NET_WM_NAME\0"
+ "_NET_WM_ICON_NAME\0"
+ "_NET_WM_ICON\0"
+
+ "_NET_WM_PID\0"
+
+ "_NET_WM_WINDOW_OPACITY\0"
+
+ "_NET_WM_STATE\0"
+ "_NET_WM_STATE_ABOVE\0"
+ "_NET_WM_STATE_BELOW\0"
+ "_NET_WM_STATE_FULLSCREEN\0"
+ "_NET_WM_STATE_MAXIMIZED_HORZ\0"
+ "_NET_WM_STATE_MAXIMIZED_VERT\0"
+ "_NET_WM_STATE_MODAL\0"
+ "_NET_WM_STATE_STAYS_ON_TOP\0"
+ "_NET_WM_STATE_DEMANDS_ATTENTION\0"
+
+ "_NET_WM_USER_TIME\0"
+ "_NET_WM_USER_TIME_WINDOW\0"
+ "_NET_WM_FULL_PLACEMENT\0"
+
+ "_NET_WM_WINDOW_TYPE\0"
+ "_NET_WM_WINDOW_TYPE_DESKTOP\0"
+ "_NET_WM_WINDOW_TYPE_DOCK\0"
+ "_NET_WM_WINDOW_TYPE_TOOLBAR\0"
+ "_NET_WM_WINDOW_TYPE_MENU\0"
+ "_NET_WM_WINDOW_TYPE_UTILITY\0"
+ "_NET_WM_WINDOW_TYPE_SPLASH\0"
+ "_NET_WM_WINDOW_TYPE_DIALOG\0"
+ "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0"
+ "_NET_WM_WINDOW_TYPE_POPUP_MENU\0"
+ "_NET_WM_WINDOW_TYPE_TOOLTIP\0"
+ "_NET_WM_WINDOW_TYPE_NOTIFICATION\0"
+ "_NET_WM_WINDOW_TYPE_COMBO\0"
+ "_NET_WM_WINDOW_TYPE_DND\0"
+ "_NET_WM_WINDOW_TYPE_NORMAL\0"
+ "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0"
+
+ "_KDE_NET_WM_FRAME_STRUT\0"
+
+ "_NET_STARTUP_INFO\0"
+ "_NET_STARTUP_INFO_BEGIN\0"
+
+ "_NET_SUPPORTING_WM_CHECK\0"
+
+ "_NET_WM_CM_S0\0"
+
+ "_NET_SYSTEM_TRAY_VISUAL\0"
+
+ "_NET_ACTIVE_WINDOW\0"
+
+ // Property formats
+ "COMPOUND_TEXT\0"
+ "TEXT\0"
+ "UTF8_STRING\0"
+
+ // xdnd
+ "XdndEnter\0"
+ "XdndPosition\0"
+ "XdndStatus\0"
+ "XdndLeave\0"
+ "XdndDrop\0"
+ "XdndFinished\0"
+ "XdndTypeList\0"
+ "XdndActionList\0"
+
+ "XdndSelection\0"
+
+ "XdndAware\0"
+ "XdndProxy\0"
+
+ "XdndActionCopy\0"
+ "XdndActionLink\0"
+ "XdndActionMove\0"
+ "XdndActionPrivate\0"
+
+ // Motif DND
+ "_MOTIF_DRAG_AND_DROP_MESSAGE\0"
+ "_MOTIF_DRAG_INITIATOR_INFO\0"
+ "_MOTIF_DRAG_RECEIVER_INFO\0"
+ "_MOTIF_DRAG_WINDOW\0"
+ "_MOTIF_DRAG_TARGETS\0"
+
+ "XmTRANSFER_SUCCESS\0"
+ "XmTRANSFER_FAILURE\0"
+
+ // Xkb
+ "_XKB_RULES_NAMES\0"
+
+ // XEMBED
+ "_XEMBED\0"
+ "_XEMBED_INFO\0"
+
+ // Wacom old. (before version 0.10)
+ "Wacom Stylus\0"
+ "Wacom Cursor\0"
+ "Wacom Eraser\0"
+
+ // Tablet
+ "STYLUS\0"
+ "ERASER\0"
+};
+
+/*!
+ \internal
+ Try to resolve a \a symbol from \a library with the version specified
+ by \a vernum.
+
+ Note that, in the case of the Xfixes library, \a vernum is not the same as
+ \c XFIXES_MAJOR - it is a part of soname and may differ from the Xfixes
+ version.
+*/
+static void* qt_load_library_runtime(const char *library, int vernum,
+ int highestVernum, const char *symbol)
+{
+ QList<int> versions;
+ // we try to load in the following order:
+ // explicit version -> the default one -> (from the highest (highestVernum) to the lowest (vernum) )
+ if (vernum != -1)
+ versions << vernum;
+ versions << -1;
+ if (vernum != -1) {
+ for(int i = highestVernum; i > vernum; --i)
+ versions << i;
+ }
+ Q_FOREACH(int version, versions) {
+ QLatin1String libName(library);
+ QLibrary xfixesLib(libName, version);
+ void *ptr = xfixesLib.resolve(symbol);
+ if (ptr)
+ return ptr;
+ }
+ return 0;
+}
+
+# define XFIXES_LOAD_RUNTIME(vernum, symbol, symbol_type) \
+ (symbol_type)qt_load_library_runtime("libXfixes", vernum, 4, #symbol);
+# define XFIXES_LOAD_V1(symbol) \
+ XFIXES_LOAD_RUNTIME(1, symbol, Ptr##symbol)
+# define XFIXES_LOAD_V2(symbol) \
+ XFIXES_LOAD_RUNTIME(2, symbol, Ptr##symbol)
+
+
+class QTestLiteStaticInfoPrivate
+{
+public:
+ QTestLiteStaticInfoPrivate()
+ : use_xfixes(false)
+ , xfixes_major(0)
+ , xfixes_eventbase(0)
+ , xfixes_errorbase(0)
+ {
+ QTestLiteScreen *screen = qobject_cast<QTestLiteScreen *> (QApplicationPrivate::platformIntegration()->screens().at(0));
+ Q_ASSERT(screen);
+
+ initializeAllAtoms(screen);
+ initializeSupportedAtoms(screen);
+
+ resolveXFixes(screen);
+ }
+
+ bool isSupportedByWM(Atom atom)
+ {
+ if (!m_supportedAtoms)
+ return false;
+
+ bool supported = false;
+ int i = 0;
+ while (m_supportedAtoms[i] != 0) {
+ if (m_supportedAtoms[i++] == atom) {
+ supported = true;
+ break;
+ }
+ }
+
+ return supported;
+ }
+
+ Atom atom(QTestLiteStaticInfo::X11Atom atom)
+ {
+ return m_allAtoms[atom];
+ }
+
+ bool useXFixes() const { return use_xfixes; }
+
+ int xFixesEventBase() const {return xfixes_eventbase; }
+
+ PtrXFixesSelectSelectionInput xFixesSelectSelectionInput() const
+ {
+ return ptrXFixesSelectSelectionInput;
+ }
+
+private:
+
+ void initializeAllAtoms(QTestLiteScreen *screen) {
+ const char *names[QTestLiteStaticInfo::NAtoms];
+ const char *ptr = x11_atomnames;
+
+ int i = 0;
+ while (*ptr) {
+ names[i++] = ptr;
+ while (*ptr)
+ ++ptr;
+ ++ptr;
+ }
+
+ Q_ASSERT(i == QTestLiteStaticInfo::NPredefinedAtoms);
+
+ QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_");
+ settings_atom_name += XDisplayName(qPrintable(screen->displayName()));
+ names[i++] = settings_atom_name;
+
+ Q_ASSERT(i == QTestLiteStaticInfo::NAtoms);
+ #if 0//defined(XlibSpecificationRelease) && (XlibSpecificationRelease >= 6)
+ XInternAtoms(screen->display(), (char **)names, i, False, m_allAtoms);
+ #else
+ for (i = 0; i < QTestLiteStaticInfo::NAtoms; ++i)
+ m_allAtoms[i] = XInternAtom(screen->display(), (char *)names[i], False);
+ #endif
+ }
+
+ void initializeSupportedAtoms(QTestLiteScreen *screen)
+ {
+ Atom type;
+ int format;
+ long offset = 0;
+ unsigned long nitems, after;
+ unsigned char *data = 0;
+
+ int e = XGetWindowProperty(screen->display(), screen->rootWindow(),
+ this->atom(QTestLiteStaticInfo::_NET_SUPPORTED), 0, 0,
+ False, XA_ATOM, &type, &format, &nitems, &after, &data);
+ if (data)
+ XFree(data);
+
+ if (e == Success && type == XA_ATOM && format == 32) {
+ QBuffer ts;
+ ts.open(QIODevice::WriteOnly);
+
+ while (after > 0) {
+ XGetWindowProperty(screen->display(), screen->rootWindow(),
+ this->atom(QTestLiteStaticInfo::_NET_SUPPORTED), offset, 1024,
+ False, XA_ATOM, &type, &format, &nitems, &after, &data);
+
+ if (type == XA_ATOM && format == 32) {
+ ts.write(reinterpret_cast<char *>(data), nitems * sizeof(long));
+ offset += nitems;
+ } else
+ after = 0;
+ if (data)
+ XFree(data);
+ }
+
+ // compute nitems
+ QByteArray buffer(ts.buffer());
+ nitems = buffer.size() / sizeof(Atom);
+ m_supportedAtoms = new Atom[nitems + 1];
+ Atom *a = (Atom *) buffer.data();
+ uint i;
+ for (i = 0; i < nitems; i++)
+ m_supportedAtoms[i] = a[i];
+ m_supportedAtoms[nitems] = 0;
+
+ }
+ }
+
+ void resolveXFixes(QTestLiteScreen *screen)
+ {
+#ifndef QT_NO_XFIXES
+ // See if Xfixes is supported on the connected display
+ if (XQueryExtension(screen->display(), "XFIXES", &xfixes_major,
+ &xfixes_eventbase, &xfixes_errorbase)) {
+ ptrXFixesQueryExtension = XFIXES_LOAD_V1(XFixesQueryExtension);
+ ptrXFixesQueryVersion = XFIXES_LOAD_V1(XFixesQueryVersion);
+ ptrXFixesSetCursorName = XFIXES_LOAD_V2(XFixesSetCursorName);
+ ptrXFixesSelectSelectionInput = XFIXES_LOAD_V2(XFixesSelectSelectionInput);
+
+ if(ptrXFixesQueryExtension && ptrXFixesQueryVersion
+ && ptrXFixesQueryExtension(screen->display(), &xfixes_eventbase,
+ &xfixes_errorbase)) {
+ // Xfixes is supported.
+ // Note: the XFixes protocol version is negotiated using QueryVersion.
+ // We supply the highest version we support, the X server replies with
+ // the highest version it supports, but no higher than the version we
+ // asked for. The version sent back is the protocol version the X server
+ // will use to talk us. If this call is removed, the behavior of the
+ // X server when it receives an XFixes request is undefined.
+ int major = 3;
+ int minor = 0;
+ ptrXFixesQueryVersion(screen->display(), &major, &minor);
+ use_xfixes = (major >= 1);
+ xfixes_major = major;
+ }
+ }
+#endif // QT_NO_XFIXES
+
+ }
+
+ Atom *m_supportedAtoms;
+ Atom m_allAtoms[QTestLiteStaticInfo::NAtoms];
+
+#ifndef QT_NO_XFIXES
+ PtrXFixesQueryExtension ptrXFixesQueryExtension;
+ PtrXFixesQueryVersion ptrXFixesQueryVersion;
+ PtrXFixesSetCursorName ptrXFixesSetCursorName;
+ PtrXFixesSelectSelectionInput ptrXFixesSelectSelectionInput;
+#endif
+
+ bool use_xfixes;
+ int xfixes_major;
+ int xfixes_eventbase;
+ int xfixes_errorbase;
+
+};
+Q_GLOBAL_STATIC(QTestLiteStaticInfoPrivate, qTestLiteStaticInfoPrivate);
+
+
+Atom QTestLiteStaticInfo::atom(QTestLiteStaticInfo::X11Atom atom)
+{
+ return qTestLiteStaticInfoPrivate()->atom(atom);
+}
+
+bool QTestLiteStaticInfo::isSupportedByWM(Atom atom)
+{
+ return qTestLiteStaticInfoPrivate()->isSupportedByWM(atom);
+}
+
+bool QTestLiteStaticInfo::useXFixes()
+{
+ return qTestLiteStaticInfoPrivate()->useXFixes();
+}
+
+int QTestLiteStaticInfo::xFixesEventBase()
+{
+ return qTestLiteStaticInfoPrivate()->xFixesEventBase();
+}
+
+#ifndef QT_NO_XFIXES
+PtrXFixesSelectSelectionInput QTestLiteStaticInfo::xFixesSelectSelectionInput()
+{
+ qDebug() << qTestLiteStaticInfoPrivate()->useXFixes();
+ if (!qTestLiteStaticInfoPrivate()->useXFixes())
+ return 0;
+
+ return qTestLiteStaticInfoPrivate()->xFixesSelectSelectionInput();
+}
+#endif //QT_NO_XFIXES
diff --git a/src/plugins/platforms/testlite/qtestlitestaticinfo.h b/src/plugins/platforms/testlite/qtestlitestaticinfo.h
new file mode 100644
index 0000000..ed0f7bd
--- /dev/null
+++ b/src/plugins/platforms/testlite/qtestlitestaticinfo.h
@@ -0,0 +1,371 @@
+#ifndef QTESTLITESTATICINFO_H
+#define QTESTLITESTATICINFO_H
+
+#include <QtCore/QTextStream>
+#include <QtCore/QDataStream>
+#include <QtCore/QMetaType>
+#include <QtCore/QVariant>
+
+#if defined(_XLIB_H_) // crude hack, but...
+#error "cannot include <X11/Xlib.h> before this file"
+#endif
+#define XRegisterIMInstantiateCallback qt_XRegisterIMInstantiateCallback
+#define XUnregisterIMInstantiateCallback qt_XUnregisterIMInstantiateCallback
+#define XSetIMValues qt_XSetIMValues
+#include <X11/Xlib.h>
+#undef XRegisterIMInstantiateCallback
+#undef XUnregisterIMInstantiateCallback
+#undef XSetIMValues
+
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#ifdef index
+# undef index
+#endif
+#ifdef rindex
+# undef rindex
+#endif
+#ifdef Q_OS_VXWORS
+# ifdef open
+# undef open
+# endif
+# ifdef getpid
+# undef getpid
+# endif
+#endif // Q_OS_VXWORKS
+#include <X11/Xatom.h>
+
+//#define QT_NO_SHAPE
+#ifdef QT_NO_SHAPE
+# define XShapeCombineRegion(a,b,c,d,e,f,g)
+# define XShapeCombineMask(a,b,c,d,e,f,g)
+#else
+# include <X11/extensions/shape.h>
+#endif // QT_NO_SHAPE
+
+
+#if !defined (QT_NO_TABLET)
+# include <X11/extensions/XInput.h>
+#if defined (Q_OS_IRIX)
+# include <X11/extensions/SGIMisc.h>
+# include <wacom.h>
+#endif
+#endif // QT_NO_TABLET
+
+
+// #define QT_NO_XINERAMA
+#ifndef QT_NO_XINERAMA
+// XFree86 does not C++ify Xinerama (at least up to XFree86 4.0.3).
+extern "C" {
+# include <X11/extensions/Xinerama.h>
+}
+#endif // QT_NO_XINERAMA
+
+// #define QT_NO_XRANDR
+#ifndef QT_NO_XRANDR
+# include <X11/extensions/Xrandr.h>
+#endif // QT_NO_XRANDR
+
+// #define QT_NO_XRENDER
+#ifndef QT_NO_XRENDER
+# include <X11/extensions/Xrender.h>
+#endif // QT_NO_XRENDER
+
+#ifndef QT_NO_XSYNC
+extern "C" {
+# include "X11/extensions/sync.h"
+}
+#endif
+
+// #define QT_NO_XKB
+#ifndef QT_NO_XKB
+# include <X11/XKBlib.h>
+#endif // QT_NO_XKB
+
+
+#if !defined(XlibSpecificationRelease)
+# define X11R4
+typedef char *XPointer;
+#else
+# undef X11R4
+#endif
+
+#ifndef QT_NO_XFIXES
+typedef Bool (*PtrXFixesQueryExtension)(Display *, int *, int *);
+typedef Status (*PtrXFixesQueryVersion)(Display *, int *, int *);
+typedef void (*PtrXFixesSetCursorName)(Display *dpy, Cursor cursor, const char *name);
+typedef void (*PtrXFixesSelectSelectionInput)(Display *dpy, Window win, Atom selection, unsigned long eventMask);
+#endif // QT_NO_XFIXES
+
+#ifndef QT_NO_XCURSOR
+#include <X11/Xcursor/Xcursor.h>
+typedef Cursor (*PtrXcursorLibraryLoadCursor)(Display *, const char *);
+#endif // QT_NO_XCURSOR
+
+#ifndef QT_NO_XINERAMA
+typedef Bool (*PtrXineramaQueryExtension)(Display *dpy, int *event_base, int *error_base);
+typedef Bool (*PtrXineramaIsActive)(Display *dpy);
+typedef XineramaScreenInfo *(*PtrXineramaQueryScreens)(Display *dpy, int *number);
+#endif // QT_NO_XINERAMA
+
+#ifndef QT_NO_XRANDR
+typedef void (*PtrXRRSelectInput)(Display *, Window, int);
+typedef int (*PtrXRRUpdateConfiguration)(XEvent *);
+typedef int (*PtrXRRRootToScreen)(Display *, Window);
+typedef Bool (*PtrXRRQueryExtension)(Display *, int *, int *);
+#endif // QT_NO_XRANDR
+
+#ifndef QT_NO_XINPUT
+typedef int (*PtrXCloseDevice)(Display *, XDevice *);
+typedef XDeviceInfo* (*PtrXListInputDevices)(Display *, int *);
+typedef XDevice* (*PtrXOpenDevice)(Display *, XID);
+typedef void (*PtrXFreeDeviceList)(XDeviceInfo *);
+typedef int (*PtrXSelectExtensionEvent)(Display *, Window, XEventClass *, int);
+#endif // QT_NO_XINPUT
+
+/*
+ * Solaris patch 108652-47 and higher fixes crases in
+ * XRegisterIMInstantiateCallback, but the function doesn't seem to
+ * work.
+ *
+ * Instead, we disabled R6 input, and open the input method
+ * immediately at application start.
+ */
+
+//######### XFree86 has wrong declarations for XRegisterIMInstantiateCallback
+//######### and XUnregisterIMInstantiateCallback in at least version 3.3.2.
+//######### Many old X11R6 header files lack XSetIMValues.
+//######### Therefore, we have to declare these functions ourselves.
+
+extern "C" Bool XRegisterIMInstantiateCallback(
+ Display*,
+ struct _XrmHashBucketRec*,
+ char*,
+ char*,
+ XIMProc, //XFree86 has XIDProc, which has to be wrong
+ XPointer
+);
+
+extern "C" Bool XUnregisterIMInstantiateCallback(
+ Display*,
+ struct _XrmHashBucketRec*,
+ char*,
+ char*,
+ XIMProc, //XFree86 has XIDProc, which has to be wrong
+ XPointer
+);
+
+#ifndef X11R4
+# include <X11/Xlocale.h>
+#endif // X11R4
+
+
+#ifndef QT_NO_MITSHM
+# include <X11/extensions/XShm.h>
+#endif // QT_NO_MITSHM
+
+// rename a couple of X defines to get rid of name clashes
+// resolve the conflict between X11's FocusIn and QEvent::FocusIn
+enum {
+ XFocusOut = FocusOut,
+ XFocusIn = FocusIn,
+ XKeyPress = KeyPress,
+ XKeyRelease = KeyRelease,
+ XNone = None,
+ XRevertToParent = RevertToParent,
+ XGrayScale = GrayScale,
+ XCursorShape = CursorShape
+};
+#undef FocusOut
+#undef FocusIn
+#undef KeyPress
+#undef KeyRelease
+#undef None
+#undef RevertToParent
+#undef GrayScale
+#undef CursorShape
+
+#ifdef FontChange
+#undef FontChange
+#endif
+
+
+class QTestLiteStaticInfo
+{
+public:
+ enum X11Atom {
+ // window-manager <-> client protocols
+ WM_PROTOCOLS,
+ WM_DELETE_WINDOW,
+ WM_TAKE_FOCUS,
+ _NET_WM_PING,
+ _NET_WM_CONTEXT_HELP,
+ _NET_WM_SYNC_REQUEST,
+ _NET_WM_SYNC_REQUEST_COUNTER,
+
+ // ICCCM window state
+ WM_STATE,
+ WM_CHANGE_STATE,
+
+ // Session management
+ WM_CLIENT_LEADER,
+ WM_WINDOW_ROLE,
+ SM_CLIENT_ID,
+
+ // Clipboard
+ CLIPBOARD,
+ INCR,
+ TARGETS,
+ MULTIPLE,
+ TIMESTAMP,
+ SAVE_TARGETS,
+ CLIP_TEMPORARY,
+ _QT_SELECTION,
+ _QT_CLIPBOARD_SENTINEL,
+ _QT_SELECTION_SENTINEL,
+ CLIPBOARD_MANAGER,
+
+ RESOURCE_MANAGER,
+
+ _XSETROOT_ID,
+
+ _QT_SCROLL_DONE,
+ _QT_INPUT_ENCODING,
+
+ _MOTIF_WM_HINTS,
+
+ DTWM_IS_RUNNING,
+ ENLIGHTENMENT_DESKTOP,
+ _DT_SAVE_MODE,
+ _SGI_DESKS_MANAGER,
+
+ // EWMH (aka NETWM)
+ _NET_SUPPORTED,
+ _NET_VIRTUAL_ROOTS,
+ _NET_WORKAREA,
+
+ _NET_MOVERESIZE_WINDOW,
+ _NET_WM_MOVERESIZE,
+
+ _NET_WM_NAME,
+ _NET_WM_ICON_NAME,
+ _NET_WM_ICON,
+
+ _NET_WM_PID,
+
+ _NET_WM_WINDOW_OPACITY,
+
+ _NET_WM_STATE,
+ _NET_WM_STATE_ABOVE,
+ _NET_WM_STATE_BELOW,
+ _NET_WM_STATE_FULLSCREEN,
+ _NET_WM_STATE_MAXIMIZED_HORZ,
+ _NET_WM_STATE_MAXIMIZED_VERT,
+ _NET_WM_STATE_MODAL,
+ _NET_WM_STATE_STAYS_ON_TOP,
+ _NET_WM_STATE_DEMANDS_ATTENTION,
+
+ _NET_WM_USER_TIME,
+ _NET_WM_USER_TIME_WINDOW,
+ _NET_WM_FULL_PLACEMENT,
+
+ _NET_WM_WINDOW_TYPE,
+ _NET_WM_WINDOW_TYPE_DESKTOP,
+ _NET_WM_WINDOW_TYPE_DOCK,
+ _NET_WM_WINDOW_TYPE_TOOLBAR,
+ _NET_WM_WINDOW_TYPE_MENU,
+ _NET_WM_WINDOW_TYPE_UTILITY,
+ _NET_WM_WINDOW_TYPE_SPLASH,
+ _NET_WM_WINDOW_TYPE_DIALOG,
+ _NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
+ _NET_WM_WINDOW_TYPE_POPUP_MENU,
+ _NET_WM_WINDOW_TYPE_TOOLTIP,
+ _NET_WM_WINDOW_TYPE_NOTIFICATION,
+ _NET_WM_WINDOW_TYPE_COMBO,
+ _NET_WM_WINDOW_TYPE_DND,
+ _NET_WM_WINDOW_TYPE_NORMAL,
+ _KDE_NET_WM_WINDOW_TYPE_OVERRIDE,
+
+ _KDE_NET_WM_FRAME_STRUT,
+
+ _NET_STARTUP_INFO,
+ _NET_STARTUP_INFO_BEGIN,
+
+ _NET_SUPPORTING_WM_CHECK,
+
+ _NET_WM_CM_S0,
+
+ _NET_SYSTEM_TRAY_VISUAL,
+
+ _NET_ACTIVE_WINDOW,
+
+ // Property formats
+ COMPOUND_TEXT,
+ TEXT,
+ UTF8_STRING,
+
+ // Xdnd
+ XdndEnter,
+ XdndPosition,
+ XdndStatus,
+ XdndLeave,
+ XdndDrop,
+ XdndFinished,
+ XdndTypelist,
+ XdndActionList,
+
+ XdndSelection,
+
+ XdndAware,
+ XdndProxy,
+
+ XdndActionCopy,
+ XdndActionLink,
+ XdndActionMove,
+ XdndActionPrivate,
+
+ // Motif DND
+ _MOTIF_DRAG_AND_DROP_MESSAGE,
+ _MOTIF_DRAG_INITIATOR_INFO,
+ _MOTIF_DRAG_RECEIVER_INFO,
+ _MOTIF_DRAG_WINDOW,
+ _MOTIF_DRAG_TARGETS,
+
+ XmTRANSFER_SUCCESS,
+ XmTRANSFER_FAILURE,
+
+ // Xkb
+ _XKB_RULES_NAMES,
+
+ // XEMBED
+ _XEMBED,
+ _XEMBED_INFO,
+
+ XWacomStylus,
+ XWacomCursor,
+ XWacomEraser,
+
+ XTabletStylus,
+ XTabletEraser,
+
+ NPredefinedAtoms,
+
+ _QT_SETTINGS_TIMESTAMP = NPredefinedAtoms,
+ NAtoms
+ };
+
+ static Atom atom(X11Atom atom);
+ static bool isSupportedByWM(Atom atom);
+
+ static bool useXFixes();
+ static int xFixesEventBase();
+
+ #ifndef QT_NO_XFIXES
+ static PtrXFixesSelectSelectionInput xFixesSelectSelectionInput();
+ #endif //QT_NO_XFIXES
+
+
+
+};
+
+#endif // QTESTLITESTATICINFO_H
diff --git a/src/plugins/platforms/testlite/qtestlitewindow.cpp b/src/plugins/platforms/testlite/qtestlitewindow.cpp
index 6f9ad58..71232ac 100644
--- a/src/plugins/platforms/testlite/qtestlitewindow.cpp
+++ b/src/plugins/platforms/testlite/qtestlitewindow.cpp
@@ -44,6 +44,7 @@
#include "qtestliteintegration.h"
#include "qtestlitescreen.h"
#include "qtestlitekeyboard.h"
+#include "qtestlitestaticinfo.h"
#include <QtGui/QWindowSystemInterface>
#include <QSocketNotifier>
@@ -101,19 +102,26 @@ QTestLiteWindow::QTestLiteWindow(QWidget *window)
XSetWindowBackgroundPixmap(mScreen->display(), x_window, XNone);
- XSelectInput(mScreen->display(), x_window, ExposureMask | KeyPressMask | KeyReleaseMask |
+ XSelectInput(mScreen->display(), x_window,
+ ExposureMask | KeyPressMask | KeyReleaseMask |
EnterWindowMask | LeaveWindowMask | FocusChangeMask |
- PointerMotionMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
+ PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
+ ButtonMotionMask | PropertyChangeMask |
StructureNotifyMask);
gc = createGC();
- Atom wmDeleteWindowAtom = mScreen->wmDeleteWindowAtom();
- XChangeProperty (mScreen->display(), x_window,
- mScreen->wmProtocolsAtom(),
- XA_ATOM, 32, PropModeAppend,
- (unsigned char *) &wmDeleteWindowAtom, 1);
- mScreen->setWmDeleteWindowAtom(wmDeleteWindowAtom);
+ Atom protocols[5];
+ int n = 0;
+ protocols[n++] = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::WM_DELETE_WINDOW); // support del window protocol
+ protocols[n++] = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::WM_TAKE_FOCUS); // support take focus window protocol
+ protocols[n++] = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_NET_WM_PING); // support _NET_WM_PING protocol
+#ifndef QT_NO_XSYNC
+ protocols[n++] = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol
+#endif // QT_NO_XSYNC
+ if (window->windowFlags() & Qt::WindowContextHelpButtonHint)
+ protocols[n++] = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_NET_WM_CONTEXT_HELP);
+ XSetWMProtocols(mScreen->display(), x_window, protocols, n);
}
@@ -336,10 +344,11 @@ QtMWMHints QTestLiteWindow::getMWMHints() const
int format;
ulong nitems, bytesLeft;
uchar *data = 0;
- if ((XGetWindowProperty(mScreen->display(), x_window, mScreen->atomForMotifWmHints(), 0, 5, false,
- mScreen->atomForMotifWmHints(), &type, &format, &nitems, &bytesLeft,
+ Atom atomForMotifWmHints = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_MOTIF_WM_HINTS);
+ if ((XGetWindowProperty(mScreen->display(), x_window, atomForMotifWmHints, 0, 5, false,
+ atomForMotifWmHints, &type, &format, &nitems, &bytesLeft,
&data) == Success)
- && (type == mScreen->atomForMotifWmHints()
+ && (type == atomForMotifWmHints
&& format == 32
&& nitems >= 5)) {
mwmhints = *(reinterpret_cast<QtMWMHints *>(data));
@@ -359,12 +368,13 @@ QtMWMHints QTestLiteWindow::getMWMHints() const
void QTestLiteWindow::setMWMHints(const QtMWMHints &mwmhints)
{
+ Atom atomForMotifWmHints = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_MOTIF_WM_HINTS);
if (mwmhints.flags != 0l) {
XChangeProperty(mScreen->display(), x_window,
- mScreen->atomForMotifWmHints(), mScreen->atomForMotifWmHints(), 32,
+ atomForMotifWmHints, atomForMotifWmHints, 32,
PropModeReplace, (unsigned char *) &mwmhints, 5);
} else {
- XDeleteProperty(mScreen->display(), x_window, mScreen->atomForMotifWmHints());
+ XDeleteProperty(mScreen->display(), x_window, atomForMotifWmHints);
}
}
diff --git a/src/plugins/platforms/testlite/testlite.pro b/src/plugins/platforms/testlite/testlite.pro
index d2f2562..9f8075c 100644
--- a/src/plugins/platforms/testlite/testlite.pro
+++ b/src/plugins/platforms/testlite/testlite.pro
@@ -10,7 +10,10 @@ SOURCES = \
qtestlitewindow.cpp \
qtestlitecursor.cpp \
qtestlitescreen.cpp \
- qtestlitekeyboard.cpp
+ qtestlitekeyboard.cpp \
+ qtestliteclipboard.cpp \
+ qtestlitemime.cpp \
+ qtestlitestaticinfo.cpp
HEADERS = \
qtestliteintegration.h \
@@ -18,7 +21,10 @@ HEADERS = \
qtestlitewindow.h \
qtestlitecursor.h \
qtestlitescreen.h \
- qtestlitekeyboard.h
+ qtestlitekeyboard.h \
+ qtestliteclipboard.h \
+ qtestlitemime.h \
+ qtestlitestaticinfo.h
LIBS += -lX11 -lXext