Port DataDevice to the new inheritance approach
This was done mostly because I wanted to get rid of the Resource dependency in AbstractDataSource so I can make our xwl bridge direct, but this also fixes up some issues with object lifespan present in the previous version and keeps all our clipboard code in-line.
This commit is contained in:
parent
85d6888504
commit
096deea9ec
24 changed files with 345 additions and 499 deletions
|
@ -8,6 +8,6 @@
|
|||
|
||||
using namespace KWaylandServer;
|
||||
|
||||
AbstractDataSource::AbstractDataSource(Resource::Private *d, QObject *parent)
|
||||
: Resource(d, parent)
|
||||
AbstractDataSource::AbstractDataSource(QObject *parent)
|
||||
: QObject(parent)
|
||||
{}
|
||||
|
|
|
@ -27,10 +27,7 @@ namespace KWaylandServer {
|
|||
// Anything related to selections are pure virtual, content relating
|
||||
// to drag and drop has a default implementation
|
||||
|
||||
|
||||
// TODO ideally this shouldn't inherit from resource as it provides some misleading public methods
|
||||
// This can be resolved once DataSource is ported to the new system
|
||||
class KWAYLANDSERVER_EXPORT AbstractDataSource : public Resource
|
||||
class KWAYLANDSERVER_EXPORT AbstractDataSource : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -64,16 +61,18 @@ public:
|
|||
Q_UNUSED(action);
|
||||
};
|
||||
|
||||
virtual wl_client* client() {
|
||||
return Resource::client()->client();
|
||||
}
|
||||
virtual wl_client* client() const {
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
Q_SIGNALS:
|
||||
void aboutToBeDestroyed();
|
||||
|
||||
void mimeTypeOffered(const QString&);
|
||||
void supportedDragAndDropActionsChanged();
|
||||
|
||||
protected:
|
||||
explicit AbstractDataSource(Resource::Private *d, QObject *parent = nullptr);
|
||||
explicit AbstractDataSource(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
// Wayland
|
||||
#include <wayland-client.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
class TestDataDevice : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -101,8 +103,6 @@ void TestDataDevice::init()
|
|||
registry.setup();
|
||||
|
||||
m_dataDeviceManagerInterface = m_display->createDataDeviceManager(m_display);
|
||||
m_dataDeviceManagerInterface->create();
|
||||
QVERIFY(m_dataDeviceManagerInterface->isValid());
|
||||
|
||||
QVERIFY(dataDeviceManagerSpy.wait());
|
||||
m_dataDeviceManager = registry.createDataDeviceManager(dataDeviceManagerSpy.first().first().value<quint32>(),
|
||||
|
@ -179,8 +179,6 @@ void TestDataDevice::testCreate()
|
|||
QVERIFY(!deviceInterface->origin());
|
||||
QVERIFY(!deviceInterface->icon());
|
||||
QVERIFY(!deviceInterface->selection());
|
||||
QVERIFY(deviceInterface->parentResource());
|
||||
|
||||
|
||||
// this will probably fail, we need to make a selection client side
|
||||
QVERIFY(!m_seatInterface->selection());
|
||||
|
@ -433,12 +431,10 @@ void TestDataDevice::testSetSelection()
|
|||
dataDevice->setSelection(2, dataSource.data());
|
||||
QVERIFY(selectionChangedSpy.wait());
|
||||
// now unbind the dataDevice
|
||||
QSignalSpy unboundSpy(deviceInterface, &DataDeviceInterface::unbound);
|
||||
QSignalSpy unboundSpy(deviceInterface, &QObject::destroyed);
|
||||
QVERIFY(unboundSpy.isValid());
|
||||
dataDevice.reset();
|
||||
QVERIFY(unboundSpy.wait());
|
||||
// send a selection to the unbound data device
|
||||
deviceInterface->sendSelection(deviceInterface->selection());
|
||||
}
|
||||
|
||||
void TestDataDevice::testSendSelectionOnSeat()
|
||||
|
@ -491,7 +487,7 @@ void TestDataDevice::testSendSelectionOnSeat()
|
|||
|
||||
// now let's try to destroy the data device and set a focused keyboard just while the data device is being destroyedd
|
||||
m_seatInterface->setFocusedKeyboardSurface(nullptr);
|
||||
QSignalSpy unboundSpy(serverDataDevice, &Resource::unbound);
|
||||
QSignalSpy unboundSpy(serverDataDevice, &QObject::destroyed);
|
||||
QVERIFY(unboundSpy.isValid());
|
||||
dataDevice.reset();
|
||||
QVERIFY(unboundSpy.wait());
|
||||
|
@ -575,6 +571,21 @@ void TestDataDevice::testReplaceSource()
|
|||
dataSource3.reset();
|
||||
dataDevice2->setSelection(1, dataSource4.data());
|
||||
QVERIFY(selectionOfferedSpy.wait());
|
||||
|
||||
auto dataOffer = selectionOfferedSpy.last()[0].value<DataOffer*>();
|
||||
|
||||
// try to crash by destroying the data source, then requesting data
|
||||
dataSource4.reset();
|
||||
int pipeFds[2];
|
||||
Q_ASSERT(pipe(pipeFds) == 0);
|
||||
|
||||
dataOffer->receive(QStringLiteral("text/plain"), pipeFds[1]);
|
||||
close(pipeFds[1]);
|
||||
|
||||
//spin the event loop, nothing should explode
|
||||
QTest::qWait(10);
|
||||
|
||||
close(pipeFds[0]);
|
||||
}
|
||||
|
||||
void TestDataDevice::testDestroy()
|
||||
|
|
|
@ -29,7 +29,6 @@ private Q_SLOTS:
|
|||
void testTargetAccepts_data();
|
||||
void testTargetAccepts();
|
||||
void testRequestSend();
|
||||
void testRequestSendOnUnbound();
|
||||
void testCancel();
|
||||
void testServerGet();
|
||||
void testDestroy();
|
||||
|
@ -82,8 +81,6 @@ void TestDataSource::init()
|
|||
registry.setup();
|
||||
|
||||
m_dataDeviceManagerInterface = m_display->createDataDeviceManager(m_display);
|
||||
m_dataDeviceManagerInterface->create();
|
||||
QVERIFY(m_dataDeviceManagerInterface->isValid());
|
||||
|
||||
QVERIFY(dataDeviceManagerSpy.wait());
|
||||
m_dataDeviceManager = registry.createDataDeviceManager(dataDeviceManagerSpy.first().first().value<quint32>(),
|
||||
|
@ -131,7 +128,6 @@ void TestDataSource::testOffer()
|
|||
QPointer<DataSourceInterface> serverDataSource = dataSourceCreatedSpy.first().first().value<DataSourceInterface*>();
|
||||
QVERIFY(!serverDataSource.isNull());
|
||||
QCOMPARE(serverDataSource->mimeTypes().count(), 0);
|
||||
QVERIFY(serverDataSource->parentResource());
|
||||
|
||||
QSignalSpy offeredSpy(serverDataSource.data(), SIGNAL(mimeTypeOffered(QString)));
|
||||
QVERIFY(offeredSpy.isValid());
|
||||
|
@ -161,10 +157,6 @@ void TestDataSource::testOffer()
|
|||
dataSource.reset();
|
||||
QVERIFY(!serverDataSource.isNull());
|
||||
wl_display_flush(m_connection->display());
|
||||
// after running the event loop the Wayland event should be delivered, but it uses delete later
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(!serverDataSource.isNull());
|
||||
// so once more event loop
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(serverDataSource.isNull());
|
||||
}
|
||||
|
@ -212,7 +204,6 @@ void TestDataSource::testRequestSend()
|
|||
|
||||
QScopedPointer<DataSource> dataSource(m_dataDeviceManager->createDataSource());
|
||||
QVERIFY(dataSource->isValid());
|
||||
|
||||
QSignalSpy sendRequestedSpy(dataSource.data(), SIGNAL(sendDataRequested(QString,qint32)));
|
||||
QVERIFY(sendRequestedSpy.isValid());
|
||||
|
||||
|
@ -234,28 +225,6 @@ void TestDataSource::testRequestSend()
|
|||
writeFile.close();
|
||||
}
|
||||
|
||||
void TestDataSource::testRequestSendOnUnbound()
|
||||
{
|
||||
// this test verifies that the server doesn't crash when requesting a send on an unbound DataSource
|
||||
using namespace KWayland::Client;
|
||||
using namespace KWaylandServer;
|
||||
QSignalSpy dataSourceCreatedSpy(m_dataDeviceManagerInterface, &DataDeviceManagerInterface::dataSourceCreated);
|
||||
QVERIFY(dataSourceCreatedSpy.isValid());
|
||||
|
||||
QScopedPointer<DataSource> dataSource(m_dataDeviceManager->createDataSource());
|
||||
QVERIFY(dataSource->isValid());
|
||||
QVERIFY(dataSourceCreatedSpy.wait());
|
||||
QCOMPARE(dataSourceCreatedSpy.count(), 1);
|
||||
auto sds = dataSourceCreatedSpy.first().first().value<DataSourceInterface*>();
|
||||
QVERIFY(sds);
|
||||
|
||||
QSignalSpy unboundSpy(sds, &Resource::unbound);
|
||||
QVERIFY(unboundSpy.isValid());
|
||||
dataSource.reset();
|
||||
QVERIFY(unboundSpy.wait());
|
||||
sds->requestData(QStringLiteral("text/plain"), -1);
|
||||
}
|
||||
|
||||
void TestDataSource::testCancel()
|
||||
{
|
||||
using namespace KWayland::Client;
|
||||
|
|
|
@ -84,8 +84,6 @@ void TestDragAndDrop::init()
|
|||
m_seatInterface->create();
|
||||
QVERIFY(m_seatInterface->isValid());
|
||||
m_dataDeviceManagerInterface = m_display->createDataDeviceManager(m_display);
|
||||
m_dataDeviceManagerInterface->create();
|
||||
QVERIFY(m_dataDeviceManagerInterface->isValid());
|
||||
m_display->createShm();
|
||||
|
||||
m_thread = new QThread(this);
|
||||
|
|
|
@ -72,7 +72,6 @@ void SelectionTest::init()
|
|||
m_seatInterface->setHasKeyboard(true);
|
||||
m_seatInterface->create();
|
||||
m_ddmInterface = m_display->createDataDeviceManager(m_display);
|
||||
m_ddmInterface->create();
|
||||
|
||||
// setup connection
|
||||
setupConnection(&m_client1);
|
||||
|
|
|
@ -1814,7 +1814,6 @@ void TestWaylandSeat::testSelection()
|
|||
using namespace KWayland::Client;
|
||||
using namespace KWaylandServer;
|
||||
QScopedPointer<DataDeviceManagerInterface> ddmi(m_display->createDataDeviceManager());
|
||||
ddmi->create();
|
||||
Registry registry;
|
||||
QSignalSpy dataDeviceManagerSpy(®istry, SIGNAL(dataDeviceManagerAnnounced(quint32,quint32)));
|
||||
QVERIFY(dataDeviceManagerSpy.isValid());
|
||||
|
@ -1927,7 +1926,6 @@ void TestWaylandSeat::testDataDeviceForKeyboardSurface()
|
|||
using namespace KWaylandServer;
|
||||
// create the DataDeviceManager
|
||||
QScopedPointer<DataDeviceManagerInterface> ddmi(m_display->createDataDeviceManager());
|
||||
ddmi->create();
|
||||
QSignalSpy ddiCreatedSpy(ddmi.data(), &DataDeviceManagerInterface::dataDeviceCreated);
|
||||
QVERIFY(ddiCreatedSpy.isValid());
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ public:
|
|||
AbstractDataSource(nullptr)
|
||||
{}
|
||||
~TestDataSource() {
|
||||
emit unbound();
|
||||
emit aboutToBeDestroyed();
|
||||
}
|
||||
void requestData(const QString &mimeType, qint32 fd) override {
|
||||
Q_UNUSED(mimeType);
|
||||
|
|
|
@ -40,7 +40,7 @@ DataControlSourceV1InterfacePrivate::DataControlSourceV1InterfacePrivate(DataCon
|
|||
void DataControlSourceV1InterfacePrivate::zwlr_data_control_source_v1_destroy_resource(QtWaylandServer::zwlr_data_control_source_v1::Resource *resource)
|
||||
{
|
||||
Q_UNUSED(resource)
|
||||
emit q->unbound();
|
||||
emit q->aboutToBeDestroyed();
|
||||
delete q;
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ void DataControlSourceV1InterfacePrivate::zwlr_data_control_source_v1_destroy(Qt
|
|||
}
|
||||
|
||||
DataControlSourceV1Interface::DataControlSourceV1Interface(DataControlDeviceManagerV1Interface *parent, ::wl_resource *resource)
|
||||
: AbstractDataSource(nullptr, parent)
|
||||
: AbstractDataSource(parent)
|
||||
, d(new DataControlSourceV1InterfacePrivate(this, resource))
|
||||
{
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ QStringList DataControlSourceV1Interface::mimeTypes() const
|
|||
return d->mimeTypes;
|
||||
}
|
||||
|
||||
wl_client *DataControlSourceV1Interface::client()
|
||||
wl_client *DataControlSourceV1Interface::client() const
|
||||
{
|
||||
return d->resource()->client();
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
void cancel() override;
|
||||
|
||||
QStringList mimeTypes() const override;
|
||||
wl_client *client() override;
|
||||
wl_client *client() const override;
|
||||
|
||||
static DataControlSourceV1Interface *get(wl_resource *native);
|
||||
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "datadevice_interface.h"
|
||||
#include "datadevicemanager_interface.h"
|
||||
#include "dataoffer_interface_p.h"
|
||||
#include "datasource_interface.h"
|
||||
#include "dataoffer_interface.h"
|
||||
#include "display.h"
|
||||
#include "resource_p.h"
|
||||
#include "pointer_interface.h"
|
||||
#include "seat_interface.h"
|
||||
#include "seat_interface_p.h"
|
||||
#include "surface_interface.h"
|
||||
// Wayland
|
||||
#include <wayland-server.h>
|
||||
#include <qwayland-server-wayland.h>
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
|
||||
class DataDeviceInterface::Private : public Resource::Private
|
||||
class DataDeviceInterfacePrivate : public QtWaylandServer::wl_data_device
|
||||
{
|
||||
public:
|
||||
Private(SeatInterface *seat, DataDeviceInterface *q, DataDeviceManagerInterface *manager, wl_resource *parentResource);
|
||||
~Private();
|
||||
DataDeviceInterfacePrivate(SeatInterface *seat, DataDeviceInterface *_q, wl_resource *resource);
|
||||
|
||||
DataOfferInterface *createDataOffer(AbstractDataSource *source);
|
||||
|
||||
|
@ -31,9 +31,7 @@ public:
|
|||
SurfaceInterface *surface = nullptr;
|
||||
SurfaceInterface *icon = nullptr;
|
||||
|
||||
DataSourceInterface *selection = nullptr;
|
||||
QMetaObject::Connection selectionUnboundConnection;
|
||||
QMetaObject::Connection selectionDestroyedConnection;
|
||||
QPointer<DataSourceInterface> selection;
|
||||
|
||||
struct Drag {
|
||||
SurfaceInterface *surface = nullptr;
|
||||
|
@ -45,47 +43,34 @@ public:
|
|||
};
|
||||
Drag drag;
|
||||
|
||||
DataDeviceInterface *q;
|
||||
|
||||
QPointer<SurfaceInterface> proxyRemoteSurface;
|
||||
|
||||
private:
|
||||
DataDeviceInterface *q_func() {
|
||||
return reinterpret_cast<DataDeviceInterface*>(q);
|
||||
}
|
||||
void startDrag(DataSourceInterface *dataSource, SurfaceInterface *origin, SurfaceInterface *icon, quint32 serial);
|
||||
void setSelection(DataSourceInterface *dataSource);
|
||||
static void startDragCallback(wl_client *client, wl_resource *resource, wl_resource *source, wl_resource *origin, wl_resource *icon, uint32_t serial);
|
||||
static void setSelectionCallback(wl_client *client, wl_resource *resource, wl_resource *source, uint32_t serial);
|
||||
|
||||
static const struct wl_data_device_interface s_interface;
|
||||
protected:
|
||||
void data_device_destroy_resource(Resource *resource) override;
|
||||
void data_device_start_drag(Resource *resource, wl_resource *source, wl_resource *origin, wl_resource *icon, uint32_t serial) override;
|
||||
void data_device_set_selection(Resource *resource, wl_resource *source, uint32_t serial) override;
|
||||
void data_device_release(Resource *resource) override;
|
||||
};
|
||||
|
||||
#ifndef K_DOXYGEN
|
||||
const struct wl_data_device_interface DataDeviceInterface::Private::s_interface = {
|
||||
startDragCallback,
|
||||
setSelectionCallback,
|
||||
resourceDestroyedCallback
|
||||
};
|
||||
#endif
|
||||
|
||||
DataDeviceInterface::Private::Private(SeatInterface *seat, DataDeviceInterface *q, DataDeviceManagerInterface *manager, wl_resource *parentResource)
|
||||
: Resource::Private(q, manager, parentResource, &wl_data_device_interface, &s_interface)
|
||||
DataDeviceInterfacePrivate::DataDeviceInterfacePrivate(SeatInterface *seat, DataDeviceInterface *_q, wl_resource *resource)
|
||||
: QtWaylandServer::wl_data_device(resource)
|
||||
, seat(seat)
|
||||
, q(_q)
|
||||
{
|
||||
}
|
||||
|
||||
DataDeviceInterface::Private::~Private() = default;
|
||||
|
||||
void DataDeviceInterface::Private::startDragCallback(wl_client *client, wl_resource *resource, wl_resource *source, wl_resource *origin, wl_resource *icon, uint32_t serial)
|
||||
void DataDeviceInterfacePrivate::data_device_start_drag(Resource *resource, wl_resource *sourceResource, wl_resource *originResource, wl_resource *iconResource, uint32_t serial)
|
||||
{
|
||||
Q_UNUSED(client)
|
||||
Q_UNUSED(serial)
|
||||
// TODO: verify serial
|
||||
cast<Private>(resource)->startDrag(DataSourceInterface::get(source), SurfaceInterface::get(origin), SurfaceInterface::get(icon), serial);
|
||||
}
|
||||
Q_UNUSED(resource)
|
||||
SurfaceInterface *focusSurface = SurfaceInterface::get(originResource);
|
||||
SurfaceInterface *i = SurfaceInterface::get(iconResource);
|
||||
DataSourceInterface *dataSource = nullptr;
|
||||
if (sourceResource) {
|
||||
dataSource = DataSourceInterface::get(sourceResource);
|
||||
}
|
||||
|
||||
void DataDeviceInterface::Private::startDrag(DataSourceInterface *dataSource, SurfaceInterface *origin, SurfaceInterface *i, quint32 serial)
|
||||
{
|
||||
SurfaceInterface *focusSurface = origin;
|
||||
if (proxyRemoteSurface) {
|
||||
// origin is a proxy surface
|
||||
focusSurface = proxyRemoteSurface.data();
|
||||
|
@ -100,144 +85,123 @@ void DataDeviceInterface::Private::startDrag(DataSourceInterface *dataSource, Su
|
|||
}
|
||||
}
|
||||
// TODO: source is allowed to be null, handled client internally!
|
||||
Q_Q(DataDeviceInterface);
|
||||
source = dataSource;
|
||||
if (dataSource) {
|
||||
QObject::connect(dataSource, &Resource::aboutToBeUnbound, q, [this] { source = nullptr; });
|
||||
QObject::connect(dataSource, &AbstractDataSource::aboutToBeDestroyed, q, [this] { source = nullptr; });
|
||||
}
|
||||
surface = origin;
|
||||
surface = focusSurface;
|
||||
icon = i;
|
||||
drag.serial = serial;
|
||||
emit q->dragStarted();
|
||||
}
|
||||
|
||||
void DataDeviceInterface::Private::setSelectionCallback(wl_client *client, wl_resource *resource, wl_resource *source, uint32_t serial)
|
||||
void DataDeviceInterfacePrivate::data_device_set_selection(Resource *resource, wl_resource *source, uint32_t serial)
|
||||
{
|
||||
Q_UNUSED(client)
|
||||
Q_UNUSED(resource)
|
||||
Q_UNUSED(serial)
|
||||
// TODO: verify serial
|
||||
cast<Private>(resource)->setSelection(DataSourceInterface::get(source));
|
||||
}
|
||||
DataSourceInterface *dataSource = DataSourceInterface::get(source);
|
||||
|
||||
void DataDeviceInterface::Private::setSelection(DataSourceInterface *dataSource)
|
||||
{
|
||||
if (dataSource && dataSource->supportedDragAndDropActions() && wl_resource_get_version(dataSource->resource()) >= WL_DATA_SOURCE_ACTION_SINCE_VERSION) {
|
||||
wl_resource_post_error(dataSource->resource(), WL_DATA_SOURCE_ERROR_INVALID_SOURCE, "Data source is for drag and drop");
|
||||
wl_resource_post_error(dataSource->resource(), QtWaylandServer::wl_data_source::error_invalid_source, "Data source is for drag and drop");
|
||||
return;
|
||||
}
|
||||
|
||||
if (selection == dataSource) {
|
||||
return;
|
||||
}
|
||||
Q_Q(DataDeviceInterface);
|
||||
QObject::disconnect(selectionUnboundConnection);
|
||||
QObject::disconnect(selectionDestroyedConnection);
|
||||
if (selection) {
|
||||
selection->cancel();
|
||||
}
|
||||
selection = dataSource;
|
||||
if (selection) {
|
||||
auto clearSelection = [this] {
|
||||
setSelection(nullptr);
|
||||
};
|
||||
selectionUnboundConnection = QObject::connect(selection, &Resource::unbound, q, clearSelection);
|
||||
selectionDestroyedConnection = QObject::connect(selection, &QObject::destroyed, q, clearSelection);
|
||||
emit q->selectionChanged(selection);
|
||||
} else {
|
||||
selectionUnboundConnection = QMetaObject::Connection();
|
||||
selectionDestroyedConnection = QMetaObject::Connection();
|
||||
emit q->selectionCleared();
|
||||
}
|
||||
}
|
||||
|
||||
DataOfferInterface *DataDeviceInterface::Private::createDataOffer(AbstractDataSource *source)
|
||||
void DataDeviceInterfacePrivate::data_device_release(QtWaylandServer::wl_data_device::Resource *resource)
|
||||
{
|
||||
wl_resource_destroy(resource->handle);
|
||||
}
|
||||
|
||||
|
||||
DataOfferInterface *DataDeviceInterfacePrivate::createDataOffer(AbstractDataSource *source)
|
||||
{
|
||||
if (!resource) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!source) {
|
||||
// a data offer can only exist together with a source
|
||||
return nullptr;
|
||||
}
|
||||
Q_Q(DataDeviceInterface);
|
||||
DataOfferInterface *offer = new DataOfferInterface(source, q, resource);
|
||||
auto c = q->global()->display()->getConnection(wl_resource_get_client(resource));
|
||||
offer->create(c, wl_resource_get_version(resource), 0);
|
||||
if (!offer->resource()) {
|
||||
// TODO: send error?
|
||||
delete offer;
|
||||
|
||||
wl_resource *data_offer_resource = wl_resource_create(resource()->client(), &wl_data_offer_interface, resource()->version(), 0);
|
||||
if (!data_offer_resource) {
|
||||
wl_resource_post_no_memory(resource()->handle);
|
||||
return nullptr;
|
||||
}
|
||||
wl_data_device_send_data_offer(resource, offer->resource());
|
||||
|
||||
DataOfferInterface *offer = new DataOfferInterface(source, data_offer_resource);
|
||||
send_data_offer(offer->resource());
|
||||
offer->sendAllOffers();
|
||||
return offer;
|
||||
}
|
||||
|
||||
DataDeviceInterface::DataDeviceInterface(SeatInterface *seat, DataDeviceManagerInterface *parent, wl_resource *parentResource)
|
||||
: Resource(new Private(seat, this, parent, parentResource))
|
||||
void DataDeviceInterfacePrivate::data_device_destroy_resource(QtWaylandServer::wl_data_device::Resource *resource)
|
||||
{
|
||||
Q_UNUSED(resource)
|
||||
delete q;
|
||||
}
|
||||
|
||||
DataDeviceInterface::DataDeviceInterface(SeatInterface *seat, wl_resource *resource)
|
||||
: QObject(nullptr)
|
||||
, d(new DataDeviceInterfacePrivate(seat, this, resource))
|
||||
{
|
||||
seat->d_func()->registerDataDevice(this);
|
||||
}
|
||||
|
||||
DataDeviceInterface::~DataDeviceInterface() = default;
|
||||
|
||||
SeatInterface *DataDeviceInterface::seat() const
|
||||
{
|
||||
Q_D();
|
||||
return d->seat;
|
||||
}
|
||||
|
||||
DataSourceInterface *DataDeviceInterface::dragSource() const
|
||||
{
|
||||
Q_D();
|
||||
return d->source;
|
||||
}
|
||||
|
||||
SurfaceInterface *DataDeviceInterface::icon() const
|
||||
{
|
||||
Q_D();
|
||||
return d->icon;
|
||||
}
|
||||
|
||||
SurfaceInterface *DataDeviceInterface::origin() const
|
||||
{
|
||||
Q_D();
|
||||
return d->proxyRemoteSurface ? d->proxyRemoteSurface.data() : d->surface;
|
||||
}
|
||||
|
||||
DataSourceInterface *DataDeviceInterface::selection() const
|
||||
{
|
||||
Q_D();
|
||||
return d->selection;
|
||||
}
|
||||
|
||||
void DataDeviceInterface::sendSelection(AbstractDataSource *other)
|
||||
{
|
||||
Q_D();
|
||||
auto r = d->createDataOffer(other);
|
||||
if (!r) {
|
||||
return;
|
||||
}
|
||||
if (!d->resource) {
|
||||
return;
|
||||
}
|
||||
wl_data_device_send_selection(d->resource, r->resource());
|
||||
d->send_selection(r->resource());
|
||||
}
|
||||
|
||||
void DataDeviceInterface::sendClearSelection()
|
||||
{
|
||||
Q_D();
|
||||
if (!d->resource) {
|
||||
return;
|
||||
}
|
||||
wl_data_device_send_selection(d->resource, nullptr);
|
||||
d->send_selection(nullptr);
|
||||
}
|
||||
|
||||
void DataDeviceInterface::drop()
|
||||
{
|
||||
Q_D();
|
||||
if (!d->resource) {
|
||||
return;
|
||||
}
|
||||
wl_data_device_send_drop(d->resource);
|
||||
d->send_drop();
|
||||
if (d->drag.posConnection) {
|
||||
disconnect(d->drag.posConnection);
|
||||
d->drag.posConnection = QMetaObject::Connection();
|
||||
|
@ -245,15 +209,14 @@ void DataDeviceInterface::drop()
|
|||
disconnect(d->drag.destroyConnection);
|
||||
d->drag.destroyConnection = QMetaObject::Connection();
|
||||
d->drag.surface = nullptr;
|
||||
client()->flush();
|
||||
wl_client_flush(d->resource()->client());
|
||||
}
|
||||
|
||||
void DataDeviceInterface::updateDragTarget(SurfaceInterface *surface, quint32 serial)
|
||||
{
|
||||
Q_D();
|
||||
if (d->drag.surface) {
|
||||
if (d->resource && d->drag.surface->resource()) {
|
||||
wl_data_device_send_leave(d->resource);
|
||||
if (d->drag.surface->resource()) {
|
||||
d->send_leave();
|
||||
}
|
||||
if (d->drag.posConnection) {
|
||||
disconnect(d->drag.posConnection);
|
||||
|
@ -289,48 +252,43 @@ void DataDeviceInterface::updateDragTarget(SurfaceInterface *surface, quint32 se
|
|||
if (d->seat->isDragPointer()) {
|
||||
d->drag.posConnection = connect(d->seat, &SeatInterface::pointerPosChanged, this,
|
||||
[this] {
|
||||
Q_D();
|
||||
const QPointF pos = d->seat->dragSurfaceTransformation().map(d->seat->pointerPos());
|
||||
wl_data_device_send_motion(d->resource, d->seat->timestamp(),
|
||||
d->send_motion(d->seat->timestamp(),
|
||||
wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
|
||||
client()->flush();
|
||||
wl_client_flush(d->resource()->client());
|
||||
}
|
||||
);
|
||||
} else if (d->seat->isDragTouch()) {
|
||||
d->drag.posConnection = connect(d->seat, &SeatInterface::touchMoved, this,
|
||||
[this](qint32 id, quint32 serial, const QPointF &globalPosition) {
|
||||
Q_D();
|
||||
Q_UNUSED(id);
|
||||
if (serial != d->drag.serial) {
|
||||
// different touch down has been moved
|
||||
return;
|
||||
}
|
||||
const QPointF pos = d->seat->dragSurfaceTransformation().map(globalPosition);
|
||||
wl_data_device_send_motion(d->resource, d->seat->timestamp(),
|
||||
wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
|
||||
client()->flush();
|
||||
d->send_motion(d->seat->timestamp(),
|
||||
wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
|
||||
wl_client_flush(d->resource()->client());
|
||||
}
|
||||
);
|
||||
}
|
||||
d->drag.destroyConnection = connect(d->drag.surface, &QObject::destroyed, this,
|
||||
[this] {
|
||||
Q_D();
|
||||
if (d->resource) {
|
||||
wl_data_device_send_leave(d->resource);
|
||||
}
|
||||
d->send_leave();
|
||||
if (d->drag.posConnection) {
|
||||
disconnect(d->drag.posConnection);
|
||||
}
|
||||
d->drag = Private::Drag();
|
||||
d->drag = DataDeviceInterfacePrivate::Drag();
|
||||
}
|
||||
);
|
||||
|
||||
// TODO: handle touch position
|
||||
const QPointF pos = d->seat->dragSurfaceTransformation().map(d->seat->pointerPos());
|
||||
wl_data_device_send_enter(d->resource, serial, surface->resource(),
|
||||
wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()), offer ? offer->resource() : nullptr);
|
||||
d->send_enter(serial, surface->resource(),
|
||||
wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()), offer ? offer->resource() : nullptr);
|
||||
if (offer) {
|
||||
offer->d_func()->sendSourceActions();
|
||||
offer->sendSourceActions();
|
||||
auto matchOffers = [source, offer] {
|
||||
DataDeviceManagerInterface::DnDAction action{DataDeviceManagerInterface::DnDAction::None};
|
||||
if (source->supportedDragAndDropActions().testFlag(offer->preferredDragAndDropAction())) {
|
||||
|
@ -353,25 +311,23 @@ void DataDeviceInterface::updateDragTarget(SurfaceInterface *surface, quint32 se
|
|||
d->drag.targetActionConnection = connect(offer, &DataOfferInterface::dragAndDropActionsChanged, source, matchOffers);
|
||||
d->drag.sourceActionConnection = connect(source, &DataSourceInterface::supportedDragAndDropActionsChanged, source, matchOffers);
|
||||
}
|
||||
d->client->flush();
|
||||
wl_client_flush(d->resource()->client());
|
||||
}
|
||||
|
||||
quint32 DataDeviceInterface::dragImplicitGrabSerial() const
|
||||
{
|
||||
Q_D();
|
||||
return d->drag.serial;
|
||||
}
|
||||
|
||||
void DataDeviceInterface::updateProxy(SurfaceInterface *remote)
|
||||
{
|
||||
Q_D();
|
||||
// TODO: connect destroy signal?
|
||||
d->proxyRemoteSurface = remote;
|
||||
}
|
||||
|
||||
DataDeviceInterface::Private *DataDeviceInterface::d_func() const
|
||||
wl_client *DataDeviceInterface::client()
|
||||
{
|
||||
return reinterpret_cast<DataDeviceInterface::Private*>(d.data());
|
||||
return d->resource()->client();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
@ -21,6 +22,7 @@ class DataSourceInterface;
|
|||
class AbstractDataSource;
|
||||
class SeatInterface;
|
||||
class SurfaceInterface;
|
||||
class DataDeviceInterfacePrivate;
|
||||
|
||||
/**
|
||||
* @brief DataDeviceInterface allows clients to share data by copy-and-paste and drag-and-drop.
|
||||
|
@ -33,7 +35,7 @@ class SurfaceInterface;
|
|||
* @see SeatInterface
|
||||
* @see DataSourceInterface
|
||||
**/
|
||||
class KWAYLANDSERVER_EXPORT DataDeviceInterface : public Resource
|
||||
class KWAYLANDSERVER_EXPORT DataDeviceInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -78,17 +80,17 @@ public:
|
|||
**/
|
||||
void updateProxy(SurfaceInterface *remote);
|
||||
|
||||
wl_client *client();
|
||||
|
||||
Q_SIGNALS:
|
||||
void dragStarted();
|
||||
void selectionChanged(KWaylandServer::DataSourceInterface*);
|
||||
void selectionCleared();
|
||||
|
||||
private:
|
||||
friend class DataDeviceManagerInterface;
|
||||
explicit DataDeviceInterface(SeatInterface *seat, DataDeviceManagerInterface *parent, wl_resource *parentResource);
|
||||
|
||||
class Private;
|
||||
Private *d_func() const;
|
||||
friend class DataDeviceManagerInterfacePrivate;
|
||||
explicit DataDeviceInterface(SeatInterface *seat, wl_resource *resource);
|
||||
QScopedPointer<DataDeviceInterfacePrivate> d;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
@ -9,107 +10,66 @@
|
|||
#include "display.h"
|
||||
#include "seat_interface_p.h"
|
||||
// Wayland
|
||||
#include <wayland-server.h>
|
||||
#include <qwayland-server-wayland.h>
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
|
||||
class DataDeviceManagerInterface::Private : public Global::Private
|
||||
static const quint32 s_version = 3;
|
||||
|
||||
class DataDeviceManagerInterfacePrivate : public QtWaylandServer::wl_data_device_manager
|
||||
{
|
||||
public:
|
||||
Private(DataDeviceManagerInterface *q, Display *d);
|
||||
DataDeviceManagerInterfacePrivate(DataDeviceManagerInterface *q, Display *d);
|
||||
|
||||
DataDeviceManagerInterface *q;
|
||||
private:
|
||||
void bind(wl_client *client, uint32_t version, uint32_t id) override;
|
||||
void createDataSource(wl_client *client, wl_resource *resource, uint32_t id);
|
||||
void getDataDevice(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *seat);
|
||||
|
||||
static void unbind(wl_resource *resource);
|
||||
static void createDataSourceCallback(wl_client *client, wl_resource *resource, uint32_t id);
|
||||
static void getDataDeviceCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *seat);
|
||||
static Private *cast(wl_resource *r) {
|
||||
return reinterpret_cast<Private*>(wl_resource_get_user_data(r));
|
||||
}
|
||||
|
||||
DataDeviceManagerInterface *q;
|
||||
static const struct wl_data_device_manager_interface s_interface;
|
||||
static const quint32 s_version;
|
||||
static const qint32 s_dataDeviceVersion;
|
||||
static const qint32 s_dataSourceVersion;
|
||||
protected:
|
||||
void data_device_manager_create_data_source(Resource *resource, uint32_t id) override;
|
||||
void data_device_manager_get_data_device(Resource *resource, uint32_t id, wl_resource *seat) override;
|
||||
};
|
||||
|
||||
const quint32 DataDeviceManagerInterface::Private::s_version = 3;
|
||||
const qint32 DataDeviceManagerInterface::Private::s_dataDeviceVersion = 3;
|
||||
const qint32 DataDeviceManagerInterface::Private::s_dataSourceVersion = 3;
|
||||
|
||||
#ifndef K_DOXYGEN
|
||||
const struct wl_data_device_manager_interface DataDeviceManagerInterface::Private::s_interface = {
|
||||
createDataSourceCallback,
|
||||
getDataDeviceCallback
|
||||
};
|
||||
#endif
|
||||
|
||||
DataDeviceManagerInterface::Private::Private(DataDeviceManagerInterface *q, Display *d)
|
||||
: Global::Private(d, &wl_data_device_manager_interface, s_version)
|
||||
DataDeviceManagerInterfacePrivate::DataDeviceManagerInterfacePrivate(DataDeviceManagerInterface *q, Display *d)
|
||||
: QtWaylandServer::wl_data_device_manager(*d, s_version)
|
||||
, q(q)
|
||||
{
|
||||
}
|
||||
|
||||
void DataDeviceManagerInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id)
|
||||
void DataDeviceManagerInterfacePrivate::data_device_manager_create_data_source(Resource *resource, uint32_t id)
|
||||
{
|
||||
auto c = display->getConnection(client);
|
||||
wl_resource *resource = c->createResource(&wl_data_device_manager_interface, qMin(version, s_version), id);
|
||||
if (!resource) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
wl_resource_set_implementation(resource, &s_interface, this, unbind);
|
||||
// TODO: should we track?
|
||||
}
|
||||
|
||||
void DataDeviceManagerInterface::Private::unbind(wl_resource *resource)
|
||||
{
|
||||
Q_UNUSED(resource)
|
||||
}
|
||||
|
||||
void DataDeviceManagerInterface::Private::createDataSourceCallback(wl_client *client, wl_resource *resource, uint32_t id)
|
||||
{
|
||||
cast(resource)->createDataSource(client, resource, id);
|
||||
}
|
||||
|
||||
void DataDeviceManagerInterface::Private::createDataSource(wl_client *client, wl_resource *resource, uint32_t id)
|
||||
{
|
||||
DataSourceInterface *dataSource = new DataSourceInterface(q, resource);
|
||||
dataSource->create(display->getConnection(client), qMin(wl_resource_get_version(resource), s_dataSourceVersion) , id);
|
||||
if (!dataSource->resource()) {
|
||||
wl_resource_post_no_memory(resource);
|
||||
delete dataSource;
|
||||
wl_resource *data_source_resource = wl_resource_create(resource->client(), &wl_data_source_interface, resource->version(), id);
|
||||
if (!data_source_resource) {
|
||||
wl_resource_post_no_memory(resource->handle);
|
||||
return;
|
||||
}
|
||||
DataSourceInterface *dataSource = new DataSourceInterface(q, data_source_resource);
|
||||
emit q->dataSourceCreated(dataSource);
|
||||
}
|
||||
|
||||
void DataDeviceManagerInterface::Private::getDataDeviceCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *seat)
|
||||
{
|
||||
cast(resource)->getDataDevice(client, resource, id, seat);
|
||||
}
|
||||
|
||||
void DataDeviceManagerInterface::Private::getDataDevice(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *seat)
|
||||
void DataDeviceManagerInterfacePrivate::data_device_manager_get_data_device(Resource *resource, uint32_t id, wl_resource *seat)
|
||||
{
|
||||
SeatInterface *s = SeatInterface::get(seat);
|
||||
Q_ASSERT(s);
|
||||
DataDeviceInterface *dataDevice = new DataDeviceInterface(s, q, resource);
|
||||
dataDevice->create(display->getConnection(client), qMin(wl_resource_get_version(resource), s_dataDeviceVersion), id);
|
||||
if (!dataDevice->resource()) {
|
||||
wl_resource_post_no_memory(resource);
|
||||
if (!s) {
|
||||
return;
|
||||
}
|
||||
s->d_func()->registerDataDevice(dataDevice);
|
||||
|
||||
wl_resource *data_device_resource = wl_resource_create(resource->client(), &wl_data_device_interface, resource->version(), id);
|
||||
if (!data_device_resource) {
|
||||
wl_resource_post_no_memory(resource->handle);
|
||||
return;
|
||||
}
|
||||
DataDeviceInterface *dataDevice = new DataDeviceInterface(s, data_device_resource);
|
||||
emit q->dataDeviceCreated(dataDevice);
|
||||
}
|
||||
|
||||
DataDeviceManagerInterface::DataDeviceManagerInterface(Display *display, QObject *parent)
|
||||
: Global(new Private(this, display), parent)
|
||||
: QObject(parent)
|
||||
, d(new DataDeviceManagerInterfacePrivate(this, display))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
@ -9,7 +10,6 @@
|
|||
#include <QObject>
|
||||
|
||||
#include <KWaylandServer/kwaylandserver_export.h>
|
||||
#include "global.h"
|
||||
#include "datadevice_interface.h"
|
||||
|
||||
namespace KWaylandServer
|
||||
|
@ -17,20 +17,20 @@ namespace KWaylandServer
|
|||
|
||||
class Display;
|
||||
class DataSourceInterface;
|
||||
class DataDeviceManagerInterfacePrivate;
|
||||
|
||||
/**
|
||||
* @brief Represents the Global for wl_data_device_manager interface.
|
||||
*
|
||||
**/
|
||||
class KWAYLANDSERVER_EXPORT DataDeviceManagerInterface : public Global
|
||||
class KWAYLANDSERVER_EXPORT DataDeviceManagerInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual ~DataDeviceManagerInterface();
|
||||
~DataDeviceManagerInterface() override;
|
||||
|
||||
/**
|
||||
* Drag and Drop actions supported by the DataSourceInterface.
|
||||
* @since 5.XX
|
||||
**/
|
||||
enum class DnDAction {
|
||||
None = 0,
|
||||
|
@ -47,7 +47,7 @@ Q_SIGNALS:
|
|||
private:
|
||||
explicit DataDeviceManagerInterface(Display *display, QObject *parent = nullptr);
|
||||
friend class Display;
|
||||
class Private;
|
||||
QScopedPointer<DataDeviceManagerInterfacePrivate> d;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,159 +1,160 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "dataoffer_interface_p.h"
|
||||
#include "dataoffer_interface.h"
|
||||
#include "datadevice_interface.h"
|
||||
#include "datasource_interface.h"
|
||||
|
||||
// Qt
|
||||
#include <QStringList>
|
||||
#include <QPointer>
|
||||
// Wayland
|
||||
#include <wayland-server.h>
|
||||
#include <qwayland-server-wayland.h>
|
||||
// system
|
||||
#include <unistd.h>
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
|
||||
#ifndef K_DOXYGEN
|
||||
const struct wl_data_offer_interface DataOfferInterface::Private::s_interface = {
|
||||
acceptCallback,
|
||||
receiveCallback,
|
||||
resourceDestroyedCallback,
|
||||
finishCallback,
|
||||
setActionsCallback
|
||||
};
|
||||
#endif
|
||||
|
||||
DataOfferInterface::Private::Private(AbstractDataSource *source, DataDeviceInterface *parentInterface, DataOfferInterface *q, wl_resource *parentResource)
|
||||
: Resource::Private(q, nullptr, parentResource, &wl_data_offer_interface, &s_interface)
|
||||
, source(source)
|
||||
, dataDevice(parentInterface)
|
||||
class DataOfferInterfacePrivate : public QtWaylandServer::wl_data_offer
|
||||
{
|
||||
public:
|
||||
DataOfferInterfacePrivate(AbstractDataSource *source, DataOfferInterface *q, wl_resource *resource);
|
||||
DataOfferInterface *q;
|
||||
QPointer<AbstractDataSource> source;
|
||||
|
||||
// defaults are set to sensible values for < version 3 interfaces
|
||||
DataDeviceManagerInterface::DnDActions supportedDnDActions = DataDeviceManagerInterface::DnDAction::Copy | DataDeviceManagerInterface::DnDAction::Move;
|
||||
DataDeviceManagerInterface::DnDAction preferredDnDAction = DataDeviceManagerInterface::DnDAction::Copy;
|
||||
|
||||
protected:
|
||||
void data_offer_destroy_resource(Resource *resource) override;
|
||||
void data_offer_accept(Resource *resource, uint32_t serial, const QString &mime_type) override;
|
||||
void data_offer_receive(Resource *resource, const QString &mime_type, int32_t fd) override;
|
||||
void data_offer_destroy(Resource *resource) override;
|
||||
void data_offer_finish(Resource *resource) override;
|
||||
void data_offer_set_actions(Resource *resource, uint32_t dnd_actions, uint32_t preferred_action) override;
|
||||
};
|
||||
|
||||
|
||||
DataOfferInterfacePrivate::DataOfferInterfacePrivate(AbstractDataSource *_source, DataOfferInterface *_q, wl_resource *resource)
|
||||
: QtWaylandServer::wl_data_offer(resource)
|
||||
, q(_q)
|
||||
, source(_source)
|
||||
{
|
||||
// TODO: connect to new selections
|
||||
}
|
||||
|
||||
DataOfferInterface::Private::~Private() = default;
|
||||
|
||||
void DataOfferInterface::Private::acceptCallback(wl_client *client, wl_resource *resource, uint32_t serial, const char *mimeType)
|
||||
void DataOfferInterfacePrivate::data_offer_accept(Resource *resource, uint32_t serial, const QString &mime_type)
|
||||
{
|
||||
Q_UNUSED(client)
|
||||
Q_UNUSED(resource)
|
||||
Q_UNUSED(serial)
|
||||
auto p = cast<Private>(resource);
|
||||
if (!p->source) {
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
p->source->accept(mimeType ? QString::fromUtf8(mimeType) : QString());
|
||||
source->accept(mime_type);
|
||||
}
|
||||
|
||||
void DataOfferInterface::Private::receiveCallback(wl_client *client, wl_resource *resource, const char *mimeType, int32_t fd)
|
||||
{
|
||||
Q_UNUSED(client)
|
||||
cast<Private>(resource)->receive(QString::fromUtf8(mimeType), fd);
|
||||
}
|
||||
|
||||
void DataOfferInterface::Private::receive(const QString &mimeType, qint32 fd)
|
||||
void DataOfferInterfacePrivate::data_offer_receive(Resource *resource, const QString &mime_type, int32_t fd)
|
||||
{
|
||||
Q_UNUSED(resource)
|
||||
if (!source) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
source->requestData(mimeType, fd);
|
||||
source->requestData(mime_type, fd);
|
||||
}
|
||||
|
||||
void DataOfferInterface::Private::finishCallback(wl_client *client, wl_resource *resource)
|
||||
void DataOfferInterfacePrivate::data_offer_destroy(QtWaylandServer::wl_data_offer::Resource *resource)
|
||||
{
|
||||
Q_UNUSED(client)
|
||||
auto p = cast<Private>(resource);
|
||||
if (!p->source) {
|
||||
return;
|
||||
}
|
||||
p->source->dndFinished();
|
||||
wl_resource_destroy(resource->handle);
|
||||
}
|
||||
|
||||
void DataOfferInterfacePrivate::data_offer_finish(Resource *resource)
|
||||
{
|
||||
Q_UNUSED(resource)
|
||||
source->dndFinished();
|
||||
// TODO: It is a client error to perform other requests than wl_data_offer.destroy after this one
|
||||
}
|
||||
|
||||
void DataOfferInterface::Private::setActionsCallback(wl_client *client, wl_resource *resource, uint32_t dnd_actions, uint32_t preferred_action)
|
||||
void DataOfferInterfacePrivate::data_offer_set_actions(Resource *resource, uint32_t dnd_actions, uint32_t preferred_action)
|
||||
{
|
||||
// TODO: check it's drag and drop, otherwise send error
|
||||
Q_UNUSED(client)
|
||||
DataDeviceManagerInterface::DnDActions supportedActions;
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) {
|
||||
if (dnd_actions & QtWaylandServer::wl_data_device_manager::dnd_action_copy) {
|
||||
supportedActions |= DataDeviceManagerInterface::DnDAction::Copy;
|
||||
}
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) {
|
||||
if (dnd_actions & QtWaylandServer::wl_data_device_manager::dnd_action_move) {
|
||||
supportedActions |= DataDeviceManagerInterface::DnDAction::Move;
|
||||
}
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) {
|
||||
if (dnd_actions & QtWaylandServer::wl_data_device_manager::dnd_action_ask) {
|
||||
supportedActions |= DataDeviceManagerInterface::DnDAction::Ask;
|
||||
}
|
||||
// verify that the no other actions are sent
|
||||
if (dnd_actions & ~(WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)) {
|
||||
wl_resource_post_error(resource, WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK, "Invalid action mask");
|
||||
if (dnd_actions & ~(QtWaylandServer::wl_data_device_manager::dnd_action_copy | QtWaylandServer::wl_data_device_manager::dnd_action_move | QtWaylandServer::wl_data_device_manager::dnd_action_ask)) {
|
||||
wl_resource_post_error(resource->handle, error_invalid_action_mask, "Invalid action mask");
|
||||
return;
|
||||
}
|
||||
if (preferred_action != WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY &&
|
||||
preferred_action != WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE &&
|
||||
preferred_action != WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK &&
|
||||
preferred_action != WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE) {
|
||||
wl_resource_post_error(resource, WL_DATA_OFFER_ERROR_INVALID_ACTION, "Invalid preferred action");
|
||||
if (preferred_action != QtWaylandServer::wl_data_device_manager::dnd_action_copy &&
|
||||
preferred_action != QtWaylandServer::wl_data_device_manager::dnd_action_move &&
|
||||
preferred_action != QtWaylandServer::wl_data_device_manager::dnd_action_ask &&
|
||||
preferred_action != QtWaylandServer::wl_data_device_manager::dnd_action_none) {
|
||||
wl_resource_post_error(resource->handle, error_invalid_action, "Invalid preferred action");
|
||||
return;
|
||||
}
|
||||
|
||||
DataDeviceManagerInterface::DnDAction preferredAction = DataDeviceManagerInterface::DnDAction::None;
|
||||
if (preferred_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) {
|
||||
if (preferred_action == QtWaylandServer::wl_data_device_manager::dnd_action_copy) {
|
||||
preferredAction = DataDeviceManagerInterface::DnDAction::Copy;
|
||||
} else if (preferred_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) {
|
||||
} else if (preferred_action == QtWaylandServer::wl_data_device_manager::dnd_action_move) {
|
||||
preferredAction = DataDeviceManagerInterface::DnDAction::Move;
|
||||
} else if (preferred_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) {
|
||||
} else if (preferred_action == QtWaylandServer::wl_data_device_manager::dnd_action_ask) {
|
||||
preferredAction = DataDeviceManagerInterface::DnDAction::Ask;
|
||||
}
|
||||
|
||||
auto p = cast<Private>(resource);
|
||||
p->supportedDnDActions = supportedActions;
|
||||
p->preferredDnDAction = preferredAction;
|
||||
emit p->q_func()->dragAndDropActionsChanged();
|
||||
supportedDnDActions = supportedActions;
|
||||
preferredDnDAction = preferredAction;
|
||||
emit q->dragAndDropActionsChanged();
|
||||
}
|
||||
|
||||
void DataOfferInterface::Private::sendSourceActions()
|
||||
void DataOfferInterface::sendSourceActions()
|
||||
{
|
||||
if (!source) {
|
||||
if (!d->source) {
|
||||
return;
|
||||
}
|
||||
if (wl_resource_get_version(resource) < WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION) {
|
||||
if (d->resource()->version() < WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION) {
|
||||
return;
|
||||
}
|
||||
uint32_t wlActions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
|
||||
const auto actions = source->supportedDragAndDropActions();
|
||||
uint32_t wlActions = QtWaylandServer::wl_data_device_manager::dnd_action_none;
|
||||
const auto actions = d->source->supportedDragAndDropActions();
|
||||
if (actions.testFlag(DataDeviceManagerInterface::DnDAction::Copy)) {
|
||||
wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||
wlActions |= QtWaylandServer::wl_data_device_manager::dnd_action_copy;
|
||||
}
|
||||
if (actions.testFlag(DataDeviceManagerInterface::DnDAction::Move)) {
|
||||
wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
||||
wlActions |= QtWaylandServer::wl_data_device_manager::dnd_action_move;
|
||||
}
|
||||
if (actions.testFlag(DataDeviceManagerInterface::DnDAction::Ask)) {
|
||||
wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
||||
wlActions |= QtWaylandServer::wl_data_device_manager::dnd_action_ask;
|
||||
}
|
||||
wl_data_offer_send_source_actions(resource, wlActions);
|
||||
d->send_source_actions(wlActions);
|
||||
}
|
||||
|
||||
DataOfferInterface::DataOfferInterface(AbstractDataSource *source, DataDeviceInterface *parentInterface, wl_resource *parentResource)
|
||||
: Resource(new Private(source, parentInterface, this, parentResource))
|
||||
void DataOfferInterfacePrivate::data_offer_destroy_resource(QtWaylandServer::wl_data_offer::Resource *resource)
|
||||
{
|
||||
Q_UNUSED(resource)
|
||||
delete q;
|
||||
}
|
||||
|
||||
DataOfferInterface::DataOfferInterface(AbstractDataSource *source, wl_resource *resource)
|
||||
: QObject(nullptr)
|
||||
, d(new DataOfferInterfacePrivate(source, this, resource))
|
||||
{
|
||||
Q_ASSERT(source);
|
||||
connect(source, &DataSourceInterface::mimeTypeOffered, this,
|
||||
[this](const QString &mimeType) {
|
||||
Q_D();
|
||||
if (!d->resource) {
|
||||
return;
|
||||
}
|
||||
wl_data_offer_send_offer(d->resource, mimeType.toUtf8().constData());
|
||||
}
|
||||
);
|
||||
QObject::connect(source, &QObject::destroyed, this,
|
||||
[this] {
|
||||
Q_D();
|
||||
d->source = nullptr;
|
||||
d->send_offer(mimeType);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -162,44 +163,40 @@ DataOfferInterface::~DataOfferInterface() = default;
|
|||
|
||||
void DataOfferInterface::sendAllOffers()
|
||||
{
|
||||
Q_D();
|
||||
for (const QString &mimeType : d->source->mimeTypes()) {
|
||||
wl_data_offer_send_offer(d->resource, mimeType.toUtf8().constData());
|
||||
d->send_offer(mimeType);
|
||||
}
|
||||
}
|
||||
|
||||
DataOfferInterface::Private *DataOfferInterface::d_func() const
|
||||
wl_resource *DataOfferInterface::resource() const
|
||||
{
|
||||
return reinterpret_cast<DataOfferInterface::Private*>(d.data());
|
||||
return d->resource()->handle;
|
||||
}
|
||||
|
||||
DataDeviceManagerInterface::DnDActions DataOfferInterface::supportedDragAndDropActions() const
|
||||
{
|
||||
Q_D();
|
||||
return d->supportedDnDActions;
|
||||
}
|
||||
|
||||
DataDeviceManagerInterface::DnDAction DataOfferInterface::preferredDragAndDropAction() const
|
||||
{
|
||||
Q_D();
|
||||
return d->preferredDnDAction;
|
||||
}
|
||||
|
||||
void DataOfferInterface::dndAction(DataDeviceManagerInterface::DnDAction action)
|
||||
{
|
||||
Q_D();
|
||||
if (wl_resource_get_version(d->resource) < WL_DATA_OFFER_ACTION_SINCE_VERSION) {
|
||||
if (d->resource()->version() < WL_DATA_OFFER_ACTION_SINCE_VERSION) {
|
||||
return;
|
||||
}
|
||||
uint32_t wlAction = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
|
||||
uint32_t wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_none;
|
||||
if (action == DataDeviceManagerInterface::DnDAction::Copy) {
|
||||
wlAction = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||
wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_copy;
|
||||
} else if (action == DataDeviceManagerInterface::DnDAction::Move ) {
|
||||
wlAction = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
||||
wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_move;
|
||||
} else if (action == DataDeviceManagerInterface::DnDAction::Ask) {
|
||||
wlAction = WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
||||
wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_ask;
|
||||
}
|
||||
wl_data_offer_send_action(d->resource, wlAction);
|
||||
d->send_action(wlAction);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
@ -18,18 +19,21 @@ namespace KWaylandServer
|
|||
|
||||
class DataDeviceInterface;
|
||||
class AbstractDataSource;
|
||||
class DataOfferInterfacePrivate;
|
||||
|
||||
/**
|
||||
* @brief Represents the Resource for the wl_data_offer interface.
|
||||
*
|
||||
**/
|
||||
class KWAYLANDSERVER_EXPORT DataOfferInterface : public Resource
|
||||
class KWAYLANDSERVER_EXPORT DataOfferInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual ~DataOfferInterface();
|
||||
|
||||
void sendAllOffers();
|
||||
void sendSourceActions();
|
||||
wl_resource *resource() const;
|
||||
|
||||
/**
|
||||
* @returns The Drag and Drop actions supported by this DataOfferInterface.
|
||||
|
@ -58,11 +62,10 @@ Q_SIGNALS:
|
|||
void dragAndDropActionsChanged();
|
||||
|
||||
private:
|
||||
friend class DataDeviceInterface;
|
||||
explicit DataOfferInterface(AbstractDataSource *source, DataDeviceInterface *parentInterface, wl_resource *parentResource);
|
||||
friend class DataDeviceInterfacePrivate;
|
||||
explicit DataOfferInterface(AbstractDataSource *source, wl_resource *resource);
|
||||
|
||||
class Private;
|
||||
Private *d_func() const;
|
||||
QScopedPointer<DataOfferInterfacePrivate> d;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
@ -10,92 +11,91 @@
|
|||
// Qt
|
||||
#include <QStringList>
|
||||
// Wayland
|
||||
#include <wayland-server.h>
|
||||
#include <qwayland-server-wayland.h>
|
||||
// system
|
||||
#include <unistd.h>
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
|
||||
class DataSourceInterface::Private : public Resource::Private
|
||||
class DataSourceInterfacePrivate : public QtWaylandServer::wl_data_source
|
||||
{
|
||||
public:
|
||||
Private(DataSourceInterface *q, DataDeviceManagerInterface *parent, wl_resource *parentResource);
|
||||
~Private();
|
||||
DataSourceInterfacePrivate(DataSourceInterface *_q, ::wl_resource *resource);
|
||||
|
||||
DataSourceInterface *q;
|
||||
QStringList mimeTypes;
|
||||
DataDeviceManagerInterface::DnDActions supportedDnDActions = DataDeviceManagerInterface::DnDAction::None;
|
||||
|
||||
protected:
|
||||
void data_source_destroy_resource(Resource *resource) override;
|
||||
void data_source_offer(Resource *resource, const QString &mime_type) override;
|
||||
void data_source_destroy(Resource *resource) override;
|
||||
void data_source_set_actions(Resource *resource, uint32_t dnd_actions) override;
|
||||
|
||||
private:
|
||||
DataSourceInterface *q_func() {
|
||||
return reinterpret_cast<DataSourceInterface *>(q);
|
||||
}
|
||||
void offer(const QString &mimeType);
|
||||
|
||||
static void offerCallback(wl_client *client, wl_resource *resource, const char *mimeType);
|
||||
static void setActionsCallback(wl_client *client, wl_resource *resource, uint32_t dnd_actions);
|
||||
|
||||
const static struct wl_data_source_interface s_interface;
|
||||
};
|
||||
|
||||
#ifndef K_DOXYGEN
|
||||
const struct wl_data_source_interface DataSourceInterface::Private::s_interface = {
|
||||
offerCallback,
|
||||
resourceDestroyedCallback,
|
||||
setActionsCallback
|
||||
};
|
||||
#endif
|
||||
|
||||
DataSourceInterface::Private::Private(DataSourceInterface *q, DataDeviceManagerInterface *parent, wl_resource *parentResource)
|
||||
: Resource::Private(q, parent, parentResource, &wl_data_source_interface, &s_interface)
|
||||
DataSourceInterfacePrivate::DataSourceInterfacePrivate(DataSourceInterface *_q, ::wl_resource *resource)
|
||||
: QtWaylandServer::wl_data_source(resource)
|
||||
, q(_q)
|
||||
{
|
||||
}
|
||||
|
||||
DataSourceInterface::Private::~Private() = default;
|
||||
|
||||
void DataSourceInterface::Private::offerCallback(wl_client *client, wl_resource *resource, const char *mimeType)
|
||||
void DataSourceInterfacePrivate::data_source_destroy_resource(Resource *resource)
|
||||
{
|
||||
Q_UNUSED(client)
|
||||
cast<Private>(resource)->offer(QString::fromUtf8(mimeType));
|
||||
Q_UNUSED(resource)
|
||||
emit q->aboutToBeDestroyed();
|
||||
delete q;
|
||||
}
|
||||
|
||||
void DataSourceInterface::Private::offer(const QString &mimeType)
|
||||
void DataSourceInterfacePrivate::data_source_offer(QtWaylandServer::wl_data_source::Resource *resource, const QString &mime_type)
|
||||
{
|
||||
Q_UNUSED(resource)
|
||||
mimeTypes << mime_type;
|
||||
emit q->mimeTypeOffered(mime_type);
|
||||
}
|
||||
|
||||
void DataSourceInterfacePrivate::data_source_destroy(QtWaylandServer::wl_data_source::Resource *resource)
|
||||
{
|
||||
wl_resource_destroy(resource->handle);
|
||||
}
|
||||
|
||||
void DataSourceInterfacePrivate::offer(const QString &mimeType)
|
||||
{
|
||||
mimeTypes << mimeType;
|
||||
Q_Q(DataSourceInterface);
|
||||
emit q->mimeTypeOffered(mimeType);
|
||||
}
|
||||
|
||||
void DataSourceInterface::Private::setActionsCallback(wl_client *client, wl_resource *resource, uint32_t dnd_actions)
|
||||
void DataSourceInterfacePrivate::data_source_set_actions(Resource *resource, uint32_t dnd_actions)
|
||||
{
|
||||
Q_UNUSED(client)
|
||||
DataDeviceManagerInterface::DnDActions supportedActions;
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) {
|
||||
if (dnd_actions & QtWaylandServer::wl_data_device_manager::dnd_action_copy) {
|
||||
supportedActions |= DataDeviceManagerInterface::DnDAction::Copy;
|
||||
}
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) {
|
||||
if (dnd_actions & QtWaylandServer::wl_data_device_manager::dnd_action_move) {
|
||||
supportedActions |= DataDeviceManagerInterface::DnDAction::Move;
|
||||
}
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) {
|
||||
if (dnd_actions & QtWaylandServer::wl_data_device_manager::dnd_action_ask) {
|
||||
supportedActions |= DataDeviceManagerInterface::DnDAction::Ask;
|
||||
}
|
||||
// verify that the no other actions are sent
|
||||
if (dnd_actions & ~(WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)) {
|
||||
wl_resource_post_error(resource, WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK, "Invalid action mask");
|
||||
if (dnd_actions & ~(QtWaylandServer::wl_data_device_manager::dnd_action_copy | QtWaylandServer::wl_data_device_manager::dnd_action_move | QtWaylandServer::wl_data_device_manager::dnd_action_ask)) {
|
||||
wl_resource_post_error(resource->handle, QtWaylandServer::wl_data_source::error_invalid_action_mask, "Invalid action mask");
|
||||
return;
|
||||
}
|
||||
auto p = cast<Private>(resource);
|
||||
if (p->supportedDnDActions!= supportedActions) {
|
||||
p->supportedDnDActions = supportedActions;
|
||||
emit p->q_func()->supportedDragAndDropActionsChanged();
|
||||
if (supportedDnDActions!= supportedActions) {
|
||||
supportedDnDActions = supportedActions;
|
||||
emit q->supportedDragAndDropActionsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
DataSourceInterface::DataSourceInterface(DataDeviceManagerInterface *parent, wl_resource *parentResource)
|
||||
: AbstractDataSource(new Private(this, parent, parentResource))
|
||||
DataSourceInterface::DataSourceInterface(DataDeviceManagerInterface *parent, wl_resource *resource)
|
||||
: AbstractDataSource(parent)
|
||||
, d(new DataSourceInterfacePrivate(this, resource))
|
||||
{
|
||||
if (wl_resource_get_version(parentResource) < WL_DATA_SOURCE_ACTION_SINCE_VERSION) {
|
||||
Q_D();
|
||||
if (d->resource()->version() < WL_DATA_SOURCE_ACTION_SINCE_VERSION) {
|
||||
d->supportedDnDActions = DataDeviceManagerInterface::DnDAction::Copy;
|
||||
}
|
||||
}
|
||||
|
@ -104,86 +104,79 @@ DataSourceInterface::~DataSourceInterface() = default;
|
|||
|
||||
void DataSourceInterface::accept(const QString &mimeType)
|
||||
{
|
||||
Q_D();
|
||||
// TODO: does this require a sanity check on the possible mimeType?
|
||||
wl_data_source_send_target(d->resource, mimeType.isEmpty() ? nullptr : mimeType.toUtf8().constData());
|
||||
d->send_target(mimeType);
|
||||
}
|
||||
|
||||
void DataSourceInterface::requestData(const QString &mimeType, qint32 fd)
|
||||
{
|
||||
Q_D();
|
||||
// TODO: does this require a sanity check on the possible mimeType?
|
||||
if (d->resource) {
|
||||
wl_data_source_send_send(d->resource, mimeType.toUtf8().constData(), int32_t(fd));
|
||||
}
|
||||
d->send_send(mimeType, int32_t(fd));
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void DataSourceInterface::cancel()
|
||||
{
|
||||
Q_D();
|
||||
if (!d->resource) {
|
||||
return;
|
||||
}
|
||||
wl_data_source_send_cancelled(d->resource);
|
||||
Resource::client()->flush();
|
||||
d->send_cancelled();
|
||||
}
|
||||
|
||||
QStringList DataSourceInterface::mimeTypes() const
|
||||
{
|
||||
Q_D();
|
||||
return d->mimeTypes;
|
||||
}
|
||||
|
||||
DataSourceInterface *DataSourceInterface::get(wl_resource *native)
|
||||
{
|
||||
return Private::get<DataSourceInterface>(native);
|
||||
}
|
||||
|
||||
DataSourceInterface::Private *DataSourceInterface::d_func() const
|
||||
{
|
||||
return reinterpret_cast<DataSourceInterface::Private*>(d.data());
|
||||
if (!native) {
|
||||
return nullptr;
|
||||
}
|
||||
auto priv = static_cast<DataSourceInterfacePrivate*>(QtWaylandServer::wl_data_source::Resource::fromResource(native)->object());
|
||||
return priv->q;
|
||||
}
|
||||
|
||||
DataDeviceManagerInterface::DnDActions DataSourceInterface::supportedDragAndDropActions() const
|
||||
{
|
||||
Q_D();
|
||||
return d->supportedDnDActions;
|
||||
}
|
||||
|
||||
void DataSourceInterface::dropPerformed()
|
||||
{
|
||||
Q_D();
|
||||
if (wl_resource_get_version(d->resource) < WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION) {
|
||||
if (d->resource()->version() < WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION) {
|
||||
return;
|
||||
}
|
||||
wl_data_source_send_dnd_drop_performed(d->resource);
|
||||
d->send_dnd_drop_performed();
|
||||
}
|
||||
|
||||
void DataSourceInterface::dndFinished()
|
||||
{
|
||||
Q_D();
|
||||
if (wl_resource_get_version(d->resource) < WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) {
|
||||
if (d->resource()->version() < WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) {
|
||||
return;
|
||||
}
|
||||
wl_data_source_send_dnd_finished(d->resource);
|
||||
d->send_dnd_finished();
|
||||
}
|
||||
|
||||
void DataSourceInterface::dndAction(DataDeviceManagerInterface::DnDAction action)
|
||||
{
|
||||
Q_D();
|
||||
if (wl_resource_get_version(d->resource) < WL_DATA_SOURCE_ACTION_SINCE_VERSION) {
|
||||
if (d->resource()->version() < WL_DATA_SOURCE_ACTION_SINCE_VERSION) {
|
||||
return;
|
||||
}
|
||||
uint32_t wlAction = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
|
||||
uint32_t wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_none;
|
||||
if (action == DataDeviceManagerInterface::DnDAction::Copy) {
|
||||
wlAction = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||
wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_copy;
|
||||
} else if (action == DataDeviceManagerInterface::DnDAction::Move ) {
|
||||
wlAction = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
||||
wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_move;
|
||||
} else if (action == DataDeviceManagerInterface::DnDAction::Ask) {
|
||||
wlAction = WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
||||
wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_ask;
|
||||
}
|
||||
wl_data_source_send_action(d->resource, wlAction);
|
||||
d->send_action(wlAction);
|
||||
}
|
||||
|
||||
wl_resource *DataSourceInterface::resource() const
|
||||
{
|
||||
return d->resource()->handle;
|
||||
}
|
||||
|
||||
wl_client *DataSourceInterface::client() const
|
||||
{
|
||||
return d->resource()->client();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
@ -15,6 +16,8 @@
|
|||
namespace KWaylandServer
|
||||
{
|
||||
|
||||
class DataSourceInterfacePrivate;
|
||||
|
||||
/**
|
||||
* @brief Represents the Resource for the wl_data_source interface.
|
||||
**/
|
||||
|
@ -42,12 +45,15 @@ public:
|
|||
void dndFinished() override;
|
||||
void dndAction(DataDeviceManagerInterface::DnDAction action) override;
|
||||
|
||||
wl_resource *resource() const;
|
||||
|
||||
wl_client *client() const override;
|
||||
|
||||
private:
|
||||
friend class DataDeviceManagerInterface;
|
||||
friend class DataDeviceManagerInterfacePrivate;
|
||||
explicit DataSourceInterface(DataDeviceManagerInterface *parent, wl_resource *parentResource);
|
||||
|
||||
class Private;
|
||||
Private *d_func() const;
|
||||
QScopedPointer<DataSourceInterfacePrivate> d;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -38,8 +38,7 @@ PrimarySelectionSourceV1InterfacePrivate::PrimarySelectionSourceV1InterfacePriva
|
|||
void PrimarySelectionSourceV1InterfacePrivate::zwp_primary_selection_source_v1_destroy_resource(QtWaylandServer::zwp_primary_selection_source_v1::Resource *resource)
|
||||
{
|
||||
Q_UNUSED(resource)
|
||||
emit q->aboutToBeUnbound();
|
||||
emit q->unbound();
|
||||
emit q->aboutToBeDestroyed();
|
||||
delete q;
|
||||
}
|
||||
|
||||
|
@ -55,7 +54,7 @@ void PrimarySelectionSourceV1InterfacePrivate::zwp_primary_selection_source_v1_d
|
|||
}
|
||||
|
||||
PrimarySelectionSourceV1Interface::PrimarySelectionSourceV1Interface(PrimarySelectionDeviceManagerV1Interface *parent, ::wl_resource *resource)
|
||||
: AbstractDataSource(nullptr, parent)
|
||||
: AbstractDataSource(parent)
|
||||
, d(new PrimarySelectionSourceV1InterfacePrivate(this, resource))
|
||||
{
|
||||
}
|
||||
|
@ -78,7 +77,7 @@ QStringList PrimarySelectionSourceV1Interface::mimeTypes() const
|
|||
return d->mimeTypes;
|
||||
}
|
||||
|
||||
wl_client *PrimarySelectionSourceV1Interface::client()
|
||||
wl_client *PrimarySelectionSourceV1Interface::client() const
|
||||
{
|
||||
return d->resource()->client();
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
QStringList mimeTypes() const override;
|
||||
|
||||
static PrimarySelectionSourceV1Interface *get(wl_resource *native);
|
||||
wl_client *client() override;
|
||||
wl_client *client() const override;
|
||||
|
||||
private:
|
||||
friend class PrimarySelectionDeviceManagerV1InterfacePrivate;
|
||||
|
|
|
@ -247,7 +247,13 @@ QVector<TouchInterface *> SeatInterface::Private::touchsForSurface(SurfaceInterf
|
|||
|
||||
QVector<DataDeviceInterface *> SeatInterface::Private::dataDevicesForSurface(SurfaceInterface *surface) const
|
||||
{
|
||||
return interfacesForSurface(surface, dataDevices);
|
||||
QVector<DataDeviceInterface *> primarySelectionDevices;
|
||||
for (auto it = dataDevices.constBegin(); it != dataDevices.constEnd(); ++it) {
|
||||
if ((*it)->client() == *surface->client()) {
|
||||
primarySelectionDevices << *it;
|
||||
}
|
||||
}
|
||||
return primarySelectionDevices;
|
||||
}
|
||||
|
||||
void SeatInterface::Private::registerDataDevice(DataDeviceInterface *dataDevice)
|
||||
|
@ -259,7 +265,6 @@ void SeatInterface::Private::registerDataDevice(DataDeviceInterface *dataDevice)
|
|||
keys.focus.selections.removeOne(dataDevice);
|
||||
};
|
||||
QObject::connect(dataDevice, &QObject::destroyed, q, dataDeviceCleanup);
|
||||
QObject::connect(dataDevice, &Resource::unbound, q, dataDeviceCleanup);
|
||||
QObject::connect(dataDevice, &DataDeviceInterface::selectionChanged, q,
|
||||
[this, dataDevice] {
|
||||
updateSelection(dataDevice);
|
||||
|
@ -303,7 +308,7 @@ void SeatInterface::Private::registerDataDevice(DataDeviceInterface *dataDevice)
|
|||
}
|
||||
);
|
||||
if (dataDevice->dragSource()) {
|
||||
drag.dragSourceDestroyConnection = QObject::connect(dataDevice->dragSource(), &Resource::aboutToBeUnbound, q,
|
||||
drag.dragSourceDestroyConnection = QObject::connect(dataDevice->dragSource(), &AbstractDataSource::aboutToBeDestroyed, q,
|
||||
[this] {
|
||||
const auto serial = display->nextSerial();
|
||||
if (drag.target) {
|
||||
|
@ -324,7 +329,7 @@ void SeatInterface::Private::registerDataDevice(DataDeviceInterface *dataDevice)
|
|||
// is the new DataDevice for the current keyoard focus?
|
||||
if (keys.focus.surface) {
|
||||
// same client?
|
||||
if (keys.focus.surface->client() == dataDevice->client()) {
|
||||
if (*keys.focus.surface->client() == dataDevice->client()) {
|
||||
keys.focus.selections.append(dataDevice);
|
||||
if (currentSelection) {
|
||||
dataDevice->sendSelection(currentSelection);
|
||||
|
@ -419,7 +424,7 @@ void SeatInterface::Private::endDrag(quint32 serial)
|
|||
void SeatInterface::Private::updateSelection(DataDeviceInterface *dataDevice)
|
||||
{
|
||||
// if the update is from the focussed window we should inform the active client
|
||||
if (!(keys.focus.surface && (keys.focus.surface->client() == dataDevice->client()))) {
|
||||
if (!(keys.focus.surface && (*keys.focus.surface->client() == dataDevice->client()))) {
|
||||
return;
|
||||
}
|
||||
q->setSelection(dataDevice->selection());
|
||||
|
@ -1644,8 +1649,7 @@ void SeatInterface::setSelection(AbstractDataSource *selection)
|
|||
auto cleanup = [this]() {
|
||||
setSelection(nullptr);
|
||||
};
|
||||
connect(selection, &DataSourceInterface::unbound, this, cleanup);
|
||||
connect(selection, &QObject::destroyed, this, cleanup);
|
||||
connect(selection, &DataSourceInterface::aboutToBeDestroyed, this, cleanup);
|
||||
}
|
||||
|
||||
d->currentSelection = selection;
|
||||
|
@ -1684,7 +1688,7 @@ void SeatInterface::setPrimarySelection(AbstractDataSource *selection)
|
|||
auto cleanup = [this]() {
|
||||
setPrimarySelection(nullptr);
|
||||
};
|
||||
connect(selection, &DataSourceInterface::unbound, this, cleanup);
|
||||
connect(selection, &DataSourceInterface::aboutToBeDestroyed, this, cleanup);
|
||||
}
|
||||
|
||||
d->currentPrimarySelection = selection;
|
||||
|
|
|
@ -780,8 +780,8 @@ Q_SIGNALS:
|
|||
private:
|
||||
friend class Display;
|
||||
friend class DataControlDeviceV1Interface;
|
||||
friend class DataDeviceInterface;
|
||||
friend class PrimarySelectionDeviceV1Interface;
|
||||
friend class DataDeviceManagerInterface;
|
||||
friend class TextInputManagerV2InterfacePrivate;
|
||||
explicit SeatInterface(Display *display, QObject *parent);
|
||||
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2017 Martin Flöser <mgraesslin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#ifndef KWAYLAND_SERVER_DATAOFFERINTERFACE_P_H
|
||||
#define KWAYLAND_SERVER_DATAOFFERINTERFACE_P_H
|
||||
#include "dataoffer_interface.h"
|
||||
#include "datasource_interface.h"
|
||||
#include "resource_p.h"
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
#include <wayland-server.h>
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
|
||||
class Q_DECL_HIDDEN DataOfferInterface::Private : public Resource::Private
|
||||
{
|
||||
public:
|
||||
Private(AbstractDataSource *source, DataDeviceInterface *parentInterface, DataOfferInterface *q, wl_resource *parentResource);
|
||||
~Private();
|
||||
QPointer<AbstractDataSource> source;
|
||||
DataDeviceInterface *dataDevice;
|
||||
// defaults are set to sensible values for < version 3 interfaces
|
||||
DataDeviceManagerInterface::DnDActions supportedDnDActions = DataDeviceManagerInterface::DnDAction::Copy | DataDeviceManagerInterface::DnDAction::Move;
|
||||
DataDeviceManagerInterface::DnDAction preferredDnDAction = DataDeviceManagerInterface::DnDAction::Copy;
|
||||
|
||||
void sendSourceActions();
|
||||
|
||||
private:
|
||||
DataOfferInterface *q_func() {
|
||||
return reinterpret_cast<DataOfferInterface *>(q);
|
||||
}
|
||||
void receive(const QString &mimeType, qint32 fd);
|
||||
static void acceptCallback(wl_client *client, wl_resource *resource, uint32_t serial, const char *mimeType);
|
||||
static void receiveCallback(wl_client *client, wl_resource *resource, const char *mimeType, int32_t fd);
|
||||
static void finishCallback(wl_client *client, wl_resource *resource);
|
||||
static void setActionsCallback(wl_client *client, wl_resource *resource, uint32_t dnd_actions, uint32_t preferred_action);
|
||||
|
||||
static const struct wl_data_offer_interface s_interface;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -240,7 +240,6 @@ int main(int argc, char **argv)
|
|||
Display display;
|
||||
display.start();
|
||||
DataDeviceManagerInterface *ddm = display.createDataDeviceManager();
|
||||
ddm->create();
|
||||
display.createCompositor(&display);
|
||||
XdgShellInterface *shell = display.createXdgShell();
|
||||
display.createShm();
|
||||
|
|
Loading…
Reference in a new issue