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