4e08ba12b1285800faac2904d6aff35e6eedddbc
[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()->Terminate();
242
243   mAdaptor->Stop();
244
245   mFramework->Quit();
246   // This will trigger OnTerminate(), below, after the main loop has completed.
247 }
248
249 void Application::OnInit()
250 {
251   mFramework->AddAbortCallback(MakeCallback(this, &Application::QuitFromMainLoop));
252
253   CreateAdaptorBuilder();
254   // If an application was pre-initialized, a window was made in advance
255   if(mLaunchpadState == Launchpad::NONE)
256   {
257     CreateWindow();
258   }
259
260   CreateAdaptor();
261
262   if(mLaunchpadState == Launchpad::PRE_INITIALIZED)
263   {
264     ChangePreInitializedWindowSize();
265   }
266
267   // Run the adaptor
268   mAdaptor->Start();
269   Accessibility::Accessible::SetObjectRegistry(mAdaptor->GetObjectRegistry());
270
271   if(!mStylesheet.empty())
272   {
273     Dali::StyleMonitor::Get().SetTheme(mStylesheet);
274   }
275
276   // Wire up the LifecycleController
277   Dali::LifecycleController lifecycleController = Dali::LifecycleController::Get();
278
279   InitSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnInit);
280   TerminateSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnTerminate);
281   PauseSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnPause);
282   ResumeSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnResume);
283   ResetSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnReset);
284   LanguageChangedSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnLanguageChanged);
285
286   Dali::Application application(this);
287   mInitSignal.Emit(application);
288
289   mAdaptor->NotifySceneCreated();
290 }
291
292 void Application::OnTerminate()
293 {
294   // We've been told to quit by AppCore, ecore_x_destroy has been called, need to quit synchronously
295   // delete the window as ecore_x has been destroyed by AppCore
296
297   Dali::Application application(this);
298   mTerminateSignal.Emit(application);
299
300   if(mAdaptor)
301   {
302     // Ensure that the render-thread is not using the surface(window) after we delete it
303     mAdaptor->Stop();
304   }
305
306   mMainWindow.Reset(); // This only resets (clears) the default Window
307 }
308
309 void Application::OnPause()
310 {
311   // A DALi app should handle Pause/Resume events.
312   // DALi just delivers the framework Pause event to the application, but not actually pause DALi core.
313   // Pausing DALi core only occurs on the Window Hidden framework event
314   Dali::Application application(this);
315   mPauseSignal.Emit(application);
316 }
317
318 void Application::OnResume()
319 {
320   // Emit the signal first so the application can queue any messages before we do an update/render
321   // This ensures we do not just redraw the last frame before pausing if that's not required
322   Dali::Application application(this);
323   mResumeSignal.Emit(application);
324
325   // DALi just delivers the framework Resume event to the application.
326   // Resuming DALi core only occurs on the Window Show framework event
327
328   // Trigger processing of events queued up while paused
329   CoreEventInterface& coreEventInterface = Internal::Adaptor::Adaptor::GetImplementation(GetAdaptor());
330   coreEventInterface.ProcessCoreEvents();
331 }
332
333 void Application::OnReset()
334 {
335   /*
336    * usually, reset callback was called when a caller request to launch this application via aul.
337    * because Application class already handled initialization in OnInit(), OnReset do nothing.
338    */
339   Dali::Application application(this);
340   mResetSignal.Emit(application);
341 }
342
343 void Application::OnAppControl(void* data)
344 {
345   Dali::Application application(this);
346   mAppControlSignal.Emit(application, data);
347 }
348
349 void Application::OnLanguageChanged()
350 {
351   mAdaptor->NotifyLanguageChanged();
352   Dali::Application application(this);
353   mLanguageChangedSignal.Emit(application);
354 }
355
356 void Application::OnRegionChanged()
357 {
358   Dali::Application application(this);
359   mRegionChangedSignal.Emit(application);
360 }
361
362 void Application::OnBatteryLow(Dali::DeviceStatus::Battery::Status status)
363 {
364   Dali::Application application(this);
365   mLowBatterySignal.Emit(status);
366 }
367
368 void Application::OnMemoryLow(Dali::DeviceStatus::Memory::Status status)
369 {
370   Dali::Application application(this);
371   mLowMemorySignal.Emit(status);
372 }
373
374 void Application::OnSurfaceCreated(Any newSurface)
375 {
376   void* newWindow = AnyCast<void*>(newSurface);
377   void* oldWindow = AnyCast<void*>(mMainWindow.GetNativeHandle());
378   if(oldWindow != newWindow)
379   {
380     auto                                 renderSurfaceFactory = Dali::Internal::Adaptor::GetRenderSurfaceFactory();
381     std::unique_ptr<WindowRenderSurface> newSurfacePtr        = renderSurfaceFactory->CreateWindowRenderSurface(PositionSize(), newSurface, true);
382
383     mAdaptor->ReplaceSurface(mMainWindow, *newSurfacePtr.release());
384   }
385 }
386
387 void Application::OnSurfaceDestroyed(Any surface)
388 {
389 }
390
391 bool Application::AddIdle(CallbackBase* callback, bool hasReturnValue)
392 {
393   return mAdaptor->AddIdle(callback, hasReturnValue);
394 }
395
396 std::string Application::GetRegion() const
397 {
398   return mFramework->GetRegion();
399 }
400
401 std::string Application::GetLanguage() const
402 {
403   return mFramework->GetLanguage();
404 }
405
406 Dali::ObjectRegistry Application::GetObjectRegistry() const
407 {
408   Dali::ObjectRegistry objectRegistry;
409   if(mAdaptor)
410   {
411     objectRegistry = mAdaptor->GetObjectRegistry();
412   }
413   return objectRegistry;
414 }
415
416 Dali::Adaptor& Application::GetAdaptor()
417 {
418   return *mAdaptor;
419 }
420
421 Dali::Window Application::GetWindow()
422 {
423   return mMainWindow;
424 }
425
426 std::string Application::GetResourcePath()
427 {
428   return Internal::Adaptor::Framework::GetResourcePath();
429 }
430
431 std::string Application::GetDataPath()
432 {
433   return Internal::Adaptor::Framework::GetDataPath();
434 }
435
436 void Application::SetStyleSheet(const std::string& stylesheet)
437 {
438   mStylesheet = stylesheet;
439 }
440
441 void Application::SetCommandLineOptions(int* argc, char** argv[])
442 {
443   delete mCommandLineOptions;
444
445   mCommandLineOptions = new CommandLineOptions(argc, argv);
446
447   mFramework->SetCommandLineOptions(argc, argv);
448 }
449
450 void Application::SetDefaultWindowType(WindowType type)
451 {
452   mDefaultWindowType = type;
453   mMainWindow.SetType(type);
454 }
455
456 ApplicationPtr Application::GetPreInitializedApplication()
457 {
458   // Reset the handle to decrease the reference count
459   ApplicationPtr application = gPreInitializedApplication;
460   gPreInitializedApplication.Reset();
461
462   return application;
463 }
464
465 Graphics::Controller& Application::GetController()
466 {
467   auto& adaptor = Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor);
468   return adaptor.GetGraphicsInterface().GetController();
469 }
470
471 } // namespace Adaptor
472
473 } // namespace Internal
474
475 } // namespace Dali