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