[NUI] Add UI thread feature (#4358)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / Application / NUIApplication.cs
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 using System;
19 using System.ComponentModel;
20 using System.Diagnostics.CodeAnalysis;
21 using System.Threading;
22 using System.Reflection;
23 using Tizen.Applications;
24 using Tizen.Applications.CoreBackend;
25 using Tizen.NUI.Xaml;
26
27 namespace Tizen.NUI
28 {
29
30     /// <summary>
31     /// Represents an application that have a UI screen. The NUIApplication class has a default stage.
32     /// </summary>
33     /// <since_tizen> 3 </since_tizen>
34     public class NUIApplication : CoreApplication
35     {
36         /// <summary>
37         /// The instance of ResourceManager.
38         /// </summary>
39         private static System.Resources.ResourceManager resourceManager = null;
40         private static string currentLoadedXaml = null;
41
42         /// <summary>
43         /// The border window
44         /// </summary>
45         private bool borderEnabled = false;
46         private IBorderInterface borderInterface = null;
47
48         /// <summary>
49         /// Xaml loaded delegate.
50         /// </summary>
51         [EditorBrowsable(EditorBrowsableState.Never)]
52         public delegate void XamlLoadedHandler(string xamlName);
53
54         static NUIApplication()
55         {
56             Registry.Instance.SavedApplicationThread = Thread.CurrentThread;
57         }
58
59         /// <summary>
60         /// The default constructor.
61         /// </summary>
62         /// <since_tizen> 3 </since_tizen>
63         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")]
64         public NUIApplication() : base(new NUICoreBackend())
65         {
66         }
67
68         /// <summary>
69         /// The constructor with window size and position.
70         /// </summary>
71         /// <param name="windowSize">The window size.</param>
72         /// <param name="windowPosition">The window position.</param>
73         /// <since_tizen> 5 </since_tizen>
74         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
75         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")]
76         [EditorBrowsable(EditorBrowsableState.Never)]
77         public NUIApplication(Size2D windowSize, Position2D windowPosition) : base(new NUICoreBackend("", NUIApplication.WindowMode.Opaque, windowSize, windowPosition))
78         {
79         }
80
81         /// <summary>
82         /// The constructor with a stylesheet.
83         /// </summary>
84         /// <param name="styleSheet">The styleSheet url.</param>
85         /// <since_tizen> 3 </since_tizen>
86         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")]
87         public NUIApplication(string styleSheet) : base(new NUICoreBackend(styleSheet))
88         {
89         }
90
91         /// <summary>
92         /// The constructor with a stylesheet, window size, and position.
93         /// </summary>
94         /// <param name="styleSheet">The styleSheet URL.</param>
95         /// <param name="windowSize">The window size.</param>
96         /// <param name="windowPosition">The window position.</param>
97         /// <since_tizen> 5 </since_tizen>
98         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
99         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")]
100         [EditorBrowsable(EditorBrowsableState.Never)]
101         public NUIApplication(string styleSheet, Size2D windowSize, Position2D windowPosition) : base(new NUICoreBackend(styleSheet, WindowMode.Opaque, windowSize, windowPosition))
102         {
103         }
104
105         /// <summary>
106         /// The constructor with a stylesheet and window mode.
107         /// </summary>
108         /// <param name="styleSheet">The styleSheet url.</param>
109         /// <param name="windowMode">The windowMode.</param>
110         /// <since_tizen> 3 </since_tizen>
111         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")]
112         public NUIApplication(string styleSheet, WindowMode windowMode) : base(new NUICoreBackend(styleSheet, windowMode))
113         {
114         }
115
116         /// <summary>
117         /// The constructor with a stylesheet, window mode, window size, and position.
118         /// </summary>
119         /// <param name="styleSheet">The styleSheet URL.</param>
120         /// <param name="windowMode">The windowMode.</param>
121         /// <param name="windowSize">The window size.</param>
122         /// <param name="windowPosition">The window position.</param>
123         /// <since_tizen> 5 </since_tizen>
124         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
125         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")]
126         [EditorBrowsable(EditorBrowsableState.Never)]
127         public NUIApplication(string styleSheet, WindowMode windowMode, Size2D windowSize, Position2D windowPosition) : base(new NUICoreBackend(styleSheet, windowMode, windowSize, windowPosition))
128         {
129         }
130
131         /// <summary>
132         /// Internal inhouse constructor with Graphics Backend Type
133         /// </summary>
134         /// <param name="backend"></param>
135         /// <param name="windowMode"></param>
136         /// <param name="windowSize"></param>
137         /// <param name="windowPosition"></param>
138         /// <param name="styleSheet"></param>
139         /// InhouseAPI, this could be opened in NextTizen
140         [Obsolete("Do not use! This will be deprecated!")]
141         [EditorBrowsable(EditorBrowsableState.Never)]
142         public NUIApplication(Graphics.BackendType backend, WindowMode windowMode = WindowMode.Opaque, Size2D windowSize = null, Position2D windowPosition = null, string styleSheet = "") : base(new NUICoreBackend(styleSheet, windowMode, windowSize, windowPosition))
143         {
144             //windowMode and styleSheet will be added later. currently it's not working as expected.
145             Graphics.Backend = backend;
146             Tizen.Log.Error("NUI", "Plaese DO NOT set graphical backend type with this constructor! This will give no effect!");
147         }
148
149         /// <summary>
150         /// The constructor with theme option.
151         /// </summary>
152         /// <param name="option">The theme option.</param>
153         [EditorBrowsable(EditorBrowsableState.Never)]
154         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")]
155         public NUIApplication(ThemeOptions option) : base(new NUICoreBackend())
156         {
157             ApplyThemeOption(option);
158         }
159
160         /// <summary>
161         /// The constructor with window size and position and theme option.
162         /// </summary>
163         /// <param name="windowSize">The window size.</param>
164         /// <param name="windowPosition">The window position.</param>
165         /// <param name="option">The theme option.</param>
166         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")]
167         [EditorBrowsable(EditorBrowsableState.Never)]
168         public NUIApplication(Size2D windowSize, Position2D windowPosition, ThemeOptions option) : base(new NUICoreBackend("", NUIApplication.WindowMode.Opaque, windowSize, windowPosition))
169         {
170             ApplyThemeOption(option);
171         }
172
173         /// <summary>
174         /// The constructor with a stylesheet, window mode and default window type.
175         /// It is the only way to create an IME window.
176         /// </summary>
177         /// <param name="styleSheet">The styleSheet URL.</param>
178         /// <param name="windowMode">The windowMode.</param>
179         /// <param name="type">The default window type.</param>
180         /// <since_tizen> 9 </since_tizen>
181         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")]
182         public NUIApplication(string styleSheet, WindowMode windowMode, WindowType type) : base(new NUICoreBackend(styleSheet, windowMode, type))
183         {
184             ExternalThemeManager.Initialize();
185         }
186
187         /// <summary>
188         /// The constructor with a stylesheet, window mode, size, position, theme option and boderInterface
189         /// It is the only way to create an IME window.
190         /// </summary>
191         /// <param name="styleSheet">The styleSheet URL.</param>
192         /// <param name="windowMode">The windowMode.</param>
193         /// <param name="windowSize">The window size.</param>
194         /// <param name="windowPosition">The window position.</param>
195         /// <param name="borderInterface"><see cref="Tizen.NUI.IBorderInterface"/>If borderInterface is null, defaultBorder is enabled.</param>
196         [EditorBrowsable(EditorBrowsableState.Never)]
197         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")]
198         public NUIApplication(string styleSheet, Size2D windowSize, Position2D windowPosition, IBorderInterface borderInterface, WindowMode windowMode = WindowMode.Opaque) : base(new NUICoreBackend(styleSheet, windowMode, windowSize, windowPosition))
199         {
200             borderEnabled = true;
201             this.borderInterface = borderInterface;
202         }
203
204         /// <summary>
205         /// The constructor with a stylesheet, window mode, coretask
206         /// </summary>
207         /// <note>
208         /// There is the UI thread feature.
209         /// UI thread is an additional thread that an Application object creates. The thread is for UI events.
210         /// To enable the UI Thread, you have to pass CoreTask object using this contructor.
211         /// When the UI thread feature is enabled, The methods of CoreTask are emitted on the main thread,
212         /// and the NUIApplication's events are emitted on the UI thread.
213         /// If you want to handle windows or actors in cases like when the memory level of the device is low, you have to use the NUIApplication events, not the CoreTask methods.
214         /// The CoreTask is not for handling GUI.
215         /// Callbacks of the all events in NUIApplication except the CoreTask are emitted on the UI thread.
216         /// </note>
217         /// <param name="styleSheet">The styleSheet URL.</param>
218         /// <param name="windowMode">The windowMode.</param>
219         /// <param name="task">True If app creates a UI Thread</param>
220         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")]
221         [EditorBrowsable(EditorBrowsableState.Never)]
222         public NUIApplication(string styleSheet, WindowMode windowMode, CoreTask task) : base(new NUICoreBackend(styleSheet, windowMode), task)
223         {
224         }
225
226         /// <summary>
227         /// The constructor with a stylesheet, window mode, window size, position, coretask
228         /// </summary>
229         /// <param name="styleSheet">The styleSheet URL.</param>
230         /// <param name="windowMode">The windowMode.</param>
231         /// <param name="windowSize">The window size.</param>
232         /// <param name="windowPosition">The window position.</param>
233         /// <param name="task">True If app creates a UI Thread</param>
234         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")]
235         [EditorBrowsable(EditorBrowsableState.Never)]
236         public NUIApplication(string styleSheet, WindowMode windowMode, Size2D windowSize, Position2D windowPosition, CoreTask task) : base(new NUICoreBackend(styleSheet, windowMode, windowSize, windowPosition), task)
237         {
238         }
239
240         /// <summary>
241         /// Occurs whenever the application is resumed.
242         /// </summary>
243         /// <since_tizen> 4 </since_tizen>
244         public event EventHandler Resumed;
245
246         /// <summary>
247         /// Occurs whenever the application is paused.
248         /// </summary>
249         /// <since_tizen> 4 </since_tizen>
250         public event EventHandler Paused;
251
252         /// <summary>
253         /// Xaml loaded event.
254         /// </summary>
255         [EditorBrowsable(EditorBrowsableState.Never)]
256         public static event XamlLoadedHandler XamlLoaded;
257
258         /// <summary>
259         /// Enumeration for deciding whether a NUI application window is opaque or transparent.
260         /// </summary>
261         /// <since_tizen> 3 </since_tizen>
262         public enum WindowMode
263         {
264             /// <summary>
265             /// Opaque
266             /// </summary>
267             /// <since_tizen> 3 </since_tizen>
268             Opaque = 0,
269             /// <summary>
270             /// Transparent
271             /// </summary>
272             /// <since_tizen> 3 </since_tizen>
273             Transparent = 1
274         }
275
276         /// <summary>
277         /// Enumeration for theme options of the NUIApplication.
278         /// </summary>
279         [Flags]
280         [EditorBrowsable(EditorBrowsableState.Never)]
281         public enum ThemeOptions : int
282         {
283             /// <summary>
284             /// No option specified.
285             /// </summary>
286             [EditorBrowsable(EditorBrowsableState.Never)]
287             None = 0,
288
289             /// <summary>
290             /// Enable platform theme.
291             /// When this option is on, all views in the NUIApplication is affected by platform theme (e.g. light/dark).
292             /// </summary>
293             [EditorBrowsable(EditorBrowsableState.Never)]
294             PlatformThemeEnabled = 1 << 0,
295
296             /// <summary>
297             /// Sets the default value of View.ThemeChangeSensitive.
298             /// when this option is on, all views are made sensitive on theme changing by default.
299             /// </summary>
300             [EditorBrowsable(EditorBrowsableState.Never)]
301             ThemeChangeSensitive = 1 << 1,
302         };
303
304         /// <summary>
305         /// Current loaded xaml's full name.
306         /// </summary>
307         [EditorBrowsable(EditorBrowsableState.Never)]
308         public static string CurrentLoadedXaml
309         {
310             get
311             {
312                 return currentLoadedXaml;
313             }
314             set
315             {
316                 if (currentLoadedXaml != value)
317                 {
318                     currentLoadedXaml = value;
319                     XamlLoaded?.Invoke(value);
320                 }
321             }
322         }
323
324         /// <summary>
325         /// ResourceManager to handle multilingual.
326         /// </summary>
327         /// <since_tizen> 4 </since_tizen>
328         public static System.Resources.ResourceManager MultilingualResourceManager
329         {
330             get
331             {
332                 return resourceManager;
333             }
334             set
335             {
336                 resourceManager = value;
337             }
338         }
339
340         /// <summary>
341         /// Gets the window instance.
342         /// </summary>
343         /// <since_tizen> 3 </since_tizen>
344         [Obsolete("Do not use! This will be deprecated!")]
345         [EditorBrowsable(EditorBrowsableState.Never)]
346         public Window Window
347         {
348             get
349             {
350                 return GetDefaultWindow();
351             }
352         }
353
354         /// <summary>
355         /// Gets the Application Id.
356         /// </summary>
357         /// <since_tizen> 6 </since_tizen>
358         [EditorBrowsable(EditorBrowsableState.Never)]
359         public string AppId
360         {
361             get
362             {
363                 return Tizen.Applications.Application.Current.ApplicationInfo.ApplicationId;
364             }
365         }
366
367         /// <summary>
368         /// Gets the default window.
369         /// </summary>
370         /// <returns>The default Window.</returns>
371         /// <since_tizen> 6 </since_tizen>
372         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
373         [EditorBrowsable(EditorBrowsableState.Never)]
374         public static Window GetDefaultWindow()
375         {
376             return Window.Instance;
377         }
378
379         internal Application ApplicationHandle
380         {
381             get
382             {
383                 return ((NUICoreBackend)this.Backend).ApplicationHandle;
384             }
385         }
386
387         /// <summary>
388         /// Register the assembly to XAML.
389         /// </summary>
390         /// <since_tizen> 5 </since_tizen>
391         public static void RegisterAssembly(Assembly assembly)
392         {
393             XamlParser.s_assemblies.Add(assembly);
394         }
395
396         /// <summary>
397         /// Runs the NUIApplication.
398         /// </summary>
399         /// <param name="args">Arguments from commandline.</param>
400         /// <since_tizen> 4 </since_tizen>
401         public override void Run(string[] args)
402         {
403             Backend.AddEventHandler(EventType.PreCreated, OnPreCreate);
404             Backend.AddEventHandler(EventType.Resumed, OnResume);
405             Backend.AddEventHandler(EventType.Paused, OnPause);
406             base.Run(args);
407         }
408
409         /// <summary>
410         /// Exits the NUIApplication.
411         /// </summary>
412         /// <since_tizen> 4 </since_tizen>
413         public override void Exit()
414         {
415             base.Exit();
416         }
417
418         /// <summary>
419         /// Ensures that the function passed in is called from the main loop when it is idle.
420         /// </summary>
421         /// <param name="func">The function to call</param>
422         /// <returns>true if added successfully, false otherwise</returns>
423         /// <since_tizen> 4 </since_tizen>
424         public bool AddIdle(System.Delegate func)
425         {
426             return ((NUICoreBackend)this.Backend).AddIdle(func);
427         }
428
429         /// <summary>
430         /// Sets the number of frames per render.
431         /// </summary>
432         /// <param name="numberOfVSyncsPerRender">The number of vsyncs between successive renders.</param>
433         /// <remarks>
434         /// Suggest this is a power of two:
435         /// 1 - render each vsync frame.
436         /// 2 - render every other vsync frame.
437         /// 4 - render every fourth vsync frame.
438         /// 8 - render every eighth vsync frame. <br />
439         /// For example, if an application runs on 60 FPS and SetRenderRefreshRate(2) is called, the frames per second will be changed to 30.
440         ///</remarks>
441         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
442         [EditorBrowsable(EditorBrowsableState.Never)]
443         public static void SetRenderRefreshRate(uint numberOfVSyncsPerRender)
444         {
445             Adaptor.Instance.SetRenderRefreshRate(numberOfVSyncsPerRender);
446         }
447
448         /// <summary>
449         /// Overrides this method if you want to handle behavior.
450         /// </summary>
451         /// <since_tizen> 3 </since_tizen>
452         protected override void OnLocaleChanged(LocaleChangedEventArgs e)
453         {
454             base.OnLocaleChanged(e);
455         }
456
457         /// <summary>
458         /// Overrides this method if you want to handle behavior.
459         /// </summary>
460         /// <since_tizen> 3 </since_tizen>
461         protected override void OnLowBattery(LowBatteryEventArgs e)
462         {
463             base.OnLowBattery(e);
464         }
465
466         /// <summary>
467         /// Overrides this method if you want to handle behavior.
468         /// </summary>
469         /// <since_tizen> 3 </since_tizen>
470         protected override void OnLowMemory(LowMemoryEventArgs e)
471         {
472             base.OnLowMemory(e);
473         }
474
475         /// <summary>
476         /// Overrides this method if you want to handle behavior.
477         /// </summary>
478         /// <since_tizen> 3 </since_tizen>
479         protected override void OnRegionFormatChanged(RegionFormatChangedEventArgs e)
480         {
481             base.OnRegionFormatChanged(e);
482         }
483
484         /// <summary>
485         /// Overrides this method if you want to handle behavior.
486         /// </summary>
487         /// <since_tizen> 3 </since_tizen>
488         protected override void OnTerminate()
489         {
490             base.OnTerminate();
491         }
492
493         /// <summary>
494         /// Overrides this method if you want to handle behavior.
495         /// </summary>
496         /// <since_tizen> 3 </since_tizen>
497         protected virtual void OnPause()
498         {
499             Paused?.Invoke(this, EventArgs.Empty);
500         }
501
502         /// <summary>
503         /// Overrides this method if you want to handle behavior.
504         /// </summary>
505         /// <since_tizen> 3 </since_tizen>
506         protected virtual void OnResume()
507         {
508             Resumed?.Invoke(this, EventArgs.Empty);
509         }
510
511         /// <summary>
512         /// Overrides this method if you want to handle behavior.
513         /// </summary>
514         /// <since_tizen> 3 </since_tizen>
515         protected virtual void OnPreCreate()
516         {
517             Tizen.Tracer.Begin("[NUI] OnPreCreate()");
518
519             if (borderEnabled)
520             {
521                 GetDefaultWindow().EnableBorder(borderInterface, new Window.BorderCloseDelegate(Exit));
522             }
523
524             Tizen.Tracer.End();
525         }
526
527         /// <summary>
528         /// Overrides this method if you want to handle behavior.
529         /// </summary>
530         /// <since_tizen> 3 </since_tizen>
531         protected override void OnAppControlReceived(AppControlReceivedEventArgs e)
532         {
533             if (e != null)
534             {
535                 Log.Info("NUI", "OnAppControlReceived() is called! ApplicationId=" + e.ReceivedAppControl.ApplicationId);
536                 Log.Info("NUI", "CallerApplicationId=" + e.ReceivedAppControl.CallerApplicationId + "   IsReplyRequest=" + e.ReceivedAppControl.IsReplyRequest);
537             }
538             base.OnAppControlReceived(e);
539         }
540
541         /// <summary>
542         /// Overrides this method if you want to handle behavior.
543         /// </summary>
544         /// <since_tizen> 3 </since_tizen>
545         protected override void OnCreate()
546         {
547             Tizen.Tracer.Begin("[NUI] OnCreate()");
548
549             base.OnCreate();
550
551             Tizen.Tracer.End();
552         }
553
554         /// <summary>
555         /// This is used to improve application launch performance.
556         /// </summary>
557         [EditorBrowsable(EditorBrowsableState.Never)]
558         static public void Preload()
559         {
560             Interop.Application.PreInitialize();
561 #if ExternalThemeEnabled
562             ThemeManager.Preload();
563 #endif
564             IsPreload = true;
565         }
566
567         /// <summary>
568         /// Check if it is loaded as dotnet-loader-nui.
569         /// </summary>
570         static internal bool IsPreload { get; set; }
571
572         private void ApplyThemeOption(ThemeOptions option)
573         {
574             if ((option & ThemeOptions.PlatformThemeEnabled) != 0)
575             {
576                 ThemeManager.PlatformThemeEnabled = true;
577             }
578
579             if ((option & ThemeOptions.ThemeChangeSensitive) != 0)
580             {
581                 ThemeManager.ApplicationThemeChangeSensitive = true;
582             }
583         }
584     }
585
586     /// <summary>
587     /// Graphics Backend Type.
588     /// </summary>
589     [SuppressMessage("Microsoft.Design", "CA1052:StaticHolderTypesShouldBeStaticOrNotInheritable")]
590     [EditorBrowsable(EditorBrowsableState.Never)]
591     [Obsolete("Do not use! This will be deprecated!")]
592     public class Graphics
593     {
594         /// <summary>
595         /// Graphics Backend Type.
596         /// </summary>
597         public enum BackendType
598         {
599             /// <summary>
600             /// The GLES backend.
601             /// </summary>
602             Gles,
603             /// <summary>
604             /// The Vulkan backend.
605             /// </summary>
606             Vulkan
607         }
608
609         /// <summary>
610         /// The backend used by the NUIApplication.
611         /// </summary>
612         [EditorBrowsable(EditorBrowsableState.Never)]
613         internal static BackendType Backend = BackendType.Gles;
614
615         internal const string GlesCSharpBinder = NDalicPINVOKE.Lib;
616         internal const string VulkanCSharpBinder = "libdali-csharp-binder-vk.so";
617     }
618 }