[dali_2.0.42] Merge branch 'devel/master'
[platform/core/uifw/dali-adaptor.git] / dali / internal / adaptor / common / application-impl.cpp
1 /*
2  * Copyright (c) 2021 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/public-api/object/object-registry.h>
25
26 // INTERNAL INCLUDES
27 #include <dali/devel-api/adaptor-framework/accessibility-impl.h>
28 #include <dali/devel-api/adaptor-framework/style-monitor.h>
29 #include <dali/devel-api/text-abstraction/font-client.h>
30 #include <dali/internal/adaptor/common/adaptor-impl.h>
31 #include <dali/internal/adaptor/common/framework.h>
32 #include <dali/internal/adaptor/common/lifecycle-controller-impl.h>
33 #include <dali/internal/system/common/command-line-options.h>
34 #include <dali/internal/window-system/common/render-surface-factory.h>
35 #include <dali/internal/window-system/common/window-impl.h>
36 #include <dali/internal/window-system/common/window-render-surface.h>
37 #include <dali/internal/window-system/common/window-system.h>
38
39 // To disable a macro with the same name from one of OpenGL headers
40 #undef Status
41
42 namespace Dali
43 {
44 namespace TizenPlatform
45 {
46 class TizenPlatformAbstraction;
47 }
48
49 namespace Integration
50 {
51 class Core;
52 }
53
54 namespace Internal
55 {
56 namespace Adaptor
57 {
58 ApplicationPtr Application::gPreInitializedApplication(NULL);
59
60 ApplicationPtr Application::New(
61   int*                           argc,
62   char**                         argv[],
63   const std::string&             stylesheet,
64   Dali::Application::WINDOW_MODE windowMode,
65   const PositionSize&            positionSize,
66   Framework::Type                applicationType,
67   WindowType                     type)
68 {
69   ApplicationPtr application(new Application(argc, argv, stylesheet, windowMode, positionSize, applicationType, type));
70   return application;
71 }
72
73 void Application::PreInitialize(int* argc, char** argv[])
74 {
75   if(!gPreInitializedApplication)
76   {
77     Dali::TextAbstraction::FontClientPreInitialize();
78
79     gPreInitializedApplication = new Application(argc, argv, "", Dali::Application::OPAQUE, PositionSize(), Framework::NORMAL, WindowType::NORMAL);
80     gPreInitializedApplication->CreateWindow(); // Only create window
81     gPreInitializedApplication->mLaunchpadState = Launchpad::PRE_INITIALIZED;
82   }
83 }
84
85 Application::Application(int* argc, char** argv[], const std::string& stylesheet, Dali::Application::WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType, WindowType type)
86 : mInitSignal(),
87   mTerminateSignal(),
88   mPauseSignal(),
89   mResumeSignal(),
90   mResetSignal(),
91   mAppControlSignal(),
92   mLanguageChangedSignal(),
93   mRegionChangedSignal(),
94   mEventLoop(nullptr),
95   mFramework(nullptr),
96   mCommandLineOptions(nullptr),
97   mAdaptorBuilder(nullptr),
98   mAdaptor(nullptr),
99   mMainWindow(),
100   mMainWindowMode(windowMode),
101   mMainWindowName(),
102   mStylesheet(stylesheet),
103   mEnvironmentOptions(),
104   mWindowPositionSize(positionSize),
105   mLaunchpadState(Launchpad::NONE),
106   mDefaultWindowType(type),
107   mSlotDelegate(this)
108 {
109   // Get mName from environment options
110   mMainWindowName = mEnvironmentOptions.GetWindowName();
111   if(mMainWindowName.empty() && argc && (*argc > 0))
112   {
113     // Set mName from command-line args if environment option not set
114     mMainWindowName = (*argv)[0];
115   }
116
117   mCommandLineOptions = new CommandLineOptions(argc, argv);
118   mFramework          = new Framework(*this, argc, argv, applicationType);
119   mUseRemoteSurface   = (applicationType == Framework::WATCH);
120 }
121
122 Application::~Application()
123 {
124   SingletonService service = SingletonService::Get();
125   // Note this can be false i.e. if Application has never created a Core instance
126   if(service)
127   {
128     service.UnregisterAll();
129   }
130
131   mMainWindow.Reset();
132   delete mAdaptor;
133   delete mAdaptorBuilder;
134   delete mCommandLineOptions;
135   delete mFramework;
136 }
137
138 void Application::StoreWindowPositionSize(PositionSize positionSize)
139 {
140   mWindowPositionSize = positionSize;
141 }
142
143 void Application::ChangePreInitializedWindowSize()
144 {
145   int screenWidth, screenHeight;
146   Dali::Internal::Adaptor::WindowSystem::GetScreenSize(screenWidth, screenHeight);
147
148   if(mWindowPositionSize != PositionSize(0, 0, 0, 0))
149   {
150     Dali::DevelWindow::SetPositionSize(mMainWindow, mWindowPositionSize);
151   }
152   else if(mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0)
153   {
154     // Command line options override environment options and full screen
155     mWindowPositionSize.width  = mCommandLineOptions->stageWidth;
156     mWindowPositionSize.height = mCommandLineOptions->stageHeight;
157     mMainWindow.SetSize(Dali::Window::WindowSize(mWindowPositionSize.width, mWindowPositionSize.height));
158   }
159   else if(mEnvironmentOptions.GetWindowWidth() && mEnvironmentOptions.GetWindowHeight())
160   {
161     // Environment options override full screen functionality if command line arguments not provided
162     mWindowPositionSize.width  = mEnvironmentOptions.GetWindowWidth();
163     mWindowPositionSize.height = mEnvironmentOptions.GetWindowHeight();
164     mMainWindow.SetSize(Dali::Window::WindowSize(mWindowPositionSize.width, mWindowPositionSize.height));
165   }
166   else if(screenWidth != mWindowPositionSize.width || screenHeight != mWindowPositionSize.height)
167   {
168     //Some apps can receive screen size differently after launching by specifying size in manifest.
169     mWindowPositionSize.width  = screenWidth;
170     mWindowPositionSize.height = screenHeight;
171     mMainWindow.SetSize(Dali::Window::WindowSize(mWindowPositionSize.width, mWindowPositionSize.height));
172   }
173 }
174
175 void Application::CreateWindow()
176 {
177   if(mWindowPositionSize.width == 0 && mWindowPositionSize.height == 0)
178   {
179     if(mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0)
180     {
181       // Command line options override environment options and full screen
182       mWindowPositionSize.width  = mCommandLineOptions->stageWidth;
183       mWindowPositionSize.height = mCommandLineOptions->stageHeight;
184     }
185     else if(mEnvironmentOptions.GetWindowWidth() && mEnvironmentOptions.GetWindowHeight())
186     {
187       // Environment options override full screen functionality if command line arguments not provided
188       mWindowPositionSize.width  = mEnvironmentOptions.GetWindowWidth();
189       mWindowPositionSize.height = mEnvironmentOptions.GetWindowHeight();
190     }
191   }
192
193   const std::string& windowClassName = mEnvironmentOptions.GetWindowClassName();
194
195   Internal::Adaptor::Window* window = Internal::Adaptor::Window::New(mWindowPositionSize, mMainWindowName, windowClassName, mDefaultWindowType, mMainWindowMode == Dali::Application::TRANSPARENT);
196   mMainWindow                       = Dali::Window(window);
197
198   // Quit the application when the window is closed
199   GetImplementation(mMainWindow).DeleteRequestSignal().Connect(mSlotDelegate, &Application::Quit);
200 }
201
202 void Application::CreateAdaptor()
203 {
204   DALI_ASSERT_ALWAYS(mMainWindow && "Window required to create adaptor");
205
206   auto graphicsFactory = mAdaptorBuilder->GetGraphicsFactory();
207
208   Integration::SceneHolder sceneHolder = Integration::SceneHolder(&Dali::GetImplementation(mMainWindow));
209
210   mAdaptor = Adaptor::New(graphicsFactory, sceneHolder, &mEnvironmentOptions);
211
212   Adaptor::GetImplementation(*mAdaptor).SetUseRemoteSurface(mUseRemoteSurface);
213 }
214
215 void Application::CreateAdaptorBuilder()
216 {
217   mAdaptorBuilder = new AdaptorBuilder(mEnvironmentOptions);
218 }
219
220 void Application::MainLoop()
221 {
222   // Run the application
223   mFramework->Run();
224 }
225
226 void Application::Lower()
227 {
228   // Lower the application without quitting it.
229   mMainWindow.Lower();
230 }
231
232 void Application::Quit()
233 {
234   // Actually quit the application.
235   // Force a call to Quit even if adaptor is not running.
236   Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor).AddIdle(MakeCallback(this, &Application::QuitFromMainLoop), false, true);
237 }
238
239 void Application::QuitFromMainLoop()
240 {
241   Accessibility::Bridge::GetCurrentBridge()->ApplicationHidden();
242   Accessibility::Bridge::GetCurrentBridge()->Terminate();
243
244   mAdaptor->Stop();
245
246   mFramework->Quit();
247   // This will trigger OnTerminate(), below, after the main loop has completed.
248 }
249
250 void Application::OnInit()
251 {
252   mFramework->AddAbortCallback(MakeCallback(this, &Application::QuitFromMainLoop));
253
254   CreateAdaptorBuilder();
255   // If an application was pre-initialized, a window was made in advance
256   if(mLaunchpadState == Launchpad::NONE)
257   {
258     CreateWindow();
259   }
260
261   CreateAdaptor();
262
263   if(mLaunchpadState == Launchpad::PRE_INITIALIZED)
264   {
265     ChangePreInitializedWindowSize();
266   }
267
268   // Run the adaptor
269   mAdaptor->Start();
270   Accessibility::Accessible::SetObjectRegistry(mAdaptor->GetObjectRegistry());
271
272   if(!mStylesheet.empty())
273   {
274     Dali::StyleMonitor::Get().SetTheme(mStylesheet);
275   }
276
277   // Wire up the LifecycleController
278   Dali::LifecycleController lifecycleController = Dali::LifecycleController::Get();
279
280   InitSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnInit);
281   TerminateSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnTerminate);
282   PauseSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnPause);
283   ResumeSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnResume);
284   ResetSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnReset);
285   LanguageChangedSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnLanguageChanged);
286
287   Dali::Application application(this);
288   mInitSignal.Emit(application);
289
290   mAdaptor->NotifySceneCreated();
291 }
292
293 void Application::OnTerminate()
294 {
295   // We've been told to quit by AppCore, ecore_x_destroy has been called, need to quit synchronously
296   // delete the window as ecore_x has been destroyed by AppCore
297
298   Dali::Application application(this);
299   mTerminateSignal.Emit(application);
300
301   if(mAdaptor)
302   {
303     // Ensure that the render-thread is not using the surface(window) after we delete it
304     mAdaptor->Stop();
305   }
306
307   mMainWindow.Reset(); // This only resets (clears) the default Window
308 }
309
310 void Application::OnPause()
311 {
312   // A DALi app should handle Pause/Resume events.
313   // DALi just delivers the framework Pause event to the application, but not actually pause DALi core.
314   // Pausing DALi core only occurs on the Window Hidden framework event
315   Dali::Application application(this);
316   mPauseSignal.Emit(application);
317 }
318
319 void Application::OnResume()
320 {
321   // Emit the signal first so the application can queue any messages before we do an update/render
322   // This ensures we do not just redraw the last frame before pausing if that's not required
323   Dali::Application application(this);
324   mResumeSignal.Emit(application);
325
326   // DALi just delivers the framework Resume event to the application.
327   // Resuming DALi core only occurs on the Window Show framework event
328
329   // Trigger processing of events queued up while paused
330   CoreEventInterface& coreEventInterface = Internal::Adaptor::Adaptor::GetImplementation(GetAdaptor());
331   coreEventInterface.ProcessCoreEvents();
332 }
333
334 void Application::OnReset()
335 {
336   /*
337    * usually, reset callback was called when a caller request to launch this application via aul.
338    * because Application class already handled initialization in OnInit(), OnReset do nothing.
339    */
340   Dali::Application application(this);
341   mResetSignal.Emit(application);
342 }
343
344 void Application::OnAppControl(void* data)
345 {
346   Dali::Application application(this);
347   mAppControlSignal.Emit(application, data);
348 }
349
350 void Application::OnLanguageChanged()
351 {
352   mAdaptor->NotifyLanguageChanged();
353   Dali::Application application(this);
354   mLanguageChangedSignal.Emit(application);
355 }
356
357 void Application::OnRegionChanged()
358 {
359   Dali::Application application(this);
360   mRegionChangedSignal.Emit(application);
361 }
362
363 void Application::OnBatteryLow(Dali::DeviceStatus::Battery::Status status)
364 {
365   Dali::Application application(this);
366   mLowBatterySignal.Emit(status);
367 }
368
369 void Application::OnMemoryLow(Dali::DeviceStatus::Memory::Status status)
370 {
371   Dali::Application application(this);
372   mLowMemorySignal.Emit(status);
373 }
374
375 void Application::OnSurfaceCreated(Any newSurface)
376 {
377   void* newWindow = AnyCast<void*>(newSurface);
378   void* oldWindow = AnyCast<void*>(mMainWindow.GetNativeHandle());
379   if(oldWindow != newWindow)
380   {
381     auto                                 renderSurfaceFactory = Dali::Internal::Adaptor::GetRenderSurfaceFactory();
382     std::unique_ptr<WindowRenderSurface> newSurfacePtr        = renderSurfaceFactory->CreateWindowRenderSurface(PositionSize(), newSurface, true);
383
384     mAdaptor->ReplaceSurface(mMainWindow, *newSurfacePtr.release());
385   }
386 }
387
388 void Application::OnSurfaceDestroyed(Any surface)
389 {
390 }
391
392 bool Application::AddIdle(CallbackBase* callback, bool hasReturnValue)
393 {
394   return mAdaptor->AddIdle(callback, hasReturnValue);
395 }
396
397 std::string Application::GetRegion() const
398 {
399   return mFramework->GetRegion();
400 }
401
402 std::string Application::GetLanguage() const
403 {
404   return mFramework->GetLanguage();
405 }
406
407 Dali::ObjectRegistry Application::GetObjectRegistry() const
408 {
409   Dali::ObjectRegistry objectRegistry;
410   if(mAdaptor)
411   {
412     objectRegistry = mAdaptor->GetObjectRegistry();
413   }
414   return objectRegistry;
415 }
416
417 Dali::Adaptor& Application::GetAdaptor()
418 {
419   return *mAdaptor;
420 }
421
422 Dali::Window Application::GetWindow()
423 {
424   return mMainWindow;
425 }
426
427 std::string Application::GetResourcePath()
428 {
429   return Internal::Adaptor::Framework::GetResourcePath();
430 }
431
432 std::string Application::GetDataPath()
433 {
434   return Internal::Adaptor::Framework::GetDataPath();
435 }
436
437 void Application::SetStyleSheet(const std::string& stylesheet)
438 {
439   mStylesheet = stylesheet;
440 }
441
442 void Application::SetCommandLineOptions(int* argc, char** argv[])
443 {
444   delete mCommandLineOptions;
445
446   mCommandLineOptions = new CommandLineOptions(argc, argv);
447
448   mFramework->SetCommandLineOptions(argc, argv);
449 }
450
451 void Application::SetDefaultWindowType(WindowType type)
452 {
453   mDefaultWindowType = type;
454   mMainWindow.SetType(type);
455 }
456
457 ApplicationPtr Application::GetPreInitializedApplication()
458 {
459   return gPreInitializedApplication;
460 }
461
462 Graphics::Controller& Application::GetController()
463 {
464   auto& adaptor = Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor);
465   return adaptor.GetGraphicsInterface().GetController();
466 }
467
468 } // namespace Adaptor
469
470 } // namespace Internal
471
472 } // namespace Dali