From cbd74648d063ff2b24f9a78db086a00aa8ae4484 Mon Sep 17 00:00:00 2001 From: Przemyslaw Brudny Date: Fri, 9 Apr 2021 17:27:57 +0200 Subject: [PATCH] [EGD-6494] Application Manager on action switch fix Application Manager switch on Action no longer causes to newly opened application main window switch but it calls declared action handler. --- module-apps/Application.cpp | 50 ++++++++++++++++--- module-apps/Application.hpp | 32 ++++++++---- .../ApplicationAlarmClock.cpp | 1 - .../ApplicationAntenna.cpp | 2 - .../ApplicationCalculator.cpp | 2 - .../application-call/ApplicationCall.cpp | 2 - .../ApplicationDesktop.cpp | 1 - .../ApplicationMeditation.cpp | 2 +- .../ApplicationMessages.cpp | 2 +- .../ApplicationMusicPlayer.cpp | 2 - .../application-notes/ApplicationNotes.cpp | 2 +- .../ApplicationOnBoarding.cpp | 1 - .../ApplicationSettings.cpp | 2 - .../ApplicationSettings.cpp | 2 - .../ApplicationSpecialInput.cpp | 2 +- module-apps/messages/AppMessage.hpp | 30 +++++------ module-apps/options/type/OptionContact.cpp | 1 + .../model/ApplicationManager.cpp | 17 +++++-- .../model/ApplicationHandle.hpp | 2 + 19 files changed, 97 insertions(+), 58 deletions(-) diff --git a/module-apps/Application.cpp b/module-apps/Application.cpp index 5b31a01b4145983116b376f01d54ac23ad9b9139..319fe9c295bad0efd169ba7693bcdef9e49f730f 100644 --- a/module-apps/Application.cpp +++ b/module-apps/Application.cpp @@ -2,10 +2,10 @@ // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "Application.hpp" -#include "Common.hpp" // for RefreshModes -#include "GuiTimer.hpp" // for GuiTimer -#include "Item.hpp" // for Item -#include "MessageType.hpp" // for MessageType +#include "Common.hpp" // for RefreshModes +#include "GuiTimer.hpp" // for GuiTimer +#include "Item.hpp" // for Item +#include "MessageType.hpp" // for MessageType #include "module-apps/popups/data/PopupRequestParams.hpp" #include "module-apps/popups/data/PhoneModeParams.hpp" #include "module-sys/Timers/TimerFactory.hpp" // for Timer @@ -373,7 +373,15 @@ namespace app try { const auto &actionHandler = receivers.at(action); auto &data = msg->getData(); - return actionHandler(std::move(data)); + + auto result = actionHandler(std::move(data)); + + if (windowsStack.isEmpty()) { + LOG_ERROR("OnAction application switch with no window provided. Fallback to default mainWindow."); + setActiveWindow(gui::name::window::main_window); + } + + return result; } catch (const std::out_of_range &) { LOG_ERROR("Application %s is not able to handle action #%d", GetName().c_str(), action); @@ -382,6 +390,20 @@ namespace app } sys::MessagePointer Application::handleApplicationSwitch(sys::Message *msgl) + { + auto *msg = static_cast(msgl); + + switch (msg->getApplicationStartupReason()) { + case StartupReason::Launch: + return handleApplicationSwitchLaunch(msgl); + case StartupReason::OnAction: + return handleApplicationSwitchOnAction(msgl); + } + + return sys::msgNotHandled(); + } + + sys::MessagePointer Application::handleApplicationSwitchLaunch(sys::Message *msgl) { auto *msg = static_cast(msgl); bool handled = false; @@ -428,6 +450,19 @@ namespace app return sys::msgNotHandled(); } + sys::MessagePointer Application::handleApplicationSwitchOnAction(sys::Message *msgl) + { + if ((state == State::ACTIVATING) || (state == State::INITIALIZING) || (state == State::ACTIVE_BACKGROUND)) { + setState(State::ACTIVE_FORGROUND); + app::manager::Controller::confirmSwitch(this); + return sys::msgHandled(); + } + else { + LOG_ERROR("Application already running - no startup on Action"); + return sys::msgNotHandled(); + } + } + sys::MessagePointer Application::handleSwitchWindow(sys::Message *msgl) { auto msg = static_cast(msgl); @@ -656,9 +691,10 @@ namespace app void Application::messageSwitchApplication(sys::Service *sender, std::string application, std::string window, - std::unique_ptr data) + std::unique_ptr data, + StartupReason startupReason) { - auto msg = std::make_shared(application, window, std::move(data)); + auto msg = std::make_shared(application, window, std::move(data), startupReason); sender->bus.sendUnicast(msg, application); } diff --git a/module-apps/Application.hpp b/module-apps/Application.hpp index 5b2217d285cc0429c571ec63063ac95a2df497ec..b20fe5147f46b9d645571986e9b2d2990e9d2367 100644 --- a/module-apps/Application.hpp +++ b/module-apps/Application.hpp @@ -8,9 +8,9 @@ #include "Audio/Profiles/Profile.hpp" // for Profile, Pro... #include "CallbackStorage.hpp" -#include "Service/Common.hpp" // for ReturnCodes -#include "Service/Message.hpp" // for MessagePointer -#include "Service/Service.hpp" // for Service +#include "Service/Common.hpp" // for ReturnCodes +#include "Service/Message.hpp" // for MessagePointer +#include "Service/Service.hpp" // for Service #include "Timers/TimerHandle.hpp" #include "SwitchData.hpp" // for SwitchData #include "SystemManager/SystemManager.hpp" // for SystemManager @@ -20,13 +20,13 @@ #include #include -#include // for list -#include // for allocator, map -#include // for make_shared -#include // for uint32_t -#include // for string -#include // for move, pair -#include // for vector +#include // for list +#include // for allocator, map +#include // for make_shared +#include // for uint32_t +#include // for string +#include // for move, pair +#include // for vector #include "TopBarManager.hpp" #include "popups/Popups.hpp" #include "WindowsFactory.hpp" @@ -77,6 +77,13 @@ namespace app Failure }; + enum class StartupReason + { + Launch, // Default startup causing application MainWindow to be added to stack. + OnAction, // Switch to application was caused by action. Enum is used to prevent called applications to + // switch to main window on application switch and allow declared handler to switch to desired window. + }; + struct StartInBackground { StartInBackground(bool _value) : value{_value} @@ -168,6 +175,8 @@ namespace app sys::MessagePointer handleMinuteUpdated(sys::Message *msgl); sys::MessagePointer handleAction(sys::Message *msgl); sys::MessagePointer handleApplicationSwitch(sys::Message *msgl); + sys::MessagePointer handleApplicationSwitchLaunch(sys::Message *msgl); + sys::MessagePointer handleApplicationSwitchOnAction(sys::Message *msgl); sys::MessagePointer handleSwitchWindow(sys::Message *msgl); sys::MessagePointer handleUpdateWindow(sys::Message *msgl); sys::MessagePointer handleAppClose(sys::Message *msgl); @@ -312,7 +321,8 @@ namespace app static void messageSwitchApplication(sys::Service *sender, std::string application, std::string window, - std::unique_ptr data); + std::unique_ptr data, + StartupReason startupReason); static void messageCloseApplication(sys::Service *sender, std::string application); static void messageRebuildApplication(sys::Service *sender, std::string application); static void messageApplicationLostFocus(sys::Service *sender, std::string application); diff --git a/module-apps/application-alarm-clock/ApplicationAlarmClock.cpp b/module-apps/application-alarm-clock/ApplicationAlarmClock.cpp index 85fbf8dc12e971fc522fc32aaf7736be9cf17375..baaceea7550f74682bae016e4ab724a0661da2a7 100644 --- a/module-apps/application-alarm-clock/ApplicationAlarmClock.cpp +++ b/module-apps/application-alarm-clock/ApplicationAlarmClock.cpp @@ -70,7 +70,6 @@ namespace app } createUserInterface(); - setActiveWindow(gui::name::window::main_window); return ret; } diff --git a/module-apps/application-antenna/ApplicationAntenna.cpp b/module-apps/application-antenna/ApplicationAntenna.cpp index b186946f40fda3abf7d897cfe39bdc068f2301a8..8e6e7d04b83d35976fd2e9d4ef71bd7976396c42 100644 --- a/module-apps/application-antenna/ApplicationAntenna.cpp +++ b/module-apps/application-antenna/ApplicationAntenna.cpp @@ -156,8 +156,6 @@ namespace app createUserInterface(); - setActiveWindow(gui::name::window::main_window); - CellularServiceAPI::GetAntenna(this, antenna); return ret; diff --git a/module-apps/application-calculator/ApplicationCalculator.cpp b/module-apps/application-calculator/ApplicationCalculator.cpp index 227b50cf36dfa82812b43c50efa08ddacda87182..94effe3701d99ac7ae0cd967b60bd920eb80f18a 100644 --- a/module-apps/application-calculator/ApplicationCalculator.cpp +++ b/module-apps/application-calculator/ApplicationCalculator.cpp @@ -28,8 +28,6 @@ namespace app createUserInterface(); - setActiveWindow(gui::name::window::main_window); - return ret; } diff --git a/module-apps/application-call/ApplicationCall.cpp b/module-apps/application-call/ApplicationCall.cpp index a363b80619a9a36c3d384e8d014df9625dc03632..d535e894a59a886ad9a934f52d9a99bac01c08e0 100644 --- a/module-apps/application-call/ApplicationCall.cpp +++ b/module-apps/application-call/ApplicationCall.cpp @@ -216,8 +216,6 @@ namespace app createUserInterface(); - setActiveWindow(gui::name::window::main_window); - return ret; } diff --git a/module-apps/application-desktop/ApplicationDesktop.cpp b/module-apps/application-desktop/ApplicationDesktop.cpp index 4e82015de603cd39b4f2dfc24f3de30d024fae13..13f5470896b7a14b56932909105daa425f40147f 100644 --- a/module-apps/application-desktop/ApplicationDesktop.cpp +++ b/module-apps/application-desktop/ApplicationDesktop.cpp @@ -390,7 +390,6 @@ namespace app requestUnreadThreadsCount(this); requestUnreadCallsCount(this); createUserInterface(); - setActiveWindow(gui::name::window::main_window); connect(sdesktop::UpdateOsMessage(), [&](sys::Message *msg) { auto *updateMsg = dynamic_cast(msg); diff --git a/module-apps/application-meditation/ApplicationMeditation.cpp b/module-apps/application-meditation/ApplicationMeditation.cpp index b053bbdb17d55764aaa16d112cc8766c9342058d..6ad2e6da53f7a14d025a42bce5c7b2dc9cd216e9 100644 --- a/module-apps/application-meditation/ApplicationMeditation.cpp +++ b/module-apps/application-meditation/ApplicationMeditation.cpp @@ -24,7 +24,7 @@ namespace app return ret; createUserInterface(); - setActiveWindow(gui::name::window::main_window); + return ret; } diff --git a/module-apps/application-messages/ApplicationMessages.cpp b/module-apps/application-messages/ApplicationMessages.cpp index 5e7ae13a5c2d6eee2364660fe548800d2a404539..92ebddb87cd4fa35fffec216ba2a39cab48382d7 100644 --- a/module-apps/application-messages/ApplicationMessages.cpp +++ b/module-apps/application-messages/ApplicationMessages.cpp @@ -126,7 +126,7 @@ namespace app } createUserInterface(); - setActiveWindow(gui::name::window::main_window); + return ret; } diff --git a/module-apps/application-music-player/ApplicationMusicPlayer.cpp b/module-apps/application-music-player/ApplicationMusicPlayer.cpp index 4597dab9c5e82b1781017d455a7afa0f34aa387c..7a705e800cc31449663b32b363069efb55f49f66 100644 --- a/module-apps/application-music-player/ApplicationMusicPlayer.cpp +++ b/module-apps/application-music-player/ApplicationMusicPlayer.cpp @@ -51,8 +51,6 @@ namespace app createUserInterface(); - setActiveWindow(gui::name::window::main_window); - return ret; } diff --git a/module-apps/application-notes/ApplicationNotes.cpp b/module-apps/application-notes/ApplicationNotes.cpp index c17a701941ded4c20b3471c9714b60f1432a4f93..436da235000572c515367dc1f1e44fcb5ac180a9 100644 --- a/module-apps/application-notes/ApplicationNotes.cpp +++ b/module-apps/application-notes/ApplicationNotes.cpp @@ -74,7 +74,7 @@ namespace app } createUserInterface(); - setActiveWindow(gui::name::window::main_window); + return ret; } diff --git a/module-apps/application-onboarding/ApplicationOnBoarding.cpp b/module-apps/application-onboarding/ApplicationOnBoarding.cpp index f2fe1dee23463f7b72d5e620aa70ed0c603976f9..a5473583a11d558bf21561fd9ea08cc9e0b4d653 100644 --- a/module-apps/application-onboarding/ApplicationOnBoarding.cpp +++ b/module-apps/application-onboarding/ApplicationOnBoarding.cpp @@ -64,7 +64,6 @@ namespace app } createUserInterface(); - setActiveWindow(gui::name::window::main_window); connect(typeid(manager::GetCurrentDisplayLanguageResponse), [&](sys::Message *msg) { if (gui::window::name::onBoarding_languages == getCurrentWindow()->getName()) { diff --git a/module-apps/application-settings-new/ApplicationSettings.cpp b/module-apps/application-settings-new/ApplicationSettings.cpp index 10008dd8afacb7c7deeae9f7348002c604552690..e3bc8b0032a0b222fb89c704770cf9335004c815 100644 --- a/module-apps/application-settings-new/ApplicationSettings.cpp +++ b/module-apps/application-settings-new/ApplicationSettings.cpp @@ -329,8 +329,6 @@ namespace app createUserInterface(); - setActiveWindow(gui::name::window::main_window); - settings->registerValueChange(settings::operators_on, [this](const std::string &value) { operatorOnChanged(value); }); settings->registerValueChange( diff --git a/module-apps/application-settings/ApplicationSettings.cpp b/module-apps/application-settings/ApplicationSettings.cpp index 604027ed0a5522a7ae4093aec80874f74e1c3832..cc6461f0c109606f914b87344f647e2fc3f9e92e 100644 --- a/module-apps/application-settings/ApplicationSettings.cpp +++ b/module-apps/application-settings/ApplicationSettings.cpp @@ -108,8 +108,6 @@ namespace app createUserInterface(); - setActiveWindow(gui::name::window::main_window); - return ret; } diff --git a/module-apps/application-special-input/ApplicationSpecialInput.cpp b/module-apps/application-special-input/ApplicationSpecialInput.cpp index 0dbddacb71908286f8a4981b753d8583aa5fb150..5c643ab769d04251d5e2970cc4b69b59b24710d2 100644 --- a/module-apps/application-special-input/ApplicationSpecialInput.cpp +++ b/module-apps/application-special-input/ApplicationSpecialInput.cpp @@ -47,7 +47,7 @@ sys::ReturnCodes ApplicationSpecialInput::InitHandler() LOG_ERROR("Can't initialize ApplicationSpecialInput"); } createUserInterface(); - setActiveWindow(gui::name::window::main_window); + return ret; } diff --git a/module-apps/messages/AppMessage.hpp b/module-apps/messages/AppMessage.hpp index 5e99f6974600060078b8214ef8ce81137f41b636..384bc7b1cd95e87d9c37b0806759878260c8408b 100644 --- a/module-apps/messages/AppMessage.hpp +++ b/module-apps/messages/AppMessage.hpp @@ -56,42 +56,36 @@ namespace app std::string targetWindow; // optional data for the target window. std::unique_ptr data; - // name of the application to which switch should be performed after finishing tasks in target application and - // window. - std::string returnApplication; - // name of the window to which switch should be performed after finishing tasks in target application and - // window. - std::string returnWindow; + + StartupReason startupReason = StartupReason::Launch; public: AppSwitchMessage(const std::string &targetApplication, const std::string &targetWindow, std::unique_ptr data, - const std::string &returnApplication = "", - const std::string &returnWindow = "") - : AppMessage(MessageType::AppSwitch), targetApplication{targetApplication}, targetWindow{targetWindow}, - data{std::move(data)}, returnApplication{returnApplication}, returnWindow{returnWindow} {}; + StartupReason startupReason) + : AppMessage(MessageType::AppSwitch), targetApplication{targetApplication}, + targetWindow{targetWindow}, data{std::move(data)}, startupReason{startupReason} {}; virtual ~AppSwitchMessage(){}; - [[nodiscard]] std::string getTargetWindowName() const + [[nodiscard]] std::string getTargetWindowName() const noexcept { return targetWindow; }; - [[nodiscard]] std::string getReturnWindowName() const - { - return returnWindow; - }; + [[nodiscard]] std::unique_ptr &getData() { return data; }; - [[nodiscard]] std::string getTargetApplicationName() const + + [[nodiscard]] std::string getTargetApplicationName() const noexcept { return targetApplication; }; - [[nodiscard]] std::string getReturnApplicationName() const + + [[nodiscard]] StartupReason getApplicationStartupReason() const noexcept { - return returnApplication; + return startupReason; }; }; diff --git a/module-apps/options/type/OptionContact.cpp b/module-apps/options/type/OptionContact.cpp index 4ccc6ff283833db60853167b51ca5a009c600d58..feec4ae8bd4fca9daeaae43201e26e8de2c0fb59 100644 --- a/module-apps/options/type/OptionContact.cpp +++ b/module-apps/options/type/OptionContact.cpp @@ -53,6 +53,7 @@ namespace gui::option app::manager::OnSwitchBehaviour::RunInBackground); } case ContactOperation::Details: { + data->ignoreCurrentWindowOnStack = true; return app::manager::Controller::sendAction(app, app::manager::actions::ShowContactDetails, std::move(data), diff --git a/module-services/service-appmgr/model/ApplicationManager.cpp b/module-services/service-appmgr/model/ApplicationManager.cpp index 9bf3a3dbbf69afa86d3dedd50279c59ed894faeb..3449171fa440aa4b0ccc1a736787085078d377b5 100644 --- a/module-services/service-appmgr/model/ApplicationManager.cpp +++ b/module-services/service-appmgr/model/ApplicationManager.cpp @@ -417,7 +417,8 @@ namespace app::manager if (app.state() == ApplicationHandle::State::ACTIVE_BACKGROUND) { LOG_INFO("Switching focus to application [%s] (window [%s])", app.name().c_str(), app.switchWindow.c_str()); setState(State::AwaitingFocusConfirmation); - app::Application::messageSwitchApplication(this, app.name(), app.switchWindow, std::move(app.switchData)); + app::Application::messageSwitchApplication( + this, app.name(), app.switchWindow, std::move(app.switchData), StartupReason::Launch); } else { LOG_INFO("Starting application %s", app.name().c_str()); @@ -496,7 +497,7 @@ namespace app::manager if (app->name() == currentlyFocusedApp->name()) { // Switch window only. app::Application::messageSwitchApplication( - this, app->name(), app->switchWindow, std::move(app->switchData)); + this, app->name(), app->switchWindow, std::move(app->switchData), StartupReason::Launch); return false; } @@ -585,6 +586,7 @@ namespace app::manager return ActionProcessStatus::Dropped; } + targetApp->startupReason = StartupReason::Launch; action.setTargetApplication(targetApp->name()); SwitchRequest switchRequest(ServiceName, targetApp->name(), gui::name::window::main_window, nullptr); return handleSwitchApplication(&switchRequest) ? ActionProcessStatus::Accepted : ActionProcessStatus::Dropped; @@ -632,6 +634,10 @@ namespace app::manager } const auto targetApp = actionHandlers.front(); + + // Inform that target app switch is caused by Action + targetApp->startupReason = StartupReason::OnAction; + action.setTargetApplication(targetApp->name()); auto &actionParams = action.params; if (targetApp->state() != ApplicationHandle::State::ACTIVE_FORGROUND) { @@ -725,7 +731,9 @@ namespace app::manager LOG_INFO("Switch application to %s", app.name().c_str()); app.setState(ApplicationHandle::State::ACTIVATING); setState(State::AwaitingFocusConfirmation); - app::Application::messageSwitchApplication(this, app.name(), app.switchWindow, std::move(app.switchData)); + + app::Application::messageSwitchApplication( + this, app.name(), app.switchWindow, std::move(app.switchData), launchingApp->startupReason); } } @@ -877,6 +885,9 @@ namespace app::manager void ApplicationManager::onLaunchFinished(ApplicationHandle &app) { + // reset startupReason to default Launch + app.startupReason = StartupReason::Launch; + if (!actionsRegistry.hasPendingAction()) { return; } diff --git a/module-services/service-appmgr/service-appmgr/model/ApplicationHandle.hpp b/module-services/service-appmgr/service-appmgr/model/ApplicationHandle.hpp index 4a30aa5eb41054ffd780d35da18b16b9ddece038..6cb997c8863f52c902781d6176d1089a29d750bc 100644 --- a/module-services/service-appmgr/service-appmgr/model/ApplicationHandle.hpp +++ b/module-services/service-appmgr/service-appmgr/model/ApplicationHandle.hpp @@ -44,6 +44,8 @@ namespace app::manager // is closeable and there is incoming call. This flag is also used when closeable // application is on front and there is a timeout to block the application. + StartupReason startupReason = StartupReason::Launch; // Informs application about startup reason. + private: auto getManifest() const -> const ApplicationManifest &; };