File indexing completed on 2024-12-01 05:02:03

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