Merge "Direct Rendering" into devel/master
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Thu, 7 Jul 2022 09:22:42 +0000 (09:22 +0000)
committerGerrit Code Review <gerrit@review>
Thu, 7 Jul 2022 09:22:42 +0000 (09:22 +0000)
19 files changed:
dali/devel-api/adaptor-framework/application-devel.cpp
dali/devel-api/adaptor-framework/native-image-source-queue.h
dali/internal/adaptor/android/framework-android.cpp
dali/internal/adaptor/androidjni/framework-androidjni.cpp
dali/internal/adaptor/common/application-impl.cpp
dali/internal/adaptor/common/application-impl.h
dali/internal/adaptor/common/framework.h
dali/internal/adaptor/macos/framework-mac.mm
dali/internal/adaptor/tizen-wayland/component-application-impl.cpp
dali/internal/adaptor/tizen-wayland/framework-tizen.cpp
dali/internal/adaptor/tizen-wayland/tizen-wearable/watch-application-impl.cpp
dali/internal/adaptor/ubuntu/framework-ubuntu.cpp
dali/internal/adaptor/windows/framework-win.cpp
dali/internal/system/common/environment-variables.h
dali/internal/system/common/widget-application-impl.cpp
dali/internal/window-system/tizen-wayland/ecore-wl/window-base-ecore-wl.cpp
dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.cpp
dali/public-api/adaptor-framework/application.cpp
dali/public-api/adaptor-framework/application.h

index 533a68c..8ce55e2 100644 (file)
@@ -48,7 +48,7 @@ Application New(int* argc, char** argv[], const std::string& stylesheet, Applica
     internal->StoreWindowPositionSize(positionSize);
   } else
   {
-    internal = Internal::Adaptor::Application::New(argc, argv, stylesheet, windowMode, positionSize, Internal::Adaptor::Framework::NORMAL, type);
+    internal = Internal::Adaptor::Application::New(argc, argv, stylesheet, windowMode, positionSize, Internal::Adaptor::Framework::NORMAL, type, false);
   }
   return Application(internal.Get());
 }
index 01ca473..cba01ca 100644 (file)
@@ -65,12 +65,12 @@ public:
     */
   enum class ColorFormat
   {
-    RGB888,   /// 8 red bits, 8 green bits, 8 blue bits
-    RGBA8888, /// 8 red bits, 8 green bits, 8 blue bits, alpha 8 bits
-    RGBX8888, /// 8 red bits, 8 green bits, 8 blue bits, and 8 ignored bits
-    BGR888,   /// 8 blue bits, 8 green bits, 8 red bits
-    BGRA8888, /// 8 blue bits, 8 green bits, 8 red bits, alpha 8 bits
-    BGRX8888, /// 8 blue bits, 8 green bits, 8 red bits, and 8 ignored bits
+    BGR888   = 0, /// 8 blue bits, 8 green bits, 8 red bits
+    BGRA8888 = 1, /// 8 blue bits, 8 green bits, 8 red bits, alpha 8 bits
+    BGRX8888 = 2, /// 8 blue bits, 8 green bits, 8 red bits, and 8 ignored bits
+    RGB888   = 3, /// 8 red bits, 8 green bits, 8 blue bits
+    RGBA8888 = 4, /// 8 red bits, 8 green bits, 8 blue bits, alpha 8 bits
+    RGBX8888 = 5, /// 8 red bits, 8 green bits, 8 blue bits, and 8 ignored bits
   };
 
   /**
index e01ff71..8151ba8 100644 (file)
@@ -488,8 +488,9 @@ struct Framework::Impl
   }
 };
 
-Framework::Framework(Framework::Observer& observer, int* argc, char*** argv, Type type)
+Framework::Framework(Framework::Observer& observer, Framework::TaskObserver& taskObserver, int* argc, char*** argv, Type type, bool useUiThread)
 : mObserver(observer),
+  mTaskObserver(taskObserver),
   mInitialised(false),
   mPaused(false),
   mRunning(false),
index caa35be..649d281 100644 (file)
@@ -84,8 +84,9 @@ struct Framework::Impl
   std::string      mRegion;
 };
 
-Framework::Framework(Framework::Observer& observer, int* argc, char*** argv, Type type)
+Framework::Framework(Framework::Observer& observer, Framework::TaskObserver& taskObserver, int* argc, char*** argv, Type type, bool useUiThread)
 : mObserver(observer),
+  mTaskObserver(taskObserver),
   mInitialised(false),
   mPaused(false),
   mRunning(false),
index 97a23e0..13a3fbe 100644 (file)
@@ -26,6 +26,7 @@
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/accessibility-bridge.h>
+#include <dali/devel-api/adaptor-framework/environment-variable.h>
 #include <dali/devel-api/adaptor-framework/style-monitor.h>
 #include <dali/devel-api/atspi-interfaces/accessible.h>
 #include <dali/devel-api/text-abstraction/font-client.h>
@@ -33,6 +34,7 @@
 #include <dali/internal/adaptor/common/framework.h>
 #include <dali/internal/adaptor/common/lifecycle-controller-impl.h>
 #include <dali/internal/system/common/command-line-options.h>
+#include <dali/internal/system/common/environment-variables.h>
 #include <dali/internal/window-system/common/render-surface-factory.h>
 #include <dali/internal/window-system/common/window-impl.h>
 #include <dali/internal/window-system/common/window-render-surface.h>
@@ -68,9 +70,10 @@ ApplicationPtr Application::New(
   Dali::Application::WINDOW_MODE windowMode,
   const PositionSize&            positionSize,
   Framework::Type                applicationType,
-  WindowType                     type)
+  WindowType                     type,
+  bool                           useUiThread)
 {
-  ApplicationPtr application(new Application(argc, argv, stylesheet, windowMode, positionSize, applicationType, type));
+  ApplicationPtr application(new Application(argc, argv, stylesheet, windowMode, positionSize, applicationType, type, useUiThread));
   return application;
 }
 
@@ -80,13 +83,13 @@ void Application::PreInitialize(int* argc, char** argv[])
   {
     Dali::TextAbstraction::FontClientPreInitialize();
 
-    gPreInitializedApplication = new Application(argc, argv, "", Dali::Application::OPAQUE, PositionSize(), Framework::NORMAL, WindowType::NORMAL);
+    gPreInitializedApplication = new Application(argc, argv, "", Dali::Application::OPAQUE, PositionSize(), Framework::NORMAL, WindowType::NORMAL, false);
     gPreInitializedApplication->CreateWindow(); // Only create window
     gPreInitializedApplication->mLaunchpadState = Launchpad::PRE_INITIALIZED;
   }
 }
 
-Application::Application(int* argc, char** argv[], const std::string& stylesheet, Dali::Application::WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType, WindowType type)
+Application::Application(int* argc, char** argv[], const std::string& stylesheet, Dali::Application::WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType, WindowType type, bool useUiThread)
 : mInitSignal(),
   mTerminateSignal(),
   mPauseSignal(),
@@ -108,6 +111,7 @@ Application::Application(int* argc, char** argv[], const std::string& stylesheet
   mWindowPositionSize(positionSize),
   mLaunchpadState(Launchpad::NONE),
   mDefaultWindowType(type),
+  mUseUiThread(useUiThread),
   mSlotDelegate(this)
 {
   // Get mName from environment options
@@ -118,8 +122,14 @@ Application::Application(int* argc, char** argv[], const std::string& stylesheet
     mMainWindowName = (*argv)[0];
   }
 
+  const char* uiThreadEnabled = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_ENABLE_UI_THREAD);
+  if(uiThreadEnabled && std::atoi(uiThreadEnabled) != 0)
+  {
+    mUseUiThread = true;
+  }
+
   mCommandLineOptions = new CommandLineOptions(argc, argv);
-  mFramework          = new Framework(*this, argc, argv, applicationType);
+  mFramework          = new Framework(*this, *this, argc, argv, applicationType, mUseUiThread);
   mUseRemoteSurface   = (applicationType == Framework::WATCH);
 }
 
@@ -169,7 +179,7 @@ void Application::ChangePreInitializedWindowSize()
   }
   else if(screenWidth != mWindowPositionSize.width || screenHeight != mWindowPositionSize.height)
   {
-    //Some apps can receive screen size differently after launching by specifying size in manifest.
+    // Some apps can receive screen size differently after launching by specifying size in manifest.
     mWindowPositionSize.width  = screenWidth;
     mWindowPositionSize.height = screenHeight;
     mMainWindow.SetSize(Dali::Window::WindowSize(mWindowPositionSize.width, mWindowPositionSize.height));
@@ -397,6 +407,48 @@ void Application::OnSurfaceDestroyed(Any surface)
 {
 }
 
+void Application::OnTaskInit()
+{
+  Dali::Application application(this);
+  mTaskInitSignal.Emit(application);
+}
+
+void Application::OnTaskTerminate()
+{
+  Dali::Application application(this);
+  mTaskTerminateSignal.Emit(application);
+}
+
+void Application::OnTaskAppControl(void* data)
+{
+  Dali::Application application(this);
+  mTaskAppControlSignal.Emit(application, data);
+}
+
+void Application::OnTaskLanguageChanged()
+{
+  Dali::Application application(this);
+  mTaskLanguageChangedSignal.Emit(application);
+}
+
+void Application::OnTaskRegionChanged()
+{
+  Dali::Application application(this);
+  mTaskRegionChangedSignal.Emit(application);
+}
+
+void Application::OnTaskBatteryLow(Dali::DeviceStatus::Battery::Status status)
+{
+  Dali::Application application(this);
+  mTaskLowBatterySignal.Emit(status);
+}
+
+void Application::OnTaskMemoryLow(Dali::DeviceStatus::Memory::Status status)
+{
+  Dali::Application application(this);
+  mTaskLowMemorySignal.Emit(status);
+}
+
 bool Application::AddIdle(CallbackBase* callback, bool hasReturnValue)
 {
   return mAdaptor->AddIdle(callback, hasReturnValue);
index ed03bfa..7a1f603 100644 (file)
@@ -64,7 +64,7 @@ typedef IntrusivePtr<Application> ApplicationPtr;
 /**
  * Implementation of the Application class.
  */
