From d75d00666a14d20f38cf235f568d0c5f16246c59 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Sun, 19 Nov 2006 23:02:25 +0000 Subject: [PATCH] Windows: Make sure AWTInputAdapter is not reporting events twice after a grab change --- .../org/lwjgl/opengl/AbstractAWTInput.java | 6 ++- .../org/lwjgl/opengl/WindowsAWTInput.java | 8 ++- .../org/lwjgl/opengl/WindowsKeyboard.java | 52 +++++++++++++++++-- src/java/org/lwjgl/opengl/WindowsMouse.java | 40 ++++++++------ 4 files changed, 86 insertions(+), 20 deletions(-) diff --git a/src/java/org/lwjgl/opengl/AbstractAWTInput.java b/src/java/org/lwjgl/opengl/AbstractAWTInput.java index 72cf12c0..5e2e96d1 100644 --- a/src/java/org/lwjgl/opengl/AbstractAWTInput.java +++ b/src/java/org/lwjgl/opengl/AbstractAWTInput.java @@ -59,10 +59,14 @@ abstract class AbstractAWTInput implements AWTCanvasInputImplementation { this.robot = AWTUtil.createRobot(canvas); } - protected synchronized MouseEventQueue getMouseEventQueue() { + protected MouseEventQueue getMouseEventQueue() { return mouse_queue; } + protected KeyboardEventQueue getKeyboardEventQueue() { + return keyboard_queue; + } + public synchronized void grabMouse(boolean grab) { this.grab = grab; if (mouse_queue != null) diff --git a/src/java/org/lwjgl/opengl/WindowsAWTInput.java b/src/java/org/lwjgl/opengl/WindowsAWTInput.java index ae46882c..7ce150d0 100644 --- a/src/java/org/lwjgl/opengl/WindowsAWTInput.java +++ b/src/java/org/lwjgl/opengl/WindowsAWTInput.java @@ -115,9 +115,15 @@ final class WindowsAWTInput extends AbstractAWTInput { private void grab(boolean grab) { if (has_grabbed != grab) { cached_mouse.grab(grab); + cached_keyboard.grab(grab); has_grabbed = grab; - if (!grab) + cached_mouse.flush(); + cached_keyboard.flush(); + getMouseEventQueue().clearEvents(); + getKeyboardEventQueue().clearEvents(); + if (!grab) { getCanvas().setCursor(cached_cursor); + } } } diff --git a/src/java/org/lwjgl/opengl/WindowsKeyboard.java b/src/java/org/lwjgl/opengl/WindowsKeyboard.java index 6e76ff85..a01d1067 100644 --- a/src/java/org/lwjgl/opengl/WindowsKeyboard.java +++ b/src/java/org/lwjgl/opengl/WindowsKeyboard.java @@ -47,6 +47,7 @@ import org.lwjgl.BufferUtils; final class WindowsKeyboard { private final static int BUFFER_SIZE = 50; + private final long hwnd; private final WindowsDirectInput dinput; private final WindowsDirectInputDevice keyboard; private final IntBuffer temp_data_buffer; @@ -55,14 +56,17 @@ final class WindowsKeyboard { private final CharBuffer unicode_buffer; private final ByteBuffer ascii_buffer; + private boolean grabbed; + public WindowsKeyboard(WindowsDirectInput dinput, long hwnd) throws LWJGLException { + this.hwnd = hwnd; this.dinput = dinput; try { keyboard = dinput.createDevice(WindowsDirectInput.KEYBOARD_TYPE); try { - keyboard.setCooperateLevel(hwnd, WindowsDirectInputDevice.DISCL_NONEXCLUSIVE | WindowsDirectInputDevice.DISCL_FOREGROUND); keyboard.setDataFormat(WindowsDirectInput.KEYBOARD_TYPE); keyboard.setBufferSize(BUFFER_SIZE); + acquireNonExclusive(); } catch (LWJGLException e) { keyboard.release(); throw e; @@ -84,15 +88,48 @@ final class WindowsKeyboard { ascii_buffer = BufferUtils.createByteBuffer(2); } } - private static native boolean isWindowsNT(); + private boolean acquire(int flags) { + try { + keyboard.setCooperateLevel(hwnd, flags); + keyboard.acquire(); + return true; + } catch (LWJGLException e) { + LWJGLUtil.log("Failed to acquire keyboard: " + e); + return false; + } + } + + private boolean acquireNonExclusive() { + return acquire(WindowsDirectInputDevice.DISCL_NONEXCLUSIVE | WindowsDirectInputDevice.DISCL_FOREGROUND) || + acquire(WindowsDirectInputDevice.DISCL_NONEXCLUSIVE | WindowsDirectInputDevice.DISCL_BACKGROUND); + } + public void destroy() { keyboard.unacquire(); keyboard.release(); dinput.release(); } + public void grab(boolean grab) { + if(grab) { + if (!grabbed) { + flush(); + grabbed = true; + keyboard.unacquire(); + if (!acquire(WindowsDirectInputDevice.DISCL_EXCLUSIVE | WindowsDirectInputDevice.DISCL_FOREGROUND)) + LWJGLUtil.log("Failed to reset cooperative mode"); + } + } else { + if (grabbed) { + grabbed = false; + keyboard.unacquire(); + acquireNonExclusive(); + } + } + } + public void poll(ByteBuffer keyDownBuffer) { int ret = keyboard.acquire(); if (ret != WindowsDirectInput.DI_OK && ret != WindowsDirectInput.DI_NOEFFECT) @@ -181,7 +218,12 @@ final class WindowsKeyboard { private static native int ToAscii(int wVirtKey, int wScanCode, ByteBuffer lpKeyState, ByteBuffer lpChar, int flags); private static native int GetKeyboardState(ByteBuffer lpKeyState); - public void read(ByteBuffer buffer) { + public void flush() { + processEvents(); + temp_data_buffer.clear(); + } + + private void processEvents() { int ret = keyboard.acquire(); if (ret != WindowsDirectInput.DI_OK && ret != WindowsDirectInput.DI_NOEFFECT) return; @@ -202,6 +244,10 @@ final class WindowsKeyboard { LWJGLUtil.log("Failed to read keyboard (0x" + Integer.toHexString(ret) + ")"); break; } + } + + public void read(ByteBuffer buffer) { + processEvents(); temp_data_buffer.flip(); translateData(temp_data_buffer, buffer); } diff --git a/src/java/org/lwjgl/opengl/WindowsMouse.java b/src/java/org/lwjgl/opengl/WindowsMouse.java index 6decfcf6..e82575ea 100644 --- a/src/java/org/lwjgl/opengl/WindowsMouse.java +++ b/src/java/org/lwjgl/opengl/WindowsMouse.java @@ -246,32 +246,42 @@ final class WindowsMouse { temp_data_buffer.clear(); ret = mouse.getDeviceData(temp_data_buffer); - if (ret == WindowsDirectInput.DI_OK) { - if (mouse_grabbed) { - temp_data_buffer.flip(); - copyDXEvents(temp_data_buffer); - } - } else if (ret == WindowsDirectInput.DI_BUFFEROVERFLOW) { - LWJGLUtil.log("Mouse buffer overflowed"); - } else if (ret == WindowsDirectInput.DIERR_INPUTLOST) { - LWJGLUtil.log("Mouse input lost"); - } else if (ret == WindowsDirectInput.DIERR_NOTACQUIRED) { - LWJGLUtil.log("Mouse not acquired"); - } else { - LWJGLUtil.log("unknown mouse error (" + Integer.toHexString(ret) + ")"); + switch (ret) { + case WindowsDirectInput.DI_OK: + break; + case WindowsDirectInput.DI_BUFFEROVERFLOW: + LWJGLUtil.log("Mouse buffer overflowed"); + break; + case WindowsDirectInput.DIERR_INPUTLOST: + LWJGLUtil.log("Mouse input lost"); + break; + case WindowsDirectInput.DIERR_NOTACQUIRED: + LWJGLUtil.log("Mouse not acquired"); + break; + default: + LWJGLUtil.log("unknown mouse error (" + Integer.toHexString(ret) + ")"); + break; } } + public final void flush() { + readDXBuffer(); + temp_data_buffer.clear(); + } + public void read(ByteBuffer buffer) { readDXBuffer(); + if (mouse_grabbed) { + temp_data_buffer.flip(); + copyDXEvents(temp_data_buffer); + } event_queue.copyEvents(buffer); } public void grab(boolean grab) { if(grab) { if (!mouse_grabbed) { - // flush DX event buffer - readDXBuffer(); + flush(); mouse_grabbed = true; mouse.unacquire(); if (!acquire(WindowsDirectInputDevice.DISCL_EXCLUSIVE | WindowsDirectInputDevice.DISCL_FOREGROUND))