Windows: Make sure AWTInputAdapter is not reporting events twice after a grab change
This commit is contained in:
parent
5d6ae4138a
commit
d75d00666a
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
|
|
Loading…
Reference in New Issue