mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-07-09 08:00:40 +00:00
Use GetMouseMovePointsEx to smooth mouse input.
Uses GetMouseMovePointsEx to get mouse move history so mouse events aren't dropped even with low framerates. Fixes #76.
This commit is contained in:
parent
2a97192ef8
commit
095d3f26c0
|
@ -111,6 +111,13 @@ namespace OpenTK.Platform.Windows
|
||||||
|
|
||||||
internal static class Functions
|
internal static class Functions
|
||||||
{
|
{
|
||||||
|
#region GetLastError
|
||||||
|
|
||||||
|
[DllImport("Kernel32.dll")]
|
||||||
|
internal static extern uint GetLastError();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Window functions
|
#region Window functions
|
||||||
|
|
||||||
#region SetWindowPos
|
#region SetWindowPos
|
||||||
|
@ -371,6 +378,21 @@ namespace OpenTK.Platform.Windows
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region GetMessageTime
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the message time for the last message retrieved by the
|
||||||
|
/// GetMessage function. The time is a long integer that specifies the
|
||||||
|
/// elapsed time, in milliseconds, from the time the system was started
|
||||||
|
/// to the time the message was created (that is, placed in the thread's
|
||||||
|
/// message queue).
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The return value specifies the message time.</returns>
|
||||||
|
[DllImport("User32.dll")]
|
||||||
|
internal static extern int GetMessageTime();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region SendMessage
|
#region SendMessage
|
||||||
|
|
||||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||||
|
@ -1004,6 +1026,30 @@ namespace OpenTK.Platform.Windows
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
public static extern bool SetCursorPos(int X, int Y);
|
public static extern bool SetCursorPos(int X, int Y);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a history of up to 64 previous coordinates of the mouse or pen.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cbSize">The size, in bytes, of the MouseMovePoint structure.</param>
|
||||||
|
/// <param name="pointsIn">
|
||||||
|
/// A pointer to a MOUSEMOVEPOINT structure containing valid mouse
|
||||||
|
/// coordinates (in screen coordinates). It may also contain a time
|
||||||
|
/// stamp.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="pointsBufferOut">
|
||||||
|
/// A pointer to a buffer that will receive the points. It should be at
|
||||||
|
/// least cbSize * nBufPoints in size.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="nBufPoints">The number of points to be retrieved.</param>
|
||||||
|
/// <param name="resolution">
|
||||||
|
/// The resolution desired. This parameter can GMMP_USE_DISPLAY_POINTS
|
||||||
|
/// or GMMP_USE_HIGH_RESOLUTION_POINTS.
|
||||||
|
/// </param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[DllImport("user32", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)]
|
||||||
|
unsafe internal static extern int GetMouseMovePointsEx(
|
||||||
|
uint cbSize, MouseMovePoint* pointsIn,
|
||||||
|
MouseMovePoint* pointsBufferOut, int nBufPoints, uint resolution);
|
||||||
|
|
||||||
#region Async input
|
#region Async input
|
||||||
|
|
||||||
#region GetCursorPos
|
#region GetCursorPos
|
||||||
|
@ -1633,6 +1679,19 @@ namespace OpenTK.Platform.Windows
|
||||||
internal static readonly IntPtr MESSAGE_ONLY = new IntPtr(-3);
|
internal static readonly IntPtr MESSAGE_ONLY = new IntPtr(-3);
|
||||||
|
|
||||||
internal static readonly IntPtr HKEY_LOCAL_MACHINE = new IntPtr(unchecked((int)0x80000002));
|
internal static readonly IntPtr HKEY_LOCAL_MACHINE = new IntPtr(unchecked((int)0x80000002));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the points using the display resolution.
|
||||||
|
/// </summary>
|
||||||
|
internal const int GMMP_USE_DISPLAY_POINTS = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves high resolution points. Points can range from zero to
|
||||||
|
/// 65,535 (0xFFFF) in both x and y coordinates. This is the resolution
|
||||||
|
/// provided by absolute coordinate pointing devices such as drawing
|
||||||
|
/// tablets.
|
||||||
|
/// </summary>
|
||||||
|
internal const int GMMP_USE_HIGH_RESOLUTION_POINTS = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -2917,6 +2976,36 @@ namespace OpenTK.Platform.Windows
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region MouseMovePoint
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains information about the mouse's location in screen coordinates.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct MouseMovePoint
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The x-coordinate of the mouse.
|
||||||
|
/// </summary>
|
||||||
|
public int X;
|
||||||
|
/// <summary>
|
||||||
|
/// The y-coordinate of the mouse.
|
||||||
|
/// </summary>
|
||||||
|
public int Y;
|
||||||
|
/// <summary>
|
||||||
|
/// The time stamp of the mouse coordinate.
|
||||||
|
/// </summary>
|
||||||
|
public int Time;
|
||||||
|
/// <summary>
|
||||||
|
/// Additional information associated with this coordinate.
|
||||||
|
/// </summary>
|
||||||
|
public IntPtr ExtraInfo;
|
||||||
|
|
||||||
|
public static readonly int SizeInBytes = Marshal.SizeOf(default(MouseMovePoint));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region --- Enums ---
|
#region --- Enums ---
|
||||||
|
|
|
@ -70,6 +70,7 @@ namespace OpenTK.Platform.Windows
|
||||||
bool borderless_maximized_window_state = false; // Hack to get maximized mode with hidden border (not normally possible).
|
bool borderless_maximized_window_state = false; // Hack to get maximized mode with hidden border (not normally possible).
|
||||||
bool focused;
|
bool focused;
|
||||||
bool mouse_outside_window = true;
|
bool mouse_outside_window = true;
|
||||||
|
int mouse_last_timestamp = 0;
|
||||||
bool invisible_since_creation; // Set by WindowsMessage.CREATE and consumed by Visible = true (calls BringWindowToFront).
|
bool invisible_since_creation; // Set by WindowsMessage.CREATE and consumed by Visible = true (calls BringWindowToFront).
|
||||||
int suppress_resize; // Used in WindowBorder and WindowState in order to avoid rapid, consecutive resize events.
|
int suppress_resize; // Used in WindowBorder and WindowState in order to avoid rapid, consecutive resize events.
|
||||||
bool is_in_modal_loop; // set to true whenever we enter the modal resize/move event loop
|
bool is_in_modal_loop; // set to true whenever we enter the modal resize/move event loop
|
||||||
|
@ -403,10 +404,86 @@ namespace OpenTK.Platform.Windows
|
||||||
|
|
||||||
void HandleMouseMove(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
void HandleMouseMove(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||||
{
|
{
|
||||||
Point point = new Point(
|
unsafe
|
||||||
(short)((uint)lParam.ToInt32() & 0x0000FFFF),
|
{
|
||||||
(short)(((uint)lParam.ToInt32() & 0xFFFF0000) >> 16));
|
Point point = new Point(
|
||||||
mouse.Position = point;
|
(short)((uint)lParam.ToInt32() & 0x0000FFFF),
|
||||||
|
(short)(((uint)lParam.ToInt32() & 0xFFFF0000) >> 16));
|
||||||
|
|
||||||
|
// GetMouseMovePointsEx works with screen coordinates
|
||||||
|
Point screenPoint = point;
|
||||||
|
Functions.ClientToScreen(handle, ref screenPoint);
|
||||||
|
int timestamp = Functions.GetMessageTime();
|
||||||
|
|
||||||
|
// & 0xFFFF to handle multiple monitors http://support.microsoft.com/kb/269743
|
||||||
|
MouseMovePoint movePoint = new MouseMovePoint()
|
||||||
|
{
|
||||||
|
X = screenPoint.X & 0xFFFF,
|
||||||
|
Y = screenPoint.Y & 0xFFFF,
|
||||||
|
Time = timestamp,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Max points GetMouseMovePointsEx can return is 64.
|
||||||
|
int numPoints = 64;
|
||||||
|
|
||||||
|
MouseMovePoint* movePoints = stackalloc MouseMovePoint[numPoints];
|
||||||
|
|
||||||
|
// GetMouseMovePointsEx fills in movePoints so that the most
|
||||||
|
// recent events are at low indices in the array.
|
||||||
|
int points = Functions.GetMouseMovePointsEx(
|
||||||
|
(uint)MouseMovePoint.SizeInBytes,
|
||||||
|
&movePoint, movePoints, numPoints,
|
||||||
|
Constants.GMMP_USE_DISPLAY_POINTS);
|
||||||
|
|
||||||
|
uint lastError = Functions.GetLastError();
|
||||||
|
|
||||||
|
// No points returned or search point not found
|
||||||
|
if (points == 0 || (points == -1 && lastError == 1171))
|
||||||
|
{
|
||||||
|
// Just use the mouse move position
|
||||||
|
mouse.Position = point;
|
||||||
|
}
|
||||||
|
else if (points == -1)
|
||||||
|
{
|
||||||
|
throw new System.ComponentModel.Win32Exception((int)lastError);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Exclude the current position.
|
||||||
|
Point currentScreenPosition = new Point(mouse.X, mouse.Y);
|
||||||
|
Functions.ClientToScreen(handle, ref currentScreenPosition);
|
||||||
|
|
||||||
|
// Find the first move point we've already seen.
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0; i < points; ++i)
|
||||||
|
{
|
||||||
|
if (movePoints[i].Time < mouse_last_timestamp)
|
||||||
|
break;
|
||||||
|
if (movePoints[i].Time == mouse_last_timestamp &&
|
||||||
|
movePoints[i].X == currentScreenPosition.X &&
|
||||||
|
movePoints[i].Y == currentScreenPosition.Y)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now move the mouse to each point before the one just found.
|
||||||
|
while (--i >= 0)
|
||||||
|
{
|
||||||
|
Point position = new Point(movePoints[i].X, movePoints[i].Y);
|
||||||
|
// Handle multiple monitors http://support.microsoft.com/kb/269743
|
||||||
|
if (position.X > 32767)
|
||||||
|
{
|
||||||
|
position.X -= 65536;
|
||||||
|
}
|
||||||
|
if (position.Y > 32767)
|
||||||
|
{
|
||||||
|
position.Y -= 65536;
|
||||||
|
}
|
||||||
|
Functions.ScreenToClient(handle, ref position);
|
||||||
|
mouse.Position = position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mouse_last_timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
if (mouse_outside_window)
|
if (mouse_outside_window)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue