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