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

It's mostly a copy-paste of DataDevice.
This commit is contained in:
David Edmundson 2020-06-01 23:29:53 +01:00
parent 963551d775
commit e712c5db2b
14 changed files with 732 additions and 0 deletions

View file

@ -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

View file

@ -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);

View file

@ -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.

View file

@ -0,0 +1,143 @@
/*
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();
}
}

View file

@ -0,0 +1,64 @@
/*
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

View file

@ -0,0 +1,77 @@
/*
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;
}

View file

@ -0,0 +1,43 @@
/*
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

View file

@ -0,0 +1,87 @@
/*
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;
}
}

View file

@ -0,0 +1,48 @@
/*
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

View file

@ -0,0 +1,92 @@
/*
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))
{
}
PrimarySelectionSourceV1Interface::~PrimarySelectionSourceV1Interface() = default;
void PrimarySelectionSourceV1Interface::requestData(const QString &mimeType, qint32 fd)
{
d->send_send(mimeType, fd);
close(fd);
}
void PrimarySelectionSourceV1Interface::cancel()
{
d->send_cancelled();
}
QStringList PrimarySelectionSourceV1Interface::mimeTypes() const
{
return d->mimeTypes;
}
wl_client *PrimarySelectionSourceV1Interface::client()
{
return d->resource()->client();
}
PrimarySelectionSourceV1Interface *PrimarySelectionSourceV1Interface::get(wl_resource *native)
{
auto priv = static_cast<PrimarySelectionSourceV1InterfacePrivate*>(QtWaylandServer::zwp_primary_selection_source_v1::Resource::fromResource(native)->object());
return priv->q;
}
}

View file

@ -0,0 +1,49 @@
/*
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_SOURCE_INTERFACE_H
#define WAYLAND_SERVER_PRIMARY_SELECTION_SOURCE_INTERFACE_H
#include "abstract_data_source.h"
#include <KWaylandServer/kwaylandserver_export.h>
#include "primaryselectiondevicemanager_v1_interface.h"
namespace KWaylandServer
{
class PrimarySelectionSourceV1InterfacePrivate;
/**
* @brief Represents the Resource for the zwp_primary_selection_source_v1 interface.
* Lifespan is mapped to the underlying object
**/
class KWAYLANDSERVER_EXPORT PrimarySelectionSourceV1Interface : public AbstractDataSource
{
Q_OBJECT
public:
~PrimarySelectionSourceV1Interface() override;
void requestData(const QString &mimeType, qint32 fd) override;
void cancel() override;
QStringList mimeTypes() const override;
static PrimarySelectionSourceV1Interface *get(wl_resource *native);
wl_client *client() override;
private:
friend class PrimarySelectionDeviceManagerV1InterfacePrivate;
explicit PrimarySelectionSourceV1Interface(PrimarySelectionDeviceManagerV1Interface *parent, ::wl_resource *resource);
QScopedPointer<PrimarySelectionSourceV1InterfacePrivate> d;
};
}
Q_DECLARE_METATYPE(KWaylandServer::PrimarySelectionSourceV1Interface*)
#endif

View file

@ -16,6 +16,8 @@
#include "keyboard_interface_p.h"
#include "pointer_interface.h"
#include "pointer_interface_p.h"
#include "primaryselectiondevice_v1_interface.h"
#include "primaryselectionsource_v1_interface.h"
#include "surface_interface.h"
#include "textinput_interface_p.h"
// Qt
@ -359,6 +361,37 @@ void SeatInterface::Private::registerDataControlDevice(DataControlDeviceV1Interf
}
}
void SeatInterface::Private::registerPrimarySelectionDevice(PrimarySelectionDeviceV1Interface *primarySelectionDevice)
{
Q_ASSERT(primarySelectionDevice->seat() == q);
primarySelectionDevices << primarySelectionDevice;
auto dataDeviceCleanup = [this, primarySelectionDevice] {
primarySelectionDevices.removeOne(primarySelectionDevice);
keys.focus.primarySelections.removeOne(primarySelectionDevice);
};
QObject::connect(primarySelectionDevice, &QObject::destroyed, q, dataDeviceCleanup);
QObject::connect(primarySelectionDevice, &PrimarySelectionDeviceV1Interface::selectionChanged, q,
[this, primarySelectionDevice] {
updatePrimarySelection(primarySelectionDevice);
}
);
QObject::connect(primarySelectionDevice, &PrimarySelectionDeviceV1Interface::selectionCleared, q,
[this, primarySelectionDevice] {
updatePrimarySelection(primarySelectionDevice);
}
);
// is the new DataDevice for the current keyoard focus?
if (keys.focus.surface) {
// same client?
if (*keys.focus.surface->client() == primarySelectionDevice->client()) {
keys.focus.primarySelections.append(primarySelectionDevice);
if (currentPrimarySelection) {
primarySelectionDevice->sendSelection(currentPrimarySelection);
}
}
}
}
void SeatInterface::Private::registerTextInput(TextInputInterface *ti)
{
@ -412,6 +445,15 @@ void SeatInterface::Private::updateSelection(DataDeviceInterface *dataDevice)
q->setSelection(dataDevice->selection());
}
void SeatInterface::Private::updatePrimarySelection(PrimarySelectionDeviceV1Interface *primarySelectionDevice)
{
// if the update is from the focussed window we should inform the active client
if (!(keys.focus.surface && (*keys.focus.surface->client() == primarySelectionDevice->client()))) {
return;
}
q->setPrimarySelection(primarySelectionDevice->selection());
}
void SeatInterface::setHasKeyboard(bool has)
{
Q_D();
@ -1134,6 +1176,22 @@ void SeatInterface::setFocusedKeyboardSurface(SurfaceInterface *surface)
dataDevice->sendClearSelection();
}
}
// primary selection
QVector<PrimarySelectionDeviceV1Interface *> primarySelectionDevices;
for (auto it = d->primarySelectionDevices.constBegin(); it != d->primarySelectionDevices.constEnd(); ++it) {
if ((*it)->client() == *surface->client()) {
primarySelectionDevices << *it;
}
}
d->keys.focus.primarySelections = primarySelectionDevices;
for (auto primaryDataDevice : primarySelectionDevices) {
if (d->currentSelection) {
primaryDataDevice->sendSelection(d->currentPrimarySelection);
} else {
primaryDataDevice->sendClearSelection();
}
}
}
for (auto it = d->keys.focus.keyboards.constBegin(), end = d->keys.focus.keyboards.constEnd(); it != end; ++it) {
(*it)->setFocusedSurface(surface, serial);
@ -1632,4 +1690,36 @@ void SeatInterface::setSelection(AbstractDataSource *selection)
emit selectionChanged(selection);
}
void SeatInterface::setPrimarySelection(AbstractDataSource *selection)
{
Q_D();
if (d->currentPrimarySelection == selection) {
return;
}
if (d->currentPrimarySelection) {
d->currentPrimarySelection->cancel();
disconnect(d->currentPrimarySelection, nullptr, this, nullptr);
}
if (selection) {
auto cleanup = [this]() {
setPrimarySelection(nullptr);
};
connect(selection, &DataSourceInterface::unbound, this, cleanup);
}
d->currentPrimarySelection = selection;
for (auto focussedSelection: qAsConst(d->keys.focus.primarySelections)) {
if (selection) {
focussedSelection->sendSelection(selection);
} else {
focussedSelection->sendClearSelection();
}
}
emit primarySelectionChanged(selection);
}
}

