summaryrefslogtreecommitdiffstats
path: root/examples/minidesk/doc/src/minidesk.qdoc
blob: ad85c36ecf8930eda0ee9dd7540bfa7fb942e425 (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
/****************************************************************************
**
** Copyright (C) 2018 Pelagicore AG
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Pelagicore 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 minidesk
\title Desktop System-UI Example
\image minidesk.png Screenshot
\brief Minimal Desktop System-UI in pure QML
\ingroup applicationmanager-examples

\section1 Introduction

The \e {Desktop System-UI Example} showcases the application-manager API in a simple fashion. The
focus is on the concepts, less on elegance or completeness, for instance no error checking is done.
Some features will only print debug messages without further functionality. A classic desktop with
server-side window decorations is emulated.

The following features are supported:
\list
\li Start applications by clicking an icon on the top left
\li Stop applications by clicking on the top/left window decoration rectangle
\li Raise applications by clicking on the decoration
\li Drag windows by pressing on the window decoration and moving
\li System-UI sends 'propA' change when an app is started
\li System-UI and App2 react on window property changes with a debug message
\li App1 animation can be stopped and restarted by a click
\li App1 sends 'rotation' property to System-UI on stop
\li App1 shows a pop-up on the System-UI while it is paused
\li App2 will make use of an IPC extension when it is started
\li App2 logs the document URL it has been started with
\li App2 triggers a notification in the System-UI when the bulb icon is clicked
\li A separate (\"wayland\") process started outside of appman will be shown as App1
\endlist

\note The example can be run in single- and multi-process mode. In the following, multi-process is
assumed and corresponding terminology is used. The terms \e client and \e application, respectively
\e server and \e {System-UI} are used interchangeably. The System-UI comprises compositing and
generic inter-process communication (IPC).

\section2 Invocation
The example can be started from within the minidesk folder with:
\badcode
path/to/bin/appman -c am-config.yaml -r
\endcode

\note The application-manager attempts to register a \c freedesktop.org compliant notification
server. DBus errors might occur if it conflicts with the server running on the host desktop
environment. In this case, a private session bus needs to be started by adding the
\c --start-session-dbus option:
\badcode
path/to/bin/appman -c am-config.yaml -r --start-session-dbus
\endcode

\section1 Walkthrough

\section2 System-UI Window

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

The \l{QtApplicationManager} module has to be imported to be able 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 as well be a \l{Window}. On top of the background the
\l{minidesk/system-ui/Readme.qml}{Readme} element is shown that displays a usage how-to. At the
bottom left there is a textual indication for whether the application-manager runs in single- 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. This is achieved by using the \l{ApplicationManager} element as the model. Amongst
others, it provides the \c icon role which is used as the \l{Image} source URL. The \c icon URL is
defined in the \l{Manifest Definition}{info.yaml} file of the application. To indicate that an
application has been launched, the opacity of the corresponding application's icon is decreased
through a binding to the \c isRunning role.

Clicking on an application icon will launch the corresponding application through a call to
\l {ApplicationManager::startApplication()}{ApplicationManager.startApplication()}. The first
argument, \c applicationId, is provided by the ApplicationManager model (e.g. "tld.minidesk.app1"
for the first application). Both applications will be started with the (optional) document URL
"documentUrl". Subsequent clicks on an already launched icon will still call
\l{ApplicationManager::}{startApplication()}, but will be silently ignored. The content of the
\c appContainter will be set below in the \c onWindowReady handler. The content is provided by the
two applications in an \l{ApplicationManagerWindow} root element.

\section2 Application Windows in the System-UI

\printto System-UI for a pop-up and notification

This second \l{Repeater} provides the window chrome for the actual applications in its delegate.
The model is the same as for the first \l{Repeater}, essentially the \l{ApplicationManager}
element. The chrome consists of:
\list
\li A fixed size window \l{Rectangle} with a "tan" color. The default location depends on the
    \c model.index, hence each application has a different location.
\li The name of the application, prefixed with "Decoration" on the top horizontal center. The name
    is also provided by the \l{ApplicationManager} model and read from the application's
    \l{Manifest Definition}{info.yaml} file.
\li A \l{MouseArea} for dragging the window and setting the z-order. The \l{MouseArea} fills the
    entire window, though the application container is placed on top of it and hence it will not
    handle dragging. Simply increasing the z-order on each click is only done to keep the code to
    a minimum.
\li A small chocolate-colored \l Rectangle on the top left corner for closing the window chrome and
    stopping the actual application (see
    \l{ApplicationManager::stopApplication()}{stopApplication()}).
\li A container \l{Item} where the actual application will be placed in. The \c appContainer is
    exposed, so it can later be referenced to place the actual application window in it.
\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
The \c popUpContainer \l{Item} provides a System-UI recipient for the pop-up rendered
by App1. App1 instantiates another \l{ApplicationManagerWindow} for the pop-up within its
\l{ApplicationManagerWindow} root element, as shown here:
\quotefromfile 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 choose \c{type: "pop-up"} to
indicate that the window is supposed to be shown as a pop-up. In the \c onWindowReady handler below
the System-UI checks for this property and handles the window appropriately as a pop-up.

\section3 Notification API Usage

An alternative to the above 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 the \e bulb icon of App2 is clicked:

\quotefromfile 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 will increase 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. Presenting the first notification only is a simplification to keep the code short.

\section2 WindowManager Signal Handler

\quotefromfile 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 items in the System-UI. The \l {WindowManager::windowReady}{onWindowReady} handler is invoked
when a new application window is shown (visibility set to true). The \c index parameter references
into the \l{WindowManager} model, which holds the window surfaces. The first line translates this
index to the application index of the \l{ApplicationManager} model and assigns it to \c appIndex.

Only the "pop-up" ApplicationManagerWindow of App1 has the user-defined \c type property set. All
other windows don't have the \c type property. In the latter case, the application's \c window
passed to \c onWindowReady is re-parented to the System-UI's \c winChrome. Also the size of the
window is set to fill the entire \c appContainer.

There is a special treatment for an invalid \c appIndex for demonstration purposes: it is assumed
that the window surface is from an external application that follows the Wayland protocol. For
example a Qt application could be started on the command line as follows:

\badcode
QT_WAYLAND_DISABLE_WINDOWDECORATION=1 ./qtapp -platform wayland
\endcode

This application will then be shown inside the App1 container.
\c QT_WAYLAND_DISABLE_WINDOWDECORATION is set to disable client side window decorations, since they
are provided by the System-UI. Note, that an application started in this way, can just as well be
closed only from the command line.

Pop-ups (windows with type "pop-up") are re-parented to their respective \c popUpContainer.

The \c onWindowClosing handler determines if the window is a top-level application window. If so,
the applications's \c winChrome is set to invisible and the corresponding application icon is set
to fully opaque to indicate that the application is not running. The \c onWindowLost handler calls
\l{WindowManager::releaseWindow()}{WindowManager.releaseWindow()} to free all resources associated
with the \c window.


\section2 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 property \c pi is defined, as well as a signal \c computed and a function \c circumference.
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 is how
App2 makes use of this interface extension:

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

The interface is used here immediately when it becomes ready. It can, of course, be accessed from
elsewhere, too. The \l{ApplicationInterfaceExtension::name}{ApplicationInterfaceExtension.name} has
to 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 will be sent
the \l{ApplicationInterface::quit()}{ApplicationInterface.quit()} signal. The application can do
some clean-up and must subsequently confirm with
\l{ApplicationInterface::acknowledgeQuit()}{ApplicationInterface.acknowledgeQuit()}, like App2 does:
\quotefromfile 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.

*/