[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 651c633e0db1f651e4b6bdf2a93ecf852be98621..8cf13985b14d647e4a8bea315f036c209fe7d386 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 d06d61b49cb680af47f4286cf73d305dbcb9df25..24ff8abccb70f974766fbdb4c86fa3910e26a9b9 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 226a4581ec9ac0d5255b21b839c9d6c0f3a8c8ca..b0e9e16b30b99583dfb59701990aeff26d8157c8 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 abd684a50466af06f365586f4bd5d2990d6706dc..a10d78fe9b1ea787a072964832543baab38f97c1 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 b4a5edd6de199179c24e354423bc7dea07574918..3b0cc1b23e44e07c5041b470efd2dfebb3510afe 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 86e8959d278c10ca19b587caf05cf4745ed54a8f..5b462c6fddd60e0365610e563edf405f15391307 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 9b9a1fa2881381dd01b28f9393870a10ddc22b7f..6448da9f933dfa5f90b7ea5f9fa5386483a7b421 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 bae95ee9064ce83ca1693c08f0fdfc71c3b98966..2ffb6b3cbdf45f3fd9ff54c99b51dd67bdf1709e 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 3f4c6cbced2b6789a1e3f1e5134c6e52593b58a5..ad13c859eafa52e8b8e555fa2e06f9a8ef8ede21 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;
             }