View file

@ -712,6 +712,8 @@ public:
**/
void setSelection(AbstractDataSource *selection);
void setPrimarySelection(AbstractDataSource *selection);
static SeatInterface *get(wl_resource *native);
Q_SIGNALS:
@ -741,6 +743,12 @@ Q_SIGNALS:
**/
void selectionChanged(KWaylandServer::AbstractDataSource*);
/**
* Emitted whenever the primary selection changes
* @see primarySelection
**/
void primarySelectionChanged(KWaylandServer::AbstractDataSource*);
/**
* Emitted when a drag'n'drop operation is started
* @since 5.6
@ -769,6 +777,7 @@ Q_SIGNALS:
private:
friend class Display;
friend class DataControlDeviceV1Interface;
friend class PrimarySelectionDeviceV1Interface;
friend class DataDeviceManagerInterface;
friend class TextInputManagerUnstableV0Interface;
friend class TextInputManagerUnstableV2Interface;

View file

@ -24,6 +24,7 @@ class DataDeviceInterface;
class DataSourceInterface;
class DataControlDeviceV1Interface;
class TextInputInterface;
class PrimarySelectionDeviceV1Interface;
class SeatInterface::Private : public Global::Private
{
@ -37,6 +38,7 @@ public:
QVector<TouchInterface *> touchsForSurface(SurfaceInterface *surface) const;
QVector<DataDeviceInterface *> dataDevicesForSurface(SurfaceInterface *surface) const;
TextInputInterface *textInputForSurface(SurfaceInterface *surface) const;
void registerPrimarySelectionDevice(PrimarySelectionDeviceV1Interface *primarySelectionDevice);
void registerDataDevice(DataDeviceInterface *dataDevice);
void registerDataControlDevice(DataControlDeviceV1Interface *dataDevice);
void registerTextInput(TextInputInterface *textInput);
@ -52,12 +54,14 @@ public:
QVector<KeyboardInterface*> keyboards;
QVector<TouchInterface*> touchs;
QVector<DataDeviceInterface*> dataDevices;
QVector<PrimarySelectionDeviceV1Interface*> primarySelectionDevices;
QVector<DataControlDeviceV1Interface*> dataControlDevices;
QVector<TextInputInterface*> textInputs;
// the last thing copied into the clipboard content
AbstractDataSource *currentSelection = nullptr;
AbstractDataSource *currentPrimarySelection = nullptr;
// Pointer related members
struct Pointer {
@ -109,6 +113,7 @@ public:
QMetaObject::Connection destroyConnection;
quint32 serial = 0;
QVector<DataDeviceInterface *> selections;
QVector<PrimarySelectionDeviceV1Interface *> primarySelections;
};
Focus focus;
quint32 lastStateSerial = 0;
@ -173,6 +178,7 @@ private:
void getKeyboard(wl_client *client, wl_resource *resource, uint32_t id);
void getTouch(wl_client *client, wl_resource *resource, uint32_t id);
void updateSelection(DataDeviceInterface *dataDevice);
void updatePrimarySelection(PrimarySelectionDeviceV1Interface *primarySelectionDevice);
static Private *cast(wl_resource *r);
static void unbind(wl_resource *r);