[NUI.WindowSystem] Introduce the new InputGenerate feature
authorJunseok Kim <juns.kim@samsung.com>
Thu, 14 Sep 2023 05:07:47 +0000 (14:07 +0900)
committerdongsug-song <35130733+dongsug-song@users.noreply.github.com>
Thu, 21 Sep 2023 09:03:17 +0000 (18:03 +0900)
src/Tizen.NUI.WindowSystem/src/internal/Interop/Interop.InputGenerator.cs [new file with mode: 0644]
src/Tizen.NUI.WindowSystem/src/public/InputGenerator.cs [new file with mode: 0644]
test/Tizen.NUI.WindowSystem.InputGenerator/Tizen.NUI.WindowSystem.InputGenerator.cs [new file with mode: 0644]
test/Tizen.NUI.WindowSystem.InputGenerator/Tizen.NUI.WindowSystem.InputGenerator.csproj [new file with mode: 0644]
test/Tizen.NUI.WindowSystem.InputGenerator/shared/res/Tizen.NUI.WindowSystem.InputGenerator.png [new file with mode: 0644]
test/Tizen.NUI.WindowSystem.InputGenerator/tizen-manifest.xml [new file with mode: 0644]
test/Tizen.NUI.WindowSystem.InputGenerator/tizen_dotnet_project.yaml [new file with mode: 0644]

diff --git a/src/Tizen.NUI.WindowSystem/src/internal/Interop/Interop.InputGenerator.cs b/src/Tizen.NUI.WindowSystem/src/internal/Interop/Interop.InputGenerator.cs
new file mode 100644 (file)
index 0000000..d9bbd03
--- /dev/null
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tizen.NUI.WindowSystem
+{
+    internal static partial class Interop
+    {
+        internal static partial class InputGenerator
+        {
+            const string lib = "libcapi-ui-efl-util.so.0";
+
+            [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "efl_util_input_initialize_generator")]
+            internal static extern IntPtr Init(int devType);
+
+            [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "efl_util_input_initialize_generator_with_name")]
+            internal static extern IntPtr InitWithName(int devType, string devName);
+
+            [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "efl_util_input_initialize_generator_with_sync")]
+            internal static extern IntPtr SyncInit(int devType, string devName);
+
+            [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "efl_util_input_deinitialize_generator")]
+            internal static extern ErrorCode Deinit(IntPtr inputGenHandler);
+
+            [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "efl_util_input_generate_key")]
+            internal static extern ErrorCode GenerateKey(IntPtr inputGenHandler, string keyName, int pressed);
+
+            [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "efl_util_input_generate_pointer")]
+            internal static extern ErrorCode GeneratePointer(IntPtr inputGenHandler, int buttons, int pointerType, int x, int y);
+
+            [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "efl_util_input_generate_wheel")]
+            internal static extern ErrorCode GenerateWheel(IntPtr inputGenHandler, int wheelType, int value);
+
+            [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "efl_util_input_generate_touch")]
+            internal static extern ErrorCode GenerateTouch(IntPtr inputGenHandler, int idx, int touchType, int x, int y);
+
+            [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "efl_util_input_generate_touch_axis")]
+            internal static extern ErrorCode GenerateTouchAxis(IntPtr inputGenHandler, int idx, int touchType, int x, int y, double radius_x, double radius_y, double pressure, double angle, double palm);
+
+            // Enumeration of input device types.
+            // The device type may be used overlapped.
+            internal enum DeviceType
+            {
+                None = 0x0,
+                Touchscreen = (1 << 0),
+                Keyboard = (1 << 1),
+                Pointer = (1 << 2),
+                All = Touchscreen | Keyboard,   // Keyboard and Touchscreen
+            }
+
+            // Enumeration of touch event types
+            internal enum TouchType
+            {
+                None,
+                Begin,
+                Update,
+                End,
+            }
+
+            // Enumeration of pointer event types
+            internal enum PointerType
+            {
+                Down,
+                Up,
+                Move,
+            }
+
+            // Enumeration of pointer wheel event types
+            internal enum PointerWheelType
+            {
+                Vertical,
+                Horizontal,
+            }
+
+            private const int ErrorTzsh = -0x02860000;
+
+            internal enum ErrorCode
+            {
+                None = Tizen.Internals.Errors.ErrorCode.None,                            // Successful
+                OutOfMemory = Tizen.Internals.Errors.ErrorCode.OutOfMemory,              // Out of memory
+                InvalidParameter = Tizen.Internals.Errors.ErrorCode.InvalidParameter,    // Invalid parameter
+                InvalidOperation = Tizen.Internals.Errors.ErrorCode.InvalidOperation,    // Invalid operation
+                PermissionDenied = Tizen.Internals.Errors.ErrorCode.PermissionDenied,    // Permission denied
+                NotSupported = Tizen.Internals.Errors.ErrorCode.NotSupported,            // NOT supported
+                NoService = ErrorTzsh | 0x01,                                            // Service does not exist
+            }
+        }
+    }
+}
diff --git a/src/Tizen.NUI.WindowSystem/src/public/InputGenerator.cs b/src/Tizen.NUI.WindowSystem/src/public/InputGenerator.cs
new file mode 100644 (file)
index 0000000..a9ccf0a
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * 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;
+using System.ComponentModel;
+
+namespace Tizen.NUI.WindowSystem
+{
+    /// <summary>
+    /// Class for the Tizen Input Generator.
+    /// </summary>
+    /// <privilege>
+    /// http://tizen.org/privilege/inputgenerator
+    /// </privilege>
+    /// This class is need to be hidden as inhouse API.
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public class InputGenerator : IDisposable
+    {
+        private IntPtr _handler;
+        private bool disposed = false;
+        private bool isDisposeQueued = false;
+
+        /// <summary>
+        /// Enumeration of input device types.
+        /// </summary>
+        public enum DeviceType
+        {
+            /// <summary>
+            /// None.
+            /// </summary>
+            None = Interop.InputGenerator.DeviceType.None,
+
+            /// <summary>
+            /// Touchscreen device.
+            /// </summary>
+            Touchscreen = Interop.InputGenerator.DeviceType.Touchscreen,
+
+            /// <summary>
+            /// Keyboard device.
+            /// </summary>
+            Keyboard = Interop.InputGenerator.DeviceType.Keyboard,
+
+            /// <summary>
+            /// Pointer device.
+            /// </summary>
+            Pointer = Interop.InputGenerator.DeviceType.Pointer,
+
+            /// <summary>
+            /// Keyboard and Touchscreen device.
+            /// </summary>
+            All = Interop.InputGenerator.DeviceType.All,
+        }
+
+        /// <summary>
+        /// Enumeration of touch event types.
+        /// </summary>
+        public enum TouchType
+        {
+            /// <summary>
+            /// None.
+            /// </summary>
+            None = Interop.InputGenerator.TouchType.None,
+
+            /// <summary>
+            /// Touch begin.
+            /// </summary>
+            Begin = Interop.InputGenerator.TouchType.Begin,
+
+            /// <summary>
+            /// Touch move.
+            /// </summary>
+            Update = Interop.InputGenerator.TouchType.Update,
+
+            /// <summary>
+            /// Touch end.
+            /// </summary>
+            End = Interop.InputGenerator.TouchType.End,
+        }
+
+        /// <summary>
+        /// Enumeration of pointer event types.
+        /// </summary>
+        public enum PointerType
+        {
+            /// <summary>
+            /// Pointer down.
+            /// </summary>
+            Down = Interop.InputGenerator.PointerType.Down,
+
+            /// <summary>
+            /// Pointer up.
+            /// </summary>
+            Up = Interop.InputGenerator.PointerType.Up,
+
+            /// <summary>
+            /// Pointer move.
+            /// </summary>
+            Move = Interop.InputGenerator.PointerType.Move,
+        }
+
+        /// <summary>
+        /// Enumeration of pointer wheel event types.
+        /// </summary>
+        public enum PointerWheelType
+        {
+            /// <summary>
+            /// Vertical wheel.
+            /// </summary>
+            Vertical = Interop.InputGenerator.PointerWheelType.Vertical,
+
+            /// <summary>
+            /// Horizontal wheel.
+            /// </summary>
+            Horizontal = Interop.InputGenerator.PointerWheelType.Horizontal,
+        }
+
+        internal void ErrorCodeThrow(Interop.InputGenerator.ErrorCode error)
+        {
+            switch (error)
+            {
+                case Interop.InputGenerator.ErrorCode.None :
+                    return;
+                case Interop.InputGenerator.ErrorCode.OutOfMemory :
+                    throw new Tizen.Applications.Exceptions.OutOfMemoryException("Out of Memory");
+                case Interop.InputGenerator.ErrorCode.InvalidParameter :
+                    throw new ArgumentException("Invalid Parameter");
+                case Interop.InputGenerator.ErrorCode.PermissionDenied :
+                    throw new Tizen.Applications.Exceptions.PermissionDeniedException("Permission denied");
+                case Interop.InputGenerator.ErrorCode.NotSupported :
+                    throw new NotSupportedException("Not Supported");
+                case Interop.InputGenerator.ErrorCode.NoService :
+                    throw new InvalidOperationException("No Service");
+                default :
+                    throw new InvalidOperationException("Unknown Error");
+            }
+        }
+
+        /// <summary>
+        /// Creates a new InputGenerator.
+        /// </summary>
+        /// <param name="devType">The Device type of the new input generator.</param>
+        /// <exception cref="ArgumentException">Thrown when failed of invalid argument.</exception>
+        /// <exception cref="ArgumentNullException">Thrown when a argument is null.</exception>
+        public InputGenerator(DeviceType devType)
+        {
+            if (devType == DeviceType.None)
+            {
+                throw new ArgumentException("Invalid device type");
+            }
+
+            _handler = Interop.InputGenerator.Init((int)devType);
+        }
+
+        public InputGenerator(DeviceType devType, string name, bool sync = false)
+        {
+            if (devType == DeviceType.None)
+            {
+                throw new ArgumentException("Invalid device type");
+            }
+
+            if (sync)
+                _handler = Interop.InputGenerator.SyncInit((int)devType, name);
+            else
+                _handler = Interop.InputGenerator.InitWithName((int)devType, name);
+        }
+
+        /// <summary>
+        /// Destructor.
+        /// </summary>
+        ~InputGenerator()
+        {
+            if (!isDisposeQueued)
+            {
+                isDisposeQueued = true;
+                DisposeQueue.Instance.Add(this);
+            }
+        }
+
+        /// <summary>
+        /// Dispose.
+        /// </summary>
+        public void Dispose()
+        {
+            if (isDisposeQueued)
+            {
+                Dispose(DisposeTypes.Implicit);
+            }
+            else
+            {
+                Dispose(DisposeTypes.Explicit);
+                GC.SuppressFinalize(this);
+            }
+        }
+
+        /// <inheritdoc/>
+        protected virtual void Dispose(DisposeTypes type)
+        {
+            if (!disposed)
+            {
+                if (_handler != IntPtr.Zero)
+                {
+                    Interop.InputGenerator.ErrorCode res = Interop.InputGenerator.Deinit(_handler);
+                    ErrorCodeThrow(res);
+                    _handler = IntPtr.Zero;
+                }
+                disposed = true;
+            }
+        }
+
+        /// <summary>
+        /// Generate given key.
+        /// </summary>
+        /// <param name="keyName">The key name to generate.</param>
+        /// <param name="pressed">Set the key is pressed or released.</param>
+        public void GenerateKey(string keyName, int pressed)
+        {
+            Interop.InputGenerator.ErrorCode res = Interop.InputGenerator.GenerateKey(_handler, keyName, pressed);
+            ErrorCodeThrow(res);
+        }
+
+        /// <summary>
+        /// Generate given pointer.
+        /// </summary>
+        /// <param name="buttons">The pointer button to generate.</param>
+        /// <param name="pointerType">The type of the pointer.</param>
+        /// <param name="x">X coordinate of the pointer.</param>
+        /// <param name="y">Y coordinate of the pointer.</param>
+        public void GeneratePointer(int buttons, PointerType pointerType, int x, int y)
+        {
+            Interop.InputGenerator.ErrorCode res = Interop.InputGenerator.GeneratePointer(_handler, buttons, (int)pointerType, x, y);
+            ErrorCodeThrow(res);
+        }
+
+        /// <summary>
+        /// Generate given wheel.
+        /// </summary>
+        /// <param name="wheelType">The wheel type to generate.</param>
+        /// <param name="value">The value of the wheel.</param>
+        public void GenerateWheel(PointerWheelType wheelType, int value)
+        {
+            Interop.InputGenerator.ErrorCode res = Interop.InputGenerator.GenerateWheel(_handler, (int)wheelType, value);
+            ErrorCodeThrow(res);
+        }
+
+        /// <summary>
+        /// Generate given touch.
+        /// </summary>
+        /// <param name="idx">The touch index to generate.</param>
+        /// <param name="touchType">The touch type to generate.</param>
+        /// <param name="x">X coordinate of the touch.</param>
+        /// <param name="y">Y coordinate of the touch.</param>
+        public void GenerateTouch(int idx, TouchType touchType, int x, int y)
+        {
+            Interop.InputGenerator.ErrorCode res = Interop.InputGenerator.GenerateTouch(_handler, idx, (int) touchType, x, y);
+            ErrorCodeThrow(res);
+        }
+
+        /// <summary>
+        /// Generate given touch with axis.
+        /// </summary>
+        /// <param name="idx">The touch index to generate.</param>
+        /// <param name="touchType">The touch type to generate.</param>
+        /// <param name="x">X coordinate of the touch.</param>
+        /// <param name="y">Y coordinate of the touch.</param>
+        /// <param name="radius_x">radius_x of the touch.</param>
+        /// <param name="radius_y">radius_y of the touch.</param>
+        /// <param name="pressure">pressure of the touch.</param>
+        /// <param name="angle">angle of the touch.</param>
+        /// <param name="palm">palm of the touch.</param>
+        public void GenerateTouchAxis(int idx, TouchType touchType, int x, int y, double radius_x, double radius_y, double pressure, double angle, double palm)
+        {
+            Interop.InputGenerator.ErrorCode res = Interop.InputGenerator.GenerateTouchAxis(_handler, idx, (int) touchType, x, y, radius_x, radius_y, pressure, angle, palm);
+            ErrorCodeThrow(res);
+        }
+    }
+}
diff --git a/test/Tizen.NUI.WindowSystem.InputGenerator/Tizen.NUI.WindowSystem.InputGenerator.cs b/test/Tizen.NUI.WindowSystem.InputGenerator/Tizen.NUI.WindowSystem.InputGenerator.cs
new file mode 100644 (file)
index 0000000..e61ac3a
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * 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;
+using Tizen;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.WindowSystem;
+using System.Collections.Generic;
+
+namespace Tizen.NUI.WindowSystem
+{
+    class Program : NUIApplication
+    {
+        protected override void OnCreate()
+        {
+            base.OnCreate();
+            Initialize();
+        }
+
+        void Initialize()
+        {
+            Window win = Window.Instance;
+            inputGen = new InputGenerator(InputGenerator.DeviceType.All, null);
+
+            win.WindowSize = new Size2D(500, 500);
+            win.KeyEvent += OnKeyEvent;
+            win.BackgroundColor = Color.White;
+
+            View windowView = new View();
+            windowView.Size2D = new Size2D(500, 500);
+            windowView.BackgroundColor = Color.White;
+            windowView.TouchEvent += OnTouchEvent;
+            win.Add(windowView);
+
+            centerLabel = new TextLabel("InputGenerator Sample, Click to generate Return Key.");
+            centerLabel.HorizontalAlignment = HorizontalAlignment.Center;
+            centerLabel.VerticalAlignment = VerticalAlignment.Center;
+            centerLabel.TextColor = Color.Black;
+            centerLabel.PointSize = 12.0f;
+            centerLabel.HeightResizePolicy = ResizePolicyType.FillToParent;
+            centerLabel.WidthResizePolicy = ResizePolicyType.FillToParent;
+            windowView.Add(centerLabel);
+
+            repeatCounter = 0;
+        }
+
+        private void OnKeyEvent(object sender, Window.KeyEventArgs e)
+        {
+            if (e.Key.State == Key.StateType.Down && (e.Key.KeyPressedName == "XF86Back" || e.Key.KeyPressedName == "Escape"))
+            {
+                Exit();
+            }
+            if (e.Key.State == Key.StateType.Down && e.Key.KeyPressedName == "Return")
+            {
+                repeatCounter++;
+                centerLabel.Text = "Return Key Pressed, counter: " + repeatCounter.ToString();
+            }
+        }
+
+        private bool OnTouchEvent(object sender, View.TouchEventArgs e)
+        {
+            if (e.Touch.GetState(0) == PointStateType.Down)
+            {
+                inputGen.GenerateKey("Return", 1);
+                inputGen.GenerateKey("Return", 0);
+
+                return true;
+            }
+
+            return false;
+        }
+
+        static void Main(string[] args)
+        {
+            var app = new Program();
+            app.Run(args);
+        }
+
+        private InputGenerator inputGen;
+        private TextLabel centerLabel;
+        int repeatCounter = 0;
+    }
+}
diff --git a/test/Tizen.NUI.WindowSystem.InputGenerator/Tizen.NUI.WindowSystem.InputGenerator.csproj b/test/Tizen.NUI.WindowSystem.InputGenerator/Tizen.NUI.WindowSystem.InputGenerator.csproj
new file mode 100644 (file)
index 0000000..b0bb521
--- /dev/null
@@ -0,0 +1,27 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+      <OutputType>Exe</OutputType>
+      <TargetFramework>net6.0</TargetFramework>
+  </PropertyGroup>
+
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+      <DebugType>portable</DebugType>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+      <DebugType>None</DebugType>
+  </PropertyGroup>
+
+  <ItemGroup>
+      <PackageReference Include="Tizen.NET.Sdk" Version="1.0.9" />
+      <ProjectReference Include="../../src/Tizen/Tizen.csproj" />
+      <ProjectReference Include="../../src/Tizen.NUI.Components/Tizen.NUI.Components.csproj" />
+      <ProjectReference Include="../../src/Tizen.NUI/Tizen.NUI.csproj" />
+      <ProjectReference Include="../../src/Tizen.NUI.WindowSystem/Tizen.NUI.WindowSystem.csproj" />
+  </ItemGroup>
+
+  <PropertyGroup>
+      <NeedInjection>True</NeedInjection>
+  </PropertyGroup>
+
+</Project>
diff --git a/test/Tizen.NUI.WindowSystem.InputGenerator/shared/res/Tizen.NUI.WindowSystem.InputGenerator.png b/test/Tizen.NUI.WindowSystem.InputGenerator/shared/res/Tizen.NUI.WindowSystem.InputGenerator.png
new file mode 100644 (file)
index 0000000..9f3cb98
Binary files /dev/null and b/test/Tizen.NUI.WindowSystem.InputGenerator/shared/res/Tizen.NUI.WindowSystem.InputGenerator.png differ
diff --git a/test/Tizen.NUI.WindowSystem.InputGenerator/tizen-manifest.xml b/test/Tizen.NUI.WindowSystem.InputGenerator/tizen-manifest.xml
new file mode 100644 (file)
index 0000000..b9b9b08
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="7.5" package="org.tizen.example.InputGenerator" version="1.0.0">
+  <profile name="common" />
+  <ui-application appid="org.tizen.example.InputGenerator"
+                                       exec="Tizen.NUI.WindowSystem.InputGenerator.dll"
+                                       type="dotnet-nui"
+                                       multiple="false"
+                                       taskmanage="true"
+                                       nodisplay="false"
+                                       launch_mode="single"
+                    api-version="10">
+    <label>Tizen.NUI.WindowSystem.InputGenerator</label>
+    <icon>Tizen.NUI.WindowSystem.InputGenerator.png</icon>
+    <metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" />
+  </ui-application>
+</manifest>
diff --git a/test/Tizen.NUI.WindowSystem.InputGenerator/tizen_dotnet_project.yaml b/test/Tizen.NUI.WindowSystem.InputGenerator/tizen_dotnet_project.yaml
new file mode 100644 (file)
index 0000000..01c7a15
--- /dev/null
@@ -0,0 +1,9 @@
+# csproj file path
+csproj_file: Tizen.NUI.WindowSystem.InputGenerator.csproj
+
+# files monitored for dirty/modified status
+files:
+  - Tizen.NUI.WindowSystem.InputGenerator.csproj
+  - Tizen.NUI.WindowSystem.InputGenerator.cs
+  - tizen-manifest.xml
+  - shared/res/Tizen.NUI.WindowSystem.InputGenerator.png
\ No newline at end of file