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