--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tizen.NUI.WindowSystem.Shell
+{
+ internal static partial class Interop
+ {
+ internal static partial class KVMService
+ {
+ const string lib = "libtzsh_kvm_service.so.0";
+
+ [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "tzsh_kvm_service_create")]
+ internal static extern IntPtr Create(IntPtr tzsh, IntPtr win);
+
+ [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "tzsh_kvm_service_destroy")]
+ internal static extern int Destroy(IntPtr kvmService);
+
+ [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "tzsh_kvm_service_perform_drop")]
+ internal static extern int PerformDrop(IntPtr kvmService);
+
+ [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "tzsh_kvm_service_secondary_selection_set")]
+ internal static extern int SetSecondarySelection(IntPtr kvmService);
+
+ [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "tzsh_kvm_service_secondary_selection_unset")]
+ internal static extern int UnsetSecondarySelection(IntPtr kvmService);
+
+ internal delegate void KVMDragStartEventCallback(IntPtr data, IntPtr kvmService);
+ [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "tzsh_kvm_service_drag_start_cb_set")]
+ internal static extern int SetDragStartEventHandler(IntPtr kvmService, KVMDragStartEventCallback func, IntPtr data);
+
+ internal delegate void KVMDragEndEventCallback(IntPtr data, IntPtr kvmService);
+ [global::System.Runtime.InteropServices.DllImport(lib, EntryPoint = "tzsh_kvm_service_drag_end_cb_set")]
+ internal static extern int SetDragEndEventHandler(IntPtr kvmService, KVMDragEndEventCallback func, IntPtr data);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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.Shell
+{
+ /// <summary>
+ /// Class for the Tizen KVM service.
+ /// </summary>
+ /// This class is need to be hidden as inhouse API.
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public class KVMService : IDisposable
+ {
+ private TizenShell _tzsh;
+ private IntPtr _kvmService;
+ private int _tzshWin;
+ private bool disposed = false;
+ private bool isDisposeQueued = false;
+
+ private Interop.KVMService.KVMDragStartEventCallback _onDragStarted;
+ private Interop.KVMService.KVMDragEndEventCallback _onDragEnded;
+
+ private event EventHandler _dragStarted;
+ private event EventHandler _dragEnded;
+
+ /// <summary>
+ /// Creates a new KVM Service handle.
+ /// </summary>
+ /// <param name="tzShell">The TizenShell instance.</param>
+ /// <param name="win">The window to provide service of the quickpanel.</param>
+ /// <exception cref="ArgumentException">Thrown when failed of invalid argument.</exception>
+ /// <exception cref="ArgumentNullException">Thrown when a argument is null.</exception>
+ public KVMService(TizenShell tzShell, Window win)
+ {
+ if (tzShell == null)
+ {
+ throw new ArgumentNullException(nameof(tzShell));
+ }
+ if (tzShell.GetNativeHandle() == IntPtr.Zero)
+ {
+ throw new ArgumentException("tzShell is not initialized.");
+ }
+ if (win == null)
+ {
+ throw new ArgumentNullException(nameof(win));
+ }
+
+ _tzsh = tzShell;
+ _tzshWin = win.GetNativeId();
+ _kvmService = Interop.KVMService.Create(_tzsh.GetNativeHandle(), (IntPtr)_tzshWin);
+ if (_kvmService == IntPtr.Zero)
+ {
+ int err = Tizen.Internals.Errors.ErrorFacts.GetLastResult();
+ _tzsh.ErrorCodeThrow(err);
+ }
+ }
+
+ /// <summary>
+ /// Destructor.
+ /// </summary>
+ ~KVMService()
+ {
+ 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 (_kvmService != IntPtr.Zero)
+ {
+ int res = Interop.KVMService.Destroy(_kvmService);
+ _kvmService = IntPtr.Zero;
+ }
+ disposed = true;
+ }
+ }
+
+ /// <summary>
+ /// Emits the event when the drag started from any window.
+ /// </summary>
+ /// <exception cref="ArgumentException">Thrown when failed of invalid argument.</exception>
+ public event EventHandler DragStarted
+ {
+ add
+ {
+ if (_dragStarted == null)
+ {
+ _onDragStarted = OnDragStarted;
+ int res = Interop.KVMService.SetDragStartEventHandler(_kvmService, _onDragStarted, IntPtr.Zero);
+ _tzsh.ErrorCodeThrow(res);
+ }
+ _dragStarted += value;
+ }
+ remove
+ {
+ _dragStarted -= value;
+ if (_dragStarted == null)
+ {
+ int res = Interop.KVMService.SetDragStartEventHandler(_kvmService, null, IntPtr.Zero);
+ _tzsh.ErrorCodeThrow(res);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Emits the event when the drag ended on any window except KVM window.
+ /// </summary>
+ /// <exception cref="ArgumentException">Thrown when failed of invalid argument.</exception>
+ public event EventHandler DragEnded
+ {
+ add
+ {
+ if (_dragEnded == null)
+ {
+ _onDragEnded = OnDragEnded;
+ int res = Interop.KVMService.SetDragEndEventHandler(_kvmService, _onDragEnded, IntPtr.Zero);
+ _tzsh.ErrorCodeThrow(res);
+ }
+ _dragEnded += value;
+ }
+ remove
+ {
+ _dragEnded -= value;
+ if (_dragEnded == null)
+ {
+ int res = Interop.KVMService.SetDragEndEventHandler(_kvmService, null, IntPtr.Zero);
+ _tzsh.ErrorCodeThrow(res);
+ }
+ }
+ }
+
+ private void OnDragStarted(IntPtr data, IntPtr softkeyService)
+ {
+ _dragStarted?.Invoke(this, EventArgs.Empty);
+ }
+
+ private void OnDragEnded(IntPtr data, IntPtr softkeyService)
+ {
+ _dragEnded?.Invoke(this, EventArgs.Empty);
+ }
+
+ /// <summary>
+ /// Requests to perform drop to KVM window.
+ /// </summary>
+ /// <exception cref="ArgumentException">Thrown when failed of invalid argument.</exception>
+ public void PerformDrop()
+ {
+ int res = Interop.KVMService.PerformDrop(_kvmService);
+ _tzsh.ErrorCodeThrow(res);
+ }
+
+ /// <summary>
+ /// Requests to set KVM window as secondary selection window.
+ /// </summary>
+ /// <exception cref="ArgumentException">Thrown when failed of invalid argument.</exception>
+ public void SetSecondarySelction()
+ {
+ int res = Interop.KVMService.SetSecondarySelection(_kvmService);
+ _tzsh.ErrorCodeThrow(res);
+ }
+
+ /// <summary>
+ /// Requests to unset secondary selection window of KVM window.
+ /// </summary>
+ /// <exception cref="ArgumentException">Thrown when failed of invalid argument.</exception>
+ public void UnsetSecondarySelction()
+ {
+ int res = Interop.KVMService.UnsetSecondarySelection(_kvmService);
+ _tzsh.ErrorCodeThrow(res);
+ }
+ }
+}
--- /dev/null
+using System;
+using Tizen;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.WindowSystem;
+using System.Collections.Generic;
+
+namespace NUIWindowKVMSample
+{
+ class Program : NUIApplication
+ {
+ protected override void OnCreate()
+ {
+ base.OnCreate();
+ Initialize();
+ }
+
+ void Initialize()
+ {
+ Window win = Window.Instance;
+ dnd = DragAndDrop.Instance;
+
+ 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);
+
+ TextLabel text = new TextLabel("Start drag here");
+ text.HorizontalAlignment = HorizontalAlignment.Center;
+ text.VerticalAlignment = VerticalAlignment.Center;
+ text.TextColor = Color.Black;
+ text.PointSize = 12.0f;
+ text.HeightResizePolicy = ResizePolicyType.FillToParent;
+ text.WidthResizePolicy = ResizePolicyType.FillToParent;
+ windowView.Add(text);
+
+ KVMServiceWindow kvmServiceWindow = new KVMServiceWindow(new Rectangle(2500, 0, 60, 1440));
+ kvmServiceWindow.Show();
+ }
+
+ private void OnKeyEvent(object sender, Window.KeyEventArgs e)
+ {
+ if (e.Key.State == Key.StateType.Down && (e.Key.KeyPressedName == "XF86Back" || e.Key.KeyPressedName == "Escape"))
+ {
+ Exit();
+ }
+ }
+
+ private bool OnTouchEvent(object sender, View.TouchEventArgs e)
+ {
+ if (e.Touch.GetState(0) == PointStateType.Down)
+ {
+ View shadowView = new ImageView(Tizen.Applications.Application.Current.DirectoryInfo.SharedResource + "NUIWindowKVMSample.png");
+ shadowView.Size = new Size(100, 100);
+
+ DragData dragData;
+ dragData.MimeType = "text/plain";
+ dragData.Data = "Hello World";
+ dnd.StartDragAndDrop((View)sender, shadowView, dragData, OnSourceEventHandler);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ private void OnSourceEventHandler(DragSourceEventType e)
+ {
+ if (e == DragSourceEventType.Start)
+ {
+ Log.Debug("KVMSample", "Source App SourceEvnetType: Start");
+ }
+ else if (e == DragSourceEventType.Cancel)
+ {
+ Log.Debug("KVMSample", "Source App SourceEvnetType: Cancel");
+ }
+ else if (e == DragSourceEventType.Accept)
+ {
+ Log.Debug("KVMSample", "Source App SourceEvnetType: Accept");
+ }
+ else if (e == DragSourceEventType.Finish)
+ {
+ Log.Debug("KVMSample", "Source App SourceEvnetType: Finish");
+ }
+ }
+
+ static void Main(string[] args)
+ {
+ var app = new Program();
+ app.Run(args);
+ }
+
+ private DragAndDrop dnd;
+ }
+
+ class KVMServiceWindow : Window
+ {
+ public KVMServiceWindow(Rectangle winGeometry) :
+ base("KVM service Window", new Rectangle(winGeometry.X, winGeometry.Y, winGeometry.Width, winGeometry.Height))
+ {
+ dnd = DragAndDrop.Instance;
+ this.WindowSize = new Size2D(winGeometry.Width, winGeometry.Height);
+ this.BackgroundColor = Color.Yellow;
+
+ View windowView = new View();
+ windowView.Size2D = new Size2D(winGeometry.Width, winGeometry.Height);
+ windowView.BackgroundColor = Color.Yellow;
+ this.Add(windowView);
+
+ dnd.AddListener(windowView, OnDnDEvent);
+
+ tzShell = new Tizen.NUI.WindowSystem.Shell.TizenShell();
+ kvmService = new Tizen.NUI.WindowSystem.Shell.KVMService(tzShell, this);
+ kvmService.SetSecondarySelction();
+ kvmService.DragStarted += OnDragStarted;
+ kvmService.DragEnded += OnDragEnded;
+ }
+
+ private void OnDnDEvent(object sender, DragEvent e)
+ {
+ if (e.DragType == DragType.Enter)
+ {
+ Log.Debug("KVMSample", "Target(KVM) App DRagEvnetType: Enter");
+ kvmService.PerformDrop();
+ }
+ if (e.DragType == DragType.Drop)
+ {
+ Log.Debug("KVMSample", "Target(KVM) App DRagEvnetType: Drop, Data: " + e.Data);
+ }
+ }
+
+ private void OnDragStarted(object sender, EventArgs e)
+ {
+ Log.Debug("KVMSample", "Tizen KVM: Drag started");
+ }
+
+ private void OnDragEnded(object sender, EventArgs e)
+ {
+ Log.Debug("KVMSample", "Tizen KVM: Drag ended");
+ }
+
+ private DragAndDrop dnd;
+ private Tizen.NUI.WindowSystem.Shell.TizenShell tzShell;
+ private Tizen.NUI.WindowSystem.Shell.KVMService kvmService;
+ }
+}
--- /dev/null
+<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>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="7.5" package="org.tizen.example.NUIWindowKVMSample" version="1.0.0">
+ <profile name="common" />
+ <ui-application appid="org.tizen.example.NUIWindowKVMSample"
+ exec="NUIWindowKVMSample.dll"
+ type="dotnet-nui"
+ multiple="false"
+ taskmanage="true"
+ nodisplay="false"
+ launch_mode="single"
+ api-version="10">
+ <label>NUIWindowKVMSample</label>
+ <icon>NUIWindowKVMSample.png</icon>
+ <metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" />
+ </ui-application>
+</manifest>
--- /dev/null
+# csproj file path
+csproj_file: NUIWindowKVMSample.csproj
+
+# files monitored for dirty/modified status
+files:
+ - NUIWindowKVMSample.csproj
+ - NUIWindowKVMSample.cs
+ - tizen-manifest.xml
+ - shared/res/NUIWindowKVMSample.png
\ No newline at end of file