-class Application : public BaseObject, public Framework::Observer
+class Application : public BaseObject, public Framework::Observer, public Framework::TaskObserver
 {
 public:
   typedef Dali::Application::LowBatterySignalType LowBatterySignalType;
@@ -82,8 +82,9 @@ public:
    * @param[in]  positionSize      A position and a size of the window
    * @param[in]  applicationType   A member of Dali::Framework::Type
    * @param[in]  type              It is window type for default window.
+   * @param[in]  useUiThread       True if the application would create a UI thread
    */
-  static ApplicationPtr New(int* argc, char** argv[], const std::string& stylesheet, WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType, WindowType type);
+  static ApplicationPtr New(int* argc, char** argv[], const std::string& stylesheet, WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType, WindowType type, bool useUiThread);
 
   /**
    * @copydoc Dali::DevelApplication::PreInitialize()
@@ -180,9 +181,9 @@ public: // From Framework::Observer
   void OnResume() override;
 
   /**
-  * Called when the framework received AppControlSignal.
-  * @param[in] The bundle data of AppControl event.
-  */
+   * Called when the framework received AppControlSignal.
+   * @param[in] The bundle data of AppControl event.
+   */
   void OnAppControl(void* data) override;
 
   /**
@@ -196,18 +197,18 @@ public: // From Framework::Observer
   void OnLanguageChanged() override;
 
   /**
-  * Called when the framework informs the application that the region of the device has changed.
-  */
+   * Called when the framework informs the application that the region of the device has changed.
+   */
   void OnRegionChanged() override;
 
   /**
-  * Called when the framework informs the application that the battery level of the device is low.
-  */
+   * Called when the framework informs the application that the battery level of the device is low.
+   */
   void OnBatteryLow(Dali::DeviceStatus::Battery::Status status) override;
 
   /**
-  * Called when the framework informs the application that the memory level of the device is low.
-  */
+   * Called when the framework informs the application that the memory level of the device is low.
+   */
   void OnMemoryLow(Dali::DeviceStatus::Memory::Status status) override;
 
   /**
@@ -220,6 +221,43 @@ public: // From Framework::Observer
    */
   void OnSurfaceDestroyed(Any newSurface) override;
 
+public: // From Framework::TaskObserver
+  /**
+   * Called when the framework is initialised.
+   */
+  void OnTaskInit() override;
+
+  /**
+   * Called when the framework is terminated.
+   */
+  void OnTaskTerminate() override;
+
+  /**
+   * Called when the framework received AppControlSignal.
+   * @param[in] The bundle data of AppControl event.
+   */
+  void OnTaskAppControl(void* data) override;
+
+  /**
+   * Called when the framework informs the application that the language of the device has changed.
+   */
+  void OnTaskLanguageChanged() override;
+
+  /**
+   * Called when the framework informs the application that the region of the device has changed.
+   */
+  void OnTaskRegionChanged() override;
+
+  /**
+   * Called when the framework informs the application that the battery level of the device is low.
+   */
+  void OnTaskBatteryLow(Dali::DeviceStatus::Battery::Status status) override;
+
+  /**
+   * Called when the framework informs the application that the memory level of the device is low.
+   */
+  void OnTaskMemoryLow(Dali::DeviceStatus::Memory::Status status) override;
+
 public:
   /**
    * Sets a user defined theme file.
@@ -285,8 +323,8 @@ public: // Signals
   }
 
   /**
-  * @copydoc Dali::Application::AppControlSignal()
-  */
+   * @copydoc Dali::Application::AppControlSignal()
+   */
   Dali::Application::AppControlSignalType& AppControlSignal()
   {
     return mAppControlSignal;
@@ -301,29 +339,85 @@ public: // Signals
   }
 
   /**
-  * @copydoc Dali::Application::RegionChangedSignal()
-  */
+   * @copydoc Dali::Application::RegionChangedSignal()
+   */
   Dali::Application::AppSignalType& RegionChangedSignal()
   {
     return mRegionChangedSignal;
   }
 
   /**
-  * @copydoc Dali::Application::LowBatterySignal()
-  */
+   * @copydoc Dali::Application::LowBatterySignal()
+   */
   Dali::Application::LowBatterySignalType& LowBatterySignal()
   {
     return mLowBatterySignal;
   }
 
   /**
-  * @copydoc Dali::Application:::LowMemorySignal()
-  */
+   * @copydoc Dali::Application:::LowMemorySignal()
+   */
   Dali::Application::LowMemorySignalType& LowMemorySignal()
   {
     return mLowMemorySignal;
   }
 
+  /**
+   * @copydoc Dali::Application::TaskInitSignal()
+   */
+  Dali::Application::AppSignalType& TaskInitSignal()
+  {
+    return mTaskInitSignal;
+  }
+
+  /**
+   * @copydoc Dali::Application::TaskTerminateSignal()
+   */
+  Dali::Application::AppSignalType& TaskTerminateSignal()
+  {
+    return mTaskTerminateSignal;
+  }
+
+  /**
+   * @copydoc Dali::Application::TaskAppControlSignal()
+   */
+  Dali::Application::AppControlSignalType& TaskAppControlSignal()
+  {
+    return mTaskAppControlSignal;
+  }
+
+  /**
+   * @copydoc Dali::Application::TaskLanguageChangedSignal()
+   */
+  Dali::Application::AppSignalType& TaskLanguageChangedSignal()
+  {
+    return mTaskLanguageChangedSignal;
+  }
+
+  /**
+   * @copydoc Dali::Application::TaskRegionChangedSignal()
+   */
+  Dali::Application::AppSignalType& TaskRegionChangedSignal()
+  {
+    return mTaskRegionChangedSignal;
+  }
+
+  /**
+   * @copydoc Dali::Application::TaskLowBatterySignal()
+   */
+  Dali::Application::LowBatterySignalType& TaskLowBatterySignal()
+  {
+    return mTaskLowBatterySignal;
+  }
+
+  /**
+   * @copydoc Dali::Application::TaskLowMemorySignal()
+   */
+  Dali::Application::LowMemorySignalType& TaskLowMemorySignal()
+  {
+    return mTaskLowMemorySignal;
+  }
+
 protected:
   /**
    * Private Constructor
@@ -334,8 +428,9 @@ protected:
    * @param[in]  positionSize       A position and a size of the window
    * @param[in]  applicationType    A member of Dali::Framework::Type
    * @param[in]  type               The default window's type.
+   * @param[in]  useUiThread         True if the application would create UI thread
    */
-  Application(int* argc, char** argv[], const std::string& stylesheet, WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType, WindowType type);
+  Application(int* argc, char** argv[], const std::string& stylesheet, WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType, WindowType type, bool useUiThread);
 
   /**
    * Destructor
@@ -383,6 +478,14 @@ private:
   LowBatterySignalType mLowBatterySignal;
   LowMemorySignalType  mLowMemorySignal;
 
+  AppSignalType        mTaskInitSignal;
+  AppSignalType        mTaskTerminateSignal;
+  AppControlSignalType mTaskAppControlSignal;
+  AppSignalType        mTaskLanguageChangedSignal;
+  AppSignalType        mTaskRegionChangedSignal;
+  LowBatterySignalType mTaskLowBatterySignal;
+  LowMemorySignalType  mTaskLowMemorySignal;
+
   EventLoop* mEventLoop;
   Framework* mFramework;
 
@@ -403,6 +506,7 @@ private:
   Launchpad::State   mLaunchpadState;
   bool               mUseRemoteSurface;
   WindowType         mDefaultWindowType; ///< Default window's type. It is used when Application is created.
+  bool               mUseUiThread;
 
   SlotDelegate<Application> mSlotDelegate;
 
index 5ab74ac..bef6b77 100644 (file)
@@ -59,6 +59,8 @@ public:
 
   /**
    * Observer class for the framework.
+   * @brief When the UI thread is enabled, the events are emitted on the UI thread.
+   * When it is disabled, the events are emitted on the main thread.
    */
   class Observer
   {
@@ -99,9 +101,9 @@ public:
     }
 
     /**
-    * Invoked when the AppControl message is received.
-    * @param[in] The bundle data of AppControl message.
-    */
+     * Invoked when the AppControl message is received.
+     * @param[in] The bundle data of AppControl message.
+     */
     virtual void OnAppControl(void*)
     {
     }
@@ -182,15 +184,75 @@ public:
 #endif
   };
 
