diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 95106bd1de..d23d2c79bd 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -334,9 +334,11 @@ cvtepu cvtsi cwd cxfksword +CXSCREEN CXSMICON CXVIRTUALSCREEN cyberrex +CYSCREEN CYSMICON CYVIRTUALSCREEN cziplib diff --git a/src/modules/MouseUtils/MouseJumpUI/Helpers/NativeMethods.cs b/src/modules/MouseUtils/MouseJumpUI/Helpers/NativeMethods.cs new file mode 100644 index 0000000000..9627c27e04 --- /dev/null +++ b/src/modules/MouseUtils/MouseJumpUI/Helpers/NativeMethods.cs @@ -0,0 +1,112 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +namespace MouseJumpUI.Helpers +{ + // Win32 functions required for temporary workaround for issue #1273 + internal class NativeMethods + { + [DllImport("user32.dll")] + internal static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize); + + [DllImport("user32.dll")] + internal static extern int GetSystemMetrics(SystemMetric smIndex); + + [StructLayout(LayoutKind.Sequential)] + public struct INPUT + { + internal INPUTTYPE type; + internal InputUnion data; + + internal static int Size + { + get { return Marshal.SizeOf(typeof(INPUT)); } + } + } + + [StructLayout(LayoutKind.Explicit)] + internal struct InputUnion + { + [FieldOffset(0)] + internal MOUSEINPUT mi; + [FieldOffset(0)] + internal KEYBDINPUT ki; + [FieldOffset(0)] + internal HARDWAREINPUT hi; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct MOUSEINPUT + { + internal int dx; + internal int dy; + internal int mouseData; + internal uint dwFlags; + internal uint time; + internal UIntPtr dwExtraInfo; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct KEYBDINPUT + { + internal short wVk; + internal short wScan; + internal uint dwFlags; + internal int time; + internal UIntPtr dwExtraInfo; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HARDWAREINPUT + { + internal int uMsg; + internal short wParamL; + internal short wParamH; + } + + internal enum INPUTTYPE : uint + { + INPUT_MOUSE = 0, + INPUT_KEYBOARD = 1, + INPUT_HARDWARE = 2, + } + + internal enum MOUSE_INPUT_FLAGS : uint + { + MOUSEEVENTF_MOVE = 0x0001, + MOUSEEVENTF_LEFTDOWN = 0x0002, + MOUSEEVENTF_LEFTUP = 0x0004, + MOUSEEVENTF_RIGHTDOWN = 0x0008, + MOUSEEVENTF_RIGHTUP = 0x0010, + MOUSEEVENTF_MIDDLEDOWN = 0x0020, + MOUSEEVENTF_MIDDLEUP = 0x0040, + MOUSEEVENTF_XDOWN = 0x0080, + MOUSEEVENTF_XUP = 0x0100, + MOUSEEVENTF_WHEEL = 0x0800, + MOUSEEVENTF_HWHEEL = 0x1000, + MOUSEEVENTF_MOVE_NOCOALESCE = 0x2000, + MOUSEEVENTF_VIRTUALDESK = 0x4000, + MOUSEEVENTF_ABSOLUTE = 0x8000, + } + + internal enum SystemMetric + { + SM_CXSCREEN = 0, + SM_CYSCREEN = 1, + } + + internal static int CalculateAbsoluteCoordinateX(int x) + { + return (x * 65536) / GetSystemMetrics(SystemMetric.SM_CXSCREEN); + } + + internal static int CalculateAbsoluteCoordinateY(int y) + { + return (y * 65536) / GetSystemMetrics(SystemMetric.SM_CYSCREEN); + } + } +} diff --git a/src/modules/MouseUtils/MouseJumpUI/MainForm.cs b/src/modules/MouseUtils/MouseJumpUI/MainForm.cs index cfd0836ee4..a7bfbf8067 100644 --- a/src/modules/MouseUtils/MouseJumpUI/MainForm.cs +++ b/src/modules/MouseUtils/MouseJumpUI/MainForm.cs @@ -43,6 +43,29 @@ internal partial class MainForm : Form this.Close(); } + // Sends an input simulating an absolute mouse move to the new location. + private void SimulateMouseMovementEvent(Point location) + { + NativeMethods.INPUT mouseMoveInput = new NativeMethods.INPUT + { + type = NativeMethods.INPUTTYPE.INPUT_MOUSE, + data = new NativeMethods.InputUnion + { + mi = new NativeMethods.MOUSEINPUT + { + dx = NativeMethods.CalculateAbsoluteCoordinateX(location.X), + dy = NativeMethods.CalculateAbsoluteCoordinateY(location.Y), + mouseData = 0, + dwFlags = (uint)NativeMethods.MOUSE_INPUT_FLAGS.MOUSEEVENTF_MOVE | (uint)NativeMethods.MOUSE_INPUT_FLAGS.MOUSEEVENTF_ABSOLUTE, + time = 0, + dwExtraInfo = 0, + }, + }, + }; + NativeMethods.INPUT[] inputs = new NativeMethods.INPUT[] { mouseMoveInput }; + _ = NativeMethods.SendInput(1, inputs, NativeMethods.INPUT.Size); + } + private void Thumbnail_Click(object sender, EventArgs e) { var mouseEventArgs = (MouseEventArgs)e; @@ -83,6 +106,10 @@ internal partial class MainForm : Form // https://github.com/mikeclayton/FancyMouse/pull/3 Cursor.Position = scaledLocation; Cursor.Position = scaledLocation; + + // Simulate mouse input for handlers that won't just catch the Cursor change + SimulateMouseMovementEvent(scaledLocation); + Microsoft.PowerToys.Telemetry.PowerToysTelemetry.Log.WriteEvent(new Telemetry.MouseJumpTeleportCursorEvent()); }