Browse Source

Use a different workaround (time-based) for GLFW Mac bug where setting GLFW_CURSOR_DISABLED creates a large mouse delta in a few frames.

tags/v2.6.4
Andrew Belt 3 weeks ago
parent
commit
40e529f393
1 changed files with 12 additions and 24 deletions
  1. +12
    -24
      src/window/Window.cpp

+ 12
- 24
src/window/Window.cpp View File

@@ -98,7 +98,7 @@ struct Window::Internal {
int lastWindowHeight = 0; int lastWindowHeight = 0;


int frame = 0; int frame = 0;
bool ignoreNextMouseDelta = false;
double ignoreMouseDeltaUntil = -INFINITY;
double monitorRefreshRate = 0.0; double monitorRefreshRate = 0.0;
double frameTime = NAN; double frameTime = NAN;
double lastFrameDuration = NAN; double lastFrameDuration = NAN;
@@ -167,28 +167,15 @@ static void cursorPosCallback(GLFWwindow* win, double xpos, double ypos) {
math::Vec mousePos = math::Vec(xpos, ypos).div(APP->window->pixelRatio / APP->window->windowRatio).round(); math::Vec mousePos = math::Vec(xpos, ypos).div(APP->window->pixelRatio / APP->window->windowRatio).round();
math::Vec mouseDelta = mousePos.minus(APP->window->internal->lastMousePos); math::Vec mouseDelta = mousePos.minus(APP->window->internal->lastMousePos);


// if (glfwGetInputMode(win, GLFW_CURSOR) != GLFW_CURSOR_NORMAL && std::fabs(mouseDelta.y) > 20.0) {
// DEBUG("%d (%f, %f) (%f, %f)", APP->window->internal->frame, VEC_ARGS(mousePos), VEC_ARGS(mouseDelta));
// }

// Workaround for GLFW warping mouse to a different position when the cursor is locked or unlocked. // Workaround for GLFW warping mouse to a different position when the cursor is locked or unlocked.
if (APP->window->internal->ignoreNextMouseDelta) {
APP->window->internal->ignoreNextMouseDelta = false;
if (APP->window->internal->ignoreMouseDeltaUntil > APP->window->internal->frameTime) {
mouseDelta = math::Vec(); mouseDelta = math::Vec();
} }


int cursorMode = glfwGetInputMode(win, GLFW_CURSOR);
(void) cursorMode;

#if defined ARCH_MAC
// Workaround for Mac. We can't use GLFW_CURSOR_DISABLED because it's buggy, so implement it on our own.
// This is not an ideal implementation. For example, if the user drags off the screen, the new mouse position will be clamped.
if (cursorMode == GLFW_CURSOR_HIDDEN) {
// CGSetLocalEventsSuppressionInterval(0.0);
glfwSetCursorPos(win, APP->window->internal->lastMousePos.x, APP->window->internal->lastMousePos.y);
CGAssociateMouseAndMouseCursorPosition(true);
mousePos = APP->window->internal->lastMousePos;
}
// Because sometimes the cursor turns into an arrow when its position is on the boundary of the window
glfwSetCursor(win, NULL);
#endif

APP->window->internal->lastMousePos = mousePos; APP->window->internal->lastMousePos = mousePos;


APP->event->handleHover(mousePos, mouseDelta); APP->event->handleHover(mousePos, mouseDelta);
@@ -647,12 +634,14 @@ void Window::cursorLock() {
if (!settings::allowCursorLock) if (!settings::allowCursorLock)
return; return;


#if defined ARCH_MAC
glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
#else
glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

// Due to a bug in GLFW, setting GLFW_CURSOR_DISABLED causes a spurious mouse position delta after a few frames.
// https://github.com/glfw/glfw/issues/2523
// Emperically, this seems to be up to 3-6 frames at 60 Hz but in fewer frames at lower framerates.
#if defined ARCH_MAC
internal->ignoreMouseDeltaUntil = internal->frameTime + 0.09;
#endif #endif
internal->ignoreNextMouseDelta = true;
} }




@@ -661,7 +650,6 @@ void Window::cursorUnlock() {
return; return;


glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_NORMAL); glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
internal->ignoreNextMouseDelta = true;
} }






Loading…
Cancel
Save