+  /**
+   * TaskObserver class for the framework.
+   * @brief This is used only when UiThread is enabled. the events are emitted on the main thread.
+   */
+  class TaskObserver
+  {
+  public:
+    /**
+     * Invoked when the application is to be initialised.
+     */
+    virtual void OnTaskInit()
+    {
+    }
+
+    /**
+     * Invoked when the application is to be terminated.
+     */
+    virtual void OnTaskTerminate()
+    {
+    }
+
+    /**
+     * Invoked when the AppControl message is received.
+     * @param[in] The bundle data of AppControl message.
+     */
+    virtual void OnTaskAppControl(void*)
+    {
+    }
+
+    /**
+     * Invoked when the language of the device is changed.
+     */
+    virtual void OnTaskLanguageChanged()
+    {
+    }
+
+    /**
+     * Invoked when the region is changed.
+     */
+    virtual void OnTaskRegionChanged()
+    {
+    }
+
+    /**
+     * Invoked when the battery level of the device is low.
+     */
+    virtual void OnTaskBatteryLow(Dali::DeviceStatus::Battery::Status status)
+    {
+    }
+
+    /**
+     * Invoked when the memory level of the device is low.
+     */
+    virtual void OnTaskMemoryLow(Dali::DeviceStatus::Memory::Status status)
+    {
+    }
+  };
+
 public:
   /**
    * Constructor
-   * @param[in]  observer  The observer of the Framework.
-   * @param[in]  argc      A pointer to the number of arguments.
-   * @param[in]  argv      A pointer the the argument list.
-   * @param[in]  type      The type of application
+   * @param[in]  observer      The observer of the Framework.
+   * @param[in]  taskObserver  The task observer of the Framework.
+   * @param[in]  argc          A pointer to the number of arguments.
+   * @param[in]  argv          A pointer the the argument list.
+   * @param[in]  type          The type of application
+   * @param[in]  useUiThread   True if the application would create a UI thread
    */
