Merge pull request #302 from Frassle/mouse
[Win32] Fix spurious mouse enter and leave messages
This commit is contained in:
commit
0013b91f65
1 changed files with 81 additions and 26 deletions
|
@ -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_capture_count = 0;
|
||||||
int mouse_last_timestamp = 0;
|
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.
|
||||||
|
@ -384,6 +385,14 @@ namespace OpenTK.Platform.Windows
|
||||||
return null;
|
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)
|
void HandleChar(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
|
@ -400,12 +409,40 @@ 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(
|
||||||
|
(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
|
unsafe
|
||||||
{
|
{
|
||||||
Point point = new Point(
|
|
||||||
(short)((uint)lParam.ToInt32() & 0x0000FFFF),
|
|
||||||
(short)(((uint)lParam.ToInt32() & 0xFFFF0000) >> 16));
|
|
||||||
|
|
||||||
// GetMouseMovePointsEx works with screen coordinates
|
// GetMouseMovePointsEx works with screen coordinates
|
||||||
Point screenPoint = point;
|
Point screenPoint = point;
|
||||||
Functions.ClientToScreen(handle, ref screenPoint);
|
Functions.ClientToScreen(handle, ref screenPoint);
|
||||||
|
@ -479,24 +516,18 @@ namespace OpenTK.Platform.Windows
|
||||||
}
|
}
|
||||||
mouse_last_timestamp = timestamp;
|
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)
|
void HandleMouseLeave(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||||
{
|
{
|
||||||
mouse_outside_window = true;
|
// If the mouse is captured we get spurious MOUSELEAVE events.
|
||||||
// Mouse tracking is disabled automatically by the OS
|
// So ignore WM_MOUSELEAVE if capture count != 0.
|
||||||
|
if (mouse_capture_count == 0 )
|
||||||
OnMouseLeave(EventArgs.Empty);
|
{
|
||||||
|
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)
|
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)
|
void HandleLButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||||
{
|
{
|
||||||
Functions.SetCapture(window.Handle);
|
SetCapture();
|
||||||
OnMouseDown(MouseButton.Left);
|
OnMouseDown(MouseButton.Left);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleMButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
void HandleMButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||||
{
|
{
|
||||||
Functions.SetCapture(window.Handle);
|
SetCapture();
|
||||||
OnMouseDown(MouseButton.Middle);
|
OnMouseDown(MouseButton.Middle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleRButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
void HandleRButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||||
{
|
{
|
||||||
Functions.SetCapture(window.Handle);
|
SetCapture();
|
||||||
OnMouseDown(MouseButton.Right);
|
OnMouseDown(MouseButton.Right);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleXButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
void HandleXButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||||
{
|
{
|
||||||
Functions.SetCapture(window.Handle);
|
SetCapture();
|
||||||
MouseButton button =
|
MouseButton button =
|
||||||
((wParam.ToInt32() & 0xFFFF0000) >> 16) == 1 ?
|
((wParam.ToInt32() & 0xFFFF0000) >> 16) == 1 ?
|
||||||
MouseButton.Button1 : MouseButton.Button2;
|
MouseButton.Button1 : MouseButton.Button2;
|
||||||
|
@ -542,25 +573,25 @@ namespace OpenTK.Platform.Windows
|
||||||
|
|
||||||
void HandleLButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
void HandleLButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||||
{
|
{
|
||||||
Functions.ReleaseCapture();
|
ReleaseCapture();
|
||||||
OnMouseUp(MouseButton.Left);
|
OnMouseUp(MouseButton.Left);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleMButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
void HandleMButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||||
{
|
{
|
||||||
Functions.ReleaseCapture();
|
ReleaseCapture();
|
||||||
OnMouseUp(MouseButton.Middle);
|
OnMouseUp(MouseButton.Middle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleRButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
void HandleRButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||||
{
|
{
|
||||||
Functions.ReleaseCapture();
|
ReleaseCapture();
|
||||||
OnMouseUp(MouseButton.Right);
|
OnMouseUp(MouseButton.Right);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleXButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
void HandleXButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||||
{
|
{
|
||||||
Functions.ReleaseCapture();
|
ReleaseCapture();
|
||||||
MouseButton button =
|
MouseButton button =
|
||||||
((wParam.ToInt32() & 0xFFFF0000) >> 16) == 1 ?
|
((wParam.ToInt32() & 0xFFFF0000) >> 16) == 1 ?
|
||||||
MouseButton.Button1 : MouseButton.Button2;
|
MouseButton.Button1 : MouseButton.Button2;
|
||||||
|
@ -694,6 +725,10 @@ namespace OpenTK.Platform.Windows
|
||||||
result = HandleSetCursor(handle, message, wParam, lParam);
|
result = HandleSetCursor(handle, message, wParam, lParam);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WindowMessage.CAPTURECHANGED:
|
||||||
|
HandleCaptureChanged(handle, message, wParam, lParam);
|
||||||
|
break;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Input events
|
#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()
|
private void EnableMouseTracking()
|
||||||
{
|
{
|
||||||
TrackMouseEventStructure me = new TrackMouseEventStructure();
|
TrackMouseEventStructure me = new TrackMouseEventStructure();
|
||||||
|
|
Loading…
Reference in a new issue