diff options
author | Laszlo Agocs <laszlo.p.agocs@nokia.com> | 2011-05-06 16:36:43 (GMT) |
---|---|---|
committer | Jørgen Lind <jorgen.lind@nokia.com> | 2011-05-09 11:48:04 (GMT) |
commit | 5e3240f53720921bbcb869cd5a4b35167b087505 (patch) | |
tree | 24522fa02615d4abe35f1a6ad8baaceee893686d /src | |
parent | eb0c2e7229bb3559e6f8754122b298479407c153 (diff) | |
download | Qt-5e3240f53720921bbcb869cd5a4b35167b087505.zip Qt-5e3240f53720921bbcb869cd5a4b35167b087505.tar.gz Qt-5e3240f53720921bbcb869cd5a4b35167b087505.tar.bz2 |
Added Wayland selection support.
Messed up when I cherry-picked eb0c2e7229bb3559e6f8754122b298479407c153
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandclipboard.cpp | 242 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandclipboard.h | 86 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/wayland.pro | 2 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/xcb.pro | 2 | ||||
-rw-r--r-- | src/plugins/platforms/xlib/xlib.pro | 2 |
5 files changed, 334 insertions, 0 deletions
diff --git a/src/plugins/platforms/wayland/qwaylandclipboard.cpp b/src/plugins/platforms/wayland/qwaylandclipboard.cpp new file mode 100644 index 0000000..9c533aa --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandclipboard.cpp @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** 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 "qwaylandclipboard.h" +#include "qwaylanddisplay.h" +#include "qwaylandinputdevice.h" +#include <QtGui/QPlatformNativeInterface> +#include <QtGui/QApplication> +#include <QtCore/QMimeData> +#include <QtCore/QStringList> +#include <QtCore/QFile> +#include <QtCore/QtDebug> + +static QWaylandClipboard *clipboard; + +class QWaylandSelection +{ +public: + QWaylandSelection(QWaylandDisplay *display, QMimeData *data); + ~QWaylandSelection(); + +private: + static uint32_t getTime(); + static void send(void *data, struct wl_selection *selection, const char *mime_type, int fd); + static void cancelled(void *data, struct wl_selection *selection); + static const struct wl_selection_listener selectionListener; + + QMimeData *mMimeData; + struct wl_selection *mSelection; +}; + +const struct wl_selection_listener QWaylandSelection::selectionListener = { + QWaylandSelection::send, + QWaylandSelection::cancelled +}; + +uint32_t QWaylandSelection::getTime() +{ + struct timeval tv; + gettimeofday(&tv, 0); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +QWaylandSelection::QWaylandSelection(QWaylandDisplay *display, QMimeData *data) + : mMimeData(data), mSelection(0) +{ + struct wl_shell *shell = display->wl_shell(); + mSelection = wl_shell_create_selection(shell); + wl_selection_add_listener(mSelection, &selectionListener, this); + foreach (const QString &format, data->formats()) + wl_selection_offer(mSelection, format.toLatin1().constData()); + wl_selection_activate(mSelection, + display->inputDevices().at(0)->wl_input_device(), + getTime()); +} + +QWaylandSelection::~QWaylandSelection() +{ + if (mSelection) { + clipboard->unregisterSelection(this); + wl_selection_destroy(mSelection); + } + delete mMimeData; +} + +void QWaylandSelection::send(void *data, + struct wl_selection *selection, + const char *mime_type, + int fd) +{ + Q_UNUSED(selection); + QWaylandSelection *self = static_cast<QWaylandSelection *>(data); + QString mimeType = QString::fromLatin1(mime_type); + QByteArray content = self->mMimeData->data(mimeType); + if (!content.isEmpty()) { + QFile f; + if (f.open(fd, QIODevice::WriteOnly)) + f.write(content); + } + close(fd); +} + +void QWaylandSelection::cancelled(void *data, struct wl_selection *selection) +{ + Q_UNUSED(selection); + delete static_cast<QWaylandSelection *>(data); +} + +QWaylandClipboard::QWaylandClipboard(QWaylandDisplay *display) + : mDisplay(display), mSelection(0), mMimeDataIn(0), mOffer(0) +{ + clipboard = this; +} + +QWaylandClipboard::~QWaylandClipboard() +{ + if (mOffer) + wl_selection_offer_destroy(mOffer); + delete mMimeDataIn; + qDeleteAll(mSelections); +} + +void QWaylandClipboard::unregisterSelection(QWaylandSelection *selection) +{ + mSelections.removeOne(selection); +} + +void QWaylandClipboard::syncCallback(void *data) +{ + *static_cast<bool *>(data) = true; +} + +void QWaylandClipboard::forceRoundtrip(struct wl_display *display) +{ + bool done = false; + wl_display_sync_callback(display, syncCallback, &done); + wl_display_iterate(display, WL_DISPLAY_WRITABLE); + while (!done) + wl_display_iterate(display, WL_DISPLAY_READABLE); +} + +const QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode) const +{ + Q_ASSERT(mode == QClipboard::Clipboard); + if (!mMimeDataIn) + mMimeDataIn = new QMimeData; + mMimeDataIn->clear(); + if (!mOfferedMimeTypes.isEmpty() && mOffer) { + foreach (const QString &mimeType, mOfferedMimeTypes) { + int pipefd[2]; + if (pipe(pipefd) == -1) { + qWarning("QWaylandClipboard::mimedata: pipe() failed"); + break; + } + QByteArray mimeTypeBa = mimeType.toLatin1(); + wl_selection_offer_receive(mOffer, mimeTypeBa.constData(), pipefd[1]); + QByteArray content; + forceRoundtrip(mDisplay->wl_display()); + char buf[256]; + int n; + close(pipefd[1]); + while ((n = read(pipefd[0], &buf, sizeof buf)) > 0) + content.append(buf, n); + close(pipefd[0]); + mMimeDataIn->setData(mimeType, content); + } + } + return mMimeDataIn; +} + +void QWaylandClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) +{ + Q_ASSERT(mode == QClipboard::Clipboard); + if (!mDisplay->inputDevices().isEmpty()) { + if (!data) + data = new QMimeData; + mSelection = new QWaylandSelection(mDisplay, data); + } else { + qWarning("QWaylandClipboard::setMimeData: No input devices"); + } +} + +bool QWaylandClipboard::supportsMode(QClipboard::Mode mode) const +{ + return mode == QClipboard::Clipboard; +} + +const struct wl_selection_offer_listener QWaylandClipboard::selectionOfferListener = { + QWaylandClipboard::offer, + QWaylandClipboard::keyboardFocus +}; + +void QWaylandClipboard::createSelectionOffer(uint32_t id) +{ + mOfferedMimeTypes.clear(); + if (mOffer) + wl_selection_offer_destroy(mOffer); + mOffer = 0; + struct wl_selection_offer *offer = wl_selection_offer_create(mDisplay->wl_display(), id, 1); + wl_selection_offer_add_listener(offer, &selectionOfferListener, this); +} + +void QWaylandClipboard::offer(void *data, + struct wl_selection_offer *selection_offer, + const char *type) +{ + Q_UNUSED(selection_offer); + QWaylandClipboard *self = static_cast<QWaylandClipboard *>(data); + self->mOfferedMimeTypes.append(QString::fromLatin1(type)); +} + +void QWaylandClipboard::keyboardFocus(void *data, + struct wl_selection_offer *selection_offer, + wl_input_device *input_device) +{ + QWaylandClipboard *self = static_cast<QWaylandClipboard *>(data); + if (!input_device) { + wl_selection_offer_destroy(selection_offer); + self->mOffer = 0; + return; + } + self->mOffer = selection_offer; + self->emitChanged(QClipboard::Clipboard); +} diff --git a/src/plugins/platforms/wayland/qwaylandclipboard.h b/src/plugins/platforms/wayland/qwaylandclipboard.h new file mode 100644 index 0000000..606a1f6 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandclipboard.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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 QWAYLANDCLIPBOARD_H +#define QWAYLANDCLIPBOARD_H + +#include <QtGui/QPlatformClipboard> +#include <QtCore/QStringList> + +class QWaylandDisplay; +class QWaylandSelection; +struct wl_selection_offer; + +class QWaylandClipboard : public QPlatformClipboard +{ +public: + QWaylandClipboard(QWaylandDisplay *display); + ~QWaylandClipboard(); + + const QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) const; + void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard); + bool supportsMode(QClipboard::Mode mode) const; + + void unregisterSelection(QWaylandSelection *selection); + + void createSelectionOffer(uint32_t id); + +private: + static void offer(void *data, + struct wl_selection_offer *selection_offer, + const char *type); + static void keyboardFocus(void *data, + struct wl_selection_offer *selection_offer, + struct wl_input_device *input_device); + static const struct wl_selection_offer_listener selectionOfferListener; + + static void syncCallback(void *data); + static void forceRoundtrip(struct wl_display *display); + + QWaylandDisplay *mDisplay; + QWaylandSelection *mSelection; + mutable QMimeData *mMimeDataIn; + QList<QWaylandSelection *> mSelections; + QStringList mOfferedMimeTypes; + struct wl_selection_offer *mOffer; +}; + +#endif // QWAYLANDCLIPBOARD_H diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro index 76f8be5..1303fcd 100644 --- a/src/plugins/platforms/wayland/wayland.pro +++ b/src/plugins/platforms/wayland/wayland.pro @@ -6,6 +6,8 @@ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms DEFINES += Q_PLATFORM_WAYLAND DEFINES += $$QMAKE_DEFINES_WAYLAND +QT += core-private gui-private opengl-private + SOURCES = main.cpp \ qwaylandintegration.cpp \ qwaylandnativeinterface.cpp \ diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro index 101bdcd..139f5c9 100644 --- a/src/plugins/platforms/xcb/xcb.pro +++ b/src/plugins/platforms/xcb/xcb.pro @@ -3,6 +3,8 @@ TARGET = xcb include(../../qpluginbase.pri) QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms +QT += core-private gui-private + SOURCES = \ qxcbconnection.cpp \ qxcbintegration.cpp \ diff --git a/src/plugins/platforms/xlib/xlib.pro b/src/plugins/platforms/xlib/xlib.pro index ea77a29..ffce14b 100644 --- a/src/plugins/platforms/xlib/xlib.pro +++ b/src/plugins/platforms/xlib/xlib.pro @@ -3,6 +3,8 @@ TARGET = qxlib include(../../qpluginbase.pri) QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms +QT += core-private gui-private opengl-private + SOURCES = \ main.cpp \ qxlibintegration.cpp \ |