diff --git a/Directory.Packages.props b/Directory.Packages.props index 5afa09327e..6734a7f99a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -33,6 +33,7 @@ + diff --git a/NOTICE.md b/NOTICE.md index b7c165b08b..119e359b25 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -308,6 +308,7 @@ SOFTWARE. - Microsoft.Windows.CsWin32 0.2.46-beta - Microsoft.Windows.CsWinRT 2.0.2 - Microsoft.Windows.SDK.BuildTools 10.0.22621.755 +- Microsoft.Windows.SDK.Contracts 10.0.19041.1 - Microsoft.WindowsAppSDK 1.3.230502000 - Microsoft.Xaml.Behaviors.WinUI.Managed 2.0.9 - Microsoft.Xaml.Behaviors.Wpf 1.1.39 diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs b/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs index a5b91eb460..2c7f271b61 100644 --- a/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs +++ b/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs @@ -20,6 +20,7 @@ using System.Threading; using Microsoft.Win32; using MouseWithoutBorders.Class; using MouseWithoutBorders.Form; +using Windows.UI.Input.Preview.Injection; namespace MouseWithoutBorders { @@ -110,6 +111,21 @@ namespace MouseWithoutBorders Common.Log(e.Message); } + try + { + InputSimulation.Injector = InputInjector.TryCreate(); + if (InputSimulation.Injector != null) + { + InputSimulation.MoveMouseRelative(0, 0); + NativeMethods.InjectMouseInputAvailable = true; + } + } + catch (EntryPointNotFoundException) + { + NativeMethods.InjectMouseInputAvailable = false; + Common.Log($"{nameof(NativeMethods.InjectMouseInputAvailable)} = false"); + } + bool dummy = Setting.Values.DrawMouseEx; Is64bitOS = IntPtr.Size == 8; tcpPort = Setting.Values.TcpPort; diff --git a/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs b/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs index b46dcd9cb9..220da7454e 100644 --- a/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs +++ b/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs @@ -15,6 +15,8 @@ using System.Globalization; using System.Runtime.InteropServices; using System.ServiceProcess; using System.Threading.Tasks; +using Windows.UI.Input.Preview.Injection; +using static MouseWithoutBorders.Class.NativeMethods; [module: SuppressMessage("Microsoft.Portability", "CA1901:PInvokeDeclarationsShouldBePortable", Scope = "member", Target = "MouseWithoutBorders.InputSimulation.#keybd_event(System.Byte,System.Byte,System.UInt32,System.Int32)", MessageId = "3", Justification = "Dotnet port with style preservation")] [module: SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", Scope = "member", Target = "MouseWithoutBorders.InputSimulation.#InputProcessKeyEx(System.Int32,System.Int32,System.Boolean&)", MessageId = "MouseWithoutBorders.NativeMethods.LockWorkStation", Justification = "Dotnet port with style preservation")] @@ -23,15 +25,30 @@ namespace MouseWithoutBorders.Class { internal class InputSimulation { + public static InputInjector Injector; + private InputSimulation() { } + internal static InjectedInputMouseInfo MouseInputToInjectedInputMouseInfo(MOUSEINPUT mouseInput) + { + var injectedInput = new InjectedInputMouseInfo(); + + injectedInput.DeltaX = mouseInput.dx; + injectedInput.DeltaY = mouseInput.dy; + injectedInput.MouseData = (uint)mouseInput.mouseData; + injectedInput.MouseOptions = (InjectedInputMouseOptions)mouseInput.dwFlags; + injectedInput.TimeOffsetInMilliseconds = (uint)mouseInput.time; + + return injectedInput; + } + private static uint SendInputEx(NativeMethods.INPUT input) { Common.PaintCount = 0; - uint rv; + uint rv = 0; if (Common.Is64bitOS) { NativeMethods.INPUT64 input64 = default; @@ -58,18 +75,27 @@ namespace MouseWithoutBorders.Class input64.mi.dwExtraInfo = input.mi.dwExtraInfo; } - NativeMethods.INPUT64[] inputs = { input64 }; - - // mouse click simulation - // TODO: Find alternative API that simulates mouse input more directly - rv = NativeMethods.SendInput64(1, inputs, Marshal.SizeOf(input64)); + if (input.type == 0 && (input.mi.dwFlags & (int)NativeMethods.MOUSEEVENTF.MOVE) != 0 && NativeMethods.InjectMouseInputAvailable) + { + Injector.InjectMouseInput(new[] { MouseInputToInjectedInputMouseInfo(input64.mi) }); + } + else + { + NativeMethods.INPUT64[] inputs = { input64 }; + rv = NativeMethods.SendInput64(1, inputs, Marshal.SizeOf(input64)); + } } else { - NativeMethods.INPUT[] inputs = { input }; - - // TODO: Find alternative API that simulates mouse input more directly - rv = NativeMethods.SendInput(1, inputs, Marshal.SizeOf(input)); + if (input.type == 0 && (input.mi.dwFlags & (int)NativeMethods.MOUSEEVENTF.MOVE) != 0 && NativeMethods.InjectMouseInputAvailable) + { + Injector.InjectMouseInput(new[] { MouseInputToInjectedInputMouseInfo(input.mi) }); + } + else + { + NativeMethods.INPUT[] inputs = { input }; + rv = NativeMethods.SendInput(1, inputs, Marshal.SizeOf(input)); + } } return rv; diff --git a/src/modules/MouseWithoutBorders/App/Class/NativeMethods.cs b/src/modules/MouseWithoutBorders/App/Class/NativeMethods.cs index 6bc101f6ca..a0b1621c97 100644 --- a/src/modules/MouseWithoutBorders/App/Class/NativeMethods.cs +++ b/src/modules/MouseWithoutBorders/App/Class/NativeMethods.cs @@ -576,6 +576,8 @@ namespace MouseWithoutBorders.Class [DllImport("user32.dll", EntryPoint = "SendInput", SetLastError = true)] internal static extern uint SendInput64(uint nInputs, INPUT64[] pInputs, int cbSize); + internal static bool InjectMouseInputAvailable { get; set; } + [DllImport("user32.dll", EntryPoint = "GetMessageExtraInfo", SetLastError = true)] internal static extern IntPtr GetMessageExtraInfo(); diff --git a/src/modules/MouseWithoutBorders/App/MouseWithoutBorders.csproj b/src/modules/MouseWithoutBorders/App/MouseWithoutBorders.csproj index 60e75ccb63..a526b68449 100644 --- a/src/modules/MouseWithoutBorders/App/MouseWithoutBorders.csproj +++ b/src/modules/MouseWithoutBorders/App/MouseWithoutBorders.csproj @@ -217,6 +217,7 @@ all +