-  Framework(Observer& observer, int* argc, char*** argv, Type type = NORMAL);
+  Framework(Observer& observer, TaskObserver& taskObserver, int* argc, char*** argv, Type type, bool useUiThread);
 
   /**
    * Destructor
@@ -328,15 +390,16 @@ private:
   void InitThreads();
 
 private:
-  Observer&    mObserver;
-  bool         mInitialised;
-  bool         mPaused;
-  bool         mRunning;
-  int*         mArgc;
-  char***      mArgv;
-  std::string  mBundleName;
-  std::string  mBundleId;
-  AbortHandler mAbortHandler;
+  Observer&     mObserver;
+  TaskObserver& mTaskObserver;
+  bool          mInitialised;
+  bool          mPaused;
+  bool          mRunning;
+  int*          mArgc;
+  char***       mArgv;
+  std::string   mBundleName;
+  std::string   mBundleId;
+  AbortHandler  mAbortHandler;
 
 private: // impl members
   struct Impl;
index 4bd637c..b9c1439 100644 (file)
@@ -112,8 +112,9 @@ private:
   std::string mRegion;
 };
 
-Framework::Framework( Framework::Observer& observer, int *argc, char ***argv, Type type )
+Framework::Framework(Framework::Observer& observer, Framework::TaskObserver& taskObserver, int* argc, char*** argv, Type type, bool useUiThread)
 : mObserver(observer),
+  mTaskObserver(taskObserver),
   mInitialised(false),
   mPaused(false),
   mRunning(false),
index ceec60a..09f3aa4 100644 (file)
@@ -35,7 +35,7 @@ ComponentApplicationPtr ComponentApplication::New(
 }
 
 ComponentApplication::ComponentApplication(int* argc, char** argv[], const std::string& stylesheet, Dali::Application::WINDOW_MODE windowMode)
-: Application(argc, argv, stylesheet, windowMode, PositionSize(), Framework::COMPONENT, WindowType::NORMAL)
+: Application(argc, argv, stylesheet, windowMode, PositionSize(), Framework::COMPONENT, WindowType::NORMAL, false)
 {
 }
 
index 7db93c7..3f638d8 100644 (file)
 #include <app_control_internal.h>
 #include <bundle.h>
 #include <bundle_internal.h>
+#include <dlog.h>
+#include <glib.h>
 #include <system_info.h>
 #include <system_settings.h>
 #include <widget_base.h>
 #include <app_core_ui_base.hh>
 #include <app_event_internal.hh>
+
 // CONDITIONAL INCLUDES
 #ifdef APPCORE_WATCH_AVAILABLE
 #include <appcore-watch/watch_app.h>
@@ -219,33 +222,230 @@ struct Framework::Impl
   class UiAppContext : public AppCoreUiBase
   {
   public:
+    class Task : public AppCoreTaskBase
+    {
+    public:
+      explicit Task(Framework* framework)
+      : mFramework(framework),
+        mNewBatteryStatus(Dali::DeviceStatus::Battery::Status::NORMAL),
+        mNewMemoryStatus(Dali::DeviceStatus::Memory::NORMAL)
+      {
+      }
+
+      virtual ~Task()
+      {
+      }
+
+      int OnCreate() override
+      {
+        // On the main thread, the log functions are not set. So print_log() is used directly.
+        print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnCreate() emitted", __MODULE__, __func__, __LINE__);
+        mFramework->mTaskObserver.OnTaskInit();
+        return AppCoreTaskBase::OnCreate();
+      }
+
+      int OnTerminate() override
+      {
+        print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnTerminate() emitted", __MODULE__, __func__, __LINE__);
+        mFramework->mTaskObserver.OnTaskTerminate();
+        return AppCoreTaskBase::OnTerminate();
+      }
+
+      int OnControl(tizen_base::Bundle b) override
+      {
+        print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnControl() emitted", __MODULE__, __func__, __LINE__);
+        AppCoreTaskBase::OnControl(b);
+
+        app_control_h appControl = nullptr;
+
+        auto* bundleData = b.GetHandle();
+        if(bundleData)
+        {
+          if(app_control_create_event(bundleData, &appControl) != TIZEN_ERROR_NONE)
+          {
+            print_log(DLOG_ERROR, "DALI", "%s: %s(%d) > Failed to create an app_control handle with Bundle", __MODULE__, __func__, __LINE__);
+          }
+        }
+        else
+        {
+          if(app_control_create(&appControl) != TIZEN_ERROR_NONE)
+          {
+            print_log(DLOG_ERROR, "DALI", "%s: %s(%d) > Failed to create an app_control handle", __MODULE__, __func__, __LINE__);
+          }
+        }
+        mFramework->mTaskObserver.OnTaskAppControl(appControl);
+
+        app_control_destroy(appControl);
+        return 0;
+      }
+
+      void OnUiEvent(AppCoreTaskBase::UiState state) override
+      {
+        // This event is emitted when the UI thread is paused or resumed.
+        print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnUiEvent() emitted", __MODULE__, __func__, __LINE__);
+
+        // Note: This isn't implemented.
+        AppCoreTaskBase::OnUiEvent(state);
+      }
+
+      void OnLowMemory(AppCoreTaskBase::LowMemoryState state) override
+      {
+        print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLowMemory() emitted", __MODULE__, __func__, __LINE__);
+
+        mNewMemoryStatus = AppCore::GetMemoryStatus(static_cast<app_event_low_memory_status_e>(state));
+
+        PostToUiThread(
+          [](gpointer userData) -> gboolean
+          {
+            auto* task      = static_cast<Task*>(userData);
+            auto* framework = static_cast<Framework*>(task->mFramework);
+            framework->mObserver.OnMemoryLow(task->mNewMemoryStatus);
+            return G_SOURCE_REMOVE;
+          });
+        mFramework->mTaskObserver.OnTaskMemoryLow(mNewMemoryStatus);
+        AppCoreTaskBase::OnLowMemory(state);
+      }
+
+      void OnLowBattery(AppCoreTaskBase::LowBatteryState state) override
+      {
+        print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLowBattery() emitted", __MODULE__, __func__, __LINE__);
+        mNewBatteryStatus = AppCore::GetBatteryStatus(static_cast<app_event_low_battery_status_e>(state));
+
+        PostToUiThread(
+          [](gpointer userData) -> gboolean
+          {
+            auto* task      = static_cast<Task*>(userData);
+            auto* framework = static_cast<Framework*>(task->mFramework);
+            framework->mObserver.OnBatteryLow(task->mNewBatteryStatus);
+            return G_SOURCE_REMOVE;
+          });
+        mFramework->mTaskObserver.OnTaskBatteryLow(mNewBatteryStatus);
+        AppCoreTaskBase::OnLowBattery(state);
+      }
+
+      void OnLangChanged(const std::string& lang) override
+      {
+        print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLangChanged() emitted", __MODULE__, __func__, __LINE__);
+        mNewLanguage = lang;
+        mFramework->SetLanguage(mNewLanguage);
+
+        PostToUiThread(
+          [](gpointer userData) -> gboolean
+          {
+            auto* task      = static_cast<Task*>(userData);
+            auto* framework = static_cast<Framework*>(task->mFramework);
+            framework->mObserver.OnLanguageChanged();
+            return G_SOURCE_REMOVE;
+          });
+
+        mFramework->mTaskObserver.OnTaskLanguageChanged();
+        AppCoreTaskBase::OnLangChanged(lang);
+      }
+
+      void OnRegionChanged(const std::string& region) override
+      {
+        print_log(DLOG_INFO, "DALI", "%s: %s(%d) > nRegionChanged() emitted", __MODULE__, __func__, __LINE__);
+        mNewRegion = region;
+        mFramework->SetRegion(mNewRegion);
+
+        PostToUiThread(
+          [](gpointer userData) -> gboolean
+          {
+            auto* task      = static_cast<Task*>(userData);
+            auto* framework = static_cast<Framework*>(task->mFramework);
+            framework->mObserver.OnRegionChanged();
+            return G_SOURCE_REMOVE;
+          });
+
+        mFramework->mTaskObserver.OnTaskRegionChanged();
+        AppCoreTaskBase::OnRegionChanged(mNewRegion);
+      }
+
+      void OnDeviceOrientationChanged(AppCoreTaskBase::DeviceOrientationState state) override
+      {
+        print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnDeviceOrientationChanged() emitted", __MODULE__, __func__, __LINE__);
+        // Note: This isn't emitted to the App.
+        AppCoreTaskBase::OnDeviceOrientationChanged(state);
+      }
+
+    private:
+      GMainContext* GetTizenGlibContext()
+      {
+        GMainContext* context;
+        const char*   env = getenv("TIZEN_GLIB_CONTEXT");
+        if(env)
+        {
+          context = (GMainContext*)strtoul(env, nullptr, 10);
+        }
+        else
+        {
+          context = nullptr;
+        }
+
+        return context;
+      }
+
+      void PostToUiThread(GSourceFunc func)
+      {
+        GSource* source = g_idle_source_new();
+        g_source_set_callback(source, func, this, nullptr);
+        g_source_attach(source, GetTizenGlibContext());
+        g_source_unref(source);
+      }
+
+    private:
+      Framework*                          mFramework;
+      std::string                         mNewLanguage;
+      std::string                         mNewRegion;
+      Dali::DeviceStatus::Battery::Status mNewBatteryStatus;
+      Dali::DeviceStatus::Memory::Status  mNewMemoryStatus;
+    };
+
     explicit UiAppContext(unsigned int hint, Framework* framework)
     : AppCoreUiBase(hint),
-      mFramework(framework)
+      mFramework(framework),
+      mUseUiThread(false)
     {
-      mLanguageChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LANG_CHANGE, OnLanguageChanged, this);
-      AddEvent(mLanguageChanged);
+      if(hint & AppCoreUiBase::HINT_DUAL_THREAD)
+      {
+        mUseUiThread = true;
+      }
+
+      if(!mUseUiThread)
+      {
+        mLanguageChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LANG_CHANGE, OnLanguageChanged, this);
+        AddEvent(mLanguageChanged);
 
-      mDeviceOrientationChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED, OnDeviceOrientationChanged, this);
-      AddEvent(mDeviceOrientationChanged);
+        mDeviceOrientationChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED, OnDeviceOrientationChanged, this);
+        AddEvent(mDeviceOrientationChanged);
 
-      mRegionFormatChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::REGION_CHANGE, OnRegionFormatChanged, this);
-      AddEvent(mRegionFormatChanged);
+        mRegionFormatChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::REGION_CHANGE, OnRegionFormatChanged, this);
+        AddEvent(mRegionFormatChanged);
 
-      mLowMemory = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LOW_MEMORY, OnLowMemory, this);
-      AddEvent(mLowMemory);
+        mLowMemory = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LOW_MEMORY, OnLowMemory, this);
+        AddEvent(mLowMemory);
 
-      mLowBattery = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LOW_BATTERY, OnLowBattery, this);
-      AddEvent(mLowBattery);
+        mLowBattery = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LOW_BATTERY, OnLowBattery, this);
+        AddEvent(mLowBattery);
+      }
     }
 
     virtual ~UiAppContext()
     {
-      RemoveEvent(mLowBattery);
-      RemoveEvent(mLowMemory);
-      RemoveEvent(mRegionFormatChanged);
-      RemoveEvent(mDeviceOrientationChanged);
-      RemoveEvent(mLanguageChanged);
+      if(!mUseUiThread)
+      {
+        RemoveEvent(mLowBattery);
+        RemoveEvent(mLowMemory);
+        RemoveEvent(mRegionFormatChanged);
+        RemoveEvent(mDeviceOrientationChanged);
+        RemoveEvent(mLanguageChanged);
+      }
+    }
+
+    std::unique_ptr<AppCoreTaskBase> CreateTask() override
+    {
+      return std::unique_ptr<AppCoreTaskBase>(
+        new Task(mFramework));
     }
 
     int OnCreate() override
@@ -451,12 +651,14 @@ struct Framework::Impl
     std::shared_ptr<AppEvent> mRegionFormatChanged;
     std::shared_ptr<AppEvent> mLowBattery;
     std::shared_ptr<AppEvent> mLowMemory;
+    bool                      mUseUiThread;
   };
 
   // Constructor
-  Impl(void* data, Type type)
+  Impl(void* data, Type type, bool useUiThread)
   : mAbortCallBack(NULL),
-    mCallbackManager(NULL)
+    mCallbackManager(NULL),
+    mUseUiThread(useUiThread)
 #ifdef APPCORE_WATCH_AVAILABLE
     ,
     mWatchCallback()
@@ -597,6 +799,7 @@ struct Framework::Impl
   Framework*                    mFramework;
   AppCore::AppEventHandlerPtr   handlers[5];
   std::unique_ptr<UiAppContext> mUiAppContext;
+  bool                          mUseUiThread;
 #ifdef APPCORE_WATCH_AVAILABLE
   watch_app_lifecycle_callback_s mWatchCallback;
   app_event_handler_h            watchHandlers[5];
@@ -767,6 +970,26 @@ struct Framework::Impl
                           AppCoreUiBase::HINT_HW_ACC_CONTROL |
                           AppCoreUiBase::HINT_WINDOW_AUTO_CONTROL;
 
+      // For testing UIThread model, This code turns on the UI Thread feature forcibly.
+      //  ex) app_launcher -e [APPID] __K_UI_THREAD enable
+      // This code doesn't change mUseUiThread in Internal::Application
+      bundle* b = bundle_import_from_argv(*mFramework->mArgc, *mFramework->mArgv);
+      if(b != nullptr)
+      {
+        const char* val = bundle_get_val(b, "__K_UI_THREAD");
+        if(val != nullptr && strcmp(val, "enable") == 0)
+        {
+          mUseUiThread = true;
+        }
+
+        bundle_free(b);
+      }
+
+      if(mUseUiThread)
+      {
+        hint |= AppCoreUiBase::HINT_DUAL_THREAD;
+      }
+
       mUiAppContext = std::make_unique<UiAppContext>(hint, mFramework);
     }
 
@@ -988,8 +1211,9 @@ private:
   Impl& operator=(const Impl& impl);
 };
 
-Framework::Framework(Framework::Observer& observer, int* argc, char*** argv, Type type)
+Framework::Framework(Framework::Observer& observer, Framework::TaskObserver& taskObserver, int* argc, char*** argv, Type type, bool useUiThread)
 : mObserver(observer),
+  mTaskObserver(taskObserver),
   mInitialised(false),
   mPaused(false),
   mRunning(false),
@@ -1010,7 +1234,7 @@ Framework::Framework(Framework::Observer& observer, int* argc, char*** argv, Typ
 
   InitThreads();
 
-  mImpl = new Impl(this, type);
+  mImpl = new Impl(this, type, useUiThread);
 }
 
 Framework::~Framework()
index 72cf282..7f7a7f1 100644 (file)
@@ -50,7 +50,7 @@ WatchApplicationPtr WatchApplication::New(
 }
 
 WatchApplication::WatchApplication(int* argc, char** argv[], const std::string& stylesheet, Dali::Application::WINDOW_MODE windowMode)
-: Application(argc, argv, stylesheet, windowMode, PositionSize(), Framework::WATCH, WindowType::NORMAL),
+: Application(argc, argv, stylesheet, windowMode, PositionSize(), Framework::WATCH, WindowType::NORMAL, false),
   mState(UNINITIALIZED)
 {
 }
index 38e3d76..60529c5 100644 (file)
@@ -134,8 +134,9 @@ struct Framework::Impl
   }
 };
 
-Framework::Framework(Framework::Observer& observer, int* argc, char*** argv, Type type)
+Framework::Framework(Framework::Observer& observer, Framework::TaskObserver& taskObserver, int* argc, char*** argv, Type type, bool useUiThread)
 : mObserver(observer),
+  mTaskObserver(taskObserver),
   mInitialised(false),
   mPaused(false),
   mRunning(false),
index 2a5ab92..0623baf 100644 (file)
@@ -184,8 +184,9 @@ private:
   std::string      mRegion;\r
 };\r
 \r
-Framework::Framework(Framework::Observer& observer, int* argc, char*** argv, Type type)\r
+Framework::Framework(Framework::Observer& observer, Framework::TaskObserver& taskObserver, int* argc, char*** argv, Type type, bool useUiThread)\r
 : mObserver(observer),\r
+  mTaskObserver(taskObserver),\r
   mInitialised(false),\r
   mPaused(false),\r
   mRunning(false),\r
index f4b661a..c262bd7 100644 (file)
@@ -144,6 +144,8 @@ namespace Adaptor
 
 #define DALI_ENV_SUPPRESS_SCREEN_READER "DALI_SUPPRESS_SCREEN_READER"
 
+#define DALI_ENV_ENABLE_UI_THREAD "DALI_ENABLE_UI_THREAD"
+
 } // namespace Adaptor
 
 } // namespace Internal
index 2b07db9..5c7aef6 100644 (file)
@@ -48,7 +48,7 @@ WidgetApplicationPtr WidgetApplication::New(
 }
 
 WidgetApplication::WidgetApplication(int* argc, char** argv[], const std::string& stylesheet)
-: Application(argc, argv, stylesheet, Dali::WidgetApplication::OPAQUE, PositionSize(), Framework::WIDGET, WindowType::NORMAL)
+: Application(argc, argv, stylesheet, Dali::WidgetApplication::OPAQUE, PositionSize(), Framework::WIDGET, WindowType::NORMAL, false)
 {
   DALI_LOG_ERROR("WidgetApplication is not implemented in UBUNTU profile.\n");
 }
index ccef811..f123f25 100644 (file)
@@ -655,8 +655,8 @@ void WindowBaseEcoreWl::Initialize(PositionSize positionSize, Any surface, bool
   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_WL_EVENT_SELECTION_DATA_READY, EcoreEventDataReceive, this));
 
   // Register Vconf notify - font name and size
-  vconf_notify_key_changed(DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_NAME, VconfNotifyFontNameChanged, this);
-  vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontSizeChanged, this);
+  vconf_notify_key_changed_for_ui_thread(DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_NAME, VconfNotifyFontNameChanged, this);
+  vconf_notify_key_changed_for_ui_thread(VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontSizeChanged, this);
 
   mDisplay = ecore_wl_display_get();
 
index 6c15aad..a77a163 100644 (file)
@@ -824,8 +824,8 @@ void WindowBaseEcoreWl2::Initialize(PositionSize positionSize, Any surface, bool
   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_WL2_EVENT_AUX_MESSAGE, EcoreEventWindowAuxiliaryMessage, this));
 
   // Register Vconf notify - font name and size
-  vconf_notify_key_changed(DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_NAME, VconfNotifyFontNameChanged, this);
-  vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontSizeChanged, this);
+  vconf_notify_key_changed_for_ui_thread(DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_NAME, VconfNotifyFontNameChanged, this);
+  vconf_notify_key_changed_for_ui_thread(VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontSizeChanged, this);
 
   Ecore_Wl2_Display* display = ecore_wl2_connected_display_get(NULL);
   mDisplay                   = ecore_wl2_display_get(display);
index 17403d2..20099eb 100644 (file)
@@ -46,7 +46,7 @@ Application Application::New(int* argc, char** argv[])
   }
   else
   {
-    internal = Internal::Adaptor::Application::New(argc, argv, "", OPAQUE, PositionSize(), Internal::Adaptor::Framework::NORMAL, WindowType::NORMAL);
+    internal = Internal::Adaptor::Application::New(argc, argv, "", OPAQUE, PositionSize(), Internal::Adaptor::Framework::NORMAL, WindowType::NORMAL, false);
   }
   return Application(internal.Get());
 }
@@ -66,7 +66,7 @@ Application Application::New(int* argc, char** argv[], const std::string& styles
   }
   else
   {
-    internal = Internal::Adaptor::Application::New(argc, argv, stylesheet, OPAQUE, PositionSize(), Internal::Adaptor::Framework::NORMAL, WindowType::NORMAL);
+    internal = Internal::Adaptor::Application::New(argc, argv, stylesheet, OPAQUE, PositionSize(), Internal::Adaptor::Framework::NORMAL, WindowType::NORMAL, false);
   }
   return Application(internal.Get());
 }
@@ -88,7 +88,7 @@ Application Application::New(int* argc, char** argv[], const std::string& styles
   }
   else
   {
-    internal = Internal::Adaptor::Application::New(argc, argv, stylesheet, windowMode, PositionSize(), Internal::Adaptor::Framework::NORMAL, WindowType::NORMAL);
+    internal = Internal::Adaptor::Application::New(argc, argv, stylesheet, windowMode, PositionSize(), Internal::Adaptor::Framework::NORMAL, WindowType::NORMAL, false);
   }
   return Application(internal.Get());
 }
@@ -113,7 +113,32 @@ Application Application::New(int* argc, char** argv[], const std::string& styles
   }
   else
   {
-    internal = Internal::Adaptor::Application::New(argc, argv, stylesheet, windowMode, positionSize, Internal::Adaptor::Framework::NORMAL, WindowType::NORMAL);
+    internal = Internal::Adaptor::Application::New(argc, argv, stylesheet, windowMode, positionSize, Internal::Adaptor::Framework::NORMAL, WindowType::NORMAL, false);
+  }
+  return Application(internal.Get());
+}
+
+Application Application::New(int* argc, char** argv[], const std::string& stylesheet, Application::WINDOW_MODE windowMode, PositionSize positionSize, bool useUiThread)
+{
+  Internal::Adaptor::ApplicationPtr internal = Internal::Adaptor::Application::GetPreInitializedApplication();
+  if(internal)
+  {
+    // pre-initialized application
+    internal->SetCommandLineOptions(argc, argv);
+    if(argc && (*argc > 0))
+    {
+      internal->GetWindow().SetClass((*argv)[0], "");
+    }
+    internal->SetStyleSheet(stylesheet);
+
+    internal->GetWindow().SetTransparency((windowMode == Application::OPAQUE ? false : true));
+
+    //Store only the value before adaptor is created
+    internal->StoreWindowPositionSize(positionSize);
+  }
+  else
+  {
+    internal = Internal::Adaptor::Application::New(argc, argv, stylesheet, windowMode, positionSize, Internal::Adaptor::Framework::NORMAL, WindowType::NORMAL, useUiThread);
   }
   return Application(internal.Get());
 }
@@ -229,6 +254,41 @@ Application::LowMemorySignalType& Application::LowMemorySignal()
   return Internal::Adaptor::GetImplementation(*this).LowMemorySignal();
 }
 
+Application::AppSignalType& Application::TaskInitSignal()
+{
+  return Internal::Adaptor::GetImplementation(*this).TaskInitSignal();
+}
+
+Application::AppSignalType& Application::TaskTerminateSignal()
+{
+  return Internal::Adaptor::GetImplementation(*this).TaskTerminateSignal();
+}
+
+Application::AppControlSignalType& Application::TaskAppControlSignal()
+{
+  return Internal::Adaptor::GetImplementation(*this).TaskAppControlSignal();
+}
+
+Application::AppSignalType& Application::TaskLanguageChangedSignal()
+{
+  return Internal::Adaptor::GetImplementation(*this).TaskLanguageChangedSignal();
+}
+
+Application::AppSignalType& Application::TaskRegionChangedSignal()
+{
+  return Internal::Adaptor::GetImplementation(*this).TaskRegionChangedSignal();
+}
+
+Application::LowBatterySignalType& Application::TaskLowBatterySignal()
+{
+  return Internal::Adaptor::GetImplementation(*this).TaskLowBatterySignal();
+}
+
+Application::LowMemorySignalType& Application::TaskLowMemorySignal()
+{
+  return Internal::Adaptor::GetImplementation(*this).TaskLowMemorySignal();
+}
+
 Application::Application(Internal::Adaptor::Application* application)
 : BaseHandle(application)
 {
index 90ed7b5..4861e71 100644 (file)
@@ -90,6 +90,22 @@ class Application;
  * app.ResumeSignal().Connect(&app, &MyApplication::Resume);
  * @endcode
  *
+ *
+ * #### UI thread
+ * There is the UI thread feature.
+ * UI thread is an additional thread that an Application object creates. The thread is for UI events.
+ *
+ * When the UI thread feature is enabled, you can use the task signals(TaskInit, TaskTerminate, TaskAppControl, TaskLanguageChanged, TaskLowBattery, and TaskLowMemory).
+ * The task signals are emitted on the main thread,
+ * and the normal signals(Init, Terminate, Pause, Resume, Reset, AppControl, LanguageChanged, Region, LowBattery, and LowMemory) are emitted on the UI thread.
+ *
+ * If you want to handle windows or actors in cases like when the memory level of the device is low, you have to use the normal signals, not the task signals.
+ * Callbacks of all signals in DALi except the task signals are emitted on the UI thread. (e.g., Timer callbacks are emitted on the UI thread.)
+ *
+ * To enable the UI Thread, you can use this method. you have to set True to the useUiThread.
+ * Dali::Application::New(int *argc, char **argv[], const std::string &stylesheet, Application::WINDOW_MODE windowMode, PositionSize positionSize, bool useUiThread)
+ *
+ *
  * This class accepts command line arguments as well. The following options are supported:
  *
  * @code
@@ -188,6 +204,25 @@ public:
   static Application New(int* argc, char** argv[], const std::string& stylesheet, Application::WINDOW_MODE windowMode, PositionSize positionSize);
 
   /**
+   * @brief This is the constructor for applications.
+   *
+   * @SINCE_2_1.20
+   * @PRIVLEVEL_PUBLIC
+   * @PRIVILEGE_DISPLAY
+   * @param[in,out]  argc         A pointer to the number of arguments
+   * @param[in,out]  argv         A pointer to the argument list
+   * @param[in]      stylesheet   The path to user defined theme file
+   * @param[in]      windowMode   A member of WINDOW_MODE
+   * @param[in]      positionSize A position and a size of the window
+   * @param[in]      useUiThread  True if the application would create a UI thread
+   * @return A handle to the Application
+   * @note If the stylesheet is not specified, then the library's default stylesheet will not be overridden.<BR>
+   * UI thread is an additional thread that DALi creates for UI events.
+   * The UI thread isn't blocked from the system events(AppControl, LanguageChanged, RegionChanged, LowMemory, LowBattery task signals).
+   */
+  static Application New(int* argc, char** argv[], const std::string& stylesheet, Application::WINDOW_MODE windowMode, PositionSize positionSize, bool useUiThread);
+
+  /**
    * @brief Constructs an empty handle.
    * @SINCE_1_0.0
    */
