Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 23 additions & 12 deletions WinSyncScroll/ViewModels/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<INPUT>();

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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)
);
}

Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down