diff --git a/src/main/java/org/lwjglx/input/Mouse.java b/src/main/java/org/lwjglx/input/Mouse.java index dd4e799e..fed42708 100644 --- a/src/main/java/org/lwjglx/input/Mouse.java +++ b/src/main/java/org/lwjglx/input/Mouse.java @@ -53,6 +53,10 @@ public static void addMoveEvent(double mouseX, double mouseY) { ignoreNextMove--; return; } + float scale = Display.getPixelScaleFactor(); + // convert from screen-space coordinates to framebuffer coordinates + mouseX *= scale; + mouseY *= scale; dx += (int) mouseX - latestX; dy += Display.getHeight() - (int) mouseY - latestY; latestX = (int) mouseX; @@ -279,7 +283,13 @@ public static void setCursorPosition(int new_x, int new_y) { if (grabbed) { return; } - GLFW.glfwSetCursorPos(Display.getWindow(), new_x, new_y); + // convert back from framebuffer coordinates to screen-space coordinates + float inv_scale = 1.0f / Display.getPixelScaleFactor(); + new_x *= inv_scale; + new_y *= inv_scale; + GLFW.glfwSetCursorPos(Display.getWindow(), new_x * inv_scale, new_y * inv_scale); + // this might lose accuracy, since we just went from fb->screen and this will + // undo that change. Yay floating point numbers! addMoveEvent(new_x, new_y); } diff --git a/src/main/java/org/lwjglx/opengl/Display.java b/src/main/java/org/lwjglx/opengl/Display.java index a045c55e..ec96337d 100644 --- a/src/main/java/org/lwjglx/opengl/Display.java +++ b/src/main/java/org/lwjglx/opengl/Display.java @@ -195,9 +195,6 @@ public static void create(PixelFormat pixelFormat, ContextAttribs attribs, long glfwWindowHintString(GLFW_X11_CLASS_NAME, Config.X11_CLASS_NAME); glfwWindowHintString(GLFW_COCOA_FRAME_NAME, Config.COCOA_FRAME_NAME); - glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE); // request a non-hidpi framebuffer on Retina displays - // on MacOS - if (Config.WINDOW_CENTERED) { glfwWindowHint(GLFW_POSITION_X, (monitorWidth - mode.getWidth()) / 2); glfwWindowHint(GLFW_POSITION_Y, (monitorHeight - mode.getHeight()) / 2); @@ -607,19 +604,14 @@ public static int getY() { return displayY; } + // vanilla and forge both expect these to return the framebuffer width + // rather than the window width, and they both call glViewport with the + // result public static int getWidth() { - return displayWidth; - } - - public static int getHeight() { - return displayHeight; - } - - public static int getFramebufferWidth() { return displayFramebufferWidth; } - public static int getFramebufferHeight() { + public static int getHeight() { return displayFramebufferHeight; } @@ -892,10 +884,20 @@ public static float getPixelScaleFactor() { if (!isCreated()) { return 1.0f; } - float[] xScale = new float[1]; - float[] yScale = new float[1]; - glfwGetWindowContentScale(getWindow(), xScale, yScale); - return Math.max(xScale[0], yScale[0]); + int[] windowWidth = new int[1]; + int[] windowHeight = new int[1]; + int[] framebufferWidth = new int[1]; + int[] framebufferHeight = new int[1]; + float xScale, yScale; + // via technicality we actually have to divide the framebuffer + // size by the window size here, since glfwGetWindowContentScale + // returns a value not equal to 1 even on platforms where the + // framebuffer size and window size always map 1:1 + glfwGetWindowSize(getWindow(), windowWidth, windowHeight); + glfwGetFramebufferSize(getWindow(), framebufferWidth, framebufferHeight); + xScale = (float) framebufferWidth[0] / windowWidth[0]; + yScale = (float) framebufferHeight[0] / windowHeight[0]; + return Math.max(xScale, yScale); } public static void setSwapInterval(int value) {