From 8fb557550d4d3a7b799134af672f499531cc407e Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Wed, 29 Dec 2021 13:38:21 +0200 Subject: [PATCH 01/16] homescreenhandler: Set the application currently app running Bug-AGL: SPEC-4202 Signed-off-by: Marius Vlad Change-Id: Ifba64095536cee149ed80d94a42abeefdcdd16f4 --- homescreen/src/homescreenhandler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homescreen/src/homescreenhandler.cpp b/homescreen/src/homescreenhandler.cpp index ee8d614..d5e46fa 100644 --- a/homescreen/src/homescreenhandler.cpp +++ b/homescreen/src/homescreenhandler.cpp @@ -131,11 +131,11 @@ void HomescreenHandler::tapShortcut(QString application_id) // require calling 'agl_shell_activate_app' agl_shell_activate_app(agl_shell, application_id.toStdString().c_str(), output); - if (mp_launcher) { - mp_launcher->setCurrent(application_id); - } #endif + if (mp_launcher) { + mp_launcher->setCurrent(application_id); + } appStarted(application_id); } -- 2.16.6 From d7e13c3ccce72d55f2ea25ee06e822cda5ff911e Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Wed, 29 Dec 2021 15:46:57 +0200 Subject: [PATCH 02/16] homescreenhandler: Start applications from homescreen panel We're missing application start-up from within homescreen. The top panel surface contains a list of applications which can be started directly (without the launcher). Bug-AGL: SPEC-4203 Signed-off-by: Marius Vlad Change-Id: Icd008c8bdbf3f107972b5b279f1439cab5aaebee --- homescreen/src/homescreenhandler.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/homescreen/src/homescreenhandler.cpp b/homescreen/src/homescreenhandler.cpp index d5e46fa..94e1c9b 100644 --- a/homescreen/src/homescreenhandler.cpp +++ b/homescreen/src/homescreenhandler.cpp @@ -133,10 +133,18 @@ void HomescreenHandler::tapShortcut(QString application_id) #endif - if (mp_launcher) { - mp_launcher->setCurrent(application_id); + QDBusPendingReply<> reply = applaunch_iface->start(application_id); + reply.waitForFinished(); + if (reply.isError()) { + HMI_ERROR("HomeScreen","Unable to start application '%s': %s", + application_id.toStdString().c_str(), + reply.error().message().toStdString().c_str()); + } else { + if (mp_launcher) { + mp_launcher->setCurrent(application_id); + } + appStarted(application_id); } - appStarted(application_id); } #if 0 -- 2.16.6 From 1ffe62b257cbeffce9d812b4c63ee5359587943f Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Wed, 29 Dec 2021 16:05:32 +0200 Subject: [PATCH 03/16] package: Removal older artefacts from previous appfw Bug-AGL: SPEC-4204 Signed-off-by: Marius Vlad Change-Id: I74dfa2e24132b1928815963dfa6e1bcc4f706375 --- package/icon.svg | 279 ---------------------------------------------------- package/package.pro | 27 ----- 2 files changed, 306 deletions(-) delete mode 100644 package/icon.svg delete mode 100644 package/package.pro diff --git a/package/icon.svg b/package/icon.svg deleted file mode 100644 index 91661a7..0000000 --- a/package/icon.svg +++ /dev/null @@ -1,279 +0,0 @@ - - - -image/svg+xmlMULTIMEDIA - \ No newline at end of file diff --git a/package/package.pro b/package/package.pro deleted file mode 100644 index 1035088..0000000 --- a/package/package.pro +++ /dev/null @@ -1,27 +0,0 @@ -DISTFILES = icon.svg config.xml - -copy_icon.target = $$OUT_PWD/root/icon.svg -copy_icon.depends = $$_PRO_FILE_PWD_/icon.svg -copy_icon.commands = $(COPY_FILE) \"$$replace(copy_icon.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_icon.target, /, $$QMAKE_DIR_SEP)\" -QMAKE_EXTRA_TARGETS += copy_icon -PRE_TARGETDEPS += $$copy_icon.target - -copy_config.target = $$OUT_PWD/root/config.xml -copy_config.depends = $$_PRO_FILE_PWD_/config.xml -copy_config.commands = $(COPY_FILE) \"$$replace(copy_config.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_config.target, /, $$QMAKE_DIR_SEP)\" -QMAKE_EXTRA_TARGETS += copy_config -PRE_TARGETDEPS += $$copy_config.target - -WGT_TYPE = -CONFIG(debug, debug|release) { - WGT_TYPE = -debug -} - -wgt.target = package -wgt.commands = wgtpkg-pack -f -o homescreen$${WGT_TYPE}.wgt root - -QMAKE_EXTRA_TARGETS += wgt - -deploy.files = homescreen.wgt -deploy.path = /usr/AGL/apps/autoinstall -INSTALLS += deploy -- 2.16.6 From a920d9537132f3778c137edee8d6741102919787 Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Wed, 29 Dec 2021 16:09:09 +0200 Subject: [PATCH 04/16] homescreenhandler: Remove old artifacts We're no longer using anything from the older appfw so remove dead code. Bug-AGL: SPEC-4204 Signed-off-by: Marius Vlad Change-Id: I8a9714701a9bbb0da6768cd4bcbca52cb23464cd --- homescreen/src/homescreenhandler.cpp | 102 +---------------------------------- 1 file changed, 1 insertion(+), 101 deletions(-) diff --git a/homescreen/src/homescreenhandler.cpp b/homescreen/src/homescreenhandler.cpp index 94e1c9b..9111ebb 100644 --- a/homescreen/src/homescreenhandler.cpp +++ b/homescreen/src/homescreenhandler.cpp @@ -38,19 +38,10 @@ HomescreenHandler::HomescreenHandler(Shell *_aglShell, ApplicationLauncher *laun HomescreenHandler::~HomescreenHandler() { -#if 0 - if (mp_hs != NULL) { - delete mp_hs; - } -#endif } void HomescreenHandler::init(void) { -#if 0 - mp_hs = new LibHomeScreen(); - mp_hs->init(port, token); -#endif myThis = this; /* @@ -61,45 +52,6 @@ void HomescreenHandler::init(void) connect(applaunch_iface, SIGNAL(started(QString)), this, SLOT(appStarted(QString))); connect(applaunch_iface, SIGNAL(terminated(QString)), this, SLOT(appTerminated(QString))); -#if 0 - mp_hs->registerCallback(nullptr, HomescreenHandler::onRep_static); - - mp_hs->set_event_handler(LibHomeScreen::Event_OnScreenMessage, [this](json_object *object){ - const char *display_message = json_object_get_string( - json_object_object_get(object, "display_message")); - HMI_DEBUG("HomeScreen","set_event_handler Event_OnScreenMessage display_message = %s", display_message); - }); - - // should be handled in the top panel - mp_hs->set_event_handler(LibHomeScreen::Event_ShowNotification,[this](json_object *object){ - json_object *p_obj = json_object_object_get(object, "parameter"); - const char *icon = json_object_get_string( - json_object_object_get(p_obj, "icon")); - const char *text = json_object_get_string( - json_object_object_get(p_obj, "text")); - const char *app_id = json_object_get_string( - json_object_object_get(p_obj, "caller")); - HMI_DEBUG("HomeScreen","Event_ShowNotification icon=%s, text=%s, caller=%s", icon, text, app_id); - QFileInfo icon_file(icon); - QString icon_path; - if (icon_file.isFile() && icon_file.exists()) { - icon_path = QString(QLatin1String(icon)); - } else { - icon_path = "./images/Utility_Logo_Grey-01.svg"; - } - - emit showNotification(QString(QLatin1String(app_id)), icon_path, QString(QLatin1String(text))); - }); - - // should be handled in the bottom panel - mp_hs->set_event_handler(LibHomeScreen::Event_ShowInformation,[this](json_object *object){ - json_object *p_obj = json_object_object_get(object, "parameter"); - const char *info = json_object_get_string( - json_object_object_get(p_obj, "info")); - - emit showInformation(QString(QLatin1String(info))); - }); -#endif } static struct wl_output * @@ -111,27 +63,7 @@ getWlOutput(QPlatformNativeInterface *native, QScreen *screen) void HomescreenHandler::tapShortcut(QString application_id) { - HMI_DEBUG("HomeScreen","tapShortcut %s", application_id.toStdString().c_str()); -#if 0 - struct json_object* j_json = json_object_new_object(); - struct json_object* value; - - struct agl_shell *agl_shell = aglShell->shell.get(); - QPlatformNativeInterface *native = qApp->platformNativeInterface(); - struct wl_output *output = getWlOutput(native, qApp->screens().first()); - - value = json_object_new_string("normal.full"); - json_object_object_add(j_json, "area", value); - - mp_hs->showWindow(application_id.toStdString().c_str(), j_json); - - // this works (and it is redundant the first time), due to the default - // policy engine installed which actives the application, when starting - // the first time. Later calls to HomescreenHandler::tapShortcut will - // require calling 'agl_shell_activate_app' - agl_shell_activate_app(agl_shell, application_id.toStdString().c_str(), output); - -#endif + HMI_DEBUG("HomeScreen","tapShortcut %s", application_id.toStdString().c_str()); QDBusPendingReply<> reply = applaunch_iface->start(application_id); reply.waitForFinished(); @@ -147,38 +79,6 @@ void HomescreenHandler::tapShortcut(QString application_id) } } -#if 0 -void HomescreenHandler::onRep_static(struct json_object* reply_contents) -{ - static_cast(HomescreenHandler::myThis)->onRep(reply_contents); -} - -void HomescreenHandler::onEv_static(const string& event, struct json_object* event_contents) -{ - static_cast(HomescreenHandler::myThis)->onEv(event, event_contents); -} - -void HomescreenHandler::onRep(struct json_object* reply_contents) -{ - const char* str = json_object_to_json_string(reply_contents); - HMI_DEBUG("HomeScreen","HomeScreen onReply %s", str); -} - -void HomescreenHandler::onEv(const string& event, struct json_object* event_contents) -{ - const char* str = json_object_to_json_string(event_contents); - HMI_DEBUG("HomeScreen","HomeScreen onEv %s, contents: %s", event.c_str(), str); - - if (event.compare("homescreen/on_screen_message") == 0) { - struct json_object *json_data = json_object_object_get(event_contents, "data"); - struct json_object *json_display_message = json_object_object_get(json_data, "display_message"); - const char* display_message = json_object_get_string(json_display_message); - - HMI_DEBUG("HomeScreen","display_message = %s", display_message); - } -} -#endif - void HomescreenHandler::appStarted(const QString& application_id) { struct agl_shell *agl_shell = aglShell->shell.get(); -- 2.16.6 From bd55b5dd6131004daa43cfbbe7d0a22bc380bb90 Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Mon, 10 Jan 2022 14:13:17 +0200 Subject: [PATCH 05/16] homescreen/homescreen.pro: Bump protocol requirements This change is needed because we've updated the protocol in the compositor. Bug-AGL: SPEC-4207 Signed-off-by: Marius Vlad Change-Id: I9e85af39f61d7e6724faa11b10de571e4e60540e --- homescreen/homescreen.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homescreen/homescreen.pro b/homescreen/homescreen.pro index 7e93e02..3f94c11 100644 --- a/homescreen/homescreen.pro +++ b/homescreen/homescreen.pro @@ -51,7 +51,7 @@ RESOURCES += \ qml/images/images.qrc \ qml/qml.qrc -AGL_SHELL_PATH = $$system(pkg-config --variable=pkgdatadir agl-compositor-0.0.19-protocols) +AGL_SHELL_PATH = $$system(pkg-config --variable=pkgdatadir agl-compositor-0.0.20-protocols) WAYLANDCLIENTSOURCES += $$AGL_SHELL_PATH/agl-shell.xml target.path = $${PREFIX}/usr/bin -- 2.16.6 From 37ba3ff90d878a135e347508505657e3d56c5edd Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Mon, 17 Jan 2022 13:46:38 +0200 Subject: [PATCH 06/16] homescreenhandler: Do not attempt to start launcher Our launcher application is started by systemd as a user session, and attempting to start it again would result into being started once more, but this by applaunchd. Until we merge homescreen and launcher together avoid starting it and just activate it whenever necessary. Bug-AGL: SPEC-4215 Signed-off-by: Marius Vlad Change-Id: I90806457b74a2439cb8bdc88068954eb7ef1d532 --- homescreen/src/homescreenhandler.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/homescreen/src/homescreenhandler.cpp b/homescreen/src/homescreenhandler.cpp index 9111ebb..4a8b9cd 100644 --- a/homescreen/src/homescreenhandler.cpp +++ b/homescreen/src/homescreenhandler.cpp @@ -24,6 +24,9 @@ #define APPLAUNCH_DBUS_IFACE "org.automotivelinux.AppLaunch" #define APPLAUNCH_DBUS_OBJECT "/org/automotivelinux/AppLaunch" +/* LAUNCHER_APP_ID shouldn't be started by applaunchd as it is started as a + * user session by systemd */ +#define LAUNCHER_APP_ID "launcher" void* HomescreenHandler::myThis = 0; @@ -63,20 +66,27 @@ getWlOutput(QPlatformNativeInterface *native, QScreen *screen) void HomescreenHandler::tapShortcut(QString application_id) { + QDBusPendingReply<> reply; HMI_DEBUG("HomeScreen","tapShortcut %s", application_id.toStdString().c_str()); - QDBusPendingReply<> reply = applaunch_iface->start(application_id); + if (application_id == LAUNCHER_APP_ID) + goto activate_app; + + reply = applaunch_iface->start(application_id); reply.waitForFinished(); + if (reply.isError()) { HMI_ERROR("HomeScreen","Unable to start application '%s': %s", application_id.toStdString().c_str(), reply.error().message().toStdString().c_str()); - } else { - if (mp_launcher) { - mp_launcher->setCurrent(application_id); - } - appStarted(application_id); + return; + } + +activate_app: + if (mp_launcher) { + mp_launcher->setCurrent(application_id); } + appStarted(application_id); } void HomescreenHandler::appStarted(const QString& application_id) -- 2.16.6 From 20970d846906a070305d8e96cf0735bf7fd831b1 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Tue, 18 Jan 2022 12:47:02 +0100 Subject: [PATCH 07/16] homescreenhandler: keep track of active apps When the current app window is closed, the current behavior depends on whether this action terminates the app: - if the app is terminated, then we switch back to the launcher - in the other case, we display the background, even if other apps are running In order to implement a better behavior, we should keep track of active apps and switch back to the previously active one when the current app window is closed. Bug-AGL: SPEC-4222 Signed-off-by: Arnaud Ferraris Change-Id: Idf1fe42886e95e2b37349b066204fde002d7c3b5 --- homescreen/src/homescreenhandler.cpp | 29 +++++++++++++++++++++++++++-- homescreen/src/homescreenhandler.h | 3 +++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/homescreen/src/homescreenhandler.cpp b/homescreen/src/homescreenhandler.cpp index 4a8b9cd..5ed1fab 100644 --- a/homescreen/src/homescreenhandler.cpp +++ b/homescreen/src/homescreenhandler.cpp @@ -89,6 +89,27 @@ activate_app: appStarted(application_id); } +/* + * Keep track of currently running apps and the order in which + * they were activated. That way, when an app is closed, we can + * switch back to the previously active one. + */ +void HomescreenHandler::addAppToStack(const QString& application_id) +{ + if (application_id == "homescreen") + return; + + if (!apps_stack.contains(application_id)) { + apps_stack << application_id; + } else { + int current_pos = apps_stack.indexOf(application_id); + int last_pos = apps_stack.size() - 1; + + if (current_pos != last_pos) + apps_stack.move(current_pos, last_pos); + } +} + void HomescreenHandler::appStarted(const QString& application_id) { struct agl_shell *agl_shell = aglShell->shell.get(); @@ -97,10 +118,14 @@ void HomescreenHandler::appStarted(const QString& application_id) HMI_DEBUG("HomeScreen", "Activating application %s", application_id.toStdString().c_str()); agl_shell_activate_app(agl_shell, application_id.toStdString().c_str(), output); + addAppToStack(application_id); } void HomescreenHandler::appTerminated(const QString& application_id) { - HMI_DEBUG("HomeScreen", "Application %s terminated, activating launcher", application_id.toStdString().c_str()); - appStarted("launcher"); + HMI_DEBUG("HomeScreen", "Application %s terminated, activating last app", application_id.toStdString().c_str()); + if (apps_stack.contains(application_id)) { + apps_stack.removeOne(application_id); + appStarted(apps_stack.last()); + } } diff --git a/homescreen/src/homescreenhandler.h b/homescreen/src/homescreenhandler.h index d94740b..503221a 100644 --- a/homescreen/src/homescreenhandler.h +++ b/homescreen/src/homescreenhandler.h @@ -48,6 +48,8 @@ public: static void onEv_static(const string& event, struct json_object* event_contents); #endif + void addAppToStack(const QString& application_id); + signals: void showNotification(QString application_id, QString icon_path, QString text); void showInformation(QString info); @@ -60,6 +62,7 @@ private: ApplicationLauncher *mp_launcher; Shell *aglShell; org::automotivelinux::AppLaunch *applaunch_iface; + QStringList apps_stack; }; #endif // HOMESCREENHANDLER_H -- 2.16.6 From a3c4beb8a9d1a01a4a29434e8319be7ce3f0d42f Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Tue, 18 Jan 2022 12:52:43 +0100 Subject: [PATCH 08/16] Use agl-shell-desktop protocol to keep track of closed windows Currently, we have no way of knowing when the main window of an application is closed unless this action terminates the app. Hooking up the `agl-shell-desktop` protocol allows us to be notified when this happens, so we can instruct `homescreenhandler` to switch back to the previously active app. Bug-AGL: SPEC-4222 Signed-off-by: Arnaud Ferraris Change-Id: I26dfaccce8894c2599afd9b14349b0703727d47a --- homescreen/homescreen.pro | 2 +- homescreen/src/main.cpp | 85 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 68 insertions(+), 19 deletions(-) diff --git a/homescreen/homescreen.pro b/homescreen/homescreen.pro index 3f94c11..80f0f49 100644 --- a/homescreen/homescreen.pro +++ b/homescreen/homescreen.pro @@ -52,7 +52,7 @@ RESOURCES += \ qml/qml.qrc AGL_SHELL_PATH = $$system(pkg-config --variable=pkgdatadir agl-compositor-0.0.20-protocols) -WAYLANDCLIENTSOURCES += $$AGL_SHELL_PATH/agl-shell.xml +WAYLANDCLIENTSOURCES += $$AGL_SHELL_PATH/agl-shell.xml $$AGL_SHELL_PATH/agl-shell-desktop.xml target.path = $${PREFIX}/usr/bin target.files += $${OUT_PWD}/$${TARGET} diff --git a/homescreen/src/main.cpp b/homescreen/src/main.cpp index 75ed97c..cf7f02e 100644 --- a/homescreen/src/main.cpp +++ b/homescreen/src/main.cpp @@ -40,19 +40,64 @@ #include #include "wayland-agl-shell-client-protocol.h" +#include "wayland-agl-shell-desktop-client-protocol.h" #include "shell.h" +struct shell_data { + struct agl_shell *shell; + struct agl_shell_desktop *shell_desktop; +}; + +static void +agl_shell_desktop_application(void *data, + struct agl_shell_desktop *agl_shell_desktop, + const char *app_id) +{ + HomescreenHandler *homescreenHandler = static_cast(data); + + if (homescreenHandler) + homescreenHandler->addAppToStack(app_id); +} + +static void +agl_shell_desktop_state_app(void *data, + struct agl_shell_desktop *agl_shell_desktop, + const char *app_id, + const char *app_data, + uint32_t state, + uint32_t role) +{ + HomescreenHandler *homescreenHandler = static_cast(data); + + if (homescreenHandler && state == AGL_SHELL_DESKTOP_APP_STATE_DESTROYED) + homescreenHandler->appTerminated(app_id); +} + +static const struct agl_shell_desktop_listener shell_desktop_listener = { + agl_shell_desktop_application, + agl_shell_desktop_state_app +}; + static void global_add(void *data, struct wl_registry *reg, uint32_t name, const char *interface, uint32_t) { - struct agl_shell **shell = static_cast(data); + struct shell_data *shell_data = static_cast(data); + + if (!shell_data) + return; if (strcmp(interface, agl_shell_interface.name) == 0) { - *shell = static_cast( + shell_data->shell = static_cast( wl_registry_bind(reg, name, &agl_shell_interface, 1) ); } + + if (strcmp(interface, agl_shell_desktop_interface.name) == 0) { + shell_data->shell_desktop = static_cast( + wl_registry_bind(reg, name, &agl_shell_desktop_interface, 1) + ); + } } static void @@ -84,25 +129,22 @@ getWlOutput(QPlatformNativeInterface *native, QScreen *screen) } -static struct agl_shell * -register_agl_shell(QPlatformNativeInterface *native) +static void +register_agl_shell(QPlatformNativeInterface *native, struct shell_data *shell_data) { struct wl_display *wl; struct wl_registry *registry; - struct agl_shell *shell = nullptr; wl = static_cast( native->nativeResourceForIntegration("display") ); registry = wl_display_get_registry(wl); - wl_registry_add_listener(registry, ®istry_listener, &shell); + wl_registry_add_listener(registry, ®istry_listener, shell_data); /* Roundtrip to get all globals advertised by the compositor */ wl_display_roundtrip(wl); wl_registry_destroy(registry); - - return shell; } static struct wl_surface * @@ -210,14 +252,14 @@ int main(int argc, char *argv[]) QGuiApplication a(argc, argv); const char *screen_name; bool is_demo_val = false; + struct shell_data shell_data = { nullptr, nullptr }; QPlatformNativeInterface *native = qApp->platformNativeInterface(); - struct agl_shell *agl_shell = nullptr; screen_name = getenv("HOMESCREEN_START_SCREEN"); const char *is_demo = getenv("HOMESCREEN_DEMO_CI"); if (is_demo && strcmp(is_demo, "1") == 0) - is_demo_val = true; + is_demo_val = true; QCoreApplication::setOrganizationDomain("LinuxFoundation"); QCoreApplication::setOrganizationName("AutomotiveGradeLinux"); @@ -226,15 +268,20 @@ int main(int argc, char *argv[]) /* we need to have an app_id */ a.setDesktopFileName("homescreen"); - agl_shell = register_agl_shell(native); - if (!agl_shell) { - fprintf(stderr, "agl_shell extension is not advertised. " - "Are you sure that agl-compositor is running?\n"); - exit(EXIT_FAILURE); + register_agl_shell(native, &shell_data); + if (!shell_data.shell) { + fprintf(stderr, "agl_shell extension is not advertised. " + "Are you sure that agl-compositor is running?\n"); + exit(EXIT_FAILURE); + } + if (!shell_data.shell_desktop) { + fprintf(stderr, "agl_shell_desktop extension is not advertised. " + "Are you sure that agl-compositor is running?\n"); + exit(EXIT_FAILURE); } - std::shared_ptr shell{agl_shell, agl_shell_destroy}; - Shell *aglShell = new Shell(shell, &a); + std::shared_ptr agl_shell{shell_data.shell, agl_shell_destroy}; + Shell *aglShell = new Shell(agl_shell, &a); // import C++ class to QML qmlRegisterType("HomeScreen", 1, 0, "StatusBarModel"); @@ -245,6 +292,8 @@ int main(int argc, char *argv[]) HomescreenHandler* homescreenHandler = new HomescreenHandler(aglShell, launcher); homescreenHandler->init(); + agl_shell_desktop_add_listener(shell_data.shell_desktop, &shell_desktop_listener, homescreenHandler); + QQmlApplicationEngine engine; QQmlContext *context = engine.rootContext(); @@ -260,7 +309,7 @@ int main(int argc, char *argv[]) /* instead of loading main.qml we load one-by-one each of the QMLs, * divided now between several surfaces: panels, background. */ - load_agl_shell_app(native, &engine, agl_shell, screen_name, is_demo_val); + load_agl_shell_app(native, &engine, shell_data.shell, screen_name, is_demo_val); return a.exec(); } -- 2.16.6 From b7b156ece9492401f7bfe7676e7521f4cdd32905 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Fri, 28 Jan 2022 17:02:52 -0500 Subject: [PATCH 09/16] Re-enable status bar Re-enable the status bar Bluetooth and Wifi status monitoring via the libqtappfw provided objects, and also hook up the currently stubbed weather support so it'll start working if it is updated in libqtappfw. Bug-AGL: SPEC-4182 Signed-off-by: Scott Murray Change-Id: I3aeb98dc01c0bc09550824f44bcb1d40f324e49e --- homescreen/homescreen.pro | 2 +- homescreen/qml/StatusArea.qml | 8 ++------ homescreen/src/main.cpp | 10 ++++------ homescreen/src/statusbarmodel.cpp | 19 +++---------------- 4 files changed, 10 insertions(+), 29 deletions(-) diff --git a/homescreen/homescreen.pro b/homescreen/homescreen.pro index 80f0f49..fd53072 100644 --- a/homescreen/homescreen.pro +++ b/homescreen/homescreen.pro @@ -17,7 +17,7 @@ TEMPLATE = app TARGET = homescreen QT = qml quick gui-private dbus CONFIG += c++11 link_pkgconfig wayland-scanner -PKGCONFIG += wayland-client +PKGCONFIG += wayland-client qtappfw-weather qtappfw-network qtappfw-bt DBUS_INTERFACES = $$[QT_SYSROOT]/usr/share/dbus-1/interfaces/org.automotivelinux.AppLaunch.xml diff --git a/homescreen/qml/StatusArea.qml b/homescreen/qml/StatusArea.qml index 87b27ad..4a8fbc0 100644 --- a/homescreen/qml/StatusArea.qml +++ b/homescreen/qml/StatusArea.qml @@ -30,7 +30,7 @@ Item { interval: 100; running: true; repeat: true; onTriggered: root.now = new Date } -/* + Connections { target: weather @@ -54,7 +54,7 @@ Item { temperature_item.text = temperature.split(".")[0] + '°F' } } -*/ + RowLayout { anchors.fill: parent spacing: 0 @@ -126,7 +126,6 @@ Item { fillMode: Image.PreserveAspectFit property string deviceName: "none" property bool connStatus: false -/* Connections { target: bluetooth @@ -134,9 +133,7 @@ Item { bt_icon.connStatus = state } } -*/ } -/* Repeater { model: StatusBarModel { objectName: "statusBar" } delegate: Image { @@ -146,7 +143,6 @@ Item { fillMode: Image.PreserveAspectFit } } -*/ } } } diff --git a/homescreen/src/main.cpp b/homescreen/src/main.cpp index cf7f02e..4e3073f 100644 --- a/homescreen/src/main.cpp +++ b/homescreen/src/main.cpp @@ -26,10 +26,9 @@ #include #include -#if 0 #include #include -#endif + #include "applicationlauncher.h" #include "statusbarmodel.h" #include "mastervolume.h" @@ -299,10 +298,9 @@ int main(int argc, char *argv[]) context->setContextProperty("homescreenHandler", homescreenHandler); context->setContextProperty("launcher", launcher); -#if 0 - context->setContextProperty("weather", new Weather(bindingAddress)); - context->setContextProperty("bluetooth", new Bluetooth(bindingAddress, context)); -#endif + context->setContextProperty("weather", new Weather()); + context->setContextProperty("bluetooth", new Bluetooth(false, context)); + // we add it here even if we don't use it context->setContextProperty("shell", aglShell); diff --git a/homescreen/src/statusbarmodel.cpp b/homescreen/src/statusbarmodel.cpp index 8b46cd1..447466d 100644 --- a/homescreen/src/statusbarmodel.cpp +++ b/homescreen/src/statusbarmodel.cpp @@ -17,9 +17,8 @@ #include "statusbarmodel.h" #include "statusbarserver.h" -#if 0 -#include "network.h" -#endif +#include +#include class StatusBarModel::Private { @@ -31,10 +30,8 @@ private: public: StatusBarServer server; QString iconList[StatusBarServer::SupportedCount]; -#if 0 Network *network; WifiAdapter *wifi_a; -#endif }; StatusBarModel::Private::Private(StatusBarModel *parent) @@ -64,8 +61,7 @@ StatusBarModel::~StatusBarModel() void StatusBarModel::init(QQmlContext *context) { -#if 0 - d->network = new Network(url, context); + d->network = new Network(false, context); context->setContextProperty("network", d->network); d->wifi_a = static_cast(d->network->findAdapter("wifi")); Q_CHECK_PTR(d->wifi_a); @@ -78,12 +74,10 @@ void StatusBarModel::init(QQmlContext *context) this, &StatusBarModel::onWifiStrengthChanged); setWifiStatus(d->wifi_a->wifiConnected(), d->wifi_a->wifiEnabled(), d->wifi_a->wifiStrength()); -#endif } void StatusBarModel::setWifiStatus(bool connected, bool enabled, int strength) { -#if 0 if (enabled && connected) if (strength < 30) d->server.setStatusIcon(0, QStringLiteral("qrc:/images/Status/HMI_Status_Wifi_1Bar-01.png")); @@ -95,29 +89,22 @@ void StatusBarModel::setWifiStatus(bool connected, bool enabled, int strength) d->server.setStatusIcon(0, QStringLiteral("qrc:/images/Status/HMI_Status_Wifi_Full-01.png")); else d->server.setStatusIcon(0, QStringLiteral("qrc:/images/Status/HMI_Status_Wifi_NoBars-01.png")); -#endif } void StatusBarModel::onWifiConnectedChanged(bool connected) { -#if 0 setWifiStatus(connected, d->wifi_a->wifiEnabled(), d->wifi_a->wifiStrength()); -#endif } void StatusBarModel::onWifiEnabledChanged(bool enabled) { -#if 0 setWifiStatus(d->wifi_a->wifiConnected(), enabled, d->wifi_a->wifiStrength()); -#endif } void StatusBarModel::onWifiStrengthChanged(int strength) { -#if 0 qInfo() << "Strength changed: " << strength; setWifiStatus(d->wifi_a->wifiConnected(), d->wifi_a->wifiEnabled(), strength); -#endif } int StatusBarModel::rowCount(const QModelIndex &parent) const -- 2.16.6 From c35327b02a28a83536450a664326d183662e89e1 Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Mon, 21 Feb 2022 20:31:39 +0200 Subject: [PATCH 10/16] homescreenhandler: Avoid passing an invalid appid If there's no item added in the QList we'll return an invalid value pointing to some invalid memory, which we can not determine if its empty string or not, so this makes sure we check the list itself. Found when looking at removal/activation of surfaces while re-doing some parts in the compositor. Bug-AGL: SPEC-4263 Signed-off-by: Marius Vlad Change-Id: I912aa5a42a7d21374a389a7f193979f30504a83b --- homescreen/src/homescreenhandler.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homescreen/src/homescreenhandler.cpp b/homescreen/src/homescreenhandler.cpp index 5ed1fab..c44cbb9 100644 --- a/homescreen/src/homescreenhandler.cpp +++ b/homescreen/src/homescreenhandler.cpp @@ -126,6 +126,7 @@ void HomescreenHandler::appTerminated(const QString& application_id) HMI_DEBUG("HomeScreen", "Application %s terminated, activating last app", application_id.toStdString().c_str()); if (apps_stack.contains(application_id)) { apps_stack.removeOne(application_id); - appStarted(apps_stack.last()); + if (!apps_stack.isEmpty()) + appStarted(apps_stack.last()); } } -- 2.16.6 From e490ff1e1e31b4a837cb8063f7346dc65ffe073e Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Fri, 17 Jun 2022 20:30:05 -0400 Subject: [PATCH 11/16] Add VIS vehicle signal support Update the volume control code to use to use VIS signalling instead of the previous agl-service-audiomixer binding usage. Bug-AGL: SPEC-4409 Signed-off-by: Scott Murray Change-Id: Ifc622a51991110c7786b80ee0af574ed6ca80561 (cherry picked from commit e3b392b8a0767f35e6dbbdb1e9d126294aebdcb5) --- homescreen/homescreen.pro | 2 +- homescreen/qml/MediaAreaBlank.qml | 12 +--- homescreen/src/main.cpp | 1 + homescreen/src/mastervolume.cpp | 122 ++++++++++++++++++-------------------- homescreen/src/mastervolume.h | 21 +++---- 5 files changed, 74 insertions(+), 84 deletions(-) diff --git a/homescreen/homescreen.pro b/homescreen/homescreen.pro index fd53072..00ed5e7 100644 --- a/homescreen/homescreen.pro +++ b/homescreen/homescreen.pro @@ -17,7 +17,7 @@ TEMPLATE = app TARGET = homescreen QT = qml quick gui-private dbus CONFIG += c++11 link_pkgconfig wayland-scanner -PKGCONFIG += wayland-client qtappfw-weather qtappfw-network qtappfw-bt +PKGCONFIG += wayland-client qtappfw-weather qtappfw-network qtappfw-bt qtappfw-vehicle-signals DBUS_INTERFACES = $$[QT_SYSROOT]/usr/share/dbus-1/interfaces/org.automotivelinux.AppLaunch.xml diff --git a/homescreen/qml/MediaAreaBlank.qml b/homescreen/qml/MediaAreaBlank.qml index 7a9e8af..b758a7d 100644 --- a/homescreen/qml/MediaAreaBlank.qml +++ b/homescreen/qml/MediaAreaBlank.qml @@ -19,9 +19,7 @@ import QtQuick 2.2 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.0 import AGL.Demo.Controls 1.0 -/* import MasterVolume 1.0 -*/ Image { anchors.fill: parent @@ -68,16 +66,13 @@ Image { transitions: Transition { NumberAnimation { property: "opacity"; duration: 500} } -/* + MasterVolume { id: mv objectName: "mv" onVolumeChanged: slider.value = volume - Component.onCompleted: { - mv.open(bindingAddress); - } } -*/ + Item { id: master_volume anchors.fill: parent @@ -108,10 +103,9 @@ Image { to: 100 stepSize: 1 snapMode: Slider.SnapOnRelease -/* onValueChanged: mv.volume = value Component.onCompleted: value = mv.volume -*/ + onPressedChanged: { if (pressed) {volume_timer.stop()} else {volume_timer.restart()} diff --git a/homescreen/src/main.cpp b/homescreen/src/main.cpp index 4e3073f..74ec4f4 100644 --- a/homescreen/src/main.cpp +++ b/homescreen/src/main.cpp @@ -248,6 +248,7 @@ load_agl_shell_app(QPlatformNativeInterface *native, int main(int argc, char *argv[]) { setenv("QT_QPA_PLATFORM", "wayland", 1); + setenv("QT_QUICK_CONTROLS_STYLE", "AGL", 1); QGuiApplication a(argc, argv); const char *screen_name; bool is_demo_val = false; diff --git a/homescreen/src/mastervolume.cpp b/homescreen/src/mastervolume.cpp index de8d75d..8d7ecb4 100644 --- a/homescreen/src/mastervolume.cpp +++ b/homescreen/src/mastervolume.cpp @@ -18,25 +18,21 @@ #include #include -#define MASTER_CONTROL "Master Playback" - -MasterVolume::MasterVolume(QObject* parent) - : QObject(parent) - , m_volume{50} +MasterVolume::MasterVolume(QObject* parent) : + QObject(parent), + m_volume(50) { -#if 0 - connect(&m_client, SIGNAL(connected()), this, SLOT(onClientConnected())); - connect(&m_client, SIGNAL(disconnected()), this, SLOT(onClientDisconnected())); - connect(&m_client, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onClientError(QAbstractSocket::SocketError))); - connect(&m_client, SIGNAL(eventReceived(QString, const QJsonValue&)), this, SLOT(onClientEventReceived(QString, const QJsonValue&))); -#endif -} + VehicleSignalsConfig vsConfig("homescreen"); + m_vs = new VehicleSignals(vsConfig); -#if 0 -void MasterVolume::open(const QUrl& url) -{ + if (m_vs) { + QObject::connect(m_vs, &VehicleSignals::connected, this, &MasterVolume::onConnected); + QObject::connect(m_vs, &VehicleSignals::authorized, this, &MasterVolume::onAuthorized); + QObject::connect(m_vs, &VehicleSignals::disconnected, this, &MasterVolume::onDisconnected); + + m_vs->connect(); + } } -#endif qint32 MasterVolume::getVolume() const { @@ -45,72 +41,70 @@ qint32 MasterVolume::getVolume() const void MasterVolume::setVolume(qint32 volume) { - if (m_volume != volume) - { - m_volume = volume; -#if 0 - QJsonObject arg; - arg.insert("control", MASTER_CONTROL); - double v = (double) volume / 100.0; - arg.insert("value", v); - m_client.call("audiomixer", "volume", arg); -#endif - } -} + if (m_volume == volume) + return; -#if 0 + m_volume = volume; -void MasterVolume::onClientConnected() -{ + if (!(m_vs && m_connected)) + return; - QJsonObject arg; - arg.insert("control", MASTER_CONTROL); - m_client.call("audiomixer", "volume", arg, [this](bool r, const QJsonValue& v) { - if (r && v.isObject()) { - int volume = v.toObject()["response"].toObject()["volume"].toDouble() * 100; - volume = qBound(0, volume, 100); - if (m_volume != volume) - { - m_volume = volume; - emit VolumeChanged(); - } - } - - QJsonObject arg; - arg.insert("event", "volume_changed"); - m_client.call("audiomixer", "subscribe", arg); - }); + m_vs->set("Vehicle.Cabin.Infotainment.Media.Volume", QString::number(volume)); } -void MasterVolume::onClientDisconnected() +void MasterVolume::onConnected() { - qDebug() << "MasterVolume::onClientDisconnected!"; - QTimer::singleShot(1000, this, SLOT(TryOpen())); + if (!m_vs) + return; + + m_vs->authorize(); } -void MasterVolume::onClientError(QAbstractSocket::SocketError se) +void MasterVolume::onAuthorized() { - qDebug() << "MasterVolume::onClientError: " << se; + if (!m_vs) + return; + + m_connected = true; + + QObject::connect(m_vs, &VehicleSignals::getSuccessResponse, this, &MasterVolume::onGetSuccessResponse); + QObject::connect(m_vs, &VehicleSignals::signalNotification, this, &MasterVolume::onSignalNotification); + + m_vs->subscribe("Vehicle.Cabin.Infotainment.Media.Volume"); + m_vs->get("Vehicle.Cabin.Infotainment.Media.Volume"); } -void MasterVolume::onClientEventReceived(QString name, const QJsonValue& data) +void MasterVolume::onDisconnected() { - qDebug() << "MasterVolume::onClientEventReceived[" << name << "]: " << data; - if (name == "audiomixer/volume_changed") - { - QString ctlName = data.toObject()["control"].toString(); + QObject::disconnect(m_vs, &VehicleSignals::signalNotification, this, &MasterVolume::onGetSuccessResponse); + QObject::disconnect(m_vs, &VehicleSignals::signalNotification, this, &MasterVolume::onSignalNotification); - if (ctlName != MASTER_CONTROL) - return; + m_connected = false; +} - int volume = data.toObject()["value"].toDouble() * 100; +void MasterVolume::updateVolume(QString value) +{ + bool ok; + qint32 volume = value.toInt(&ok); + if (ok) { volume = qBound(0, volume, 100); - if (m_volume != volume) - { + if (m_volume != volume) { m_volume = volume; emit VolumeChanged(); } } } -#endif +void MasterVolume::onGetSuccessResponse(QString path, QString value, QString timestamp) +{ + if (path == "Vehicle.Cabin.Infotainment.Media.Volume") { + updateVolume(value); + emit VolumeChanged(); + } +} + +void MasterVolume::onSignalNotification(QString path, QString value, QString timestamp) +{ + if (path == "Vehicle.Cabin.Infotainment.Media.Volume") + updateVolume(value); +} diff --git a/homescreen/src/mastervolume.h b/homescreen/src/mastervolume.h index 04ce3b5..fbbab4b 100644 --- a/homescreen/src/mastervolume.h +++ b/homescreen/src/mastervolume.h @@ -16,32 +16,33 @@ #include #include +#include "vehiclesignals.h" -class MasterVolume - : public QObject +class MasterVolume : public QObject { Q_OBJECT Q_PROPERTY (uint32_t volume READ getVolume WRITE setVolume NOTIFY VolumeChanged) private: qint32 m_volume; + VehicleSignals *m_vs; + bool m_connected; + + void updateVolume(QString value); public: MasterVolume(QObject* parent = nullptr); ~MasterVolume() = default; - //Q_INVOKABLE void open(const QUrl& url); Q_INVOKABLE qint32 getVolume() const; Q_INVOKABLE void setVolume(qint32 val); private slots: -#if 0 - void onClientConnected(); - void onClientDisconnected(); - void onClientError(QAbstractSocket::SocketError se); - void onClientEventReceived(QString name, const QJsonValue& data); - void TryOpen(); -#endif + void onConnected(); + void onAuthorized(); + void onDisconnected(); + void onGetSuccessResponse(QString path, QString value, QString timestamp); + void onSignalNotification(QString path, QString value, QString timestamp); signals: void VolumeChanged(); -- 2.16.6 From d1347bf236f84908fea96ba929e0e8376c2b1d78 Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Thu, 7 Jul 2022 13:00:19 +0300 Subject: [PATCH 12/16] homescreen: Bail out if no screens are found It might happen the system doesn't have any outputs connected, or there are literally no outputs present in the system. Instead of crashing and systemd trying always to start it up just make sure we handle that and print out a message about what is going it. Bug-AGL: SPEC-4459 Signed-off-by: Marius Vlad Change-Id: Ia3dfab66e69ea36b2cf50fc0f6c1fd188a87e240 --- homescreen/src/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/homescreen/src/main.cpp b/homescreen/src/main.cpp index 74ec4f4..e9a5817 100644 --- a/homescreen/src/main.cpp +++ b/homescreen/src/main.cpp @@ -221,6 +221,11 @@ load_agl_shell_app(QPlatformNativeInterface *native, else screen = find_screen(screen_name); + if (!screen) { + qDebug() << "No outputs present in the system."; + return; + } + qDebug() << "found primary screen " << qApp->primaryScreen()->name() << "first screen " << qApp->screens().first()->name(); output = getWlOutput(native, screen); -- 2.16.6 From 20f629dd6d8628611d950073c4f7a0446c40365a Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Sat, 10 Sep 2022 12:59:02 -0400 Subject: [PATCH 13/16] Rework to use launcher wrapper from libqtappfw Changes: - Switch to using the new app launcher API wrapper from libqtappfw in order to migrate to the new gRPC based API implementation. - The appStarted and appTerminated methods in HomescreenHandler have been renamed to activateApp and deactivateApp, respectively, to better reflect what they do. A new processAppStatusEvent method had been added that calls them as appropriate based on the event from the AppLauncherClient status update signal. - The copyright headers in the source files have been tweaked to remove the Apache license boilerplate in favour of a SPDX license tag. - The code in main.cpp that was not formatted with Linux-style has been reformatted to match the rest of the file. Bug-AGL: SPEC-4559 Signed-off-by: Scott Murray Change-Id: I236cb6a412945a6df7d35652c55f664264964f9c --- homescreen/homescreen.pro | 7 +- homescreen/src/homescreenhandler.cpp | 147 ++++++++++++++++------------------- homescreen/src/homescreenhandler.h | 59 +++++--------- homescreen/src/main.cpp | 144 ++++++++++++++++------------------ 4 files changed, 157 insertions(+), 200 deletions(-) diff --git a/homescreen/homescreen.pro b/homescreen/homescreen.pro index 00ed5e7..c713c76 100644 --- a/homescreen/homescreen.pro +++ b/homescreen/homescreen.pro @@ -15,11 +15,10 @@ TEMPLATE = app TARGET = homescreen -QT = qml quick gui-private dbus +QT = qml quick gui-private CONFIG += c++11 link_pkgconfig wayland-scanner -PKGCONFIG += wayland-client qtappfw-weather qtappfw-network qtappfw-bt qtappfw-vehicle-signals - -DBUS_INTERFACES = $$[QT_SYSROOT]/usr/share/dbus-1/interfaces/org.automotivelinux.AppLaunch.xml +PKGCONFIG += wayland-client +PKGCONFIG += qtappfw-weather qtappfw-network qtappfw-bt qtappfw-vehicle-signals qtappfw-applauncher SOURCES += \ src/main.cpp \ diff --git a/homescreen/src/homescreenhandler.cpp b/homescreen/src/homescreenhandler.cpp index c44cbb9..16d65fb 100644 --- a/homescreen/src/homescreenhandler.cpp +++ b/homescreen/src/homescreenhandler.cpp @@ -1,60 +1,43 @@ +// SPDX-License-Identifier: Apache-2.0 /* * Copyright (c) 2017, 2018, 2019 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright (c) 2022 Konsulko Group */ #include #include -#include "homescreenhandler.h" #include + +#include "homescreenhandler.h" #include "hmi-debug.h" #include -#define APPLAUNCH_DBUS_IFACE "org.automotivelinux.AppLaunch" -#define APPLAUNCH_DBUS_OBJECT "/org/automotivelinux/AppLaunch" -/* LAUNCHER_APP_ID shouldn't be started by applaunchd as it is started as a - * user session by systemd */ +// LAUNCHER_APP_ID shouldn't be started by applaunchd as it is started as +// a user session by systemd #define LAUNCHER_APP_ID "launcher" -void* HomescreenHandler::myThis = 0; - HomescreenHandler::HomescreenHandler(Shell *_aglShell, ApplicationLauncher *launcher, QObject *parent) : - QObject(parent), - aglShell(_aglShell) + QObject(parent), + aglShell(_aglShell) { - mp_launcher = launcher; - applaunch_iface = new org::automotivelinux::AppLaunch(APPLAUNCH_DBUS_IFACE, APPLAUNCH_DBUS_OBJECT, - QDBusConnection::sessionBus(), this); + mp_launcher = launcher; + mp_applauncher_client = new AppLauncherClient(); + + // + // The "started" event is received any time a start request is made to applaunchd, + // and the application either starts successfully or is already running. This + // effectively acts as a "switch to app X" action. + // + connect(mp_applauncher_client, + &AppLauncherClient::appStatusEvent, + this, + &HomescreenHandler::processAppStatusEvent); } HomescreenHandler::~HomescreenHandler() { -} - -void HomescreenHandler::init(void) -{ - myThis = this; - - /* - * The "started" signal is received any time a start request is made to applaunchd, - * and the application either starts successfully or is already running. This - * effectively acts as a "switch to app X" action. - */ - connect(applaunch_iface, SIGNAL(started(QString)), this, SLOT(appStarted(QString))); - connect(applaunch_iface, SIGNAL(terminated(QString)), this, SLOT(appTerminated(QString))); - + delete mp_applauncher_client; } static struct wl_output * @@ -64,29 +47,24 @@ getWlOutput(QPlatformNativeInterface *native, QScreen *screen) return static_cast(output); } -void HomescreenHandler::tapShortcut(QString application_id) +void HomescreenHandler::tapShortcut(QString app_id) { - QDBusPendingReply<> reply; - HMI_DEBUG("HomeScreen","tapShortcut %s", application_id.toStdString().c_str()); - - if (application_id == LAUNCHER_APP_ID) - goto activate_app; + HMI_DEBUG("HomeScreen","tapShortcut %s", app_id.toStdString().c_str()); - reply = applaunch_iface->start(application_id); - reply.waitForFinished(); + if (app_id == LAUNCHER_APP_ID) + goto activate_app; - if (reply.isError()) { - HMI_ERROR("HomeScreen","Unable to start application '%s': %s", - application_id.toStdString().c_str(), - reply.error().message().toStdString().c_str()); - return; - } + if (!mp_applauncher_client->startApplication(app_id)) { + HMI_ERROR("HomeScreen","Unable to start application '%s'", + app_id.toStdString().c_str()); + return; + } activate_app: - if (mp_launcher) { - mp_launcher->setCurrent(application_id); - } - appStarted(application_id); + if (mp_launcher) { + mp_launcher->setCurrent(app_id); + } + activateApp(app_id); } /* @@ -94,39 +72,48 @@ activate_app: * they were activated. That way, when an app is closed, we can * switch back to the previously active one. */ -void HomescreenHandler::addAppToStack(const QString& application_id) +void HomescreenHandler::addAppToStack(const QString& app_id) { - if (application_id == "homescreen") - return; - - if (!apps_stack.contains(application_id)) { - apps_stack << application_id; - } else { - int current_pos = apps_stack.indexOf(application_id); - int last_pos = apps_stack.size() - 1; - - if (current_pos != last_pos) - apps_stack.move(current_pos, last_pos); - } + if (app_id == "homescreen") + return; + + if (!apps_stack.contains(app_id)) { + apps_stack << app_id; + } else { + int current_pos = apps_stack.indexOf(app_id); + int last_pos = apps_stack.size() - 1; + + if (current_pos != last_pos) + apps_stack.move(current_pos, last_pos); + } } -void HomescreenHandler::appStarted(const QString& application_id) +void HomescreenHandler::activateApp(const QString& app_id) { struct agl_shell *agl_shell = aglShell->shell.get(); QPlatformNativeInterface *native = qApp->platformNativeInterface(); struct wl_output *output = getWlOutput(native, qApp->screens().first()); - HMI_DEBUG("HomeScreen", "Activating application %s", application_id.toStdString().c_str()); - agl_shell_activate_app(agl_shell, application_id.toStdString().c_str(), output); - addAppToStack(application_id); + HMI_DEBUG("HomeScreen", "Activating application %s", app_id.toStdString().c_str()); + agl_shell_activate_app(agl_shell, app_id.toStdString().c_str(), output); + addAppToStack(app_id); +} + +void HomescreenHandler::deactivateApp(const QString& app_id) +{ + if (apps_stack.contains(app_id)) { + apps_stack.removeOne(app_id); + if (!apps_stack.isEmpty()) + activateApp(apps_stack.last()); + } } -void HomescreenHandler::appTerminated(const QString& application_id) +void HomescreenHandler::processAppStatusEvent(const QString &app_id, const QString &status) { - HMI_DEBUG("HomeScreen", "Application %s terminated, activating last app", application_id.toStdString().c_str()); - if (apps_stack.contains(application_id)) { - apps_stack.removeOne(application_id); - if (!apps_stack.isEmpty()) - appStarted(apps_stack.last()); - } + if (status == "started") { + activateApp(app_id); + } else if (status == "terminated") { + HMI_DEBUG("HomeScreen", "Application %s terminated, activating last app", app_id.toStdString().c_str()); + deactivateApp(app_id); + } } diff --git a/homescreen/src/homescreenhandler.h b/homescreen/src/homescreenhandler.h index 503221a..a2baeb2 100644 --- a/homescreen/src/homescreenhandler.h +++ b/homescreen/src/homescreenhandler.h @@ -1,68 +1,49 @@ +// SPDX-License-Identifier: Apache-2.0 /* * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright (c) 2022 Konsulko Group */ #ifndef HOMESCREENHANDLER_H #define HOMESCREENHANDLER_H #include +#include #include "applicationlauncher.h" -#include "applaunch_interface.h" +#include "AppLauncherClient.h" #include "shell.h" -#include using namespace std; class HomescreenHandler : public QObject { - Q_OBJECT + Q_OBJECT public: - explicit HomescreenHandler(Shell *aglShell, ApplicationLauncher *launcher = 0, QObject *parent = 0); - ~HomescreenHandler(); - - void init(void); + explicit HomescreenHandler(Shell *aglShell, ApplicationLauncher *launcher = 0, QObject *parent = 0); + ~HomescreenHandler(); - Q_INVOKABLE void tapShortcut(QString application_id); + Q_INVOKABLE void tapShortcut(QString application_id); -#if 0 - void onRep(struct json_object* reply_contents); - void onEv(const string& event, struct json_object* event_contents); -#endif - static void* myThis; -#if 0 - static void onRep_static(struct json_object* reply_contents); - static void onEv_static(const string& event, struct json_object* event_contents); -#endif - - void addAppToStack(const QString& application_id); + void addAppToStack(const QString& application_id); + void activateApp(const QString& app_id); + void deactivateApp(const QString& app_id); signals: - void showNotification(QString application_id, QString icon_path, QString text); - void showInformation(QString info); + void showNotification(QString application_id, QString icon_path, QString text); + void showInformation(QString info); public slots: - void appStarted(const QString& application_id); - void appTerminated(const QString& application_id); + void processAppStatusEvent(const QString &id, const QString &status); private: - ApplicationLauncher *mp_launcher; - Shell *aglShell; - org::automotivelinux::AppLaunch *applaunch_iface; - QStringList apps_stack; + ApplicationLauncher *mp_launcher; + AppLauncherClient *mp_applauncher_client; + + Shell *aglShell; + + QStringList apps_stack; }; #endif // HOMESCREENHANDLER_H diff --git a/homescreen/src/main.cpp b/homescreen/src/main.cpp index e9a5817..2c2f7c0 100644 --- a/homescreen/src/main.cpp +++ b/homescreen/src/main.cpp @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0 /* * Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH * Copyright (c) 2017, 2018 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright (c) 2022 Konsulko Group */ #include @@ -69,7 +59,7 @@ agl_shell_desktop_state_app(void *data, HomescreenHandler *homescreenHandler = static_cast(data); if (homescreenHandler && state == AGL_SHELL_DESKTOP_APP_STATE_DESTROYED) - homescreenHandler->appTerminated(app_id); + homescreenHandler->deactivateApp(app_id); } static const struct agl_shell_desktop_listener shell_desktop_listener = { @@ -252,68 +242,68 @@ load_agl_shell_app(QPlatformNativeInterface *native, int main(int argc, char *argv[]) { - setenv("QT_QPA_PLATFORM", "wayland", 1); - setenv("QT_QUICK_CONTROLS_STYLE", "AGL", 1); - QGuiApplication a(argc, argv); - const char *screen_name; - bool is_demo_val = false; - struct shell_data shell_data = { nullptr, nullptr }; - - QPlatformNativeInterface *native = qApp->platformNativeInterface(); - screen_name = getenv("HOMESCREEN_START_SCREEN"); - - const char *is_demo = getenv("HOMESCREEN_DEMO_CI"); - if (is_demo && strcmp(is_demo, "1") == 0) - is_demo_val = true; - - QCoreApplication::setOrganizationDomain("LinuxFoundation"); - QCoreApplication::setOrganizationName("AutomotiveGradeLinux"); - QCoreApplication::setApplicationName("HomeScreen"); - QCoreApplication::setApplicationVersion("0.7.0"); - /* we need to have an app_id */ - a.setDesktopFileName("homescreen"); - - register_agl_shell(native, &shell_data); - if (!shell_data.shell) { - fprintf(stderr, "agl_shell extension is not advertised. " - "Are you sure that agl-compositor is running?\n"); - exit(EXIT_FAILURE); - } - if (!shell_data.shell_desktop) { - fprintf(stderr, "agl_shell_desktop extension is not advertised. " - "Are you sure that agl-compositor is running?\n"); - exit(EXIT_FAILURE); - } - - std::shared_ptr agl_shell{shell_data.shell, agl_shell_destroy}; - Shell *aglShell = new Shell(agl_shell, &a); - - // import C++ class to QML - qmlRegisterType("HomeScreen", 1, 0, "StatusBarModel"); - qmlRegisterType("MasterVolume", 1, 0, "MasterVolume"); - - ApplicationLauncher *launcher = new ApplicationLauncher(); - launcher->setCurrent(QStringLiteral("launcher")); - HomescreenHandler* homescreenHandler = new HomescreenHandler(aglShell, launcher); - homescreenHandler->init(); - - agl_shell_desktop_add_listener(shell_data.shell_desktop, &shell_desktop_listener, homescreenHandler); - - QQmlApplicationEngine engine; - QQmlContext *context = engine.rootContext(); - - context->setContextProperty("homescreenHandler", homescreenHandler); - context->setContextProperty("launcher", launcher); - context->setContextProperty("weather", new Weather()); - context->setContextProperty("bluetooth", new Bluetooth(false, context)); - - // we add it here even if we don't use it - context->setContextProperty("shell", aglShell); - - /* instead of loading main.qml we load one-by-one each of the QMLs, - * divided now between several surfaces: panels, background. - */ - load_agl_shell_app(native, &engine, shell_data.shell, screen_name, is_demo_val); - - return a.exec(); + setenv("QT_QPA_PLATFORM", "wayland", 1); + setenv("QT_QUICK_CONTROLS_STYLE", "AGL", 1); + + QGuiApplication app(argc, argv); + const char *screen_name; + bool is_demo_val = false; + struct shell_data shell_data = { nullptr, nullptr }; + + QPlatformNativeInterface *native = qApp->platformNativeInterface(); + screen_name = getenv("HOMESCREEN_START_SCREEN"); + + const char *is_demo = getenv("HOMESCREEN_DEMO_CI"); + if (is_demo && strcmp(is_demo, "1") == 0) + is_demo_val = true; + + QCoreApplication::setOrganizationDomain("LinuxFoundation"); + QCoreApplication::setOrganizationName("AutomotiveGradeLinux"); + QCoreApplication::setApplicationName("HomeScreen"); + QCoreApplication::setApplicationVersion("0.7.0"); + + // we need to have an app_id + app.setDesktopFileName("homescreen"); + + register_agl_shell(native, &shell_data); + if (!shell_data.shell) { + fprintf(stderr, "agl_shell extension is not advertised. " + "Are you sure that agl-compositor is running?\n"); + exit(EXIT_FAILURE); + } + if (!shell_data.shell_desktop) { + fprintf(stderr, "agl_shell_desktop extension is not advertised. " + "Are you sure that agl-compositor is running?\n"); + exit(EXIT_FAILURE); + } + + std::shared_ptr agl_shell{shell_data.shell, agl_shell_destroy}; + Shell *aglShell = new Shell(agl_shell, &app); + + // Import C++ class to QML + qmlRegisterType("HomeScreen", 1, 0, "StatusBarModel"); + qmlRegisterType("MasterVolume", 1, 0, "MasterVolume"); + + ApplicationLauncher *launcher = new ApplicationLauncher(); + launcher->setCurrent(QStringLiteral("launcher")); + HomescreenHandler* homescreenHandler = new HomescreenHandler(aglShell, launcher); + + agl_shell_desktop_add_listener(shell_data.shell_desktop, &shell_desktop_listener, homescreenHandler); + + QQmlApplicationEngine engine; + QQmlContext *context = engine.rootContext(); + + context->setContextProperty("homescreenHandler", homescreenHandler); + context->setContextProperty("launcher", launcher); + context->setContextProperty("weather", new Weather()); + context->setContextProperty("bluetooth", new Bluetooth(false, context)); + + // We add it here even if we don't use it + context->setContextProperty("shell", aglShell); + + // Instead of loading main.qml we load one-by-one each of the QMLs, + // divided now between several surfaces: panels, background. + load_agl_shell_app(native, &engine, shell_data.shell, screen_name, is_demo_val); + + return app.exec(); } -- 2.16.6 From 98d13ef3af738ad9186b5c5a027e874d1bc1dfbc Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Thu, 22 Sep 2022 16:36:33 +0300 Subject: [PATCH 14/16] homescreen: Support for bound_ok and bound_fail events This adds support for version 2 of the protocol, but to also provide an example for other clients how to use it. Bug-AGL: SPEC-4502 Signed-off-by: Marius Vlad Change-Id: I710026bf293280d7aec2aa5d6e4528965840e23c --- homescreen/src/main.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 8 deletions(-) diff --git a/homescreen/src/main.cpp b/homescreen/src/main.cpp index 2c2f7c0..4a13607 100644 --- a/homescreen/src/main.cpp +++ b/homescreen/src/main.cpp @@ -32,9 +32,16 @@ #include "wayland-agl-shell-desktop-client-protocol.h" #include "shell.h" +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + struct shell_data { struct agl_shell *shell; struct agl_shell_desktop *shell_desktop; + bool wait_for_bound; + bool bound_ok; + int ver; }; static void @@ -62,6 +69,31 @@ agl_shell_desktop_state_app(void *data, homescreenHandler->deactivateApp(app_id); } +static void +agl_shell_bound_ok(void *data, struct agl_shell *agl_shell) +{ + struct shell_data *shell_data = static_cast(data); + shell_data->wait_for_bound = false; + + shell_data->bound_ok = true; +} + +static void +agl_shell_bound_fail(void *data, struct agl_shell *agl_shell) +{ + struct shell_data *shell_data = static_cast(data); + shell_data->wait_for_bound = false; + + shell_data->bound_ok = false; +} + +#ifdef AGL_SHELL_BOUND_OK_SINCE_VERSION +static const struct agl_shell_listener shell_listener = { + agl_shell_bound_ok, + agl_shell_bound_fail, +}; +#endif + static const struct agl_shell_desktop_listener shell_desktop_listener = { agl_shell_desktop_application, agl_shell_desktop_state_app @@ -69,7 +101,7 @@ static const struct agl_shell_desktop_listener shell_desktop_listener = { static void global_add(void *data, struct wl_registry *reg, uint32_t name, - const char *interface, uint32_t) + const char *interface, uint32_t ver) { struct shell_data *shell_data = static_cast(data); @@ -77,9 +109,20 @@ global_add(void *data, struct wl_registry *reg, uint32_t name, return; if (strcmp(interface, agl_shell_interface.name) == 0) { - shell_data->shell = static_cast( - wl_registry_bind(reg, name, &agl_shell_interface, 1) - ); + if (ver >= 2) { + shell_data->shell = + static_cast( + wl_registry_bind(reg, name, &agl_shell_interface, MIN(2, ver))); +#ifdef AGL_SHELL_BOUND_OK_SINCE_VERSION + agl_shell_add_listener(shell_data->shell, &shell_listener, data); +#endif + } else { + shell_data->shell = + static_cast( + wl_registry_bind(reg, name, &agl_shell_interface, 1)); + } + shell_data->ver = ver; + } if (strcmp(interface, agl_shell_desktop_interface.name) == 0) { @@ -117,6 +160,14 @@ getWlOutput(QPlatformNativeInterface *native, QScreen *screen) return static_cast(output); } +static struct wl_display * +getWlDisplay(QPlatformNativeInterface *native) +{ + return static_cast( + native->nativeResourceForIntegration("display") + ); +} + static void register_agl_shell(QPlatformNativeInterface *native, struct shell_data *shell_data) @@ -124,9 +175,7 @@ register_agl_shell(QPlatformNativeInterface *native, struct shell_data *shell_da struct wl_display *wl; struct wl_registry *registry; - wl = static_cast( - native->nativeResourceForIntegration("display") - ); + wl = getWlDisplay(native); registry = wl_display_get_registry(wl); wl_registry_add_listener(registry, ®istry_listener, shell_data); @@ -248,7 +297,8 @@ int main(int argc, char *argv[]) QGuiApplication app(argc, argv); const char *screen_name; bool is_demo_val = false; - struct shell_data shell_data = { nullptr, nullptr }; + int ret = 0; + struct shell_data shell_data = { nullptr, nullptr, true, false, 0 }; QPlatformNativeInterface *native = qApp->platformNativeInterface(); screen_name = getenv("HOMESCREEN_START_SCREEN"); @@ -277,6 +327,22 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } + qDebug() << "agl-shell interface is at version " << shell_data.ver; + if (shell_data.ver >= 2) { + while (ret != -1 && shell_data.wait_for_bound) { + ret = wl_display_dispatch(getWlDisplay(native)); + + if (shell_data.wait_for_bound) + continue; + } + + if (!shell_data.bound_ok) { + qInfo() << "agl_shell extension already in use by other shell client."; + exit(EXIT_FAILURE); + } + } + + std::shared_ptr agl_shell{shell_data.shell, agl_shell_destroy}; Shell *aglShell = new Shell(agl_shell, &app); -- 2.16.6 From 52c767388614e2ec6fa26851840bf01d97c5d49e Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Thu, 22 Sep 2022 16:50:11 +0300 Subject: [PATCH 15/16] homescreen: Add support for v3 of agl-shell protocol This protocol update adds support for started/terminated/activate/deactive events sent by the compositor. With this change we remove support for agl-shell-desktop protocol and instead rely on this new protocol update. Bug-AGL: SPEC-4528 Signed-off-by: Marius Vlad Change-Id: I9eb2135c5331eea82635583e8ca7cdf4e41a3d5e --- homescreen/homescreen.pro | 2 +- homescreen/src/homescreenhandler.cpp | 30 +++++++------- homescreen/src/main.cpp | 80 +++++++++++++++--------------------- 3 files changed, 51 insertions(+), 61 deletions(-) diff --git a/homescreen/homescreen.pro b/homescreen/homescreen.pro index c713c76..16a01f6 100644 --- a/homescreen/homescreen.pro +++ b/homescreen/homescreen.pro @@ -51,7 +51,7 @@ RESOURCES += \ qml/qml.qrc AGL_SHELL_PATH = $$system(pkg-config --variable=pkgdatadir agl-compositor-0.0.20-protocols) -WAYLANDCLIENTSOURCES += $$AGL_SHELL_PATH/agl-shell.xml $$AGL_SHELL_PATH/agl-shell-desktop.xml +WAYLANDCLIENTSOURCES += $$AGL_SHELL_PATH/agl-shell.xml target.path = $${PREFIX}/usr/bin target.files += $${OUT_PWD}/$${TARGET} diff --git a/homescreen/src/homescreenhandler.cpp b/homescreen/src/homescreenhandler.cpp index 16d65fb..920c054 100644 --- a/homescreen/src/homescreenhandler.cpp +++ b/homescreen/src/homescreenhandler.cpp @@ -51,20 +51,16 @@ void HomescreenHandler::tapShortcut(QString app_id) { HMI_DEBUG("HomeScreen","tapShortcut %s", app_id.toStdString().c_str()); - if (app_id == LAUNCHER_APP_ID) - goto activate_app; + if (app_id == LAUNCHER_APP_ID) { + activateApp(app_id); + return; + } if (!mp_applauncher_client->startApplication(app_id)) { HMI_ERROR("HomeScreen","Unable to start application '%s'", app_id.toStdString().c_str()); return; } - -activate_app: - if (mp_launcher) { - mp_launcher->setCurrent(app_id); - } - activateApp(app_id); } /* @@ -90,13 +86,16 @@ void HomescreenHandler::addAppToStack(const QString& app_id) void HomescreenHandler::activateApp(const QString& app_id) { - struct agl_shell *agl_shell = aglShell->shell.get(); - QPlatformNativeInterface *native = qApp->platformNativeInterface(); - struct wl_output *output = getWlOutput(native, qApp->screens().first()); + struct agl_shell *agl_shell = aglShell->shell.get(); + QPlatformNativeInterface *native = qApp->platformNativeInterface(); + struct wl_output *output = getWlOutput(native, qApp->screens().first()); + + if (mp_launcher) { + mp_launcher->setCurrent(app_id); + } - HMI_DEBUG("HomeScreen", "Activating application %s", app_id.toStdString().c_str()); - agl_shell_activate_app(agl_shell, app_id.toStdString().c_str(), output); - addAppToStack(app_id); + HMI_DEBUG("HomeScreen", "Activating application %s", app_id.toStdString().c_str()); + agl_shell_activate_app(agl_shell, app_id.toStdString().c_str(), output); } void HomescreenHandler::deactivateApp(const QString& app_id) @@ -110,6 +109,9 @@ void HomescreenHandler::deactivateApp(const QString& app_id) void HomescreenHandler::processAppStatusEvent(const QString &app_id, const QString &status) { + HMI_DEBUG("HomeScreen", "Processing application %s, status %s", + app_id.toStdString().c_str(), status.toStdString().c_str()); + if (status == "started") { activateApp(app_id); } else if (status == "terminated") { diff --git a/homescreen/src/main.cpp b/homescreen/src/main.cpp index 4a13607..8c3391f 100644 --- a/homescreen/src/main.cpp +++ b/homescreen/src/main.cpp @@ -29,7 +29,6 @@ #include #include "wayland-agl-shell-client-protocol.h" -#include "wayland-agl-shell-desktop-client-protocol.h" #include "shell.h" #ifndef MIN @@ -38,37 +37,12 @@ struct shell_data { struct agl_shell *shell; - struct agl_shell_desktop *shell_desktop; + HomescreenHandler *homescreenHandler; bool wait_for_bound; bool bound_ok; int ver; }; -static void -agl_shell_desktop_application(void *data, - struct agl_shell_desktop *agl_shell_desktop, - const char *app_id) -{ - HomescreenHandler *homescreenHandler = static_cast(data); - - if (homescreenHandler) - homescreenHandler->addAppToStack(app_id); -} - -static void -agl_shell_desktop_state_app(void *data, - struct agl_shell_desktop *agl_shell_desktop, - const char *app_id, - const char *app_data, - uint32_t state, - uint32_t role) -{ - HomescreenHandler *homescreenHandler = static_cast(data); - - if (homescreenHandler && state == AGL_SHELL_DESKTOP_APP_STATE_DESTROYED) - homescreenHandler->deactivateApp(app_id); -} - static void agl_shell_bound_ok(void *data, struct agl_shell *agl_shell) { @@ -87,18 +61,43 @@ agl_shell_bound_fail(void *data, struct agl_shell *agl_shell) shell_data->bound_ok = false; } +static void +agl_shell_app_state(void *data, struct agl_shell *agl_shell, + const char *app_id, uint32_t state) +{ + struct shell_data *shell_data = static_cast(data); + HomescreenHandler *homescreenHandler = shell_data->homescreenHandler; + + if (!homescreenHandler) + return; + + switch (state) { + case AGL_SHELL_APP_STATE_STARTED: + qDebug() << "Got AGL_SHELL_APP_STATE_STARTED for app_id " << app_id; + homescreenHandler->processAppStatusEvent(app_id, "started"); + break; + case AGL_SHELL_APP_STATE_TERMINATED: + qDebug() << "Got AGL_SHELL_APP_STATE_TERMINATED for app_id " << app_id; + // handled by HomescreenHandler::processAppStatusEvent + break; + case AGL_SHELL_APP_STATE_ACTIVATED: + qDebug() << "Got AGL_SHELL_APP_STATE_ACTIVATED for app_id " << app_id; + homescreenHandler->addAppToStack(app_id); + break; + default: + break; + } +} + + #ifdef AGL_SHELL_BOUND_OK_SINCE_VERSION static const struct agl_shell_listener shell_listener = { agl_shell_bound_ok, agl_shell_bound_fail, + agl_shell_app_state, }; #endif -static const struct agl_shell_desktop_listener shell_desktop_listener = { - agl_shell_desktop_application, - agl_shell_desktop_state_app -}; - static void global_add(void *data, struct wl_registry *reg, uint32_t name, const char *interface, uint32_t ver) @@ -112,7 +111,7 @@ global_add(void *data, struct wl_registry *reg, uint32_t name, if (ver >= 2) { shell_data->shell = static_cast( - wl_registry_bind(reg, name, &agl_shell_interface, MIN(2, ver))); + wl_registry_bind(reg, name, &agl_shell_interface, MIN(3, ver))); #ifdef AGL_SHELL_BOUND_OK_SINCE_VERSION agl_shell_add_listener(shell_data->shell, &shell_listener, data); #endif @@ -124,12 +123,6 @@ global_add(void *data, struct wl_registry *reg, uint32_t name, shell_data->ver = ver; } - - if (strcmp(interface, agl_shell_desktop_interface.name) == 0) { - shell_data->shell_desktop = static_cast( - wl_registry_bind(reg, name, &agl_shell_desktop_interface, 1) - ); - } } static void @@ -321,11 +314,6 @@ int main(int argc, char *argv[]) "Are you sure that agl-compositor is running?\n"); exit(EXIT_FAILURE); } - if (!shell_data.shell_desktop) { - fprintf(stderr, "agl_shell_desktop extension is not advertised. " - "Are you sure that agl-compositor is running?\n"); - exit(EXIT_FAILURE); - } qDebug() << "agl-shell interface is at version " << shell_data.ver; if (shell_data.ver >= 2) { @@ -352,9 +340,9 @@ int main(int argc, char *argv[]) ApplicationLauncher *launcher = new ApplicationLauncher(); launcher->setCurrent(QStringLiteral("launcher")); - HomescreenHandler* homescreenHandler = new HomescreenHandler(aglShell, launcher); - agl_shell_desktop_add_listener(shell_data.shell_desktop, &shell_desktop_listener, homescreenHandler); + HomescreenHandler* homescreenHandler = new HomescreenHandler(aglShell, launcher); + shell_data.homescreenHandler = homescreenHandler; QQmlApplicationEngine engine; QQmlContext *context = engine.rootContext(); -- 2.16.6 From d4f3ddfbad7a64937f00f13ba964e18d33effbb0 Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Thu, 29 Sep 2022 14:22:11 +0300 Subject: [PATCH 16/16] homescreen: Change from qmake to meson This change will basically make way for adding grpc/protobuf support into homescreen, which turns out it's a pain to do with either qmake or cmake. Eventually, we'll move all our demos to using meson, which have gained a lot of support for building and support different technologies to allow far more saner configurations to take place. Based heavily on the work done by Scott Murray in libqtappfw, in the applauncher module. Bug-AGL: SPEC-4584 Signed-off-by: Marius Vlad Suggested-by: Scott Murray Change-Id: Id64bf3d5b41912d32df7f78e94ab04d231bb0c83 --- homescreen/homescreen.pro | 60 -------------------- homescreen/meson.build | 107 +++++++++++++++++++++++++++++++++++ homescreen/src/hmi-debug.h | 1 - homescreen/src/homescreenhandler.cpp | 3 +- homescreen/src/main.cpp | 5 +- homescreen/src/shell.cpp | 5 +- homescreen/src/shell.h | 2 +- homescreen.pro => meson.build | 25 ++++++-- 8 files changed, 135 insertions(+), 73 deletions(-) delete mode 100644 homescreen/homescreen.pro create mode 100644 homescreen/meson.build rename homescreen.pro => meson.build (61%) diff --git a/homescreen/homescreen.pro b/homescreen/homescreen.pro deleted file mode 100644 index 16a01f6..0000000 --- a/homescreen/homescreen.pro +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH -# Copyright (c) 2017 TOYOTA MOTOR CORPORATION -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -TEMPLATE = app -TARGET = homescreen -QT = qml quick gui-private -CONFIG += c++11 link_pkgconfig wayland-scanner -PKGCONFIG += wayland-client -PKGCONFIG += qtappfw-weather qtappfw-network qtappfw-bt qtappfw-vehicle-signals qtappfw-applauncher - -SOURCES += \ - src/main.cpp \ - src/shell.cpp \ - src/statusbarmodel.cpp \ - src/statusbarserver.cpp \ - src/applicationlauncher.cpp \ - src/mastervolume.cpp \ - src/homescreenhandler.cpp - -HEADERS += \ - src/shell.h \ - src/constants.h \ - src/statusbarmodel.h \ - src/statusbarserver.h \ - src/applicationlauncher.h \ - src/mastervolume.h \ - src/homescreenhandler.h - -OTHER_FILES += \ - README.md - -RESOURCES += \ - qml/images/MediaPlayer/mediaplayer.qrc \ - qml/images/MediaMusic/mediamusic.qrc \ - qml/images/Weather/weather.qrc \ - qml/images/Shortcut/shortcut.qrc \ - qml/images/Status/status.qrc \ - qml/images/images.qrc \ - qml/qml.qrc - -AGL_SHELL_PATH = $$system(pkg-config --variable=pkgdatadir agl-compositor-0.0.20-protocols) -WAYLANDCLIENTSOURCES += $$AGL_SHELL_PATH/agl-shell.xml - -target.path = $${PREFIX}/usr/bin -target.files += $${OUT_PWD}/$${TARGET} -target.CONFIG = no_check_exist executable - -INSTALLS += target diff --git a/homescreen/meson.build b/homescreen/meson.build new file mode 100644 index 0000000..fc93d06 --- /dev/null +++ b/homescreen/meson.build @@ -0,0 +1,107 @@ +cpp = meson.get_compiler('cpp') +qt5_dep = dependency('qt5', modules: ['Qml', 'Quick', 'Gui']) +dep_wayland_client = dependency('wayland-client', version: '>= 1.20.0') +dep_qtappfw = [ + dependency('qtappfw-weather'), + dependency('qtappfw-network'), + dependency('qtappfw-bt'), + dependency('qtappfw-vehicle-signals'), + dependency('qtappfw-applauncher') +] + +qt_defines = [] +qpa_header_path = join_paths(qt5_dep.version(), 'QtGui') +qpa_header = join_paths(qpa_header_path, 'qpa/qplatformnativeinterface.h') +# we pass this QT_QPA_HEADER straight in the code as there's no easy +# way to pass the correct header +if cpp.has_header(qpa_header, dependencies : qt5_dep) + qt_defines += [ '-DQT_QPA_HEADER=<@0@>'.format(qpa_header) ] + message('Found QtGui QPA header in ' + qpa_header_path) +endif + +dep_scanner = dependency('wayland-scanner') +prog_scanner = find_program(dep_scanner.get_pkgconfig_variable('wayland_scanner')) +agl_compositor_dep = dependency('agl-compositor-0.0.20-protocols') +dir_agl_compositor_base = agl_compositor_dep.get_pkgconfig_variable('pkgdatadir') + +homescreen_dep = [ + qt5_dep, + dep_wayland_client, + dep_qtappfw, +] + +homescreen_resources = [ + 'qml/images/MediaPlayer/mediaplayer.qrc', + 'qml/images/MediaMusic/mediamusic.qrc', + 'qml/images/Weather/weather.qrc', + 'qml/images/Shortcut/shortcut.qrc', + 'qml/images/Status/status.qrc', + 'qml/images/images.qrc', + 'qml/qml.qrc' +] + +resource_files = qt5.compile_resources(sources: homescreen_resources) + +protocols = [ + [ 'agl-shell', 'agl-compositor' ], +] + +foreach proto: protocols + proto_name = proto[0] + if proto[1] == 'agl-compositor' + base_file = proto_name + xml_path = join_paths(dir_agl_compositor_base, '@0@.xml'.format(base_file)) + endif + + foreach output_type: [ 'client-header', 'server-header', 'private-code' ] + if output_type == 'client-header' + output_file = '@0@-client-protocol.h'.format(base_file) + elif output_type == 'server-header' + output_file = '@0@-server-protocol.h'.format(base_file) + else + output_file = '@0@-protocol.c'.format(base_file) + if dep_scanner.version().version_compare('< 1.14.91') + output_type = 'code' + endif + endif + + var_name = output_file.underscorify() + target = custom_target( + '@0@ @1@'.format(base_file, output_type), + command: [ prog_scanner, output_type, '@INPUT@', '@OUTPUT@' ], + input: xml_path, + output: output_file, + ) + message('protocol name is ' + var_name) + set_variable(var_name, target) + endforeach +endforeach + +homescreen_src_headers = [ + 'src/applicationlauncher.h', + 'src/mastervolume.h', + 'src/statusbarmodel.h', + 'src/statusbarserver.h', + 'src/homescreenhandler.h', + 'src/shell.h' +] + +moc_files = qt5.compile_moc(headers: homescreen_src_headers, + dependencies: qt5_dep) + +homescreen_src = [ + 'src/shell.cpp', + 'src/statusbarserver.cpp', + 'src/statusbarmodel.cpp', + 'src/applicationlauncher.cpp', + 'src/mastervolume.cpp', + 'src/homescreenhandler.cpp', + 'src/main.cpp', + agl_shell_client_protocol_h, + agl_shell_protocol_c +] + +executable('homescreen', homescreen_src, resource_files, moc_files, + cpp_args: qt_defines, + dependencies : homescreen_dep, + install: true) diff --git a/homescreen/src/hmi-debug.h b/homescreen/src/hmi-debug.h index 47ae1f7..ea9bae8 100644 --- a/homescreen/src/hmi-debug.h +++ b/homescreen/src/hmi-debug.h @@ -49,7 +49,6 @@ static void _HMI_LOG(enum LOG_LEVEL level, const char* file, const char* func, c struct timespec tp; uint32_t time; va_list args; - int ret; const int log_level = (getenv("USE_HMI_DEBUG") == NULL) ? LOG_LEVEL_ERROR : atoi(getenv("USE_HMI_DEBUG")); if(log_level < level) { diff --git a/homescreen/src/homescreenhandler.cpp b/homescreen/src/homescreenhandler.cpp index 920c054..2858ef4 100644 --- a/homescreen/src/homescreenhandler.cpp +++ b/homescreen/src/homescreenhandler.cpp @@ -11,7 +11,8 @@ #include "homescreenhandler.h" #include "hmi-debug.h" -#include +// defined by meson build file +#include QT_QPA_HEADER // LAUNCHER_APP_ID shouldn't be started by applaunchd as it is started as // a user session by systemd diff --git a/homescreen/src/main.cpp b/homescreen/src/main.cpp index 8c3391f..c910727 100644 --- a/homescreen/src/main.cpp +++ b/homescreen/src/main.cpp @@ -25,10 +25,11 @@ #include "homescreenhandler.h" #include "hmi-debug.h" -#include +// meson will define these +#include QT_QPA_HEADER #include -#include "wayland-agl-shell-client-protocol.h" +#include "agl-shell-client-protocol.h" #include "shell.h" #ifndef MIN diff --git a/homescreen/src/shell.cpp b/homescreen/src/shell.cpp index 1427b7c..ffb4439 100644 --- a/homescreen/src/shell.cpp +++ b/homescreen/src/shell.cpp @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Collabora Ltd. + * Copyright © 2019, 2022 Collabora Ltd. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -26,7 +26,8 @@ #include #include #include "shell.h" -#include +// defined by meson build file +#include QT_QPA_HEADER #include static struct wl_output * diff --git a/homescreen/src/shell.h b/homescreen/src/shell.h index 8bf0e9b..a6e3f7e 100644 --- a/homescreen/src/shell.h +++ b/homescreen/src/shell.h @@ -32,7 +32,7 @@ #include #include #include -#include "wayland-agl-shell-client-protocol.h" +#include "agl-shell-client-protocol.h" /* * Basic type to wrap the agl_shell wayland object into a QObject, so that it diff --git a/homescreen.pro b/meson.build similarity index 61% rename from homescreen.pro rename to meson.build index bf0d4bb..3d77b36 100644 --- a/homescreen.pro +++ b/meson.build @@ -1,4 +1,5 @@ -# Copyright (c) 2017 TOYOTA MOTOR CORPORATION +# +# Copyright ©, 2022 Collabora, Ltd. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -11,10 +12,22 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# -TEMPLATE = subdirs - -load(configure) +project ( + 'homescreen', + ['c', 'cpp'], + version : '1.0.0', + license : 'Apache-2.0', + meson_version : '>= 0.60.0', + default_options : + [ + 'warning_level=1', + 'buildtype=debugoptimized', + 'c_std=c17', + 'cpp_std=c++17' + ], +) -SUBDIRS = \ - homescreen +qt5 = import('qt5') +subdir('homescreen') -- 2.16.6