dece482954f1cd40b6f944660f4704314cbcfaee
[platform/core/uifw/dali-adaptor.git] / adaptors / common / application-impl.cpp
1 /*
2  * Copyright (c) 2016 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 "application-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23
24 // INTERNAL INCLUDES
25 #include <style-monitor.h>
26 #include <command-line-options.h>
27 #include <common/adaptor-impl.h>
28 #include <singleton-service-impl.h>
29 #include <lifecycle-controller-impl.h>
30
31 // CONDITIONAL INCLUDES
32 #ifdef DALI_ELDBUS_AVAILABLE
33 #include <Eldbus.h>
34 #endif // DALI_ELDBUS_AVAILABLE
35
36 namespace Dali
37 {
38
39 namespace TizenPlatform
40 {
41 class TizenPlatformAbstraction;
42 }
43
44 namespace Integration
45 {
46 class Core;
47 }
48
49 namespace Internal
50 {
51
52 namespace Adaptor
53 {
54
55 #if defined(DEBUG_ENABLED)
56 namespace
57 {
58 Integration::Log::Filter* gDBusLogging = Integration::Log::Filter::New( Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_DBUS" );
59 } // anonymous namespace
60 #endif
61
62 ApplicationPtr Application::New(
63   int* argc,
64   char **argv[],
65   const std::string& stylesheet,
66   Dali::Application::WINDOW_MODE windowMode,
67   Framework::Type applicationType)
68 {
69   ApplicationPtr application ( new Application (argc, argv, stylesheet, windowMode, applicationType ) );
70   return application;
71 }
72
73 Application::Application( int* argc, char** argv[], const std::string& stylesheet,
74   Dali::Application::WINDOW_MODE windowMode, Framework::Type applicationType )
75 : mInitSignal(),
76   mTerminateSignal(),
77   mPauseSignal(),
78   mResumeSignal(),
79   mResetSignal(),
80   mResizeSignal(),
81   mAppControlSignal(),
82   mLanguageChangedSignal(),
83   mRegionChangedSignal(),
84   mBatteryLowSignal(),
85   mMemoryLowSignal(),
86   mEventLoop( NULL ),
87   mFramework( NULL ),
88   mContextLossConfiguration( Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS ),
89   mCommandLineOptions( NULL ),
90   mSingletonService( SingletonService::New() ),
91   mAdaptor( NULL ),
92   mWindow(),
93   mWindowMode( windowMode ),
94   mName(),
95   mStylesheet( stylesheet ),
96   mEnvironmentOptions(),
97   mSlotDelegate( this )
98 {
99   // Get mName from environment options
100   mName = mEnvironmentOptions.GetWindowName();
101   if( mName.empty() && argc && ( *argc > 0 ) )
102   {
103     // Set mName from command-line args if environment option not set
104     mName = (*argv)[0];
105   }
106
107   mCommandLineOptions = new CommandLineOptions(argc, argv);
108   mFramework = new Framework( *this, argc, argv, applicationType );
109   mUseRemoteSurface = (applicationType == Framework::WATCH);
110 }
111
112 Application::~Application()
113 {
114   mSingletonService.UnregisterAll();
115
116   delete mFramework;
117   delete mCommandLineOptions;
118   delete mAdaptor;
119
120 #ifdef DALI_ELDBUS_AVAILABLE
121   // Shutdown ELDBus.
122   DALI_LOG_INFO( gDBusLogging, Debug::General, "Shutting down DBus\n" );
123   eldbus_shutdown();
124 #endif
125
126   mWindow.Reset();
127 }
128
129 void Application::CreateWindow()
130 {
131   PositionSize windowPosition(0, 0, 0, 0);  // this will use full screen
132
133   if( mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0 )
134   {
135     // Command line options override environment options and full screen
136     windowPosition = PositionSize( 0, 0, mCommandLineOptions->stageWidth, mCommandLineOptions->stageHeight );
137   }
138   else if( mEnvironmentOptions.GetWindowWidth() && mEnvironmentOptions.GetWindowHeight() )
139   {
140     // Environment options override full screen functionality if command line arguments not provided
141     windowPosition = PositionSize( 0, 0, mEnvironmentOptions.GetWindowWidth(), mEnvironmentOptions.GetWindowHeight() );
142   }
143
144   const std::string& windowClassName = mEnvironmentOptions.GetWindowClassName();
145   mWindow = Dali::Window::New( windowPosition, mName, windowClassName, mWindowMode == Dali::Application::TRANSPARENT );
146
147   // Quit the application when the window is closed
148   GetImplementation( mWindow ).DeleteRequestSignal().Connect( mSlotDelegate, &Application::Quit );
149 }
150
151 void Application::CreateAdaptor()
152 {
153   DALI_ASSERT_ALWAYS( mWindow && "Window required to create adaptor" );
154
155   mAdaptor = Dali::Internal::Adaptor::Adaptor::New( mWindow, mContextLossConfiguration, &mEnvironmentOptions );
156
157   mAdaptor->ResizedSignal().Connect( mSlotDelegate, &Application::OnResize );
158
159   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SetUseRemoteSurface( mUseRemoteSurface );
160 }
161
162 void Application::MainLoop(Dali::Configuration::ContextLoss configuration)
163 {
164   mContextLossConfiguration = configuration;
165
166   // Run the application
167   mFramework->Run();
168 }
169
170 void Application::Lower()
171 {
172   // Lower the application without quitting it.
173   mWindow.Lower();
174 }
175
176 void Application::Quit()
177 {
178   // Actually quit the application.
179   AddIdle( MakeCallback( this, &Application::QuitFromMainLoop ) );
180 }
181
182 void Application::QuitFromMainLoop()
183 {
184   mAdaptor->Stop();
185
186   mFramework->Quit();
187   // This will trigger OnTerminate(), below, after the main loop has completed.
188 }
189
190 void Application::OnInit()
191 {
192   mFramework->AddAbortCallback( MakeCallback( this, &Application::QuitFromMainLoop ) );
193
194   CreateWindow();
195
196 #ifdef DALI_ELDBUS_AVAILABLE
197   // Initialize ElDBus.
198   DALI_LOG_INFO( gDBusLogging, Debug::General, "Starting DBus Initialization\n" );
199   eldbus_init();
200 #endif
201
202   // Start the adaptor
203   CreateAdaptor();
204   mAdaptor->Start();
205
206   // Check if user requires no vsyncing and set on X11 Adaptor
207   if (mCommandLineOptions->noVSyncOnRender)
208   {
209     mAdaptor->SetUseHardwareVSync(false);
210   }
211
212   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SetStereoBase( mCommandLineOptions->stereoBase );
213   if( mCommandLineOptions->viewMode != 0 )
214   {
215     ViewMode viewMode = MONO;
216     if( mCommandLineOptions->viewMode <= STEREO_INTERLACED )
217     {
218       viewMode = static_cast<ViewMode>( mCommandLineOptions->viewMode );
219     }
220     Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SetViewMode( viewMode );
221   }
222
223   if( ! mStylesheet.empty() )
224   {
225     Dali::StyleMonitor::Get().SetTheme( mStylesheet );
226   }
227
228   // Wire up the LifecycleController
229   Dali::LifecycleController lifecycleController = Dali::LifecycleController::Get();
230
231   InitSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnInit );
232   TerminateSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnTerminate );
233   PauseSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnPause );
234   ResumeSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnResume );
235   ResetSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnReset );
236   ResizeSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnResize );
237   LanguageChangedSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnLanguageChanged );
238
239   Dali::Application application(this);
240   mInitSignal.Emit( application );
241
242   mAdaptor->NotifySceneCreated();
243 }
244
245 void Application::OnTerminate()
246 {
247   // we've been told to quit by AppCore, ecore_x_destroy has been called, need to quit synchronously
248   // delete the window as ecore_x has been destroyed by AppCore
249
250   Dali::Application application(this);
251   mTerminateSignal.Emit( application );
252
253   if( mAdaptor )
254   {
255     // Ensure that the render-thread is not using the surface(window) after we delete it
256     mAdaptor->Stop();
257   }
258
259   mWindow.Reset();
260 }
261
262 void Application::OnPause()
263 {
264   mAdaptor->Pause();
265   Dali::Application application(this);
266   mPauseSignal.Emit( application );
267 }
268
269 void Application::OnResume()
270 {
271   // Emit the signal first so the application can queue any messages before we do an update/render
272   // This ensures we do not just redraw the last frame before pausing if that's not required
273   Dali::Application application(this);
274   mResumeSignal.Emit( application );
275   mAdaptor->Resume();
276 }
277
278 void Application::OnReset()
279 {
280   /*
281    * usually, reset callback was called when a caller request to launch this application via aul.
282    * because Application class already handled initialization in OnInit(), OnReset do nothing.
283    */
284   Dali::Application application(this);
285   mResetSignal.Emit( application );
286 }
287
288 void Application::OnAppControl(void *data)
289 {
290   Dali::Application application(this);
291   mAppControlSignal.Emit( application , data );
292 }
293
294 void Application::OnLanguageChanged()
295 {
296   mAdaptor->NotifyLanguageChanged();
297   Dali::Application application(this);
298   mLanguageChangedSignal.Emit( application );
299 }
300
301 void Application::OnRegionChanged()
302 {
303   Dali::Application application(this);
304   mRegionChangedSignal.Emit( application );
305 }
306
307 void Application::OnBatteryLow()
308 {
309   Dali::Application application(this);
310   mBatteryLowSignal.Emit( application );
311 }
312
313 void Application::OnMemoryLow()
314 {
315   Dali::Application application(this);
316   mMemoryLowSignal.Emit( application );
317 }
318
319 void Application::OnResize(Dali::Adaptor& adaptor)
320 {
321   Dali::Application application(this);
322   mResizeSignal.Emit( application );
323 }
324
325 bool Application::AddIdle( CallbackBase* callback )
326 {
327   return mAdaptor->AddIdle( callback );
328 }
329
330 Dali::Adaptor& Application::GetAdaptor()
331 {
332   return *mAdaptor;
333 }
334
335 Dali::Window Application::GetWindow()
336 {
337   return mWindow;
338 }
339
340 // Stereoscopy
341
342 void Application::SetViewMode( ViewMode viewMode )
343 {
344   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SetViewMode( viewMode );
345 }
346
347 ViewMode Application::GetViewMode() const
348 {
349   return Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).GetViewMode();
350 }
351
352 void Application::SetStereoBase( float stereoBase )
353 {
354   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SetStereoBase( stereoBase );
355 }
356
357 float Application::GetStereoBase() const
358 {
359   return Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).GetStereoBase();
360 }
361
362
363 void Application::ReplaceWindow(PositionSize windowPosition, const std::string& name)
364 {
365   Dali::Window newWindow = Dali::Window::New( windowPosition, name, mWindowMode == Dali::Application::TRANSPARENT );
366   Window& windowImpl = GetImplementation(newWindow);
367   windowImpl.SetAdaptor(*mAdaptor);
368   newWindow.ShowIndicator(Dali::Window::INVISIBLE);
369   Dali::RenderSurface* renderSurface = windowImpl.GetSurface();
370
371   Any nativeWindow = newWindow.GetNativeHandle();
372   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).ReplaceSurface(nativeWindow, *renderSurface);
373   mWindow = newWindow;
374 }
375
376 } // namespace Adaptor
377
378 } // namespace Internal
379
380 } // namespace Dali