[NUI] Do not connect default signals when View created
authorEunki, Hong <eunkiki.hong@samsung.com>
Mon, 6 Mar 2023 13:25:05 +0000 (22:25 +0900)
committertscholb <scholb.kim@samsung.com>
Mon, 13 Mar 2023 10:02:21 +0000 (19:02 +0900)
Since Window.ViewAdded signal required to all common view's creation time,
It will reduce each view's creation time.
And more, ViewAdded signal only works for default windows previously.

Now we make the signal ownership from window.

And additionaly, register custom HitTest signal only if subclass required.

TODO : The role of signal conflict with View.AddedToWindow.
Can we just remove this ViewAdded signal?

TODO : Can we just skip default view constructor's signal connection?

Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
src/Tizen.NUI/src/internal/Common/WindowViewAddedSignal.cs [new file with mode: 0755]
src/Tizen.NUI/src/internal/Interop/Interop.WindowViewAddedSignal.cs [new file with mode: 0755]
src/Tizen.NUI/src/public/BaseComponents/View.cs
src/Tizen.NUI/src/public/BaseComponents/ViewEvent.cs
src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs
src/Tizen.NUI/src/public/BaseComponents/ViewPublicMethods.cs
src/Tizen.NUI/src/public/Window/BorderWindow.cs
src/Tizen.NUI/src/public/Window/WindowEvent.cs
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/EventPropagationSample.cs
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/HitTestSample.cs
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/WindowEventsTest.cs

