/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
// EXTERNAL INCLUDES
#include <dali/devel-api/common/singleton-service.h>
#include <dali/integration-api/debug.h>
+#include <dali/integration-api/trace.h>
#include <dali/public-api/object/object-registry.h>
// INTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/accessibility-impl.h>
+#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>
#include <dali/internal/adaptor/common/adaptor-impl.h>
+#include <dali/internal/adaptor/common/framework-factory.h>
#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/system/common/system-settings.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>
{
namespace Adaptor
{
+DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_APPLICATION, true);
+
ApplicationPtr Application::gPreInitializedApplication(NULL);
ApplicationPtr Application::New(
- int* argc,
- char** argv[],
- const std::string& stylesheet,
- Dali::Application::WINDOW_MODE windowMode,
- const PositionSize& positionSize,
- Framework::Type applicationType)
-{
- ApplicationPtr application(new Application(argc, argv, stylesheet, windowMode, positionSize, applicationType));
+ int* argc,
+ char** argv[],
+ const std::string& stylesheet,
+ Framework::Type applicationType,
+ bool useUiThread,
+ const WindowData& windowData)
+{
+ ApplicationPtr application(new Application(argc, argv, stylesheet, applicationType, useUiThread, windowData));
return application;
}
{
if(!gPreInitializedApplication)
{
- Dali::TextAbstraction::FontClientPreInitialize();
+ bool isUseUIThread = false;
- gPreInitializedApplication = new Application(argc, argv, "", Dali::Application::OPAQUE, PositionSize(), Framework::NORMAL);
- gPreInitializedApplication->CreateWindow(); // Only create window
+#ifdef UI_THREAD_AVAILABLE
+ char* retEnv = std::getenv("TIZEN_UI_THREAD");
+ if(retEnv)
+ {
+ std::string uiThreadEnv = retEnv;
+ std::string enabledString = "true";
+ if(uiThreadEnv == enabledString)
+ {
+ isUseUIThread = true;
+ }
+ }
+#endif
+
+ Dali::TextAbstraction::FontClientPreInitialize();
+ WindowData windowData;
+ gPreInitializedApplication = new Application(argc, argv, "", Framework::NORMAL, isUseUIThread, windowData);
gPreInitializedApplication->mLaunchpadState = Launchpad::PRE_INITIALIZED;
+
+#ifdef UI_THREAD_AVAILABLE
+ if(isUseUIThread)
+ {
+ DALI_LOG_RELEASE_INFO("PRE_INITIALIZED with UI Threading");
+ gPreInitializedApplication->mUIThreadLoader = new UIThreadLoader(argc, argv);
+ gPreInitializedApplication->mUIThreadLoader->Run([&]() { gPreInitializedApplication->CreateWindow(); });
+ }
+ else
+#endif
+ {
+ DALI_LOG_RELEASE_INFO("Only PRE_INITIALIZED");
+ gPreInitializedApplication->CreateWindow(); // Only create window
+ }
}
}
-Application::Application(int* argc, char** argv[], const std::string& stylesheet, Dali::Application::WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType)
+Application::Application(int* argc, char** argv[], const std::string& stylesheet, Framework::Type applicationType, bool useUiThread, const WindowData& windowData)
: mInitSignal(),
mTerminateSignal(),
mPauseSignal(),
mAppControlSignal(),
mLanguageChangedSignal(),
mRegionChangedSignal(),
- mEventLoop(nullptr),
mFramework(nullptr),
+ mFrameworkFactory(nullptr),
mCommandLineOptions(nullptr),
mAdaptorBuilder(nullptr),
mAdaptor(nullptr),
+ mEnvironmentOptions(nullptr),
mMainWindow(),
- mMainWindowMode(windowMode),
+ mMainWindowMode(windowData.GetTransparency() ? WINDOW_MODE::TRANSPARENT : WINDOW_MODE::OPAQUE),
mMainWindowName(),
+ mIsMainWindowFrontBufferRendering(windowData.GetFrontBufferRendering()),
mStylesheet(stylesheet),
- mEnvironmentOptions(),
- mWindowPositionSize(positionSize),
+ mWindowPositionSize(windowData.GetPositionSize()),
mLaunchpadState(Launchpad::NONE),
- mSlotDelegate(this)
-{
- // Get mName from environment options
- mMainWindowName = mEnvironmentOptions.GetWindowName();
- if(mMainWindowName.empty() && argc && (*argc > 0))
+ mDefaultWindowType(windowData.GetWindowType()),
+ mUseUiThread(useUiThread),
+ mIsSystemInitialized(false),
+ mSlotDelegate(this),
+ mUIThreadLoader(nullptr)
+{
+ // Set mName from command-line args
+ if(argc && (*argc > 0))
{
- // Set mName from command-line args if environment option not set
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);
- mUseRemoteSurface = (applicationType == Framework::WATCH);
+
+ mFrameworkFactory = std::unique_ptr<FrameworkFactory>(Dali::Internal::Adaptor::CreateFrameworkFactory());
+ mFramework = mFrameworkFactory->CreateFramework(FrameworkBackend::DEFAULT, *this, *this, argc, argv, applicationType, mUseUiThread);
+
+ mUseRemoteSurface = (applicationType == Framework::WATCH);
}
Application::~Application()
}
mMainWindow.Reset();
- delete mAdaptor;
- delete mAdaptorBuilder;
+
delete mCommandLineOptions;
- delete mFramework;
+
+ // Application is created in Main thread whether UI Threading is enabled or not.
+ // But some resources are created in Main thread or UI thread.
+ // The below code is for the resource are created in Main thread.
+ if(!mUseUiThread)
+ {
+ delete mAdaptor;
+ delete mAdaptorBuilder;
+ if(mIsSystemInitialized)
+ {
+ WindowSystem::Shutdown();
+ }
+ }
+ else
+ {
+ if(mUIThreadLoader)
+ {
+ delete mUIThreadLoader;
+ }
+ }
}
void Application::StoreWindowPositionSize(PositionSize positionSize)
mWindowPositionSize = positionSize;
}
-void Application::ChangePreInitializedWindowSize()
+void Application::StoreFrontBufferRendering(bool enable)
+{
+ mIsMainWindowFrontBufferRendering = enable;
+}
+
+void Application::ChangePreInitializedWindowInfo()
{
+ // Set window name
+ auto windowClassName = mEnvironmentOptions->GetWindowClassName();
+ auto windowName = mEnvironmentOptions->GetWindowName();
+ if(!windowName.empty())
+ {
+ mMainWindowName = windowName;
+ }
+ mMainWindow.SetClass(mMainWindowName, windowClassName);
+
+ // The real screen size may be different from the value of the preinitialized state. Update it.
+ Dali::Internal::Adaptor::WindowSystem::UpdateScreenSize();
+
int screenWidth, screenHeight;
Dali::Internal::Adaptor::WindowSystem::GetScreenSize(screenWidth, screenHeight);
+ // Set window position / size
if(mWindowPositionSize != PositionSize(0, 0, 0, 0))
{
Dali::DevelWindow::SetPositionSize(mMainWindow, mWindowPositionSize);
mWindowPositionSize.height = mCommandLineOptions->stageHeight;
mMainWindow.SetSize(Dali::Window::WindowSize(mWindowPositionSize.width, mWindowPositionSize.height));
}
- else if(mEnvironmentOptions.GetWindowWidth() && mEnvironmentOptions.GetWindowHeight())
+ else if(mEnvironmentOptions->GetWindowWidth() && mEnvironmentOptions->GetWindowHeight())
{
// Environment options override full screen functionality if command line arguments not provided
- mWindowPositionSize.width = mEnvironmentOptions.GetWindowWidth();
- mWindowPositionSize.height = mEnvironmentOptions.GetWindowHeight();
+ mWindowPositionSize.width = mEnvironmentOptions->GetWindowWidth();
+ mWindowPositionSize.height = mEnvironmentOptions->GetWindowHeight();
mMainWindow.SetSize(Dali::Window::WindowSize(mWindowPositionSize.width, mWindowPositionSize.height));
}
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));
}
+
+ // Set front buffer rendering
+ Dali::DevelWindow::SetFrontBufferRendering(mMainWindow, mIsMainWindowFrontBufferRendering);
}
void Application::CreateWindow()
{
- if(mWindowPositionSize.width == 0 && mWindowPositionSize.height == 0)
+ Internal::Adaptor::Window* window;
+ WindowData windowData;
+ windowData.SetTransparency(mMainWindowMode);
+ windowData.SetWindowType(mDefaultWindowType);
+ windowData.SetFrontBufferRendering(mIsMainWindowFrontBufferRendering);
+
+ DALI_LOG_RELEASE_INFO("Create Default Window");
+
+ WindowSystem::Initialize();
+ mIsSystemInitialized = true;
+
+ if(mLaunchpadState != Launchpad::PRE_INITIALIZED)
{
- if(mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0)
+ if(mWindowPositionSize.width == 0 && mWindowPositionSize.height == 0)
{
- // Command line options override environment options and full screen
- mWindowPositionSize.width = mCommandLineOptions->stageWidth;
- mWindowPositionSize.height = mCommandLineOptions->stageHeight;
+ if(mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0)
+ {
+ // Command line options override environment options and full screen
+ mWindowPositionSize.width = mCommandLineOptions->stageWidth;
+ mWindowPositionSize.height = mCommandLineOptions->stageHeight;
+ }
+ else if(mEnvironmentOptions->GetWindowWidth() && mEnvironmentOptions->GetWindowHeight())
+ {
+ // Environment options override full screen functionality if command line arguments not provided
+ mWindowPositionSize.width = mEnvironmentOptions->GetWindowWidth();
+ mWindowPositionSize.height = mEnvironmentOptions->GetWindowHeight();
+ }
}
- else if(mEnvironmentOptions.GetWindowWidth() && mEnvironmentOptions.GetWindowHeight())
+
+ auto windowClassName = mEnvironmentOptions->GetWindowClassName();
+ auto windowName = mEnvironmentOptions->GetWindowName();
+ if(!windowName.empty())
{
- // Environment options override full screen functionality if command line arguments not provided
- mWindowPositionSize.width = mEnvironmentOptions.GetWindowWidth();
- mWindowPositionSize.height = mEnvironmentOptions.GetWindowHeight();
+ mMainWindowName = windowName;
}
- }
- const std::string& windowClassName = mEnvironmentOptions.GetWindowClassName();
+ windowData.SetPositionSize(mWindowPositionSize);
+ window = Internal::Adaptor::Window::New(mMainWindowName, windowClassName, windowData);
+ }
+ else
+ {
+ // The position, size, window name, and frontbuffering of the pre-initialized application
+ // will be updated in ChangePreInitializedWindowInfo() when the real application is launched.
+ windowData.SetPositionSize(mWindowPositionSize);
+ window = Internal::Adaptor::Window::New("", "", windowData);
+ }
- Internal::Adaptor::Window* window = Internal::Adaptor::Window::New(mWindowPositionSize, mMainWindowName, windowClassName, mMainWindowMode == Dali::Application::TRANSPARENT);
- mMainWindow = Dali::Window(window);
+ mMainWindow = Dali::Window(window);
// Quit the application when the window is closed
GetImplementation(mMainWindow).DeleteRequestSignal().Connect(mSlotDelegate, &Application::Quit);
Integration::SceneHolder sceneHolder = Integration::SceneHolder(&Dali::GetImplementation(mMainWindow));
- mAdaptor = Adaptor::New(graphicsFactory, sceneHolder, &mEnvironmentOptions);
+ mAdaptor = Adaptor::New(graphicsFactory, sceneHolder, mEnvironmentOptions.get());
Adaptor::GetImplementation(*mAdaptor).SetUseRemoteSurface(mUseRemoteSurface);
}
void Application::CreateAdaptorBuilder()
{
- mAdaptorBuilder = new AdaptorBuilder(mEnvironmentOptions);
+ mAdaptorBuilder = new AdaptorBuilder(*mEnvironmentOptions);
}
void Application::MainLoop()
void Application::OnInit()
{
+ mEnvironmentOptions = std::unique_ptr<EnvironmentOptions>(new EnvironmentOptions());
+
mFramework->AddAbortCallback(MakeCallback(this, &Application::QuitFromMainLoop));
CreateAdaptorBuilder();
// If an application was pre-initialized, a window was made in advance
if(mLaunchpadState == Launchpad::NONE)
{
+ DALI_LOG_RELEASE_INFO("default Window is created in standalone");
CreateWindow();
}
if(mLaunchpadState == Launchpad::PRE_INITIALIZED)
{
- ChangePreInitializedWindowSize();
+ ChangePreInitializedWindowInfo();
}
// Run the adaptor
+ DALI_TRACE_BEGIN(gTraceFilter, "DALI_APP_ADAPTOR_START");
mAdaptor->Start();
+ DALI_TRACE_END(gTraceFilter, "DALI_APP_ADAPTOR_START");
Accessibility::Accessible::SetObjectRegistry(mAdaptor->GetObjectRegistry());
if(!mStylesheet.empty())
LanguageChangedSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnLanguageChanged);
Dali::Application application(this);
+
+ DALI_TRACE_BEGIN(gTraceFilter, "DALI_APP_EMIT_INIT_SIGNAL");
mInitSignal.Emit(application);
+ DALI_TRACE_END(gTraceFilter, "DALI_APP_EMIT_INIT_SIGNAL");
mAdaptor->NotifySceneCreated();
+
+ // Ensure the join of Font thread at this point
+ Dali::TextAbstraction::FontClientJoinFontThreads();
}
void Application::OnTerminate()
}
mMainWindow.Reset(); // This only resets (clears) the default Window
+
+ // If DALi's UI Thread works, some resources are created in UI Thread, not Main thread.
+ // For that case, these resource should be deleted in UI Thread.
+ if(mUseUiThread)
+ {
+ delete mAdaptor;
+ delete mAdaptorBuilder;
+ WindowSystem::Shutdown();
+ }
}
void Application::OnPause()
mLowMemorySignal.Emit(status);
}
+void Application::OnDeviceOrientationChanged(Dali::DeviceStatus::Orientation::Status status)
+{
+ Dali::Application application(this);
+ mDeviceOrientationChangedSignal.Emit(status);
+}
+
void Application::OnSurfaceCreated(Any newSurface)
{
void* newWindow = AnyCast<void*>(newSurface);
{
}
+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);
+}
+
+void Application::OnTaskDeviceOrientationChanged(Dali::DeviceStatus::Orientation::Status status)
+{
+ Dali::Application application(this);
+ mTaskDeviceOrientationChangedSignal.Emit(status);
+}
+
bool Application::AddIdle(CallbackBase* callback, bool hasReturnValue)
{
return mAdaptor->AddIdle(callback, hasReturnValue);
std::string Application::GetResourcePath()
{
- return Internal::Adaptor::Framework::GetResourcePath();
+ return SystemSettings::GetResourcePath();
}
std::string Application::GetDataPath()
{
- return Internal::Adaptor::Framework::GetDataPath();
+ return SystemSettings::GetDataPath();
+}
+
+void Application::FlushUpdateMessages()
+{
+ Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor).FlushUpdateMessages();
}
void Application::SetStyleSheet(const std::string& stylesheet)
mCommandLineOptions = new CommandLineOptions(argc, argv);
mFramework->SetCommandLineOptions(argc, argv);
+
+ if(argc && (*argc > 0))
+ {
+ // Set mName from command-line args
+ mMainWindowName = (*argv)[0];
+ }
}
-ApplicationPtr Application::GetPreInitializedApplication()
+void Application::SetDefaultWindowType(WindowType type)
+{
+ mDefaultWindowType = type;
+ mMainWindow.SetType(type);
+}
+
+int32_t Application::GetRenderThreadId() const
{
- return gPreInitializedApplication;
+ if(mAdaptor)
+ {
+ return Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor).GetRenderThreadId();
+ }
+ return 0;
}
-Graphics::Controller& Application::GetController()
+ApplicationPtr Application::GetPreInitializedApplication()
{
- auto& adaptor = Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor);
- return adaptor.GetGraphicsInterface().GetController();
+ // Reset the handle to decrease the reference count
+ ApplicationPtr application = gPreInitializedApplication;
+ gPreInitializedApplication.Reset();
+
+ return application;
}
} // namespace Adaptor