Skip to content

Commit

Permalink
Fix mouse buttons always getting reset when cursor leaves the window
Browse files Browse the repository at this point in the history
  • Loading branch information
UnknownShadow200 committed Jun 4, 2018
1 parent 0dfbeab commit 918b204
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 99 deletions.
21 changes: 0 additions & 21 deletions OpenTK/Platform/Windows/API.cs
Expand Up @@ -152,9 +152,6 @@ internal static class API {

[DllImport("user32.dll"), SuppressUnmanagedCodeSecurity]
public static extern IntPtr LoadCursor(IntPtr hInstance, IntPtr lpCursorName);

[DllImport("user32.dll", SetLastError = true), SuppressUnmanagedCodeSecurity]
public static extern bool TrackMouseEvent(ref TrackMouseEventStructure lpEventTrack);

[DllImport("user32.dll", SetLastError = true), SuppressUnmanagedCodeSecurity]
internal static extern bool GetCursorPos(ref POINT point);
Expand Down Expand Up @@ -417,15 +414,6 @@ internal struct Win32Rectangle {
}
}

struct TrackMouseEventStructure {
public int Size;
public TrackMouseEventFlags Flags;
public IntPtr TrackWindowHandle;
public uint HoverTime;

public static readonly int SizeInBytes = Marshal.SizeOf(typeof(TrackMouseEventStructure));
}

enum GWL {
WNDPROC = (-4),
IntPtr = (-6),
Expand Down Expand Up @@ -721,15 +709,6 @@ internal enum MapVirtualKeyType {
ScanCodeToVirtualKeyExtended = 3,
VirtualKeyToScanCodeExtended = 4,
}

[Flags]
enum TrackMouseEventFlags : uint {
HOVER = 0x00000001,
LEAVE = 0x00000002,
NONCLIENT = 0x00000010,
QUERY = 0x40000000,
CANCEL = 0x80000000,
}

internal delegate IntPtr WindowProcedure(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam);

Expand Down
47 changes: 11 additions & 36 deletions OpenTK/Platform/Windows/WinGLNative.cs
Expand Up @@ -49,7 +49,6 @@ internal sealed class WinGLNative : INativeWindow
WinWindowInfo window;
WindowState windowState = WindowState.Normal;
bool focused;
bool mouse_outside_window = true;
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.

Expand Down Expand Up @@ -170,31 +169,18 @@ internal sealed class WinGLNative : INativeWindow
break;

case WindowMessage.MOUSEMOVE:
// set before position change, in case mouse buttons changed when outside window
uint mouse_flags = (uint)wParam.ToInt64();
mouse[MouseButton.Left] = (mouse_flags & 0x01) != 0;
mouse[MouseButton.Right] = (mouse_flags & 0x02) != 0;
mouse[MouseButton.Middle] = (mouse_flags & 0x10) != 0;
// TODO: do we need to set XBUTTON1 / XBUTTON 2 here

uint mouse_xy = (uint)lParam.ToInt32();
Point point = new Point(
(short)((uint)lParam.ToInt32() & 0x0000FFFF),
(short)(((uint)lParam.ToInt32() & 0xFFFF0000) >> 16));
mouse.Position = point;

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();

if (MouseEnter != null)
MouseEnter(this, EventArgs.Empty);
}
break;

case WindowMessage.MOUSELEAVE:
mouse_outside_window = true;
// Mouse tracking is disabled automatically by the OS

if (MouseLeave != null)
MouseLeave(this, EventArgs.Empty);
// Set all mouse buttons to off when user leaves window, prevents them being stuck down.
for( MouseButton btn = 0; btn < MouseButton.LastButton; btn++ )
mouse[btn] = false;
(short)(mouse_xy & 0x0000FFFF),
(short)((mouse_xy & 0xFFFF0000) >> 16));
mouse.Position = point;
break;

case WindowMessage.MOUSEWHEEL:
Expand Down Expand Up @@ -355,17 +341,6 @@ internal sealed class WinGLNative : INativeWindow
return API.DefWindowProc(handle, message, wParam, lParam);
}

private void EnableMouseTracking() {
TrackMouseEventStructure me = new TrackMouseEventStructure();
me.Size = TrackMouseEventStructure.SizeInBytes;
me.TrackWindowHandle = window.handle;
me.Flags = TrackMouseEventFlags.LEAVE;

if (!API.TrackMouseEvent(ref me))
Debug.Print("[Warning] Failed to enable mouse tracking, error: {0}.",
Marshal.GetLastWin32Error());
}

