Windows: Make sure AWTInputAdapter is not reporting events twice after a grab change

This commit is contained in:
Elias Naur 2006-11-19 23:02:25 +00:00
parent 5d6ae4138a
commit d75d00666a
4 changed files with 86 additions and 20 deletions

View File

@ -59,10 +59,14 @@ abstract class AbstractAWTInput implements AWTCanvasInputImplementation {
this.robot = AWTUtil.createRobot(canvas); this.robot = AWTUtil.createRobot(canvas);
} }
protected synchronized MouseEventQueue getMouseEventQueue() { protected MouseEventQueue getMouseEventQueue() {
return mouse_queue; return mouse_queue;
} }
protected KeyboardEventQueue getKeyboardEventQueue() {
return keyboard_queue;
}
public synchronized void grabMouse(boolean grab) { public synchronized void grabMouse(boolean grab) {
this.grab = grab; this.grab = grab;
if (mouse_queue != null) if (mouse_queue != null)

View File

@ -115,9 +115,15 @@ final class WindowsAWTInput extends AbstractAWTInput {
private void grab(boolean grab) { private void grab(boolean grab) {
if (has_grabbed != grab) { if (has_grabbed != grab) {
cached_mouse.grab(grab); cached_mouse.grab(grab);
cached_keyboard.grab(grab);
has_grabbed = grab; has_grabbed = grab;
if (!grab) cached_mouse.flush();
cached_keyboard.flush();
getMouseEventQueue().clearEvents();
getKeyboardEventQueue().clearEvents();
if (!grab) {
getCanvas().setCursor(cached_cursor); getCanvas().setCursor(cached_cursor);
}
} }
} }

View File

@ -47,6 +47,7 @@ import org.lwjgl.BufferUtils;
final class WindowsKeyboard { final class WindowsKeyboard {
private final static int BUFFER_SIZE = 50; private final static int BUFFER_SIZE = 50;
private final long hwnd;
private final WindowsDirectInput dinput; private final WindowsDirectInput dinput;
private final WindowsDirectInputDevice keyboard; private final WindowsDirectInputDevice keyboard;
private final IntBuffer temp_data_buffer; private final IntBuffer temp_data_buffer;
@ -55,14 +56,17 @@ final class WindowsKeyboard {
private final CharBuffer unicode_buffer; private final CharBuffer unicode_buffer;
private final ByteBuffer ascii_buffer; private final ByteBuffer ascii_buffer;
private boolean grabbed;
public WindowsKeyboard(WindowsDirectInput dinput, long hwnd) throws LWJGLException { public WindowsKeyboard(WindowsDirectInput dinput, long hwnd) throws LWJGLException {
this.hwnd = hwnd;
this.dinput = dinput; this.dinput = dinput;
try { try {
keyboard = dinput.createDevice(WindowsDirectInput.KEYBOARD_TYPE); keyboard = dinput.createDevice(WindowsDirectInput.KEYBOARD_TYPE);
try { try {
keyboard.setCooperateLevel(hwnd, WindowsDirectInputDevice.DISCL_NONEXCLUSIVE | WindowsDirectInputDevice.DISCL_FOREGROUND);
keyboard.setDataFormat(WindowsDirectInput.KEYBOARD_TYPE); keyboard.setDataFormat(WindowsDirectInput.KEYBOARD_TYPE);
keyboard.setBufferSize(BUFFER_SIZE); keyboard.setBufferSize(BUFFER_SIZE);
acquireNonExclusive();
} catch (LWJGLException e) { } catch (LWJGLException e) {
keyboard.release(); keyboard.release();
throw e; throw e;
@ -84,15 +88,48 @@ final class WindowsKeyboard {
ascii_buffer = BufferUtils.createByteBuffer(2); ascii_buffer = BufferUtils.createByteBuffer(2);
} }
} }
private static native boolean isWindowsNT(); 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() { public void destroy() {
keyboard.unacquire(); keyboard.unacquire();
keyboard.release(); keyboard.release();
dinput.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) { public void poll(ByteBuffer keyDownBuffer) {
int ret = keyboard.acquire(); int ret = keyboard.acquire();
if (ret != WindowsDirectInput.DI_OK && ret != WindowsDirectInput.DI_NOEFFECT) 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 ToAscii(int wVirtKey, int wScanCode, ByteBuffer lpKeyState, ByteBuffer lpChar, int flags);
private static native int GetKeyboardState(ByteBuffer lpKeyState); 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(); int ret = keyboard.acquire();
if (ret != WindowsDirectInput.DI_OK && ret != WindowsDirectInput.DI_NOEFFECT) if (ret != WindowsDirectInput.DI_OK && ret != WindowsDirectInput.DI_NOEFFECT)
return; return;
@ -202,6 +244,10 @@ final class WindowsKeyboard {
LWJGLUtil.log("Failed to read keyboard (0x" + Integer.toHexString(ret) + ")"); LWJGLUtil.log("Failed to read keyboard (0x" + Integer.toHexString(ret) + ")");
break; break;
} }
}
public void read(ByteBuffer buffer) {
processEvents();
temp_data_buffer.flip(); temp_data_buffer.flip();
translateData(temp_data_buffer, buffer); translateData(temp_data_buffer, buffer);
} }

View File

@ -246,32 +246,42 @@ final class WindowsMouse {
temp_data_buffer.clear(); temp_data_buffer.clear();
ret = mouse.getDeviceData(temp_data_buffer); ret = mouse.getDeviceData(temp_data_buffer);
if (ret == WindowsDirectInput.DI_OK) { switch (ret) {
if (mouse_grabbed) { case WindowsDirectInput.DI_OK:
temp_data_buffer.flip(); break;
copyDXEvents(temp_data_buffer); case WindowsDirectInput.DI_BUFFEROVERFLOW:
} LWJGLUtil.log("Mouse buffer overflowed");
} else if (ret == WindowsDirectInput.DI_BUFFEROVERFLOW) { break;
LWJGLUtil.log("Mouse buffer overflowed"); case WindowsDirectInput.DIERR_INPUTLOST:
} else if (ret == WindowsDirectInput.DIERR_INPUTLOST) { LWJGLUtil.log("Mouse input lost");
LWJGLUtil.log("Mouse input lost"); break;
} else if (ret == WindowsDirectInput.DIERR_NOTACQUIRED) { case WindowsDirectInput.DIERR_NOTACQUIRED:
LWJGLUtil.log("Mouse not acquired"); LWJGLUtil.log("Mouse not acquired");
} else { break;
LWJGLUtil.log("unknown mouse error (" + Integer.toHexString(ret) + ")"); default:
LWJGLUtil.log("unknown mouse error (" + Integer.toHexString(ret) + ")");
break;
} }
} }
public final void flush() {
readDXBuffer();
temp_data_buffer.clear();
}
public void read(ByteBuffer buffer) { public void read(ByteBuffer buffer) {
readDXBuffer(); readDXBuffer();
if (mouse_grabbed) {
temp_data_buffer.flip();
copyDXEvents(temp_data_buffer);
}
event_queue.copyEvents(buffer); event_queue.copyEvents(buffer);
} }
public void grab(boolean grab) { public void grab(boolean grab) {
if(grab) { if(grab) {
if (!mouse_grabbed) { if (!mouse_grabbed) {
// flush DX event buffer flush();
readDXBuffer();
mouse_grabbed = true; mouse_grabbed = true;
mouse.unacquire(); mouse.unacquire();
if (!acquire(WindowsDirectInputDevice.DISCL_EXCLUSIVE | WindowsDirectInputDevice.DISCL_FOREGROUND)) if (!acquire(WindowsDirectInputDevice.DISCL_EXCLUSIVE | WindowsDirectInputDevice.DISCL_FOREGROUND))