3c460d53cde791d0ec3949095346763f072108b1
[apps/agl-cluster-demo-dashboard.git] / app / main.cpp
1 /*
2  * Copyright (C) 2016 The Qt Company Ltd.
3  * Copyright (C) 2018, 2019 Konsulko Group
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <QtCore/QDebug>
19 #include <QGuiApplication>
20 #include <QtCore/QCommandLineParser>
21 #include <QtCore/QUrlQuery>
22 #include <QtGui/QGuiApplication>
23 #include <QtQml/QQmlApplicationEngine>
24 #include <QtQml/QQmlContext>
25 #include <QtQml/QQmlComponent>
26 #include <QtQml/qqml.h>
27 #include <QQuickWindow>
28 #include <QtQuickControls2/QQuickStyle>
29 #include <qpa/qplatformnativeinterface.h>
30 #include <QTimer>
31 #include <glib.h>
32 #include <QDebug>
33 #include <QScreen>
34
35 #include <signalcomposer.h>
36 #include <wayland-client.h>
37 #include "agl-shell-client-protocol.h"
38
39 // Global indicating whether canned animation should run
40 bool runAnimation = true;
41
42 static void
43 global_add(void *data, struct wl_registry *reg, uint32_t name,
44            const char *interface, uint32_t version)
45 {
46         struct agl_shell **shell = static_cast<struct agl_shell **>(data);
47         if (strcmp(interface, agl_shell_interface.name) == 0) {
48                 *shell = static_cast<struct agl_shell *>(wl_registry_bind(reg,
49                                         name, &agl_shell_interface, version)
50                 );
51         }
52 }
53
54 static void
55 global_remove(void *data, struct wl_registry *reg, uint32_t id)
56 {
57         (void) data;
58         (void) reg;
59         (void) id;
60 }
61
62 static const struct wl_registry_listener registry_listener = {
63         global_add,
64         global_remove,
65 };
66
67 static struct agl_shell *
68 register_agl_shell(QPlatformNativeInterface *native)
69 {
70         struct wl_display *wl;
71         struct wl_registry *registry;
72         struct agl_shell *shell = nullptr;
73
74         wl = static_cast<struct wl_display *>(native->nativeResourceForIntegration("display"));
75         registry = wl_display_get_registry(wl);
76
77         wl_registry_add_listener(registry, &registry_listener, &shell);
78         wl_display_roundtrip(wl);
79         wl_registry_destroy(registry);
80
81         return shell;
82 }
83
84 static struct wl_surface *
85 getWlSurface(QPlatformNativeInterface *native, QWindow *window)
86 {
87         void *surf = native->nativeResourceForWindow("surface", window);
88         return static_cast<struct ::wl_surface *>(surf);
89 }
90
91 static struct wl_output *
92 getWlOutput(QPlatformNativeInterface *native, QScreen *screen)
93 {
94         void *output = native->nativeResourceForScreen("output", screen);
95         return static_cast<struct ::wl_output*>(output);
96 }
97
98 void read_config(void)
99 {
100         GKeyFile* conf_file;
101         gboolean value;
102
103         // Load settings from configuration file if it exists
104         conf_file = g_key_file_new();
105         if(conf_file &&
106            g_key_file_load_from_dirs(conf_file,
107                                      "AGL.conf",
108                                      (const gchar**) g_get_system_config_dirs(),
109                                      NULL,
110                                      G_KEY_FILE_KEEP_COMMENTS,
111                                      NULL) == TRUE) {
112                 GError *err = NULL;
113                 value = g_key_file_get_boolean(conf_file,
114                                                "dashboard",
115                                                "animation",
116                                                &err);
117                 if(value) {
118                         runAnimation = true;
119                 } else {
120                         if(err == NULL) {
121                                 runAnimation = false;
122                         } else {
123                                 qWarning("Invalid value for \"animation\" key!");
124                         }
125                 }
126         }
127
128 }
129
130 static struct wl_surface *
131 create_component(QPlatformNativeInterface *native, QQmlComponent *comp,
132                 QScreen *screen, QObject **qobj)
133 {
134         QObject *obj = comp->create();
135         //QObject *screen_obj = new QScreen(screen);
136         obj->setParent(screen);
137
138         QWindow *win = qobject_cast<QWindow *>(obj);
139         *qobj = obj;
140
141         return getWlSurface(native, win);
142 }
143
144
145 int main(int argc, char *argv[])
146 {
147         QString myname = QString("cluster-gauges");
148         struct agl_shell *agl_shell;
149         struct wl_output *output;
150
151         QObject *qobj_bg;
152         QScreen *screen;
153
154         QGuiApplication app(argc, argv);
155         app.setDesktopFileName(myname);
156         QPlatformNativeInterface *native = qApp->platformNativeInterface();
157
158         agl_shell = register_agl_shell(native);
159         if (!agl_shell) {
160                 exit(EXIT_FAILURE);
161         }
162
163         std::shared_ptr<struct agl_shell> shell{agl_shell, agl_shell_destroy};
164
165         screen = qApp->primaryScreen();
166         output = getWlOutput(native, screen);
167
168         QCommandLineParser parser;
169         parser.addPositionalArgument("port", app.translate("main", "port for binding"));
170         parser.addPositionalArgument("secret", app.translate("main", "secret for binding"));
171         parser.addHelpOption();
172         parser.addVersionOption();
173         parser.process(app);
174
175         QStringList positionalArguments = parser.positionalArguments();
176
177         QQmlApplicationEngine engine;
178         QQmlContext *context = engine.rootContext();
179
180         if (positionalArguments.length() == 2) {
181                 int port = positionalArguments.takeFirst().toInt();
182                 QString secret = positionalArguments.takeFirst();
183
184                 QUrl bindingAddress;
185                 QUrlQuery query;
186
187                 struct wl_surface *bg;
188
189                 bindingAddress.setScheme(QStringLiteral("ws"));
190                 bindingAddress.setHost(QStringLiteral("localhost"));
191                 bindingAddress.setPort(port);
192                 bindingAddress.setPath(QStringLiteral("/api"));
193
194                 query.addQueryItem(QStringLiteral("token"), secret);
195                 bindingAddress.setQuery(query);
196
197                 read_config();
198
199                 context->setContextProperty(QStringLiteral("bindingAddress"),
200                                             bindingAddress);
201
202                 context->setContextProperty("SignalComposer",
203                                             new SignalComposer(bindingAddress,
204                                                                context));
205                 context->setContextProperty("runAnimation", runAnimation);
206
207                 QQmlComponent bg_comp(&engine, QUrl("qrc:/cluster-gauges.qml"));
208                 qDebug() << bg_comp.errors();
209
210                 bg = create_component(native, &bg_comp, screen, &qobj_bg);
211
212                 // set the surface as the background
213                 agl_shell_set_background(agl_shell, bg, output);
214
215                 // instruct the compositor it can display after Qt has a chance
216                 // to load everything
217                 QTimer::singleShot(500, [agl_shell](){
218                         qDebug() << "agl_shell ready!";
219                         agl_shell_ready(agl_shell);
220                 });
221         }
222
223         return app.exec();
224 }