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"