M module-apps/Application.cpp => module-apps/Application.cpp +43 -7
@@ 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);
@@ 383,6 391,20 @@ namespace app
sys::MessagePointer Application::handleApplicationSwitch(sys::Message *msgl)
{
+ auto *msg = static_cast<AppSwitchMessage *>(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<AppSwitchMessage *>(msgl);
bool handled = false;
LOG_DEBUG("AppSwitch: %s", msg->getTargetApplicationName().c_str());
@@ 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<AppSwitchWindowMessage *>(msgl);
@@ 656,9 691,10 @@ namespace app
void Application::messageSwitchApplication(sys::Service *sender,
std::string application,
std::string window,
- std::unique_ptr<gui::SwitchData> data)
+ std::unique_ptr<gui::SwitchData> data,
+ StartupReason startupReason)
{
- auto msg = std::make_shared<AppSwitchMessage>(application, window, std::move(data));
+ auto msg = std::make_shared<AppSwitchMessage>(application, window, std::move(data), startupReason);
sender->bus.sendUnicast(msg, application);
}
M module-apps/Application.hpp => module-apps/Application.hpp +21 -11
@@ 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 <PhoneModes/Observer.hpp>
#include <service-appmgr/ApplicationManifest.hpp>
-#include <list> // for list
-#include <map> // for allocator, map
-#include <memory> // for make_shared
-#include <stdint.h> // for uint32_t
-#include <string> // for string
-#include <utility> // for move, pair
-#include <vector> // for vector
+#include <list> // for list
+#include <map> // for allocator, map
+#include <memory> // for make_shared
+#include <stdint.h> // for uint32_t
+#include <string> // for string
+#include <utility> // for move, pair
+#include <vector> // 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<gui::SwitchData> data);
+ std::unique_ptr<gui::SwitchData> 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);
M module-apps/application-alarm-clock/ApplicationAlarmClock.cpp => module-apps/application-alarm-clock/ApplicationAlarmClock.cpp +0 -1
@@ 70,7 70,6 @@ namespace app
}
createUserInterface();
- setActiveWindow(gui::name::window::main_window);
return ret;
}
M module-apps/application-antenna/ApplicationAntenna.cpp => module-apps/application-antenna/ApplicationAntenna.cpp +0 -2
@@ 156,8 156,6 @@ namespace app
createUserInterface();
- setActiveWindow(gui::name::window::main_window);
-
CellularServiceAPI::GetAntenna(this, antenna);
return ret;
M module-apps/application-calculator/ApplicationCalculator.cpp => module-apps/application-calculator/ApplicationCalculator.cpp +0 -2
@@ 28,8 28,6 @@ namespace app
createUserInterface();
- setActiveWindow(gui::name::window::main_window);
-
return ret;
}
M module-apps/application-call/ApplicationCall.cpp => module-apps/application-call/ApplicationCall.cpp +0 -2
@@ 216,8 216,6 @@ namespace app
createUserInterface();
- setActiveWindow(gui::name::window::main_window);
-
return ret;
}
M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +0 -1
@@ 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<sdesktop::UpdateOsMessage *>(msg);
M module-apps/application-meditation/ApplicationMeditation.cpp => module-apps/application-meditation/ApplicationMeditation.cpp +1 -1
@@ 24,7 24,7 @@ namespace app
return ret;
createUserInterface();
- setActiveWindow(gui::name::window::main_window);
+
return ret;
}
M module-apps/application-messages/ApplicationMessages.cpp => module-apps/application-messages/ApplicationMessages.cpp +1 -1
@@ 126,7 126,7 @@ namespace app
}
createUserInterface();
- setActiveWindow(gui::name::window::main_window);
+
return ret;
}
M module-apps/application-music-player/ApplicationMusicPlayer.cpp => module-apps/application-music-player/ApplicationMusicPlayer.cpp +0 -2
@@ 51,8 51,6 @@ namespace app
createUserInterface();
- setActiveWindow(gui::name::window::main_window);
-
return ret;
}
M module-apps/application-notes/ApplicationNotes.cpp => module-apps/application-notes/ApplicationNotes.cpp +1 -1
@@ 74,7 74,7 @@ namespace app
}
createUserInterface();
- setActiveWindow(gui::name::window::main_window);
+
return ret;
}
M module-apps/application-onboarding/ApplicationOnBoarding.cpp => module-apps/application-onboarding/ApplicationOnBoarding.cpp +0 -1
@@ 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()) {
M module-apps/application-settings-new/ApplicationSettings.cpp => module-apps/application-settings-new/ApplicationSettings.cpp +0 -2
@@ 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(
M module-apps/application-settings/ApplicationSettings.cpp => module-apps/application-settings/ApplicationSettings.cpp +0 -2
@@ 108,8 108,6 @@ namespace app
createUserInterface();
- setActiveWindow(gui::name::window::main_window);
-
return ret;
}
M module-apps/application-special-input/ApplicationSpecialInput.cpp => module-apps/application-special-input/ApplicationSpecialInput.cpp +1 -1
@@ 47,7 47,7 @@ sys::ReturnCodes ApplicationSpecialInput::InitHandler()
LOG_ERROR("Can't initialize ApplicationSpecialInput");
}
createUserInterface();
- setActiveWindow(gui::name::window::main_window);
+
return ret;
}
M module-apps/messages/AppMessage.hpp => module-apps/messages/AppMessage.hpp +12 -18
@@ 56,42 56,36 @@ namespace app
std::string targetWindow;
// optional data for the target window.
std::unique_ptr<gui::SwitchData> 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<gui::SwitchData> 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<gui::SwitchData> &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;
};
};
M module-apps/options/type/OptionContact.cpp => module-apps/options/type/OptionContact.cpp +1 -0
@@ 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),
M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +14 -3
@@ 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;
}
M module-services/service-appmgr/service-appmgr/model/ApplicationHandle.hpp => module-services/service-appmgr/service-appmgr/model/ApplicationHandle.hpp +2 -0
@@ 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 &;
};