diff options
Diffstat (limited to 'src/client/qwaylanddatadevice.cpp')
-rw-r--r-- | src/client/qwaylanddatadevice.cpp | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp new file mode 100644 index 000000000..2d6a6f4b6 --- /dev/null +++ b/src/client/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_p.h" + +#include "qwaylanddatadevicemanager_p.h" +#include "qwaylanddataoffer_p.h" +#include "qwaylanddatasource_p.h" +#include "qwaylanddnd_p.h" +#include "qwaylandinputdevice_p.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) +{ + 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); +} |