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