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