From feb66df4069e36893cd1a082c9788443474ac7de Mon Sep 17 00:00:00 2001 From: dkdk-ryu Date: Fri, 8 Jul 2022 13:20:33 +0900 Subject: [PATCH] [NUI] Add UI thread feature (#4358) * [NUI] Add UI thread feature UI thread means that the events related to GUI (e.g. touch, key, window events) are emitted on the UI thread. In the main thread, the LowBattery, LowMemory and etc events are emitted. * [NUI] Add UIThread example app --- .../src/internal/Application/Application.cs | 459 +++++++++++++++++++++ .../src/internal/Application/NUICoreBackend.cs | 163 +++++++- .../src/internal/Interop/Interop.Application.cs | 3 + .../src/internal/Interop/NDalicPINVOKE.cs | 22 + .../src/public/Application/NUIApplication.cs | 38 ++ test/Tizen.NUI.UIThread/Tizen.NUI.UIThread.cs | 160 +++++++ test/Tizen.NUI.UIThread/Tizen.NUI.UIThread.csproj | 26 ++ .../shared/res/Tizen.NUI.UIThread.png | Bin 0 -> 10097 bytes test/Tizen.NUI.UIThread/tizen-manifest.xml | 17 + 9 files changed, 884 insertions(+), 4 deletions(-) create mode 100644 test/Tizen.NUI.UIThread/Tizen.NUI.UIThread.cs create mode 100644 test/Tizen.NUI.UIThread/Tizen.NUI.UIThread.csproj create mode 100644 test/Tizen.NUI.UIThread/shared/res/Tizen.NUI.UIThread.png create mode 100644 test/Tizen.NUI.UIThread/tizen-manifest.xml diff --git a/src/Tizen.NUI/src/internal/Application/Application.cs b/src/Tizen.NUI/src/internal/Application/Application.cs index effb0d8..5e3ce7e 100755 --- a/src/Tizen.NUI/src/internal/Application/Application.cs +++ b/src/Tizen.NUI/src/internal/Application/Application.cs @@ -463,6 +463,56 @@ namespace Tizen.NUI appControlSignal = null; } + //Task + if (applicationTaskInitEventCallbackDelegate != null) + { + taskInitSignal?.Disconnect(applicationTaskInitEventCallbackDelegate); + taskInitSignal?.Dispose(); + taskInitSignal = null; + } + + if (applicationTaskTerminateEventCallbackDelegate != null) + { + taskTerminateSignal?.Disconnect(applicationTaskTerminateEventCallbackDelegate); + taskTerminateSignal?.Dispose(); + taskTerminateSignal = null; + } + + if (applicationTaskLanguageChangedEventCallbackDelegate != null) + { + taskLanguageChangedSignal?.Disconnect(applicationTaskLanguageChangedEventCallbackDelegate); + taskLanguageChangedSignal?.Dispose(); + taskLanguageChangedSignal = null; + } + + if (applicationTaskRegionChangedEventCallbackDelegate != null) + { + taskRegionChangedSignal?.Disconnect(applicationTaskRegionChangedEventCallbackDelegate); + taskRegionChangedSignal?.Dispose(); + taskRegionChangedSignal = null; + } + + if (applicationTaskBatteryLowEventCallbackDelegate != null) + { + taskBatteryLowSignal?.Disconnect(applicationTaskBatteryLowEventCallbackDelegate); + taskBatteryLowSignal?.Dispose(); + taskBatteryLowSignal = null; + } + + if (applicationTaskMemoryLowEventCallbackDelegate != null) + { + taskMemoryLowSignal?.Disconnect(applicationTaskMemoryLowEventCallbackDelegate); + taskMemoryLowSignal?.Dispose(); + taskMemoryLowSignal = null; + } + + if (applicationTaskAppControlEventCallbackDelegate != null) + { + taskAppControlSignal?.Disconnect(applicationTaskAppControlEventCallbackDelegate); + taskAppControlSignal?.Dispose(); + taskAppControlSignal = null; + } + window?.Dispose(); window = null; @@ -548,6 +598,34 @@ namespace Tizen.NUI private NUIApplicationAppControlEventCallbackDelegate applicationAppControlEventCallbackDelegate; private ApplicationControlSignal appControlSignal; + private DaliEventHandler applicationTaskInitEventHandler; + private NUIApplicationInitEventCallbackDelegate applicationTaskInitEventCallbackDelegate; + private ApplicationSignal taskInitSignal; + + private DaliEventHandler applicationTaskTerminateEventHandler; + private NUIApplicationTerminateEventCallbackDelegate applicationTaskTerminateEventCallbackDelegate; + private ApplicationSignal taskTerminateSignal; + + private DaliEventHandler applicationTaskLanguageChangedEventHandler; + private NUIApplicationLanguageChangedEventCallbackDelegate applicationTaskLanguageChangedEventCallbackDelegate; + private ApplicationSignal taskLanguageChangedSignal; + + private DaliEventHandler applicationTaskRegionChangedEventHandler; + private NUIApplicationRegionChangedEventCallbackDelegate applicationTaskRegionChangedEventCallbackDelegate; + private ApplicationSignal taskRegionChangedSignal; + + private DaliEventHandler applicationTaskBatteryLowEventHandler; + private NUIApplicationBatteryLowEventCallbackDelegate applicationTaskBatteryLowEventCallbackDelegate; + private LowBatterySignalType taskBatteryLowSignal; + + private DaliEventHandler applicationTaskMemoryLowEventHandler; + private NUIApplicationMemoryLowEventCallbackDelegate applicationTaskMemoryLowEventCallbackDelegate; + private LowMemorySignalType taskMemoryLowSignal; + + private DaliEventHandler applicationTaskAppControlEventHandler; + private NUIApplicationAppControlEventCallbackDelegate applicationTaskAppControlEventCallbackDelegate; + private ApplicationControlSignal taskAppControlSignal; + private Window window; /** @@ -996,6 +1074,300 @@ namespace Tizen.NUI } } + /// + /// @brief Event for Initialized signal which can be used to subscribe/unsubscribe the event handler + /// provided by the user. Initialized signal is emitted when application is initialized + /// + public event DaliEventHandler TaskInitialized + { + add + { + // Restricted to only one listener + if (applicationTaskInitEventHandler == null) + { + Tizen.Log.Fatal("NUI", "TaskInitialized Property adding"); + applicationTaskInitEventHandler += value; + applicationTaskInitEventCallbackDelegate = new NUIApplicationInitEventCallbackDelegate(OnApplicationTaskInit); + taskInitSignal = this.TaskInitSignal(); + taskInitSignal?.Connect(applicationTaskInitEventCallbackDelegate); + } + } + + remove + { + if (applicationTaskInitEventHandler != null) + { + taskInitSignal?.Disconnect(applicationTaskInitEventCallbackDelegate); + taskInitSignal?.Dispose(); + taskInitSignal = null; + } + + applicationTaskInitEventHandler -= value; + } + } + + private void OnApplicationTaskInit(IntPtr data) + { + if (applicationTaskInitEventHandler != null) + { + NUIApplicationInitEventArgs e = new NUIApplicationInitEventArgs(); + e.Application = this; + applicationTaskInitEventHandler.Invoke(this, e); + } + + } + + /// + /// @brief Event for Terminated signal which can be used to subscribe/unsubscribe the event handler + /// provided by the user. Terminated signal is emitted when application is terminating + /// + public event DaliEventHandler TaskTerminating + { + add + { + // Restricted to only one listener + if (applicationTaskTerminateEventHandler == null) + { + applicationTaskTerminateEventHandler += value; + + applicationTaskTerminateEventCallbackDelegate = new NUIApplicationTerminateEventCallbackDelegate(OnNUIApplicationTaskTerminate); + taskTerminateSignal = this.TaskTerminateSignal(); + taskTerminateSignal?.Connect(applicationTaskTerminateEventCallbackDelegate); + } + } + + remove + { + if (applicationTaskTerminateEventHandler != null) + { + taskTerminateSignal?.Disconnect(applicationTaskTerminateEventCallbackDelegate); + taskTerminateSignal?.Dispose(); + taskTerminateSignal = null; + } + + applicationTaskTerminateEventHandler -= value; + } + } + + private void OnNUIApplicationTaskTerminate(IntPtr data) + { + if (applicationTaskTerminateEventHandler != null) + { + NUIApplicationTerminatingEventArgs e = new NUIApplicationTerminatingEventArgs(); + e.Application = this; + applicationTaskTerminateEventHandler.Invoke(this, e); + } + } + + /// + /// @brief Event for TaskLanguageChanged signal which can be used to subscribe/unsubscribe the event handler + /// provided by the user. TaskLanguageChanged signal is emitted when the region of the device is changed. + /// + public event DaliEventHandler TaskLanguageChanged + { + add + { + // Restricted to only one listener + if (applicationTaskLanguageChangedEventHandler == null) + { + applicationTaskLanguageChangedEventHandler += value; + + applicationTaskLanguageChangedEventCallbackDelegate = new NUIApplicationLanguageChangedEventCallbackDelegate(OnNUIApplicationTaskLanguageChanged); + taskLanguageChangedSignal = this.TaskLanguageChangedSignal(); + taskLanguageChangedSignal?.Connect(applicationTaskLanguageChangedEventCallbackDelegate); + } + } + + remove + { + if (applicationTaskLanguageChangedEventHandler != null) + { + taskLanguageChangedSignal?.Disconnect(applicationTaskLanguageChangedEventCallbackDelegate); + taskLanguageChangedSignal?.Dispose(); + taskLanguageChangedSignal = null; + } + + applicationTaskLanguageChangedEventHandler -= value; + } + } + + private void OnNUIApplicationTaskLanguageChanged(IntPtr data) + { + if (applicationTaskLanguageChangedEventHandler != null) + { + NUIApplicationLanguageChangedEventArgs e = new NUIApplicationLanguageChangedEventArgs(); + e.Application = this; + applicationTaskLanguageChangedEventHandler.Invoke(this, e); + } + } + + /// + /// @brief Event for TaskRegionChanged signal which can be used to subscribe/unsubscribe the event handler + /// provided by the user. TaskRegionChanged signal is emitted when the region of the device is changed. + /// + public event DaliEventHandler TaskRegionChanged + { + add + { + // Restricted to only one listener + if (applicationTaskRegionChangedEventHandler == null) + { + applicationTaskRegionChangedEventHandler += value; + + applicationTaskRegionChangedEventCallbackDelegate = new NUIApplicationRegionChangedEventCallbackDelegate(OnNUIApplicationTaskRegionChanged); + taskRegionChangedSignal = this.TaskRegionChangedSignal(); + taskRegionChangedSignal?.Connect(applicationTaskRegionChangedEventCallbackDelegate); + } + } + + remove + { + if (applicationTaskRegionChangedEventHandler != null) + { + taskRegionChangedSignal?.Disconnect(applicationTaskRegionChangedEventCallbackDelegate); + taskRegionChangedSignal?.Dispose(); + taskRegionChangedSignal = null; + } + + applicationTaskRegionChangedEventHandler -= value; + } + } + + private void OnNUIApplicationTaskRegionChanged(IntPtr data) + { + if (applicationTaskRegionChangedEventHandler != null) + { + NUIApplicationRegionChangedEventArgs e = new NUIApplicationRegionChangedEventArgs(); + e.Application = this; + applicationTaskRegionChangedEventHandler.Invoke(this, e); + } + } + + /// + /// @brief Event for TaskBatteryLow signal which can be used to subscribe/unsubscribe the event handler + /// provided by the user. TaskBatteryLow signal is emitted when the battery level of the device is low. + /// + public event DaliEventHandler TaskBatteryLow + { + add + { + // Restricted to only one listener + if (applicationTaskBatteryLowEventHandler == null) + { + applicationTaskBatteryLowEventHandler += value; + + applicationTaskBatteryLowEventCallbackDelegate = new NUIApplicationBatteryLowEventCallbackDelegate(OnNUIApplicationTaskBatteryLow); + taskBatteryLowSignal = this.TaskBatteryLowSignal(); + taskBatteryLowSignal?.Connect(applicationTaskBatteryLowEventCallbackDelegate); + } + } + + remove + { + if (applicationTaskBatteryLowEventHandler != null) + { + taskBatteryLowSignal?.Disconnect(applicationTaskBatteryLowEventCallbackDelegate); + taskBatteryLowSignal?.Dispose(); + taskBatteryLowSignal = null; + } + + applicationTaskBatteryLowEventHandler -= value; + } + } + + private void OnNUIApplicationTaskBatteryLow(BatteryStatus status) + { + NUIApplicationBatteryLowEventArgs e = new NUIApplicationBatteryLowEventArgs(); + + // Populate all members of "e" (NUIApplicationBatteryLowEventArgs) with real data + e.BatteryStatus = status; + applicationTaskBatteryLowEventHandler?.Invoke(this, e); + } + + /// + /// @brief Event for TaskMemoryLow signal which can be used to subscribe/unsubscribe the event handler + /// provided by the user. TaskMemoryLow signal is emitted when the memory level of the device is low. + /// + public event DaliEventHandler TaskMemoryLow + { + add + { + // Restricted to only one listener + if (applicationTaskMemoryLowEventHandler == null) + { + applicationTaskMemoryLowEventHandler += value; + + applicationTaskMemoryLowEventCallbackDelegate = new NUIApplicationMemoryLowEventCallbackDelegate(OnNUIApplicationTaskMemoryLow); + taskMemoryLowSignal = this.TaskMemoryLowSignal(); + taskMemoryLowSignal?.Connect(applicationTaskMemoryLowEventCallbackDelegate); + } + } + + remove + { + if (applicationTaskMemoryLowEventHandler != null) + { + taskMemoryLowSignal?.Disconnect(applicationTaskMemoryLowEventCallbackDelegate); + taskMemoryLowSignal?.Dispose(); + taskMemoryLowSignal = null; + } + + applicationTaskMemoryLowEventHandler -= value; + } + } + + private void OnNUIApplicationTaskMemoryLow(MemoryStatus status) + { + NUIApplicationMemoryLowEventArgs e = new NUIApplicationMemoryLowEventArgs(); + + // Populate all members of "e" (NUIApplicationMemoryLowEventArgs) with real data + e.MemoryStatus = status; + applicationTaskMemoryLowEventHandler?.Invoke(this, e); + } + + /// + /// @brief Event for TaskAppControl signal which can be used to subscribe/unsubscribe the event handler + /// provided by the user. TaskAppControl signal is emitted when another application sends a launch request to the application. + /// + public event DaliEventHandler TaskAppControl + { + add + { + // Restricted to only one listener + if (applicationTaskAppControlEventHandler == null) + { + applicationTaskAppControlEventHandler += value; + + applicationTaskAppControlEventCallbackDelegate = new NUIApplicationAppControlEventCallbackDelegate(OnNUIApplicationTaskAppControl); + taskAppControlSignal = this.TaskAppControlSignal(); + taskAppControlSignal?.Connect(applicationTaskAppControlEventCallbackDelegate); + } + } + + remove + { + if (applicationTaskAppControlEventHandler != null) + { + taskAppControlSignal?.Disconnect(applicationTaskAppControlEventCallbackDelegate); + taskAppControlSignal?.Dispose(); + taskAppControlSignal = null; + } + + applicationTaskAppControlEventHandler -= value; + } + } + + private void OnNUIApplicationTaskAppControl(IntPtr application, IntPtr voidp) + { + if (applicationTaskAppControlEventHandler != null) + { + NUIApplicationAppControlEventArgs e = new NUIApplicationAppControlEventArgs(); + e.VoidP = voidp; + e.Application = this; + applicationTaskAppControlEventHandler.Invoke(this, e); + } + } + protected static Application instance; // singleton public static Application Instance @@ -1100,6 +1472,19 @@ namespace Tizen.NUI return instance; } + public static Application NewApplication(string[] args, string stylesheet, NUIApplication.WindowMode windowMode, Rectangle positionSize, bool useUIThread) + { + if (instance != null) + { + return instance; + } + Application ret = New(args, stylesheet, windowMode, positionSize, useUIThread); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + + instance = ret; + return instance; + } + /// /// Ensures that the function passed in is called from the main loop when it is idle. /// @@ -1218,6 +1603,30 @@ namespace Tizen.NUI return ret; } + public static Application New(string[] args, string stylesheet, NUIApplication.WindowMode windowMode, Rectangle positionSize, bool useUIThread) + { + Application ret = null; + int argc = 0; + string argvStr = ""; + try + { + argc = args.Length; + argvStr = string.Join(" ", args); + + ret = new Application(Interop.Application.New(argc, stylesheet, (int)windowMode, Rectangle.getCPtr(positionSize), useUIThread), true); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + } + catch (Exception exception) + { + Tizen.Log.Fatal("NUI", "[Error] got exception during Application New(), this should not occur, message : " + exception.Message); + Tizen.Log.Fatal("NUI", "[Error] error line number : " + new StackTrace(exception, true).GetFrame(0).GetFileLineNumber()); + Tizen.Log.Fatal("NUI", "[Error] Stack Trace : " + exception.StackTrace); + throw; + } + + return ret; + } + public Application() : this(Interop.Application.NewApplication(), true) { if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); @@ -1393,5 +1802,55 @@ namespace Tizen.NUI if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; } + + //Task + internal ApplicationSignal TaskInitSignal() + { + ApplicationSignal ret = new ApplicationSignal(NDalicPINVOKE.ApplicationTaskInitSignal(SwigCPtr), false); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + internal ApplicationSignal TaskTerminateSignal() + { + ApplicationSignal ret = new ApplicationSignal(NDalicPINVOKE.ApplicationTaskTerminateSignal(SwigCPtr), false); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + internal ApplicationControlSignal TaskAppControlSignal() + { + ApplicationControlSignal ret = new ApplicationControlSignal(NDalicPINVOKE.ApplicationTaskAppControlSignal(SwigCPtr), false); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + internal ApplicationSignal TaskLanguageChangedSignal() + { + ApplicationSignal ret = new ApplicationSignal(NDalicPINVOKE.ApplicationTaskLanguageChangedSignal(SwigCPtr), false); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + internal ApplicationSignal TaskRegionChangedSignal() + { + ApplicationSignal ret = new ApplicationSignal(NDalicPINVOKE.ApplicationTaskRegionChangedSignal(SwigCPtr), false); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + internal LowBatterySignalType TaskBatteryLowSignal() + { + LowBatterySignalType ret = new LowBatterySignalType(NDalicPINVOKE.ApplicationTaskLowBatterySignal(SwigCPtr), false); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + internal LowMemorySignalType TaskMemoryLowSignal() + { + LowMemorySignalType ret = new LowMemorySignalType(NDalicPINVOKE.ApplicationTaskLowMemorySignal(SwigCPtr), false); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } } } diff --git a/src/Tizen.NUI/src/internal/Application/NUICoreBackend.cs b/src/Tizen.NUI/src/internal/Application/NUICoreBackend.cs index 4dc9b17..3fa6ce7 100755 --- a/src/Tizen.NUI/src/internal/Application/NUICoreBackend.cs +++ b/src/Tizen.NUI/src/internal/Application/NUICoreBackend.cs @@ -23,7 +23,7 @@ using Tizen.Applications; namespace Tizen.NUI { - class NUICoreBackend : ICoreBackend + class NUICoreBackend : ICoreTaskBackend { /// /// The Application instance to connect event. @@ -33,11 +33,13 @@ namespace Tizen.NUI private NUIApplication.WindowMode windowMode = NUIApplication.WindowMode.Opaque; private Rectangle windowRectangle = null; private WindowType defaultWindowType = WindowType.Normal; + private ICoreTask coreTask; /// /// The Dictionary to contain each type of event callback. /// protected IDictionary Handlers = new Dictionary(); + protected IDictionary TaskHandlers = new Dictionary(); /// /// The default Constructor. @@ -177,11 +179,29 @@ namespace Tizen.NUI { if (windowRectangle != null) { - application = Application.NewApplication(args, stylesheet, windowMode, windowRectangle); + if (coreTask != null) + { + application = Application.NewApplication(args, stylesheet, windowMode, windowRectangle, true); + } + else + { + application = Application.NewApplication(args, stylesheet, windowMode, windowRectangle); + } } else { - application = Application.NewApplication(args, stylesheet, windowMode); + if (coreTask != null) + { + // The Rectangle(0, 0, 0, 0) means that want to use the full screen size window at 0,0. + using (Rectangle rec = new Rectangle(0, 0, 0, 0)) + { + application = Application.NewApplication(args, stylesheet, windowMode, rec, true); + } + } + else + { + application = Application.NewApplication(args, stylesheet, windowMode); + } } } Tizen.Tracer.End(); @@ -201,11 +221,34 @@ namespace Tizen.NUI Tizen.Tracer.End(); + if (coreTask != null) + { + application.TaskBatteryLow += OnTaskBatteryLow; + application.TaskLanguageChanged += OnTaskLanguageChanged; + application.TaskMemoryLow += OnTaskMemoryLow; + application.TaskRegionChanged += OnTaskRegionChanged; + + application.TaskInitialized += OnTaskInitialized; + application.TaskTerminating += OnTaskTerminated; + application.TaskAppControl += OnTaskAppControl; + // Note: UIEvent, DeviceOrientationChanged are not implemented. + } + application.MainLoop(); application.Dispose(); } /// + /// Sets the core task. + /// + /// The core task interface. + /// 10 + public void SetCoreTask(ICoreTask task) + { + coreTask = task; + } + + /// /// The Region changed event callback function. /// /// The application instance. @@ -354,7 +397,7 @@ namespace Tizen.NUI { Log.Info("NUI", "NUICorebackend OnAppControl Called"); var handler = Handlers[EventType.AppControlReceived] as Action; - SafeAppControlHandle handle = new SafeAppControlHandle(e.VoidP, false); + using SafeAppControlHandle handle = new SafeAppControlHandle(e.VoidP, false); handler?.Invoke(new AppControlReceivedEventArgs(new ReceivedAppControl(handle))); } @@ -370,6 +413,118 @@ namespace Tizen.NUI handler?.Invoke(); } + /// + /// The Region changed event callback function. The callback is emitted on the main thread. + /// + /// The application instance. + /// The event argument for RegionChanged. + private void OnTaskRegionChanged(object source, NUIApplicationRegionChangedEventArgs e) + { + Log.Info("NUI", "NUICorebackend OnTaskRegionChanged Called"); + coreTask.OnRegionFormatChanged(new RegionFormatChangedEventArgs((source as Application)?.GetRegion())); + } + + /// + /// The Memory Low event callback function. The callback is emitted on the main thread. + /// + /// The application instance. + /// The event argument for MemoryLow. + private void OnTaskMemoryLow(object source, NUIApplicationMemoryLowEventArgs e) + { + Log.Info("NUI", "NUICorebackend OnTaskMemoryLow Called"); + switch (e.MemoryStatus) + { + case Application.MemoryStatus.Normal: + { + coreTask.OnLowMemory(new LowMemoryEventArgs(LowMemoryStatus.None)); + break; + } + case Application.MemoryStatus.Low: + { + coreTask.OnLowMemory(new LowMemoryEventArgs(LowMemoryStatus.SoftWarning)); + break; + } + case Application.MemoryStatus.CriticallyLow: + { + coreTask.OnLowMemory(new LowMemoryEventArgs(LowMemoryStatus.HardWarning)); + break; + } + } + } + + /// + /// The Language changed event callback function. The callback is emitted on the main thread. + /// + /// The application instance. + /// The event argument for LanguageChanged. + private void OnTaskLanguageChanged(object source, NUIApplicationLanguageChangedEventArgs e) + { + Log.Info("NUI", "NUICorebackend OnTaskLanguageChanged Called"); + coreTask.OnLocaleChanged(new LocaleChangedEventArgs((source as Application)?.GetLanguage())); + } + + /// + /// The Battery Low event callback function. The callback is emitted on the main thread. + /// + /// The application instance. + /// The event argument for BatteryLow. + private void OnTaskBatteryLow(object source, NUIApplicationBatteryLowEventArgs e) + { + Log.Info("NUI", "NUICorebackend OnTaskBatteryLow Called"); + switch (e.BatteryStatus) + { + case Application.BatteryStatus.Normal: + { + coreTask?.OnLowBattery(new LowBatteryEventArgs(LowBatteryStatus.None)); + break; + } + case Application.BatteryStatus.CriticallyLow: + { + coreTask?.OnLowBattery(new LowBatteryEventArgs(LowBatteryStatus.CriticalLow)); + break; + } + case Application.BatteryStatus.PowerOff: + { + coreTask?.OnLowBattery(new LowBatteryEventArgs(LowBatteryStatus.PowerOff)); + break; + } + } + } + + /// + /// The Initialized event callback function. The callback is emitted on the main thread. + /// + /// The application instance. + /// The event argument for Initialized. + private void OnTaskInitialized(object source, NUIApplicationInitEventArgs e) + { + Log.Info("NUI", "NUICorebackend OnTaskInitialized Called"); + coreTask.OnCreate(); + } + + /// + /// The Terminated event callback function. The callback is emitted on the main thread. + /// + /// The application instance. + /// The event argument for Terminated. + private void OnTaskTerminated(object source, NUIApplicationTerminatingEventArgs e) + { + Log.Info("NUI", "NUICorebackend OnTaskTerminated Called"); + coreTask.OnTerminate(); + } + + /// + /// The App control event callback function. The callback is emitted on the main thread. + /// + /// The application instance. + /// The event argument for AppControl. + private void OnTaskAppControl(object source, NUIApplicationAppControlEventArgs e) + { + Log.Info("NUI", "NUICorebackend OnTaskAppControl Called"); + using SafeAppControlHandle handle = new SafeAppControlHandle(e.VoidP, false); + coreTask.OnAppControlReceived(new AppControlReceivedEventArgs(new ReceivedAppControl(handle))); + } + internal Application ApplicationHandle { get diff --git a/src/Tizen.NUI/src/internal/Interop/Interop.Application.cs b/src/Tizen.NUI/src/internal/Interop/Interop.Application.cs index a4ab450..a258523 100755 --- a/src/Tizen.NUI/src/internal/Interop/Interop.Application.cs +++ b/src/Tizen.NUI/src/internal/Interop/Interop.Application.cs @@ -91,6 +91,9 @@ namespace Tizen.NUI [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Application_New__SWIG_5")] public static extern global::System.IntPtr New(int jarg1, string jarg3, int jarg4, global::System.Runtime.InteropServices.HandleRef jarg5, int jarg6); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Application_New__SWIG_6")] + public static extern global::System.IntPtr New(int jarg1, string jarg3, int jarg4, global::System.Runtime.InteropServices.HandleRef jarg5, bool jarg7); } } } diff --git a/src/Tizen.NUI/src/internal/Interop/NDalicPINVOKE.cs b/src/Tizen.NUI/src/internal/Interop/NDalicPINVOKE.cs index 62d0b49..d830f53 100755 --- a/src/Tizen.NUI/src/internal/Interop/NDalicPINVOKE.cs +++ b/src/Tizen.NUI/src/internal/Interop/NDalicPINVOKE.cs @@ -277,6 +277,28 @@ namespace Tizen.NUI [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Application_LowMemorySignal")] public static extern global::System.IntPtr ApplicationLowMemorySignal(global::System.Runtime.InteropServices.HandleRef jarg1); + //Task + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Application_TaskInitSignal")] + public static extern global::System.IntPtr ApplicationTaskInitSignal(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Application_TaskTerminateSignal")] + public static extern global::System.IntPtr ApplicationTaskTerminateSignal(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Application_TaskAppControlSignal")] + public static extern global::System.IntPtr ApplicationTaskAppControlSignal(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Application_TaskLanguageChangedSignal")] + public static extern global::System.IntPtr ApplicationTaskLanguageChangedSignal(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Application_TaskRegionChangedSignal")] + public static extern global::System.IntPtr ApplicationTaskRegionChangedSignal(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Application_TaskLowBatterySignal")] + public static extern global::System.IntPtr ApplicationTaskLowBatterySignal(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Application_TaskLowMemorySignal")] + public static extern global::System.IntPtr ApplicationTaskLowMemorySignal(global::System.Runtime.InteropServices.HandleRef jarg1); + [Obsolete("This has been deprecated in API9 and will be removed in API11. Use NDalicPINVOKE.DeleteBaseHandle(...) instead.")] [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_delete_BaseHandle")] diff --git a/src/Tizen.NUI/src/public/Application/NUIApplication.cs b/src/Tizen.NUI/src/public/Application/NUIApplication.cs index 1c4b472..8f84534 100755 --- a/src/Tizen.NUI/src/public/Application/NUIApplication.cs +++ b/src/Tizen.NUI/src/public/Application/NUIApplication.cs @@ -178,6 +178,7 @@ namespace Tizen.NUI /// The windowMode. /// The default window type. /// 9 + [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")] public NUIApplication(string styleSheet, WindowMode windowMode, WindowType type) : base(new NUICoreBackend(styleSheet, windowMode, type)) { ExternalThemeManager.Initialize(); @@ -193,6 +194,7 @@ namespace Tizen.NUI /// The window position. /// If borderInterface is null, defaultBorder is enabled. [EditorBrowsable(EditorBrowsableState.Never)] + [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")] public NUIApplication(string styleSheet, Size2D windowSize, Position2D windowPosition, IBorderInterface borderInterface, WindowMode windowMode = WindowMode.Opaque) : base(new NUICoreBackend(styleSheet, windowMode, windowSize, windowPosition)) { borderEnabled = true; @@ -200,6 +202,42 @@ namespace Tizen.NUI } /// + /// The constructor with a stylesheet, window mode, coretask + /// + /// + /// There is the UI thread feature. + /// UI thread is an additional thread that an Application object creates. The thread is for UI events. + /// To enable the UI Thread, you have to pass CoreTask object using this contructor. + /// When the UI thread feature is enabled, The methods of CoreTask are emitted on the main thread, + /// and the NUIApplication's events are emitted on the UI thread. + /// 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. + /// The CoreTask is not for handling GUI. + /// Callbacks of the all events in NUIApplication except the CoreTask are emitted on the UI thread. + /// + /// The styleSheet URL. + /// The windowMode. + /// True If app creates a UI Thread + [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")] + [EditorBrowsable(EditorBrowsableState.Never)] + public NUIApplication(string styleSheet, WindowMode windowMode, CoreTask task) : base(new NUICoreBackend(styleSheet, windowMode), task) + { + } + + /// + /// The constructor with a stylesheet, window mode, window size, position, coretask + /// + /// The styleSheet URL. + /// The windowMode. + /// The window size. + /// The window position. + /// True If app creates a UI Thread + [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")] + [EditorBrowsable(EditorBrowsableState.Never)] + public NUIApplication(string styleSheet, WindowMode windowMode, Size2D windowSize, Position2D windowPosition, CoreTask task) : base(new NUICoreBackend(styleSheet, windowMode, windowSize, windowPosition), task) + { + } + + /// /// Occurs whenever the application is resumed. /// /// 4 diff --git a/test/Tizen.NUI.UIThread/Tizen.NUI.UIThread.cs b/test/Tizen.NUI.UIThread/Tizen.NUI.UIThread.cs new file mode 100644 index 0000000..8c70f09 --- /dev/null +++ b/test/Tizen.NUI.UIThread/Tizen.NUI.UIThread.cs @@ -0,0 +1,160 @@ + +using Tizen.Applications; +using Tizen.NUI; +using Tizen.NUI.Components; +using Tizen.NUI.BaseComponents; + +namespace UIThreadApp +{ + public class AppCoreTask : CoreTask + { + public override void OnCreate() + { + Tizen.Log.Info("UIThreadApp", "CoreTask OnCreate"); + } + + public override void OnTerminate() + { + Tizen.Log.Info("UIThreadApp", "CoreTask OnTerminate"); + } + + public override void OnAppControlReceived(AppControlReceivedEventArgs e) + { + Tizen.Log.Info("UIThreadApp", "CoreTask OnAppControlReceived " + e.ReceivedAppControl.ApplicationId); + } + + public override void OnLowMemory(LowMemoryEventArgs e) + { + Tizen.Log.Info("UIThreadApp", "CoreTask OnLowMemory " + e.LowMemoryStatus); + } + + public override void OnLowBattery(LowBatteryEventArgs e) + { + Tizen.Log.Info("UIThreadApp", "CoreTask OnCreate " + e.LowBatteryStatus); + } + + public override void OnLocaleChanged(LocaleChangedEventArgs e) + { + Tizen.Log.Info("UIThreadApp", "CoreTask OnLocaleChanged " + e.Locale); + } + + public override void OnRegionFormatChanged(RegionFormatChangedEventArgs e) + { + Tizen.Log.Info("UIThreadApp", "CoreTask OnRegionFormatChanged " + e.Region); + } + } + + class Program : NUIApplication + { + private View root; + private Control control; + + public Program(string styleSheet, WindowMode windowMode, CoreTask task) : base(styleSheet, windowMode, task) + { + } + + protected override void OnCreate() + { + Tizen.Log.Info("UIThreadApp", "NUIApplication OnCreate"); + base.OnCreate(); + Initialize(); + } + + protected override void OnLocaleChanged(LocaleChangedEventArgs e) + { + Tizen.Log.Info("UIThreadApp", "NUIApplication OnLocaleChanged " + e.Locale); + } + + protected override void OnLowBattery(LowBatteryEventArgs e) + { + Tizen.Log.Info("UIThreadApp", "NUIApplication OnLowBattery " + e.LowBatteryStatus); + } + + protected override void OnLowMemory(LowMemoryEventArgs e) + { + Tizen.Log.Info("UIThreadApp", "NUIApplication OnLowMemory " + e.LowMemoryStatus); + } + + protected override void OnRegionFormatChanged(RegionFormatChangedEventArgs e) + { + Tizen.Log.Info("UIThreadApp", "NUIApplication OnRegionFormatChanged " + e.Region); + } + + protected override void OnTerminate() + { + Tizen.Log.Info("UIThreadApp", "NUIApplication OnTerminate"); + } + + protected override void OnPause() + { + Tizen.Log.Info("UIThreadApp", "NUIApplication OnPause"); + } + + protected override void OnResume() + { + Tizen.Log.Info("UIThreadApp", "NUIApplication OnResume"); + } + + protected override void OnPreCreate() + { + Tizen.Log.Info("UIThreadApp", "NUIApplication OnPreCreate"); + } + + protected override void OnAppControlReceived(AppControlReceivedEventArgs e) + { + Tizen.Log.Info("UIThreadApp", "NUIApplication OnAppControlReceived " + e.ReceivedAppControl.ApplicationId); + } + + void Initialize() + { + + Window window = NUIApplication.GetDefaultWindow(); + + root = new View() + { + Size = window.Size, + BackgroundColor = new Color(0.8f, 0.8f, 0.8f, 0.6f), + ParentOrigin = ParentOrigin.Center, + PivotPoint = PivotPoint.Center, + PositionUsesPivotPoint = true, + }; + window.Add(root); + + control = new Control() + { + Size = new Size(100, 100), + BackgroundColor = Color.Blue, + ParentOrigin = ParentOrigin.Center, + PivotPoint = PivotPoint.Center, + PositionUsesPivotPoint = true, + BoxShadow = new Shadow(0, new Color(0.2f, 0.2f, 0.2f, 0.3f), new Vector2(5, 5)), + CornerRadius = 0.5f, + CornerRadiusPolicy = VisualTransformPolicyType.Relative, + }; + + root.Add(control); + + var animation = new Animation(2000); + animation.AnimateTo(control, "SizeWidth", 200, 0, 1000); + animation.AnimateTo(control, "SizeWidth", 100, 1000, 2000); + animation.Looping = true; + animation.Play(); + + NUIApplication.GetDefaultWindow().KeyEvent += OnKeyEvent; + } + + public void OnKeyEvent(object sender, Window.KeyEventArgs e) + { + if (e.Key.State == Key.StateType.Down && (e.Key.KeyPressedName == "XF86Back" || e.Key.KeyPressedName == "Escape")) + { + Exit(); + } + } + + static void Main(string[] args) + { + var app = new Program("", NUIApplication.WindowMode.Opaque, new AppCoreTask()); + app.Run(args); + } + } +} diff --git a/test/Tizen.NUI.UIThread/Tizen.NUI.UIThread.csproj b/test/Tizen.NUI.UIThread/Tizen.NUI.UIThread.csproj new file mode 100644 index 0000000..1badb70 --- /dev/null +++ b/test/Tizen.NUI.UIThread/Tizen.NUI.UIThread.csproj @@ -0,0 +1,26 @@ + + + + Exe + netcoreapp3.1 + + + + portable + + + None + + + + + + + + + + + True + + + diff --git a/test/Tizen.NUI.UIThread/shared/res/Tizen.NUI.UIThread.png b/test/Tizen.NUI.UIThread/shared/res/Tizen.NUI.UIThread.png new file mode 100644 index 0000000000000000000000000000000000000000..9f3cb98608134e7b9eb4beb7394fec9f03e40f63 GIT binary patch literal 10097 zcmV-%Cyv;OP)KLZ*U+5Lu!Sk^o_Z5E4Meg@_7P6crJiNL9pw)e1;Xm069{HJUZAPk55R%$-RIA z6-eL&AQ0xu!e<4=008gy@A0LT~suv4>S3ILP<0Bm`DLLvaF4FK%)Nj?Pt*r}7;7Xa9z9H|HZjR63e zC`Tj$K)V27Re@400>HumpsYY5E(E}?0f1SyGDiY{y#)Yvj#!WnKwtoXnL;eg03bL5 z07D)V%>y7z1E4U{zu>7~aD})?0RX_umCct+(lZpemCzb@^6=o|A>zVpu|i=NDG+7} zl4`aK{0#b-!z=TL9Wt0BGO&T{GJWpjryhdijfaIQ&2!o}p04JRKYg3k&Tf zVxhe-O!X z{f;To;xw^bEES6JSc$k$B2CA6xl)ltA<32E66t?3@gJ7`36pmX0IY^jz)rRYwaaY4 ze(nJRiw;=Qb^t(r^DT@T3y}a2XEZW-_W%Hszxj_qD**t_m!#tW0KDiJT&R>6OvVTR z07RgHDzHHZ48atvzz&?j9lXF70$~P3Knx_nJP<+#`N z#-MZ2bTkiLfR>_b(HgWKJ%F~Nr_oF3b#wrIijHG|(J>BYjM-sajE6;FiC7vY#};Gd zST$CUHDeuEH+B^pz@B062qXfFfD`NpUW5?BY=V%GM_5c)L#QR}BeW8_2v-S%gfYS= zB9o|3v?Y2H`NVi)In3rTB8+ej^> zQ=~r95NVuDChL%G$=>7$vVg20myx%S50Foi`^m%Pw-h?Xh~i8Mq9jtJloCocWk2Nv zrJpiFnV_ms&8eQ$2&#xWpIS+6pmtC%Q-`S&GF4Q#^mhymh7E(qNMa}%YZ-ePrx>>xFPTiH1=E+A$W$=bG8>s^ zm=Bn5Rah$aDtr}@$`X}2l~$F0mFKEdRdZE8)p@E5RI61Ft6o-prbbn>P~)iy)E2AN zsU20jsWz_8Qg>31P|s0cqrPALg8E|(vWA65poU1JRAaZs8I2(p#xiB`SVGovRs-uS zYnV-9TeA7=Om+qP8+I>yOjAR1s%ETak!GFdam@h^# z)@rS0t$wXH+Irf)+G6c;?H29p+V6F6oj{!|o%K3xI`?%6x;DB|x`n#ibhIR?(H}Q3Gzd138Ei2)WAMz7W9Vy`X}HnwgyEn!VS)>mv$8&{hQn>w4zwy3R}t;BYlZQm5)6pty=DfLrs+A-|>>;~;Q z_F?uV_HFjh9n2gO9o9Q^JA86v({H5aB!kjoO6 zc9$1ZZKsN-Zl8L~mE{`ly3)1N^`o1+o7}D0ZPeY&J;i;i`%NyJ8_8Y6J?}yE@b_5a zam?eLr<8@mESk|3$_SkmS{wQ>%qC18))9_|&j{ZT zes8AvOzF(F2#DZEY>2oYX&IRp`F#{ADl)1r>QS^)ba8a|EY_^#S^HO&t^Rgqwv=MZThqqEWH8 zxJo>d=ABlR_Bh=;eM9Tw|Ih34~oTE|= zX_mAr*D$vzw@+p(E0Yc6dFE}(8oqt`+R{gE3x4zjX+Sb3_cYE^= zgB=w+-tUy`ytONMS8KgRef4hA?t0j zufM;t32jm~jUGrkaOInTZ`zyfns>EuS}G30LFK_G-==(f<51|K&cocp&EJ`SxAh3? zNO>#LI=^+SEu(FqJ)ynt=!~PC9bO$rzPJB=?=j6w@a-(u02P7 zaQ)#(uUl{HW%tYNS3ItC^iAtK(eKlL`f9+{bJzISE?u8_z3;~C8@FyI-5j_jy7l;W z_U#vU3hqqYU3!mrul&B+{ptt$59)uk{;_4iZQ%G|z+lhASr6|H35TBkl>gI*;nGLU zN7W-nBaM%pA0HbH8olyl&XeJ%vZoWz%6?Y=dFykl=imL}`%BMQ{Mhgd`HRoLu6e2R za__6DuR6yg#~-}Tc|Gx_{H@O0eebyMy5GmWADJlpK>kqk(fVV@r_fLLKIeS?{4e)} z^ZO;zpECde03c&XQcVB=dL;k=fP(-4`Tqa_faw4Lbua(`>RI+y?e7jKeZ#YO-C z9G*!;K~#9!?45adROR)@KX>k(nam`UjU_-Jvaf<7q7+#w0xcl2xgaWPU0Rp6YNfW; zpJHvRty^2f)(u1jtRN^Tn}`aihzKGe`@V%WnIyB{<@d*XLlVd`%gu!CJkLDDn7PaQ zeb0H%`JQv$S27HP^Ky2H?fej&eWH~9AU#`froT%Apc!xhkZt~V1HcV900~fm5KsUd z0=&RpU>~px(9YxmFvew71oaFPJ8%(jInc%Yv;-Q)dA%U81K13#2fhKm1M<&kO+C%U z1@tq)>kRY-npk-K6riK|8Dah|0;~X*16zTWz=rdnCN6z}G3G!wr~_-z+x(Qu=fF(h zJ>bZBP@|X2fC0d8;L_9V*?ww%o&lx-p8@Zl_kOFEUcel4J^RaP2xxgp1MUWG zxAPg`)fsrPlfREjqjPh+_+9ekW?&=G|7;3rh5=K6jHC^t1Q%x_nVGTMpCsiY`|fSi(A=Q{L73JfC6ZSQJ2yAO~8Dh z&6%pH3xR=2_Yewn2pQZzz|Dk#?o<9GRQHtq&w)({wru&CqN#bnlB5D!&fI3F+j!^p z^hyCe&G><3z@2A;rskSXfjgbkx)qz^bG>L-`tct?Vqm#Y3AcnKM}ah=`saIbAfh zJ@8f1W6xrPTds7m?%s?u9nezwJuv=s&{PFcA>d9Lpd|*B=u8;x;r?z;&N6udI0(E_ zmzugDX@E*V(14J^D`U?}KuhJnB*;D`0_w-WRY`kQ11Q${^EIj5-TABqv{XJp6woCV z)SH08Nqxb~vgrZ$~6K&Y59)-8!OeN;L%E z95TQ!SS`Fd9M{C>nE7wmK$6Vwg$)Rp-$~pZxBz%Inm>$&CVUyuYm!_s02zAaibuS> zvG{lKUX^<;j-Px`Y$ia(dRe%n85Jj!1W1yg*lp&|3SgITD3IomNOwwPIVBppZDgcK zbZ#KiAkD@%yCY0q9TEj@Su*J!iIT8^eoO;d0&|ka3G&0h1Yl1hpteHP7$skV2KM?g zgIWr!e`zBb8Y?W>nV6P+;heWDf!d5P3{$h883Cn{NMhqV7$(6x;Dgf z*L(O~cWbD|5HNgdF$=F-t9*FsJyNY!#{#PO2AJ!}b^z98{QXV|Q znu97|K9S-U1gw;XG7uaA7?jZPh?@jX%?Xz=8>p&Bn!5HYx8 zP6;=?U4+kXK(1WDCyG~wO)cgh(~5cKt_im9$YClIHHv~Y0=3I zv4Yw&W}{%Slhil2@|i!PjRUEJon>DK*;QQig0%6NMyH8hCVd)!44d#ewZs$1-Cr(b z&L@6mKAO!VJrfTKZtvn`!+jaFZmPguRfIv&J><2qg8Iw4jhy6;F!jU z4@xTc`#<&5`DHH$4{MO8fKujZCZecaCwf`6I>g-Z^%&L0IxeO~x{bB>X7bpuG*PNk z7?nBh3tSj2s0~PVuJq*iRDllls(!0GJ38pl*TwgX158>UKJoh_L4zUFig|vn4^20q zo-N+6;S~AFt6sie9c0my^|-pZ^)>Kr8$8v|#XC27kQGU^j8LP!{AIMD-chG28ZvO! zm$@>pdQJH605_ya+`q^Nz>+-?I=$>=-l`DfDv)X&pf}7aVa1XFlgDK-Ah&jVHg4+Z zV8d@S>3g9=02`{-9FM7t7^>{gZ>v*KOLTfSvy+`t{S@t!t1xhoo51!6o!%_ss<(?d zQlLSuoVcAW9|Eih^4^C&{`OENx3y1B!(O{g8=v2r&XdDag*grxRcUNCqG+L7P+I`) zVhTNKfnOieBD(cz=8#mHwR7;}nvkI2GHjMU&*D8QPrd5px{+!8@v`JIrH}V^@zV8a zqTsIT1XY)sKy4e<-DF7+)j?el+lMtM(glZ_h|jDVkY?j&Euu4V9=pVXThayPRtpLA z(eIZ)x{ZwoRX*4nsT0FBqP4vy%hSCkP#_iSrxgqDz3L$uaPqo(vPwkPsaB-%^VTk|xhY%lbjc_nu zq@hTWAk8N3RMUV24f-~To$-00kBcvNM_Bno7#hh5gZs>?5DPx@LkqjG02ww28BAE{ zRX zB674&QxVe5d)Hj>(Wfd$i%Tzdgc7qdhUNGT$9kdH2UKv$jOou}>A=twR!8nIl)Ipo~&_RAqiI ziuw{ZF?-(H5Uv!|Q|{PQp+{4N7Y4x0jbY|(i?H^X#@f9q9M{22ujS+_^vjE%skyg{ zlh3bmGh=xG;xLcb&G8XDq>4DVDw0?OQYCOH%=<1xmqMM1SEtga8bUv;!8iLo+9f8|$0hOcE;Xh*%M#qs(ZLNJ9Vce&|2BsC zU~`16Tf!VVu3=A*oPBR-DvnKIBF8nT7ybJBukS-F`Z@qPO3mLf%!!>NvwnAkzAqK> zP=7bi_pjJiv}~`++v`Gnyd%Pa!zPiSB&3m5NgmJvSbH+4tz){3Q=*_yV|$@atIYV2 z=+;=FTVsWP^n5eoFkY(R(A)81b4{#CJ}qY|wO3wQ#bm$k%va zW(j1-!pk(GoY;Y~+M^d1`}z8i#;-4Ovcsn{^@k7}_o)?q2@j{5bL*sSDX8VqXdcrg z>=G1e%-$NdCE35q4`tCx#MFWi{mU^8Q#jyQzOzuA(&BdvDsO0s@E}O zdXeyQQ>Cg0TSA!RVsn$NqZ*zx8)JLAn0t2yhn}d%;FfmAyyoSx86|Aoqk_vOG&0SW zjO~3+?0+nk9*iJ8TMz_dD+wsjxv;&Rbz{>ld$Q-g4KZ$#SGe(ZiMGuYZtUowcT*8%1o|9RW|dVz02lpmq+f>)@b$wv7p^Lrh;Dfco;OfR5^UM8^5pgiI3=>OWrnx0Gp3V+{!vhgvqq%S@x?;n+{os~Au)e-kon(- z%9yC~WQRn>(oPwgHnlUnm7VK5Iq2Q2dbaD?J}&034vF3RliT2)Ru%aWnEz&wCJNn~R<6M_wni#4 zTc!0t*`^k01~_e|X+=<;0RysZbk0-gnxinHt)0Pb95|u`s8fBJ-d&t5TN4!bNuIc@ z0o4FfB&Ke%4pe|!+BW88PF?W14VyY*EbZfPuXh{F%!eD_oIWZPly;6_a)JYCONnI_F?ObA|LA z1^m^ZYIep^U;-&Y>pX?AeO%PbwuwELs(VAT%J7bleJt6nQf#rtKG4-!wszOPsMa}3 zrP`WquMLr%Dbuxq%nh9cIgy!?n2HT;?Lew8WB82|NsC&PptYI` z;I^S1(|GzT>$G+J6)x-?IR!awnZoi#HYbd8PT;@ ztS7?+2P)IlFp2DMF98`ckIwh;!y%1-4s?-|8vmR*7BpD8CqhIwV7~@U?F{Lb!nN(~ z3}|jAH@)U-4{C1b=~7D~i|_@nPIfbe?u{KR+!hgQZ;Dwi;*vx^gaO`SGfes>NP4D? zt_>A#=;UBjJ39?yc(1?oaxrgBQW&O^%DCU%h!jp@ZdX_Y^BGNL#&mSjH&3B!Lz!HU zja2)o)72L-@Q2}0KxgAIjfFc^7Vn6#uS7=+8C;sHFsi+SQ5_t#$%<`~w0_0Q_Wi2x zh$G-q;K@EN?zq@Vc8bK~%L6<$vjmzbRclhIx%Y{M(OqAr-vxHA%u~3&gM+3~Os?+J zidnTTB$)J9LD2qs3B*3eamSv-7o}I0SHFg$hly>P#rO6N#20UXg7-N(iBt5Yj#^NbP}tPIv%+f-WG z5)=SC>dAzI1{XJwd8)sgt6Ntc=g!_5VdNw)WXZK@hOalqWz9I*{BE-hR6{r*9-v19 zna6vkP!u%yWOsxeg*rZyr*O#7z%9`-L#BPUP4K=JZ1ei|rmz4s+g9P3>Q~~d%o>?W z=Jqh*0v)odAuCEXOf_iH%FdQMGx%_8g!|`|F!YTgF1kSBxq)u_w>%Zxfz1`cFa=Fh zUpum;vNd(BrMIw491Ixzd6A!)8x-CcmdXoP*8Ya0$AboA-zyQh(ef0b1d&R}2$wAJ z&L|Jpzv>lBM@{j7-{6vl3W@}y+S(cQa2D$iYdo;P$ADM8w8@c~Jlew*jms{SYL^(< z&cUo@0dUod3El(zSef^`&eGc$h(XP?@#8_2pG+uZ)XWmR;o40yj{KlRWLrF^YF$-# zzOId(oBO%os9JqIU@F;_c@?e6g$-pEk4>iiJyLYAY#+nfBCy(>lUcm|UY@*P$W34evUsXjDmLLw* zvtD%5oo_6YU!d{$`z7?6QpC0b>!_9=3v?zd@Cj!m&PeLbYtn=!`73E3k$@tdfvxRi z)vzw!(AkOqPuUD^XQ$s^jx*kz#DD3TBAi3(8Ky6*<9-*^s%_K-^F&jHFE@s1Ke3R9 z7Wqju6>uzQ(0@viFmG-t?ltSmrV7vA=n>{ytK`}368Ch8zCdK=Xb+QqmBEt>{5-JG z&)}AJvhozsgJhi)Ri~+?Cb)K`bifc25z6hjk|SQ$!b2m7s1S zS)z-uhsFv!4yyE-T*OW9mvF!z8!E4D2=m#uL1?U4X4a++aii3iE4JzT3`WGcB|y6@ z8>`0GFmcPm%Ys19GyYlT&Q#R z|BA)ru#kdl>ap?eXpi8V!)0FYWeJqHbZa29>_!itd>jjXQ;RDek&TXaMw zB~PKit26S=VunmFX5G=M{eOSNp!b_a!twCfERX$0wX$_*m6yCcyQ1=}&m+qN9N7_xezOh<0x_Dr ziTzx-n<%g|LZ222O+ASxwI*EUCOy}(gL!AbseWc{JE(Az~U zDp#%l=obNAno%Oijbj=V)bKej`dDIx#BG;YGBzD&mdu!T*6jBn0k?H^3J*JRd8x8r zR%HZU2d<_rMMpFexn<4YOdE%57bocnyP1M>KxgBL&4Bot7##_-b<)UnF+zxI9PZ z+Wu~uWm=bdZeR`nyR1Al7!9b)D64CyPPJA7n#fS3^XA7s9=X}Wtl?=fU#jQ3#T<(> ze;)`LJh3FepxdpfI9z>5wPIx7tLlGLHT{kQZ*jVa1{CW&daH+L`ovc>zPC`1t1kJI zJu35m2=VR8An$LtrVMu3LCuPK;2E)k3h;jprQI(BmM*DK=h0?7C4G)ari zgic%&V&E%Zu`MG~uu?V$1Hb|E_c2K4NyTu8;((J7fQAH7dNTVV)aV8#6p@z+Z zYhA)X1g4Hnr)>g`%8nvkY&V-8-8F9hpoD+S@d?^7%~rP0ej|k+z7O$-FXJz+o4qX} z`c~st`2PU@L_pnvIDIksA_My)4DRk^Oxwg9l=Vk62pTj_t9~6j8Zx-#RWDPQ2E^_x zC->nbUvuc;~+rt{&|LbMVmWU`stE^MbEYm?U`1xDKSSH31l4}+@BqYh-t9M~S= zwgtYJo@4Tca9Ph!>~er8&n%Dj@~HGxY6Z z0apDeDMuY>qOkD05Hq6;a}N4+zS^aVd~*C}(qJX1ev)xMjSS?gT++?S6BZqQd&nnF zdm2;8wyqC+>SxR=UNOkAZusmF)XjBo7O}aY=Jj>*x-iBOHQxAi1u)%ePyrU3@loxW z-9jBtj>7!wJeFPd!|h>kN(^mPrl}zVezU;GzZUsL+AlSZg0Rvmj)1`pAJ%M!r)>(0 ztq5Y*(js7FtS(6`az9X9D}bs3)XAgLXlP+G(PPVkT-2(pu1Etef5Xd!d45sPOpQ`C0Iukpj=__8=ZizrM)5Fy*n2?z=f16Xnr&W~XEZwIoz}(Ug2}aH+slw|G ziK^V#MtdD_O}s-IkGuoSvBd294N&0CtE~m}fKTVgbs;8Q?_t5N2$%fFD;k{|)ey48 zYliE|6y>Yj^ijq2^=Lq6{+38QUhg%D=t;aX43VNsY%q#-Ub-=z9*wO%MWXLJ#q{l# zf^5K`SBo%I!;)&lYNejcw1s|N_%2i~WQw5XtFiXb3_#S2B^^`{J9&HK{&u0pH9b?f zuZy*(NZh;7&$ew5A~M|iVToXYJhcpHX~jmCjXy2%lW(>@PFWv{mFvCNj5OkwMAajR z*v)$-P%rjx8w|2=tDC(=I{&vcz?3hy`?~7Pod88 z{VI{8+KH0W6Q|ZDbK^&|p1H)UQ*zu8Tf#;s&jC+b5+RmrI!^Rjoq^902jE1{AeoF$ z+}>y@V6xeAku0sWR-OhPP1sP3%d$*U%e&y+5KUH@QGG)*O=F6MrBG)cpyRF5P^%oJ zlVumso|C$;&P$c@3#$RG4NyU(>Ush5&tq1l_<^f{$+dCu+S~+uFm-vR`ROZ55a;PF zsjVB-_Rj7T5yvd&pT|;g5vGRjtIeC(lJFw$0WE>4=P;PZf!>JoPHSCkNqVUOa5JLb zDR_G=BG2zA93J)m(vu;5b!pl^XxOq?KXBgh;kYZ*gEs`A|hXVBQTt3`Q+Mn zerB2;?f%o%bSRwOvdH{AfH)(xD{!S5^EIgDdmHAu|EUS)c9OXz(OC>?sdy1df-e#K z9Jqmt5hwh1HqCSkAS=%6tEQu~1+jVK3Sbqm_e}KIPUKV1%h@Bg^Fwg<$^Q=k6D;UR TJbOA100000NkvXXu0mjf?x(Kf literal 0 HcmV?d00001 diff --git a/test/Tizen.NUI.UIThread/tizen-manifest.xml b/test/Tizen.NUI.UIThread/tizen-manifest.xml new file mode 100644 index 0000000..ba61a12 --- /dev/null +++ b/test/Tizen.NUI.UIThread/tizen-manifest.xml @@ -0,0 +1,17 @@ + + + + + + Tizen.NUI.UIThread.png + + + + -- 2.7.4