summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2011-05-22 22:23:48 +0200
committerLars Knoll <lars.knoll@nokia.com>2011-05-30 14:44:12 +0200
commit1b1142b305c9664dd9d3d9544a9db5b5e4b6bd08 (patch)
treee92c63636371a79730a0ea78ab3df361ec3b222f
parent1d3864488cb2ae4b105948d6569d08c477f77d80 (diff)
Add xcb based mime type handling
Reworked the code from the xlib lighthouse plugin to remove most of the Xlib dependencies. The code originally comdes from qdnd_x11.cpp
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp31
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbmime.cpp311
-rw-r--r--src/plugins/platforms/xcb/qxcbmime.h68
-rw-r--r--src/plugins/platforms/xcb/xcb.pro2
5 files changed, 415 insertions, 2 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index da6e69eb36..bdd18500a3 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -583,9 +583,12 @@ static const char * xcb_atomnames = {
"_NET_ACTIVE_WINDOW\0"
// Property formats
+ "XA_STRING\0"
"COMPOUND_TEXT\0"
"TEXT\0"
"UTF8_STRING\0"
+ "XA_PIXMAP\0"
+ "XA_BITMAP\0"
// xdnd
"XdndEnter\0"
@@ -663,8 +666,32 @@ void QXcbConnection::initializeAllAtoms() {
for (i = 0; i < QXcbAtom::NAtoms; ++i)
cookies[i] = xcb_intern_atom(xcb_connection(), false, strlen(names[i]), names[i]);
- for (i = 0; i < QXcbAtom::NAtoms; ++i)
- m_allAtoms[i] = xcb_intern_atom_reply(xcb_connection(), cookies[i], 0)->atom;
+ for (i = 0; i < QXcbAtom::NAtoms; ++i) {
+ xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookies[i], 0);
+ m_allAtoms[i] = reply->atom;
+ free(reply);
+ }
+}
+
+xcb_atom_t QXcbConnection::internAtom(const char *name)
+{
+ if (!name || *name == 0)
+ return XCB_NONE;
+
+ xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_connection(), false, strlen(name), name);
+ xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookie, 0);
+ int atom = reply->atom;
+ free(reply);
+ return atom;
+}
+
+QByteArray QXcbConnection::atomName(xcb_atom_t atom)
+{
+ xcb_get_atom_name_cookie_t cookie = xcb_get_atom_name_unchecked(xcb_connection(), atom);
+ xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(xcb_connection(), cookie, 0);
+ QByteArray result(xcb_get_atom_name_name(reply));
+ free(reply);
+ return result;
}
void QXcbConnection::sync()
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 23c704f6de..124b8512ea 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -164,9 +164,12 @@ namespace QXcbAtom {
_NET_ACTIVE_WINDOW,
// Property formats
+ XA_STRING,
COMPOUND_TEXT,
TEXT,
UTF8_STRING,
+ XA_PIXMAP,
+ XA_BITMAP,
// Xdnd
XdndEnter,
@@ -234,6 +237,8 @@ public:
int primaryScreen() const { return m_primaryScreen; }
xcb_atom_t atom(QXcbAtom::Atom atom);
+ xcb_atom_t internAtom(const char *name);
+ QByteArray atomName(xcb_atom_t atom);
const char *displayName() const { return m_displayName.constData(); }
diff --git a/src/plugins/platforms/xcb/qxcbmime.cpp b/src/plugins/platforms/xcb/qxcbmime.cpp
new file mode 100644
index 0000000000..311a909447
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbmime.cpp
@@ -0,0 +1,311 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxcbmime.h"
+
+#include <QtCore/QTextCodec>
+#include <QtGui/QImageWriter>
+#include <QtCore/QBuffer>
+
+#include <X11/Xutil.h>
+
+#undef XA_STRING
+#undef XA_PIXMAP
+#undef XA_BITMAP
+
+QXcbMime::QXcbMime()
+ : QInternalMimeData()
+{ }
+
+QXcbMime::~QXcbMime()
+{}
+
+
+
+QString QXcbMime::mimeAtomToString(QXcbConnection *connection, xcb_atom_t a)
+{
+ if (a == XCB_NONE)
+ return 0;
+
+ // special cases for string type
+ if (a == connection->atom(QXcbAtom::XA_STRING)
+ || a == connection->atom(QXcbAtom::UTF8_STRING)
+ || a == connection->atom(QXcbAtom::TEXT)
+ || a == connection->atom(QXcbAtom::COMPOUND_TEXT))
+ return QLatin1String("text/plain");
+
+ // special case for images
+ if (a == connection->atom(QXcbAtom::XA_PIXMAP))
+ return QLatin1String("image/ppm");
+
+ QByteArray atomName = connection->atomName(a);
+
+ // special cases for uris
+ if (atomName == "text/x-moz-url")
+ atomName = "text/uri-list";
+
+ return QString::fromLatin1(atomName.constData());
+}
+
+bool QXcbMime::mimeDataForAtom(QXcbConnection *connection, xcb_atom_t a, QMimeData *mimeData, QByteArray *data,
+ xcb_atom_t *atomFormat, int *dataFormat)
+{
+ if (!data)
+ return false;
+
+ bool ret = false;
+ *atomFormat = a;
+ *dataFormat = 8;
+
+ if ((a == connection->atom(QXcbAtom::UTF8_STRING)
+ || a == connection->atom(QXcbAtom::XA_STRING)
+ || a == connection->atom(QXcbAtom::TEXT)
+ || a == connection->atom(QXcbAtom::COMPOUND_TEXT))
+ && QInternalMimeData::hasFormatHelper(QLatin1String("text/plain"), mimeData)) {
+ if (a == connection->atom(QXcbAtom::UTF8_STRING)){
+ *data = QInternalMimeData::renderDataHelper(QLatin1String("text/plain"), mimeData);
+ ret = true;
+ } else if (a == connection->atom(QXcbAtom::XA_STRING)) {
+ *data = QString::fromUtf8(QInternalMimeData::renderDataHelper(
+ QLatin1String("text/plain"), mimeData)).toLocal8Bit();
+ ret = true;
+ } else if (a == connection->atom(QXcbAtom::TEXT)
+ || a == connection->atom(QXcbAtom::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 == connection->atom(QXcbAtom::COMPOUND_TEXT))
+ ? XCompoundTextStyle : XStdICCTextStyle;
+ XTextProperty textprop;
+ if (list[0] != NULL
+ && XmbTextListToTextProperty(DISPLAY_FROM_XCB(connection), 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);
+ }
+ }
+ return ret;
+ }
+
+ QString atomName = mimeAtomToString(connection, a);
+ if (QInternalMimeData::hasFormatHelper(atomName, mimeData)) {
+ *data = QInternalMimeData::renderDataHelper(atomName, mimeData);
+ if (atomName == QLatin1String("application/x-color"))
+ *dataFormat = 16;
+ ret = true;
+ } 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 == connection->atom(QXcbAtom::XA_PIXMAP) || a == connection->atom(QXcbAtom::XA_BITMAP)) && mimeData->hasImage()) {
+ ret = true;
+ }
+ return ret;
+}
+
+QList<xcb_atom_t> QXcbMime::mimeAtomsForFormat(QXcbConnection *connection, const QString &format)
+{
+ QList<xcb_atom_t> atoms;
+ atoms.append(connection->internAtom(format.toLatin1()));
+
+ // special cases for strings
+ if (format == QLatin1String("text/plain")) {
+ atoms.append(connection->atom(QXcbAtom::UTF8_STRING));
+ atoms.append(connection->atom(QXcbAtom::XA_STRING));
+ atoms.append(connection->atom(QXcbAtom::TEXT));
+ atoms.append(connection->atom(QXcbAtom::COMPOUND_TEXT));
+ }
+
+ // special cases for uris
+ if (format == QLatin1String("text/uri-list"))
+ atoms.append(connection->internAtom("text/x-moz-url"));
+
+ //special cases for images
+ if (format == QLatin1String("image/ppm"))
+ atoms.append(connection->atom(QXcbAtom::XA_PIXMAP));
+ if (format == QLatin1String("image/pbm"))
+ atoms.append(connection->atom(QXcbAtom::XA_BITMAP));
+
+ return atoms;
+}
+
+QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a, const QByteArray &data, const QString &format,
+ QVariant::Type requestedType, const QByteArray &encoding)
+{
+ QString atomName = mimeAtomToString(connection, 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 == connection->atom(QXcbAtom::UTF8_STRING))
+ return QString::fromUtf8(data);
+ if (a == connection->atom(QXcbAtom::XA_STRING))
+ return QString::fromLatin1(data);
+ if (a == connection->atom(QXcbAtom::TEXT)
+ || a == connection->atom(QXcbAtom::COMPOUND_TEXT))
+ // #### might be wrong for COMPOUND_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();
+ }
+ }
+
+#if 0 // ###
+ // special case for images
+ if (format == QLatin1String("image/ppm")) {
+ if (a == XA_PIXMAP && data.size() == sizeof(Pixmap)) {
+ Pixmap xpm = *((Pixmap*)data.data());
+ if (!xpm)
+ return QByteArray();
+ Window root;
+ int x;
+ int y;
+ uint width;
+ uint height;
+ uint border_width;
+ uint depth;
+
+ XGetGeometry(display, xpm, &root, &x, &y, &width, &height, &border_width, &depth);
+ XImage *ximg = XGetImage(display,xpm,x,y,width,height,AllPlanes,depth==1 ? XYPixmap : ZPixmap);
+ QImage qimg = QXlibStatic::qimageFromXImage(ximg);
+ XDestroyImage(ximg);
+
+ QImageWriter imageWriter;
+ imageWriter.setFormat("PPMRAW");
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ imageWriter.setDevice(&buf);
+ imageWriter.write(qimg);
+ return buf.buffer();
+ }
+ }
+#endif
+ return QVariant();
+}
+
+xcb_atom_t QXcbMime::mimeAtomForFormat(QXcbConnection *connection, const QString &format, QVariant::Type requestedType,
+ const QList<xcb_atom_t> &atoms, QByteArray *requestedEncoding)
+{
+ requestedEncoding->clear();
+
+ // find matches for string types
+ if (format == QLatin1String("text/plain")) {
+ if (atoms.contains(connection->atom(QXcbAtom::UTF8_STRING)))
+ return connection->atom(QXcbAtom::UTF8_STRING);
+ if (atoms.contains(connection->atom(QXcbAtom::COMPOUND_TEXT)))
+ return connection->atom(QXcbAtom::COMPOUND_TEXT);
+ if (atoms.contains(connection->atom(QXcbAtom::TEXT)))
+ return connection->atom(QXcbAtom::TEXT);
+ if (atoms.contains(connection->atom(QXcbAtom::XA_STRING)))
+ return connection->atom(QXcbAtom::XA_STRING);
+ }
+
+ // find matches for uri types
+ if (format == QLatin1String("text/uri-list")) {
+ xcb_atom_t a = connection->internAtom(format.toLatin1());
+ if (a && atoms.contains(a))
+ return a;
+ a = connection->internAtom("text/x-moz-url");
+ if (a && atoms.contains(a))
+ return a;
+ }
+
+ // find match for image
+ if (format == QLatin1String("image/ppm")) {
+ if (atoms.contains(connection->atom(QXcbAtom::XA_PIXMAP)))
+ return connection->atom(QXcbAtom::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"));
+
+ xcb_atom_t a = connection->internAtom(formatWithCharset.toLatin1());
+ if (a && atoms.contains(a)) {
+ *requestedEncoding = "utf-8";
+ return a;
+ }
+ }
+
+ xcb_atom_t a = connection->internAtom(format.toLatin1());
+ if (a && atoms.contains(a))
+ return a;
+
+ return 0;
+}
diff --git a/src/plugins/platforms/xcb/qxcbmime.h b/src/plugins/platforms/xcb/qxcbmime.h
new file mode 100644
index 0000000000..4ab38ed803
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbmime.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXCBMIME_H
+#define QXCBMIME_H
+
+#include <private/qdnd_p.h>
+
+#include <QtGui/QClipboard>
+
+#include "qxcbintegration.h"
+#include "qxcbconnection.h"
+
+class QXcbMime : public QInternalMimeData {
+ Q_OBJECT
+public:
+ QXcbMime();
+ ~QXcbMime();
+
+ static QList<xcb_atom_t> mimeAtomsForFormat(QXcbConnection *connection, const QString &format);
+ static QString mimeAtomToString(QXcbConnection *connection, xcb_atom_t a);
+ static bool mimeDataForAtom(QXcbConnection *connection, xcb_atom_t a, QMimeData *mimeData, QByteArray *data,
+ xcb_atom_t *atomFormat, int *dataFormat);
+ static QVariant mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a, const QByteArray &data, const QString &format,
+ QVariant::Type requestedType, const QByteArray &encoding);
+ static xcb_atom_t mimeAtomForFormat(QXcbConnection *connection, const QString &format, QVariant::Type requestedType,
+ const QList<xcb_atom_t> &atoms, QByteArray *requestedEncoding);
+};
+
+#endif // QXCBMIME_H
diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro
index c6bf17f0ef..6dd69c0643 100644
--- a/src/plugins/platforms/xcb/xcb.pro
+++ b/src/plugins/platforms/xcb/xcb.pro
@@ -9,6 +9,7 @@ SOURCES = \
qxcbconnection.cpp \
qxcbintegration.cpp \
qxcbkeyboard.cpp \
+ qxcbmime.cpp \
qxcbscreen.cpp \
qxcbwindow.cpp \
qxcbwindowsurface.cpp \
@@ -19,6 +20,7 @@ HEADERS = \
qxcbconnection.h \
qxcbintegration.h \
qxcbkeyboard.h \
+ qxcbmime.h \
qxcbobject.h \
qxcbscreen.h \
qxcbwindow.h \