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.
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;
void HandleMouseMove(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
- unsafe
+ Point point = new Point(
+ (short)((uint)lParam.ToInt32() & 0x0000FFFF),
+ (short)(((uint)lParam.ToInt32() & 0xFFFF0000) >> 16));
+
+ if (mouse_capture_count > 0)
{
- Point point = new Point(
- (short)((uint)lParam.ToInt32() & 0x0000FFFF),
- (short)(((uint)lParam.ToInt32() & 0xFFFF0000) >> 16));
+ 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
+ {
// GetMouseMovePointsEx works with screen coordinates
Point screenPoint = point;
Functions.ClientToScreen(handle, ref screenPoint);
}
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)
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;
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;
result = HandleSetCursor(handle, message, wParam, lParam);
break;
+ case WindowMessage.CAPTURECHANGED:
+ HandleCaptureChanged(handle, message, wParam, lParam);
+ break;
+
#endregion
#region Input events
}
}
+ 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();