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