Commit c82b0db0 authored by David Edmundson's avatar David Edmundson
Browse files

Introduce API round primary-selection-unstable-v1.xml AKA middle-click paste

It's mostly a copy-paste of DataDevice.
parent b9381012
......@@ -40,6 +40,10 @@ set(SERVER_LIB_SRCS
pointerconstraints_interface_v1.cpp
pointergestures_interface.cpp
pointergestures_interface_v1.cpp
primaryselectiondevice_v1_interface.cpp
primaryselectiondevicemanager_v1_interface.cpp
primaryselectionoffer_v1_interface.cpp
primaryselectionsource_v1_interface.cpp
region_interface.cpp
relativepointer_interface.cpp
relativepointer_interface_v1.cpp
......@@ -244,6 +248,11 @@ ecm_add_qtwayland_server_protocol(SERVER_LIB_SRCS
BASENAME viewporter
)
ecm_add_qtwayland_server_protocol(SERVER_LIB_SRCS
PROTOCOL ${WaylandProtocols_DATADIR}/unstable/primary-selection/primary-selection-unstable-v1.xml
BASENAME wp-primary-selection-unstable-v1
)
set(SERVER_GENERATED_SRCS
${CMAKE_CURRENT_BINARY_DIR}/wayland-blur-client-protocol.h
${CMAKE_CURRENT_BINARY_DIR}/wayland-blur-server-protocol.h
......@@ -378,6 +387,7 @@ set(SERVER_LIB_HEADERS
pointer_interface.h
pointerconstraints_interface.h
pointergestures_interface.h
primaryselectiondevicemanager_v1_interface.h
region_interface.h
relativepointer_interface.h
remote_access_interface.h
......
......@@ -29,6 +29,7 @@
#include "plasmawindowmanagement_interface.h"
#include "pointerconstraints_interface_p.h"
#include "pointergestures_interface_p.h"
#include "primaryselectiondevicemanager_v1_interface.h"
#include "relativepointer_interface_p.h"
#include "remote_access_interface.h"
#include "seat_interface.h"
......@@ -524,6 +525,13 @@ ViewporterInterface *Display::createViewporter(QObject *parent)
return viewporter;
}
PrimarySelectionDeviceManagerV1Interface *Display::createPrimarySelectionDeviceManagerV1(QObject *parent)
{
auto primarySelection = new PrimarySelectionDeviceManagerV1Interface(this, parent);
connect(this, &Display::aboutToTerminate, primarySelection, [primarySelection] { delete primarySelection; });
return primarySelection;
}
void Display::createShm()
{
Q_ASSERT(d->display);
......
......@@ -78,6 +78,7 @@ class KeyStateInterface;
class LinuxDmabufUnstableV1Interface;
class TabletManagerInterface;
class DataControlDeviceManagerV1Interface;
class PrimarySelectionDeviceManagerV1Interface;
class KeyboardShortcutsInhibitManagerV1Interface;
class ViewporterInterface;
......@@ -333,6 +334,11 @@ public:
*/
ViewporterInterface *createViewporter(QObject *parent = nullptr);
/**
* Creates the PrimarySelectionDeviceManagerV1Interface
*/
PrimarySelectionDeviceManagerV1Interface *createPrimarySelectionDeviceManagerV1(QObject *parent = nullptr);
/**
* Gets the ClientConnection for the given @p client.
* If there is no ClientConnection yet for the given @p client, it will be created.
......
/*
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 "primaryselectiondevice_v1_interface.h"
#include "primaryselectiondevicemanager_v1_interface.h"
#include "primaryselectionoffer_v1_interface.h"
#include "primaryselectionsource_v1_interface.h"
#include "display.h"
#include "seat_interface.h"
#include "seat_interface_p.h"
// Wayland
#include <qwayland-server-wp-primary-selection-unstable-v1.h>
namespace KWaylandServer
{
class PrimarySelectionDeviceV1InterfacePrivate: public QtWaylandServer::zwp_primary_selection_device_v1
{
public:
PrimarySelectionDeviceV1InterfacePrivate(PrimarySelectionDeviceV1Interface *q, SeatInterface *seat, wl_resource *resource);
PrimarySelectionOfferV1Interface *createDataOffer(AbstractDataSource *source);
PrimarySelectionDeviceV1Interface *q;
SeatInterface *seat;
QPointer<PrimarySelectionSourceV1Interface> selection;
private:
void setSelection(PrimarySelectionSourceV1Interface *dataSource);
protected:
void zwp_primary_selection_device_v1_destroy_resource(Resource *resource) override;
void zwp_primary_selection_device_v1_set_selection(Resource *resource, wl_resource *source, uint32_t serial) override;
void zwp_primary_selection_device_v1_destroy(Resource *resource) override;
};
PrimarySelectionDeviceV1InterfacePrivate::PrimarySelectionDeviceV1InterfacePrivate(PrimarySelectionDeviceV1Interface *_q, SeatInterface *seat, wl_resource *resource)
: QtWaylandServer::zwp_primary_selection_device_v1(resource)
, q(_q)
, seat(seat)
{
}
void PrimarySelectionDeviceV1InterfacePrivate::zwp_primary_selection_device_v1_set_selection(Resource *resource, wl_resource *source, uint32_t serial)
{
Q_UNUSED(resource)
Q_UNUSED(serial)
PrimarySelectionSourceV1Interface *dataSource = nullptr;
if (source) {
dataSource = PrimarySelectionSourceV1Interface::get(source);
Q_ASSERT(dataSource);
}
if (selection == dataSource) {
return;
}
if (selection) {
selection->cancel();
}
selection = dataSource;
if (selection) {
emit q->selectionChanged(selection);
}
}
void PrimarySelectionDeviceV1InterfacePrivate::zwp_primary_selection_device_v1_destroy(QtWaylandServer::zwp_primary_selection_device_v1::Resource *resource)
{
wl_resource_destroy(resource->handle);
}
PrimarySelectionOfferV1Interface *PrimarySelectionDeviceV1InterfacePrivate::createDataOffer(AbstractDataSource *source)
{
if (!source) {
// a data offer can only exist together with a source
return nullptr;
}
wl_resource *data_offer_resource = wl_resource_create(resource()->client(), &zwp_primary_selection_offer_v1_interface, resource()->version(), 0);
if (!data_offer_resource) {
wl_resource_post_no_memory(resource()->handle);
return nullptr;
}
PrimarySelectionOfferV1Interface *offer = new PrimarySelectionOfferV1Interface(source, data_offer_resource);
send_data_offer(offer->resource());
offer->sendAllOffers();
return offer;
}
void PrimarySelectionDeviceV1InterfacePrivate::zwp_primary_selection_device_v1_destroy_resource(QtWaylandServer::zwp_primary_selection_device_v1::Resource *resource)
{
Q_UNUSED(resource)
delete q;
}
PrimarySelectionDeviceV1Interface::PrimarySelectionDeviceV1Interface(SeatInterface *seat, wl_resource *resource)
: QObject()
, d(new PrimarySelectionDeviceV1InterfacePrivate(this, seat, resource))
{
seat->d_func()->registerPrimarySelectionDevice(this);
}
PrimarySelectionDeviceV1Interface::~PrimarySelectionDeviceV1Interface() = default;
SeatInterface *PrimarySelectionDeviceV1Interface::seat() const
{
return d->seat;
}
PrimarySelectionSourceV1Interface *PrimarySelectionDeviceV1Interface::selection() const
{
return d->selection;
}
void PrimarySelectionDeviceV1Interface::sendSelection(AbstractDataSource *other)
{
if (!other) {
sendClearSelection();
return;
}
PrimarySelectionOfferV1Interface *offer = d->createDataOffer(other);
if (!offer) {
return;
}
d->send_selection(offer->resource());
}
void PrimarySelectionDeviceV1Interface::sendClearSelection()
{
d->send_selection(nullptr);
}
wl_client *PrimarySelectionDeviceV1Interface::client() const
{
return d->resource()->client();
}
}
/*
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
*/
#ifndef WAYLAND_SERVER_PRIMARY_SELECTION_DEVICE_INTERFACE_H
#define WAYLAND_SERVER_PRIMARY_SELECTION_DEVICE_INTERFACE_H
#include <QObject>
#include <KWaylandServer/kwaylandserver_export.h>
struct wl_resource;
struct wl_client;
namespace KWaylandServer
{
class AbstractDataSource;
class PrimarySelectionDeviceManagerV1Interface;
class PrimarySelectionOfferV1Interface;
class PrimarySelectionSourceV1Interface;
class SeatInterface;
class SurfaceInterface;
class PrimarySelectionDeviceV1InterfacePrivate;
/**
* @brief Represents the Resource for the wl_data_device interface.
*
* @see SeatInterface
* @see PrimarySelectionSourceInterface
* Lifespan is mapped to the underlying object
**/
class KWAYLANDSERVER_EXPORT PrimarySelectionDeviceV1Interface : public QObject
{
Q_OBJECT
public:
virtual ~PrimarySelectionDeviceV1Interface();
SeatInterface *seat() const;
PrimarySelectionSourceV1Interface *selection() const;
void sendSelection(AbstractDataSource *other);
void sendClearSelection();
wl_client *client() const;
Q_SIGNALS:
void selectionChanged(KWaylandServer::PrimarySelectionSourceV1Interface*);
void selectionCleared();
private:
friend class PrimarySelectionDeviceManagerV1InterfacePrivate;
explicit PrimarySelectionDeviceV1Interface(SeatInterface *seat, wl_resource *resource);
QScopedPointer<PrimarySelectionDeviceV1InterfacePrivate> d;
};
}
Q_DECLARE_METATYPE(KWaylandServer::PrimarySelectionDeviceV1Interface*)
#endif
/*
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 "primaryselectiondevicemanager_v1_interface.h"
#include "primaryselectiondevice_v1_interface.h"
#include "primaryselectionsource_v1_interface.h"
#include "display.h"
#include "seat_interface_p.h"
// Wayland
#include <qwayland-server-wp-primary-selection-unstable-v1.h>
static const int s_version = 1;
namespace KWaylandServer
{
class PrimarySelectionDeviceManagerV1InterfacePrivate : public QtWaylandServer::zwp_primary_selection_device_manager_v1
{
public:
PrimarySelectionDeviceManagerV1InterfacePrivate(PrimarySelectionDeviceManagerV1Interface *q, Display *d);
PrimarySelectionDeviceManagerV1Interface *q;
protected:
void zwp_primary_selection_device_manager_v1_create_source(Resource *resource, uint32_t id) override;
void zwp_primary_selection_device_manager_v1_get_device(Resource *resource, uint32_t id, wl_resource *seat) override;
void zwp_primary_selection_device_manager_v1_destroy(Resource *resource) override;
};
PrimarySelectionDeviceManagerV1InterfacePrivate::PrimarySelectionDeviceManagerV1InterfacePrivate(PrimarySelectionDeviceManagerV1Interface *q, Display *d)
: QtWaylandServer::zwp_primary_selection_device_manager_v1(*d, s_version)
, q(q)
{
}
void PrimarySelectionDeviceManagerV1InterfacePrivate::zwp_primary_selection_device_manager_v1_create_source(Resource *resource, uint32_t id)
{
wl_resource *data_source_resource = wl_resource_create(resource->client(), &zwp_primary_selection_source_v1_interface, resource->version(), id);
if (!data_source_resource) {
wl_resource_post_no_memory(resource->handle);
return;
}
PrimarySelectionSourceV1Interface *dataSource = new PrimarySelectionSourceV1Interface(q, data_source_resource);
emit q->dataSourceCreated(dataSource);
}
void PrimarySelectionDeviceManagerV1InterfacePrivate::zwp_primary_selection_device_manager_v1_get_device(Resource *resource, uint32_t id, wl_resource *seat)
{
SeatInterface *s = SeatInterface::get(seat);
Q_ASSERT(s);
if (!s) {
return;
}
wl_resource *data_device_resource = wl_resource_create(resource->client(), &zwp_primary_selection_device_v1_interface, resource->version(), id);
if (!data_device_resource) {
wl_resource_post_no_memory(resource->handle);
return;
}
PrimarySelectionDeviceV1Interface *dataDevice = new PrimarySelectionDeviceV1Interface(s, data_device_resource);
emit q->dataDeviceCreated(dataDevice);
}
void PrimarySelectionDeviceManagerV1InterfacePrivate::zwp_primary_selection_device_manager_v1_destroy(Resource *resource)
{
wl_resource_destroy(resource->handle);
}
PrimarySelectionDeviceManagerV1Interface::PrimarySelectionDeviceManagerV1Interface(Display *display, QObject *parent)
: QObject(parent)
, d(new PrimarySelectionDeviceManagerV1InterfacePrivate(this, display))
{
}
PrimarySelectionDeviceManagerV1Interface::~PrimarySelectionDeviceManagerV1Interface() = default;
}
/*
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
*/
#ifndef WAYLAND_SERVER_PRIMARY_SELECTION_DEVICE_MANAGER_INTERFACE_H
#define WAYLAND_SERVER_PRIMARY_SELECTION_DEVICE_MANAGER_INTERFACE_H
#include <QObject>
#include <KWaylandServer/kwaylandserver_export.h>
namespace KWaylandServer
{
class Display;
class PrimarySelectionSourceV1Interface;
class PrimarySelectionDeviceManagerV1InterfacePrivate;
class PrimarySelectionDeviceV1Interface;
/**
* @brief Represents the Global for zwp_primary_selection_manager_v1 interface.
*
**/
class KWAYLANDSERVER_EXPORT PrimarySelectionDeviceManagerV1Interface : public QObject
{
Q_OBJECT
public:
~PrimarySelectionDeviceManagerV1Interface();
Q_SIGNALS:
void dataSourceCreated(KWaylandServer::PrimarySelectionSourceV1Interface *dataSource);
void dataDeviceCreated(KWaylandServer::PrimarySelectionDeviceV1Interface *dataDevice);
private:
explicit PrimarySelectionDeviceManagerV1Interface(Display *display, QObject *parent = nullptr);
friend class Display;
QScopedPointer<PrimarySelectionDeviceManagerV1InterfacePrivate> d;
};
}
#endif
/*
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 "primaryselectionoffer_v1_interface.h"
#include "primaryselectiondevice_v1_interface.h"
#include "primaryselectionsource_v1_interface.h"
// Qt
#include <QStringList>
#include <QPointer>
// Wayland
#include <qwayland-server-wp-primary-selection-unstable-v1.h>
// system
#include <unistd.h>
namespace KWaylandServer
{
class PrimarySelectionOfferV1InterfacePrivate : public QtWaylandServer::zwp_primary_selection_offer_v1
{
public:
PrimarySelectionOfferV1InterfacePrivate(PrimarySelectionOfferV1Interface *q, AbstractDataSource *source, wl_resource *resource);
PrimarySelectionOfferV1Interface *q;
QPointer<AbstractDataSource> source;
protected:
void zwp_primary_selection_offer_v1_receive(Resource *resource, const QString &mime_type, int32_t fd) override;
void zwp_primary_selection_offer_v1_destroy(Resource *resource) override;
void zwp_primary_selection_offer_v1_destroy_resource(Resource *resource) override;
};
PrimarySelectionOfferV1InterfacePrivate::PrimarySelectionOfferV1InterfacePrivate(PrimarySelectionOfferV1Interface *_q, AbstractDataSource *source, wl_resource *resource)
: QtWaylandServer::zwp_primary_selection_offer_v1(resource)
, q(_q)
, source(source)
{
}
void PrimarySelectionOfferV1InterfacePrivate::zwp_primary_selection_offer_v1_destroy(QtWaylandServer::zwp_primary_selection_offer_v1::Resource *resource)
{
wl_resource_destroy(resource->handle);
}
void PrimarySelectionOfferV1InterfacePrivate::zwp_primary_selection_offer_v1_destroy_resource(QtWaylandServer::zwp_primary_selection_offer_v1::Resource *resource)
{
Q_UNUSED(resource)
delete q;
}
void PrimarySelectionOfferV1InterfacePrivate::zwp_primary_selection_offer_v1_receive(Resource *resource, const QString &mimeType, qint32 fd)
{
Q_UNUSED(resource)
if (!source) {
close(fd);
return;
}
source->requestData(mimeType, fd);
}
PrimarySelectionOfferV1Interface::PrimarySelectionOfferV1Interface(AbstractDataSource *source, wl_resource *resource)
: QObject()
, d(new PrimarySelectionOfferV1InterfacePrivate(this, source, resource))
{
Q_ASSERT(source);
connect(source, &AbstractDataSource::mimeTypeOffered, this,
[this](const QString &mimeType) {
d->send_offer(mimeType);
}
);
}
PrimarySelectionOfferV1Interface::~PrimarySelectionOfferV1Interface() = default;
void PrimarySelectionOfferV1Interface::sendAllOffers()
{
for (const QString &mimeType : d->source->mimeTypes()) {
d->send_offer(mimeType);
}
}
wl_resource *PrimarySelectionOfferV1Interface::resource() const
{
return d->resource()->handle;
}
}
/*
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
*/
#ifndef WAYLAND_SERVER_PRIMARY_SELECTION_OFFER_INTERFACE_H
#define WAYLAND_SERVER_PRIMARY_SELECTION_OFFER_INTERFACE_H
#include <QObject>
#include <KWaylandServer/kwaylandserver_export.h>
#include "primaryselectiondevicemanager_v1_interface.h"
struct wl_resource;
namespace KWaylandServer
{
class AbstractDataSource;
class PrimarySelectionDeviceV1Interface;
class PrimarySelectionSourceV1Interface;
class PrimarySelectionOfferV1InterfacePrivate;
/**
* @brief Represents the Resource for the wl_data_offer interface.
* Lifespan is mapped to the underlying object
**/
class KWAYLANDSERVER_EXPORT PrimarySelectionOfferV1Interface : public QObject
{
Q_OBJECT
public:
~PrimarySelectionOfferV1Interface() override;
void sendAllOffers();
wl_resource *resource() const;
private:
friend class PrimarySelectionDeviceV1InterfacePrivate;
explicit PrimarySelectionOfferV1Interface(AbstractDataSource *source, wl_resource *resource);
QScopedPointer<PrimarySelectionOfferV1InterfacePrivate> d;
};
}
Q_DECLARE_METATYPE(KWaylandServer::PrimarySelectionOfferV1Interface*)
#endif
/*
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 "primaryselectionsource_v1_interface.h"
#include "primaryselectiondevicemanager_v1_interface.h"
#include "clientconnection.h"
// Qt
#include <QStringList>
// Wayland
#include <qwayland-server-wp-primary-selection-unstable-v1.h>
// system
#include <unistd.h>
namespace KWaylandServer
{
class PrimarySelectionSourceV1InterfacePrivate : public QtWaylandServer::zwp_primary_selection_source_v1
{
public:
PrimarySelectionSourceV1InterfacePrivate(PrimarySelectionSourceV1Interface *q, ::wl_resource *resource);
QStringList mimeTypes;
PrimarySelectionSourceV1Interface *q;
protected:
void zwp_primary_selection_source_v1_destroy_resource(Resource *resource) override;
void zwp_primary_selection_source_v1_offer(Resource *resource, const QString &mime_type) override;
void zwp_primary_selection_source_v1_destroy(Resource *resource) override;
};
PrimarySelectionSourceV1InterfacePrivate::PrimarySelectionSourceV1InterfacePrivate(PrimarySelectionSourceV1Interface *_q, ::wl_resource *resource)
: QtWaylandServer::zwp_primary_selection_source_v1(resource)
, q(_q)
{
}
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();
delete q;
}
void PrimarySelectionSourceV1InterfacePrivate::zwp_primary_selection_source_v1_offer(Resource *, const QString &mimeType)
{
mimeTypes << mimeType;
emit q->mimeTypeOffered(mimeType);
}
void PrimarySelectionSourceV1InterfacePrivate::zwp_primary_selection_source_v1_destroy(QtWaylandServer::zwp_primary_selection_source_v1::Resource *resource)
{
wl_resource_destroy(resource->handle);
}
PrimarySelectionSourceV1Interface::PrimarySelectionSourceV1Interface(PrimarySelectionDeviceManagerV1Interface *parent, ::wl_resource *resource)
: AbstractDataSource(nullptr, parent)
, d(new PrimarySelectionSourceV1InterfacePrivate(this, resource))
{
}