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

0001 /*
0002     SPDX-FileCopyrightText: 2015 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/plasmashell.h"
0014 #include "../src/client/plasmawindowmanagement.h"
0015 #include "../src/client/pointer.h"
0016 #include "../src/client/registry.h"
0017 #include "../src/client/seat.h"
0018 #include "../src/client/shell.h"
0019 #include "../src/client/shm_pool.h"
0020 #include "../src/client/surface.h"
0021 // Qt
0022 #include <QDebug>
0023 #include <QFile>
0024 #include <QGuiApplication>
0025 #include <QImage>
0026 #include <QMimeType>
0027 #include <QThread>
0028 // system
0029 #include <unistd.h>
0030 
0031 #include <linux/input.h>
0032 
0033 using namespace KWayland::Client;
0034 
0035 class PanelTest : public QObject
0036 {
0037     Q_OBJECT
0038 public:
0039     explicit PanelTest(QObject *parent = nullptr);
0040     ~PanelTest() override;
0041 
0042     void init();
0043 
0044 private:
0045     void setupRegistry(Registry *registry);
0046     void render();
0047     void showTooltip(const QPointF &pos);
0048     void hideTooltip();
0049     void moveTooltip(const QPointF &pos);
0050     QThread *m_connectionThread;
0051     ConnectionThread *m_connectionThreadObject;
0052     EventQueue *m_eventQueue = nullptr;
0053     Compositor *m_compositor = nullptr;
0054     Seat *m_seat = nullptr;
0055     Shell *m_shell = nullptr;
0056     ShellSurface *m_shellSurface = nullptr;
0057     ShmPool *m_shm = nullptr;
0058     Surface *m_surface = nullptr;
0059     PlasmaShell *m_plasmaShell = nullptr;
0060     PlasmaShellSurface *m_plasmaShellSurface = nullptr;
0061     PlasmaWindowManagement *m_windowManagement = nullptr;
0062     struct {
0063         Surface *surface = nullptr;
0064         ShellSurface *shellSurface = nullptr;
0065         PlasmaShellSurface *plasmaSurface = nullptr;
0066         bool visible = false;
0067     } m_tooltip;
0068 };
0069 
0070 PanelTest::PanelTest(QObject *parent)
0071     : QObject(parent)
0072     , m_connectionThread(new QThread(this))
0073     , m_connectionThreadObject(new ConnectionThread())
0074 {
0075 }
0076 
0077 PanelTest::~PanelTest()
0078 {
0079     m_connectionThread->quit();
0080     m_connectionThread->wait();
0081     m_connectionThreadObject->deleteLater();
0082 }
0083 
0084 void PanelTest::init()
0085 {
0086     connect(
0087         m_connectionThreadObject,
0088         &ConnectionThread::connected,
0089         this,
0090         [this] {
0091             m_eventQueue = new EventQueue(this);
0092             m_eventQueue->setup(m_connectionThreadObject);
0093 
0094             Registry *registry = new Registry(this);
0095             setupRegistry(registry);
0096         },
0097         Qt::QueuedConnection);
0098     m_connectionThreadObject->moveToThread(m_connectionThread);
0099     m_connectionThread->start();
0100 
0101     m_connectionThreadObject->initConnection();
0102 }
0103 
0104 void PanelTest::showTooltip(const QPointF &pos)
0105 {
0106     if (!m_tooltip.surface) {
0107         m_tooltip.surface = m_compositor->createSurface(this);
0108         m_tooltip.shellSurface = m_shell->createSurface(m_tooltip.surface, this);
0109         if (m_plasmaShell) {
0110             m_tooltip.plasmaSurface = m_plasmaShell->createSurface(m_tooltip.surface, this);
0111         }
0112     }
0113     m_tooltip.shellSurface->setTransient(m_surface, pos.toPoint());
0114 
0115     if (!m_tooltip.visible) {
0116         const QSize size(100, 50);
0117         auto buffer = m_shm->getBuffer(size, size.width() * 4).toStrongRef();
0118         buffer->setUsed(true);
0119         QImage image(buffer->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
0120         image.fill(Qt::red);
0121 
0122         m_tooltip.surface->attachBuffer(*buffer);
0123         m_tooltip.surface->damage(QRect(QPoint(0, 0), size));
0124         m_tooltip.surface->commit(Surface::CommitFlag::None);
0125         m_tooltip.visible = true;
0126     }
0127 }
0128 
0129 void PanelTest::hideTooltip()
0130 {
0131     if (!m_tooltip.visible) {
0132         return;
0133     }
0134     m_tooltip.surface->attachBuffer(Buffer::Ptr());
0135     m_tooltip.surface->commit(Surface::CommitFlag::None);
0136     m_tooltip.visible = false;
0137 }
0138 
0139 void PanelTest::moveTooltip(const QPointF &pos)
0140 {
0141     if (m_tooltip.plasmaSurface) {
0142         m_tooltip.plasmaSurface->setPosition(QPoint(10, 0) + pos.toPoint());
0143     }
0144 }
0145 
0146 void PanelTest::setupRegistry(Registry *registry)
0147 {
0148     connect(registry, &Registry::compositorAnnounced, this, [this, registry](quint32 name, quint32 version) {
0149         m_compositor = registry->createCompositor(name, version, this);
0150     });
0151     connect(registry, &Registry::shellAnnounced, this, [this, registry](quint32 name, quint32 version) {
0152         m_shell = registry->createShell(name, version, this);
0153     });
0154     connect(registry, &Registry::shmAnnounced, this, [this, registry](quint32 name, quint32 version) {
0155         m_shm = registry->createShmPool(name, version, this);
0156     });
0157     connect(registry, &Registry::seatAnnounced, this, [this, registry](quint32 name, quint32 version) {
0158         m_seat = registry->createSeat(name, version, this);
0159         connect(m_seat, &Seat::hasPointerChanged, this, [this](bool has) {
0160             if (!has) {
0161                 return;
0162             }
0163             auto p = m_seat->createPointer(this);
0164             connect(p, &Pointer::buttonStateChanged, this, [this](quint32 serial, quint32 time, quint32 button, KWayland::Client::Pointer::ButtonState state) {
0165                 Q_UNUSED(time)
0166                 Q_UNUSED(serial)
0167                 if (!m_windowManagement) {
0168                     return;
0169                 }
0170                 if (state == Pointer::ButtonState::Released) {
0171                     return;
0172                 }
0173                 if (button == BTN_LEFT) {
0174                     m_windowManagement->showDesktop();
0175                 } else if (button == BTN_RIGHT) {
0176                     m_windowManagement->hideDesktop();
0177                 }
0178             });
0179             connect(p, &Pointer::entered, this, [this, p](quint32 serial, const QPointF &relativeToSurface) {
0180                 Q_UNUSED(serial)
0181                 if (p->enteredSurface() == m_surface) {
0182                     showTooltip(relativeToSurface);
0183                 }
0184             });
0185             connect(p, &Pointer::motion, this, [this, p](const QPointF &relativeToSurface) {
0186                 if (p->enteredSurface() == m_surface) {
0187                     moveTooltip(relativeToSurface);
0188                 }
0189             });
0190             connect(p, &Pointer::left, this, [this] {
0191                 hideTooltip();
0192             });
0193         });
0194     });
0195     connect(registry, &Registry::plasmaShellAnnounced, this, [this, registry](quint32 name, quint32 version) {
0196         m_plasmaShell = registry->createPlasmaShell(name, version, this);
0197     });
0198     connect(registry, &Registry::plasmaWindowManagementAnnounced, this, [this, registry](quint32 name, quint32 version) {
0199         m_windowManagement = registry->createPlasmaWindowManagement(name, version, this);
0200         connect(m_windowManagement, &PlasmaWindowManagement::showingDesktopChanged, this, [](bool set) {
0201             qDebug() << "Showing desktop changed, new state: " << set;
0202         });
0203         connect(m_windowManagement, &PlasmaWindowManagement::windowCreated, this, [this](PlasmaWindow *w) {
0204             connect(w, &PlasmaWindow::titleChanged, this, [w] {
0205                 qDebug() << "Window title changed to: " << w->title();
0206             });
0207             connect(w, &PlasmaWindow::activeChanged, this, [w] {
0208                 qDebug() << "Window active changed: " << w->isActive();
0209             });
0210             connect(w, &PlasmaWindow::maximizedChanged, this, [w] {
0211                 qDebug() << "Window maximized changed: " << w->isMaximized();
0212             });
0213             connect(w, &PlasmaWindow::maximizedChanged, this, [w] {
0214                 qDebug() << "Window minimized changed: " << w->isMinimized();
0215             });
0216             connect(w, &PlasmaWindow::keepAboveChanged, this, [w] {
0217                 qDebug() << "Window keep above changed: " << w->isKeepAbove();
0218             });
0219             connect(w, &PlasmaWindow::keepBelowChanged, this, [w] {
0220                 qDebug() << "Window keep below changed: " << w->isKeepBelow();
0221             });
0222             connect(w, &PlasmaWindow::onAllDesktopsChanged, this, [w] {
0223                 qDebug() << "Window on all desktops changed: " << w->isOnAllDesktops();
0224             });
0225             connect(w, &PlasmaWindow::fullscreenChanged, this, [w] {
0226                 qDebug() << "Window full screen changed: " << w->isFullscreen();
0227             });
0228             connect(w, &PlasmaWindow::demandsAttentionChanged, this, [w] {
0229                 qDebug() << "Window demands attention changed: " << w->isDemandingAttention();
0230             });
0231             connect(w, &PlasmaWindow::closeableChanged, this, [w] {
0232                 qDebug() << "Window is closeable changed: " << w->isCloseable();
0233             });
0234             connect(w, &PlasmaWindow::minimizeableChanged, this, [w] {
0235                 qDebug() << "Window is minimizeable changed: " << w->isMinimizeable();
0236             });
0237             connect(w, &PlasmaWindow::maximizeableChanged, this, [w] {
0238                 qDebug() << "Window is maximizeable changed: " << w->isMaximizeable();
0239             });
0240             connect(w, &PlasmaWindow::fullscreenableChanged, this, [w] {
0241                 qDebug() << "Window is fullscreenable changed: " << w->isFullscreenable();
0242             });
0243             connect(w, &PlasmaWindow::iconChanged, this, [w] {
0244                 qDebug() << "Window icon changed: " << w->icon().name();
0245             });
0246         });
0247     });
0248     connect(registry, &Registry::interfacesAnnounced, this, [this] {
0249         Q_ASSERT(m_compositor);
0250         Q_ASSERT(m_seat);
0251         Q_ASSERT(m_shell);
0252         Q_ASSERT(m_shm);
0253         m_surface = m_compositor->createSurface(this);
0254         Q_ASSERT(m_surface);
0255         m_shellSurface = m_shell->createSurface(m_surface, this);
0256         Q_ASSERT(m_shellSurface);
0257         m_shellSurface->setToplevel();
0258         connect(m_shellSurface, &ShellSurface::sizeChanged, this, &PanelTest::render);
0259         if (m_plasmaShell) {
0260             m_plasmaShellSurface = m_plasmaShell->createSurface(m_surface, this);
0261             m_plasmaShellSurface->setPosition(QPoint(10, 0));
0262             m_plasmaShellSurface->setRole(PlasmaShellSurface::Role::Panel);
0263         }
0264         render();
0265     });
0266     registry->setEventQueue(m_eventQueue);
0267     registry->create(m_connectionThreadObject);
0268     registry->setup();
0269 }
0270 
0271 void PanelTest::render()
0272 {
0273     const QSize &size = m_shellSurface->size().isValid() ? m_shellSurface->size() : QSize(300, 20);
0274     auto buffer = m_shm->getBuffer(size, size.width() * 4).toStrongRef();
0275     buffer->setUsed(true);
0276     QImage image(buffer->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
0277     image.fill(Qt::blue);
0278 
0279     m_surface->attachBuffer(*buffer);
0280     m_surface->damage(QRect(QPoint(0, 0), size));
0281     m_surface->commit(Surface::CommitFlag::None);
0282     buffer->setUsed(false);
0283 }
0284 
0285 int main(int argc, char **argv)
0286 {
0287     QGuiApplication app(argc, argv);
0288     PanelTest client;
0289     client.init();
0290 
0291     return app.exec();
0292 }
0293 
0294 #include "paneltest.moc"