summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorJan Arne Petersen <jan.petersen@kdab.com>2013-11-01 11:23:54 +0100
committerJørgen Lind <jorgen.lind@digia.com>2013-11-22 15:46:31 +0100
commit26c303e9f6ac741421d654c6a3d7528aca2e1858 (patch)
tree1024a1c3060a289b7df99b2566abc5c78a06fd4c /src/plugins/platforms
parent1364863db8110c31e252de8ccbae71eb95671a7e (diff)
Implement Drag&Drop support in platform plugin
Change-Id: I54d12c338fb6f07292e9e99f3a20fc4667a0e186 Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/wayland_common/qwaylandclipboard.cpp46
-rw-r--r--src/plugins/platforms/wayland_common/qwaylandclipboard.h9
-rw-r--r--src/plugins/platforms/wayland_common/qwaylanddatadevice.cpp242
-rw-r--r--src/plugins/platforms/wayland_common/qwaylanddatadevice.h97
-rw-r--r--src/plugins/platforms/wayland_common/qwaylanddatadevicemanager.cpp262
-rw-r--r--src/plugins/platforms/wayland_common/qwaylanddatadevicemanager.h66
-rw-r--r--src/plugins/platforms/wayland_common/qwaylanddataoffer.cpp90
-rw-r--r--src/plugins/platforms/wayland_common/qwaylanddataoffer.h52
-rw-r--r--src/plugins/platforms/wayland_common/qwaylanddatasource.cpp73
-rw-r--r--src/plugins/platforms/wayland_common/qwaylanddatasource.h34
-rw-r--r--src/plugins/platforms/wayland_common/qwaylanddisplay.h1
-rw-r--r--src/plugins/platforms/wayland_common/qwaylanddnd.cpp71
-rw-r--r--src/plugins/platforms/wayland_common/qwaylanddnd.h22
-rw-r--r--src/plugins/platforms/wayland_common/qwaylandinputdevice.cpp63
-rw-r--r--src/plugins/platforms/wayland_common/qwaylandinputdevice.h11
-rw-r--r--src/plugins/platforms/wayland_common/wayland_common.pro6
16 files changed, 615 insertions, 530 deletions
diff --git a/src/plugins/platforms/wayland_common/qwaylandclipboard.cpp b/src/plugins/platforms/wayland_common/qwaylandclipboard.cpp
index 4cf055d30..838f6d231 100644
--- a/src/plugins/platforms/wayland_common/qwaylandclipboard.cpp
+++ b/src/plugins/platforms/wayland_common/qwaylandclipboard.cpp
@@ -44,7 +44,7 @@
#include "qwaylandinputdevice.h"
#include "qwaylanddataoffer.h"
#include "qwaylanddatasource.h"
-#include "qwaylanddatadevicemanager.h"
+#include "qwaylanddatadevice.h"
QT_BEGIN_NAMESPACE
@@ -59,22 +59,36 @@ QWaylandClipboard::~QWaylandClipboard()
QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode)
{
- Q_ASSERT(mode == QClipboard::Clipboard);
- if (!mDisplay->dndSelectionHandler())
+ if (mode != QClipboard::Clipboard)
return 0;
- QWaylandDataSource *transfer_source = mDisplay->dndSelectionHandler()->selectionTransferSource();
- if (transfer_source) { //if we have the keyboard focus and selectionTransferSource then we own the clipboard
- return transfer_source->mimeData();
+ QWaylandInputDevice *inputDevice = mDisplay->currentInputDevice();
+ if (!inputDevice || !inputDevice->dataDevice())
+ return 0;
+
+ QWaylandDataSource *source = inputDevice->dataDevice()->selectionSource();
+ if (source) {
+ return source->mimeData();
}
- return mDisplay->dndSelectionHandler()->selectionTransfer();
+
+ if (inputDevice->dataDevice()->selectionOffer())
+ return inputDevice->dataDevice()->selectionOffer()->mimeData();
+
+ return 0;
}
void QWaylandClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
{
- Q_ASSERT(mode == QClipboard::Clipboard);
- if (mDisplay->dndSelectionHandler())
- mDisplay->dndSelectionHandler()->createAndSetSelectionSource(data,mode);
+ if (mode != QClipboard::Clipboard)
+ return;
+
+ QWaylandInputDevice *inputDevice = mDisplay->currentInputDevice();
+ if (!inputDevice || !inputDevice->dataDevice())
+ return;
+
+ inputDevice->dataDevice()->setSelectionSource(data ? new QWaylandDataSource(mDisplay->dndSelectionHandler(), data) : 0);
+
+ emitChanged(mode);
}
bool QWaylandClipboard::supportsMode(QClipboard::Mode mode) const
@@ -82,4 +96,16 @@ bool QWaylandClipboard::supportsMode(QClipboard::Mode mode) const
return mode == QClipboard::Clipboard;
}
+bool QWaylandClipboard::ownsMode(QClipboard::Mode mode) const
+{
+ if (mode != QClipboard::Clipboard)
+ return false;
+
+ QWaylandInputDevice *inputDevice = mDisplay->currentInputDevice();
+ if (!inputDevice || !inputDevice->dataDevice())
+ return false;
+
+ return inputDevice->dataDevice()->selectionSource() != 0;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland_common/qwaylandclipboard.h b/src/plugins/platforms/wayland_common/qwaylandclipboard.h
index a8f52e107..f1b1800e3 100644
--- a/src/plugins/platforms/wayland_common/qwaylandclipboard.h
+++ b/src/plugins/platforms/wayland_common/qwaylandclipboard.h
@@ -56,11 +56,10 @@ public:
~QWaylandClipboard();
- QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard);
- void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard);
- bool supportsMode(QClipboard::Mode mode) const;
-
- QVariant retrieveData(const QString &mimeType, QVariant::Type type) const;
+ QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
+ void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
+ bool supportsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
+ bool ownsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
private:
QWaylandDisplay *mDisplay;
diff --git a/src/plugins/platforms/wayland_common/qwaylanddatadevice.cpp b/src/plugins/platforms/wayland_common/qwaylanddatadevice.cpp
new file mode 100644
index 000000000..2a70a338c
--- /dev/null
+++ b/src/plugins/platforms/wayland_common/qwaylanddatadevice.cpp
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Compositor.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylanddatadevice.h"
+
+#include "qwaylanddatadevicemanager.h"
+#include "qwaylanddataoffer.h"
+#include "qwaylanddatasource.h"
+#include "qwaylanddnd.h"
+#include "qwaylandinputdevice.h"
+
+#include <QtCore/QMimeData>
+#include <QtGui/QGuiApplication>
+#include <QtGui/private/qguiapplication_p.h>
+
+#include <qpa/qplatformclipboard.h>
+#include <qpa/qplatformdrag.h>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <QDebug>
+
+QWaylandDataDevice::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWaylandInputDevice *inputDevice)
+ : QtWayland::wl_data_device(manager->get_data_device(inputDevice->wl_seat()))
+ , m_display(manager->display())
+ , m_enterSerial(0)
+ , m_dragWindow(0)
+ , m_dragPoint()
+ , m_dragOffer()
+ , m_selectionOffer()
+{
+}
+
+QWaylandDataDevice::~QWaylandDataDevice()
+{
+}
+
+QWaylandDataOffer *QWaylandDataDevice::selectionOffer() const
+{
+ return m_selectionOffer.data();
+}
+
+QWaylandDataSource *QWaylandDataDevice::selectionSource() const
+{
+ return m_selectionSource.data();
+}
+
+void QWaylandDataDevice::setSelectionSource(QWaylandDataSource *source)
+{
+ m_selectionSource.reset(source);
+ set_selection(source ? source->object() : 0, 0 /* TODO m_display->serial() */);
+}
+
+QWaylandDataOffer *QWaylandDataDevice::dragOffer() const
+{
+ return m_dragOffer.data();
+}
+
+void QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
+{
+ m_dragSource.reset(new QWaylandDataSource(m_display->dndSelectionHandler(), mimeData));
+
+ QWaylandWindow *origin = m_display->currentInputDevice()->pointerFocus();
+
+ start_drag(m_dragSource->object(), origin->object(), icon->object(), m_display->currentInputDevice()->serial());
+}
+
+void QWaylandDataDevice::cancelDrag()
+{
+ m_dragSource.reset();
+}
+
+void QWaylandDataDevice::data_device_data_offer(struct ::wl_data_offer *id)
+{
+ QWaylandDataOffer *offer = new QWaylandDataOffer(m_display, id);
+}
+
+void QWaylandDataDevice::data_device_drop()
+{
+ QDrag *drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->currentDrag();
+
+ qDebug() << Q_FUNC_INFO << drag << m_dragOffer.data();
+
+ QMimeData *dragData;
+ Qt::DropActions supportedActions;
+ if (drag) {
+ dragData = drag->mimeData();
+ supportedActions = drag->supportedActions();
+ } else if (m_dragOffer) {
+ dragData = m_dragOffer->mimeData();
+ supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
+ } else {
+ return;
+ }
+
+ QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(m_dragWindow, dragData, m_dragPoint, supportedActions);
+
+ if (drag) {
+ static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag(response);
+ }
+}
+
+void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface, wl_fixed_t x, wl_fixed_t y, wl_data_offer *id)
+{
+ m_enterSerial = serial;
+ m_dragWindow = QWaylandWindow::fromWlSurface(surface)->window();
+ m_dragPoint = QPoint(wl_fixed_to_int(x), wl_fixed_to_int(y));
+
+ QDrag *drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->currentDrag();
+
+ QMimeData *dragData;
+ Qt::DropActions supportedActions;
+ if (drag) {
+ dragData = drag->mimeData();
+ supportedActions = drag->supportedActions();
+ } else {
+ m_dragOffer.reset(static_cast<QWaylandDataOffer *>(wl_data_offer_get_user_data(id)));
+ if (m_dragOffer) {
+ dragData = m_dragOffer->mimeData();
+ supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
+ }
+ }
+
+ const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions);
+
+ if (drag) {
+ static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
+ } else {
+ if (response.isAccepted()) {
+ wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, m_dragOffer->firstFormat().toUtf8().constData());
+ } else {
+ wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, 0);
+ }
+ }
+}
+
+void QWaylandDataDevice::data_device_leave()
+{
+ QWindowSystemInterface::handleDrag(m_dragWindow, 0, QPoint(), Qt::IgnoreAction);
+
+ QDrag *drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->currentDrag();
+ if (!drag) {
+ m_dragOffer.reset();
+ }
+}
+
+void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixed_t y)
+{
+ Q_UNUSED(time);
+
+ QDrag *drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->currentDrag();
+
+ if (!drag && !m_dragOffer)
+ return;
+
+ m_dragPoint = QPoint(wl_fixed_to_int(x), wl_fixed_to_int(y));
+
+ QMimeData *dragData;
+ Qt::DropActions supportedActions;
+ if (drag) {
+ dragData = drag->mimeData();
+ supportedActions = drag->supportedActions();
+ } else {
+ dragData = m_dragOffer->mimeData();
+ supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
+ }
+
+ QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions);
+
+ if (drag) {
+ static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
+ } else {
+ if (response.isAccepted()) {
+ wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, m_dragOffer->firstFormat().toUtf8().constData());
+ } else {
+ wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, 0);
+ }
+ }
+}
+
+void QWaylandDataDevice::data_device_selection(wl_data_offer *id)
+{
+ if (id)
+ m_selectionOffer.reset(static_cast<QWaylandDataOffer *>(wl_data_offer_get_user_data(id)));
+ else
+ m_selectionOffer.reset();
+
+ QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
+}
+
+void QWaylandDataDevice::selectionSourceCancelled()
+{
+ m_selectionSource.reset();
+ QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
+}
+
+void QWaylandDataDevice::dragSourceCancelled()
+{
+ m_dragSource.reset();
+
+}
+
+void QWaylandDataDevice::dragSourceTargetChanged(const QString &mimeType)
+{
+ static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->updateTarget(mimeType);
+}
diff --git a/src/plugins/platforms/wayland_common/qwaylanddatadevice.h b/src/plugins/platforms/wayland_common/qwaylanddatadevice.h
new file mode 100644
index 000000000..e258d8776
--- /dev/null
+++ b/src/plugins/platforms/wayland_common/qwaylanddatadevice.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Compositor.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDDATADEVICE_H
+#define QWAYLANDDATADEVICE_H
+
+#include "qwaylanddisplay.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMimeData;
+class QWaylandDataDeviceManager;
+class QWaylandDataOffer;
+class QWaylandDataSource;
+class QWindow;
+
+class QWaylandDataDevice : public QObject, public QtWayland::wl_data_device
+{
+ Q_OBJECT
+public:
+ QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWaylandInputDevice *inputDevice);
+ ~QWaylandDataDevice();
+
+ QWaylandDataOffer *selectionOffer() const;
+ QWaylandDataSource *selectionSource() const;
+ void setSelectionSource(QWaylandDataSource *source);
+
+ QWaylandDataOffer *dragOffer() const;
+ void startDrag(QMimeData *mimeData, QWaylandWindow *icon);
+ void cancelDrag();
+
+protected:
+ void data_device_data_offer(struct ::wl_data_offer *id) Q_DECL_OVERRIDE;
+ void data_device_drop() Q_DECL_OVERRIDE;
+ void data_device_enter(uint32_t serial, struct ::wl_surface *surface, wl_fixed_t x, wl_fixed_t y, struct ::wl_data_offer *id) Q_DECL_OVERRIDE;
+ void data_device_leave() Q_DECL_OVERRIDE;
+ void data_device_motion(uint32_t time, wl_fixed_t x, wl_fixed_t y) Q_DECL_OVERRIDE;
+ void data_device_selection(struct ::wl_data_offer *id) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void selectionSourceCancelled();
+ void dragSourceCancelled();
+ void dragSourceTargetChanged(const QString &mimeType);
+
+private:
+ QWaylandDisplay *m_display;
+
+ uint32_t m_enterSerial;
+ QWindow *m_dragWindow;
+ QPoint m_dragPoint;
+ QScopedPointer<QWaylandDataOffer> m_dragOffer;
+ QScopedPointer<QWaylandDataOffer> m_selectionOffer;
+ QScopedPointer<QWaylandDataSource> m_selectionSource;
+
+ QScopedPointer<QWaylandDataSource> m_dragSource;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDDATADEVICE_H
diff --git a/src/plugins/platforms/wayland_common/qwaylanddatadevicemanager.cpp b/src/plugins/platforms/wayland_common/qwaylanddatadevicemanager.cpp
index 8674aae9e..4a96dbce3 100644
--- a/src/plugins/platforms/wayland_common/qwaylanddatadevicemanager.cpp
+++ b/src/plugins/platforms/wayland_common/qwaylanddatadevicemanager.cpp
@@ -42,285 +42,39 @@
#include "qwaylanddatadevicemanager.h"
#include "qwaylandinputdevice.h"
+#include "qwaylanddatadevice.h"
#include "qwaylanddataoffer.h"
-#include "qwaylanddatasource.h"
-#include "qwaylandshmbackingstore.h"
-
-#include <wayland-client-protocol.h>
-#include <wayland-client.h>
-
-#include <QtGui/QGuiApplication>
-#include <QtGui/private/qguiapplication_p.h>
-#include <qpa/qplatformclipboard.h>
-#include <QtGui/QPainter>
-
-#include <qpa/qwindowsysteminterface.h>
#include <QtCore/QDebug>
QT_BEGIN_NAMESPACE
-void QWaylandDataDeviceManager::data_offer(void *data,
- struct wl_data_device *data_device,
- struct wl_data_offer *id)
-{
- Q_UNUSED(data_device);
- QWaylandDataDeviceManager *handler = static_cast<QWaylandDataDeviceManager *>(data);
-
- new QWaylandDataOffer(handler->display(),id);
-}
-
-void QWaylandDataDeviceManager::enter(void *data,
- struct wl_data_device *wl_data_device,
- uint32_t time,
- struct wl_surface *surface,
- wl_fixed_t x,
- wl_fixed_t y,
- struct wl_data_offer *id)
-{
-
- Q_UNUSED(wl_data_device);
- Q_UNUSED(x);
- Q_UNUSED(y);
- QWaylandDataDeviceManager *data_device_manager = static_cast<QWaylandDataDeviceManager *>(data);
- if (time < data_device_manager->m_drag_last_event_time)
- return;
- data_device_manager->m_drag_last_event_time = time;
-
- data_device_manager->m_drag_current_event_window = QWaylandWindow::fromWlSurface(surface);
- if (!surface)
- return;
- QWaylandDataOffer *offer = static_cast<QWaylandDataOffer *>(wl_data_offer_get_user_data(id));
- if (!offer)
- return;
-
-// QPoint point(x,y);
-// Qt::DropActions allActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
-// QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(data_device_manager->m_drag_current_event_window->window(),
-// offer,point,allActions);
-// data_device_manager->m_drag_can_drop = response.accepted();
- data_device_manager->m_drag_data_offer = offer;
- if (data_device_manager->m_drag_can_drop) {
- const char *first_offer = qPrintable(offer->formats_sys().at(0));
- wl_data_offer_accept(offer->handle(),QWaylandDisplay::currentTimeMillisec(),first_offer);
- } else {
- wl_data_offer_accept(offer->handle(),QWaylandDisplay::currentTimeMillisec(),0);
- }
-}
-
-void QWaylandDataDeviceManager::leave(void *data,
- struct wl_data_device *wl_data_device)
-{
- Q_UNUSED(wl_data_device);
- QWaylandDataDeviceManager *data_device_manager = static_cast<QWaylandDataDeviceManager *>(data);
-// QWindowSystemInterface::handleDrag(data_device_manager->m_drag_current_event_window->window(),0,QPoint(0,0),Qt::IgnoreAction);
- data_device_manager->m_drag_can_drop = false;
- data_device_manager->m_drag_data_offer = 0;
- data_device_manager->m_drag_last_event_time = 0;
- data_device_manager->m_drag_current_event_window = 0;
- data_device_manager->m_drag_position = QPoint();
-}
-
-void QWaylandDataDeviceManager::motion(void *data,
- struct wl_data_device *wl_data_device,
- uint32_t time,
- wl_fixed_t x,
- wl_fixed_t y)
-{
- Q_UNUSED(wl_data_device);
- QWaylandDataDeviceManager *data_device_manager = static_cast<QWaylandDataDeviceManager *>(data);
- if (time < data_device_manager->m_drag_last_event_time)
- return;
- data_device_manager->m_drag_position = QPoint(wl_fixed_to_int(x), wl_fixed_to_int(y));
-
-// Qt::DropActions allActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
-// QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(data_device_manager->m_drag_current_event_window->window(),
-// data_device_manager->m_drag_data_offer, data_device_manager->m_drag_position ,allActions);
-// data_device_manager->m_drag_can_drop = response.accepted();
- const char *offerMime = 0;
- if (data_device_manager->m_drag_can_drop) {
- offerMime = qPrintable(data_device_manager->m_drag_data_offer->formats_sys().at(0));
- }
- wl_data_offer_accept(data_device_manager->m_drag_data_offer->handle(),QWaylandDisplay::currentTimeMillisec(),offerMime);
-}
-
-void QWaylandDataDeviceManager::drop(void *data,
- struct wl_data_device *wl_data_device)
-{
- Q_UNUSED(wl_data_device);
- QWaylandDataDeviceManager *data_device_manager = static_cast<QWaylandDataDeviceManager *>(data);
- QWindow *window = data_device_manager->m_drag_current_event_window->window();
- QMimeData *mime = data_device_manager->m_drag_data_offer;
-// QPoint point = data_device_manager->m_drag_position;
-// Qt::DropActions allActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
-
- Q_UNUSED(window);
- Q_UNUSED(mime);
-// QWindowSystemInterface::handleDrop(window,mime,point,allActions);
-}
-
-
-void QWaylandDataDeviceManager::selection(void *data,
- struct wl_data_device *wl_data_device,
- struct wl_data_offer *id)
-{
- Q_UNUSED(wl_data_device);
-
- QWaylandDataDeviceManager *handler = static_cast<QWaylandDataDeviceManager *>(data);
- QWaylandDataOffer *mime = handler->m_selection_data_offer;
- delete mime;
- QWaylandDataSource *transfer_source = handler->m_selection_data_source;
- delete transfer_source;
- handler->m_selection_data_source = 0;
-
- if (id) {
- mime = static_cast<QWaylandDataOffer *>(wl_data_offer_get_user_data(id));
- handler->m_selection_data_offer = mime;
- } else {
- handler->m_selection_data_offer = 0;
- }
-
- QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
-}
-
-const struct wl_data_device_listener QWaylandDataDeviceManager::transfer_device_listener = {
- QWaylandDataDeviceManager::data_offer,
- QWaylandDataDeviceManager::enter,
- QWaylandDataDeviceManager::leave,
- QWaylandDataDeviceManager::motion,
- QWaylandDataDeviceManager::drop,
- QWaylandDataDeviceManager::selection
-};
-
QWaylandDataDeviceManager::QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id)
- : m_display(display)
- , m_selection_data_offer(0)
- , m_selection_data_source(0)
- , m_drag_data_offer(0)
- , m_drag_data_source(0)
- , m_drag_surface(0)
- , m_drag_icon_surface(0)
- , m_drag_icon_buffer(0)
- , m_drag_can_drop(false)
+ : wl_data_device_manager(display->wl_registry(), id)
+ , m_display(display)
{
- m_data_device_manager = static_cast<struct wl_data_device_manager *>(wl_registry_bind(display->wl_registry(),id,&wl_data_device_manager_interface,1));
-
// Create transfer devices for all input devices.
// ### This only works if we get the global before all devices and is surely wrong when hotplugging.
QList<QWaylandInputDevice *> inputDevices = m_display->inputDevices();
for (int i = 0; i < inputDevices.size();i++) {
- inputDevices.at(i)->setTransferDevice(getDataDevice(inputDevices.at(i)));
+ inputDevices.at(i)->setDataDevice(getDataDevice(inputDevices.at(i)));
}
}
QWaylandDataDeviceManager::~QWaylandDataDeviceManager()
{
- wl_data_device_manager_destroy(m_data_device_manager);
+ wl_data_device_manager_destroy(object());
}
-struct wl_data_device *QWaylandDataDeviceManager::getDataDevice(QWaylandInputDevice *inputDevice)
+QWaylandDataDevice *QWaylandDataDeviceManager::getDataDevice(QWaylandInputDevice *inputDevice)
{
- struct wl_data_device *transfer_device = wl_data_device_manager_get_data_device(m_data_device_manager,
- inputDevice->wl_seat());
- wl_data_device_add_listener(transfer_device,&transfer_device_listener,this);
-
- return transfer_device;
+ return new QWaylandDataDevice(this, inputDevice);
}
-QWaylandDataOffer *QWaylandDataDeviceManager::selectionTransfer() const
-{
- return m_selection_data_offer;
-}
-
-void QWaylandDataDeviceManager::createAndSetDrag(QDrag *drag)
-{
- QWaylandInputDevice *inputDevice = m_display->lastKeyboardFocusInputDevice();
- if (!inputDevice)
- return;
-
- if (m_drag_data_source) {
- qDebug() << "QWaylandDndSelectionHandler::createAndSetDrag: Allready have a valid drag";
- delete m_drag_data_source;
- }
-
- delete m_drag_data_offer;
- m_drag_data_offer = 0;
-
- m_drag_data_source = new QWaylandDataSource(this,drag->mimeData());
-
- struct wl_data_device *transfer_device = inputDevice->transferDevice();
- m_drag_surface = m_display->createSurface(this);
- QPixmap pixmap = drag->pixmap();
- if (pixmap.isNull()) {
-// pixmap = QPlatformDrag::defaultPixmap();
- }
-
- m_drag_icon_buffer = new QWaylandShmBuffer(m_display, pixmap.size(), QImage::Format_ARGB32_Premultiplied);
-
- {
- QPainter p(m_drag_icon_buffer->image());
- p.drawPixmap(0,0,pixmap);
- }
-
- m_drag_icon_surface = m_display->compositor()->create_surface();
- wl_surface_attach(m_drag_icon_surface, m_drag_icon_buffer->buffer(), -drag->hotSpot().x(), -drag->hotSpot().y());
-
- wl_data_device_start_drag(transfer_device, m_drag_data_source->handle(), m_drag_surface, m_drag_icon_surface, QWaylandDisplay::currentTimeMillisec());
-}
-
-QMimeData *QWaylandDataDeviceManager::dragMime() const
-{
- if (m_drag_data_offer) {
- return m_drag_data_offer;
- } else if (m_drag_data_source){
- return m_drag_data_source->mimeData();
- }
- return 0;
-}
-
-bool QWaylandDataDeviceManager::canDropDrag() const
-{
- return m_drag_can_drop;
-}
-
-void QWaylandDataDeviceManager::cancelDrag()
-{
- wl_data_source_destroy(m_drag_data_source->handle() );
- wl_surface_destroy(m_drag_icon_surface);
- m_drag_data_source = 0;
-}
-
-void QWaylandDataDeviceManager::createAndSetSelectionSource(QMimeData *mimeData, QClipboard::Mode mode)
-{
- Q_UNUSED(mode);
- QWaylandDataSource *transfer_source = m_selection_data_source;
- delete transfer_source;
-
- transfer_source = new QWaylandDataSource(this,mimeData);
- m_selection_data_source = transfer_source;
- QWaylandInputDevice *inputDevice = m_display->lastKeyboardFocusInputDevice();
- if (!inputDevice)
- inputDevice = m_display->inputDevices().first(); // try to survive in apps without any surfaces
- struct wl_data_device *transfer_device = inputDevice->transferDevice();
- wl_data_device_set_selection(transfer_device,transfer_source->handle(),QWaylandDisplay::currentTimeMillisec());
-
- QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
-}
-
-QWaylandDataSource *QWaylandDataDeviceManager::selectionTransferSource()
-{
- return m_selection_data_source;
-}
-
-
-QWaylandDisplay * QWaylandDataDeviceManager::display() const
+QWaylandDisplay *QWaylandDataDeviceManager::display() const
{
return m_display;
}
-struct wl_data_device_manager *QWaylandDataDeviceManager::handle() const
-{
- return m_data_device_manager;
-}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland_common/qwaylanddatadevicemanager.h b/src/plugins/platforms/wayland_common/qwaylanddatadevicemanager.h
index 101f78448..b13e73329 100644
--- a/src/plugins/platforms/wayland_common/qwaylanddatadevicemanager.h
+++ b/src/plugins/platforms/wayland_common/qwaylanddatadevicemanager.h
@@ -44,82 +44,24 @@
#include "qwaylanddisplay.h"
-#include <QtCore/QMap>
-#include <QtCore/QMimeData>
-#include <QtCore/QStringList>
-#include <QtGui/QClipboard>
-
QT_BEGIN_NAMESPACE
-class QWaylandDataOffer;
+class QWaylandDataDevice;
class QWaylandDataSource;
-class QDrag;
-class QWaylandShmBuffer;
-class QWaylandWindow;
-class QWaylandDataDeviceManager
+class QWaylandDataDeviceManager : public QtWayland::wl_data_device_manager
{
public:
QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id);
~QWaylandDataDeviceManager();
- struct wl_data_device *getDataDevice(QWaylandInputDevice *inputDevice);
-
- QWaylandDataOffer *selectionTransfer() const;
-
- void createAndSetDrag(QDrag *drag);
- QMimeData *dragMime() const;
- bool canDropDrag() const;
- void cancelDrag();
-
- void createAndSetSelectionSource(QMimeData *mimeData, QClipboard::Mode mode);
- QWaylandDataSource *selectionTransferSource();
-
- QWaylandDisplay *display()const;
+ QWaylandDataDevice *getDataDevice(QWaylandInputDevice *inputDevice);
- struct wl_data_device_manager *handle() const;
+ QWaylandDisplay *display() const;
private:
struct wl_data_device_manager *m_data_device_manager;
QWaylandDisplay *m_display;
-
- QWaylandDataOffer *m_selection_data_offer;
- QWaylandDataSource *m_selection_data_source;
-
- QWaylandDataOffer *m_drag_data_offer;
- QWaylandDataSource *m_drag_data_source;
- QWaylandWindow *m_drag_current_event_window;
- wl_surface *m_drag_surface;
- wl_surface *m_drag_icon_surface;
- QWaylandShmBuffer *m_drag_icon_buffer;
- bool m_drag_can_drop;
- uint32_t m_drag_last_event_time;
- QPoint m_drag_position;
-
- static void data_offer(void *data,
- struct wl_data_device *wl_data_device,
- struct wl_data_offer *id);
- static void enter(void *data,
- struct wl_data_device *wl_data_device,
- uint32_t time,
- struct wl_surface *surface,
- wl_fixed_t x,
- wl_fixed_t y,
- struct wl_data_offer *id);
- static void leave(void *data,
- struct wl_data_device *wl_data_device);
- static void motion(void *data,
- struct wl_data_device *wl_data_device,
- uint32_t time,
- wl_fixed_t x,
- wl_fixed_t y);
- static void drop(void *data,
- struct wl_data_device *wl_data_device);
- static void selection(void *data,
- struct wl_data_device *wl_data_device,
- struct wl_data_offer *id);
-
- static const struct wl_data_device_listener transfer_device_listener;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland_common/qwaylanddataoffer.cpp b/src/plugins/platforms/wayland_common/qwaylanddataoffer.cpp
index d98cfc2ab..e237d0b9a 100644
--- a/src/plugins/platforms/wayland_common/qwaylanddataoffer.cpp
+++ b/src/plugins/platforms/wayland_common/qwaylanddataoffer.cpp
@@ -42,6 +42,7 @@
#include "qwaylanddataoffer.h"
#include "qwaylanddatadevicemanager.h"
+#include <QtCore/private/qcore_unix_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformclipboard.h>
@@ -49,99 +50,90 @@
QT_BEGIN_NAMESPACE
-void QWaylandDataOffer::offer_sync_callback(void *data,
- struct wl_callback *callback,
- uint32_t time)
+QWaylandDataOffer::QWaylandDataOffer(QWaylandDisplay *display, struct ::wl_data_offer *offer)
+ : QtWayland::wl_data_offer(offer)
+ , m_mimeData(new QWaylandMimeData(this, display))
{
- Q_UNUSED(time);
- QWaylandDataOffer *mime = static_cast<QWaylandDataOffer *>(data);
- if (mime->m_receiveSyncCallback == callback) {
- mime->m_receiveSyncCallback = 0;
- wl_callback_destroy(callback);
- }
}
-const struct wl_callback_listener QWaylandDataOffer::offer_sync_callback_listener = {
- QWaylandDataOffer::offer_sync_callback
-};
+QWaylandDataOffer::~QWaylandDataOffer()
+{
+ destroy();
+}
+
-void QWaylandDataOffer::offer(void *data,
- struct wl_data_offer *wl_data_offer,
- const char *type)
+QString QWaylandDataOffer::firstFormat() const
{
- Q_UNUSED(wl_data_offer);
+ if (m_mimeData->formats().isEmpty())
+ return QString();
- QWaylandDataOffer *data_offer = static_cast<QWaylandDataOffer *>(data);
+ return m_mimeData->formats().first();
+}
- if (!data_offer->m_receiveSyncCallback) {
- data_offer->m_receiveSyncCallback = wl_display_sync(data_offer->m_display->wl_display());
- wl_callback_add_listener(data_offer->m_receiveSyncCallback, &offer_sync_callback_listener, data_offer);
- }
+QMimeData *QWaylandDataOffer::mimeData()
+{
+ return m_mimeData.data();
+}
- data_offer->m_offered_mime_types.append(QString::fromLocal8Bit(type));
-// qDebug() << data_offer->m_offered_mime_types;
+void QWaylandDataOffer::data_offer_offer(const QString &mime_type)
+{
+ m_mimeData->appendFormat(mime_type);
}
-const struct wl_data_offer_listener QWaylandDataOffer::data_offer_listener = {
- QWaylandDataOffer::offer
-};
+QWaylandMimeData::QWaylandMimeData(QWaylandDataOffer *dataOffer, QWaylandDisplay *display)
+ : QInternalMimeData()
+ , m_dataOffer(dataOffer)
+ , m_display(display)
+ , m_offered_mime_types()
+{
+}
-QWaylandDataOffer::QWaylandDataOffer(QWaylandDisplay *display, struct wl_data_offer *data_offer)
- : m_display(display)
- , m_receiveSyncCallback(0)
+QWaylandMimeData::~QWaylandMimeData()
{
- m_data_offer = data_offer;
- wl_data_offer_set_user_data(m_data_offer,this);
- wl_data_offer_add_listener(m_data_offer,&data_offer_listener,this);
}
-QWaylandDataOffer::~QWaylandDataOffer()
+void QWaylandMimeData::appendFormat(const QString &mimeType)
{
- wl_data_offer_destroy(m_data_offer);
+ m_offered_mime_types.append(mimeType);
}
-bool QWaylandDataOffer::hasFormat_sys(const QString &mimeType) const
+bool QWaylandMimeData::hasFormat_sys(const QString &mimeType) const
{
return m_offered_mime_types.contains(mimeType);
}
-QStringList QWaylandDataOffer::formats_sys() const
+QStringList QWaylandMimeData::formats_sys() const
{
return m_offered_mime_types;
}
-QVariant QWaylandDataOffer::retrieveData_sys(const QString &mimeType, QVariant::Type type) const
+QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const
{
Q_UNUSED(type);
+
if (m_offered_mime_types.isEmpty())
return QVariant();
int pipefd[2];
- if (pipe(pipefd) == -1) {
+ if (qt_safe_pipe(pipefd, O_CLOEXEC) == -1) {
qWarning("QWaylandMimeData: pipe() failed");
return QVariant();
}
- QByteArray mimeTypeBa = mimeType.toLatin1();
- wl_data_offer_receive(m_data_offer,mimeTypeBa.constData(),pipefd[1]);
-
- m_display->forceRoundTrip();
+ m_dataOffer->receive(mimeType, pipefd[1]);
close(pipefd[1]);
+// m_display->forceRoundTrip();
+
QByteArray content;
- char buf[256];
+ char buf[4096];
int n;
while ((n = QT_READ(pipefd[0], &buf, sizeof buf)) > 0) {
content.append(buf, n);
}
-
close(pipefd[0]);
- return content;
-}
-struct wl_data_offer *QWaylandDataOffer::handle() const
-{
- return m_data_offer;
+ return content;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland_common/qwaylanddataoffer.h b/src/plugins/platforms/wayland_common/qwaylanddataoffer.h
index abc7c690a..4b2b832f6 100644
--- a/src/plugins/platforms/wayland_common/qwaylanddataoffer.h
+++ b/src/plugins/platforms/wayland_common/qwaylanddataoffer.h
@@ -42,47 +42,49 @@
#ifndef QWAYLANDDATAOFFER_H
#define QWAYLANDDATAOFFER_H
-#include <QString>
-#include <QByteArray>
-#include <QMimeData>
+#include "qwaylanddisplay.h"
#include <QtGui/private/qdnd_p.h>
-#include <QtGui/QClipboard>
-
-#include <stdint.h>
-
-struct wl_callback;
-struct wl_callback_listener;
-struct wl_data_offer;
-struct wl_data_offer_listener;
QT_BEGIN_NAMESPACE
class QWaylandDisplay;
+class QWaylandMimeData;
-class QWaylandDataOffer : public QInternalMimeData
+class QWaylandDataOffer : public QtWayland::wl_data_offer
{
public:
- QWaylandDataOffer(QWaylandDisplay *display, struct wl_data_offer *offer);
+ explicit QWaylandDataOffer(QWaylandDisplay *display, struct ::wl_data_offer *offer);
~QWaylandDataOffer();
- bool hasFormat_sys(const QString &mimeType) const;
- QStringList formats_sys() const;
- QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const;
+ QString firstFormat() const;
+
+ QMimeData *mimeData();
+
+protected:
+ void data_offer_offer(const QString &mime_type) Q_DECL_OVERRIDE;
- struct wl_data_offer *handle() const;
private:
+ QScopedPointer<QWaylandMimeData> m_mimeData;
+};
- struct wl_data_offer *m_data_offer;
- QWaylandDisplay *m_display;
- QStringList m_offered_mime_types;
- wl_callback *m_receiveSyncCallback;
- static void offer(void *data, struct wl_data_offer *wl_data_offer, const char *type);
- static const struct wl_data_offer_listener data_offer_listener;
+class QWaylandMimeData : public QInternalMimeData {
+public:
+ explicit QWaylandMimeData(QWaylandDataOffer *dataOffer, QWaylandDisplay *display);
+ ~QWaylandMimeData();
+
+ void appendFormat(const QString &mimeType);
+
+protected:
+ bool hasFormat_sys(const QString &mimeType) const Q_DECL_OVERRIDE;
+ QStringList formats_sys() const Q_DECL_OVERRIDE;
+ QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const Q_DECL_OVERRIDE;
- static void offer_sync_callback(void *data, struct wl_callback *wl_callback, uint32_t time);
- static const struct wl_callback_listener offer_sync_callback_listener;
+private:
+ mutable QWaylandDataOffer *m_dataOffer;
+ QWaylandDisplay *m_display;
+ QStringList m_offered_mime_types;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland_common/qwaylanddatasource.cpp b/src/plugins/platforms/wayland_common/qwaylanddatasource.cpp
index 318b924b5..ba4b68110 100644
--- a/src/plugins/platforms/wayland_common/qwaylanddatasource.cpp
+++ b/src/plugins/platforms/wayland_common/qwaylanddatasource.cpp
@@ -41,6 +41,7 @@
#include "qwaylanddatasource.h"
#include "qwaylanddataoffer.h"
+#include "qwaylanddatadevicemanager.h"
#include "qwaylandinputdevice.h"
#include "qwaylandmimehelper.h"
@@ -52,74 +53,44 @@
QT_BEGIN_NAMESPACE
-void QWaylandDataSource::data_source_target(void *data,
- struct wl_data_source *wl_data_source,
- const char *mime_type)
+QWaylandDataSource::QWaylandDataSource(QWaylandDataDeviceManager *dataDeviceManager, QMimeData *mimeData)
+ : QtWayland::wl_data_source(dataDeviceManager->create_data_source())
+ , m_mime_data(mimeData)
{
- Q_UNUSED(data);
- Q_UNUSED(wl_data_source);
- Q_UNUSED(mime_type);
-}
-
-void QWaylandDataSource::data_source_send(void *data,
- struct wl_data_source *wl_data_source,
- const char *mime_type,
- int32_t fd)
-{
- Q_UNUSED(wl_data_source);
- QWaylandDataSource *self = static_cast<QWaylandDataSource *>(data);
- QString mimeType = QString::fromLatin1(mime_type);
- QByteArray content = QWaylandMimeHelper::getByteArray(self->m_mime_data, mimeType);
- if (!content.isEmpty()) {
- QFile f;
- if (f.open(fd, QIODevice::WriteOnly))
- f.write(content);
+ if (!mimeData)
+ return;
+ Q_FOREACH (const QString &format, mimeData->formats()) {
+ offer(format);
}
- close(fd);
}
-void QWaylandDataSource::data_source_cancelled(void *data,
- struct wl_data_source *wl_data_source)
+QWaylandDataSource::~QWaylandDataSource()
{
- Q_UNUSED(data);
- Q_UNUSED(wl_data_source);
+ destroy();
}
-const struct wl_data_source_listener QWaylandDataSource::data_source_listener = {
- data_source_target,
- data_source_send,
- data_source_cancelled
-};
-
-QWaylandDataSource::QWaylandDataSource(QWaylandDataDeviceManager *dndSelectionHandler, QMimeData *mimeData)
- : m_mime_data(mimeData)
+QMimeData * QWaylandDataSource::mimeData() const
{
- m_data_source = wl_data_device_manager_create_data_source(dndSelectionHandler->handle());
- wl_data_source_add_listener(m_data_source,&data_source_listener,this);
-
- if (!mimeData)
- return;
-
- QStringList formats = mimeData->formats();
- for (int i = 0; i < formats.size(); i++) {
- const char *offer = qPrintable(formats.at(i));
- wl_data_source_offer(m_data_source,offer);
- }
+ return m_mime_data;
}
-QWaylandDataSource::~QWaylandDataSource()
+void QWaylandDataSource::data_source_cancelled()
{
- wl_data_source_destroy(m_data_source);
+ Q_EMIT cancelled();
}
-QMimeData * QWaylandDataSource::mimeData() const
+void QWaylandDataSource::data_source_send(const QString &mime_type, int32_t fd)
{
- return m_mime_data;
+ QByteArray content = QWaylandMimeHelper::getByteArray(m_mime_data, mime_type);
+ if (!content.isEmpty()) {
+ write(fd, content.constData(), content.size());
+ }
+ close(fd);
}
-struct wl_data_source *QWaylandDataSource::handle() const
+void QWaylandDataSource::data_source_target(const QString &mime_type)
{
- return m_data_source;
+ Q_EMIT targetChanged(mime_type);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland_common/qwaylanddatasource.h b/src/plugins/platforms/wayland_common/qwaylanddatasource.h
index 8fdf06368..48c445bef 100644
--- a/src/plugins/platforms/wayland_common/qwaylanddatasource.h
+++ b/src/plugins/platforms/wayland_common/qwaylanddatasource.h
@@ -42,36 +42,34 @@
#ifndef QWAYLANDDATASOURCE_H
#define QWAYLANDDATASOURCE_H
-#include "qwaylanddatadevicemanager.h"
-
-#include <wayland-client-protocol.h>
+#include "qwaylanddisplay.h"
QT_BEGIN_NAMESPACE
-class QWaylandDataSource
+class QMimeData;
+class QWaylandDataDeviceManager;
+
+class QWaylandDataSource : public QObject, public QtWayland::wl_data_source
{
+ Q_OBJECT
public:
- QWaylandDataSource(QWaylandDataDeviceManager *dndSelectionHandler, QMimeData *mimeData);
+ QWaylandDataSource(QWaylandDataDeviceManager *dataDeviceManager, QMimeData *mimeData);
~QWaylandDataSource();
QMimeData *mimeData() const;
- struct wl_data_source *handle() const;
+Q_SIGNALS:
+ void targetChanged(const QString &mime_type);
+ void cancelled();
+
+protected:
+ void data_source_cancelled() Q_DECL_OVERRIDE;
+ void data_source_send(const QString &mime_type, int32_t fd) Q_DECL_OVERRIDE;
+ void data_source_target(const QString &mime_type) Q_DECL_OVERRIDE;
+
private:
- struct wl_data_source *m_data_source;
QWaylandDisplay *m_display;
QMimeData *m_mime_data;
-
- static void data_source_target(void *data,
- struct wl_data_source *data_source,
- const char *mime_type);
- static void data_source_send(void *data,
- struct wl_data_source *data_source,
- const char *mime_type,
- int32_t fd);
- static void data_source_cancelled(void *data,
- struct wl_data_source *data_source);
- static const struct wl_data_source_listener data_source_listener;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland_common/qwaylanddisplay.h b/src/plugins/platforms/wayland_common/qwaylanddisplay.h
index 5916a5b41..be509dfd9 100644
--- a/src/plugins/platforms/wayland_common/qwaylanddisplay.h
+++ b/src/plugins/platforms/wayland_common/qwaylanddisplay.h
@@ -114,6 +114,7 @@ public:
QList<QWaylandInputDevice *> inputDevices() const { return mInputDevices; }
QWaylandInputDevice *defaultInputDevice() const;
+ QWaylandInputDevice *currentInputDevice() const { return defaultInputDevice(); }
QWaylandInputDevice *lastKeyboardFocusInputDevice() const;
void setLastKeyboardFocusInputDevice(QWaylandInputDevice *device);
diff --git a/src/plugins/platforms/wayland_common/qwaylanddnd.cpp b/src/plugins/platforms/wayland_common/qwaylanddnd.cpp
index 0dc80e636..635fd9678 100644
--- a/src/plugins/platforms/wayland_common/qwaylanddnd.cpp
+++ b/src/plugins/platforms/wayland_common/qwaylanddnd.cpp
@@ -41,57 +41,96 @@
#include "qwaylanddnd.h"
+#include "qwaylanddatadevice.h"
#include "qwaylanddatadevicemanager.h"
+#include "qwaylanddataoffer.h"
+#include "qwaylandinputdevice.h"
+
+#include <QtGui/private/qshapedpixmapdndwindow_p.h>
+
+#include <QDebug>
QT_BEGIN_NAMESPACE
QWaylandDrag::QWaylandDrag(QWaylandDisplay *display)
: m_display(display)
{
-
}
QWaylandDrag::~QWaylandDrag()
{
-
}
QMimeData * QWaylandDrag::platformDropData()
{
- return m_display->dndSelectionHandler()->dragMime();
+ if (drag())
+ return drag()->mimeData();
+ return 0;
}
-Qt::DropAction QWaylandDrag::drag(QDrag *m_drag)
+void QWaylandDrag::startDrag()
{
- Q_UNUSED(m_drag);
-// m_display->dndSelectionHandler()->createAndSetDrag(drag);
- return Qt::IgnoreAction;
+ if (!shapedPixmapWindow()) {
+ QBasicDrag::startDrag();
+ QBasicDrag::cancel();
+ }
+
+ QWaylandWindow *icon = static_cast<QWaylandWindow *>(shapedPixmapWindow()->handle());
+ m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), icon);
+ QBasicDrag::startDrag();
}
-void QWaylandDrag::move(const QMouseEvent *me)
+void QWaylandDrag::cancel()
{
- Q_UNUSED(me);
- qFatal("This function should not be called");
+ QBasicDrag::cancel();
+
+ m_display->currentInputDevice()->dataDevice()->cancelDrag();
}
-bool QWaylandDrag::canDrop() const
+void QWaylandDrag::move(const QMouseEvent *me)
{
- return false;
+ Q_UNUSED(me);
+ // Do nothing
}
void QWaylandDrag::drop(const QMouseEvent *me)
{
Q_UNUSED(me);
+ // Do nothing
}
-void QWaylandDrag::cancel()
+void QWaylandDrag::endDrag()
+{
+ // Do nothing
+}
+
+void QWaylandDrag::updateTarget(const QString &mimeType)
{
- m_display->dndSelectionHandler()->cancelDrag();
+ setCanDrop(!mimeType.isEmpty());
+
+ if (canDrop()) {
+ updateCursor(defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers()));
+ } else {
+ updateCursor(Qt::IgnoreAction);
+ }
+}
+
+void QWaylandDrag::setResponse(const QPlatformDragQtResponse &response)
+{
+ setCanDrop(response.isAccepted());
+
+ if (canDrop()) {
+ updateCursor(defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers()));
+ } else {
+ updateCursor(Qt::IgnoreAction);
+ }
}
-Qt::DropAction QWaylandDrag::executedDropAction() const
+void QWaylandDrag::finishDrag(const QPlatformDropQtResponse &response)
{
- return Qt::CopyAction;
+ setExecutedDropAction(response.acceptedAction());
+ QKeyEvent event(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier);
+ eventFilter(shapedPixmapWindow(), &event);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland_common/qwaylanddnd.h b/src/plugins/platforms/wayland_common/qwaylanddnd.h
index fa8f5b639..409b3d546 100644
--- a/src/plugins/platforms/wayland_common/qwaylanddnd.h
+++ b/src/plugins/platforms/wayland_common/qwaylanddnd.h
@@ -43,27 +43,33 @@
#define QWAYLANDDND_H
#include <qpa/qplatformdrag.h>
+#include <QtGui/private/qsimpledrag_p.h>
+
#include <QtGui/QDrag>
#include <QtCore/QMimeData>
#include "qwaylanddisplay.h"
QT_BEGIN_NAMESPACE
-class QWaylandDrag : public QPlatformDrag
+class QWaylandDrag : public QBasicDrag
{
public:
QWaylandDrag(QWaylandDisplay *display);
~QWaylandDrag();
- QMimeData *platformDropData();
+ QMimeData *platformDropData() Q_DECL_OVERRIDE;
+
+ void updateTarget(const QString &mimeType);
+ void setResponse(const QPlatformDragQtResponse &response);
+ void finishDrag(const QPlatformDropQtResponse &response);
- Qt::DropAction drag(QDrag *m_drag);
- void move(const QMouseEvent *me);
- bool canDrop() const;
- void drop(const QMouseEvent *me);
- void cancel();
+protected:
+ void startDrag() Q_DECL_OVERRIDE;
+ void cancel() Q_DECL_OVERRIDE;
+ void move(const QMouseEvent *me) Q_DECL_OVERRIDE;
+ void drop(const QMouseEvent *me) Q_DECL_OVERRIDE;
+ void endDrag() Q_DECL_OVERRIDE;
- virtual Qt::DropAction executedDropAction() const;
private:
QWaylandDisplay *m_display;
diff --git a/src/plugins/platforms/wayland_common/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland_common/qwaylandinputdevice.cpp
index 3fe6ca309..ac6a0c7da 100644
--- a/src/plugins/platforms/wayland_common/qwaylandinputdevice.cpp
+++ b/src/plugins/platforms/wayland_common/qwaylandinputdevice.cpp
@@ -44,6 +44,7 @@
#include "qwaylandintegration.h"
#include "qwaylandwindow.h"
#include "qwaylandbuffer.h"
+#include "qwaylanddatadevice.h"
#include "qwaylanddatadevicemanager.h"
#include "qwaylandtouch.h"
#include "qwaylandscreen.h"
@@ -74,7 +75,7 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, uint32_t id)
, mDisplay(display->wl_display())
, mFocusCallback(0)
, mCaps(0)
- , mTransferDevice(0)
+ , mDataDevice(0)
, mPointerFocus(0)
, mKeyboardFocus(0)
, mTouchFocus(0)
@@ -111,7 +112,7 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, uint32_t id)
#endif
if (mQDisplay->dndSelectionHandler()) {
- mTransferDevice = mQDisplay->dndSelectionHandler()->getDataDevice(this);
+ mDataDevice = mQDisplay->dndSelectionHandler()->getDataDevice(this);
}
}
@@ -159,15 +160,15 @@ void QWaylandInputDevice::handleWindowDestroyed(QWaylandWindow *window)
mKeyboardFocus = 0;
}
-void QWaylandInputDevice::setTransferDevice(struct wl_data_device *device)
+void QWaylandInputDevice::setDataDevice(QWaylandDataDevice *device)
{
- mTransferDevice = device;
+ mDataDevice = device;
}
-struct wl_data_device *QWaylandInputDevice::transferDevice() const
+QWaylandDataDevice *QWaylandInputDevice::dataDevice() const
{
- Q_ASSERT(mTransferDevice);
- return mTransferDevice;
+ Q_ASSERT(mDataDevice);
+ return mDataDevice;
}
void QWaylandInputDevice::removeMouseButtonFromState(Qt::MouseButton button)
@@ -175,6 +176,33 @@ void QWaylandInputDevice::removeMouseButtonFromState(Qt::MouseButton button)
mButtons = mButtons & !button;
}
+QWaylandWindow *QWaylandInputDevice::pointerFocus() const
+{
+ return mPointerFocus;
+}
+
+Qt::KeyboardModifiers QWaylandInputDevice::modifiers() const
+{
+ Qt::KeyboardModifiers ret = Qt::NoModifier;
+
+#ifndef QT_NO_WAYLAND_XKB
+ xkb_state_component cstate = static_cast<xkb_state_component>(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED);
+
+ if (xkb_state_mod_name_is_active(mXkbState, "Shift", cstate))
+ ret |= Qt::ShiftModifier;
+ if (xkb_state_mod_name_is_active(mXkbState, "Control", cstate))
+ ret |= Qt::ControlModifier;
+ if (xkb_state_mod_name_is_active(mXkbState, "Alt", cstate))
+ ret |= Qt::AltModifier;
+ if (xkb_state_mod_name_is_active(mXkbState, "Mod1", cstate))
+ ret |= Qt::AltModifier;
+ if (xkb_state_mod_name_is_active(mXkbState, "Mod4", cstate))
+ ret |= Qt::MetaModifier;
+#endif
+
+ return ret;
+}
+
void QWaylandInputDevice::setCursor(Qt::CursorShape newShape, QWaylandScreen *screen)
{
struct wl_cursor_image *image = screen->waylandCursor()->cursorImage(newShape);
@@ -351,25 +379,6 @@ void QWaylandInputDevice::pointer_axis(uint32_t time, uint32_t axis, int32_t val
#ifndef QT_NO_WAYLAND_XKB
-static Qt::KeyboardModifiers translateModifiers(xkb_state *state)
-{
- Qt::KeyboardModifiers ret = Qt::NoModifier;
- xkb_state_component cstate = xkb_state_component(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED);
-
- if (xkb_state_mod_name_is_active(state, "Shift", cstate))
- ret |= Qt::ShiftModifier;
- if (xkb_state_mod_name_is_active(state, "Control", cstate))
- ret |= Qt::ControlModifier;
- if (xkb_state_mod_name_is_active(state, "Alt", cstate))
- ret |= Qt::AltModifier;
- if (xkb_state_mod_name_is_active(state, "Mod1", cstate))
- ret |= Qt::AltModifier;
- if (xkb_state_mod_name_is_active(state, "Mod4", cstate))
- ret |= Qt::MetaModifier;
-
- return ret;
-}
-
static const uint32_t KeyTbl[] = {
XK_Escape, Qt::Key_Escape,
XK_Tab, Qt::Key_Tab,
@@ -589,7 +598,7 @@ void QWaylandInputDevice::keyboard_key(uint32_t serial, uint32_t time, uint32_t
if (numSyms == 1) {
xkb_keysym_t sym = syms[0];
- Qt::KeyboardModifiers modifiers = translateModifiers(mXkbState);
+ Qt::KeyboardModifiers modifiers = this->modifiers();
QEvent::Type type = isDown ? QEvent::KeyPress : QEvent::KeyRelease;
uint utf32 = xkb_keysym_to_utf32(sym);
diff --git a/src/plugins/platforms/wayland_common/qwaylandinputdevice.h b/src/plugins/platforms/wayland_common/qwaylandinputdevice.h
index c92026841..be1e4885d 100644
--- a/src/plugins/platforms/wayland_common/qwaylandinputdevice.h
+++ b/src/plugins/platforms/wayland_common/qwaylandinputdevice.h
@@ -64,6 +64,7 @@ QT_BEGIN_NAMESPACE
class QWaylandWindow;
class QWaylandDisplay;
+class QWaylandDataDevice;
class QWaylandInputDevice : public QtWayland::wl_pointer, public QtWayland::wl_keyboard, public QtWayland::wl_touch, public QtWayland::wl_seat
{
@@ -79,11 +80,15 @@ public:
void setCursor(struct wl_buffer *buffer, struct wl_cursor_image *image);
void handleWindowDestroyed(QWaylandWindow *window);
- void setTransferDevice(struct wl_data_device *device);
- struct wl_data_device *transferDevice() const;
+ void setDataDevice(QWaylandDataDevice *device);
+ QWaylandDataDevice *dataDevice() const;
void removeMouseButtonFromState(Qt::MouseButton button);
+ QWaylandWindow *pointerFocus() const;
+
+ Qt::KeyboardModifiers modifiers() const;
+
uint32_t serial() const;
uint32_t cursorSerial() const { return mCursorSerial; }
@@ -96,7 +101,7 @@ private:
struct wl_surface *pointerSurface;
- struct wl_data_device *mTransferDevice;
+ QWaylandDataDevice *mDataDevice;
QWaylandWindow *mPointerFocus;
QWaylandWindow *mKeyboardFocus;
QWaylandWindow *mTouchFocus;
diff --git a/src/plugins/platforms/wayland_common/wayland_common.pro b/src/plugins/platforms/wayland_common/wayland_common.pro
index fc00c7c3e..cd40a1824 100644
--- a/src/plugins/platforms/wayland_common/wayland_common.pro
+++ b/src/plugins/platforms/wayland_common/wayland_common.pro
@@ -27,7 +27,8 @@ SOURCES += qwaylandintegration.cpp \
qwaylanddecoration.cpp \
qwaylandeventthread.cpp\
qwaylandwindowmanagerintegration.cpp \
- qwaylandinputcontext.cpp
+ qwaylandinputcontext.cpp \
+ qwaylanddatadevice.cpp \
HEADERS += qwaylandintegration.h \
qwaylandnativeinterface.h \
@@ -54,7 +55,8 @@ HEADERS += qwaylandintegration.h \
qwaylanddecoration.h \
qwaylandeventthread.h \
qwaylandwindowmanagerintegration.h \
- qwaylandinputcontext.h
+ qwaylandinputcontext.h \
+ qwaylanddatadevice.h \
contains(DEFINES, QT_WAYLAND_GL_SUPPORT) {
SOURCES += qwaylandglintegration.cpp