最小 CPP
Minimal CPP 是一个演示如何用 C++ 编写 Wayland 合成器的示例。
Minimal CPP 是一个使用 C++ 实现完整Qt Wayland Compositor 的最小化合成器示例。QtWaylandCompositor 的 C++ API 是低级的,适用于专门的应用,如支持硬件功能,或在Qt Quick 不可用的情况下。QML API 提供了更多便利和功能。相比之下,Minimal QML 示例用 30 行 QML 实现的功能要多于本示例用 300 多行实现的功能。
本示例分为两部分。Wayland 逻辑包含在Compositor
类中,而用户界面则在Window
类中。
窗口
Window
类相当简单。为了显示 Wayland 表面,它会遍历合成器的视图,并使用QOpenGLTextureBlitter 将其渲染到屏幕上:
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(); }
所有键盘和鼠标事件都会传递给合成器。例如
void Window::mousePressEvent(QMouseEvent *event) { m_compositor->handleMousePress(event->position().toPoint(), event->button()); }
合成器
Compositor
类更为复杂,因为它必须实现基于 QML 的合成器中由WaylandCompositor 和WaylandQuickItem 处理的大部分逻辑。
create
函数使用最基本的外壳扩展IviApplication 来设置合成器。该函数在 OpenGL 上下文初始化后调用:
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); }
鼠标事件和键盘焦点的所有逻辑都需要手动实现,包括隐式鼠标抓取(将所有鼠标移动发送到接收到初始鼠标按压的表面)。请注意,Wayland 协议中的鼠标按下事件并不包含鼠标位置,因此当我们收到鼠标按下时,总是必须发送鼠标移动:
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); }
对于鼠标释放,我们会结束隐式抓取,并通知当前鼠标位置的曲面:
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); }
当我们收到新表面的通知时,我们会创建一个View
来跟踪它,并连接信号以便处理更新。
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); }
View
类子类QWaylandView ,它代表曲面的一个特定视图。advance 函数更新视图的当前缓冲区,如果有新内容则返回 true。getTexture
函数将缓冲区内容作为 OpenGL 纹理提供给Window
类:
QOpenGLTexture *View::getTexture() { if (advance()) m_texture = currentBuffer().toOpenGLTexture(); return m_texture; }
© 2025 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.