@@ -322,6 +357,8 @@ public: // Signals
   /**
    * @brief The user should connect to this signal to determine when they should initialize
    * their application.
+   * Only when the user uses the UiThread, this signal is emitted on the UI thread.
+   * Otherwise, it is emitted on the main thread.
    * @SINCE_1_0.0
    * @return The signal to connect to
    */
@@ -330,6 +367,8 @@ public: // Signals
   /**
    * @brief The user should connect to this signal to determine when they should terminate
    * their application.
+   * Only when the user uses the UiThread, this signal is emitted on the UI thread.
+   * Otherwise, it is emitted on the main thread.
    * @SINCE_1_0.0
    * @return The signal to connect to
    */
@@ -338,6 +377,8 @@ public: // Signals
   /**
    * @brief The user should connect to this signal if they need to perform any special
    * activities when the application is about to be paused.
+   * Only when the user uses the UiThread, this signal is emitted on the UI thread.
+   * Otherwise, it is emitted on the main thread.
    * @SINCE_1_0.0
    * @return The signal to connect to
    */
@@ -346,6 +387,8 @@ public: // Signals
   /**
    * @brief The user should connect to this signal if they need to perform any special
    * activities when the application has resumed.
+   * Only when the user uses the UiThread, this signal is emitted on the UI thread.
+   * Otherwise, it is emitted on the main thread.
    * @SINCE_1_0.0
    * @return The signal to connect to
    */
