File indexing completed on 2024-05-19 16:33:10

0001 /*
0002     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 #include "../src/client/compositor.h"
0007 #include "../src/client/connection_thread.h"
0008 #include "../src/client/datadevice.h"
0009 #include "../src/client/datadevicemanager.h"
0010 #include "../src/client/dataoffer.h"
0011 #include "../src/client/event_queue.h"
0012 #include "../src/client/keyboard.h"
0013 #include "../src/client/pointer.h"
0014 #include "../src/client/registry.h"
0015 #include "../src/client/seat.h"
0016 #include "../src/client/shell.h"
0017 #include "../src/client/shm_pool.h"
0018 #include "../src/client/surface.h"
0019 // Qt
0020 #include <QCoreApplication>
0021 #include <QDebug>
0022 #include <QFile>
0023 #include <QImage>
0024 #include <QMimeType>
0025 #include <QThread>
0026 #include <QtConcurrentRun>
0027 // system
0028 #include <unistd.h>
0029 
0030 using namespace KWayland::Client;
0031 
0032 class PasteClient : public QObject
0033 {
0034     Q_OBJECT
0035 public:
0036     explicit PasteClient(QObject *parent = nullptr);
0037     ~PasteClient() override;
0038 
0039     void init();
0040 
0041 private:
0042     void setupRegistry(Registry *registry);
0043     void render();
0044     QThread *m_connectionThread;
0045     ConnectionThread *m_connectionThreadObject;
0046     EventQueue *m_eventQueue = nullptr;
0047     Compositor *m_compositor = nullptr;
0048     DataDeviceManager *m_dataDeviceManager = nullptr;
0049     DataDevice *m_dataDevice = nullptr;
0050     Seat *m_seat = nullptr;
0051     Shell *m_shell = nullptr;
0052     ShellSurface *m_shellSurface = nullptr;
0053     ShmPool *m_shm = nullptr;
0054     Surface *m_surface = nullptr;
0055 };
0056 
0057 PasteClient::PasteClient(QObject *parent)
0058     : QObject(parent)
0059     , m_connectionThread(new QThread(this))
0060     , m_connectionThreadObject(new ConnectionThread())
0061 {
0062 }
0063 
0064 PasteClient::~PasteClient()
0065 {
0066     m_connectionThread->quit();
0067     m_connectionThread->wait();
0068     m_connectionThreadObject->deleteLater();
0069 }
0070 
0071 void PasteClient::init()
0072 {
0073     connect(
0074         m_connectionThreadObject,
0075         &ConnectionThread::connected,
0076         this,
0077         [this] {
0078             m_eventQueue = new EventQueue(this);
0079             m_eventQueue->setup(m_connectionThreadObject);
0080 
0081             Registry *registry = new Registry(this);
0082             setupRegistry(registry);
0083         },
0084         Qt::QueuedConnection);
0085     m_connectionThreadObject->moveToThread(m_connectionThread);
0086     m_connectionThread->start();
0087 
0088     m_connectionThreadObject->initConnection();
0089 }
0090 
0091 void PasteClient::setupRegistry(Registry *registry)
0092 {
0093     connect(registry, &Registry::compositorAnnounced, this, [this, registry](quint32 name, quint32 version) {
0094         m_compositor = registry->createCompositor(name, version, this);
0095     });
0096     connect(registry, &Registry::shellAnnounced, this, [this, registry](quint32 name, quint32 version) {
0097         m_shell = registry->createShell(name, version, this);
0098     });
0099     connect(registry, &Registry::shmAnnounced, this, [this, registry](quint32 name, quint32 version) {
0100         m_shm = registry->createShmPool(name, version, this);
0101     });
0102     connect(registry, &Registry::seatAnnounced, this, [this, registry](quint32 name, quint32 version) {
0103         m_seat = registry->createSeat(name, version, this);
0104     });
0105     connect(registry, &Registry::dataDeviceManagerAnnounced, this, [this, registry](quint32 name, quint32 version) {
0106         m_dataDeviceManager = registry->createDataDeviceManager(name, version, this);
0107     });
0108     connect(registry, &Registry::interfacesAnnounced, this, [this] {
0109         Q_ASSERT(m_compositor);
0110         Q_ASSERT(m_dataDeviceManager);
0111         Q_ASSERT(m_seat);
0112         Q_ASSERT(m_shell);
0113         Q_ASSERT(m_shm);
0114         m_surface = m_compositor->createSurface(this);
0115         Q_ASSERT(m_surface);
0116         m_shellSurface = m_shell->createSurface(m_surface, this);
0117         Q_ASSERT(m_shellSurface);
0118         m_shellSurface->setFullscreen();
0119         connect(m_shellSurface, &ShellSurface::sizeChanged, this, &PasteClient::render);
0120 
0121         m_dataDevice = m_dataDeviceManager->getDataDevice(m_seat, this);
0122         connect(m_dataDevice, &DataDevice::selectionOffered, this, [this] {
0123             auto dataOffer = m_dataDevice->offeredSelection();
0124             if (!dataOffer) {
0125                 return;
0126             }
0127             const auto &mimeTypes = dataOffer->offeredMimeTypes();
0128             auto it = std::find_if(mimeTypes.constBegin(), mimeTypes.constEnd(), [](const QMimeType &type) {
0129                 return type.inherits(QStringLiteral("text/plain"));
0130             });
0131             if (it == mimeTypes.constEnd()) {
0132                 return;
0133             }
0134             int pipeFds[2];
0135             if (pipe(pipeFds) != 0) {
0136                 return;
0137             }
0138             dataOffer->receive((*it).name(), pipeFds[1]);
0139             close(pipeFds[1]);
0140             QtConcurrent::run([pipeFds] {
0141                 QFile readPipe;
0142                 if (readPipe.open(pipeFds[0], QIODevice::ReadOnly)) {
0143                     qDebug() << "Pasted: " << readPipe.readLine();
0144                 }
0145                 close(pipeFds[0]);
0146                 QCoreApplication::quit();
0147             });
0148         });
0149     });
0150     registry->setEventQueue(m_eventQueue);
0151     registry->create(m_connectionThreadObject);
0152     registry->setup();
0153 }
0154 
0155 void PasteClient::render()
0156 {
0157     const QSize &size = m_shellSurface->size();
0158     auto buffer = m_shm->getBuffer(size, size.width() * 4).toStrongRef();
0159     buffer->setUsed(true);
0160     QImage image(buffer->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
0161     image.fill(Qt::blue);
0162 
0163     m_surface->attachBuffer(*buffer);
0164     m_surface->damage(QRect(QPoint(0, 0), size));
0165     m_surface->commit(Surface::CommitFlag::None);
0166     buffer->setUsed(false);
0167 }
0168 
0169 int main(int argc, char **argv)
0170 {
0171     QCoreApplication app(argc, argv);
0172     PasteClient client;
0173     client.init();
0174 
0175     return app.exec();
0176 }
0177 
0178 #include "pasteclient.moc"