diff --git a/module-apps/Application.cpp b/module-apps/Application.cpp index 5b31a01b4..319fe9c29 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 5b2217d28..b20fe5147 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 85fbf8dc1..baaceea75 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 b186946f4..8e6e7d04b 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 227b50cf3..94effe370 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 a363b8061..d535e894a 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 4e82015de..13f547089 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 b053bbdb1..6ad2e6da5 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 5e7ae13a5..92ebddb87 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 4597dab9c..7a705e800 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 c17a70194..436da2350 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 f2fe1dee2..a5473583a 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 10008dd8a..e3bc8b003 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 604027ed0..cc6461f0c 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 0dbddacb7..5c643ab76 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 5e99f6974..384bc7b1c 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 4ccc6ff28..feec4ae8b 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 9bf3a3dbb..3449171fa 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 4a30aa5eb..6cb997c88 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 &; };