~aleteoryx/muditaos

cbd74648d063ff2b24f9a78db086a00aa8ae4484 — Przemyslaw Brudny 5 years ago ce2dbe9
[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.
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 &;
    };