/*
- * Copyright(c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2024 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
OnResourcesChanged(changedResources);
}
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate void RootIdleCallbackType();
+
+ private RootIdleCallbackType rootIdleCallback = null;
+ private Dictionary<System.Delegate, bool> idleCallbackMap = new Dictionary<System.Delegate, bool>();
+
+ private void RootIdleCallback()
+ {
+ if (idleCallbackMap == null || IsDisposedOrQueued)
+ {
+ Tizen.Log.Error("NUI", $"[Error] Application disposed! Fail to execute idle callback!\n");
+ return;
+ }
+
+ Tizen.Log.Debug("NUI", $"Application RootIdleCallback comes\n");
+ // Reset root idle callback as null now, since we could call AddIdle during delegate function invoke
+ rootIdleCallback = null;
+
+ // Copy key list of idle callback map
+ // (Since idle callback could change the dictionary itself during iteration, we need to make a copy of keys first)
+ List<System.Delegate> delegateList = new List<System.Delegate>();
+ foreach (var func in idleCallbackMap.Keys)
+ {
+ delegateList.Add(func);
+ }
+
+ foreach (var func in delegateList)
+ {
+ // Remove delegate at map first, and then invoke it.
+ bool isValid = false;
+ if (idleCallbackMap?.Remove(func, out isValid) ?? false)
+ {
+ if (isValid)
+ {
+ func.DynamicInvoke();
+ }
+ }
+ }
+ Tizen.Log.Debug("NUI", $"Application RootIdleCallback finished\n");
+ }
+
internal Application(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
{
SetCurrentApplication(this);
return;
}
- //Release your own unmanaged resources here.
- //You should not access any managed member here except static instance.
- //because the execution order of Finalizes is non-deterministic.
- if (applicationInitEventCallbackDelegate != null)
+ if (type == DisposeTypes.Explicit)
{
- initSignal?.Disconnect(applicationInitEventCallbackDelegate);
- initSignal?.Dispose();
- initSignal = null;
- }
+ //Release your own unmanaged resources here.
+ //You should not access any managed member here except static instance.
+ //because the execution order of Finalizes is non-deterministic.
+ if (applicationInitEventCallbackDelegate != null)
+ {
+ initSignal?.Disconnect(applicationInitEventCallbackDelegate);
+ initSignal?.Dispose();
+ initSignal = null;
+ }
- if (applicationTerminateEventCallbackDelegate != null)
- {
- terminateSignal?.Disconnect(applicationTerminateEventCallbackDelegate);
- terminateSignal?.Dispose();
- terminateSignal = null;
- }
+ if (applicationTerminateEventCallbackDelegate != null)
+ {
+ terminateSignal?.Disconnect(applicationTerminateEventCallbackDelegate);
+ terminateSignal?.Dispose();
+ terminateSignal = null;
+ }
- if (applicationPauseEventCallbackDelegate != null)
- {
- pauseSignal?.Disconnect(applicationPauseEventCallbackDelegate);
- pauseSignal?.Dispose();
- pauseSignal = null;
- }
+ if (applicationPauseEventCallbackDelegate != null)
+ {
+ pauseSignal?.Disconnect(applicationPauseEventCallbackDelegate);
+ pauseSignal?.Dispose();
+ pauseSignal = null;
+ }
- if (applicationResumeEventCallbackDelegate != null)
- {
- resumeSignal?.Disconnect(applicationResumeEventCallbackDelegate);
- resumeSignal?.Dispose();
- resumeSignal = null;
- }
+ if (applicationResumeEventCallbackDelegate != null)
+ {
+ resumeSignal?.Disconnect(applicationResumeEventCallbackDelegate);
+ resumeSignal?.Dispose();
+ resumeSignal = null;
+ }
- if (applicationResetEventCallbackDelegate != null)
- {
- resetSignal?.Disconnect(applicationResetEventCallbackDelegate);
- resetSignal?.Dispose();
- resetSignal = null;
- }
+ if (applicationResetEventCallbackDelegate != null)
+ {
+ resetSignal?.Disconnect(applicationResetEventCallbackDelegate);
+ resetSignal?.Dispose();
+ resetSignal = null;
+ }
- if (applicationLanguageChangedEventCallbackDelegate != null)
- {
- languageChangedSignal?.Disconnect(applicationLanguageChangedEventCallbackDelegate);
- languageChangedSignal?.Dispose();
- languageChangedSignal = null;
- }
+ if (applicationLanguageChangedEventCallbackDelegate != null)
+ {
+ languageChangedSignal?.Disconnect(applicationLanguageChangedEventCallbackDelegate);
+ languageChangedSignal?.Dispose();
+ languageChangedSignal = null;
+ }
- if (applicationRegionChangedEventCallbackDelegate != null)
- {
- regionChangedSignal?.Disconnect(applicationRegionChangedEventCallbackDelegate);
- regionChangedSignal?.Dispose();
- regionChangedSignal = null;
- }
+ if (applicationRegionChangedEventCallbackDelegate != null)
+ {
+ regionChangedSignal?.Disconnect(applicationRegionChangedEventCallbackDelegate);
+ regionChangedSignal?.Dispose();
+ regionChangedSignal = null;
+ }
- if (applicationBatteryLowEventCallbackDelegate != null)
- {
- batteryLowSignal?.Disconnect(applicationBatteryLowEventCallbackDelegate);
- batteryLowSignal?.Dispose();
- batteryLowSignal = null;
- }
+ if (applicationBatteryLowEventCallbackDelegate != null)
+ {
+ batteryLowSignal?.Disconnect(applicationBatteryLowEventCallbackDelegate);
+ batteryLowSignal?.Dispose();
+ batteryLowSignal = null;
+ }
- if (applicationMemoryLowEventCallbackDelegate != null)
- {
- memoryLowSignal?.Disconnect(applicationMemoryLowEventCallbackDelegate);
- memoryLowSignal?.Dispose();
- memoryLowSignal = null;
- }
+ if (applicationMemoryLowEventCallbackDelegate != null)
+ {
+ memoryLowSignal?.Disconnect(applicationMemoryLowEventCallbackDelegate);
+ memoryLowSignal?.Dispose();
+ memoryLowSignal = null;
+ }
- if (applicationDeviceOrientationChangedEventCallback != null)
- {
- deviceOrientationChangedSignal?.Disconnect(applicationDeviceOrientationChangedEventCallback);
- deviceOrientationChangedSignal?.Dispose();
- deviceOrientationChangedSignal = null;
- }
+ if (applicationDeviceOrientationChangedEventCallback != null)
+ {
+ deviceOrientationChangedSignal?.Disconnect(applicationDeviceOrientationChangedEventCallback);
+ deviceOrientationChangedSignal?.Dispose();
+ deviceOrientationChangedSignal = null;
+ }
- if (applicationAppControlEventCallbackDelegate != null)
- {
- appControlSignal?.Disconnect(applicationAppControlEventCallbackDelegate);
- appControlSignal?.Dispose();
- appControlSignal = null;
- }
+ if (applicationAppControlEventCallbackDelegate != null)
+ {
+ appControlSignal?.Disconnect(applicationAppControlEventCallbackDelegate);
+ appControlSignal?.Dispose();
+ appControlSignal = null;
+ }
- //Task
- if (applicationTaskInitEventCallbackDelegate != null)
- {
- taskInitSignal?.Disconnect(applicationTaskInitEventCallbackDelegate);
- taskInitSignal?.Dispose();
- taskInitSignal = null;
- }
+ //Task
+ if (applicationTaskInitEventCallbackDelegate != null)
+ {
+ taskInitSignal?.Disconnect(applicationTaskInitEventCallbackDelegate);
+ taskInitSignal?.Dispose();
+ taskInitSignal = null;
+ }
- if (applicationTaskTerminateEventCallbackDelegate != null)
- {
- taskTerminateSignal?.Disconnect(applicationTaskTerminateEventCallbackDelegate);
- taskTerminateSignal?.Dispose();
- taskTerminateSignal = null;
- }
+ if (applicationTaskTerminateEventCallbackDelegate != null)
+ {
+ taskTerminateSignal?.Disconnect(applicationTaskTerminateEventCallbackDelegate);
+ taskTerminateSignal?.Dispose();
+ taskTerminateSignal = null;
+ }
- if (applicationTaskLanguageChangedEventCallbackDelegate != null)
- {
- taskLanguageChangedSignal?.Disconnect(applicationTaskLanguageChangedEventCallbackDelegate);
- taskLanguageChangedSignal?.Dispose();
- taskLanguageChangedSignal = null;
- }
+ if (applicationTaskLanguageChangedEventCallbackDelegate != null)
+ {
+ taskLanguageChangedSignal?.Disconnect(applicationTaskLanguageChangedEventCallbackDelegate);
+ taskLanguageChangedSignal?.Dispose();
+ taskLanguageChangedSignal = null;
+ }
- if (applicationTaskRegionChangedEventCallbackDelegate != null)
- {
- taskRegionChangedSignal?.Disconnect(applicationTaskRegionChangedEventCallbackDelegate);
- taskRegionChangedSignal?.Dispose();
- taskRegionChangedSignal = null;
- }
+ if (applicationTaskRegionChangedEventCallbackDelegate != null)
+ {
+ taskRegionChangedSignal?.Disconnect(applicationTaskRegionChangedEventCallbackDelegate);
+ taskRegionChangedSignal?.Dispose();
+ taskRegionChangedSignal = null;
+ }
- if (applicationTaskBatteryLowEventCallbackDelegate != null)
- {
- taskBatteryLowSignal?.Disconnect(applicationTaskBatteryLowEventCallbackDelegate);
- taskBatteryLowSignal?.Dispose();
- taskBatteryLowSignal = null;
- }
+ if (applicationTaskBatteryLowEventCallbackDelegate != null)
+ {
+ taskBatteryLowSignal?.Disconnect(applicationTaskBatteryLowEventCallbackDelegate);
+ taskBatteryLowSignal?.Dispose();
+ taskBatteryLowSignal = null;
+ }
- if (applicationTaskMemoryLowEventCallbackDelegate != null)
- {
- taskMemoryLowSignal?.Disconnect(applicationTaskMemoryLowEventCallbackDelegate);
- taskMemoryLowSignal?.Dispose();
- taskMemoryLowSignal = null;
- }
+ if (applicationTaskMemoryLowEventCallbackDelegate != null)
+ {
+ taskMemoryLowSignal?.Disconnect(applicationTaskMemoryLowEventCallbackDelegate);
+ taskMemoryLowSignal?.Dispose();
+ taskMemoryLowSignal = null;
+ }
- if (applicationTaskDeviceOrientationChangedEventCallback != null)
- {
- taskDeviceOrientationChangedSignal?.Disconnect(applicationTaskDeviceOrientationChangedEventCallback);
- taskDeviceOrientationChangedSignal?.Dispose();
- taskDeviceOrientationChangedSignal = null;
- }
+ if (applicationTaskDeviceOrientationChangedEventCallback != null)
+ {
+ taskDeviceOrientationChangedSignal?.Disconnect(applicationTaskDeviceOrientationChangedEventCallback);
+ taskDeviceOrientationChangedSignal?.Dispose();
+ taskDeviceOrientationChangedSignal = null;
+ }
- if (applicationTaskAppControlEventCallbackDelegate != null)
- {
- taskAppControlSignal?.Disconnect(applicationTaskAppControlEventCallbackDelegate);
- taskAppControlSignal?.Dispose();
- taskAppControlSignal = null;
+ if (applicationTaskAppControlEventCallbackDelegate != null)
+ {
+ taskAppControlSignal?.Disconnect(applicationTaskAppControlEventCallbackDelegate);
+ taskAppControlSignal?.Dispose();
+ taskAppControlSignal = null;
+ }
+
+ window?.Dispose();
+ window = null;
}
- window?.Dispose();
- window = null;
+ idleCallbackMap = null;
base.Dispose(type);
}
/// </remarks>
public bool AddIdle(System.Delegate func)
{
- System.IntPtr ip = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate<System.Delegate>(func);
- System.IntPtr ip2 = Interop.Application.MakeCallback(new System.Runtime.InteropServices.HandleRef(this, ip));
+ bool idleAdded = false; // default value is false
- bool ret = Interop.Application.AddIdle(SwigCPtr, new System.Runtime.InteropServices.HandleRef(this, ip2));
+ if (idleCallbackMap == null || IsDisposedOrQueued)
+ {
+ Tizen.Log.Error("NUI", $"[Error] Application disposed! failed to add idle {func}\n");
+ return false;
+ }
- if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
- return ret;
+ // Register root idle callback for Tizen.NUI.Application
+ if (rootIdleCallback == null)
+ {
+ rootIdleCallback = RootIdleCallback;
+ System.IntPtr ip = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate<System.Delegate>(rootIdleCallback);
+ System.IntPtr ip2 = Interop.Application.MakeCallback(new System.Runtime.InteropServices.HandleRef(this, ip));
+
+ bool ret = Interop.Application.AddIdle(SwigCPtr, new System.Runtime.InteropServices.HandleRef(this, ip2));
+ NDalicPINVOKE.ThrowExceptionIfExists();
+ if (!ret)
+ {
+ rootIdleCallback = null;
+ Tizen.Log.Error("NUI", $"[Error] failed to add idle {func}\n");
+ return false;
+ }
+ }
+
+ if (idleCallbackMap.TryGetValue(func, out bool isValid))
+ {
+ idleAdded = true; // success case
+ if (!isValid)
+ {
+ idleCallbackMap[func] = true;
+ }
+ else
+ {
+ Tizen.Log.Debug("NUI", $"Already added idle {func}\n");
+ }
+ }
+ else if (idleCallbackMap.TryAdd(func, true))
+ {
+ idleAdded = true; // success case
+ }
+
+ if (!idleAdded)
+ {
+ Tizen.Log.Error("NUI", $"[Error] failed to add idle {func}\n");
+ }
+
+ return idleAdded;
+ }
+
+ /// <summary>
+ /// Remove delegate what we added by AddIdle.
+ /// </summary>
+ /// <param name="func">The function to remove</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void RemoveIdle(System.Delegate func)
+ {
+ if (idleCallbackMap == null || IsDisposedOrQueued)
+ {
+ Tizen.Log.Error("NUI", $"[Error] Application disposed! failed to remove idle {func}\n");
+ return;
+ }
+
+ if (idleCallbackMap.TryGetValue(func, out bool isValid))
+ {
+ if (isValid)
+ {
+ idleCallbackMap[func] = false;
+ }
+ }
}
/**
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
- internal bool AddIdle(SWIGTYPE_p_Dali__CallbackBase callback)
- {
- bool ret = Interop.Application.AddIdle(SwigCPtr, SWIGTYPE_p_Dali__CallbackBase.getCPtr(callback));
- if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
- return ret;
- }
-
public Window GetWindow()
{
if (window != null)
using Tizen.NUI;
using Tizen.NUI.BaseComponents;
using Tizen.NUI.Components;
+using System;
using System.Threading;
namespace Tizen.NUI.Samples
return application;
}
+ private delegate void FuncDelegate();
+ private FuncDelegate FuncDelegater = null;
+
+ private void Func()
+ {
+ Tizen.Log.Error("NUITEST", "Idle callback comes!\n");
+ FuncDelegater = null;
+ }
+ private void Func2()
+ {
+ Tizen.Log.Error("NUITEST", "Idle callback comes! Register idle once again!\n");
+ FuncDelegater = Func;
+ GetCurrentApplication()?.AddIdle(FuncDelegater);
+ }
+
public void Activate()
{
Window window = NUIApplication.GetDefaultWindow();
Tizen.Log.Error("NUITEST", "Sleep done\n");
textLabel.Text = "Sleep done!\n";
+
+ window.KeyEvent += WinKeyEvent;
}
public void Deactivate()
{
if (root != null)
{
- NUIApplication.GetDefaultWindow().Remove(root);
+ Window window = NUIApplication.GetDefaultWindow();
+ window.Remove(root);
+ window.KeyEvent -= WinKeyEvent;
root.Dispose();
+
+ if (FuncDelegater != null)
+ {
+ GetCurrentApplication()?.RemoveIdle(FuncDelegater);
+ }
+ }
+ }
+
+ private void WinKeyEvent(object sender, Window.KeyEventArgs e)
+ {
+ if (e.Key.State == Key.StateType.Down)
+ {
+ if (e.Key.KeyPressedName == "1")
+ {
+ Tizen.Log.Error("NUITEST", "Add idle callback\n");
+ if (FuncDelegater == null)
+ {
+ FuncDelegater = Func;
+ }
+
+ GetCurrentApplication()?.AddIdle(FuncDelegater);
+ }
+ else if (e.Key.KeyPressedName == "2")
+ {
+ Tizen.Log.Error("NUITEST", "Add idle callback, and remove immediately\n");
+ if (FuncDelegater == null)
+ {
+ FuncDelegater = Func;
+ }
+
+ GetCurrentApplication()?.AddIdle(FuncDelegater);
+ GetCurrentApplication()?.RemoveIdle(FuncDelegater);
+ GetCurrentApplication()?.AddIdle(FuncDelegater);
+ GetCurrentApplication()?.RemoveIdle(FuncDelegater);
+ FuncDelegater = null;
+ }
+ else if (e.Key.KeyPressedName == "3")
+ {
+ Tizen.Log.Error("NUITEST", "Add idle callback during idle callback execute\n");
+ if (FuncDelegater == null)
+ {
+ FuncDelegater = Func2;
+ }
+
+ GetCurrentApplication()?.AddIdle(FuncDelegater);
+ }
+ else if (e.Key.KeyPressedName == "4")
+ {
+ Tizen.Log.Error("NUITEST", "Add multiple idle callback times\n");
+ if (FuncDelegater == null)
+ {
+ FuncDelegater = Func;
+ }
+
+ GetCurrentApplication()?.AddIdle(FuncDelegater);
+ GetCurrentApplication()?.AddIdle(FuncDelegater);
+ GetCurrentApplication()?.RemoveIdle(FuncDelegater);
+ GetCurrentApplication()?.AddIdle(FuncDelegater);
+
+ FuncDelegater = Func2;
+ GetCurrentApplication()?.AddIdle(FuncDelegater);
+ }
+ else if (e.Key.KeyPressedName == "5")
+ {
+ Tizen.Log.Error("NUITEST", "Self dispose after add idle callback\n");
+ if (FuncDelegater == null)
+ {
+ FuncDelegater = Func;
+ }
+
+ GetCurrentApplication()?.AddIdle(FuncDelegater);
+ GetCurrentApplication()?.Dispose();
+ }
}
}
}