Minimal CPP
„Minimal CPP“ ist ein Beispiel, das zeigt, wie man einen Wayland-Compositor in C++ schreibt.
„Minimal CPP“ ist ein minimalistisches Compositor-Beispiel, das einen vollständigen „ Qt Wayland Compositor “ mit C++ implementiert. Die C++-API von QtWaylandCompositor ist auf niedriger Ebene angesiedelt und für spezielle Anwendungen gedacht, beispielsweise zur Unterstützung von Hardwarefunktionen oder wenn Qt Quick nicht verfügbar ist. Die QML-API bietet mehr Komfort und Funktionalität. Zum Vergleich: Das Beispiel „Minimal QML“ implementiert mit 30 Zeilen QML mehr Funktionalität als dieses Beispiel mit über 300 Zeilen.

Dieses Beispiel ist in zwei Teile gegliedert. Die Wayland-Logik ist in der Klasse „ Compositor “ enthalten, die Benutzeroberfläche in der Klasse „ Window “.
Fenster
Die Klasse „ Window “ ist recht übersichtlich. Um die Wayland-Oberflächen anzuzeigen, durchläuft sie die Ansichten des Compositors und rendert sie mithilfe von „ QOpenGLTextureBlitter “ auf dem Bildschirm:
void Window::paintGL()
{
m_compositor->startRender();
QOpenGLFunctions *functions = context()->functions();
functions->glClearColor(.4f, .7f, .1f, 0.5f);
functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLenum currentTarget = GL_TEXTURE_2D;
m_textureBlitter.bind(currentTarget);
functions->glEnable(GL_BLEND);
functions->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
const auto views = m_compositor->views();
for (View *view : views) {
auto texture = view->getTexture();
if (!texture)
continue;
if (texture->target() != currentTarget) {
currentTarget = texture->target();
m_textureBlitter.bind(currentTarget);
}
GLuint textureId = texture->textureId();
QWaylandSurface *surface = view->surface();
if (surface && surface->hasContent()) {
QSize s = surface->destinationSize();
view->initPosition(size(), s);
QPointF pos = view->globalPosition();
QRectF surfaceGeometry(pos, s);
QOpenGLTextureBlitter::Origin surfaceOrigin =
view->currentBuffer().origin() == QWaylandSurface::OriginTopLeft
? QOpenGLTextureBlitter::OriginTopLeft
: QOpenGLTextureBlitter::OriginBottomLeft;
QMatrix4x4 targetTransform = QOpenGLTextureBlitter::targetTransform(surfaceGeometry, QRect(QPoint(), size()));
m_textureBlitter.blit(textureId, targetTransform, surfaceOrigin);
}
}
m_textureBlitter.release();
m_compositor->endRender();
}Alle Tastatur- und Mausereignisse werden an den Compositor weitergeleitet. Zum Beispiel:
void Window::mousePressEvent(QMouseEvent *event)
{
m_compositor->handleMousePress(event->position().toPoint(), event->button());
}Compositor
Die Klasse „ Compositor “ ist komplexer, da sie einen Großteil der Logik implementieren muss, die in einem QML-basierten Compositor von „ WaylandCompositor “ und „ WaylandQuickItem “ übernommen würde.
Die Funktion ` create ` richtet den Compositor mithilfe von ` IviApplication` ein, der grundlegendsten Shell-Erweiterung. Die Funktion wird aufgerufen, nachdem der OpenGL-Kontext initialisiert wurde:
void Compositor::create()
{
QWaylandOutput *output = new QWaylandOutput(this, m_window);
QWaylandOutputMode mode(m_window->size(), 60000);
output->addMode(mode, true);
QWaylandCompositor::create();
output->setCurrentMode(mode);
m_iviApplication = new QWaylandIviApplication(this);
connect(m_iviApplication, &QWaylandIviApplication::iviSurfaceCreated, this, &Compositor::onIviSurfaceCreated);
}Die gesamte Logik für Mausereignisse und Tastaturfokus muss manuell implementiert werden, einschließlich impliziter Maus-Grabs (das Senden aller Mausbewegungen an die Oberfläche, die den anfänglichen Mausklick empfangen hat). Beachten Sie, dass Mausklick-Ereignisse im Wayland-Protokoll keine Mausposition enthalten, sodass wir immer eine Mausbewegung senden müssen, wenn wir einen Mausklick empfangen:
void Compositor::handleMousePress(const QPoint &position, Qt::MouseButton button)
{
if (!m_mouseView) {
if ((m_mouseView = viewAt(position)))
raise(m_mouseView);
}
auto *seat = defaultSeat();
seat->sendMouseMoveEvent(m_mouseView, mapToView(m_mouseView, position));
seat->sendMousePressEvent(button);
}Bei einem Mausloslassen beenden wir das implizite „Grab“ und benachrichtigen die Oberfläche an der aktuellen Mausposition:
void Compositor::handleMousePress(const QPoint &position, Qt::MouseButton button)
{
if (!m_mouseView) {
if ((m_mouseView = viewAt(position)))
raise(m_mouseView);
}
auto *seat = defaultSeat();
seat->sendMouseMoveEvent(m_mouseView, mapToView(m_mouseView, position));
seat->sendMousePressEvent(button);
}Wenn wir über eine neue Oberfläche benachrichtigt werden, erstellen wir eine ` View `, um diese zu verfolgen, und verbinden Signale, damit wir Aktualisierungen verarbeiten können.
void Compositor::onIviSurfaceCreated(QWaylandIviSurface *iviSurface)
{
View *view = new View(iviSurface->iviId());
view->setSurface(iviSurface->surface());
view->setOutput(outputFor(m_window));
m_views << view;
connect(view, &QWaylandView::surfaceDestroyed, this, &Compositor::viewSurfaceDestroyed);
connect(iviSurface->surface(), &QWaylandSurface::redraw, this, &Compositor::triggerRender);
}Die Klasse „ View “ ist eine Unterklasse von „ QWaylandView “, die eine bestimmte Ansicht einer Oberfläche darstellt. Die Funktion „ advance “ aktualisiert den aktuellen Puffer der Ansicht und gibt „true“ zurück, wenn neuer Inhalt vorhanden ist. Die Funktion „ getTexture “ stellt den Pufferinhalt als OpenGL-Textur für die Klasse „ Window “ bereit:
QOpenGLTexture *View::getTexture() {
if (advance())
m_texture = currentBuffer().toOpenGLTexture();
return m_texture;
}© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.