diff --git a/WinSyncScroll/ViewModels/MainViewModel.cs b/WinSyncScroll/ViewModels/MainViewModel.cs index 63fcc9d..415b08e 100644 --- a/WinSyncScroll/ViewModels/MainViewModel.cs +++ b/WinSyncScroll/ViewModels/MainViewModel.cs @@ -95,8 +95,10 @@ public sealed partial class MainViewModel : IDisposable private Task? _mouseEventProcessingLoopTask; private Task? _updateMouseHookRectsLoopTask; - private int _smCxScreen; - private int _smCyScreen; + private int _smXVirtualScreen; + private int _smYVirtualScreen; + private int _smCxVirtualScreen; + private int _smCyVirtualScreen; private static readonly int SizeOfInput = Marshal.SizeOf(); @@ -144,8 +146,8 @@ private static INPUT CreateScrollInput(nuint mouseMessageId, int absoluteX, int }; var dwFlags = mouseMessageId switch { - WinApiConstants.WM_MOUSEWHEEL => MOUSE_EVENT_FLAGS.MOUSEEVENTF_WHEEL | MOUSE_EVENT_FLAGS.MOUSEEVENTF_ABSOLUTE | MOUSE_EVENT_FLAGS.MOUSEEVENTF_MOVE_NOCOALESCE, - WinApiConstants.WM_MOUSEHWHEEL => MOUSE_EVENT_FLAGS.MOUSEEVENTF_HWHEEL | MOUSE_EVENT_FLAGS.MOUSEEVENTF_ABSOLUTE | MOUSE_EVENT_FLAGS.MOUSEEVENTF_MOVE_NOCOALESCE, + WinApiConstants.WM_MOUSEWHEEL => MOUSE_EVENT_FLAGS.MOUSEEVENTF_WHEEL | MOUSE_EVENT_FLAGS.MOUSEEVENTF_VIRTUALDESK | MOUSE_EVENT_FLAGS.MOUSEEVENTF_ABSOLUTE | MOUSE_EVENT_FLAGS.MOUSEEVENTF_MOVE_NOCOALESCE, + WinApiConstants.WM_MOUSEHWHEEL => MOUSE_EVENT_FLAGS.MOUSEEVENTF_HWHEEL | MOUSE_EVENT_FLAGS.MOUSEEVENTF_VIRTUALDESK | MOUSE_EVENT_FLAGS.MOUSEEVENTF_ABSOLUTE | MOUSE_EVENT_FLAGS.MOUSEEVENTF_MOVE_NOCOALESCE, _ => MOUSE_EVENT_FLAGS.MOUSEEVENTF_MOVE, }; inputScroll.Anonymous.mi.dwFlags = dwFlags; @@ -164,7 +166,7 @@ private static INPUT CreateMoveInput(int absoluteX, int absoluteY) { type = INPUT_TYPE.INPUT_MOUSE, }; - inputMove.Anonymous.mi.dwFlags = MOUSE_EVENT_FLAGS.MOUSEEVENTF_MOVE | MOUSE_EVENT_FLAGS.MOUSEEVENTF_ABSOLUTE | MOUSE_EVENT_FLAGS.MOUSEEVENTF_MOVE_NOCOALESCE; + inputMove.Anonymous.mi.dwFlags = MOUSE_EVENT_FLAGS.MOUSEEVENTF_MOVE | MOUSE_EVENT_FLAGS.MOUSEEVENTF_VIRTUALDESK | MOUSE_EVENT_FLAGS.MOUSEEVENTF_ABSOLUTE | MOUSE_EVENT_FLAGS.MOUSEEVENTF_MOVE_NOCOALESCE; inputMove.Anonymous.mi.time = 0; inputMove.Anonymous.mi.mouseData = 0; inputMove.Anonymous.mi.dx = absoluteX; @@ -176,9 +178,11 @@ private static INPUT CreateMoveInput(int absoluteX, int absoluteY) private (int X, int Y) CalculateAbsoluteCoordinates(int x, int y) { + // Convert screen coordinates to absolute coordinates for SendInput + // Formula: ((coordinate - virtualScreenOffset) * 65536) / virtualScreenSize return ( - X: PInvoke.MulDiv(x, 65536, _smCxScreen), - Y: PInvoke.MulDiv(y, 65536, _smCyScreen) + X: PInvoke.MulDiv(x - _smXVirtualScreen, 65536, _smCxVirtualScreen), + Y: PInvoke.MulDiv(y - _smYVirtualScreen, 65536, _smCyVirtualScreen) ); } @@ -320,7 +324,7 @@ private async Task RunMouseEventProcessingLoopAsync( var (sourceAbsoluteX, sourceAbsoluteY) = CalculateAbsoluteCoordinates(sourceEventX, sourceEventY); var (targetAbsoluteX, targetAbsoluteY) = CalculateAbsoluteCoordinates(targetX, targetY); - _logger.LogTrace("Converted coordinates: Source=({SourceEventX},{SourceEventY}) -> ({SourceAbsoluteX},{SourceAbsoluteY}), Target=({TargetX},{TargetY}) -> ({TargetAbsoluteX},{TargetAbsoluteY}). _smCxScreen={SmCxScreen}, _smCyScreen={SmCyScreen}", + _logger.LogTrace("Converted coordinates: Source=({SourceEventX},{SourceEventY}) -> ({SourceAbsoluteX},{SourceAbsoluteY}), Target=({TargetX},{TargetY}) -> ({TargetAbsoluteX},{TargetAbsoluteY}). VirtualScreen={SmCxVirtualScreen}x{SmCyVirtualScreen}", sourceEventX, sourceEventY, sourceAbsoluteX, @@ -329,8 +333,8 @@ private async Task RunMouseEventProcessingLoopAsync( targetY, targetAbsoluteX, targetAbsoluteY, - _smCxScreen, - _smCyScreen); + _smCxVirtualScreen, + _smCyVirtualScreen); var inputMoveToTarget = CreateMoveInput(targetAbsoluteX, targetAbsoluteY); var inputScrollTarget = CreateScrollInput(buffer.MouseMessageId, targetAbsoluteX, targetAbsoluteY, delta); @@ -518,8 +522,15 @@ private void Start() { _logger.LogInformation("Starting scroll sync between \"{SourceWindow}\" and \"{TargetWindow}\"", Source.DisplayName, Target.DisplayName); - _smCxScreen = PInvoke.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CXSCREEN); - _smCyScreen = PInvoke.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CYSCREEN); + _smXVirtualScreen = PInvoke.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_XVIRTUALSCREEN); + _smYVirtualScreen = PInvoke.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_YVIRTUALSCREEN); + _smCxVirtualScreen = PInvoke.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CXVIRTUALSCREEN); + _smCyVirtualScreen = PInvoke.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CYVIRTUALSCREEN); + _logger.LogDebug("Virtual screen: offset=({XOffset},{YOffset}), size={Width}x{Height}", + _smXVirtualScreen, + _smYVirtualScreen, + _smCxVirtualScreen, + _smCyVirtualScreen); AppState = AppState.Running; }