@@ -353,37 +396,47 @@ public: // Signals
 
   /**
    * @brief This signal is sent when the system requires the user to reinitialize itself.
+   * Only when the user uses the UiThread, this signal is emitted on the UI thread.
+   * Otherwise, it is emitted on the main thread.
    * @SINCE_1_0.0
    * @return The signal to connect to
    */
   AppSignalType& ResetSignal();
 
   /**
-  * @brief This signal is emitted when another application sends a launch request to the application.
-  *
-  * When the application is launched, this signal is emitted after the main loop of the application starts up.
-  * The passed parameter describes the launch request and contains the information about why the application is launched.
-  * @SINCE_1_0.0
-  * @return The signal to connect to
-  */
+   * @brief This signal is emitted when another application sends a launch request to the application.
+   *
+   * When the application is launched, this signal is emitted after the main loop of the application starts up.
+   * The passed parameter describes the launch request and contains the information about why the application is launched.
+   * Only when the user uses the UiThread, this signal is emitted on the UI thread.
+   * Otherwise, it is emitted on the main thread.
+   * @SINCE_1_0.0
+   * @return The signal to connect to
+   */
   AppControlSignalType& AppControlSignal();
 
   /**
    * @brief This signal is emitted when the language is changed on the device.
+   * Only when the user uses the UiThread, this signal is emitted on the UI thread.
+   * Otherwise, it is emitted on the main thread.
    * @SINCE_1_0.0
    * @return The signal to connect to
    */
   AppSignalType& LanguageChangedSignal();
 
   /**
-  * @brief This signal is emitted when the region of the device is changed.
-  * @SINCE_1_0.0
-  * @return The signal to connect to
-  */
+   * @brief This signal is emitted when the region of the device is changed.
+   * Only when the user uses the UiThread, this signal is emitted on the UI thread.
+   * Otherwise, it is emitted on the main thread.
+   * @SINCE_1_0.0
+   * @return The signal to connect to
+   */
   AppSignalType& RegionChangedSignal();
 
   /**
    * @brief This signal is emitted when the battery level of the device is low.
+   * Only when the user uses the UiThread, this signal is emitted on the UI thread.
+   * Otherwise, it is emitted on the main thread.
    * @SINCE_1_2.62
    * @return The signal to connect to
    */
