Merge pull request #1 from X9VoiD/windowsink-vmulti

Add WindowsInk
This commit is contained in:
X9VoiD 2020-09-14 23:53:34 +08:00 committed by GitHub
commit e2c7e41d8b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 206 additions and 0 deletions

View file

@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OemKill", "OemKill\OemKill.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TouchEmu", "TouchEmu\TouchEmu.csproj", "{FC135341-4870-4555-8917-7248CFE07FCC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsInk", "WindowsInk\WindowsInk.csproj", "{5DDEBB0A-D359-49F4-B1AE-7A13DB28987B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -27,6 +29,10 @@ Global
{FC135341-4870-4555-8917-7248CFE07FCC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC135341-4870-4555-8917-7248CFE07FCC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC135341-4870-4555-8917-7248CFE07FCC}.Release|Any CPU.Build.0 = Release|Any CPU
{5DDEBB0A-D359-49F4-B1AE-7A13DB28987B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5DDEBB0A-D359-49F4-B1AE-7A13DB28987B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5DDEBB0A-D359-49F4-B1AE-7A13DB28987B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5DDEBB0A-D359-49F4-B1AE-7A13DB28987B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

47
WindowsInk/VMulti.cs Normal file
View file

@ -0,0 +1,47 @@
using System;
namespace WindowsInk
{
public static class VMulti
{
// HID report structure for XP-Pen drivers. It is used to send Windows Ink packets.
public struct InkReport
{
public byte VMultiID; // ID to communicate to the Digitizer device
public byte ReportLength; // Size of the report in bytes.
public byte ReportID; // ID of the report.
public byte Buttons; // Byte with switches for pen buttons / states
public ushort X; // X position of the pen from 0 to 32767
public ushort Y; // Y position of the pen from 0 to 32767
public ushort Pressure; // Pressure level from 0 to 8191
public byte[] ToBytes()
{
var bytes = new byte[10];
bytes[0] = VMultiID;
bytes[1] = ReportLength;
bytes[2] = ReportID;
bytes[3] = Buttons;
bytes[4] = (byte)(X & 0xFF);
bytes[5] = (byte)((X & 0xFF00) >> 8);
bytes[6] = (byte)(Y & 0xFF);
bytes[7] = (byte)((Y & 0xFF00) >> 8);
bytes[8] = (byte)(Pressure & 0xFF);
bytes[9] = (byte)((Pressure & 0xFF00) >> 8);
return bytes;
}
public static implicit operator byte[](InkReport report)
{
return report.ToBytes();
}
}
public enum ButtonMask : int
{
Press = 1,
Barrel = 2,
Eraser = 4,
Invert = 8,
InRange = 16
}
}
}

134
WindowsInk/WindowsInk.cs Normal file
View file

@ -0,0 +1,134 @@
using System;
using System.Numerics;
using HidSharp;
using OpenTabletDriver.Plugin;
using OpenTabletDriver.Plugin.Attributes;
using OpenTabletDriver.Plugin.Output;
using OpenTabletDriver.Plugin.Platform.Pointer;
using static WindowsInk.VMulti;
namespace WindowsInk
{
internal static class WindowsInkState
{
public static InkHandler InkHandler = null;
}
[PluginName("Artist Mode"), SupportedPlatform(PluginPlatform.Windows)]
public class WindowsInk : AbsoluteOutputMode
{
public override IVirtualTablet VirtualTablet => WindowsInkState.InkHandler ?? new InkHandler(Output);
}
public class InkHandler : IVirtualTablet, IPressureHandler
{
private InkReport InkReport;
private readonly HidStream VMultiDev;
private Area ScreenArea;
private bool EraserState;
public InkHandler(Area screenArea)
{
WindowsInkState.InkHandler = this;
InkReport = new InkReport()
{
VMultiID = 0x40,
ReportLength = 0x0a,
ReportID = 0x05,
Buttons = (byte)ButtonMask.InRange
};
VMultiDev = null;
foreach (var device in DeviceList.Local.GetHidDevices(productID: 47820))
{
if (device.GetMaxOutputReportLength() == 65 && device.GetMaxInputReportLength() == 65)
{
device.TryOpen(out VMultiDev);
if (VMultiDev == null)
{
Log.Write("WindowsInk", "Cannot find VirtualHID", LogLevel.Error);
}
}
}
ScreenArea = screenArea;
EraserState = false;
}
public void MouseDown(MouseButton button)
{
switch (button)
{
case MouseButton.Left:
if (!EraserState)
{
EnableBit(ButtonMask.Press);
}
break;
case MouseButton.Right:
EnableBit(ButtonMask.Barrel);
break;
case MouseButton.Middle:
EnableBit(ButtonMask.Eraser);
DisableBit(ButtonMask.Press);
EraserState = true;
StateChange();
break;
}
}
public void MouseUp(MouseButton button)
{
switch (button)
{
case MouseButton.Left:
DisableBit(ButtonMask.Press);
break;
case MouseButton.Right:
DisableBit(ButtonMask.Barrel);
break;
case MouseButton.Middle:
DisableBit(ButtonMask.Eraser);
EraserState = false;
StateChange();
break;
}
}
public void SetPosition(Vector2 pos)
{
InkReport.X = (ushort)(pos.X / ScreenArea.Width * 32767);
InkReport.Y = (ushort)(pos.Y / ScreenArea.Height * 32767);
VMultiDev.Write(InkReport);
}
public void SetPressure(float percentage)
{
InkReport.Pressure = (ushort)(percentage * 8191);
}
private void EnableBit(ButtonMask mask)
{
InkReport.Buttons = (byte)(InkReport.Buttons | (int)mask);
}
private void DisableBit(ButtonMask mask)
{
InkReport.Buttons = (byte)(InkReport.Buttons & ~(int)mask);
}
private void StateChange()
{
var prevState = InkReport.Buttons;
var prevPressure = InkReport.Pressure;
InkReport.ReportID = 0;
InkReport.Buttons = 0;
InkReport.Pressure = 0;
VMultiDev.Write(InkReport);
InkReport.ReportID = 0x05;
InkReport.Buttons = prevState;
InkReport.Pressure = prevPressure;
}
}
}

View file

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp3.1; net5.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
<CopyOutputSymbolsToOutputDirectory>false</CopyOutputSymbolsToOutputDirectory>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="HidSharpCore" Version="1.0.1" />
<ProjectReference Include="../.modules/OpenTabletDriver/OpenTabletDriver.Plugin/OpenTabletDriver.Plugin.csproj" />
</ItemGroup>
</Project>