From 8bd591fe5e8151948c1e6b9cc819037b88cbd581 Mon Sep 17 00:00:00 2001 From: Brian Matzon Date: Sat, 12 Sep 2009 22:15:21 +0000 Subject: [PATCH] support for tracking mouse outside window on drag, new api for checking if mouse is inside window --- src/java/org/lwjgl/input/Mouse.java | 32 +++++++++++++++++-- .../org/lwjgl/opengl/InputImplementation.java | 2 ++ src/java/org/lwjgl/opengl/LinuxDisplay.java | 4 +++ src/java/org/lwjgl/opengl/MacOSXDisplay.java | 4 +++ src/java/org/lwjgl/opengl/WindowsDisplay.java | 17 ++++++++++ src/java/org/lwjgl/test/input/MouseTest.java | 2 +- src/native/windows/org_lwjgl_opengl_Display.c | 9 ++++++ 7 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/java/org/lwjgl/input/Mouse.java b/src/java/org/lwjgl/input/Mouse.java index e25b7844..3feb6a2a 100644 --- a/src/java/org/lwjgl/input/Mouse.java +++ b/src/java/org/lwjgl/input/Mouse.java @@ -33,6 +33,8 @@ package org.lwjgl.input; import java.nio.ByteBuffer; import java.nio.IntBuffer; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.HashMap; import java.util.Map; @@ -135,6 +137,8 @@ public class Mouse { private static final boolean emulateCursorAnimation = LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_WINDOWS || LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_MACOSX; + private static final boolean allowNegativeMouseCoords = getPrivilegedBoolean("org.lwjgl.input.Mouse.allowNegativeMouseCoords"); + /** * Mouse cannot be constructed. */ @@ -338,9 +342,11 @@ public class Mouse { x = poll_coord1; y = poll_coord2; } - x = Math.min(implementation.getWidth() - 1, Math.max(0, x)); - y = Math.min(implementation.getHeight() - 1, Math.max(0, y)); - dwheel += poll_dwheel; + if(!allowNegativeMouseCoords) { + x = Math.min(implementation.getWidth() - 1, Math.max(0, x)); + y = Math.min(implementation.getHeight() - 1, Math.max(0, y)); + } + dwheel += poll_dwheel; read(); } } @@ -634,4 +640,24 @@ public class Mouse { } } } + + /** Gets a boolean property as a privileged action. */ + static boolean getPrivilegedBoolean(final String property_name) { + Boolean value = (Boolean)AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return new Boolean(Boolean.getBoolean(property_name)); + } + }); + return value.booleanValue(); + } + + /** + * Retrieves whether or not the mouse cursor is within the bounds of the window. + * If the mouse cursor was moved outside the display during a drag, then the result of calling + * this method will be true until the button is released. + * @return true if mouse is inside display, false otherwise. + */ + public static boolean isInsideWindow() { + return implementation.isInsideWindow(); + } } diff --git a/src/java/org/lwjgl/opengl/InputImplementation.java b/src/java/org/lwjgl/opengl/InputImplementation.java index 0c41df70..3f7de2c9 100644 --- a/src/java/org/lwjgl/opengl/InputImplementation.java +++ b/src/java/org/lwjgl/opengl/InputImplementation.java @@ -129,4 +129,6 @@ public interface InputImplementation { int getWidth(); int getHeight(); + + boolean isInsideWindow(); } diff --git a/src/java/org/lwjgl/opengl/LinuxDisplay.java b/src/java/org/lwjgl/opengl/LinuxDisplay.java index 0f059508..6242487a 100644 --- a/src/java/org/lwjgl/opengl/LinuxDisplay.java +++ b/src/java/org/lwjgl/opengl/LinuxDisplay.java @@ -1221,4 +1221,8 @@ final class LinuxDisplay implements DisplayImplementation { public int getHeight() { return Display.getDisplayMode().getHeight(); } + + public boolean isInsideWindow() { + return true; + } } diff --git a/src/java/org/lwjgl/opengl/MacOSXDisplay.java b/src/java/org/lwjgl/opengl/MacOSXDisplay.java index 0d5da2e7..25be1ba6 100644 --- a/src/java/org/lwjgl/opengl/MacOSXDisplay.java +++ b/src/java/org/lwjgl/opengl/MacOSXDisplay.java @@ -501,4 +501,8 @@ final class MacOSXDisplay implements DisplayImplementation { public int getHeight() { return Display.getDisplayMode().getHeight(); } + + public boolean isInsideWindow() { + return true; + } } diff --git a/src/java/org/lwjgl/opengl/WindowsDisplay.java b/src/java/org/lwjgl/opengl/WindowsDisplay.java index 2b1f491b..e3eba681 100644 --- a/src/java/org/lwjgl/opengl/WindowsDisplay.java +++ b/src/java/org/lwjgl/opengl/WindowsDisplay.java @@ -66,6 +66,7 @@ final class WindowsDisplay implements DisplayImplementation { private final static int WM_MBUTTONDBLCLK = 0x0209; private final static int WM_MOUSEWHEEL = 0x020A; private final static int WM_CAPTURECHANGED = 0x0215; + private final static int WM_MOUSELEAVE = 0x02A3; private final static int WM_KEYDOWN = 256; private final static int WM_KEYUP = 257; private final static int WM_SYSKEYUP = 261; @@ -154,6 +155,8 @@ final class WindowsDisplay implements DisplayImplementation { private long large_icon; private int captureMouse = -1; + private boolean trackingMouse = false; + private boolean mouseInside = false; WindowsDisplay() { current_display = this; @@ -813,6 +816,10 @@ final class WindowsDisplay implements DisplayImplementation { int yPos = transformY(getHwnd(), (int)(short)((lParam >> 16) & 0xFFFF)); handleMouseMoved(xPos, yPos, millis); checkCursorState(); + mouseInside = true; + if(!trackingMouse) { + trackingMouse = nTrackMouseEvent(hwnd); + } return 0; case WM_MOUSEWHEEL: int dwheel = (int)(short)((wParam >> 16) & 0xFFFF); @@ -878,6 +885,10 @@ final class WindowsDisplay implements DisplayImplementation { case WM_PAINT: is_dirty = true; return defWindowProc(hwnd, msg, wParam, lParam); + case WM_MOUSELEAVE: + mouseInside = false; + trackingMouse = false; + return defWindowProc(hwnd, msg, wParam, lParam); case WM_CANCELMODE: nReleaseCapture(); /* fall through */ @@ -909,6 +920,12 @@ final class WindowsDisplay implements DisplayImplementation { return -1; } + private native boolean nTrackMouseEvent(long hwnd); + + public boolean isInsideWindow() { + return mouseInside; + } + private static final class Rect { public int top; public int bottom; diff --git a/src/java/org/lwjgl/test/input/MouseTest.java b/src/java/org/lwjgl/test/input/MouseTest.java index 0b763481..cfa4ebde 100644 --- a/src/java/org/lwjgl/test/input/MouseTest.java +++ b/src/java/org/lwjgl/test/input/MouseTest.java @@ -239,7 +239,7 @@ public class MouseTest { private void handleMouse() { readBufferedMouse(); - Display.setTitle("x: " + Mouse.getX() + ", y: " + Mouse.getY() + ", [0]: " + Mouse.isButtonDown(0) + ", [1]: " + Mouse.isButtonDown(1) + ", [2]: " + Mouse.isButtonDown(2)); + Display.setTitle("x: " + Mouse.getX() + ", y: " + Mouse.getY() + ", [0]: " + Mouse.isButtonDown(0) + ", [1]: " + Mouse.isButtonDown(1) + ", [2]: " + Mouse.isButtonDown(2) + ", inside: " + Mouse.isInsideWindow()); } /** diff --git a/src/native/windows/org_lwjgl_opengl_Display.c b/src/native/windows/org_lwjgl_opengl_Display.c index 6a8a3e09..885f5d01 100644 --- a/src/native/windows/org_lwjgl_opengl_Display.c +++ b/src/native/windows/org_lwjgl_opengl_Display.c @@ -468,3 +468,12 @@ JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_WindowsDisplay_nSetCapture(JNIEnv JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_WindowsDisplay_nReleaseCapture(JNIEnv *env, jclass unused) { return ReleaseCapture(); } + +JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_WindowsDisplay_nTrackMouseEvent(JNIEnv *env, jclass clazz, jlong hwnd_ptr) { + HWND hwnd = (HWND)(INT_PTR)hwnd_ptr; + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hwnd; + return TrackMouseEvent(&tme); +} \ No newline at end of file