|
@@ -529,11 +529,17 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
|
|
*ypos = window->wl.cursorPosY;
|
|
|
}
|
|
|
|
|
|
+static GLFWbool isPointerLocked(_GLFWwindow* window);
|
|
|
+
|
|
|
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
|
|
|
{
|
|
|
- // A Wayland client can not set the cursor position
|
|
|
- _glfwInputError(GLFW_PLATFORM_ERROR,
|
|
|
- "Wayland: Cursor position setting not supported");
|
|
|
+ if (isPointerLocked(window))
|
|
|
+ {
|
|
|
+ zwp_locked_pointer_v1_set_cursor_position_hint(
|
|
|
+ window->wl.pointerLock.lockedPointer,
|
|
|
+ wl_fixed_from_double(x), wl_fixed_from_double(y));
|
|
|
+ wl_surface_commit(window->wl.surface);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
|
@@ -631,6 +637,103 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
|
|
wl_buffer_destroy(cursor->wl.buffer);
|
|
|
}
|
|
|
|
|
|
+static void handleRelativeMotion(void* data,
|
|
|
+ struct zwp_relative_pointer_v1* pointer,
|
|
|
+ uint32_t timeHi,
|
|
|
+ uint32_t timeLo,
|
|
|
+ wl_fixed_t dx,
|
|
|
+ wl_fixed_t dy,
|
|
|
+ wl_fixed_t dxUnaccel,
|
|
|
+ wl_fixed_t dyUnaccel)
|
|
|
+{
|
|
|
+ _GLFWwindow* window = data;
|
|
|
+
|
|
|
+ if (window->cursorMode != GLFW_CURSOR_DISABLED)
|
|
|
+ return;
|
|
|
+
|
|
|
+ _glfwInputCursorMotion(window,
|
|
|
+ wl_fixed_to_double(dxUnaccel),
|
|
|
+ wl_fixed_to_double(dyUnaccel));
|
|
|
+}
|
|
|
+
|
|
|
+static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
|
|
|
+ handleRelativeMotion
|
|
|
+};
|
|
|
+
|
|
|
+static void handleLocked(void* data,
|
|
|
+ struct zwp_locked_pointer_v1* lockedPointer)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+static void unlockPointer(_GLFWwindow* window)
|
|
|
+{
|
|
|
+ struct zwp_relative_pointer_v1* relativePointer =
|
|
|
+ window->wl.pointerLock.relativePointer;
|
|
|
+ struct zwp_locked_pointer_v1* lockedPointer =
|
|
|
+ window->wl.pointerLock.lockedPointer;
|
|
|
+
|
|
|
+ zwp_relative_pointer_v1_destroy(relativePointer);
|
|
|
+ zwp_locked_pointer_v1_destroy(lockedPointer);
|
|
|
+
|
|
|
+ window->wl.pointerLock.relativePointer = NULL;
|
|
|
+ window->wl.pointerLock.lockedPointer = NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static void lockPointer(_GLFWwindow* window);
|
|
|
+
|
|
|
+static void handleUnlocked(void* data,
|
|
|
+ struct zwp_locked_pointer_v1* lockedPointer)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+static const struct zwp_locked_pointer_v1_listener lockedPointerListener = {
|
|
|
+ handleLocked,
|
|
|
+ handleUnlocked
|
|
|
+};
|
|
|
+
|
|
|
+static void lockPointer(_GLFWwindow* window)
|
|
|
+{
|
|
|
+ struct zwp_relative_pointer_v1* relativePointer;
|
|
|
+ struct zwp_locked_pointer_v1* lockedPointer;
|
|
|
+
|
|
|
+ if (!_glfw.wl.relativePointerManager)
|
|
|
+ {
|
|
|
+ _glfwInputError(GLFW_PLATFORM_ERROR,
|
|
|
+ "Wayland: no relative pointer manager");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ relativePointer =
|
|
|
+ zwp_relative_pointer_manager_v1_get_relative_pointer(
|
|
|
+ _glfw.wl.relativePointerManager,
|
|
|
+ _glfw.wl.pointer);
|
|
|
+ zwp_relative_pointer_v1_add_listener(relativePointer,
|
|
|
+ &relativePointerListener,
|
|
|
+ window);
|
|
|
+
|
|
|
+ lockedPointer =
|
|
|
+ zwp_pointer_constraints_v1_lock_pointer(
|
|
|
+ _glfw.wl.pointerConstraints,
|
|
|
+ window->wl.surface,
|
|
|
+ _glfw.wl.pointer,
|
|
|
+ NULL,
|
|
|
+ ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
|
|
|
+ zwp_locked_pointer_v1_add_listener(lockedPointer,
|
|
|
+ &lockedPointerListener,
|
|
|
+ window);
|
|
|
+
|
|
|
+ window->wl.pointerLock.relativePointer = relativePointer;
|
|
|
+ window->wl.pointerLock.lockedPointer = lockedPointer;
|
|
|
+
|
|
|
+ wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
|
|
|
+ NULL, 0, 0);
|
|
|
+}
|
|
|
+
|
|
|
+static GLFWbool isPointerLocked(_GLFWwindow* window)
|
|
|
+{
|
|
|
+ return window->wl.pointerLock.lockedPointer != NULL;
|
|
|
+}
|
|
|
+
|
|
|
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
|
|
{
|
|
|
struct wl_buffer* buffer;
|
|
@@ -648,6 +751,10 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
|
|
if (window != _glfw.wl.pointerFocus)
|
|
|
return;
|
|
|
|
|
|
+ // Unlock possible pointer lock if no longer disabled.
|
|
|
+ if (window->cursorMode != GLFW_CURSOR_DISABLED && isPointerLocked(window))
|
|
|
+ unlockPointer(window);
|
|
|
+
|
|
|
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
|
|
{
|
|
|
if (cursor)
|
|
@@ -691,9 +798,15 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
|
|
wl_surface_commit(surface);
|
|
|
}
|
|
|
}
|
|
|
- else /* Cursor is hidden set cursor surface to NULL */
|
|
|
+ else if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
|
|
+ {
|
|
|
+ if (!isPointerLocked(window))
|
|
|
+ lockPointer(window);
|
|
|
+ }
|
|
|
+ else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
|
|
{
|
|
|
- wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial, NULL, 0, 0);
|
|
|
+ wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
|
|
|
+ NULL, 0, 0);
|
|
|
}
|
|
|
}
|
|
|
|