@@ -391,11 +444,75 @@ public: // Signals
 
   /**
    * @brief This signal is emitted when the memory level of the device is low.
+   * Only when the user uses the UiThread, this signal is emitted on the UI thread.
+   * Otherwise, it is emitted on the main thread.
    * @SINCE_1_2.62
    * @return The signal to connect to
    */
   LowMemorySignalType& LowMemorySignal();
 
+  // TaskSignal
+  /**
+   * @brief The user should connect to this signal to determine when they should initialize
+   * their application.
+   * Only when the user uses the UiThread, this signal is emitted on the main thread.
+   * Otherwise, it is not emitted at all.
+   * @return The signal to connect to
+   */
+  AppSignalType& TaskInitSignal();
+
+  /**
+   * @brief The user should connect to this signal to determine when they should terminate
+   * their application.
+   * Only when the user uses the UiThread, this signal is emitted on the main thread.
+   * Otherwise, it is not emitted at all.
+   * @return The signal to connect to
+   */
+  AppSignalType& TaskTerminateSignal();
+
+  /**
+   * @brief This signal is emitted when another application sends a launch request to the application.
+   *
+   * When the application is launched, this signal is emitted after the main loop of the application starts up.
+   * The passed parameter describes the launch request and contains the information about why the application is launched.
+   * Only when the user uses the UiThread, this signal is emitted on the main thread.
+   * Otherwise, it is not emitted at all.
+   * @return The signal to connect to
+   */
+  AppControlSignalType& TaskAppControlSignal();
+
+  /**
+   * @brief This signal is emitted when the language is changed on the device.
+   * Only when the user uses the UiThread, this signal is emitted on the main thread.
+   * Otherwise, it is not emitted at all.
+   * @return The signal to connect to
+   */
+  AppSignalType& TaskLanguageChangedSignal();
+
+  /**
+   * @brief This signal is emitted when the region of the device is changed.
+   * Only when the user uses the UiThread, this signal is emitted on the main thread.
+   * Otherwise, it is not emitted at all.
+   * @return The signal to connect to
+   */
+  AppSignalType& TaskRegionChangedSignal();
+
+  /**
+   * @brief This signal is emitted when the battery level of the device is low.
+   * Only when the user uses the UiThread, this signal is emitted on the main thread.
+   * Otherwise, it is not emitted at all.
+   * @return The signal to connect to
+   */
+  LowBatterySignalType& TaskLowBatterySignal();
+
+  /**
+   * @brief This signal is emitted when the memory level of the device is low.
+   * Only when the user uses the UiThread, this signal is emitted on the main thread.
+   * Otherwise, it is not emitted at all.
+   * @return The signal to connect to
+   */
+  LowMemorySignalType&  TaskLowMemorySignal();
+
 public: // Not intended for application developers
   /// @cond internal
   /**