summaryrefslogtreecommitdiffstats
path: root/examples/applicationmanager/minidesk/doc/src/minidesk.qdoc
blob: 4e68cf7ee4060ff66eb5b64515379f8dd8d399cb (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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
/****************************************************************************
**
** Copyright (C) 2019 Luxoft Sweden AB
** Copyright (C) 2018 Pelagicore AG
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Application Manager.
**
** $QT_BEGIN_LICENSE:FDL-QTAS$
** Commercial License Usage
** Licensees holding valid commercial Qt Automotive Suite licenses may use
** this file in accordance with the commercial license agreement provided
** with the Software or, alternatively, in accordance with the terms
** contained in a written agreement between you and The Qt Company.  For
** licensing terms and conditions see https://www.qt.io/terms-conditions.
** For further information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/

/*!

\example applicationmanager/minidesk
\title Desktop System UI Example
\image minidesk.png Screenshot
\brief Illustrates a minimal Desktop System UI in pure QML.
\ingroup applicationmanager-examples

\section1 Introduction

This example showcases the application manager API in a simple way, as a classic desktop with
server-side window decorations. The example focuses more on the concepts, but less on elegance or
completeness. For example, there's no error checking done. Some features in this minimal Desktop
System only print debug messages.

The following features are supported:
\list
    \li Start applications by clicking on an icon in the top left
    \li Stop an application by clicking on the icon in the top left again
    \li Close application windows by clicking on the top left window decoration rectangle
    \li Bring applications forward by clicking on the decoration
    \li Drag windows by pressing on the window decoration and moving them
    \li The System UI sends a 'propA' change when an app starts
    \li The System UI and App2 react to window property changes with a debug message
    \li Stop or restart App1 animations with a click
    \li App1 sends rotation angle as a window property to System UI on stop
    \li App1 shows a pop up on the System UI when it is paused
    \li App2 makes use of an IPC extension when it starts
    \li App2 logs the document URL that started it
    \li App2 triggers a notification in the System UI, when the bulb icon is clicked
    \li Show Wayland client windows that originate from processes outside of \c appman
\endlist

\note This example can be run in single-process or multi-process mode. In the walkthrough below, we
use multi-process and its corresponding terminology. The terms \e client and \e application;
\e server and \e {System UI} are used interchangeably. The System UI comprises both compositing and
generic Inter-Process Communication (IPC).

To start the example, navigate to the \c minidesk folder, and run the following command:
\badcode
<path-to-appman-binary> -c am-config.yaml -r
\endcode
The \c appman binary (executable file) is usually located in the Qt installation \c bin folder.

\section1 Walkthrough

\section2 System UI Window

\quotefromfile applicationmanager/minidesk/system-ui/main.qml
\skipto import Qt
\printuntil text:
\printline }
\dots

The \l{QtApplicationManager.SystemUI} module has to be imported to access the application manager
APIs. The System UI window has a fixed size and linen background color. Instead of a \l{Rectangle},
the root element could also be a \l{Window}. On top of the background, we display a
\c Readme element with information on the
features available. At the bottom left there is a textual indication for whether the
application manager runs in single-process or multi-process mode.

\section2 Launcher

\printto System-UI chrome for applications

A \l{Repeater} provides the application icons arranged in a \l{Column} on the top left corner of
the System UI; the \l{ApplicationManager} element is the model. Among others, the
ApplicationManager provides the \c icon role which is used as the \l{Image} source URL. The
\c icon URL is defined in the application's \l{Manifest Definition}{info.yaml} file. To indicate
that an application has launched, the corresponding application icon's opacity is decreased by
binding it to the \c isRunning role.

Clicking on an application icon launches the corresponding application through a call to
\l {ApplicationObject::start()}{ApplicationObject.start()}. This function is accessible through
the \c application role in the ApplicationManager model. Both applications start with
the (optional) document URL, \c documentUrl. If the application is already running,
\l {ApplicationObject::stop()}{ApplicationObject.stop()} is called instead.

\section2 Application Windows in the System UI

\printto System-UI for a pop-up

This second Repeater provides the window chrome for the application windows in its delegate. The
model is a plain ListModel fed with \l{WindowObject}{window objects} as they are created by the
WindowManager. The code that populates the window role of this ListModel is shown below. For
now let's focus on what this Repeater's delegate consists of:

\list
    \li A fixed size window container \l{Rectangle} in "tan" color. The location depends on the
        \c model.index, hence each application window has a different initial location.
    \li The name of the application that created that window, prefixed with "Decoration" on top.
        This name is from the related ApplicationObject, defined in the application's
        \l{Manifest Definition}{info.yaml} file.
    \li A MouseArea for dragging and raising the window. The MouseArea fills the entire window. The
        WindowItem containing the application's window is placed on top of it and hence it will not
        handle dragging.
    \li A small chocolate-colored \l Rectangle on the top left corner for closing the window (see
        \l{WindowObject::close()}{WindowObject.close()}). Since our sample applications only have one
        top-level window, closing it causes the corresponding application to quit.
    \li The centerpiece: a \l WindowItem to render the \c WindowObject in the SystemUI; similar to
        the relationship between image files and QML's Image component.
    \li And finally code to remove a row from the ListModel once its window has been destroyed from
        the application (client) side - either because it was closed, made invisible, or the
        application itself quit or crashed. Any of these cases results in the \l WindowObject
        losing its surface. A more sophisticated System UI could animate the disappearance of a
        window, as illustrated in the \l {Animated Windows System UI Example}.
\endlist

\section2 Pop-ups

Two approaches are implemented to display pop-ups in the System UI:

\list
    \li Through a window rendered by the client application
    \li Through the notification API provided by the application manager
\endlist

This is the corresponding System-UI code:
\printto Handler for WindowManager signals

\section3 Client Application Rendering

App1 instantiates another \l{ApplicationManagerWindow} for the pop-up within its
\l{ApplicationManagerWindow} root element, as shown here:

\quotefromfile applicationmanager/minidesk/apps/tld.minidesk.app1/app1.qml
\skipto Rectangle
\skipto ApplicationManagerWindow
\printuntil Component.onCompleted
\printline }

The \l{ApplicationManagerWindow::setWindowProperty}{ApplicationManagerWindow.setWindowProperty()}
method is used to set a freely selectable shared property. Here we chose \c{type: "pop-up"} to
indicate that the window is supposed to be shown as a pop-up.

In the WindowManager::onWindowAdded() signal handler \l{WindowManager Signal Handler}{below}, the
SystemUI checks this property and handles the window appropriately as a pop-up.

A pop-up window will be set as the content window of the \c popUpContainer WindowItem in the
SystemUI code above. For demonstration purposes, the implementation supports only one pop-up at a
time. This is sufficient, since only App1 will display a single pop-up when its animation is
paused. It is essential to understand, that there has to be an agreement between the System UI
and applications, in terms of how windows are mapped. In contrast to regular application windows
that are freely draggable and have title bars and borders, the pop-up window is just centered and
has no decoration at all. Note also how the
\l{WindowObject::contentState}{WindowObject.contentStateChanged} signal is handled in the
\c popUpContainer: the window is released when it has no surface associated any more. This is
important to free any resources that the \l{WindowObject}{window} object is using. Note that this
is done implicitly when the WindowManager model is used directly. This approach is recommended as
it's more convenient.

\section3 Notification API Usage

An alternative to the window property approach is to use the application-manager's \l{Notification}
API on the application (client) side and the \l{NotificationManager} API on the System UI (server)
side. The following code is invoked when you click on the \e bulb icon in App2:

\quotefromfile applicationmanager/minidesk/apps/tld.minidesk.app2/app2.qml
\skipto var notification
\printuntil notification.show();

App2 creates a new \l{Notification} element, sets its \l{Notification::summary}{summary} property
and calls \l{Notification::show()}{show()} on it. This call increases the
\l{NotificationManager::count}{NotificationManager.count} on the System UI side, and subsequently
the \l{Text} element's text property will be set to the \c summary string of the first
notification. For brevity, the example only presents the first notification.

\section2 WindowManager Signal Handler

\quotefromfile applicationmanager/minidesk/system-ui/main.qml
\skipto Handler for WindowManager signals
\printto IPC extension

This is the vital part of the System UI, where the window (surfaces) of the applications are mapped
to \l{WindowItem}s in the SystemUI. When a new application window is available (becomes visible),
the \l {WindowManager::windowAdded}{onWindowAdded} handler is invoked.

Only App1's "pop-up" ApplicationManagerWindow has the user-defined \c type property set. Such a
window is placed in the \c popUpContainer WindowItem. All other windows don't have a \c type
property; they are added to the \c topLevelWindowsModel. This model is used in the SystemUI chrome
Repeater above. Consequently, the \l {WindowObject}{window} object passed as an argument to
\l {WindowManager::windowAdded}{onWindowAdded} is set as the
\l{WindowItem::window}{window} property of the WindowItem (within the Repeater's delegate).

Incidentally, any Wayland client window from a process started outside of the application manager
will also be displayed since in the configuration file, "\c flags/noSecurity: \c yes" is set, for
instance in KDE's Calculator:

\badcode
$ QT_WAYLAND_DISABLE_WINDOWDECORATION=1 QT_WAYLAND_SHELL_INTEGRATION=xdg-shell-v5 kcalc -platform wayland
\endcode

\section2 Inter-Process Communication (IPC) Extension

The following snippet demonstrates how the \l{ApplicationIPCInterface} can be used to define an IPC
extension. The IPC interface has to be defined in the System UI, for instance:

\printuntil Component.onCompleted
\printline }

Here, a \c pi property is defined, as well as a \c computed signal and a \c circumference function.
After registering this interface with
\l{ApplicationIPCManager::registerInterface()}{ApplicationIPCManager.registerInterface()}, it can
be used from the application processes.

On the application side, the \l{ApplicationInterfaceExtension} type has to be used. Here's how
App2 makes use of this interface extension:

\quotefromfile applicationmanager/minidesk/apps/tld.minidesk.app2/app2.qml
\skipto ApplicationInterfaceExtension
\printuntil onPiChanged
\printline }

The interface is used here as soon as it's ready. Of course, the interface can be accessed from
elsewhere, too. The \l{ApplicationInterfaceExtension::name}{ApplicationInterfaceExtension.name}
must match the name it was registered with in
\l{ApplicationIPCManager::registerInterface()}{ApplicationIPCManager.registerInterface()}.

\section2 Application Termination

When an application is stopped from the System UI through
\l{ApplicationManager::stopApplication()}{ApplicationManager.stopApplication()}, it is sent
the \l{ApplicationInterface::quit()}{ApplicationInterface.quit()} signal. Then, the application can
do some clean-up and it must subsequently confirm with
\l{ApplicationInterface::acknowledgeQuit()}{ApplicationInterface.acknowledgeQuit()}, like App2 does:

\quotefromfile applicationmanager/minidesk/apps/tld.minidesk.app2/app2.qml
\skipto Connections
\printuntil onQuit
\printline }

Note that App1 is not well-behaved: it does not acknowledge the \c quit signal and will hence simply
be terminated by the application manager.

*/