[dali_2.3.23] Merge branch 'devel/master'
[platform/core/uifw/dali-adaptor.git] / dali / internal / adaptor / common / application-impl.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/adaptor/common/application-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/common/singleton-service.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/integration-api/trace.h>
25 #include <dali/public-api/object/object-registry.h>
26
27 // INTERNAL INCLUDES
28 #include <dali/devel-api/adaptor-framework/accessibility-bridge.h>
29 #include <dali/devel-api/adaptor-framework/environment-variable.h>
30 #include <dali/devel-api/adaptor-framework/style-monitor.h>
31 #include <dali/devel-api/atspi-interfaces/accessible.h>
32 #include <dali/devel-api/text-abstraction/font-client.h>
33 #include <dali/internal/adaptor/common/adaptor-impl.h>
34 #include <dali/internal/adaptor/common/framework-factory.h>
35 #include <dali/internal/adaptor/common/framework.h>
36 #include <dali/internal/adaptor/common/lifecycle-controller-impl.h>
37 #include <dali/internal/system/common/command-line-options.h>
38 #include <dali/internal/system/common/environment-variables.h>
39 #include <dali/internal/system/common/system-settings.h>
40 #include <dali/internal/window-system/common/render-surface-factory.h>
41 #include <dali/internal/window-system/common/window-impl.h>
42 #include <dali/internal/window-system/common/window-render-surface.h>
43 #include <dali/internal/window-system/common/window-system.h>
44
45 // To disable a macro with the same name from one of OpenGL headers
46 #undef Status
47
48 namespace Dali
49 {
50 namespace TizenPlatform
51 {
52 class TizenPlatformAbstraction;
53 }
54
55 namespace Integration
56 {
57 class Core;
58 }
59
60 namespace Internal
61 {
62 namespace Adaptor
63 {
64 DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_APPLICATION, true);
65
66 ApplicationPtr Application::gPreInitializedApplication(NULL);
67
68 ApplicationPtr Application::New(
69   int*               argc,
70   char**             argv[],
71   const std::string& stylesheet,
72   Framework::Type    applicationType,
73   bool               useUiThread,
74   const WindowData&  windowData)
75 {
76   ApplicationPtr application(new Application(argc, argv, stylesheet, applicationType, useUiThread, windowData));
77   return application;
78 }
79
80 void Application::PreInitialize(int* argc, char** argv[])
81 {
82   if(!gPreInitializedApplication)
83   {
84     bool isUseUIThread = false;
85
86 #ifdef UI_THREAD_AVAILABLE
87     char* retEnv = std::getenv("TIZEN_UI_THREAD");
88     if(retEnv)
89     {
90       std::string uiThreadEnv   = retEnv;
91       std::string enabledString = "true";
92       if(uiThreadEnv == enabledString)
93       {
94         isUseUIThread = true;
95       }
96     }
97 #endif
98
99     Dali::TextAbstraction::FontClientPreInitialize();
100     WindowData windowData;
101     gPreInitializedApplication                  = new Application(argc, argv, "", Framework::NORMAL, isUseUIThread, windowData);
102     gPreInitializedApplication->mLaunchpadState = Launchpad::PRE_INITIALIZED;
103
104 #ifdef UI_THREAD_AVAILABLE
105     if(isUseUIThread)
106     {
107       DALI_LOG_RELEASE_INFO("PRE_INITIALIZED with UI Threading");
108       gPreInitializedApplication->mUIThreadLoader = new UIThreadLoader(argc, argv);
109       gPreInitializedApplication->mUIThreadLoader->Run([&]() { gPreInitializedApplication->CreateWindow(); });
110     }
111     else
112 #endif
113     {
114       DALI_LOG_RELEASE_INFO("Only PRE_INITIALIZED");
115       gPreInitializedApplication->CreateWindow(); // Only create window
116     }
117   }
118 }
119
120 Application::Application(int* argc, char** argv[], const std::string& stylesheet, Framework::Type applicationType, bool useUiThread, const WindowData& windowData)
121 : mInitSignal(),
122   mTerminateSignal(),
123   mPauseSignal(),
124   mResumeSignal(),
125   mResetSignal(),
126   mAppControlSignal(),
127   mLanguageChangedSignal(),
128   mRegionChangedSignal(),
129   mFramework(nullptr),
130   mFrameworkFactory(nullptr),
131   mCommandLineOptions(nullptr),
132   mAdaptorBuilder(nullptr),
133   mAdaptor(nullptr),
134   mEnvironmentOptions(nullptr),
135   mMainWindow(),
136   mMainWindowMode(windowData.GetTransparency() ? WINDOW_MODE::TRANSPARENT : WINDOW_MODE::OPAQUE),
137   mMainWindowName(),
138   mIsMainWindowFrontBufferRendering(windowData.GetFrontBufferRendering()),
139   mStylesheet(stylesheet),
140   mWindowPositionSize(windowData.GetPositionSize()),
141   mLaunchpadState(Launchpad::NONE),
142   mDefaultWindowType(windowData.GetWindowType()),
143   mUseUiThread(useUiThread),
144   mIsSystemInitialized(false),
145   mSlotDelegate(this),
146   mUIThreadLoader(nullptr)
147 {
148   // Set mName from command-line args
149   if(argc && (*argc > 0))
150   {
151     mMainWindowName = (*argv)[0];
152   }
153
154   const char* uiThreadEnabled = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_ENABLE_UI_THREAD);
155   if(uiThreadEnabled && std::atoi(uiThreadEnabled) != 0)
156   {
157     mUseUiThread = true;
158   }
159
160   mCommandLineOptions = new CommandLineOptions(argc, argv);
161
162   mFrameworkFactory = std::unique_ptr<FrameworkFactory>(Dali::Internal::Adaptor::CreateFrameworkFactory());
163   mFramework        = mFrameworkFactory->CreateFramework(FrameworkBackend::DEFAULT, *this, *this, argc, argv, applicationType, mUseUiThread);
164
165   mUseRemoteSurface = (applicationType == Framework::WATCH);
166 }
167
168 Application::~Application()
169 {
170   SingletonService service = SingletonService::Get();
171   // Note this can be false i.e. if Application has never created a Core instance
172   if(service)
173   {
174     service.UnregisterAll();
175   }
176
177   mMainWindow.Reset();
178
179   delete mCommandLineOptions;
180
181   // Application is created in Main thread whether UI Threading is enabled or not.
182   // But some resources are created in Main thread or UI thread.
183   // The below code is for the resource are created in Main thread.
184   if(!mUseUiThread)
185   {
186     delete mAdaptor;
187     delete mAdaptorBuilder;
188     if(mIsSystemInitialized)
189     {
190       WindowSystem::Shutdown();
191     }
192   }
193   else
194   {
195     if(mUIThreadLoader)
196     {
197       delete mUIThreadLoader;
198     }
199   }
200 }
201
202 void Application::StoreWindowPositionSize(PositionSize positionSize)
203 {
204   mWindowPositionSize = positionSize;
205 }
206
207 void Application::StoreFrontBufferRendering(bool enable)
208 {
209   mIsMainWindowFrontBufferRendering = enable;
210 }
211
212 void Application::ChangePreInitializedWindowInfo()
213 {
214   // Set window name
215   auto windowClassName = mEnvironmentOptions->GetWindowClassName();
216   auto windowName      = mEnvironmentOptions->GetWindowName();
217   if(!windowName.empty())
218   {
219     mMainWindowName = windowName;
220   }
221   mMainWindow.SetClass(mMainWindowName, windowClassName);
222
223   // The real screen size may be different from the value of the preinitialized state. Update it.
224   Dali::Internal::Adaptor::WindowSystem::UpdateScreenSize();
225
226   int screenWidth, screenHeight;
227   Dali::Internal::Adaptor::WindowSystem::GetScreenSize(screenWidth, screenHeight);
228
229   // Set window position / size
230   if(mWindowPositionSize != PositionSize(0, 0, 0, 0))
231   {
232     Dali::DevelWindow::SetPositionSize(mMainWindow, mWindowPositionSize);
233   }
234   else if(mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0)
235   {
236     // Command line options override environment options and full screen
237     mWindowPositionSize.width  = mCommandLineOptions->stageWidth;
238     mWindowPositionSize.height = mCommandLineOptions->stageHeight;
239     mMainWindow.SetSize(Dali::Window::WindowSize(mWindowPositionSize.width, mWindowPositionSize.height));
240   }
241   else if(mEnvironmentOptions->GetWindowWidth() && mEnvironmentOptions->GetWindowHeight())
242   {
243     // Environment options override full screen functionality if command line arguments not provided
244     mWindowPositionSize.width  = mEnvironmentOptions->GetWindowWidth();
245     mWindowPositionSize.height = mEnvironmentOptions->GetWindowHeight();
246     mMainWindow.SetSize(Dali::Window::WindowSize(mWindowPositionSize.width, mWindowPositionSize.height));
247   }
248   else if(screenWidth != mWindowPositionSize.width || screenHeight != mWindowPositionSize.height)
249   {
250     // Some apps can receive screen size differently after launching by specifying size in manifest.
251     mWindowPositionSize.width  = screenWidth;
252     mWindowPositionSize.height = screenHeight;
253     mMainWindow.SetSize(Dali::Window::WindowSize(mWindowPositionSize.width, mWindowPositionSize.height));
254   }
255
256   // Set front buffer rendering
257   Dali::DevelWindow::SetFrontBufferRendering(mMainWindow, mIsMainWindowFrontBufferRendering);
258 }
259
260 void Application::CreateWindow()
261 {
262   Internal::Adaptor::Window* window;
263   WindowData                 windowData;
264   windowData.SetTransparency(mMainWindowMode);
265   windowData.SetWindowType(mDefaultWindowType);
266   windowData.SetFrontBufferRendering(mIsMainWindowFrontBufferRendering);
267
268   DALI_LOG_RELEASE_INFO("Create Default Window");
269
270   WindowSystem::Initialize();
271   mIsSystemInitialized = true;
272
273   if(mLaunchpadState != Launchpad::PRE_INITIALIZED)
274   {
275     if(mWindowPositionSize.width == 0 && mWindowPositionSize.height == 0)
276     {
277       if(mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0)
278       {
279         // Command line options override environment options and full screen
280         mWindowPositionSize.width  = mCommandLineOptions->stageWidth;
281         mWindowPositionSize.height = mCommandLineOptions->stageHeight;
282       }
283       else if(mEnvironmentOptions->GetWindowWidth() && mEnvironmentOptions->GetWindowHeight())
284       {
285         // Environment options override full screen functionality if command line arguments not provided
286         mWindowPositionSize.width  = mEnvironmentOptions->GetWindowWidth();
287         mWindowPositionSize.height = mEnvironmentOptions->GetWindowHeight();
288       }
289     }
290
291     auto windowClassName = mEnvironmentOptions->GetWindowClassName();
292     auto windowName      = mEnvironmentOptions->GetWindowName();
293     if(!windowName.empty())
294     {
295       mMainWindowName = windowName;
296     }
297
298     windowData.SetPositionSize(mWindowPositionSize);
299     window = Internal::Adaptor::Window::New(mMainWindowName, windowClassName, windowData);
300   }
301   else
302   {
303     // The position, size, window name, and frontbuffering of the pre-initialized application
304     // will be updated in ChangePreInitializedWindowInfo() when the real application is launched.
305     windowData.SetPositionSize(mWindowPositionSize);
306     window = Internal::Adaptor::Window::New("", "", windowData);
307   }
308
309   mMainWindow = Dali::Window(window);
310
311   // Quit the application when the window is closed
312   GetImplementation(mMainWindow).DeleteRequestSignal().Connect(mSlotDelegate, &Application::Quit);
313 }
314
315 void Application::CreateAdaptor()
316 {
317   DALI_ASSERT_ALWAYS(mMainWindow && "Window required to create adaptor");
318
319   auto graphicsFactory = mAdaptorBuilder->GetGraphicsFactory();
320
321   Integration::SceneHolder sceneHolder = Integration::SceneHolder(&Dali::GetImplementation(mMainWindow));
322
323   mAdaptor = Adaptor::New(graphicsFactory, sceneHolder, mEnvironmentOptions.get());
324
325   Adaptor::GetImplementation(*mAdaptor).SetUseRemoteSurface(mUseRemoteSurface);
326 }
327
328 void Application::CreateAdaptorBuilder()
329 {
330   mAdaptorBuilder = new AdaptorBuilder(*mEnvironmentOptions);
331 }
332
333 void Application::MainLoop()
334 {
335   // Run the application
336   mFramework->Run();
337 }
338
339 void Application::Lower()
340 {
341   // Lower the application without quitting it.
342   mMainWindow.Lower();
343 }
344
345 void Application::Quit()
346 {
347   // Actually quit the application.
348   // Force a call to Quit even if adaptor is not running.
349   Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor).AddIdle(MakeCallback(this, &Application::QuitFromMainLoop), false);
350 }
351
352 void Application::QuitFromMainLoop()
353 {
354   Accessibility::Bridge::GetCurrentBridge()->Terminate();
355
356   mAdaptor->Stop();
357
358   mFramework->Quit();
359   // This will trigger OnTerminate(), below, after the main loop has completed.
360 }
361
362 void Application::OnInit()
363 {
364   mEnvironmentOptions = std::unique_ptr<EnvironmentOptions>(new EnvironmentOptions());
365
366   mFramework->AddAbortCallback(MakeCallback(this, &Application::QuitFromMainLoop));
367
368   CreateAdaptorBuilder();
369   // If an application was pre-initialized, a window was made in advance
370   if(mLaunchpadState == Launchpad::NONE)
371   {
372     DALI_LOG_RELEASE_INFO("default Window is created in standalone");
373     CreateWindow();
374   }
375
376   CreateAdaptor();
377
378   if(mLaunchpadState == Launchpad::PRE_INITIALIZED)
379   {
380     ChangePreInitializedWindowInfo();
381   }
382
383   // Run the adaptor
384   DALI_TRACE_BEGIN(gTraceFilter, "DALI_APP_ADAPTOR_START");
385   mAdaptor->Start();
386   DALI_TRACE_END(gTraceFilter, "DALI_APP_ADAPTOR_START");
387   Accessibility::Accessible::SetObjectRegistry(mAdaptor->GetObjectRegistry());
388
389   if(!mStylesheet.empty())
390   {
391     Dali::StyleMonitor::Get().SetTheme(mStylesheet);
392   }
393
394   // Wire up the LifecycleController
395   Dali::LifecycleController lifecycleController = Dali::LifecycleController::Get();
396
397   InitSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnInit);
398   TerminateSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnTerminate);
399   PauseSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnPause);
400   ResumeSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnResume);
401   ResetSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnReset);
402   LanguageChangedSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnLanguageChanged);
403
404   Dali::Application application(this);
405
406   DALI_TRACE_BEGIN(gTraceFilter, "DALI_APP_EMIT_INIT_SIGNAL");
407   mInitSignal.Emit(application);
408   DALI_TRACE_END(gTraceFilter, "DALI_APP_EMIT_INIT_SIGNAL");
409
410   mAdaptor->NotifySceneCreated();
411
412   // Ensure the join of Font thread at this point
413   Dali::TextAbstraction::FontClientJoinFontThreads();
414 }
415
416 void Application::OnTerminate()
417 {
418   // We've been told to quit by AppCore, ecore_x_destroy has been called, need to quit synchronously
419   // delete the window as ecore_x has been destroyed by AppCore
420
421   Dali::Application application(this);
422   mTerminateSignal.Emit(application);
423
424   if(mAdaptor)
425   {
426     // Ensure that the render-thread is not using the surface(window) after we delete it
427     mAdaptor->Stop();
428   }
429
430   mMainWindow.Reset(); // This only resets (clears) the default Window
431
432   // If DALi's UI Thread works, some resources are created in UI Thread, not Main thread.
433   // For that case, these resource should be deleted in UI Thread.
434   if(mUseUiThread)
435   {
436     delete mAdaptor;
437     delete mAdaptorBuilder;
438     WindowSystem::Shutdown();
439   }
440 }
441
442 void Application::OnPause()
443 {
444   // A DALi app should handle Pause/Resume events.
445   // DALi just delivers the framework Pause event to the application, but not actually pause DALi core.
446   // Pausing DALi core only occurs on the Window Hidden framework event
447   Dali::Application application(this);
448   mPauseSignal.Emit(application);
449 }
450
451 void Application::OnResume()
452 {
453   // Emit the signal first so the application can queue any messages before we do an update/render
454   // This ensures we do not just redraw the last frame before pausing if that's not required
455   Dali::Application application(this);
456   mResumeSignal.Emit(application);
457
458   // DALi just delivers the framework Resume event to the application.
459   // Resuming DALi core only occurs on the Window Show framework event
460
461   // Trigger processing of events queued up while paused
462   CoreEventInterface& coreEventInterface = Internal::Adaptor::Adaptor::GetImplementation(GetAdaptor());
463   coreEventInterface.ProcessCoreEvents();
464 }
465
466 void Application::OnReset()
467 {
468   /*
469    * usually, reset callback was called when a caller request to launch this application via aul.
470    * because Application class already handled initialization in OnInit(), OnReset do nothing.
471    */
472   Dali::Application application(this);
473   mResetSignal.Emit(application);
474 }
475
476 void Application::OnAppControl(void* data)
477 {
478   Dali::Application application(this);
479   mAppControlSignal.Emit(application, data);
480 }
481
482 void Application::OnLanguageChanged()
483 {
484   mAdaptor->NotifyLanguageChanged();
485   Dali::Application application(this);
486   mLanguageChangedSignal.Emit(application);
487 }
488
489 void Application::OnRegionChanged()
490 {
491   Dali::Application application(this);
492   mRegionChangedSignal.Emit(application);
493 }
494
495 void Application::OnBatteryLow(Dali::DeviceStatus::Battery::Status status)
496 {
497   Dali::Application application(this);
498   mLowBatterySignal.Emit(status);
499 }
500
501 void Application::OnMemoryLow(Dali::DeviceStatus::Memory::Status status)
502 {
503   Dali::Application application(this);
504   mLowMemorySignal.Emit(status);
505 }
506
507 void Application::OnDeviceOrientationChanged(Dali::DeviceStatus::Orientation::Status status)
508 {
509   Dali::Application application(this);
510   mDeviceOrientationChangedSignal.Emit(status);
511 }
512
513 void Application::OnSurfaceCreated(Any newSurface)
514 {
515   void* newWindow = AnyCast<void*>(newSurface);
516   void* oldWindow = AnyCast<void*>(mMainWindow.GetNativeHandle());
517   if(oldWindow != newWindow)
518   {
519     auto                                 renderSurfaceFactory = Dali::Internal::Adaptor::GetRenderSurfaceFactory();
520     std::unique_ptr<WindowRenderSurface> newSurfacePtr        = renderSurfaceFactory->CreateWindowRenderSurface(PositionSize(), newSurface, true);
521
522     mAdaptor->ReplaceSurface(mMainWindow, *newSurfacePtr.release());
523   }
524 }
525
526 void Application::OnSurfaceDestroyed(Any surface)
527 {
528 }
529
530 void Application::OnTaskInit()
531 {
532   Dali::Application application(this);
533   mTaskInitSignal.Emit(application);
534 }
535
536 void Application::OnTaskTerminate()
537 {
538   Dali::Application application(this);
539   mTaskTerminateSignal.Emit(application);
540 }
541
542 void Application::OnTaskAppControl(void* data)
543 {
544   Dali::Application application(this);
545   mTaskAppControlSignal.Emit(application, data);
546 }
547
548 void Application::OnTaskLanguageChanged()
549 {
550   Dali::Application application(this);
551   mTaskLanguageChangedSignal.Emit(application);
552 }
553
554 void Application::OnTaskRegionChanged()
555 {
556   Dali::Application application(this);
557   mTaskRegionChangedSignal.Emit(application);
558 }
559
560 void Application::OnTaskBatteryLow(Dali::DeviceStatus::Battery::Status status)
561 {
562   Dali::Application application(this);
563   mTaskLowBatterySignal.Emit(status);
564 }
565
566 void Application::OnTaskMemoryLow(Dali::DeviceStatus::Memory::Status status)
567 {
568   Dali::Application application(this);
569   mTaskLowMemorySignal.Emit(status);
570 }
571
572 void Application::OnTaskDeviceOrientationChanged(Dali::DeviceStatus::Orientation::Status status)
573 {
574   Dali::Application application(this);
575   mTaskDeviceOrientationChangedSignal.Emit(status);
576 }
577
578 bool Application::AddIdle(CallbackBase* callback, bool hasReturnValue)
579 {
580   return mAdaptor->AddIdle(callback, hasReturnValue);
581 }
582
583 std::string Application::GetRegion() const
584 {
585   return mFramework->GetRegion();
586 }
587
588 std::string Application::GetLanguage() const
589 {
590   return mFramework->GetLanguage();
591 }
592
593 Dali::ObjectRegistry Application::GetObjectRegistry() const
594 {
595   Dali::ObjectRegistry objectRegistry;
596   if(mAdaptor)
597   {
598     objectRegistry = mAdaptor->GetObjectRegistry();
599   }
600   return objectRegistry;
601 }
602
603 Dali::Adaptor& Application::GetAdaptor()
604 {
605   return *mAdaptor;
606 }
607
608 Dali::Window Application::GetWindow()
609 {
610   return mMainWindow;
611 }
612
613 std::string Application::GetResourcePath()
614 {
615   return SystemSettings::GetResourcePath();
616 }
617
618 std::string Application::GetDataPath()
619 {
620   return SystemSettings::GetDataPath();
621 }
622
623 void Application::FlushUpdateMessages()
624 {
625   Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor).FlushUpdateMessages();
626 }
627
628 void Application::SetStyleSheet(const std::string& stylesheet)
629 {
630   mStylesheet = stylesheet;
631 }
632
633 void Application::SetCommandLineOptions(int* argc, char** argv[])
634 {
635   delete mCommandLineOptions;
636
637   mCommandLineOptions = new CommandLineOptions(argc, argv);
638
639   mFramework->SetCommandLineOptions(argc, argv);
640
641   if(argc && (*argc > 0))
642   {
643     // Set mName from command-line args
644     mMainWindowName = (*argv)[0];
645   }
646 }
647
648 void Application::SetDefaultWindowType(WindowType type)
649 {
650   mDefaultWindowType = type;
651   mMainWindow.SetType(type);
652 }
653
654 int32_t Application::GetRenderThreadId() const
655 {
656   if(mAdaptor)
657   {
658     return Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor).GetRenderThreadId();
659   }
660   return 0;
661 }
662
663 ApplicationPtr Application::GetPreInitializedApplication()
664 {
665   // Reset the handle to decrease the reference count
666   ApplicationPtr application = gPreInitializedApplication;
667   gPreInitializedApplication.Reset();
668
669   return application;
670 }
671
672 } // namespace Adaptor
673
674 } // namespace Internal
675
676 } // namespace Dali