1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\title Qt Wayland Compositor Examples - Minimal CPP
\example minimal-cpp
\brief Minimal CPP is an example that demonstrates how to write a Wayland compositor in C++.
\ingroup qtwaylandcompositor-examples
Minimal CPP is a minimalistic compositor example implementing a complete Qt Wayland Compositor
using C++. The C++ API of QtWaylandCompositor is low-level and intended for specialized
applications, such as supporting hardware features, or if Qt Quick is not available. The QML API
offers more convenience and functionality. For comparison, the
\l{Qt Wayland Compositor Examples - Minimal QML}{Minimal QML example} implements more
functionality with 30 lines of QML than this example does in 300+ lines.
\image minimal-cpp.jpg
This example is split in two parts. The Wayland logic is contained in the \c Compositor class,
and the user interface is in the \c Window class.
\section1 Window
The \c Window class is fairly straight-forward. To display the Wayland surfaces, it iterates
through the compositor's views and renders them on the screen using \l QOpenGLTextureBlitter:
\snippet minimal-cpp/window.cpp paintGL
All keyboard and mouse events are delivered to the compositor. For example:
\snippet minimal-cpp/window.cpp mousePressEvent
\section1 Compositor
The \c Compositor class is more complex, since it has to implement much of the logic that would
be handled by \l[QML]{WaylandCompositor} and \l[QML]{WaylandQuickItem} in a QML-based compositor.
The \c create function sets up the compositor, using the IviApplication, which is the most basic
shell extension. The function is called after the OpenGL context has been initialized:
\snippet minimal-cpp/compositor.cpp create
All the logic for mouse events and keyboard focus has to be implemented manually, including
implicit mouse grabs (sending all mouse moves to the surface that received the initial mouse
press). Note that mouse press events in the Wayland protocol do not contain the mouse position,
so we always have to send a mouse move when we reveive a mouse press:
\snippet minimal-cpp/compositor.cpp handleMousePress
For a mouse release, we end the implicit grab and notify the surface at the current mouse position:
\snippet minimal-cpp/compositor.cpp handleMousePress
When we are notified of a new surface, we create a \c View to keep track of it, and connect
signals so we can handle updates.
\snippet minimal-cpp/compositor.cpp surfaceCreated
The \c View class subclasses QWaylandView, which represents a specific view of a surface. The
\l {QWaylandView::advance}{advance} function updates the view's current buffer and returns true
if there is new content. The \c getTexture function makes the buffer contents available as an
OpenGL texture for the benefit of the \c Window class:
\snippet minimal-cpp/compositor.cpp getTexture
*/
|