Use another framework in OffscreenApplication
[platform/core/uifw/dali-adaptor.git] / dali / internal / adaptor / common / application-impl.cpp
1 /*
2  * Copyright (c) 2023 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/environment-variable.h>
30 #include <dali/devel-api/adaptor-framework/style-monitor.h>
31 #include <dali/devel-api/atspi-interfaces/accessible.h>
32 #include <dali/devel-api/text-abstraction/font-client.h>
33 #include <dali/internal/adaptor/common/adaptor-impl.h>
34 #include <dali/internal/adaptor/common/framework-factory.h>
35 #include <dali/internal/adaptor/common/framework.h>
36 #include <dali/internal/adaptor/common/lifecycle-controller-impl.h>
37 #include <dali/internal/system/common/command-line-options.h>
38 #include <dali/internal/system/common/environment-variables.h>
39 #include <dali/internal/system/common/system-settings.h>
40 #include <dali/internal/window-system/common/render-surface-factory.h>
41 #include <dali/internal/window-system/common/window-impl.h>
42 #include <dali/internal/window-system/common/window-render-surface.h>
43 #include <dali/internal/window-system/common/window-system.h>
44
45 // To disable a macro with the same name from one of OpenGL headers
46 #undef Status
47
48 namespace Dali
49 {
50 namespace TizenPlatform
51 {
52 class TizenPlatformAbstraction;
53 }
54
55 namespace Integration
56 {
57 class Core;
58 }
59
60 namespace Internal
61 {
62 namespace Adaptor
63 {
64 DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_APPLICATION, true);
65
66 ApplicationPtr Application::gPreInitializedApplication(NULL);
67
68 ApplicationPtr Application::New(
69   int*               argc,
70   char**             argv[],
71   const std::string& stylesheet,
72   Framework::Type    applicationType,
73   bool               useUiThread,
74   const WindowData&  windowData)
75 {
76   ApplicationPtr application(new Application(argc, argv, stylesheet, applicationType, useUiThread, windowData));
77   return application;
78 }
79
80 void Application::PreInitialize(int* argc, char** argv[])
81 {
82   if(!gPreInitializedApplication)
83   {
84     Dali::TextAbstraction::FontClientPreInitialize();
85     WindowData windowData;
86     gPreInitializedApplication                  = new Application(argc, argv, "", Framework::NORMAL, false, windowData);
87     gPreInitializedApplication->mLaunchpadState = Launchpad::PRE_INITIALIZED;
88     gPreInitializedApplication->CreateWindow(); // Only create window
89   }
90 }
91
92 Application::Application(int* argc, char** argv[], const std::string& stylesheet, Framework::Type applicationType, bool useUiThread, const WindowData& windowData)
93 : mInitSignal(),
94   mTerminateSignal(),
95   mPauseSignal(),
96   mResumeSignal(),
97   mResetSignal(),
98   mAppControlSignal(),
99   mLanguageChangedSignal(),
100   mRegionChangedSignal(),
101   mFramework(nullptr),
102   mCommandLineOptions(nullptr),
103   mAdaptorBuilder(nullptr),
104   mAdaptor(nullptr),
105   mEnvironmentOptions(nullptr),
106   mMainWindow(),
107   mMainWindowMode(windowData.GetTransparency() ? WINDOW_MODE::TRANSPARENT : WINDOW_MODE::OPAQUE),
108   mMainWindowName(),
109   mStylesheet(stylesheet),
110   mWindowPositionSize(windowData.GetPositionSize()),
111   mLaunchpadState(Launchpad::NONE),
112   mDefaultWindowType(windowData.GetWindowType()),
113   mUseUiThread(useUiThread),
114   mSlotDelegate(this)
115 {
116   // Set mName from command-line args
117   if(argc && (*argc > 0))
118   {
119     mMainWindowName = (*argv)[0];
120   }
121
122   const char* uiThreadEnabled = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_ENABLE_UI_THREAD);
123   if(uiThreadEnabled && std::atoi(uiThreadEnabled) != 0)
124   {
125     mUseUiThread = true;
126   }
127
128   mCommandLineOptions = new CommandLineOptions(argc, argv);
129   mFramework          = Dali::Internal::Adaptor::GetFrameworkFactory()->CreateFramework(FrameworkBackend::DEFAULT, *this, *this, argc, argv, applicationType, mUseUiThread);
130
131   mUseRemoteSurface = (applicationType == Framework::WATCH);
132 }
133
134 Application::~Application()
135 {
136   SingletonService service = SingletonService::Get();
137   // Note this can be false i.e. if Application has never created a Core instance
138   if(service)
139   {
140     service.UnregisterAll();
141   }
142
143   mMainWindow.Reset();
144
145   delete mCommandLineOptions;
146
147   // Application is created in Main thread whether UI Threading is enabled or not.
148   // But some resources are created in Main thread or UI thread.
149   // The below code is for the resource are created in Main thread.
150   if(!mUseUiThread)
151   {
152     delete mAdaptor;
153     delete mAdaptorBuilder;
154     WindowSystem::Shutdown();
155   }
156 }
157
158 void Application::StoreWindowPositionSize(PositionSize positionSize)
159 {
160   mWindowPositionSize = positionSize;
161 }
162
163 void Application::ChangePreInitializedWindowInfo()
164 {
165   // Set window name
166   auto windowClassName = mEnvironmentOptions->GetWindowClassName();
167   auto windowName      = mEnvironmentOptions->GetWindowName();
168   if(!windowName.empty())
169   {
170     mMainWindowName = windowName;
171   }
172   mMainWindow.SetClass(mMainWindowName, windowClassName);
173
174   // The real screen size may be different from the value of the preinitialized state. Update it.
175   Dali::Internal::Adaptor::WindowSystem::UpdateScreenSize();
176
177   int screenWidth, screenHeight;
178   Dali::Internal::Adaptor::WindowSystem::GetScreenSize(screenWidth, screenHeight);
179
180   // Set window position / size
181   if(mWindowPositionSize != PositionSize(0, 0, 0, 0))
182   {
183     Dali::DevelWindow::SetPositionSize(mMainWindow, mWindowPositionSize);
184   }
185   else if(mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0)
186   {
187     // Command line options override environment options and full screen
188     mWindowPositionSize.width  = mCommandLineOptions->stageWidth;
189     mWindowPositionSize.height = mCommandLineOptions->stageHeight;
190     mMainWindow.SetSize(Dali::Window::WindowSize(mWindowPositionSize.width, mWindowPositionSize.height));
191   }
192   else if(mEnvironmentOptions->GetWindowWidth() && mEnvironmentOptions->GetWindowHeight())
193   {
194     // Environment options override full screen functionality if command line arguments not provided
195     mWindowPositionSize.width  = mEnvironmentOptions->GetWindowWidth();
196     mWindowPositionSize.height = mEnvironmentOptions->GetWindowHeight();
197     mMainWindow.SetSize(Dali::Window::WindowSize(mWindowPositionSize.width, mWindowPositionSize.height));
198   }
199   else if(screenWidth != mWindowPositionSize.width || screenHeight != mWindowPositionSize.height)
200   {
201     // Some apps can receive screen size differently after launching by specifying size in manifest.
202     mWindowPositionSize.width  = screenWidth;
203     mWindowPositionSize.height = screenHeight;
204     mMainWindow.SetSize(Dali::Window::WindowSize(mWindowPositionSize.width, mWindowPositionSize.height));
205   }
206 }
207
208 void Application::CreateWindow()
209 {
210   Internal::Adaptor::Window* window;
211   WindowData                 windowData;
212   windowData.SetTransparency(mMainWindowMode);
213   windowData.SetWindowType(mDefaultWindowType);
214
215   WindowSystem::Initialize();
216
217   if(mLaunchpadState != Launchpad::PRE_INITIALIZED)
218   {
219     if(mWindowPositionSize.width == 0 && mWindowPositionSize.height == 0)
220     {
221       if(mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0)
222       {
223         // Command line options override environment options and full screen
224         mWindowPositionSize.width  = mCommandLineOptions->stageWidth;
225         mWindowPositionSize.height = mCommandLineOptions->stageHeight;
226       }
227       else if(mEnvironmentOptions->GetWindowWidth() && mEnvironmentOptions->GetWindowHeight())
228       {
229         // Environment options override full screen functionality if command line arguments not provided
230         mWindowPositionSize.width  = mEnvironmentOptions->GetWindowWidth();
231         mWindowPositionSize.height = mEnvironmentOptions->GetWindowHeight();
232       }
233     }
234
235     auto windowClassName = mEnvironmentOptions->GetWindowClassName();
236     auto windowName      = mEnvironmentOptions->GetWindowName();
237     if(!windowName.empty())
238     {
239       mMainWindowName = windowName;
240     }
241
242     windowData.SetPositionSize(mWindowPositionSize);
243     window = Internal::Adaptor::Window::New(mMainWindowName, windowClassName, windowData);
244   }
245   else
246   {
247     // The position, size and the window name of the pre-initialized application will be updated in ChangePreInitializedWindowInfo()
248     // when the real application is launched.
249     windowData.SetPositionSize(mWindowPositionSize);
250     window = Internal::Adaptor::Window::New("", "", windowData);
251   }
252
253   mMainWindow = Dali::Window(window);
254
255   // Quit the application when the window is closed
256   GetImplementation(mMainWindow).DeleteRequestSignal().Connect(mSlotDelegate, &Application::Quit);
257 }
258
259 void Application::CreateAdaptor()
260 {
261   DALI_ASSERT_ALWAYS(mMainWindow && "Window required to create adaptor");
262
263   auto graphicsFactory = mAdaptorBuilder->GetGraphicsFactory();
264
265   Integration::SceneHolder sceneHolder = Integration::SceneHolder(&Dali::GetImplementation(mMainWindow));
266
267   mAdaptor = Adaptor::New(graphicsFactory, sceneHolder, mEnvironmentOptions.get());
268
269   Adaptor::GetImplementation(*mAdaptor).SetUseRemoteSurface(mUseRemoteSurface);
270 }
271
272 void Application::CreateAdaptorBuilder()
273 {
274   mAdaptorBuilder = new AdaptorBuilder(*mEnvironmentOptions);
275 }
276
277 void Application::MainLoop()
278 {
279   // Run the application
280   mFramework->Run();
281 }
282
283 void Application::Lower()
284 {
285   // Lower the application without quitting it.
286   mMainWindow.Lower();
287 }
288
289 void Application::Quit()
290 {
291   // Actually quit the application.
292   // Force a call to Quit even if adaptor is not running.
293   Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor).AddIdle(MakeCallback(this, &Application::QuitFromMainLoop), false, true);
294 }
295
296 void Application::QuitFromMainLoop()
297 {
298   Accessibility::Bridge::GetCurrentBridge()->Terminate();
299
300   mAdaptor->Stop();
301
302   mFramework->Quit();
303   // This will trigger OnTerminate(), below, after the main loop has completed.
304 }
305
306 void Application::OnInit()
307 {
308   mEnvironmentOptions = std::unique_ptr<EnvironmentOptions>(new EnvironmentOptions());
309
310   mFramework->AddAbortCallback(MakeCallback(this, &Application::QuitFromMainLoop));
311
312   CreateAdaptorBuilder();
313   // If an application was pre-initialized, a window was made in advance
314   if(mLaunchpadState == Launchpad::NONE)
315   {
316     CreateWindow();
317   }
318
319   CreateAdaptor();
320
321   if(mLaunchpadState == Launchpad::PRE_INITIALIZED)
322   {
323     ChangePreInitializedWindowInfo();
324   }
325
326   // Run the adaptor
327   DALI_TRACE_BEGIN(gTraceFilter, "DALI_APP_ADAPTOR_START");
328   mAdaptor->Start();
329   DALI_TRACE_END(gTraceFilter, "DALI_APP_ADAPTOR_START");
330   Accessibility::Accessible::SetObjectRegistry(mAdaptor->GetObjectRegistry());
331
332   if(!mStylesheet.empty())
333   {
334     Dali::StyleMonitor::Get().SetTheme(mStylesheet);
335   }
336
337   // Wire up the LifecycleController
338   Dali::LifecycleController lifecycleController = Dali::LifecycleController::Get();
339
340   InitSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnInit);
341   TerminateSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnTerminate);
342   PauseSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnPause);
343   ResumeSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnResume);
344   ResetSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnReset);
345   LanguageChangedSignal().Connect(&GetImplementation(lifecycleController), &LifecycleController::OnLanguageChanged);
346
347   Dali::Application application(this);
348
349   DALI_TRACE_BEGIN(gTraceFilter, "DALI_APP_EMIT_INIT_SIGNAL");
350   mInitSignal.Emit(application);
351   DALI_TRACE_END(gTraceFilter, "DALI_APP_EMIT_INIT_SIGNAL");
352
353   mAdaptor->NotifySceneCreated();
354
355   // Ensure the join of Font thread at this point
356   Dali::TextAbstraction::FontClientJoinFontThreads();
357 }
358
359 void Application::OnTerminate()
360 {
361   // We've been told to quit by AppCore, ecore_x_destroy has been called, need to quit synchronously
362   // delete the window as ecore_x has been destroyed by AppCore
363
364   Dali::Application application(this);
365   mTerminateSignal.Emit(application);
366
367   if(mAdaptor)
368   {
369     // Ensure that the render-thread is not using the surface(window) after we delete it
370     mAdaptor->Stop();
371   }
372
373   mMainWindow.Reset(); // This only resets (clears) the default Window
374
375   // If DALi's UI Thread works, some resources are created in UI Thread, not Main thread.
376   // For that case, these resource should be deleted in UI Thread.
377   if(mUseUiThread)
378   {
379     delete mAdaptor;
380     delete mAdaptorBuilder;
381     WindowSystem::Shutdown();
382   }
383 }
384
385 void Application::OnPause()
386 {
387   // A DALi app should handle Pause/Resume events.
388   // DALi just delivers the framework Pause event to the application, but not actually pause DALi core.
389   // Pausing DALi core only occurs on the Window Hidden framework event
390   Dali::Application application(this);
391   mPauseSignal.Emit(application);
392 }
393
394 void Application::OnResume()
395 {
396   // Emit the signal first so the application can queue any messages before we do an update/render
397   // This ensures we do not just redraw the last frame before pausing if that's not required
398   Dali::Application application(this);
399   mResumeSignal.Emit(application);
400
401   // DALi just delivers the framework Resume event to the application.
402   // Resuming DALi core only occurs on the Window Show framework event
403
404   // Trigger processing of events queued up while paused
405   CoreEventInterface& coreEventInterface = Internal::Adaptor::Adaptor::GetImplementation(GetAdaptor());
406   coreEventInterface.ProcessCoreEvents();
407 }
408
409 void Application::OnReset()
410 {
411   /*
412    * usually, reset callback was called when a caller request to launch this application via aul.
413    * because Application class already handled initialization in OnInit(), OnReset do nothing.
414    */
415   Dali::Application application(this);
416   mResetSignal.Emit(application);
417 }
418
419 void Application::OnAppControl(void* data)
420 {
421   Dali::Application application(this);
422   mAppControlSignal.Emit(application, data);
423 }
424
425 void Application::OnLanguageChanged()
426 {
427   mAdaptor->NotifyLanguageChanged();
428   Dali::Application application(this);
429   mLanguageChangedSignal.Emit(application);
430 }
431
432 void Application::OnRegionChanged()
433 {
434   Dali::Application application(this);
435   mRegionChangedSignal.Emit(application);
436 }
437
438 void Application::OnBatteryLow(Dali::DeviceStatus::Battery::Status status)
439 {
440   Dali::Application application(this);
441   mLowBatterySignal.Emit(status);
442 }
443
444 void Application::OnMemoryLow(Dali::DeviceStatus::Memory::Status status)
445 {
446   Dali::Application application(this);
447   mLowMemorySignal.Emit(status);
448 }
449
450 void Application::OnDeviceOrientationChanged(Dali::DeviceStatus::Orientation::Status status)
451 {
452   Dali::Application application(this);
453   mDeviceOrientationChangedSignal.Emit(status);
454 }
455
456 void Application::OnSurfaceCreated(Any newSurface)
457 {
458   void* newWindow = AnyCast<void*>(newSurface);
459   void* oldWindow = AnyCast<void*>(mMainWindow.GetNativeHandle());
460   if(oldWindow != newWindow)
461   {
462     auto                                 renderSurfaceFactory = Dali::Internal::Adaptor::GetRenderSurfaceFactory();
463     std::unique_ptr<WindowRenderSurface> newSurfacePtr        = renderSurfaceFactory->CreateWindowRenderSurface(PositionSize(), newSurface, true);
464
465     mAdaptor->ReplaceSurface(mMainWindow, *newSurfacePtr.release());
466   }
467 }
468
469 void Application::OnSurfaceDestroyed(Any surface)
470 {
471 }
472
473 void Application::OnTaskInit()
474 {
475   Dali::Application application(this);
476   mTaskInitSignal.Emit(application);
477 }
478
479 void Application::OnTaskTerminate()
480 {
481   Dali::Application application(this);
482   mTaskTerminateSignal.Emit(application);
483 }
484
485 void Application::OnTaskAppControl(void* data)
486 {
487   Dali::Application application(this);
488   mTaskAppControlSignal.Emit(application, data);
489 }
490
491 void Application::OnTaskLanguageChanged()
492 {
493   Dali::Application application(this);
494   mTaskLanguageChangedSignal.Emit(application);
495 }
496
497 void Application::OnTaskRegionChanged()
498 {
499   Dali::Application application(this);
500   mTaskRegionChangedSignal.Emit(application);
501 }
502
503 void Application::OnTaskBatteryLow(Dali::DeviceStatus::Battery::Status status)
504 {
505   Dali::Application application(this);
506   mTaskLowBatterySignal.Emit(status);
507 }
508
509 void Application::OnTaskMemoryLow(Dali::DeviceStatus::Memory::Status status)
510 {
511   Dali::Application application(this);
512   mTaskLowMemorySignal.Emit(status);
513 }
514
515 void Application::OnTaskDeviceOrientationChanged(Dali::DeviceStatus::Orientation::Status status)
516 {
517   Dali::Application application(this);
518   mTaskDeviceOrientationChangedSignal.Emit(status);
519 }
520
521 bool Application::AddIdle(CallbackBase* callback, bool hasReturnValue)
522 {
523   return mAdaptor->AddIdle(callback, hasReturnValue);
524 }
525
526 std::string Application::GetRegion() const
527 {
528   return mFramework->GetRegion();
529 }
530
531 std::string Application::GetLanguage() const
532 {
533   return mFramework->GetLanguage();
534 }
535
536 Dali::ObjectRegistry Application::GetObjectRegistry() const
537 {
538   Dali::ObjectRegistry objectRegistry;
539   if(mAdaptor)
540   {
541     objectRegistry = mAdaptor->GetObjectRegistry();
542   }
543   return objectRegistry;
544 }
545
546 Dali::Adaptor& Application::GetAdaptor()
547 {
548   return *mAdaptor;
549 }
550
551 Dali::Window Application::GetWindow()
552 {
553   return mMainWindow;
554 }
555
556 std::string Application::GetResourcePath()
557 {
558   return SystemSettings::GetResourcePath();
559 }
560
561 std::string Application::GetDataPath()
562 {
563   return SystemSettings::GetDataPath();
564 }
565
566 void Application::SetStyleSheet(const std::string& stylesheet)
567 {
568   mStylesheet = stylesheet;
569 }
570
571 void Application::SetCommandLineOptions(int* argc, char** argv[])
572 {
573   delete mCommandLineOptions;
574
575   mCommandLineOptions = new CommandLineOptions(argc, argv);
576
577   mFramework->SetCommandLineOptions(argc, argv);
578
579   if(argc && (*argc > 0))
580   {
581     // Set mName from command-line args
582     mMainWindowName = (*argv)[0];
583   }
584 }
585
586 void Application::SetDefaultWindowType(WindowType type)
587 {
588   mDefaultWindowType = type;
589   mMainWindow.SetType(type);
590 }
591
592 int32_t Application::GetRenderThreadId() const
593 {
594   if(mAdaptor)
595   {
596     return Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor).GetRenderThreadId();
597   }
598   return 0;
599 }
600
601 ApplicationPtr Application::GetPreInitializedApplication()
602 {
603   // Reset the handle to decrease the reference count
604   ApplicationPtr application = gPreInitializedApplication;
605   gPreInitializedApplication.Reset();
606
607   return application;
608 }
609
610 } // namespace Adaptor
611
612 } // namespace Internal
613
614 } // namespace Dali