diff options
author | Jan Arne Petersen <jan.petersen@kdab.com> | 2013-11-01 12:46:22 +0100 |
---|---|---|
committer | Jørgen Lind <jorgen.lind@digia.com> | 2013-11-22 15:46:38 +0100 |
commit | d06c04238238c780b6d0019b305b4ae8c99de425 (patch) | |
tree | fa5fbf0a960e63b4525168d309ccfc78de4927fc /src/compositor | |
parent | 19992cf8f509e178b0cb0e31df28ba30b8020057 (diff) |
Add Drag&Drop support to compositor
Change-Id: Ic606ac4dfbb1c55ddb81ac8a912132102753455c
Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
Diffstat (limited to 'src/compositor')
17 files changed, 499 insertions, 314 deletions
diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri index feecbbd75..06d895540 100644 --- a/src/compositor/compositor_api/compositor_api.pri +++ b/src/compositor/compositor_api/compositor_api.pri @@ -4,13 +4,15 @@ HEADERS += \ compositor_api/qwaylandcompositor.h \ compositor_api/qwaylandsurface.h \ compositor_api/qwaylandinput.h \ - compositor_api/qwaylandinputpanel.h + compositor_api/qwaylandinputpanel.h \ + compositor_api/qwaylanddrag.h SOURCES += \ compositor_api/qwaylandcompositor.cpp \ compositor_api/qwaylandsurface.cpp \ compositor_api/qwaylandinput.cpp \ - compositor_api/qwaylandinputpanel.cpp + compositor_api/qwaylandinputpanel.cpp \ + compositor_api/qwaylanddrag.cpp QT += core-private diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp index c25abcdbd..e1cc1adef 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandcompositor.cpp @@ -43,6 +43,7 @@ #include "qwaylandinput.h" #include "wayland_wrapper/qwlcompositor_p.h" +#include "wayland_wrapper/qwldatadevice_p.h" #include "wayland_wrapper/qwlsurface_p.h" #include "wayland_wrapper/qwlinputdevice_p.h" #include "wayland_wrapper/qwlinputpanel_p.h" @@ -146,6 +147,21 @@ void QWaylandCompositor::surfaceAboutToBeDestroyed(QWaylandSurface *surface) Q_UNUSED(surface); } +QWaylandSurface *QWaylandCompositor::pickSurface(const QPointF &globalPosition) const +{ + Q_FOREACH (QtWayland::Surface *surface, m_compositor->surfaces()) { + if (QRectF(surface->pos(), surface->size()).contains(globalPosition)) + return surface->waylandSurface(); + } + + return 0; +} + +QPointF QWaylandCompositor::mapToSurface(QWaylandSurface *surface, const QPointF &globalPosition) const +{ + return globalPosition - surface->pos(); +} + /*! Override this to handle QDesktopServices::openUrl() requests from the clients. @@ -235,6 +251,11 @@ QWaylandInputPanel *QWaylandCompositor::inputPanel() const return m_compositor->inputPanel()->handle(); } +QWaylandDrag *QWaylandCompositor::drag() const +{ + return m_compositor->defaultInputDevice()->dragHandle(); +} + bool QWaylandCompositor::isDragging() const { return m_compositor->isDragging(); diff --git a/src/compositor/compositor_api/qwaylandcompositor.h b/src/compositor/compositor_api/qwaylandcompositor.h index 518f0a049..7199d969e 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.h +++ b/src/compositor/compositor_api/qwaylandcompositor.h @@ -55,6 +55,7 @@ class QOpenGLContext; class QWaylandSurface; class QWaylandInputDevice; class QWaylandInputPanel; +class QWaylandDrag; namespace QtWayland { @@ -96,6 +97,9 @@ public: virtual void surfaceCreated(QWaylandSurface *surface) = 0; virtual void surfaceAboutToBeDestroyed(QWaylandSurface *surface); + virtual QWaylandSurface *pickSurface(const QPointF &globalPosition) const; + virtual QPointF mapToSurface(QWaylandSurface *surface, const QPointF &surfacePosition) const; + virtual void openUrl(WaylandClient *client, const QUrl &url); QtWayland::Compositor *handle() const; @@ -119,6 +123,7 @@ public: QWaylandInputDevice *defaultInputDevice() const; QWaylandInputPanel *inputPanel() const; + QWaylandDrag *drag() const; bool isDragging() const; void sendDragMoveEvent(const QPoint &global, const QPoint &local, QWaylandSurface *surface); diff --git a/src/compositor/compositor_api/qwaylanddrag.cpp b/src/compositor/compositor_api/qwaylanddrag.cpp new file mode 100644 index 000000000..def763929 --- /dev/null +++ b/src/compositor/compositor_api/qwaylanddrag.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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 "qwaylanddrag.h" + +#include <private/qobject_p.h> + +#include "qwlcompositor_p.h" +#include "qwlinputdevice_p.h" +#include "qwldatadevice_p.h" +#include "qwlsurface_p.h" + +QT_BEGIN_NAMESPACE + +class QWaylandDragPrivate : public QObjectPrivate +{ +public: + QWaylandDragPrivate(QtWayland::InputDevice *id) + : inputDevice(id) + { + } + + QtWayland::InputDevice *inputDevice; +}; + + +QWaylandDrag::QWaylandDrag(QtWayland::InputDevice *inputDevice) + : QObject(* new QWaylandDragPrivate(inputDevice)) +{ +} + +QWaylandSurface *QWaylandDrag::icon() const +{ + Q_D(const QWaylandDrag); + + const QtWayland::DataDevice *dataDevice = d->inputDevice->dataDevice(); + if (!dataDevice) + return 0; + + return dataDevice->dragIcon() ? dataDevice->dragIcon()->waylandSurface() : 0; +} + +bool QWaylandDrag::visible() const +{ + Q_D(const QWaylandDrag); + + const QtWayland::DataDevice *dataDevice = d->inputDevice->dataDevice(); + if (!dataDevice) + return false; + + return dataDevice->dragIcon() != 0; +} + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylanddrag.h b/src/compositor/compositor_api/qwaylanddrag.h new file mode 100644 index 000000000..888a48a92 --- /dev/null +++ b/src/compositor/compositor_api/qwaylanddrag.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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 QWAYLANDDRAG_H +#define QWAYLANDDRAG_H + +#include <QtCompositor/qwaylandexport.h> + +#include <QObject> + +QT_BEGIN_NAMESPACE + +class QWaylandDragPrivate; +class QWaylandSurface; + +namespace QtWayland { +class InputDevice; +} +class Q_COMPOSITOR_EXPORT QWaylandDrag : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandDrag) + + Q_PROPERTY(QWaylandSurface* icon READ icon NOTIFY iconChanged) + Q_PROPERTY(bool visible READ visible NOTIFY iconChanged) + +public: + explicit QWaylandDrag(QtWayland::InputDevice *inputDevice); + + QWaylandSurface *icon() const; + bool visible() const; + +Q_SIGNALS: + void iconChanged(); +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDDRAG_H diff --git a/src/compositor/wayland_wrapper/qwlcompositor.cpp b/src/compositor/wayland_wrapper/qwlcompositor.cpp index be55e425d..3a6b91b45 100644 --- a/src/compositor/wayland_wrapper/qwlcompositor.cpp +++ b/src/compositor/wayland_wrapper/qwlcompositor.cpp @@ -486,6 +486,17 @@ QList<QtWayland::Surface *> Compositor::surfacesForClient(wl_client *client) return ret; } +Surface *Compositor::pickSurface(const QPointF &globalPosition) +{ + QWaylandSurface *surface = m_qt_compositor->pickSurface(globalPosition); + return surface ? surface->handle() : 0; +} + +QPointF Compositor::mapToSurface(Surface *surface, const QPointF &globalPosition) +{ + return m_qt_compositor->mapToSurface(surface->waylandSurface(), globalPosition); +} + void Compositor::configureTouchExtension(int flags) { if (m_touchExtension) diff --git a/src/compositor/wayland_wrapper/qwlcompositor_p.h b/src/compositor/wayland_wrapper/qwlcompositor_p.h index 65dfe3607..c8e8b2587 100644 --- a/src/compositor/wayland_wrapper/qwlcompositor_p.h +++ b/src/compositor/wayland_wrapper/qwlcompositor_p.h @@ -113,6 +113,9 @@ public: QList<Surface*> surfacesForClient(wl_client* client); QWaylandCompositor *waylandCompositor() const { return m_qt_compositor; } + Surface *pickSurface(const QPointF &globalPosition); + QPointF mapToSurface(Surface *surface, const QPointF &globalPosition); + struct wl_display *wl_display() const { return m_display->handle(); } static Compositor *instance(); diff --git a/src/compositor/wayland_wrapper/qwldatadevice.cpp b/src/compositor/wayland_wrapper/qwldatadevice.cpp index 89fa7a08e..2257455f4 100644 --- a/src/compositor/wayland_wrapper/qwldatadevice.cpp +++ b/src/compositor/wayland_wrapper/qwldatadevice.cpp @@ -40,11 +40,16 @@ #include "qwldatadevice_p.h" +#include "qwlcompositor_p.h" #include "qwldatasource_p.h" #include "qwldataoffer_p.h" -#include "qwldatadevicemanager_p.h" +#include "qwlinputdevice_p.h" +#include "qwlkeyboard_p.h" +#include "qwlpointer_p.h" +#include "qwlsurface_p.h" +#include "qwltouch_p.h" -#include <stdlib.h> +#include "qwaylanddrag.h" #include <QDebug> @@ -52,78 +57,155 @@ QT_BEGIN_NAMESPACE namespace QtWayland { -void DataDevice::start_drag(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *source, - struct wl_resource *surface, - struct wl_resource *icon, - uint32_t time) +DataDevice::DataDevice(InputDevice *inputDevice) + : wl_data_device() + , m_compositor(inputDevice->compositor()) + , m_inputDevice(inputDevice) + , m_selectionSource(0) + , m_dragClient(0) + , m_dragDataSource(0) + , m_dragFocus(0) + , m_dragFocusResource(0) + , m_dragIcon(0) { - Q_UNUSED(client); - Q_UNUSED(surface); - Q_UNUSED(icon); - Q_UNUSED(time); - DataDevice *data_device = static_cast<DataDevice *>(resource->data); - DataSource *data_source = static_cast<DataSource *>(source->data); - Q_UNUSED(data_device); - Q_UNUSED(data_source); } -void DataDevice::set_selection(struct wl_client *client, - struct wl_resource *data_device_resource, - struct wl_resource *source, - uint32_t time) +void DataDevice::setFocus(QtWaylandServer::wl_keyboard::Resource *focusResource) { - Q_UNUSED(client); - Q_UNUSED(time); - DataDevice *data_device = static_cast<DataDevice *>(data_device_resource->data); - DataSource *data_source = static_cast<DataSource *>(source->data); + if (!focusResource) + return; + + Resource *resource = resourceMap().value(focusResource->client()); + + if (!resource) + return; + + if (m_selectionSource) { + DataOffer *offer = new DataOffer(m_selectionSource, resource); + send_selection(resource->handle, offer->resource()->handle); + } +} + +void DataDevice::setDragFocus(Surface *focus, const QPointF &localPosition) +{ + if (m_dragFocusResource) { + send_leave(m_dragFocusResource->handle); + m_dragFocus = 0; + m_dragFocusResource = 0; + } + + if (!focus) + return; + + if (!m_dragDataSource && m_dragClient != focus->resource()->client()) + return; + + Resource *resource = resourceMap().value(focus->resource()->client()); + + if (!resource) + return; + + uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); + + DataOffer *offer = m_dragDataSource ? new DataOffer(m_dragDataSource, resource) : 0; + + if (m_dragDataSource && !offer) + return; - data_device->m_data_device_manager->setCurrentSelectionSource(data_source); + send_enter(resource->handle, serial, focus->resource()->handle, + wl_fixed_from_double(localPosition.x()), wl_fixed_from_double(localPosition.y()), + offer->resource()->handle); + m_dragFocus = focus; + m_dragFocusResource = resource; } -const struct wl_data_device_interface DataDevice::data_device_interface = { - DataDevice::start_drag, - DataDevice::set_selection -}; +Surface *DataDevice::dragIcon() const +{ + return m_dragIcon; +} -DataDevice::DataDevice(DataDeviceManager *data_device_manager, struct wl_client *client, uint32_t id) - : m_data_device_manager(data_device_manager) - , m_sent_selection_time(0) +void DataDevice::focus() { + Surface *focus = m_compositor->pickSurface(m_pointer->currentPosition()); - //static int i = 0; - //qDebug() << "data device" << ++i; - m_data_device_resource = - wl_client_add_object(client,&wl_data_device_interface,&data_device_interface,id, this); + if (focus != m_dragFocus) + setDragFocus(focus, m_compositor->mapToSurface(focus, m_pointer->currentPosition())); } -void DataDevice::sendSelectionFocus() +void DataDevice::motion(uint32_t time) { - if (m_data_device_manager->offerFromCompositorToClient(m_data_device_resource)) - return; + if (m_dragIcon) { + m_dragIcon->setPos(m_pointer->currentPosition()); + } - DataSource *source = m_data_device_manager->currentSelectionSource(); - if (!source || !source->client()) { - m_data_device_manager->offerRetainedSelection(m_data_device_resource); - return; + if (m_dragFocusResource && m_dragFocus) { + const QPointF &surfacePoint = m_compositor->mapToSurface(m_dragFocus, m_pointer->currentPosition()); + qDebug() << Q_FUNC_INFO << m_pointer->currentPosition() << surfacePoint; + send_motion(m_dragFocusResource->handle, time, + wl_fixed_from_double(surfacePoint.x()), wl_fixed_from_double(surfacePoint.y())); } - if (source->time() > m_sent_selection_time) { //this makes sure we don't resend - if (source->client() != m_data_device_resource->client) { //don't send selection to the client that owns the selection - DataOffer *data_offer = source->dataOffer(); - wl_resource *client_resource = - data_offer->addDataDeviceResource(m_data_device_resource); - //qDebug() << "sending data_offer for source" << source; - wl_data_device_send_selection(m_data_device_resource,client_resource); - m_sent_selection_time = source->time(); +} + +void DataDevice::button(uint32_t time, Qt::MouseButton button, uint32_t state) +{ + Q_UNUSED(time); + + if (m_dragFocusResource && + m_pointer->grabButton() == button && + state == Pointer::button_state_released) + send_drop(m_dragFocusResource->handle); + + if (!m_pointer->buttonPressed() && + state == Pointer::button_state_released) { + + if (m_dragIcon) { + m_dragIcon = 0; + Q_EMIT m_inputDevice->dragHandle()->iconChanged(); } + + setDragFocus(0, QPointF()); + m_pointer->endGrab(); + } +} + +void DataDevice::data_device_start_drag(Resource *resource, struct ::wl_resource *source, struct ::wl_resource *origin, struct ::wl_resource *icon, uint32_t serial) +{ + if (m_inputDevice->pointerDevice()->grabSerial() == serial) { + if (!m_inputDevice->pointerDevice()->buttonPressed() || + m_inputDevice->pointerDevice()->focusSurface() != Surface::fromResource(origin)) + return; + + m_dragClient = resource->client(); + m_dragDataSource = source != 0 ? DataSource::fromResource(source) : 0; + m_dragIcon = icon != 0 ? Surface::fromResource(icon) : 0; + Q_EMIT m_inputDevice->dragHandle()->iconChanged(); + + m_inputDevice->pointerDevice()->setFocus(0, QPointF()); + m_inputDevice->pointerDevice()->startGrab(this); } } -struct wl_resource *DataDevice::dataDeviceResource() const +void DataDevice::data_device_set_selection(Resource *, struct ::wl_resource *source, uint32_t serial) { - return m_data_device_resource; + Q_UNUSED(serial); + + DataSource *dataSource = source ? DataSource::fromResource(source) : 0; + + if (m_selectionSource) + m_selectionSource->cancel(); + + m_selectionSource = dataSource; + + QtWaylandServer::wl_keyboard::Resource *focusResource = m_inputDevice->keyboardDevice()->focusResource(); + Resource *resource = focusResource ? resourceMap().value(focusResource->client()) : 0; + + if (resource && m_selectionSource) { + DataOffer *offer = new DataOffer(m_selectionSource, resource); + send_selection(resource->handle, offer->resource()->handle); + } else if (resource) { + send_selection(resource->handle, 0); + } } } diff --git a/src/compositor/wayland_wrapper/qwldatadevice_p.h b/src/compositor/wayland_wrapper/qwldatadevice_p.h index 2b4acdc9d..edbb517c5 100644 --- a/src/compositor/wayland_wrapper/qwldatadevice_p.h +++ b/src/compositor/wayland_wrapper/qwldatadevice_p.h @@ -41,42 +41,49 @@ #ifndef WLDATADEVICE_H #define WLDATADEVICE_H -#include <private/qwldatadevicemanager_p.h> +#include <qwayland-server-wayland.h> +#include <qwlpointer_p.h> QT_BEGIN_NAMESPACE namespace QtWayland { +class Compositor; class DataSource; -class DataDeviceManager; +class InputDevice; +class Surface; -class DataDevice +class DataDevice : public QtWaylandServer::wl_data_device, public PointerGrabber { public: - DataDevice(DataDeviceManager *data_device_manager, struct wl_client *client, uint32_t id); + DataDevice(InputDevice *inputDevice); - void createAndSetSelectionSource(struct wl_client *client, uint32_t id, const char *name, uint32_t time); - void sendSelectionFocus(); + void setFocus(QtWaylandServer::wl_keyboard::Resource *focusResource); - struct wl_resource *dataDeviceResource() const; + void setDragFocus(Surface *focus, const QPointF &localPosition); + + Surface *dragIcon() const; + + void focus() Q_DECL_OVERRIDE; + void motion(uint32_t time) Q_DECL_OVERRIDE; + void button(uint32_t time, Qt::MouseButton button, uint32_t state) Q_DECL_OVERRIDE; +protected: + void data_device_start_drag(Resource *resource, struct ::wl_resource *source, struct ::wl_resource *origin, struct ::wl_resource *icon, uint32_t serial) Q_DECL_OVERRIDE; + void data_device_set_selection(Resource *resource, struct ::wl_resource *source, uint32_t serial) Q_DECL_OVERRIDE; - struct wl_display *display() const { return m_data_device_manager->display(); } private: - DataDeviceManager *m_data_device_manager; - uint32_t m_sent_selection_time; - struct wl_resource *m_data_device_resource; - - static const struct wl_data_device_interface data_device_interface; - static void start_drag(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *source, - struct wl_resource *surface, - struct wl_resource *icon, - uint32_t time); - static void set_selection(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *source, - uint32_t time); + Compositor *m_compositor; + InputDevice *m_inputDevice; + + DataSource *m_selectionSource; + + struct ::wl_client *m_dragClient; + DataSource *m_dragDataSource; + + Surface *m_dragFocus; + Resource *m_dragFocusResource; + + Surface *m_dragIcon; }; } diff --git a/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp b/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp index c27aa514f..289108563 100644 --- a/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp +++ b/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp @@ -59,12 +59,13 @@ QT_BEGIN_NAMESPACE namespace QtWayland { DataDeviceManager::DataDeviceManager(Compositor *compositor) - : m_compositor(compositor) + : QObject(0) + , wl_data_device_manager(compositor->wl_display()) + , m_compositor(compositor) , m_current_selection_source(0) , m_retainedReadNotifier(0) , m_compositorOwnsSelection(false) { - wl_display_add_global(compositor->wl_display(), &wl_data_device_manager_interface, this, DataDeviceManager::bind_func_drag); } void DataDeviceManager::setCurrentSelectionSource(DataSource *source) @@ -104,13 +105,13 @@ void DataDeviceManager::sourceDestroyed(DataSource *source) void DataDeviceManager::retain() { - QList<QByteArray> offers = m_current_selection_source->offerList(); + QList<QString> offers = m_current_selection_source->mimeTypes(); finishReadFromClient(); if (m_retainedReadIndex >= offers.count()) { m_compositor->feedRetainedSelectionData(&m_retainedData); return; } - QByteArray mimeType = offers.at(m_retainedReadIndex); + QString mimeType = offers.at(m_retainedReadIndex); m_retainedReadBuf.clear(); int fd[2]; if (pipe(fd) == -1) { @@ -118,8 +119,7 @@ void DataDeviceManager::retain() return; } fcntl(fd[0], F_SETFL, fcntl(fd[0], F_GETFL, 0) | O_NONBLOCK); - m_current_selection_source->postSendEvent(mimeType, fd[1]); - close(fd[1]); + m_current_selection_source->send(mimeType, fd[1]); m_retainedReadNotifier = new QSocketNotifier(fd[0], QSocketNotifier::Read, this); connect(m_retainedReadNotifier, SIGNAL(activated(int)), SLOT(readFromClient(int))); } @@ -167,8 +167,8 @@ void DataDeviceManager::readFromClient(int fd) if (n <= 0) { if (n != -1 || (errno != EAGAIN && errno != EWOULDBLOCK)) { finishReadFromClient(true); - QList<QByteArray> offers = m_current_selection_source->offerList(); - QString mimeType = QString::fromLatin1(offers.at(m_retainedReadIndex)); + QList<QString> offers = m_current_selection_source->mimeTypes(); + QString mimeType = offers.at(m_retainedReadIndex); m_retainedData.setData(mimeType, m_retainedReadBuf); ++m_retainedReadIndex; retain(); @@ -188,43 +188,6 @@ struct wl_display *DataDeviceManager::display() const return m_compositor->wl_display(); } -void DataDeviceManager::bind_func_drag(struct wl_client *client, void *data, uint32_t version, uint32_t id) -{ - Q_UNUSED(version); - wl_client_add_object(client,&wl_data_device_manager_interface,&drag_interface,id,data); -} - -void DataDeviceManager::bind_func_data(struct wl_client *client, void *data, uint32_t version, uint32_t id) -{ - Q_UNUSED(client); - Q_UNUSED(data); - Q_UNUSED(version); - Q_UNUSED(id); -} - -void DataDeviceManager::get_data_device(struct wl_client *client, - struct wl_resource *data_device_manager_resource, - uint32_t id, - struct wl_resource *input_device_resource) -{ - DataDeviceManager *data_device_manager = static_cast<DataDeviceManager *>(data_device_manager_resource->data); - InputDevice *input_device = InputDevice::fromSeatResource(input_device_resource); - input_device->clientRequestedDataDevice(data_device_manager,client,id); -} - -void DataDeviceManager::create_data_source(struct wl_client *client, - struct wl_resource *data_device_manager_resource, - uint32_t id) -{ - Q_UNUSED(data_device_manager_resource); - new DataSource(client,id, Compositor::currentTimeMsecs()); -} - -struct wl_data_device_manager_interface DataDeviceManager::drag_interface = { - DataDeviceManager::create_data_source, - DataDeviceManager::get_data_device -}; - void DataDeviceManager::overrideSelection(const QMimeData &mimeData) { QStringList formats = mimeData.formats(); @@ -243,7 +206,7 @@ void DataDeviceManager::overrideSelection(const QMimeData &mimeData) Surface *focusSurface = dev->keyboardFocus(); if (focusSurface) offerFromCompositorToClient( - dev->dataDevice(focusSurface->resource()->client())->dataDeviceResource()); + dev->dataDevice()->resourceMap().value(focusSurface->resource()->client())->handle); } bool DataDeviceManager::offerFromCompositorToClient(wl_resource *clientDataDeviceResource) @@ -275,6 +238,17 @@ void DataDeviceManager::offerRetainedSelection(wl_resource *clientDataDeviceReso offerFromCompositorToClient(clientDataDeviceResource); } +void DataDeviceManager::data_device_manager_create_data_source(Resource *resource, uint32_t id) +{ + new DataSource(resource->client(), id, Compositor::currentTimeMsecs()); +} + +void DataDeviceManager::data_device_manager_get_data_device(Resource *resource, uint32_t id, struct ::wl_resource *seat) +{ + InputDevice *input_device = InputDevice::fromSeatResource(seat); + input_device->clientRequestedDataDevice(this, resource->client(), id); +} + void DataDeviceManager::comp_accept(wl_client *, wl_resource *, uint32_t, const char *) { } diff --git a/src/compositor/wayland_wrapper/qwldatadevicemanager_p.h b/src/compositor/wayland_wrapper/qwldatadevicemanager_p.h index 11510e63b..dcb51e16b 100644 --- a/src/compositor/wayland_wrapper/qwldatadevicemanager_p.h +++ b/src/compositor/wayland_wrapper/qwldatadevicemanager_p.h @@ -48,6 +48,8 @@ #include <QtGui/QClipboard> #include <QtCore/QMimeData> +#include <qwayland-server-wayland.h> + QT_BEGIN_NAMESPACE class QSocketNotifier; @@ -59,7 +61,7 @@ class Compositor; class DataDevice; class DataSource; -class DataDeviceManager : public QObject +class DataDeviceManager : public QObject, public QtWaylandServer::wl_data_device_manager { Q_OBJECT @@ -77,6 +79,10 @@ public: bool offerFromCompositorToClient(wl_resource *clientDataDeviceResource); void offerRetainedSelection(wl_resource *clientDataDeviceResource); +protected: + void data_device_manager_create_data_source(Resource *resource, uint32_t id) Q_DECL_OVERRIDE; + void data_device_manager_get_data_device(Resource *resource, uint32_t id, struct ::wl_resource *seat) Q_DECL_OVERRIDE; + private slots: void readFromClient(int fd); @@ -89,19 +95,6 @@ private: DataSource *m_current_selection_source; - static void bind_func_drag(struct wl_client *client, void *data, - uint32_t version, uint32_t id); - static void bind_func_data(struct wl_client *client, void *data, - uint32_t version, uint32_t id); - static void get_data_device(struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *input_device); - static void create_data_source(struct wl_client *client, - struct wl_resource *resource, - uint32_t id); - static struct wl_data_device_manager_interface drag_interface; - QMimeData m_retainedData; QSocketNotifier *m_retainedReadNotifier; QList<QSocketNotifier *> m_obsoleteRetainedReadNotifiers; diff --git a/src/compositor/wayland_wrapper/qwldataoffer.cpp b/src/compositor/wayland_wrapper/qwldataoffer.cpp index c2bfea35a..86db2dc36 100644 --- a/src/compositor/wayland_wrapper/qwldataoffer.cpp +++ b/src/compositor/wayland_wrapper/qwldataoffer.cpp @@ -41,78 +41,52 @@ #include "qwldataoffer_p.h" #include "qwldatadevice_p.h" +#include "qwldatasource_p.h" -#include <wayland-server.h> - -#include <sys/time.h> #include <unistd.h> -#include <QtCore/QDebug> - QT_BEGIN_NAMESPACE namespace QtWayland { -DataOffer::DataOffer(DataSource *data_source) - : m_data_source(data_source) +DataOffer::DataOffer(DataSource *dataSource, QtWaylandServer::wl_data_device::Resource *target) + : QtWaylandServer::wl_data_offer(dataSource->resource()->client(), 0) + , m_dataSource(dataSource) { - + // FIXME: connect to dataSource and reset m_dataSource on destroy + target->data_device->send_data_offer(target->handle, resource()->handle); + Q_FOREACH (const QString &mimeType, dataSource->mimeTypes()) { + send_offer(mimeType); + } } DataOffer::~DataOffer() { } -struct wl_resource *DataOffer::addDataDeviceResource(struct wl_resource *data_device_resource) +void DataOffer::data_offer_accept(Resource *resource, uint32_t serial, const QString &mimeType) { - if (resourceForClient(data_device_resource->client)) { - qDebug() << "This should not happen, the client tries to add twice to a data offer"; - return 0; - } - struct wl_resource *new_object = - wl_client_new_object(data_device_resource->client,&wl_data_offer_interface,&data_interface,this); - wl_data_device_send_data_offer(data_device_resource, new_object); - - registerResource(new_object); - QList<QByteArray> offer_list = m_data_source->offerList(); - for (int i = 0; i < offer_list.size(); i++) { - wl_data_offer_send_offer(new_object, offer_list.at(i).constData()); - } - return new_object; + if (m_dataSource) + m_dataSource->accept(mimeType); } -const struct wl_data_offer_interface DataOffer::data_interface = { - DataOffer::accept, - DataOffer::receive, - DataOffer::destroy -}; - -void DataOffer::accept(wl_client *client, wl_resource *resource, uint32_t time, const char *type) +void DataOffer::data_offer_receive(Resource *resource, const QString &mimeType, int32_t fd) { - Q_UNUSED(client); - Q_UNUSED(resource); - Q_UNUSED(time); - Q_UNUSED(type); + if (m_dataSource) + m_dataSource->send(mimeType, fd); + else + close(fd); } -void DataOffer::receive(wl_client *client, wl_resource *resource, const char *mime_type, int32_t fd) +void DataOffer::data_offer_destroy(Resource *resource) { - Q_UNUSED(client); - - DataOffer *offer = static_cast<DataOffer *>(resource->data); - offer->m_data_source->postSendEvent(mime_type,fd); - close(fd); + wl_resource_destroy(resource->handle); } -void DataOffer::destroy(wl_client *client, wl_resource *resource) +void DataOffer::data_offer_destroy_resource(Resource *) { - Q_UNUSED(client); - DataOffer *data_offer = static_cast<DataOffer *>(resource->data); - - if (data_offer->resourceListIsEmpty()) { - delete data_offer; - } + delete this; } } diff --git a/src/compositor/wayland_wrapper/qwldataoffer_p.h b/src/compositor/wayland_wrapper/qwldataoffer_p.h index 579434450..d29658576 100644 --- a/src/compositor/wayland_wrapper/qwldataoffer_p.h +++ b/src/compositor/wayland_wrapper/qwldataoffer_p.h @@ -41,37 +41,29 @@ #ifndef WLDATAOFFER_H #define WLDATAOFFER_H -#include <private/qwldatasource_p.h> -#include <QtCompositor/qwaylandresourcecollection.h> +#include <qwayland-server-wayland.h> QT_BEGIN_NAMESPACE namespace QtWayland { -class DataOffer : public ResourceCollection +class DataSource; + +class DataOffer : public QtWaylandServer::wl_data_offer { public: - DataOffer(DataSource *data_source); + DataOffer(DataSource *data_source, QtWaylandServer::wl_data_device::Resource *target); ~DataOffer(); - struct wl_resource *addDataDeviceResource(struct wl_resource *client_resource); -private: - DataSource *m_data_source; - - static void accept(struct wl_client *client, - struct wl_resource *resource, - uint32_t time, - const char *type); - static void receive(struct wl_client *client, - struct wl_resource *resource, - const char *mime_type, - int32_t fd); - static void destroy(struct wl_client *client, - struct wl_resource *resource); - - static const struct wl_data_offer_interface data_interface; +protected: + void data_offer_accept(Resource *resource, uint32_t serial, const QString &mime_type) Q_DECL_OVERRIDE; + void data_offer_receive(Resource *resource, const QString &mime_type, int32_t fd) Q_DECL_OVERRIDE; + void data_offer_destroy(Resource *resource) Q_DECL_OVERRIDE; + void data_offer_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; +private: + DataSource *m_dataSource; }; } diff --git a/src/compositor/wayland_wrapper/qwldatasource.cpp b/src/compositor/wayland_wrapper/qwldatasource.cpp index d60ec5108..a31ed8e70 100644 --- a/src/compositor/wayland_wrapper/qwldatasource.cpp +++ b/src/compositor/wayland_wrapper/qwldatasource.cpp @@ -40,23 +40,20 @@ #include "qwldatasource_p.h" #include "qwldataoffer_p.h" +#include "qwldatadevice_p.h" #include "qwldatadevicemanager_p.h" #include "qwlcompositor_p.h" -#include <wayland-wayland-server-protocol.h> - -#include <QtCore/QDebug> +#include <unistd.h> QT_BEGIN_NAMESPACE namespace QtWayland { DataSource::DataSource(struct wl_client *client, uint32_t id, uint32_t time) - : m_time(time) + : QtWaylandServer::wl_data_source(client, id) + , m_time(time) { - m_data_source_resource = wl_client_add_object(client, &wl_data_source_interface, &DataSource::data_source_interface,id,this); - m_data_source_resource->destroy = resource_destroy; - m_data_offer = new DataOffer(this); m_manager = 0; } @@ -64,71 +61,57 @@ DataSource::~DataSource() { if (m_manager) m_manager->sourceDestroyed(this); - wl_resource_destroy(m_data_source_resource); } -void DataSource::resource_destroy(wl_resource *resource) +uint32_t DataSource::time() const { - DataSource *source = static_cast<DataSource *>(resource->data); - if (source && source->m_data_source_resource == resource) - source->m_data_source_resource = 0; - free(resource); + return m_time; } -uint32_t DataSource::time() const +QList<QString> DataSource::mimeTypes() const { - return m_time; + return m_mimeTypes; } -QList<QByteArray> DataSource::offerList() const +void DataSource::accept(const QString &mimeType) { - return m_offers; + send_target(mimeType); } -struct wl_data_source_interface DataSource::data_source_interface = { - DataSource::offer, - DataSource::destroy -}; +void DataSource::send(const QString &mimeType, int fd) +{ + send_send(mimeType, fd); + close(fd); +} -void DataSource::offer(struct wl_client *client, - struct wl_resource *resource, - const char *type) +void DataSource::cancel() { - Q_UNUSED(client); - //qDebug() << "received offer" << type; - static_cast<DataSource *>(resource->data)->m_offers.append(type); + send_cancelled(); } -void DataSource::destroy(struct wl_client *client, - struct wl_resource *resource) +void DataSource::setManager(DataDeviceManager *mgr) { - Q_UNUSED(client); - DataSource *self = static_cast<DataSource *>(resource->data); - delete self; + m_manager = mgr; } -DataOffer * DataSource::dataOffer() const +DataSource *DataSource::fromResource(struct ::wl_resource *resource) { - return m_data_offer; + return static_cast<DataSource *>(Resource::fromResource(resource)->data_source); } -void DataSource::postSendEvent(const QByteArray &mimeType, int fd) +void DataSource::data_source_offer(Resource *, const QString &mime_type) { - if (m_data_source_resource) { - wl_data_source_send_send(m_data_source_resource, mimeType.constData(), fd); - } + m_mimeTypes.append(mime_type); } -struct wl_client *DataSource::client() const +void DataSource::data_source_destroy(Resource *resource) { - if (m_data_source_resource) - return m_data_source_resource->client; - return 0; + wl_resource_destroy(resource->handle); } -void DataSource::setManager(DataDeviceManager *mgr) +void DataSource::data_source_destroy_resource(QtWaylandServer::wl_data_source::Resource *resource) { - m_manager = mgr; + delete this; } } diff --git a/src/compositor/wayland_wrapper/qwldatasource_p.h b/src/compositor/wayland_wrapper/qwldatasource_p.h index be855d8da..c46e71380 100644 --- a/src/compositor/wayland_wrapper/qwldatasource_p.h +++ b/src/compositor/wayland_wrapper/qwldatasource_p.h @@ -41,9 +41,8 @@ #ifndef WLDATASOURCE_H #define WLDATASOURCE_H -#include <wayland-server.h> +#include <qwayland-server-wayland.h> -#include <QtCore/QByteArray> #include <QtCore/QList> QT_BEGIN_NAMESPACE @@ -53,38 +52,32 @@ namespace QtWayland { class DataOffer; class DataDeviceManager; -class DataSource +class DataSource : public QtWaylandServer::wl_data_source { public: DataSource(struct wl_client *client, uint32_t id, uint32_t time); ~DataSource(); uint32_t time() const; - QList<QByteArray> offerList() const; + QList<QString> mimeTypes() const; - DataOffer *dataOffer() const; - - void postSendEvent(const QByteArray &mimeType,int fd); - struct wl_client *client() const; + void accept(const QString &mimeType); + void send(const QString &mimeType,int fd); + void cancel(); void setManager(DataDeviceManager *mgr); + static DataSource *fromResource(struct ::wl_resource *resource); + +protected: + void data_source_offer(Resource *resource, const QString &mime_type) Q_DECL_OVERRIDE; + void data_source_destroy(Resource *resource) Q_DECL_OVERRIDE; + void data_source_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; + private: uint32_t m_time; - QList<QByteArray> m_offers; - struct wl_resource *m_data_source_resource; - - DataOffer *m_data_offer; + QList<QString> m_mimeTypes; DataDeviceManager *m_manager; - - static struct wl_data_source_interface data_source_interface; - static void offer(struct wl_client *client, - struct wl_resource *resource, - const char *type); - static void destroy(struct wl_client *client, - struct wl_resource *resource); - - static void resource_destroy(struct wl_resource *resource); }; } diff --git a/src/compositor/wayland_wrapper/qwlinputdevice.cpp b/src/compositor/wayland_wrapper/qwlinputdevice.cpp index bde898995..de448c53b 100644 --- a/src/compositor/wayland_wrapper/qwlinputdevice.cpp +++ b/src/compositor/wayland_wrapper/qwlinputdevice.cpp @@ -47,6 +47,7 @@ #include "qwlqttouch_p.h" #include "qwlqtkey_p.h" #include "qwaylandcompositor.h" +#include "qwaylanddrag.h" #include "qwlpointer_p.h" #include "qwlkeyboard_p.h" #include "qwltouch_p.h" @@ -60,17 +61,18 @@ namespace QtWayland { InputDevice::InputDevice(QWaylandInputDevice *handle, Compositor *compositor) : QtWaylandServer::wl_seat(compositor->wl_display()) , m_handle(handle) + , m_dragHandle(new QWaylandDrag(this)) , m_compositor(compositor) , m_pointer(new Pointer(m_compositor, this)) , m_keyboard(new Keyboard(m_compositor, this)) , m_touch(new Touch(m_compositor)) , m_inputMethod(m_compositor->extensions() & QWaylandCompositor::TextInputExtension ? new InputMethod(m_compositor, this) : 0) + , m_data_device() { } InputDevice::~InputDevice() { - qDeleteAll(m_data_devices); } Pointer *InputDevice::pointerDevice() @@ -108,9 +110,9 @@ const Touch *InputDevice::touchDevice() const return m_touch.data(); } -void InputDevice::seat_destroy_resource(wl_seat::Resource *resource) +void InputDevice::seat_destroy_resource(wl_seat::Resource *) { - cleanupDataDeviceForClient(resource->client(), true); +// cleanupDataDeviceForClient(resource->client(), true); } void InputDevice::seat_bind_resource(wl_seat::Resource *resource) @@ -254,8 +256,8 @@ bool InputDevice::setKeyboardFocus(Surface *surface) if (surface && surface->transientInactive()) return false; - sendSelectionFocus(surface); m_keyboard->setFocus(surface); + m_data_device->setFocus(m_keyboard->focusResource()); return true; } @@ -273,35 +275,11 @@ void InputDevice::setMouseFocus(Surface *surface, const QPointF &localPos, const m_touch->setFocus(surface); } -void InputDevice::cleanupDataDeviceForClient(struct wl_client *client, bool destroyDev) +void InputDevice::clientRequestedDataDevice(DataDeviceManager *, struct wl_client *client, uint32_t id) { - for (int i = 0; i < m_data_devices.size(); i++) { - struct wl_resource *data_device_resource = - m_data_devices.at(i)->dataDeviceResource(); - if (data_device_resource->client == client) { - if (destroyDev) - delete m_data_devices.at(i); - m_data_devices.removeAt(i); - break; - } - } -} - -void InputDevice::clientRequestedDataDevice(DataDeviceManager *data_device_manager, struct wl_client *client, uint32_t id) -{ - cleanupDataDeviceForClient(client, false); - DataDevice *dataDevice = new DataDevice(data_device_manager,client,id); - m_data_devices.append(dataDevice); -} - -void InputDevice::sendSelectionFocus(Surface *surface) -{ - if (!surface) - return; - DataDevice *device = dataDevice(surface->resource()->client()); - if (device) { - device->sendSelectionFocus(); - } + if (!m_data_device) + m_data_device.reset(new DataDevice(this)); + m_data_device->add(client, id); } Compositor *InputDevice::compositor() const @@ -314,14 +292,14 @@ QWaylandInputDevice *InputDevice::handle() const return m_handle; } -DataDevice *InputDevice::dataDevice(struct wl_client *client) const +QWaylandDrag *InputDevice::dragHandle() const { - for (int i = 0; i < m_data_devices.size();i++) { - if (m_data_devices.at(i)->dataDeviceResource()->client == client) { - return m_data_devices.at(i); - } - } - return 0; + return m_dragHandle; +} + +const DataDevice *InputDevice::dataDevice() const +{ + return m_data_device.data(); } } diff --git a/src/compositor/wayland_wrapper/qwlinputdevice_p.h b/src/compositor/wayland_wrapper/qwlinputdevice_p.h index c3c8fe570..3f7e4cc87 100644 --- a/src/compositor/wayland_wrapper/qwlinputdevice_p.h +++ b/src/compositor/wayland_wrapper/qwlinputdevice_p.h @@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE class QKeyEvent; class QTouchEvent; class QWaylandInputDevice; +class QWaylandDrag; namespace QtWayland { @@ -98,11 +99,11 @@ public: void setMouseFocus(Surface *surface, const QPointF &localPos, const QPointF &globalPos); void clientRequestedDataDevice(DataDeviceManager *dndSelection, struct wl_client *client, uint32_t id); - DataDevice *dataDevice(struct wl_client *client) const; - void sendSelectionFocus(Surface *surface); + const DataDevice *dataDevice() const; Compositor *compositor() const; QWaylandInputDevice *handle() const; + QWaylandDrag *dragHandle() const; Pointer *pointerDevice(); Keyboard *keyboardDevice(); @@ -119,16 +120,15 @@ public: } private: - void cleanupDataDeviceForClient(struct wl_client *client, bool destroyDev); - QWaylandInputDevice *m_handle; + QWaylandDrag *m_dragHandle; Compositor *m_compositor; - QList<DataDevice *> m_data_devices; QScopedPointer<Pointer> m_pointer; QScopedPointer<Keyboard> m_keyboard; QScopedPointer<Touch> m_touch; QScopedPointer<InputMethod> m_inputMethod; + QScopedPointer<DataDevice> m_data_device; void seat_bind_resource(wl_seat::Resource *resource) Q_DECL_OVERRIDE; |