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

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/datasource.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 <QThread>
0025 
0026 using namespace KWayland::Client;
0027 
0028 class CopyClient : public QObject
0029 {
0030     Q_OBJECT
0031 public:
0032     explicit CopyClient(QObject *parent = nullptr);
0033     virtual ~CopyClient();
0034 
0035     void init();
0036 
0037 private:
0038     void setupRegistry(Registry *registry);
0039     void render();
0040     void copy(const QString &mimeType, qint32 fd);
0041     QThread *m_connectionThread;
0042     ConnectionThread *m_connectionThreadObject;
0043     EventQueue *m_eventQueue = nullptr;
0044     Compositor *m_compositor = nullptr;
0045     DataDeviceManager *m_dataDeviceManager = nullptr;
0046     DataDevice *m_dataDevice = nullptr;
0047     DataSource *m_copySource = nullptr;
0048     Seat *m_seat = nullptr;
0049     Shell *m_shell = nullptr;
0050     ShellSurface *m_shellSurface = nullptr;
0051     ShmPool *m_shm = nullptr;
0052     Surface *m_surface = nullptr;
0053 };
0054 
0055 CopyClient::CopyClient(QObject *parent)
0056     : QObject(parent)
0057     , m_connectionThread(new QThread(this))
0058     , m_connectionThreadObject(new ConnectionThread())
0059 {
0060 }
0061 
0062 CopyClient::~CopyClient()
0063 {
0064     m_connectionThread->quit();
0065     m_connectionThread->wait();
0066     m_connectionThreadObject->deleteLater();
0067 }
0068 
0069 void CopyClient::init()
0070 {
0071     connect(
0072         m_connectionThreadObject,
0073         &ConnectionThread::connected,
0074         this,
0075         [this] {
0076             m_eventQueue = new EventQueue(this);
0077             m_eventQueue->setup(m_connectionThreadObject);
0078 
0079             Registry *registry = new Registry(this);
0080             setupRegistry(registry);
0081         },
0082         Qt::QueuedConnection);
0083     m_connectionThreadObject->moveToThread(m_connectionThread);
0084     m_connectionThread->start();
0085 
0086     m_connectionThreadObject->initConnection();
0087 }
0088 
0089 void CopyClient::setupRegistry(Registry *registry)
0090 {
0091     connect(registry, &Registry::compositorAnnounced, this, [this, registry](quint32 name, quint32 version) {
0092         m_compositor = registry->createCompositor(name, version, this);
0093     });
0094     connect(registry, &Registry::shellAnnounced, this, [this, registry](quint32 name, quint32 version) {
0095         m_shell = registry->createShell(name, version, this);
0096     });
0097     connect(registry, &Registry::shmAnnounced, this, [this, registry](quint32 name, quint32 version) {
0098         m_shm = registry->createShmPool(name, version, this);
0099     });
0100     connect(registry, &Registry::seatAnnounced, this, [this, registry](quint32 name, quint32 version) {
0101         m_seat = registry->createSeat(name, version, this);
0102         connect(m_seat, &Seat::hasPointerChanged, this, [this] {
0103             auto p = m_seat->createPointer(this);
0104             connect(p, &Pointer::entered, this, [this](quint32 serial) {
0105                 if (m_copySource) {
0106                     m_dataDevice->setSelection(serial, m_copySource);
0107                 }
0108             });
0109         });
0110     });
0111     connect(registry, &Registry::dataDeviceManagerAnnounced, this, [this, registry](quint32 name, quint32 version) {
0112         m_dataDeviceManager = registry->createDataDeviceManager(name, version, this);
0113     });
0114     connect(registry, &Registry::interfacesAnnounced, this, [this] {
0115         Q_ASSERT(m_compositor);
0116         Q_ASSERT(m_dataDeviceManager);
0117         Q_ASSERT(m_seat);
0118         Q_ASSERT(m_shell);
0119         Q_ASSERT(m_shm);
0120         m_surface = m_compositor->createSurface(this);
0121         Q_ASSERT(m_surface);
0122         m_shellSurface = m_shell->createSurface(m_surface, this);
0123         Q_ASSERT(m_shellSurface);
0124         m_shellSurface->setFullscreen();
0125         connect(m_shellSurface, &ShellSurface::sizeChanged, this, &CopyClient::render);
0126 
0127         m_dataDevice = m_dataDeviceManager->getDataDevice(m_seat, this);
0128         m_copySource = m_dataDeviceManager->createDataSource(this);
0129         m_copySource->offer(QStringLiteral("text/plain"));
0130         connect(m_copySource, &DataSource::sendDataRequested, this, &CopyClient::copy);
0131     });
0132     registry->setEventQueue(m_eventQueue);
0133     registry->create(m_connectionThreadObject);
0134     registry->setup();
0135 }
0136 
0137 void CopyClient::render()
0138 {
0139     const QSize &size = m_shellSurface->size();
0140     auto buffer = m_shm->getBuffer(size, size.width() * 4).toStrongRef();
0141     buffer->setUsed(true);
0142     QImage image(buffer->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
0143     image.fill(Qt::green);
0144 
0145     m_surface->attachBuffer(*buffer);
0146     m_surface->damage(QRect(QPoint(0, 0), size));
0147     m_surface->commit(Surface::CommitFlag::None);
0148     buffer->setUsed(false);
0149 }
0150 
0151 void CopyClient::copy(const QString &mimeType, qint32 fd)
0152 {
0153     qDebug() << "Requested to copy for mimeType" << mimeType;
0154     QFile c;
0155     if (c.open(fd, QFile::WriteOnly, QFile::AutoCloseHandle)) {
0156         c.write(QByteArrayLiteral("foo"));
0157         c.close();
0158         qDebug() << "Copied foo";
0159     }
0160 }
0161 
0162 int main(int argc, char **argv)
0163 {
0164     QCoreApplication app(argc, argv);
0165     CopyClient client;
0166     client.init();
0167 
0168     return app.exec();
0169 }
0170 
0171 #include "copyclient.moc"