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