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:
parent
963551d775
commit
e712c5db2b
14 changed files with 732 additions and 0 deletions
|
@ -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.
|
||||
|
|
143
src/wayland/primaryselectiondevice_v1_interface.cpp
Normal file
143
src/wayland/primaryselectiondevice_v1_interface.cpp
Normal 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();
|
||||
}
|
||||
|
||||
}
|
64
src/wayland/primaryselectiondevice_v1_interface.h
Normal file
64
src/wayland/primaryselectiondevice_v1_interface.h
Normal 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
|
77
src/wayland/primaryselectiondevicemanager_v1_interface.cpp
Normal file
77
src/wayland/primaryselectiondevicemanager_v1_interface.cpp
Normal 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;
|
||||
}
|
43
src/wayland/primaryselectiondevicemanager_v1_interface.h
Normal file
43
src/wayland/primaryselectiondevicemanager_v1_interface.h
Normal 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
|
87
src/wayland/primaryselectionoffer_v1_interface.cpp
Normal file
87
src/wayland/primaryselectionoffer_v1_interface.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
48
src/wayland/primaryselectionoffer_v1_interface.h
Normal file
48
src/wayland/primaryselectionoffer_v1_interface.h
Normal 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
|
92
src/wayland/primaryselectionsource_v1_interface.cpp
Normal file
92
src/wayland/primaryselectionsource_v1_interface.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
49
src/wayland/primaryselectionsource_v1_interface.h
Normal file
49
src/wayland/primaryselectionsource_v1_interface.h
Normal 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
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue