mirror of
https://github.com/vale981/VoiDPlugins
synced 2025-03-04 16:51:38 -05:00
Repurpose WindowsInk to TouchEmu
This commit is contained in:
parent
64e2271750
commit
b30c73f52b
8 changed files with 118 additions and 104 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule ".modules/OpenTabletDriver"]
|
||||||
|
path = .modules/OpenTabletDriver
|
||||||
|
url = https://github.com/InfinityGhost/OpenTabletDriver
|
1
.modules/OpenTabletDriver
Submodule
1
.modules/OpenTabletDriver
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 5ee2bae3d188cf6c468cf93df9a5815d2daa5ef1
|
|
@ -7,7 +7,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MLFilter", "MLFilter\MLFilt
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OemKill", "OemKill\OemKill.csproj", "{4EC8FA2D-0CCC-4FC3-A32A-BC063924A803}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OemKill", "OemKill\OemKill.csproj", "{4EC8FA2D-0CCC-4FC3-A32A-BC063924A803}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsInk", "WindowsInk\WindowsInk.csproj", "{FC135341-4870-4555-8917-7248CFE07FCC}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TouchEmu", "TouchEmu\TouchEmu.csproj", "{FC135341-4870-4555-8917-7248CFE07FCC}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace WindowsInk
|
namespace TouchEmu
|
||||||
{
|
{
|
||||||
using HANDLE = IntPtr;
|
using HANDLE = IntPtr;
|
||||||
using HWND = IntPtr;
|
using HWND = IntPtr;
|
||||||
|
@ -143,10 +143,10 @@ namespace WindowsInk
|
||||||
public unsafe struct POINTER_DEVICE_INFO
|
public unsafe struct POINTER_DEVICE_INFO
|
||||||
{
|
{
|
||||||
public DWORD displayOrientation;
|
public DWORD displayOrientation;
|
||||||
public IntPtr device;
|
public void* device;
|
||||||
public POINTER_DEVICE_TYPE pointerDeviceType;
|
public POINTER_DEVICE_TYPE pointerDeviceType;
|
||||||
public IntPtr monitor;
|
public void* monitor;
|
||||||
public ulong startingCursorId;
|
public uint startingCursorId;
|
||||||
public ushort maxActiveContacts;
|
public ushort maxActiveContacts;
|
||||||
|
|
||||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 520)]
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 520)]
|
||||||
|
@ -164,6 +164,10 @@ namespace WindowsInk
|
||||||
public static extern bool InjectSyntheticPointerInput(IntPtr device, [In, MarshalAs(UnmanagedType.LPArray)] POINTER_TYPE_INFO[] pointerInfo, uint count);
|
public static extern bool InjectSyntheticPointerInput(IntPtr device, [In, MarshalAs(UnmanagedType.LPArray)] POINTER_TYPE_INFO[] pointerInfo, uint count);
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
|
[DllImport("user32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
|
||||||
public static extern bool GetPointerDevices(ref uint deviceCount, IntPtr pointerDevices);
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static unsafe extern bool GetPointerDevices(out uint deviceCount, [In, Out, MarshalAs(UnmanagedType.LPArray)] POINTER_DEVICE_INFO[] pointerDevices);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
|
||||||
|
public static extern IntPtr GetForegroundWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,38 +2,39 @@ using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using TabletDriverPlugin;
|
using TabletDriverPlugin;
|
||||||
|
|
||||||
namespace WindowsInk
|
namespace TouchEmu
|
||||||
{
|
{
|
||||||
public static class Pen
|
public static class Touch
|
||||||
{
|
{
|
||||||
private static IntPtr _penHandle;
|
private static IntPtr _penHandle;
|
||||||
private static POINTER_TYPE_INFO[] pointer;
|
private static POINTER_TYPE_INFO[] pointer;
|
||||||
private static uint _pointerId;
|
private static uint _pointerId;
|
||||||
private static IntPtr _sourceDevice;
|
private static IntPtr _sourceDevice;
|
||||||
|
|
||||||
public static void Init()
|
public static unsafe void Init()
|
||||||
{
|
{
|
||||||
uint count = 0;
|
NativeMethods.GetPointerDevices(out uint count, null);
|
||||||
NativeMethods.GetPointerDevices(ref count, out var pointerDevices);
|
POINTER_DEVICE_INFO[] pointerDevices = new POINTER_DEVICE_INFO[count];
|
||||||
foreach (var device in pointerDevices)
|
NativeMethods.GetPointerDevices(out count, pointerDevices);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
|
var device = pointerDevices[i];
|
||||||
if (device.pointerDeviceType == POINTER_DEVICE_TYPE.EXTERNAL_PEN ||
|
if (device.pointerDeviceType == POINTER_DEVICE_TYPE.EXTERNAL_PEN ||
|
||||||
device.pointerDeviceType == POINTER_DEVICE_TYPE.INTEGRATED_PEN)
|
device.pointerDeviceType == POINTER_DEVICE_TYPE.INTEGRATED_PEN)
|
||||||
{
|
{
|
||||||
_pointerId = (uint)device.startingCursorId;
|
_pointerId = (uint)device.startingCursorId;
|
||||||
_sourceDevice = device.device;
|
_sourceDevice = new IntPtr(device.device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Write("WindowsInk", "Pen created", LogLevel.Debug);
|
|
||||||
var _pointerInfo = new POINTER_INFO
|
var _pointerInfo = new POINTER_INFO
|
||||||
{
|
{
|
||||||
pointerType = POINTER_INPUT_TYPE.PT_PEN,
|
pointerType = POINTER_INPUT_TYPE.PT_PEN,
|
||||||
pointerId = _pointerId,
|
pointerId = _pointerId,
|
||||||
frameId = 0,
|
frameId = 0,
|
||||||
pointerFlags = POINTER_FLAGS.NONE,
|
pointerFlags = POINTER_FLAGS.NONE,
|
||||||
sourceDevice = IntPtr.Zero,
|
sourceDevice = _sourceDevice,
|
||||||
hwndTarget = IntPtr.Zero,
|
hwndTarget = NativeMethods.GetForegroundWindow(),
|
||||||
ptPixelLocation = new POINT(),
|
ptPixelLocation = new POINT(),
|
||||||
ptPixelLocationRaw = new POINT(),
|
ptPixelLocationRaw = new POINT(),
|
||||||
dwTime = 0,
|
dwTime = 0,
|
||||||
|
@ -67,9 +68,7 @@ namespace WindowsInk
|
||||||
_penHandle = NativeMethods.CreateSyntheticPointerDevice(POINTER_INPUT_TYPE.PT_PEN, 1, POINTER_FEEDBACK_MODE.INDIRECT);
|
_penHandle = NativeMethods.CreateSyntheticPointerDevice(POINTER_INPUT_TYPE.PT_PEN, 1, POINTER_FEEDBACK_MODE.INDIRECT);
|
||||||
var err = Marshal.GetLastWin32Error();
|
var err = Marshal.GetLastWin32Error();
|
||||||
if (err < 0 || _penHandle == IntPtr.Zero)
|
if (err < 0 || _penHandle == IntPtr.Zero)
|
||||||
Log.Write("WindowsInk", "Failed creating synthetic pointer. Reason: " + err, LogLevel.Error);
|
throw new Exception("Failed to create handle.");
|
||||||
else
|
|
||||||
Log.Write("WindowsInk", "Pen handle retrieved successfully", LogLevel.Debug);
|
|
||||||
|
|
||||||
// Notify WindowsInk
|
// Notify WindowsInk
|
||||||
ClearPointerFlags(POINTER_FLAGS.NEW);
|
ClearPointerFlags(POINTER_FLAGS.NEW);
|
||||||
|
@ -83,16 +82,19 @@ namespace WindowsInk
|
||||||
{
|
{
|
||||||
if (!NativeMethods.InjectSyntheticPointerInput(_penHandle, pointer, 1))
|
if (!NativeMethods.InjectSyntheticPointerInput(_penHandle, pointer, 1))
|
||||||
{
|
{
|
||||||
Log.Write("WindowsInk", "Injection Failed. Reason: " + Marshal.GetLastWin32Error());
|
throw new Exception($"Input injection failed. Reason: {Marshal.GetLastWin32Error()}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SetTarget()
|
||||||
|
{
|
||||||
|
pointer[0].penInfo.pointerInfo.hwndTarget = NativeMethods.GetForegroundWindow();
|
||||||
|
}
|
||||||
|
|
||||||
public static void SetPosition(POINT point)
|
public static void SetPosition(POINT point)
|
||||||
{
|
{
|
||||||
pointer[0].penInfo.pointerInfo.ptPixelLocation = point;
|
pointer[0].penInfo.pointerInfo.ptPixelLocation = point;
|
||||||
pointer[0].penInfo.pointerInfo.ptPixelLocationRaw = point;
|
pointer[0].penInfo.pointerInfo.ptPixelLocationRaw = point;
|
||||||
// pointer[0].penInfo.pointerInfo.ptHimetricLocation = point;
|
|
||||||
// pointer[0].penInfo.pointerInfo.ptHimetricLocationRaw = point;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetPressure(uint pressure)
|
public static void SetPressure(uint pressure)
|
||||||
|
@ -120,4 +122,4 @@ namespace WindowsInk
|
||||||
pointer[0].penInfo.pointerInfo.pointerFlags = flags;
|
pointer[0].penInfo.pointerInfo.pointerFlags = flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
84
TouchEmu/TouchEmu.cs
Normal file
84
TouchEmu/TouchEmu.cs
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
using TabletDriverPlugin;
|
||||||
|
using TabletDriverPlugin.Attributes;
|
||||||
|
using TabletDriverPlugin.Output;
|
||||||
|
using TabletDriverPlugin.Platform.Pointer;
|
||||||
|
|
||||||
|
namespace TouchEmu
|
||||||
|
{
|
||||||
|
public static class TouchState
|
||||||
|
{
|
||||||
|
public static IVirtualTablet touchPointer = new TouchPointerHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
[PluginName("Touch Emu"), SupportedPlatform(PluginPlatform.Windows)]
|
||||||
|
public class TouchOutputMode : AbsoluteOutputMode
|
||||||
|
{
|
||||||
|
public override IVirtualTablet VirtualTablet => TouchState.touchPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TouchPointerHandler : IVirtualTablet, IPressureHandler
|
||||||
|
{
|
||||||
|
private bool _inContact;
|
||||||
|
private bool _lastContact;
|
||||||
|
|
||||||
|
public TouchPointerHandler()
|
||||||
|
{
|
||||||
|
Touch.Init();
|
||||||
|
_inContact = false;
|
||||||
|
_lastContact = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MouseDown(MouseButton button)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MouseUp(MouseButton button)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetPosition(Point pos)
|
||||||
|
{
|
||||||
|
Touch.SetPosition(new POINT((int)pos.X, (int)pos.Y));
|
||||||
|
if (_inContact != _lastContact)
|
||||||
|
{
|
||||||
|
if (_inContact)
|
||||||
|
{
|
||||||
|
Touch.UnsetPointerFlags(POINTER_FLAGS.UP | POINTER_FLAGS.UPDATE);
|
||||||
|
Touch.SetPointerFlags(POINTER_FLAGS.DOWN);
|
||||||
|
_lastContact = _inContact;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Touch.UnsetPointerFlags(POINTER_FLAGS.DOWN | POINTER_FLAGS.UPDATE);
|
||||||
|
Touch.SetPointerFlags(POINTER_FLAGS.UP);
|
||||||
|
_lastContact = _inContact;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Touch.SetPointerFlags(POINTER_FLAGS.UPDATE);
|
||||||
|
}
|
||||||
|
Touch.SetTarget();
|
||||||
|
Touch.Inject();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetPressure(float percentage)
|
||||||
|
{
|
||||||
|
var pressure = (uint)(percentage * 1024);
|
||||||
|
if (pressure > 0)
|
||||||
|
{
|
||||||
|
Touch.SetPressure(pressure);
|
||||||
|
Touch.SetPointerFlags(POINTER_FLAGS.INCONTACT | POINTER_FLAGS.FIRSTBUTTON);
|
||||||
|
_inContact = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Touch.SetPressure(1);
|
||||||
|
Touch.UnsetPointerFlags(POINTER_FLAGS.INCONTACT | POINTER_FLAGS.FIRSTBUTTON);
|
||||||
|
_inContact = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="TabletDriverPlugin" Version="0.3.2" />
|
<ProjectReference Include="../.modules/OpenTabletDriver/TabletDriverPlugin/TabletDriverPlugin.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
|
@ -1,80 +0,0 @@
|
||||||
using TabletDriverPlugin;
|
|
||||||
using TabletDriverPlugin.Attributes;
|
|
||||||
using TabletDriverPlugin.Output;
|
|
||||||
using TabletDriverPlugin.Platform.Pointer;
|
|
||||||
|
|
||||||
namespace WindowsInk
|
|
||||||
{
|
|
||||||
public static class InkState
|
|
||||||
{
|
|
||||||
public static IPointerHandler inkPointer = new InkPointerHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
[PluginName("Windows Ink"), SupportedPlatform(PluginPlatform.Windows)]
|
|
||||||
public class InkOutputMode : AbsoluteOutputMode
|
|
||||||
{
|
|
||||||
public override IPointerHandler PointerHandler => InkState.inkPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class InkPointerHandler : IPointerHandler, IPressureHandler
|
|
||||||
{
|
|
||||||
private Point _lastPos;
|
|
||||||
private bool _inContact;
|
|
||||||
private bool _lastContact;
|
|
||||||
|
|
||||||
public InkPointerHandler()
|
|
||||||
{
|
|
||||||
Pen.Init();
|
|
||||||
_inContact = false;
|
|
||||||
_lastContact = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Point GetPosition()
|
|
||||||
{
|
|
||||||
return _lastPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetPosition(Point pos)
|
|
||||||
{
|
|
||||||
Pen.SetPosition(new POINT((int)pos.X, (int)pos.Y));
|
|
||||||
if (_inContact != _lastContact)
|
|
||||||
{
|
|
||||||
if (_inContact)
|
|
||||||
{
|
|
||||||
Pen.UnsetPointerFlags(POINTER_FLAGS.UP | POINTER_FLAGS.UPDATE);
|
|
||||||
Pen.SetPointerFlags(POINTER_FLAGS.DOWN);
|
|
||||||
_lastContact = _inContact;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Pen.UnsetPointerFlags(POINTER_FLAGS.DOWN | POINTER_FLAGS.UPDATE);
|
|
||||||
Pen.SetPointerFlags(POINTER_FLAGS.UP);
|
|
||||||
_lastContact = _inContact;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Pen.SetPointerFlags(POINTER_FLAGS.UPDATE);
|
|
||||||
}
|
|
||||||
Pen.Inject();
|
|
||||||
_lastPos = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetPressure(float percentage)
|
|
||||||
{
|
|
||||||
var pressure = (uint)(percentage * 1024);
|
|
||||||
if (pressure > 0)
|
|
||||||
{
|
|
||||||
Pen.SetPressure(pressure);
|
|
||||||
Pen.SetPointerFlags(POINTER_FLAGS.INCONTACT | POINTER_FLAGS.FIRSTBUTTON);
|
|
||||||
_inContact = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Pen.SetPressure(1);
|
|
||||||
Pen.UnsetPointerFlags(POINTER_FLAGS.INCONTACT | POINTER_FLAGS.FIRSTBUTTON);
|
|
||||||
_inContact = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue