Skip to content

Commit

Permalink
Fix "CursorVisible bugs"
Browse files Browse the repository at this point in the history
When we enter the modal resize loop on Windows with ClipCursor set, we
cause a feedback loop where every resize causes the cursor to move and
every move causes a new resize. To fix this, we need to ungrab the
cursor when we are enter the modal loop.
  • Loading branch information
thefiddler committed Nov 22, 2013
1 parent 24aa789 commit e2404d2
Showing 1 changed file with 23 additions and 8 deletions.
31 changes: 23 additions & 8 deletions Source/OpenTK/Platform/Windows/WinGLNative.cs
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ internal sealed class WinGLNative : INativeWindow, IInputDriver
bool mouse_outside_window = true; bool mouse_outside_window = true;
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


Rectangle Rectangle
bounds = new Rectangle(), bounds = new Rectangle(),
Expand Down Expand Up @@ -262,14 +263,23 @@ IntPtr WindowProcedure(IntPtr handle, WindowMessage message, IntPtr wParam, IntP
// Entering the modal size/move loop: we don't want rendering to // Entering the modal size/move loop: we don't want rendering to
// stop during this time, so we register a timer callback to continue // stop during this time, so we register a timer callback to continue
// processing from time to time. // processing from time to time.
is_in_modal_loop = true;
StartTimer(handle); StartTimer(handle);

if (!CursorVisible)
UngrabCursor();
break; break;


case WindowMessage.EXITMENULOOP: case WindowMessage.EXITMENULOOP:
case WindowMessage.EXITSIZEMOVE: case WindowMessage.EXITSIZEMOVE:
// ExitingmModal size/move loop: the timer callback is no longer // Exiting from Modal size/move loop: the timer callback is no longer
// necessary. // necessary.
is_in_modal_loop = false;
StopTimer(handle); StopTimer(handle);

// Ensure cursor remains grabbed
if (!CursorVisible)
GrabCursor();
break; break;


case WindowMessage.ERASEBKGND: case WindowMessage.ERASEBKGND:
Expand Down Expand Up @@ -306,9 +316,14 @@ IntPtr WindowProcedure(IntPtr handle, WindowMessage message, IntPtr wParam, IntP
Resize(this, EventArgs.Empty); Resize(this, EventArgs.Empty);
} }


// Ensure cursor remains grabbed if (!is_in_modal_loop)
if (!CursorVisible) {
GrabCursor(); // If we are in a modal resize/move loop, cursor grabbing is
// handled inside [ENTER|EXIT]SIZEMOVE case above.
// If not, then we have to handle cursor grabbing here.
if (!CursorVisible)
GrabCursor();
}
} }
} }
break; break;
Expand Down Expand Up @@ -351,11 +366,11 @@ IntPtr WindowProcedure(IntPtr handle, WindowMessage message, IntPtr wParam, IntP
{ {
windowState = new_state; windowState = new_state;
WindowStateChanged(this, EventArgs.Empty); WindowStateChanged(this, EventArgs.Empty);
}


// Ensure cursor remains grabbed // Ensure cursor remains grabbed
if (!CursorVisible) if (!CursorVisible)
GrabCursor(); GrabCursor();
}


break; break;


Expand Down

0 comments on commit e2404d2

Please sign in to comment.