diff options
author | Laszlo Agocs <laszlo.p.agocs@nokia.com> | 2012-01-17 15:32:32 +0200 |
---|---|---|
committer | Jørgen Lind <jorgen.lind@nokia.com> | 2012-01-17 17:30:52 +0100 |
commit | d458c31998f5e4fcf85cf31e4b9033fd18f77052 (patch) | |
tree | 112f8830e3b87a36012c7b4dd638680b64bf0ac7 /src/compositor/wayland_wrapper | |
parent | c4d4ca361744c689a6dd9b2436931fdcb5aa6df8 (diff) |
Implement selection offers from compositor to clients.
It is a hack but works beautifully. It allows the compositor to
participate in copy-paste which becomes mandatory when there is UI
running in the compositor process.
Change-Id: I1993d8705a26159eff0c9947244b66e954b9f460
Sanity-Review: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Jørgen Lind <jorgen.lind@nokia.com>
Diffstat (limited to 'src/compositor/wayland_wrapper')
5 files changed, 102 insertions, 5 deletions
diff --git a/src/compositor/wayland_wrapper/wayland_wrapper.pri b/src/compositor/wayland_wrapper/wayland_wrapper.pri index 4c1f6ee13..843f3d6d4 100644 --- a/src/compositor/wayland_wrapper/wayland_wrapper.pri +++ b/src/compositor/wayland_wrapper/wayland_wrapper.pri @@ -20,7 +20,8 @@ HEADERS += \ $$PWD/wlextendedsurface.h \ $$PWD/wlextendedoutput.h \ $$PWD/wlsubsurface.h \ - $$PWD/wltouch.h + $$PWD/wltouch.h \ + $$PWD/../../shared/qwaylandmimehelper.h SOURCES += \ $$PWD/wlcompositor.cpp \ @@ -37,5 +38,8 @@ SOURCES += \ $$PWD/wlextendedsurface.cpp \ $$PWD/wlextendedoutput.cpp \ $$PWD/wlsubsurface.cpp \ - $$PWD/wltouch.cpp + $$PWD/wltouch.cpp \ + $$PWD/../../shared/qwaylandmimehelper.cpp + +INCLUDEPATH += $$PWD/../../shared diff --git a/src/compositor/wayland_wrapper/wlcompositor.cpp b/src/compositor/wayland_wrapper/wlcompositor.cpp index 3c453d0a1..23e225255 100644 --- a/src/compositor/wayland_wrapper/wlcompositor.cpp +++ b/src/compositor/wayland_wrapper/wlcompositor.cpp @@ -402,8 +402,7 @@ void Compositor::feedRetainedSelectionData(QMimeData *data) void Compositor::overrideSelection(QMimeData *data) { - Q_UNUSED(data); - // ### TODO implement + m_data_device_manager->overrideSelection(*data); } bool Compositor::isDragging() const diff --git a/src/compositor/wayland_wrapper/wldatadevice.cpp b/src/compositor/wayland_wrapper/wldatadevice.cpp index f4b2f2b46..bdabf29a4 100644 --- a/src/compositor/wayland_wrapper/wldatadevice.cpp +++ b/src/compositor/wayland_wrapper/wldatadevice.cpp @@ -103,7 +103,9 @@ DataDevice::DataDevice(DataDeviceManager *data_device_manager, struct wl_client void DataDevice::sendSelectionFocus() { - //do for all clipboards + if (m_data_device_manager->offerFromCompositorToClient(m_data_device_resource)) + return; + DataSource *source = m_data_device_manager->currentSelectionSource(); if (!source) { return; diff --git a/src/compositor/wayland_wrapper/wldatadevicemanager.cpp b/src/compositor/wayland_wrapper/wldatadevicemanager.cpp index ba8510bc5..d3e3fb784 100644 --- a/src/compositor/wayland_wrapper/wldatadevicemanager.cpp +++ b/src/compositor/wayland_wrapper/wldatadevicemanager.cpp @@ -45,11 +45,14 @@ #include "wlinputdevice.h" #include "wlcompositor.h" #include "wldataoffer.h" +#include "wlsurface.h" +#include "qwaylandmimehelper.h" #include <QtCore/QDebug> #include <QtCore/QSocketNotifier> #include <fcntl.h> #include <QtCore/private/qcore_unix_p.h> +#include <QtCore/QFile> namespace Wayland { @@ -57,6 +60,7 @@ DataDeviceManager::DataDeviceManager(Compositor *compositor) : 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); } @@ -69,6 +73,8 @@ void DataDeviceManager::setCurrentSelectionSource(DataSource *source) return; } + m_compositorOwnsSelection = false; + finishReadFromClient(); m_current_selection_source = source; @@ -210,4 +216,72 @@ struct wl_data_device_manager_interface DataDeviceManager::drag_interface = { DataDeviceManager::get_data_device }; +void DataDeviceManager::overrideSelection(const QMimeData &mimeData) +{ + QStringList formats = mimeData.formats(); + if (formats.isEmpty()) + return; + + m_retainedData.clear(); + foreach (const QString &format, formats) + m_retainedData.setData(format, mimeData.data(format)); + + m_compositor->feedRetainedSelectionData(&m_retainedData); + + m_compositorOwnsSelection = true; + + InputDevice *dev = m_compositor->defaultInputDevice(); + Surface *focusSurface = dev->keyboardFocus(); + if (focusSurface) + offerFromCompositorToClient( + dev->dataDevice(focusSurface->base()->resource.client)->dataDeviceResource()); +} + +bool DataDeviceManager::offerFromCompositorToClient(wl_resource *clientDataDeviceResource) +{ + if (!m_compositorOwnsSelection) + return false; + + wl_client *client = clientDataDeviceResource->client; + qDebug("compositor offers %d types to %p", m_retainedData.formats().count(), client); + + struct wl_resource *selectionOffer = + wl_client_new_object(client, &wl_data_offer_interface, &compositor_offer_interface, this); + wl_resource_post_event(clientDataDeviceResource, WL_DATA_DEVICE_DATA_OFFER, selectionOffer); + foreach (const QString &format, m_retainedData.formats()) { + QByteArray ba = format.toLatin1(); + wl_resource_post_event(selectionOffer, WL_DATA_OFFER_OFFER, ba.constData()); + } + wl_resource_post_event(clientDataDeviceResource, WL_DATA_DEVICE_SELECTION, selectionOffer); + + return true; +} + +void DataDeviceManager::comp_accept(wl_client *, wl_resource *, uint32_t, const char *) +{ +} + +void DataDeviceManager::comp_receive(wl_client *client, wl_resource *resource, const char *mime_type, int32_t fd) +{ + DataDeviceManager *self = static_cast<DataDeviceManager *>(resource->data); + qDebug("client %p wants data for type %s from compositor", client, mime_type); + QByteArray content = QWaylandMimeHelper::getByteArray(&self->m_retainedData, QString::fromLatin1(mime_type)); + if (!content.isEmpty()) { + QFile f; + if (f.open(fd, QIODevice::WriteOnly)) + f.write(content); + } + close(fd); +} + +void DataDeviceManager::comp_destroy(wl_client *, wl_resource *) +{ +} + +const struct wl_data_offer_interface DataDeviceManager::compositor_offer_interface = { + DataDeviceManager::comp_accept, + DataDeviceManager::comp_receive, + DataDeviceManager::comp_destroy +}; + } //namespace diff --git a/src/compositor/wayland_wrapper/wldatadevicemanager.h b/src/compositor/wayland_wrapper/wldatadevicemanager.h index af26cb0e9..75844d207 100644 --- a/src/compositor/wayland_wrapper/wldatadevicemanager.h +++ b/src/compositor/wayland_wrapper/wldatadevicemanager.h @@ -71,6 +71,9 @@ public: void sourceDestroyed(DataSource *source); + void overrideSelection(const QMimeData &mimeData); + bool offerFromCompositorToClient(wl_resource *clientDataDeviceResource); + private slots: void readFromClient(int fd); @@ -102,6 +105,21 @@ private: int m_retainedReadIndex; QByteArray m_retainedReadBuf; + bool m_compositorOwnsSelection; + + + static void comp_accept(struct wl_client *client, + struct wl_resource *resource, + uint32_t time, + const char *type); + static void comp_receive(struct wl_client *client, + struct wl_resource *resource, + const char *mime_type, + int32_t fd); + static void comp_destroy(struct wl_client *client, + struct wl_resource *resource); + + static const struct wl_data_offer_interface compositor_offer_interface; }; } |