IntPtr CreateWindow(int x, int y, int width, int height, string title, DisplayDevice device) {
// Use win32 to create the native window.
// Keep in mind that some construction code runs in the WM_CREATE message handler.
Expand Down
10 changes: 0 additions & 10 deletions OpenTK/Platform/X11/X11GLNative.cs
Expand Up @@ -396,16 +396,6 @@ internal sealed class X11GLNative : INativeWindow, IDisposable {
FocusedChanged(this, EventArgs.Empty);
} break;

case XEventName.LeaveNotify:
if (MouseLeave != null)
MouseLeave(this, EventArgs.Empty);
break;

case XEventName.EnterNotify:
if (MouseEnter != null)
MouseEnter(this, EventArgs.Empty);
break;

case XEventName.MappingNotify:
// 0 == MappingModifier, 1 == MappingKeyboard
if (e.MappingEvent.request == 0 || e.MappingEvent.request == 1) {
Expand Down
2 changes: 0 additions & 2 deletions src/Client/Event.h
Expand Up @@ -119,8 +119,6 @@ Event_Void WindowEvents_Closed; /* Window has closed. */
Event_Void WindowEvents_VisibilityChanged; /* Visibility of the window changes. */
Event_Void WindowEvents_FocusChanged; /* Focus of the window changes. */
Event_Void WindowEvents_WindowStateChanged; /* WindowState of the window changes. */
Event_Void WindowEvents_MouseLeave; /* Mouse cursor leaves window bounds. */
Event_Void WindowEvents_MouseEnter; /* Mouse cursor re-enters window bounds. */

Event_Int KeyEvents_Press; /* Raised when a character is typed. Arg is a character. */
Event_Int KeyEvents_Down; /* Raised when a key is pressed. Arg is a member of Key enumeration. */
Expand Down
36 changes: 6 additions & 30 deletions src/Client/WinWindow.c
Expand Up @@ -21,7 +21,6 @@ HWND win_Handle;
HDC win_DC;
UInt8 win_State = WINDOW_STATE_NORMAL;
bool win_Exists, win_Focused;
bool mouse_outside_window = true;
bool invisible_since_creation; // Set by WindowsMessage.CREATE and consumed by Visible = true (calls BringWindowToFront).
Int32 suppress_resize; // Used in WindowBorder and WindowState in order to avoid rapid, consecutive resize events.

Expand Down Expand Up @@ -97,17 +96,6 @@ static void Window_SetHiddenBorder(bool hidden) {
suppress_resize--;
}

static void Window_EnableMouseTracking(void) {
TRACKMOUSEEVENT me = { 0 };
me.cbSize = sizeof(TRACKMOUSEEVENT);
me.hwndTrack = win_Handle;
me.dwFlags = TME_LEAVE;

if (!TrackMouseEvent(&me)) {
ErrorHandler_FailWithCode(GetLastError(), "Enabling mouse tracking");
}
}

static Key Window_MapKey(WPARAM key) {
if (key >= VK_F1 && key <= VK_F24) {
return Key_F1 + (key - VK_F1);
Expand Down Expand Up @@ -270,27 +258,15 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara
break;

case WM_MOUSEMOVE:
/* set before position change, in case mouse buttons changed when outside window */
Mouse_SetPressed(MouseButton_Left, wParam & 0x01);
Mouse_SetPressed(MouseButton_Right, wParam & 0x02);
Mouse_SetPressed(MouseButton_Middle, wParam & 0x10);
/* TODO: do we need to set XBUTTON1 / XBUTTON 2 here */

mouse_x = LOWORD(lParam);
mouse_y = HIWORD(lParam);
Mouse_SetPosition(mouse_x, mouse_y);

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;
Window_EnableMouseTracking();
Event_RaiseVoid(&WindowEvents_MouseEnter);
}
break;

case WM_MOUSELEAVE:
mouse_outside_window = true;
/* Mouse tracking is disabled automatically by the OS */
Event_RaiseVoid(&WindowEvents_MouseLeave);

/* Set all mouse buttons to off when user leaves window, prevents them being stuck down. */
for (btn = 0; btn < MouseButton_Count; btn++) {
Mouse_SetPressed(btn, false);
}
break;

case WM_MOUSEWHEEL:
Expand Down

0 comments on commit 918b204

Please sign in to comment.