summaryrefslogtreecommitdiffstats
path: root/examples/applicationmanager/application-features/doc/src/application-features.qdoc
blob: cc9fe3e1d89e3a38f61f7098469de476c594da58 (plain)
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Copyright (C) 2021 The Qt Company Ltd.
// Copyright (C) 2019 Luxoft Sweden AB
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!

\example applicationmanager/application-features
\title Application Features Example
\image application-features.png
\brief Showcases client applications with various features and QML modularization.
\ingroup applicationmanager-examples

\section1 Introduction

This example demonstrates how to implement some particular features you may require in an
application, such as:

\list
    \li how to implement a nested compositor
    \li how to simulate a crash and recover from it
    \li how to show multiple top-level windows simultaneously
    \li how to use the native runtime, with no QML

\endlist

Most of these features are only supported properly in
\l{Single-Process vs. Multi-Process Mode}{multi-process mode}.

The example focuses on the application (client) side. The \l{The System UI}{System UI}
(compositor/server) is based on the \l{Desktop System UI Example} with some modifications. Refer
to that example for more details on how to implement a System UI.

In addition, this example shows how to write and use \l{Writing QML Modules}{QML modules} in the
application manager context, see \l{Code Structure}{below}.

\section2 Nested Compositor

The nested compositor application shows how to implement a Wayland compositor inside an application
(Wayland client) window. The compositor is implemented in pure QML and kept to a minimum. To
display Wayland clients within this compositor, you need to set the \c WAYLAND_DISPLAY environment
variable appropriately.

To start a client with this environment variable set via command line:

\badcode
WAYLAND_DISPLAY=qtam-wayland-nested qml client.qml -platform wayland
\endcode

This command only works in multi-process mode, since the nested compositor needs a real window as
its root element.

The QML code for the nested compositor application is as follows:

\quotefromfile applicationmanager/application-features/apps/Compositor/compositor.qml
\skipto import QtQuick
\printuntil /^\}/

\section2 Crash Simulation and Recovery

This application provides various means to force a crash in an application, such as a segmentation
fault. It utilizes QML modules that include C++ and QML code; in particular, the C++ provided QML
types \c Terminator1 and \c Terminator2 are used to trigger crashes. The application manager then
prints the cause of the crash and related information, like a backtrace. The System UI implements a
basic form of crash recovery: restarting the application. Of course, crash recovery only works in
multi-process mode. In single-process mode, a crash affects the entire program (the System UI).

The QML code for the crash simulation and recovery application is as follows:

\quotefromfile applicationmanager/application-features/apps/Crash/crashapp.qml
\skipto import QtQuick
\printuntil crashAnimation.mode = parent.modelData;
\printuntil /^\}/

\section2 Two Top-Level Windows

This application illustrates how you can display multiple top-level windows by having a QtObject
as the application's root element.

The QML code for the two top-level windows application is as follows:

\quotefromfile applicationmanager/application-features/apps/Twins/twins.qml
\skipto import QtQuick
\printuntil Component.onCompleted: setWindowProperty("type", "pop-up");
\printuntil /^\}/

\section2 Native Widgets

This application is based on \l{QWidget}s. Compared to the other applications in this example,
which are QML applications, this one uses the native runtime. Consequently, the application's entry
point isn't a \c{main.qml} file, but an executable. This application is a basic application that
still adheres to this particular System UI. It's meant to illustrate the concept: the System UI
needs a \c type window property to differentiate between normal windows and popups.

This application only works in multi-process mode, as application processes cannot be started in
single-process mode.

Linking against the private application manager modules is prohibited by default to prevent
potential problems with duplicate symbols coming from QML plugins. However here building against
them is both intended and required, so we need to set the define \c AM_COMPILING_LAUNCHER:

\quotefromfile applicationmanager/application-features/apps/Widgets/CMakeLists.txt
\skipuntil /allows us to link against/
\printuntil /AM_COMPILING_LAUNCHER/

The C++ code for the native widgets application is as follows:

\quotefromfile applicationmanager/application-features/apps/Widgets/main.cpp
\skipto #include <QApplication>
\printuntil /^\}/

\section1 Code Structure

Compared to the other Qt Application Manager Examples, which are purely based on QML, this example
requires you to build it explicitly. The code is structured in a way where the resulting application
folders only contain the artifacts necessary to run the application. Consequently, you can package
these applications and install them as well.

To build Qt Application Manager, including its examples, you need to pass
\c{-DQT_BUILD_EXAMPLES=ON} to CMake. For more details, see \l{build}{Build}.

The System UI and the Crash application produce QML modules. These modules are generated as
libraries that include all the C++ and QML code and other resources, like images. Consequently,
only the libraries need to be loaded from the native file system instead of individual QML files,
images, or other such assets. As an additional bonus, you get things like pre-compiled QML, linting
checks, and auto-generation of files like qmldir.

\section2 System UI QML Module

In the \c{SystemUi/CMakeLists.txt} file, the \c systemuimodule is defined:
\quotefromfile applicationmanager/application-features/SystemUi/CMakeLists.txt
\printuntil /^\)$/

The default "qt/qml" resource prefix is used here. By providing the \c NO_PLUGIN keyword, only a
dynamic backing library is created. A QML plugin is unnecessary since the library will be loaded
explicitly (see below). To keep it simple, the module is kept in a directory with the same name as
its URI (\c SystemUi). Two images and the \c main.qml file is added to the module (there is no C++
code used, though).

The \c systemuimodule dynamic library is added to the list of resources that are loaded at startup
in the \c am-config.yaml file (key \c{ui/resources}):
\quotefromfile applicationmanager/application-features/am-config.yaml
\skipto ui:
\printuntil resources:
The library is loaded from the native file system, but the \c main.qml file can subsequently be
loaded from the resource file system (key \c{ui/mainQml}). The path starts with the resource
prefix, extended with the module URI. Since the images used in \c main.qml have relative URLs they
are also found in the resource file system.

A general overview how to add and use resources in the application manager context can be found in
\l{Using Qt Resources}.

\section2 Crash Application QML Modules

The Crash application consists of two QML modules: \c crashmodule and \c sequelmoduleplugin. The
first is analogous to the \c systemuimodule above, except that it also includes C++ code
(\c terminator1.cpp). The generated library is loaded explicitly when the application starts
through the following lines in \c{apps/Crash/info.yaml}:
\quotefromfile applicationmanager/application-features/apps/Crash/info.yaml
\skipto runtimeParameters:
\printuntil resources:

It provides the \c crashapp.qml file, which is the application's main QML file and the
\c Terminator1 QML singleton type.

The second module, \c sequelmoduleplugin is defined as a QML plugin in
\c{apps/Crash/Sequel/CMakeLists.txt}:
\quotefromfile applicationmanager/application-features/apps/Crash/Sequel/CMakeLists.txt
\printuntil /^\)$/
For convenience, \c PLUGIN_TARGET is defined with the same argument as the module target name.
This creates a plugin that already includes the backing target (see
\l{Plugin target with no backing target}{qt_add_qml_module}). The plugin is loaded implicitly
at runtime through the "\c{import Sequel}" statement in \c crashapp.qml. It provides the
\c CrashAnimation and \c Terminator2 QML types.

*/