Search code examples
javalwjglglfw

glfwSetCursorPos() not working on windows


So I've wrote a window in java using the java bindings of GLFW provided by lwjgl. It works fine on linux but for some reason some methods do not work on windows.

I've registered a key callback that works fine on both linux and windows, but a char callback for example only works on linux.

Another problem I'm having, which breaks my camera rotation because I can't center the mouse to calculate the offset from there, is that setCursorPos() is not working.

This is how I create my window:

    public void init(int selectedMonitor, int glMajor, int glMinor, int windowHints) {
        if (this.initialized) return;
        GLFWErrorCallback.createPrint(System.err).set();

        if (!GLFW.glfwInit())
            throw new WindowCreationException("Unable to initialize GLFW.");

        // Configure window hints
        GLFW.glfwDefaultWindowHints();
        GLFW.glfwWindowHint(GLFW.GLFW_RESIZABLE, (windowHints & 1));
        GLFW.glfwWindowHint(GLFW.GLFW_FOCUSED, (windowHints >> 1) & 1);
        GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, (windowHints >> 2) & 1);
        GLFW.glfwWindowHint(GLFW.GLFW_DECORATED, (windowHints >> 3) & 1);
        GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, glMajor);
        GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, glMinor);
        GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);
        GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, (windowHints >> 7));

        // Set video mode
        PointerBuffer monitors = GLFW.glfwGetMonitors();
        if (monitors == null)
            throw new WindowCreationException("Could not create window, there are no monitors.");

        if (selectedMonitor >= monitors.capacity() || selectedMonitor < 0) {
            this.currentMonitor = GLFW.glfwGetPrimaryMonitor();
        } else {
            this.currentMonitor = monitors.get(selectedMonitor);
        }
        this.vidMode = GLFW.glfwGetVideoMode(this.currentMonitor);

        // Create window handle
        this.windowHandle = GLFW.glfwCreateWindow(this.width, this.height, this.title, this.isFullscreen ? this.currentMonitor : 0L, 0L);
        if (this.windowHandle == 0L)
            throw new RuntimeException("Failed to create GLFW Window.");

        // Center window if configured
        if (((windowHints >> 4) & 1) == 1) this.centerWindow();

        // Set key callbacks
        this.addKeyCallback((window, keyCode, scanCode, action, mods) -> Key.byKeyCode(keyCode).update(action));
        this.addMouseButtonCallback((window, keyCode, action, mods) -> Key.byKeyCode(keyCode).update(action));

        glfwSetKeyCallback(this.windowHandle, (window, keyCode, scanCode, action, mods) -> {
            for (GLFWKeyCallbackI callback : this.keyCallbacks) callback.invoke(window, keyCode, scanCode, action, mods);
        });

        glfwSetCharCallback(this.windowHandle, (window, unicode) -> {
            for (GLFWCharCallbackI callback : this.charCallbacks) callback.invoke(window, unicode);
        });

        glfwSetMouseButtonCallback(this.windowHandle, (window, keyCode, action, mods) -> {
            for (GLFWMouseButtonCallbackI callback : this.mouseButtonCallbacks) callback.invoke(window, keyCode, action, mods);
        });

        glfwSetScrollCallback(this.windowHandle, (window, xOffset, yOffset) -> {
            for (GLFWScrollCallbackI callback : this.scrollCallbacks) callback.invoke(window, xOffset, yOffset);
        });

        // Make the OpenGL context current
        GLFW.glfwMakeContextCurrent(this.windowHandle);
        if (((windowHints >> 5) & 1) == 1) GLFW.glfwSwapInterval(1);

        // Configure cursor
        this.mouseX = MemoryUtil.memAllocDouble(1);
        this.mouseY = MemoryUtil.memAllocDouble(1);
        if (((windowHints >> 6) & 1) == 1) this.hideCursor(true);

        this.initialized = true;
    }

And when I execute this code:

GLFW.glfwSetCursorPos(this.windowHandle, 0, 0);
GLFW.glfwGetCursorPos(this.windowHandle, this.mouseX, this.mouseY);
System.out.println("Mouse Pos: " + this.mouseX.get(0) + ", " + this.mouseY.get(0));

The result differs between Windows and Linux.
Linux: Mouse Pos: 0, 0
Windows: Mouse Pos: 623.0, 367.0

I don't know why it's not working on windows, and it even seems to be completely unrelated to the lwjgl version, because I tried 3.1.6, 3.2.1, 3.2.2 and 3.2.3-SNAPSHOT, and it's the same for all those versions. So either the problem is me forgetting something when creating the window or windows broke something in some update, because months ago when I made a project with lwjgl 3.1.6 I'm 100% sure setCursorPos() was working on both linux and windows back then.


Solution

  • Okay, so I found the solution to the problem:

    For some reason, glfwSetCursorPos() must be called in the same thread the window was created in on windows and not on linux.

    This is kinda weird because it didn't cause a segmentation fault on windows, but calling the method from the same thread works for both windows and linux.