Merge "Use existing callback ID for recurring callbacks" into devel/master
[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/devel-api/adaptor-framework/accessibility-impl.h>
30 #include <dali/internal/adaptor/common/adaptor-impl.h>
31 #include <dali/internal/system/common/command-line-options.h>
32 #include <dali/internal/adaptor/common/framework.h>
33 #include <dali/internal/adaptor/common/lifecycle-controller-impl.h>
34 #include <dali/internal/window-system/common/window-impl.h>
35 #include <dali/internal/window-system/common/window-render-surface.h>
36 #include <dali/internal/window-system/common/render-surface-factory.h>
37
38 // To disable a macro with the same name from one of OpenGL headers
39 #undef Status
40
41 namespace Dali
42 {
43
44 namespace TizenPlatform
45 {
46 class TizenPlatformAbstraction;
47 }
48
49 namespace Integration
50 {
51 class Core;
52 }
53
54 namespace Internal
55 {
56
57 namespace Adaptor
58 {
59
60 ApplicationPtr Application::gPreInitializedApplication( NULL );
61
62 ApplicationPtr Application::New(
63   int* argc,
64   char **argv[],
65   const std::string& stylesheet,
66   Dali::Application::WINDOW_MODE windowMode,
67   const PositionSize& positionSize,
68   Framework::Type applicationType)
69 {
70   ApplicationPtr application ( new Application (argc, argv, stylesheet, windowMode, positionSize, applicationType ) );
71   return application;
72 }
73
74 void Application::PreInitialize( int* argc, char** argv[] )
75 {
76   if( !gPreInitializedApplication )
77   {
78     Dali::TextAbstraction::FontClientPreInitialize();
79
80     gPreInitializedApplication = new Application ( argc, argv, "", Dali::Application::OPAQUE, PositionSize(), Framework::NORMAL );
81     gPreInitializedApplication->CreateWindow();    // Only create window
82     gPreInitializedApplication->mLaunchpadState = Launchpad::PRE_INITIALIZED;
83   }
84 }
85
86 Application::Application( int* argc, char** argv[], const std::string& stylesheet,
87   Dali::Application::WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType )
88 : mInitSignal(),
89   mTerminateSignal(),
90   mPauseSignal(),
91   mResumeSignal(),
92   mResetSignal(),
93   mAppControlSignal(),
94   mLanguageChangedSignal(),
95   mRegionChangedSignal(),
96   mEventLoop( nullptr ),
97   mFramework( nullptr ),
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, &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()
185 {
186   // Run the application
187   mFramework->Run();
188 }
189
190 void Application::Lower()
191 {
192   // Lower the application without quitting it.
193   mMainWindow.Lower();
194 }
195
196 void Application::Quit()
197 {
198   // Actually quit the application.
199   // Force a call to Quit even if adaptor is not running.
200   Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor).AddIdle( MakeCallback( this, &Application::QuitFromMainLoop ), false, true );
201 }
202
203 void Application::QuitFromMainLoop()
204 {
205   Accessibility::Bridge::GetCurrentBridge()->Terminate();
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   Accessibility::Accessible::SetObjectRegistry(mAdaptor->GetObjectRegistry());
229
230   if( ! mStylesheet.empty() )
231   {
232     Dali::StyleMonitor::Get().SetTheme( mStylesheet );
233   }
234
235   // Wire up the LifecycleController
236   Dali::LifecycleController lifecycleController = Dali::LifecycleController::Get();
237
238   InitSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnInit );
239   TerminateSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnTerminate );
240   PauseSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnPause );
241   ResumeSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnResume );
242   ResetSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnReset );
243   LanguageChangedSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnLanguageChanged );
244
245   Dali::Application application(this);
246   mInitSignal.Emit( application );
247
248   mAdaptor->NotifySceneCreated();
249 }
250
251 void Application::OnTerminate()
252 {
253   // We've been told to quit by AppCore, ecore_x_destroy has been called, need to quit synchronously
254   // delete the window as ecore_x has been destroyed by AppCore
255
256   Dali::Application application(this);
257   mTerminateSignal.Emit( application );
258
259   if( mAdaptor )
260   {
261     // Ensure that the render-thread is not using the surface(window) after we delete it
262     mAdaptor->Stop();
263   }
264
265   mMainWindow.Reset(); // This only resets (clears) the default Window
266 }
267
268 void Application::OnPause()
269 {
270   // A DALi app should handle Pause/Resume events.
271   // DALi just delivers the framework Pause event to the application, but not actually pause DALi core.
272   // Pausing DALi core only occurs on the Window Hidden framework event
273   Dali::Application application(this);
274   mPauseSignal.Emit( application );
275 }
276
277 void Application::OnResume()
278 {
279   // Emit the signal first so the application can queue any messages before we do an update/render
280   // This ensures we do not just redraw the last frame before pausing if that's not required
281   Dali::Application application(this);
282   mResumeSignal.Emit( application );
283
284   // DALi just delivers the framework Resume event to the application.
285   // Resuming DALi core only occurs on the Window Show framework event
286
287   // Trigger processing of events queued up while paused
288   CoreEventInterface& coreEventInterface = Internal::Adaptor::Adaptor::GetImplementation( GetAdaptor() );
289   coreEventInterface.ProcessCoreEvents();
290 }
291
292 void Application::OnReset()
293 {
294   /*
295    * usually, reset callback was called when a caller request to launch this application via aul.
296    * because Application class already handled initialization in OnInit(), OnReset do nothing.
297    */
298   Dali::Application application(this);
299   mResetSignal.Emit( application );
300 }
301
302 void Application::OnAppControl(void *data)
303 {
304   Dali::Application application(this);
305   mAppControlSignal.Emit( application , data );
306 }
307
308 void Application::OnLanguageChanged()
309 {
310   mAdaptor->NotifyLanguageChanged();
311   Dali::Application application(this);
312   mLanguageChangedSignal.Emit( application );
313 }
314
315 void Application::OnRegionChanged()
316 {
317   Dali::Application application(this);
318   mRegionChangedSignal.Emit( application );
319 }
320
321 void Application::OnBatteryLow( Dali::DeviceStatus::Battery::Status status )
322 {
323   Dali::Application application(this);
324   mLowBatterySignal.Emit( status );
325 }
326
327 void Application::OnMemoryLow( Dali::DeviceStatus::Memory::Status status )
328 {
329   Dali::Application application(this);
330   mLowMemorySignal.Emit( status );
331 }
332
333 void Application::OnSurfaceCreated( Any newSurface )
334 {
335   void* newWindow = AnyCast< void* >( newSurface );
336   void* oldWindow = AnyCast< void* >( mMainWindow.GetNativeHandle() );
337   if( oldWindow != newWindow )
338   {
339     auto renderSurfaceFactory = Dali::Internal::Adaptor::GetRenderSurfaceFactory();
340     std::unique_ptr< WindowRenderSurface > newSurfacePtr
341       = renderSurfaceFactory->CreateWindowRenderSurface( PositionSize(), newSurface, true );
342
343     mAdaptor->ReplaceSurface( mMainWindow, *newSurfacePtr.release() );
344   }
345 }
346
347 void Application::OnSurfaceDestroyed( Any surface )
348 {
349 }
350
351 bool Application::AddIdle( CallbackBase* callback, bool hasReturnValue )
352 {
353   return mAdaptor->AddIdle( callback, hasReturnValue );
354 }
355
356 std::string Application::GetRegion() const
357 {
358   return mFramework->GetRegion();
359 }
360
361 std::string Application::GetLanguage() const
362 {
363   return mFramework->GetLanguage();
364 }
365
366 Dali::ObjectRegistry Application::GetObjectRegistry() const
367 {
368   Dali::ObjectRegistry objectRegistry;
369   if( mAdaptor )
370   {
371     objectRegistry = mAdaptor->GetObjectRegistry();
372   }
373   return objectRegistry;
374 }
375
376 Dali::Adaptor& Application::GetAdaptor()
377 {
378   return *mAdaptor;
379 }
380
381 Dali::Window Application::GetWindow()
382 {
383   return mMainWindow;
384 }
385
386 std::string Application::GetResourcePath()
387 {
388   return Internal::Adaptor::Framework::GetResourcePath();
389 }
390
391 std::string Application::GetDataPath()
392 {
393   return Internal::Adaptor::Framework::GetDataPath();
394 }
395
396 void Application::SetStyleSheet( const std::string& stylesheet )
397 {
398   mStylesheet = stylesheet;
399 }
400
401 void Application::SetCommandLineOptions( int* argc, char **argv[] )
402 {
403   delete mCommandLineOptions;
404
405   mCommandLineOptions = new CommandLineOptions( argc, argv );
406
407   mFramework->SetCommandLineOptions( argc, argv );
408 }
409
410 ApplicationPtr Application::GetPreInitializedApplication()
411 {
412   return gPreInitializedApplication;
413 }
414
415 } // namespace Adaptor
416
417 } // namespace Internal
418
419 } // namespace Dali