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