mirror of
https://github.com/Ryujinx/Opentk.git
synced 2024-12-23 07:15:28 +00:00
[Win32] Fix spurious mouse enter and leave messages
Mouse tracking and mouse capture didn't work well together. Mouse capture was also buggy in that it could release capture prematurely. Mouse capture is now counted and tracked better, multiple requests to set capture will only call SetCapture once. ReleaseCapture will only be called once the same number of releases have been made as sets. MW_MOUSELEAVE messages are now ignored if the mouse is captured. Mouse tracking is renabled when mouse capture is released. While the mouse is captured enter and leave events are genereated based on tracking of the mouse inside MouseMove. Fixes #301
This commit is contained in:
parent
616ac5a017
commit
a1cc67c70e
|
@ -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 focused;
|
||||
bool mouse_outside_window = true;
|
||||
int mouse_capture_count = 0;
|
||||
int mouse_last_timestamp = 0;
|
||||
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.
|
||||
|
@ -384,6 +385,14 @@ namespace OpenTK.Platform.Windows
|
|||
return null;
|
||||
}
|
||||
|
||||
private void HandleCaptureChanged(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
if (lParam != window.Handle)
|
||||
{
|
||||
mouse_capture_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleChar(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
char c;
|
||||
|
@ -400,12 +409,40 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
void HandleMouseMove(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Point point = new Point(
|
||||
(short)((uint)lParam.ToInt32() & 0x0000FFFF),
|
||||
(short)(((uint)lParam.ToInt32() & 0xFFFF0000) >> 16));
|
||||
|
||||
if (mouse_capture_count > 0)
|
||||
{
|
||||
bool mouse_was_outside_window = mouse_outside_window;
|
||||
mouse_outside_window = !ClientRectangle.Contains(point);
|
||||
|
||||
if (mouse_outside_window && !mouse_was_outside_window)
|
||||
{
|
||||
// Mouse leaving
|
||||
// If we have mouse capture we ignore WM_MOUSELEAVE events, so
|
||||
// have to manually call OnMouseLeave here.
|
||||
// Mouse tracking is disabled automatically by the OS
|
||||
OnMouseLeave(EventArgs.Empty);
|
||||
}
|
||||
else if (!mouse_outside_window && mouse_was_outside_window)
|
||||
{
|
||||
// Mouse entring
|
||||
OnMouseEnter(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
else if (/* !mouse_is_captured && */ mouse_outside_window)
|
||||
{
|
||||
// Once we receive a mouse move event, it means that the mouse has
|
||||
// re-entered the window.
|
||||
mouse_outside_window = false;
|
||||
EnableMouseTracking();
|
||||
OnMouseEnter(EventArgs.Empty);
|
||||
}
|
||||
|
||||
unsafe
|
||||
{
|
||||
Point point = new 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);
|
||||
|
@ -479,24 +516,18 @@ namespace OpenTK.Platform.Windows
|
|||
}
|
||||
mouse_last_timestamp = timestamp;
|
||||
}
|
||||
|
||||
if (mouse_outside_window)
|
||||
{
|
||||
// Once we receive a mouse move event, it means that the mouse has
|
||||
// re-entered the window.
|
||||
mouse_outside_window = false;
|
||||
EnableMouseTracking();
|
||||
|
||||
OnMouseEnter(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleMouseLeave(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
mouse_outside_window = true;
|
||||
// Mouse tracking is disabled automatically by the OS
|
||||
|
||||
OnMouseLeave(EventArgs.Empty);
|
||||
// If the mouse is captured we get spurious MOUSELEAVE events.
|
||||
// So ignore WM_MOUSELEAVE if capture count != 0.
|
||||
if (mouse_capture_count == 0 )
|
||||
{
|
||||
mouse_outside_window = true;
|
||||
// Mouse tracking is disabled automatically by the OS
|
||||
OnMouseLeave(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleMouseWheel(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
|
@ -515,25 +546,25 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
void HandleLButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.SetCapture(window.Handle);
|
||||
SetCapture();
|
||||
OnMouseDown(MouseButton.Left);
|
||||
}
|
||||
|
||||
void HandleMButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.SetCapture(window.Handle);
|
||||
SetCapture();
|
||||
OnMouseDown(MouseButton.Middle);
|
||||
}
|
||||
|
||||
void HandleRButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.SetCapture(window.Handle);
|
||||
SetCapture();
|
||||
OnMouseDown(MouseButton.Right);
|
||||
}
|
||||
|
||||
void HandleXButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.SetCapture(window.Handle);
|
||||
SetCapture();
|
||||
MouseButton button =
|
||||
((wParam.ToInt32() & 0xFFFF0000) >> 16) == 1 ?
|
||||
MouseButton.Button1 : MouseButton.Button2;
|
||||
|
@ -542,25 +573,25 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
void HandleLButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.ReleaseCapture();
|
||||
ReleaseCapture();
|
||||
OnMouseUp(MouseButton.Left);
|
||||
}
|
||||
|
||||
void HandleMButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.ReleaseCapture();
|
||||
ReleaseCapture();
|
||||
OnMouseUp(MouseButton.Middle);
|
||||
}
|
||||
|
||||
void HandleRButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.ReleaseCapture();
|
||||
ReleaseCapture();
|
||||
OnMouseUp(MouseButton.Right);
|
||||
}
|
||||
|
||||
void HandleXButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.ReleaseCapture();
|
||||
ReleaseCapture();
|
||||
MouseButton button =
|
||||
((wParam.ToInt32() & 0xFFFF0000) >> 16) == 1 ?
|
||||
MouseButton.Button1 : MouseButton.Button2;
|
||||
|
@ -694,6 +725,10 @@ namespace OpenTK.Platform.Windows
|
|||
result = HandleSetCursor(handle, message, wParam, lParam);
|
||||
break;
|
||||
|
||||
case WindowMessage.CAPTURECHANGED:
|
||||
HandleCaptureChanged(handle, message, wParam, lParam);
|
||||
break;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Input events
|
||||
|
@ -794,6 +829,26 @@ namespace OpenTK.Platform.Windows
|
|||
}
|
||||
}
|
||||
|
||||
private void SetCapture()
|
||||
{
|
||||
if (mouse_capture_count == 0)
|
||||
{
|
||||
Functions.SetCapture(window.Handle);
|
||||
}
|
||||
mouse_capture_count++;
|
||||
}
|
||||
|
||||
private void ReleaseCapture()
|
||||
{
|
||||
mouse_capture_count--;
|
||||
if (mouse_capture_count == 0)
|
||||
{
|
||||
Functions.ReleaseCapture();
|
||||
// Renable mouse tracking
|
||||
EnableMouseTracking();
|
||||
}
|
||||
}
|
||||
|
||||
private void EnableMouseTracking()
|
||||
{
|
||||
TrackMouseEventStructure me = new TrackMouseEventStructure();
|
||||
|
|
Loading…
Reference in a new issue