diff --git a/src/Tizen.NUI/src/internal/Common/WindowViewAddedSignal.cs b/src/Tizen.NUI/src/internal/Common/WindowViewAddedSignal.cs
new file mode 100755 (executable)
index 0000000..da16f17
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright(c) 2023 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Tizen.NUI
+{
+    internal class WindowViewAddedSignal : Disposable
+    {
+
+        internal WindowViewAddedSignal(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
+        {
+        }
+
+        protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
+        {
+            Interop.WindowViewAddedSignal.DeleteSignal(swigCPtr);
+        }
+
+        public bool Empty()
+        {
+            bool ret = Interop.WindowViewAddedSignal.Empty(SwigCPtr);
+
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return ret;
+        }
+
+        public uint GetConnectionCount()
+        {
+            uint ret = Interop.WindowViewAddedSignal.GetConnectionCount(SwigCPtr);
+
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return ret;
+        }
+
+        public void Connect(System.Delegate func)
+        {
+            System.IntPtr ip = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate<System.Delegate>(func);
+            {
+                Interop.WindowViewAddedSignal.Connect(SwigCPtr, new System.Runtime.InteropServices.HandleRef(this, ip));
+                if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            }
+        }
+
+        public void Disconnect(System.Delegate func)
+        {
+            System.IntPtr ip = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate<System.Delegate>(func);
+            {
+                Interop.WindowViewAddedSignal.Disconnect(SwigCPtr, new System.Runtime.InteropServices.HandleRef(this, ip));
+                if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            }
+        }
+
+        public bool Emit()
+        {
+            bool ret = Interop.WindowViewAddedSignal.Emit(SwigCPtr);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return ret;
+        }
+
+        public WindowViewAddedSignal(Window window) : this(Interop.WindowViewAddedSignal.GetSignal(Window.getCPtr(window)), false)
+        {
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+        }
+    }
+}
diff --git a/src/Tizen.NUI/src/internal/Interop/Interop.WindowViewAddedSignal.cs b/src/Tizen.NUI/src/internal/Interop/Interop.WindowViewAddedSignal.cs
new file mode 100755 (executable)
index 0000000..e8c3465
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright(c) 2023 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using System.Runtime.InteropServices;
+
+namespace Tizen.NUI
+{
+    internal static partial class Interop
+    {
+        internal static partial class WindowViewAddedSignal
+        {
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Window_View_Added_Signal")]
+            public static extern global::System.IntPtr GetSignal(HandleRef jarg1);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Window_View_Added_Signal_Empty")]
+            [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
+            public static extern bool Empty(HandleRef jarg1);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Window_View_Added_Signal_GetConnectionCount")]
+            public static extern uint GetConnectionCount(HandleRef jarg1);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Window_View_Added_Signal_Connect")]
+            public static extern void Connect(HandleRef jarg1, HandleRef jarg2);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Window_View_Added_Signal_Disconnect")]
+            public static extern void Disconnect(HandleRef jarg1, HandleRef jarg2);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Window_View_Added_Signal_Emit")]
+            [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
+            public static extern bool Emit(HandleRef jarg1);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Window_View_Added_Signal_new")]
+            public static extern global::System.IntPtr NewSignal();
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Window_View_Added_delete")]
+            public static extern void DeleteSignal(HandleRef jarg1);
+        }
+    }
+}
index 651c633..8cf1398 100755 (executable)
@@ -163,23 +163,17 @@ namespace Tizen.NUI.BaseComponents
             if (HasBody())
             {
                 PositionUsesPivotPoint = false;
-            }
-
-            onWindowSendEventCallback = SendViewAddedEventToWindow;
-            using ViewSignal signal = new ViewSignal(Interop.ActorSignal.ActorOnSceneSignal(SwigCPtr), false);
-            signal?.Connect(onWindowSendEventCallback);
+                GrabTouchAfterLeave = defaultGrabTouchAfterLeave;
+                AllowOnlyOwnTouch = defaultAllowOnlyOwnTouch;
 
-            hitTestResultDataCallback = OnHitTestResult;
-            using TouchDataSignal touchDataSignal = new TouchDataSignal(Interop.ActorSignal.ActorHitTestResultSignal(SwigCPtr), false);
-            touchDataSignal?.Connect(hitTestResultDataCallback);
+                // TODO : Can we call this function only for required subclass?
+                RegisterHitTestCallback();
+            }
 
             if (!shown)
             {
                 SetVisible(false);
             }
-
-            GrabTouchAfterLeave = defaultGrabTouchAfterLeave;
-            AllowOnlyOwnTouch = defaultAllowOnlyOwnTouch;
         }
 
         internal View(ViewImpl implementation, bool shown = true) : this(Interop.View.NewViewInternal(ViewImpl.getCPtr(implementation)), true)
index d06d61b..24ff8ab 100755 (executable)
@@ -58,13 +58,6 @@ namespace Tizen.NUI.BaseComponents
         private ResourcesLoadedCallbackType ResourcesLoadedCallback;
         private EventHandler<BackgroundResourceLoadedEventArgs> backgroundResourceLoadedEventHandler;
         private _backgroundResourceLoadedCallbackType backgroundResourceLoadedCallback;
-        private OnWindowEventCallbackType onWindowSendEventCallback;
-        private void SendViewAddedEventToWindow(IntPtr data)
-        {
-            // Unused parameter
-            _ = data;
-            NUIApplication.GetDefaultWindow()?.SendViewAdded(this);
-        }
         private TouchDataCallbackType hitTestResultDataCallback;
 
         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
index 226a458..b0e9e16 100755 (executable)
@@ -1541,14 +1541,6 @@ namespace Tizen.NUI.BaseComponents
                 backgroundResourceLoadedCallback = null;
             }
 
-            if (onWindowSendEventCallback != null)
-            {
-                NUILog.Debug($"[Dispose] onWindowSendEventCallback");
-
-                using ViewSignal signal = new ViewSignal(Interop.ActorSignal.ActorOnSceneSignal(GetBaseHandleCPtrHandleRef), false);
-                signal?.Disconnect(onWindowSendEventCallback);
-                onWindowSendEventCallback = null;
-            }
             NUILog.Debug($"[Dispose] DisConnectFromSignals END");
         }
 
index abd684a..a10d78f 100755 (executable)
@@ -924,5 +924,41 @@ namespace Tizen.NUI.BaseComponents
                 throw NDalicPINVOKE.SWIGPendingException.Retrieve();
         }
 
+        /// <summary>
+        /// Register custom HitTest function for this view.
+        /// </summary>
+        /// <seealso cref="View.HitTest" />
+        /// <remarks>
+        /// This is a hidden API(inhouse API) only for internal purpose.
+        /// </remarks>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected void RegisterHitTestCallback()
+        {
+            if (hitTestResultDataCallback == null)
+            {
+                hitTestResultDataCallback = OnHitTestResult;
+                using TouchDataSignal touchDataSignal = new TouchDataSignal(Interop.ActorSignal.ActorHitTestResultSignal(SwigCPtr), false);
+                touchDataSignal?.Connect(hitTestResultDataCallback);
+                if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            }
+        }
+
+        /// <summary>
+        /// Unregister custom HitTest function.
+        /// </summary>
+        /// <remarks>
+        /// This is a hidden API(inhouse API) only for internal purpose.
+        /// </remarks>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected void UnregisterHitTestCallback()
+        {
+            if (hitTestResultDataCallback != null)
+            {
+                using TouchDataSignal touchDataSignal = new TouchDataSignal(Interop.ActorSignal.ActorHitTestResultSignal(SwigCPtr), false);
+                touchDataSignal?.Disconnect(hitTestResultDataCallback);
+                hitTestResultDataCallback = null;
+                if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            }
+        }
     }
 }
index b4a5edd..3b0cc1b 100755 (executable)
@@ -663,6 +663,12 @@ namespace Tizen.NUI
             private bool isEnabledOverlay = false;
             private Extents prePadding = new Extents(0, 0, 0, 0);
 
+            internal BorderView() : base()
+            {
+                // BorderView will use custom HitTest function.
+                RegisterHitTestCallback();
+            }
+
             /// <summary>
             /// Set whether or not it is in overlay mode.
             /// The borderView's OverlayMode means that it is displayed at the top of the screen.
index 86e8959..5b462c6 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2023 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.
@@ -49,6 +49,7 @@ namespace Tizen.NUI
         private MovedEventCallbackType movedEventCallback;
         private OrientationChangedEventCallbackType orientationChangedEventCallback;
         private KeyboardRepeatSettingsChangedEventCallbackType keyboardRepeatSettingsChangedEventCallback;
+        private ViewAddedEventCallbackType viewAddedEventCallback;
         private AuxiliaryMessageEventCallbackType auxiliaryMessageEventCallback;
         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
         private delegate void WindowFocusChangedEventCallbackType(IntPtr window, bool focusGained);
@@ -69,6 +70,8 @@ namespace Tizen.NUI
         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
         private delegate void KeyboardRepeatSettingsChangedEventCallbackType();
         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        private delegate void ViewAddedEventCallbackType(IntPtr view);
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
         private delegate void AuxiliaryMessageEventCallbackType(IntPtr kData, IntPtr vData, IntPtr optionsArray);
         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
         private delegate bool InterceptKeyEventDelegateType(IntPtr arg1);
@@ -486,7 +489,33 @@ namespace Tizen.NUI
         /// <since_tizen> 6 </since_tizen>
         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public event EventHandler ViewAdded;
+        public event EventHandler ViewAdded
+        {
+            add
+            {
+                if (viewAddedHandler == null)
+                {
+                    viewAddedEventCallback = OnViewAdded;
+                    using WindowViewAddedSignal signal = new WindowViewAddedSignal(Interop.WindowViewAddedSignal.GetSignal(SwigCPtr), false);
+                    signal?.Connect(viewAddedEventCallback);
+                }
+                viewAddedHandler += value;
+            }
+            remove
+            {
+                viewAddedHandler -= value;
+                if (viewAddedHandler == null && viewAddedEventCallback != null)
+                {
+                    using WindowViewAddedSignal signal = new WindowViewAddedSignal(Interop.WindowViewAddedSignal.GetSignal(SwigCPtr), false);
+                    signal?.Disconnect(viewAddedEventCallback);
+                    if (signal?.Empty() == true)
+                    {
+                        viewAddedEventCallback = null;
+                    }
+                }
+            }
+        }
+
         private event EventHandler<FocusChangedEventArgs> windowFocusChangedEventHandler;
         private event EventHandler<TouchEventArgs> rootLayerTouchDataEventHandler;
         private ReturnTypeEventHandler<object, TouchEventArgs, bool> rootLayerInterceptTouchDataEventHandler;
@@ -500,12 +529,9 @@ namespace Tizen.NUI
         private event EventHandler<WindowMovedEventArgs> movedHandler;
         private event EventHandler<WindowOrientationChangedEventArgs> orientationChangedHandler;
         private event EventHandler keyboardRepeatSettingsChangedHandler;
