c44cbb95753127b5c09f268570cd559380fd5223
[apps/homescreen.git] / homescreen / src / homescreenhandler.cpp
1 /*
2  * Copyright (c) 2017, 2018, 2019 TOYOTA MOTOR CORPORATION
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <QGuiApplication>
18 #include <QFileInfo>
19 #include "homescreenhandler.h"
20 #include <functional>
21 #include "hmi-debug.h"
22
23 #include <qpa/qplatformnativeinterface.h>
24
25 #define APPLAUNCH_DBUS_IFACE     "org.automotivelinux.AppLaunch"
26 #define APPLAUNCH_DBUS_OBJECT    "/org/automotivelinux/AppLaunch"
27 /* LAUNCHER_APP_ID shouldn't be started by applaunchd as it is started as a
28  * user session by systemd */
29 #define LAUNCHER_APP_ID          "launcher"
30
31 void* HomescreenHandler::myThis = 0;
32
33 HomescreenHandler::HomescreenHandler(Shell *_aglShell, ApplicationLauncher *launcher, QObject *parent) :
34     QObject(parent),
35     aglShell(_aglShell)
36 {
37     mp_launcher = launcher;
38     applaunch_iface = new org::automotivelinux::AppLaunch(APPLAUNCH_DBUS_IFACE, APPLAUNCH_DBUS_OBJECT,
39                                                           QDBusConnection::sessionBus(), this);
40 }
41
42 HomescreenHandler::~HomescreenHandler()
43 {
44 }
45
46 void HomescreenHandler::init(void)
47 {
48     myThis = this;
49
50     /*
51      * The "started" signal is received any time a start request is made to applaunchd,
52      * and the application either starts successfully or is already running. This
53      * effectively acts as a "switch to app X" action.
54      */
55     connect(applaunch_iface, SIGNAL(started(QString)), this, SLOT(appStarted(QString)));
56     connect(applaunch_iface, SIGNAL(terminated(QString)), this, SLOT(appTerminated(QString)));
57
58 }
59
60 static struct wl_output *
61 getWlOutput(QPlatformNativeInterface *native, QScreen *screen)
62 {
63         void *output = native->nativeResourceForScreen("output", screen);
64         return static_cast<struct ::wl_output*>(output);
65 }
66
67 void HomescreenHandler::tapShortcut(QString application_id)
68 {
69     QDBusPendingReply<> reply;
70     HMI_DEBUG("HomeScreen","tapShortcut %s", application_id.toStdString().c_str());
71
72     if (application_id == LAUNCHER_APP_ID)
73         goto activate_app;
74
75     reply = applaunch_iface->start(application_id);
76     reply.waitForFinished();
77
78     if (reply.isError()) {
79         HMI_ERROR("HomeScreen","Unable to start application '%s': %s",
80             application_id.toStdString().c_str(),
81             reply.error().message().toStdString().c_str());
82         return;
83     }
84
85 activate_app:
86     if (mp_launcher) {
87         mp_launcher->setCurrent(application_id);
88     }
89     appStarted(application_id);
90 }
91
92 /*
93  * Keep track of currently running apps and the order in which
94  * they were activated. That way, when an app is closed, we can
95  * switch back to the previously active one.
96  */
97 void HomescreenHandler::addAppToStack(const QString& application_id)
98 {
99     if (application_id == "homescreen")
100         return;
101
102     if (!apps_stack.contains(application_id)) {
103         apps_stack << application_id;
104     } else {
105         int current_pos = apps_stack.indexOf(application_id);
106         int last_pos = apps_stack.size() - 1;
107
108         if (current_pos != last_pos)
109             apps_stack.move(current_pos, last_pos);
110     }
111 }
112
113 void HomescreenHandler::appStarted(const QString& application_id)
114 {
115     struct agl_shell *agl_shell = aglShell->shell.get();
116     QPlatformNativeInterface *native = qApp->platformNativeInterface();
117     struct wl_output *output = getWlOutput(native, qApp->screens().first());
118
119     HMI_DEBUG("HomeScreen", "Activating application %s", application_id.toStdString().c_str());
120     agl_shell_activate_app(agl_shell, application_id.toStdString().c_str(), output);
121     addAppToStack(application_id);
122 }
123
124 void HomescreenHandler::appTerminated(const QString& application_id)
125 {
126     HMI_DEBUG("HomeScreen", "Application %s terminated, activating last app", application_id.toStdString().c_str());
127     if (apps_stack.contains(application_id)) {
128         apps_stack.removeOne(application_id);
129         if (!apps_stack.isEmpty())
130             appStarted(apps_stack.last());
131     }
132 }