From 63532ca64788dc8fc658a6c14331538362665604 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Fri, 24 Nov 2006 14:53:01 +0000 Subject: [PATCH] Make sure that the cursor position doesn't jump when switching grab mode --- src/java/org/lwjgl/input/Mouse.java | 4 + src/java/org/lwjgl/opengl/AWTUtil.java | 73 ++++++++++++++++++- src/java/org/lwjgl/opengl/LinuxMouse.java | 10 ++- .../org/lwjgl/opengl/MouseEventQueue.java | 6 ++ src/java/org/lwjgl/test/input/MouseTest.java | 2 + 5 files changed, 90 insertions(+), 5 deletions(-) diff --git a/src/java/org/lwjgl/input/Mouse.java b/src/java/org/lwjgl/input/Mouse.java index 32dfbf3c..bd959d09 100644 --- a/src/java/org/lwjgl/input/Mouse.java +++ b/src/java/org/lwjgl/input/Mouse.java @@ -570,6 +570,10 @@ public class Mouse { isGrabbed = grab; if (isCreated()) { implementation.grabMouse(isGrabbed); + // Get latest values from native side + poll(); + event_x = x; + event_y = y; resetMouse(); } } diff --git a/src/java/org/lwjgl/opengl/AWTUtil.java b/src/java/org/lwjgl/opengl/AWTUtil.java index b287d5e1..01576bfb 100644 --- a/src/java/org/lwjgl/opengl/AWTUtil.java +++ b/src/java/org/lwjgl/opengl/AWTUtil.java @@ -37,7 +37,9 @@ package org.lwjgl.opengl; import java.awt.Cursor; import java.awt.Component; +import java.awt.GraphicsDevice; import java.awt.Dimension; +import java.awt.IllegalComponentStateException; import java.awt.Point; import java.awt.Rectangle; import java.awt.Robot; @@ -106,12 +108,75 @@ final class AWTUtil { } } + private static int transformY(Component component, int y) { + return component.getHeight() - 1 - y; + } + + /** + * Use reflection to access the JDK 1.5 pointer location, if possible and + * only if the given component is on the same screen as the cursor. Return + * null otherwise. + */ + private static Point getPointerLocation(final Component component) { + try { + final Class MouseInfo_class = Class.forName("java.awt.MouseInfo"); + final Method getPointerInfo_method = MouseInfo_class.getMethod("getPointerInfo", null); + final Class PointerInfo_class = Class.forName("java.awt.PointerInfo"); + final Method getDevice_method = PointerInfo_class.getMethod("getDevice", null); + final Method getLocation_method = PointerInfo_class.getMethod("getLocation", null); + return (Point)AccessController.doPrivileged(new PrivilegedExceptionAction() { + public final Object run() throws Exception { + Object pointer_info = getPointerInfo_method.invoke(null, null); + GraphicsDevice device = (GraphicsDevice)getDevice_method.invoke(pointer_info, null); + if (device == component.getGraphicsConfiguration().getDevice()) { + return (Point)getLocation_method.invoke(pointer_info, null); + } else + return null; + } + }); + } catch (PrivilegedActionException e) { + LWJGLUtil.log("Failed to query pointer location: " + e.getCause()); + } catch (NoSuchMethodException e) { + LWJGLUtil.log("Failed to query pointer location: " + e); + } catch (IllegalAccessException e) { + LWJGLUtil.log("Failed to query pointer location: " + e); + } catch (ClassNotFoundException e) { + LWJGLUtil.log("Failed to query pointer location: " + e); + } + return null; + } + + /** + * Use the 1.5 API to get the cursor position relative to the component. Return null + * if it fails (JDK <= 1.4). + */ + public static Point getCursorPosition(Component component) { + try { + Point pointer_location = getPointerLocation(component); + if (pointer_location != null) { + Point location = component.getLocationOnScreen(); + pointer_location.translate(-location.x, -location.y); + pointer_location.move(pointer_location.x, transformY(component, pointer_location.y)); + return pointer_location; + } + } catch (IllegalComponentStateException e) { + LWJGLUtil.log("Failed to set cursor position: " + e); + } catch (NoClassDefFoundError e) { // Not JDK 1.5 + LWJGLUtil.log("Failed to query cursor position: " + e); + } + return null; + } + public static void setCursorPosition(Component component, Robot robot, int x, int y) { if (robot != null) { - Point location = component.getLocationOnScreen(); - int transformed_x = location.x + x; - int transformed_y = location.y + component.getHeight() - 1 - y; - robot.mouseMove(transformed_x, transformed_y); + try { + Point location = component.getLocationOnScreen(); + int transformed_x = location.x + x; + int transformed_y = location.y + transformY(component, y); + robot.mouseMove(transformed_x, transformed_y); + } catch (IllegalComponentStateException e) { + LWJGLUtil.log("Failed to set cursor position: " + e); + } } } diff --git a/src/java/org/lwjgl/opengl/LinuxMouse.java b/src/java/org/lwjgl/opengl/LinuxMouse.java index b4e440e8..bc91ff60 100644 --- a/src/java/org/lwjgl/opengl/LinuxMouse.java +++ b/src/java/org/lwjgl/opengl/LinuxMouse.java @@ -173,7 +173,15 @@ final class LinuxMouse { public void changeGrabbed(boolean grab, boolean warp_pointer) { reset(); long root_window = nQueryPointer(display, window, query_pointer_buffer); - doHandlePointerMotion(grab, warp_pointer, root_window, query_pointer_buffer.get(0), query_pointer_buffer.get(1), query_pointer_buffer.get(2), query_pointer_buffer.get(3), last_event_nanos); + + int root_x = query_pointer_buffer.get(0); + int root_y = query_pointer_buffer.get(1); + int win_x = query_pointer_buffer.get(2); + int win_y = query_pointer_buffer.get(3); + // Pretend that the cursor never moved + last_x = win_x; + last_y = transformY(win_y); + doHandlePointerMotion(grab, warp_pointer, root_window, root_x, root_y, win_x, win_y, last_event_nanos); } public int getButtonCount() { diff --git a/src/java/org/lwjgl/opengl/MouseEventQueue.java b/src/java/org/lwjgl/opengl/MouseEventQueue.java index b1f02571..7961dc3b 100644 --- a/src/java/org/lwjgl/opengl/MouseEventQueue.java +++ b/src/java/org/lwjgl/opengl/MouseEventQueue.java @@ -42,6 +42,7 @@ import java.awt.event.MouseMotionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.Component; +import java.awt.Point; import java.nio.ByteBuffer; import java.nio.IntBuffer; @@ -112,6 +113,11 @@ class MouseEventQueue extends EventQueue implements MouseListener, MouseMotionLi protected void resetCursorToCenter() { clearEvents(); accum_dx = accum_dy = 0; + Point cursor_location = AWTUtil.getCursorPosition(component); + if (cursor_location != null) { + last_x = cursor_location.x; + last_y = cursor_location.y; + } } private void putMouseEvent(byte button, byte state, int dz, long nanos) { diff --git a/src/java/org/lwjgl/test/input/MouseTest.java b/src/java/org/lwjgl/test/input/MouseTest.java index 8faecc55..f0f621d7 100644 --- a/src/java/org/lwjgl/test/input/MouseTest.java +++ b/src/java/org/lwjgl/test/input/MouseTest.java @@ -242,6 +242,8 @@ public class MouseTest { if(Mouse.getEventButton() != -1 && Mouse.getEventButtonState()) { lastButton = Mouse.getEventButton(); } + if (Mouse.getEventDX() != 0 || Mouse.getEventDY() != 0) + System.out.println("Mouse.getEventDX() = " + Mouse.getEventDX() + " | Mouse.getEventDY() = " + Mouse.getEventDY()); } updateState();