+        private event EventHandler viewAddedHandler;
         private event EventHandler<AuxiliaryMessageEventArgs> auxiliaryMessageEventHandler;
 
-        internal void SendViewAdded(View view)
-        {
-            ViewAdded?.Invoke(view, EventArgs.Empty);
-        }
 
         internal event EventHandler EventProcessingFinished
         {
@@ -754,6 +780,13 @@ namespace Tizen.NUI
                 keyboardRepeatSettingsChangedEventCallback = null;
             }
 
+            if (viewAddedEventCallback != null)
+            {
+                using WindowViewAddedSignal signal = new WindowViewAddedSignal(Interop.WindowViewAddedSignal.GetSignal(GetBaseHandleCPtrHandleRef), false);
+                signal?.Disconnect(viewAddedEventCallback);
+                viewAddedEventCallback = null;
+            }
+
             if (auxiliaryMessageEventCallback != null)
             {
                 using WindowAuxiliaryMessageSignal signal = new WindowAuxiliaryMessageSignal(Interop.WindowAuxiliaryMessageSignalType.Get(GetBaseHandleCPtrHandleRef), false);
@@ -981,6 +1014,22 @@ namespace Tizen.NUI
             return;
         }
 
+        private void OnViewAdded(IntPtr view)
+        {
+            if (view == global::System.IntPtr.Zero)
+            {
+                return;
+            }
+
+            View addedView = Extensions.GetInstanceSafely<View>(this, view);
+            if (addedView)
+            {
+                // Note : object sender is View, not window it selfs (Since tizen_5.5, Pull Request #705)
+                viewAddedHandler?.Invoke(view, EventArgs.Empty);
+            }
+            return;
+        }
+
         /// <summary>
         /// The focus changed event argument.
         /// </summary>
index 9b9a1fa..6448da9 100755 (executable)
@@ -11,6 +11,12 @@ namespace Tizen.NUI.Samples
 
     class MyView : View
     {
+        public MyView() : base()
+        {
+            // Notify that we will use custom HitTest function for this class.
+            RegisterHitTestCallback();
+        }
+
         protected override bool HitTest(Touch touch)
         {
             Tizen.Log.Error("NUI", $"override HitTest\n");
index bae95ee..2ffb6b3 100644 (file)
@@ -53,6 +53,12 @@ namespace Tizen.NUI.Samples
 
     class MyView : View
     {
+        public MyView() : base()
+        {
+            // Notify that we will use custom HitTest function for this class.
+            RegisterHitTestCallback();
+        }
+
         protected override bool HitTest(Touch touch)
         {
             if(hitTest == true)
index 3f4c6cb..ad13c85 100755 (executable)
@@ -102,7 +102,7 @@ namespace Tizen.NUI.Samples
                 childViewWindow.KeyEvent += OnChildViewWindowKeyEvent;
                 childViewWindow.TransitionEffect += OnChildViewWindowTransitionEffect;
                 childViewWindow.KeyboardRepeatSettingsChanged += OnChildViewWindowKeyboardRepeatSettingsChanged;
-                childViewWindow.ViewAdded += OnChildViewWindowViewAdded;
+                //childViewWindow.ViewAdded += OnChildViewWindowViewAdded; // Block this signal for temprary
                 childViewWindow.AuxiliaryMessage += OnAuxiliaryMessageEvent;
             }
         }
@@ -120,7 +120,7 @@ namespace Tizen.NUI.Samples
                 childViewWindow.KeyEvent -= OnChildViewWindowKeyEvent;
                 childViewWindow.TransitionEffect -= OnChildViewWindowTransitionEffect;
                 childViewWindow.KeyboardRepeatSettingsChanged -= OnChildViewWindowKeyboardRepeatSettingsChanged;
-                childViewWindow.ViewAdded -= OnChildViewWindowViewAdded;
+                //childViewWindow.ViewAdded -= OnChildViewWindowViewAdded; // Block this signal for temprary
                 childViewWindow.AuxiliaryMessage -= OnAuxiliaryMessageEvent;
                 childViewWindow = null;
             }