From 23701fdf75534f7cf6118a6227a85d44a8f97b4b Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Tue, 24 Apr 2007 09:30:03 +0000 Subject: [PATCH] Windows: Remove dependency on DirectInput for WindowsMouse used by WindowsDisplay. Keyboard conversion coming up. Reasons: 1. DirectInput is deprecated (http://en.wikipedia.org/wiki/DirectInput). Specifically, Microsoft recommends using regular windows messages for keyboard and mouse input. 2. Not using DirectInput enable us to use the Raw Input JInput plugin to access multiple mice (and keyboards). 3. We're already using windows messages for features DirectInput never supported, so by removing DirectInput dependency, we get rid of some special case code. 4. When we're only using windows messages for input, we're (theoretically) more compatible than with a dependency on a properly working DirectInput. --- src/java/org/lwjgl/Sys.java | 2 +- .../org/lwjgl/opengl/WindowsAWTInput.java | 6 +- .../lwjgl/opengl/WindowsDirectInputMouse.java | 353 ++++++++++++++++++ src/java/org/lwjgl/opengl/WindowsDisplay.java | 167 ++++++++- src/java/org/lwjgl/opengl/WindowsMouse.java | 307 ++++----------- src/native/common/common_tools.c | 7 + src/native/common/common_tools.h | 1 + src/native/windows/org_lwjgl_input_Cursor.c | 6 +- src/native/windows/org_lwjgl_opengl_Display.c | 120 +++--- 9 files changed, 664 insertions(+), 305 deletions(-) create mode 100644 src/java/org/lwjgl/opengl/WindowsDirectInputMouse.java diff --git a/src/java/org/lwjgl/Sys.java b/src/java/org/lwjgl/Sys.java index f8134a57..f4ab1b31 100644 --- a/src/java/org/lwjgl/Sys.java +++ b/src/java/org/lwjgl/Sys.java @@ -57,7 +57,7 @@ public final class Sys { private static final String VERSION = "1.1"; /** Current version of the JNI library */ - static final int JNI_VERSION = 8; + static final int JNI_VERSION = 9; /** The implementation instance to delegate platform specific behavior to */ private final static SysImplementation implementation; diff --git a/src/java/org/lwjgl/opengl/WindowsAWTInput.java b/src/java/org/lwjgl/opengl/WindowsAWTInput.java index 41e95f4e..3a911345 100644 --- a/src/java/org/lwjgl/opengl/WindowsAWTInput.java +++ b/src/java/org/lwjgl/opengl/WindowsAWTInput.java @@ -53,7 +53,7 @@ final class WindowsAWTInput extends AbstractAWTInput { private Cursor cached_cursor; private long cached_hwnd; - private WindowsMouse cached_mouse; + private WindowsDirectInputMouse cached_mouse; // private WindowsKeyboard cached_keyboard; private boolean has_grabbed; @@ -96,7 +96,7 @@ final class WindowsAWTInput extends AbstractAWTInput { cached_keyboard.destroy(); }*/ WindowsDirectInput dinput = WindowsDisplay.createDirectInput(); - cached_mouse = new WindowsMouse(dinput, hwnd); + cached_mouse = new WindowsDirectInputMouse(dinput, hwnd); // cached_keyboard = new WindowsKeyboard(dinput, hwnd); } if (isGrabbed()) { @@ -105,7 +105,7 @@ final class WindowsAWTInput extends AbstractAWTInput { * task bar and clicking on it. So we'll use ClipCursor to * contain it while the cursor is grabbed. */ - WindowsDisplay.setupCursorClipping(hwnd); + WindowsDisplay.setupCursorClipping(hwnd, true); // Just clip it to a fullscreen window if (getCanvas().getCursor() != blank_cursor) { cached_cursor = getCanvas().getCursor(); /** diff --git a/src/java/org/lwjgl/opengl/WindowsDirectInputMouse.java b/src/java/org/lwjgl/opengl/WindowsDirectInputMouse.java new file mode 100644 index 00000000..ce409504 --- /dev/null +++ b/src/java/org/lwjgl/opengl/WindowsDirectInputMouse.java @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.opengl; + +/** + * This is the Windows implementation of the Mouse. + * @author elias_naur + */ + +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import java.nio.CharBuffer; + +import org.lwjgl.LWJGLException; +import org.lwjgl.LWJGLUtil; +import org.lwjgl.BufferUtils; +import org.lwjgl.input.Mouse; + +final class WindowsDirectInputMouse { + private final static int BUFFER_SIZE = 50; + private final static int BUTTON_STATES_SIZE = 7; + + private final static int DIMOFS_X = 0; + private final static int DIMOFS_Y = 4; + private final static int DIMOFS_Z = 8; + private final static int DIMOFS_BUTTON0 = 12; + private final static int DIMOFS_BUTTON1 = 13; + private final static int DIMOFS_BUTTON2 = 14; + private final static int DIMOFS_BUTTON3 = 15; + + private final long hwnd; + private final WindowsDirectInput dinput; + private final WindowsDirectInputDevice mouse; + + private final int mouse_button_count; + private final boolean has_wheel; + + private final EventQueue event_queue = new EventQueue(Mouse.EVENT_SIZE); + /* Buffer to hold a DIMOUSESTATE */ + private final ByteBuffer mouse_state; + private final IntBuffer temp_data_buffer; + + private final ByteBuffer mouse_event = ByteBuffer.allocate(Mouse.EVENT_SIZE); + + private boolean mouse_grabbed; + private byte[] win32_message_button_states = new byte[BUTTON_STATES_SIZE]; + private int accum_dwheel; + private int last_x; + private int last_y; + + public WindowsDirectInputMouse(WindowsDirectInput dinput, long hwnd) throws LWJGLException { + this.hwnd = hwnd; + this.dinput = dinput; + try { + mouse = dinput.createDevice(WindowsDirectInput.MOUSE_TYPE); + try { + mouse.setDataFormat(WindowsDirectInput.MOUSE_TYPE); + mouse.setBufferSize(BUFFER_SIZE); + if (!acquireNonExclusive()) + throw new LWJGLException("Failed to acquire mouse non-exclusive"); + } catch (LWJGLException e) { + mouse.release(); + throw e; + } + } catch (LWJGLException e) { + dinput.release(); + throw e; + } + MouseEnumerator enumerator = new MouseEnumerator(); + mouse.enumObjects(enumerator); + this.mouse_button_count = Math.min(enumerator.getButtonCount(), 4); + this.has_wheel = enumerator.hasWheel(); + mouse_state = BufferUtils.createByteBuffer(3*4 + 4); + temp_data_buffer = BufferUtils.createIntBuffer(BUFFER_SIZE*WindowsDirectInputDevice.DATA_SIZE); + } + + public boolean hasWheel() { + return has_wheel; + } + + public int getButtonCount() { + return mouse_button_count; + } + + private boolean acquire(int flags) { + try { + mouse.setCooperateLevel(hwnd, flags); + mouse.acquire(); + return true; + } catch (LWJGLException e) { + LWJGLUtil.log("Failed to acquire mouse: " + e); + return false; + } + } + + private boolean acquireNonExclusive() { + return acquire(WindowsDirectInputDevice.DISCL_NONEXCLUSIVE | WindowsDirectInputDevice.DISCL_FOREGROUND) || + acquire(WindowsDirectInputDevice.DISCL_NONEXCLUSIVE | WindowsDirectInputDevice.DISCL_BACKGROUND); + } + + public void destroy() { + mouse.unacquire(); + mouse.release(); + dinput.release(); + } + + public void poll(IntBuffer coord_buffer, ByteBuffer buttons) { + int ret = mouse.acquire(); + if (ret != WindowsDirectInput.DI_OK && ret != WindowsDirectInput.DI_NOEFFECT) + return; + mouse.poll(); + for (int i = 0; i < coord_buffer.remaining(); i++) + coord_buffer.put(coord_buffer.position() + i, 0); + mouse_state.clear(); + ret = mouse.getDeviceState(mouse_state); + int mouse_state_lx = mouse_state.getInt(); + int mouse_state_ly = mouse_state.getInt(); + int mouse_state_lz = mouse_state.getInt(); + int num_buttons = mouse_button_count; + if (mouse_grabbed || ret == WindowsDirectInput.DI_OK) { + if (ret != WindowsDirectInput.DI_OK) { + LWJGLUtil.log("Error getting mouse state: (0x" + Integer.toHexString(ret) + ")"); + return; + } + + coord_buffer.put(coord_buffer.position() + 2, mouse_state_lz); + if (num_buttons > buttons.remaining()) + num_buttons = buttons.remaining(); + for (int j = 0; j < num_buttons; j++) { + byte button_state = (mouse_state.get() & 0x80) != 0 ? (byte)1 : (byte)0; + buttons.put(buttons.position() + j, button_state); + // track the button state in the windows message buffer state array + // to get accurate button information when releasing a grab + win32_message_button_states[j] = button_state; + } + } else { + coord_buffer.put(coord_buffer.position() + 2, accum_dwheel); + if (num_buttons > win32_message_button_states.length) + num_buttons = win32_message_button_states.length; + for (int j = 0; j < num_buttons; j++) { + buttons.put(buttons.position() + j, win32_message_button_states[j]); + } + } + accum_dwheel = 0; + if (mouse_grabbed) { + coord_buffer.put(coord_buffer.position() + 0, mouse_state_lx); + coord_buffer.put(coord_buffer.position() + 1, -mouse_state_ly); + } else { + coord_buffer.put(coord_buffer.position() + 0, last_x); + coord_buffer.put(coord_buffer.position() + 1, last_y); + } + } + + private void putMouseEventWithCoords(byte button, byte state, int coord1, int coord2, int dz, long nanos) { + mouse_event.clear(); + mouse_event.put(button).put(state).putInt(coord1).putInt(coord2).putInt(dz).putLong(nanos); + mouse_event.flip(); + event_queue.putEvent(mouse_event); + } + + private void putMouseEvent(byte button, byte state, int dz, long nanos) { + if (mouse_grabbed) + putMouseEventWithCoords(button, state, 0, 0, dz, nanos); + else + putMouseEventWithCoords(button, state, last_x, last_y, dz, nanos); + } + + private void copyDXEvents(IntBuffer buffer) { + int buffer_index = 0; + int dx = 0, dy = 0, dwheel = 0; + byte button_state; + int i; + long nanos = 0; + while (buffer.hasRemaining()) { + int dwOfs = buffer.get(); + int dwData = buffer.get(); + long dwTimeStamp = ((long)buffer.get()) & 0xFFFFFFFF; + nanos = dwTimeStamp*1000000; + button_state = (dwData & 0x80) != 0 ? (byte)1 : (byte)0; + switch (dwOfs) { + case DIMOFS_BUTTON0: + putMouseEventWithCoords((byte)0, button_state, dx, -dy, dwheel, nanos); + dx = dy = dwheel = 0; + break; + case DIMOFS_BUTTON1: + putMouseEventWithCoords((byte)1, button_state, dx, -dy, dwheel, nanos); + dx = dy = dwheel = 0; + break; + case DIMOFS_BUTTON2: + putMouseEventWithCoords((byte)2, button_state, dx, -dy, dwheel, nanos); + dx = dy = dwheel = 0; + break; + case DIMOFS_BUTTON3: + putMouseEventWithCoords((byte)3, button_state, dx, -dy, dwheel, nanos); + dx = dy = dwheel = 0; + break; + case DIMOFS_X: + dx += dwData; + break; + case DIMOFS_Y: + dy += dwData; + break; + case DIMOFS_Z: + dwheel += dwData; + break; + } + } + if (dx != 0 || dy != 0 || dwheel != 0) + putMouseEventWithCoords((byte)-1, (byte)0, dx, -dy, dwheel, nanos); + } + + private void readDXBuffer() { + int ret = mouse.acquire(); + if (ret != WindowsDirectInput.DI_OK && ret != WindowsDirectInput.DI_NOEFFECT) + return; + mouse.poll(); + temp_data_buffer.clear(); + ret = mouse.getDeviceData(temp_data_buffer); + + 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(); + mouse_grabbed = true; + mouse.unacquire(); + if (!acquire(WindowsDirectInputDevice.DISCL_EXCLUSIVE | WindowsDirectInputDevice.DISCL_FOREGROUND)) + LWJGLUtil.log("Failed to reset cooperative mode"); + } + } else { + if (mouse_grabbed) { + mouse_grabbed = false; + mouse.unacquire(); + acquireNonExclusive(); + } + } + event_queue.clearEvents(); + } + + public void handleMouseScrolled(int event_dwheel, long millis) { + accum_dwheel += event_dwheel; + putMouseEvent((byte)-1, (byte)0, event_dwheel, millis*1000000); + } + + public void handleMouseMoved(int x, int y, long millis) { + int dx; + int dy; + dx = x - last_x; + dy = y - last_y; + last_x = x; + last_y = y; + long nanos = millis*1000000; + if (mouse_grabbed) { + putMouseEventWithCoords((byte)-1, (byte)0, dx, dy, 0, nanos); + } else { + putMouseEventWithCoords((byte)-1, (byte)0, x, y, 0, nanos); + } + } + + public void handleMouseButton(byte button, byte state, long millis) { + putMouseEvent(button, state, 0, millis*1000000); + if (button < BUTTON_STATES_SIZE) + win32_message_button_states[button] = state != 0 ? (byte)1 : (byte)0; + } + + private static class MouseEnumerator implements WindowsDirectInputDeviceObjectCallback { + private int button_count; + private boolean has_wheel; + + public int getButtonCount() { + return button_count; + } + + public boolean hasWheel() { + return has_wheel; + } + + public boolean nextObject(int type, String name) { + LWJGLUtil.log("Found mouse object: " + name); + switch (type) { + case WindowsDirectInputDevice.GUID_ZAxis: + has_wheel = true; + break; + case WindowsDirectInputDevice.GUID_Button: + button_count++; + break; + default: + break; + } + return true; + } + } +} diff --git a/src/java/org/lwjgl/opengl/WindowsDisplay.java b/src/java/org/lwjgl/opengl/WindowsDisplay.java index 3cc59c99..e5fb7c0a 100644 --- a/src/java/org/lwjgl/opengl/WindowsDisplay.java +++ b/src/java/org/lwjgl/opengl/WindowsDisplay.java @@ -44,6 +44,7 @@ import java.nio.IntBuffer; import org.lwjgl.LWJGLException; import org.lwjgl.LWJGLUtil; +import org.lwjgl.BufferUtils; import org.lwjgl.input.Cursor; final class WindowsDisplay implements DisplayImplementation { @@ -85,7 +86,10 @@ final class WindowsDisplay implements DisplayImplementation { private final static int SC_CONTEXTHELP = 0xF180; private final static int SC_SEPARATOR = 0xF00F; - private final static int SM_CXCURSOR = 13; + final static int SM_CXCURSOR = 13; + final static int SM_CYCURSOR = 14; + final static int SM_CMOUSEBUTTONS = 43; + final static int SM_MOUSEWHEELPRESENT = 75; private final static int SIZE_RESTORED = 0; private final static int SIZE_MINIMIZED = 1; @@ -99,9 +103,14 @@ final class WindowsDisplay implements DisplayImplementation { private final static int SW_SHOWDEFAULT = 10; private final static int SW_RESTORE = 9; + private final static IntBuffer rect_buffer = BufferUtils.createIntBuffer(4); + private final static Rect rect = new Rect(); + private final static Rect rect2 = new Rect(); private static WindowsDisplay current_display; + private static boolean cursor_clipped; private WindowsDisplayPeerInfo peer_info; + private Object current_cursor; private WindowsKeyboard keyboard; private WindowsMouse mouse; @@ -141,12 +150,37 @@ final class WindowsDisplay implements DisplayImplementation { public void destroyWindow() { nDestroyWindow(); - if (isFullscreen) - resetCursorClipping(); + resetCursorClipping(); } private static native void nDestroyWindow(); - static native void resetCursorClipping(); - static native void setupCursorClipping(long hwnd) throws LWJGLException; + static void resetCursorClipping() { + if (cursor_clipped) { + try { + clipCursor(0, null); + } catch (LWJGLException e) { + LWJGLUtil.log("Failed to reset cursor clipping: " + e); + } + cursor_clipped = false; + } + } + + private static void getGlobalClientRect(long hwnd, Rect rect) { + rect_buffer.put(0, 0).put(1, 0); + clientToScreen(hwnd, rect_buffer); + int offset_x = rect_buffer.get(0); + int offset_y = rect_buffer.get(1); + getClientRect(hwnd, rect_buffer); + rect.copyFromBuffer(rect_buffer); + rect.offset(offset_x, offset_y); + } + + static void setupCursorClipping(long hwnd) throws LWJGLException { + cursor_clipped = true; + getGlobalClientRect(hwnd, rect); + rect.copyToBuffer(rect_buffer); + clipCursor(hwnd, rect_buffer); + } + private static native void clipCursor(long hwnd, IntBuffer rect) throws LWJGLException; public void switchDisplayMode(DisplayMode mode) throws LWJGLException { nSwitchDisplayMode(mode); @@ -330,11 +364,12 @@ final class WindowsDisplay implements DisplayImplementation { } public void createMouse() throws LWJGLException { - mouse = new WindowsMouse(createDirectInput(), getHwnd()); + mouse = new WindowsMouse(getHwnd()); } public void destroyMouse() { - mouse.destroy(); + if (mouse != null) + mouse.destroy(); mouse = null; } @@ -349,7 +384,12 @@ final class WindowsDisplay implements DisplayImplementation { } public void grabMouse(boolean grab) { - mouse.grab(grab); + mouse.grab(grab, shouldGrab()); + try { + updateCursor(); + } catch (LWJGLException e) { + LWJGLUtil.log("Failed to update cursor: " + e); + } } public int getNativeCursorCapabilities() { @@ -357,11 +397,26 @@ final class WindowsDisplay implements DisplayImplementation { } public void setCursorPosition(int x, int y) { - nSetCursorPosition(x, y, isFullscreen); + getGlobalClientRect(getHwnd(), rect); + int transformed_x = rect.left + x; + int transformed_y = rect.bottom - 1 - y; + nSetCursorPosition(transformed_x, transformed_y); + setMousePosition(x, y); } - private static native void nSetCursorPosition(int x, int y, boolean fullscreen); + private static native void nSetCursorPosition(int x, int y); - public native void setNativeCursor(Object handle) throws LWJGLException; + public void setNativeCursor(Object handle) throws LWJGLException { + current_cursor = handle; + updateCursor(); + } + + private void updateCursor() throws LWJGLException { + if (mouse != null && mouse.isGrabbed()) + nSetNativeCursor(getHwnd(), mouse.getBlankCursor()); + else + nSetNativeCursor(getHwnd(), current_cursor); + } + static native void nSetNativeCursor(long hwnd, Object handle) throws LWJGLException; public int getMinCursorSize() { return getSystemMetrics(SM_CXCURSOR); @@ -371,10 +426,30 @@ final class WindowsDisplay implements DisplayImplementation { return getSystemMetrics(SM_CXCURSOR); } - public native int getSystemMetrics(int index); + static native int getSystemMetrics(int index); private static native long getDllInstance(); private static native long getHwnd(); + private static native long getDesktopWindow(); + static void centerCursor(long hwnd) { + getGlobalClientRect(getHwnd(), rect); + int local_offset_x = rect.left; + int local_offset_y = rect.top; + getGlobalClientRect(getDesktopWindow(), rect2); + Rect.intersect(rect, rect2, rect); + int center_x = (rect.left + rect.right)/2; + int center_y = (rect.top + rect.bottom)/2; + nSetCursorPosition(center_x, center_y); + int local_x = center_x - local_offset_x; + int local_y = center_y - local_offset_y; + if (current_display != null) + current_display.setMousePosition(local_x, transformY(getHwnd(), local_y)); + } + + private void setMousePosition(int x, int y) { + if (mouse != null) + mouse.setPosition(x, y); + } /* Keyboard */ public void createKeyboard() throws LWJGLException { @@ -398,13 +473,21 @@ final class WindowsDisplay implements DisplayImplementation { // public native int isStateKeySet(int key); - public native ByteBuffer nCreateCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, int images_offset, IntBuffer delays, int delays_offset) throws LWJGLException; + public static native ByteBuffer nCreateCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, int images_offset, IntBuffer delays, int delays_offset) throws LWJGLException; public Object createCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException { + return doCreateCursor(width, height, xHotspot, yHotspot, numImages, images, delays); + } + + static Object doCreateCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException { return nCreateCursor(width, height, xHotspot, yHotspot, numImages, images, images.position(), delays, delays != null ? delays.position() : -1); } - public native void destroyCursor(Object cursorHandle); + public void destroyCursor(Object cursorHandle) { + doDestroyCursor(cursorHandle); + } + static native void doDestroyCursor(Object cursorHandle); + public int getPbufferCapabilities() { try { // Return the capabilities of a minimum pixel format @@ -483,9 +566,13 @@ final class WindowsDisplay implements DisplayImplementation { mouse.handleMouseButton((byte)button, (byte)state, millis); } + private boolean shouldGrab() { + return !isMinimized && isFocused; + } + private void handleMouseMoved(int x, int y, long millis) { if (mouse != null) - mouse.handleMouseMoved(x, y, millis); + mouse.handleMouseMoved(x, y, millis, shouldGrab()); } private void handleMouseScrolled(int amount, long millis) { @@ -493,7 +580,15 @@ final class WindowsDisplay implements DisplayImplementation { mouse.handleMouseScrolled(amount, millis); } - private static native int transformY(long hwnd, int y); + private static native void getClientRect(long hwnd, IntBuffer rect); + + private static int transformY(long hwnd, int y) { + getClientRect(hwnd, rect_buffer); + rect.copyFromBuffer(rect_buffer); + return (rect.bottom - rect.top) - 1 - y; + } + + private static native void clientToScreen(long hwnd, IntBuffer point); private static boolean handleMessage(long hwnd, int msg, long wParam, long lParam, long millis) { if (current_display != null) @@ -503,12 +598,14 @@ final class WindowsDisplay implements DisplayImplementation { } private boolean doHandleMessage(long hwnd, int msg, long wParam, long lParam, long millis) { - if (isFullscreen && !isMinimized && isFocused) { + if ((isFullscreen || (mouse != null && mouse.isGrabbed())) && !isMinimized && isFocused) { try { setupCursorClipping(getHwnd()); } catch (LWJGLException e) { LWJGLUtil.log("setupCursorClipping failed: " + e.getMessage()); } + } else { + resetCursorClipping(); } switch (msg) { // disable screen saver and monitor power down messages which wreak havoc @@ -602,4 +699,40 @@ final class WindowsDisplay implements DisplayImplementation { public int getHeight() { return Display.getDisplayMode().getHeight(); } + + private static final class Rect { + public int top; + public int bottom; + public int left; + public int right; + + public void copyToBuffer(IntBuffer buffer) { + buffer.put(0, top).put(1, bottom).put(2, left).put(3, right); + } + + public void copyFromBuffer(IntBuffer buffer) { + top = buffer.get(0); + bottom = buffer.get(1); + left = buffer.get(2); + right = buffer.get(3); + } + + public void offset(int offset_x, int offset_y) { + left += offset_x; + right += offset_x; + top += offset_y; + bottom += offset_y; + } + + public static void intersect(Rect r1, Rect r2, Rect dst) { + dst.top = Math.max(r1.top, r2.top); + dst.bottom = Math.min(r1.bottom, r2.bottom); + dst.left = Math.max(r1.left, r2.left); + dst.right = Math.min(r1.right, r2.right); + } + + public String toString() { + return "Rect: top = " + top + " bottom = " + bottom + " left = " + left + " right = " + right; + } + } } diff --git a/src/java/org/lwjgl/opengl/WindowsMouse.java b/src/java/org/lwjgl/opengl/WindowsMouse.java index e82575ea..b0d1e0f1 100644 --- a/src/java/org/lwjgl/opengl/WindowsMouse.java +++ b/src/java/org/lwjgl/opengl/WindowsMouse.java @@ -44,63 +44,44 @@ import org.lwjgl.LWJGLException; import org.lwjgl.LWJGLUtil; import org.lwjgl.BufferUtils; import org.lwjgl.input.Mouse; +import org.lwjgl.input.Cursor; final class WindowsMouse { - private final static int BUFFER_SIZE = 50; - private final static int BUTTON_STATES_SIZE = 7; - - private final static int DIMOFS_X = 0; - private final static int DIMOFS_Y = 4; - private final static int DIMOFS_Z = 8; - private final static int DIMOFS_BUTTON0 = 12; - private final static int DIMOFS_BUTTON1 = 13; - private final static int DIMOFS_BUTTON2 = 14; - private final static int DIMOFS_BUTTON3 = 15; - private final long hwnd; - private final WindowsDirectInput dinput; - private final WindowsDirectInputDevice mouse; private final int mouse_button_count; private final boolean has_wheel; private final EventQueue event_queue = new EventQueue(Mouse.EVENT_SIZE); - /* Buffer to hold a DIMOUSESTATE */ - private final ByteBuffer mouse_state; - private final IntBuffer temp_data_buffer; private final ByteBuffer mouse_event = ByteBuffer.allocate(Mouse.EVENT_SIZE); + private final Object blank_cursor; private boolean mouse_grabbed; - private byte[] win32_message_button_states = new byte[BUTTON_STATES_SIZE]; + private byte[] button_states; + private int accum_dx; + private int accum_dy; private int accum_dwheel; private int last_x; private int last_y; - public WindowsMouse(WindowsDirectInput dinput, long hwnd) throws LWJGLException { + public WindowsMouse(long hwnd) throws LWJGLException { this.hwnd = hwnd; - this.dinput = dinput; - try { - mouse = dinput.createDevice(WindowsDirectInput.MOUSE_TYPE); - try { - mouse.setDataFormat(WindowsDirectInput.MOUSE_TYPE); - mouse.setBufferSize(BUFFER_SIZE); - if (!acquireNonExclusive()) - throw new LWJGLException("Failed to acquire mouse non-exclusive"); - } catch (LWJGLException e) { - mouse.release(); - throw e; - } - } catch (LWJGLException e) { - dinput.release(); - throw e; - } - MouseEnumerator enumerator = new MouseEnumerator(); - mouse.enumObjects(enumerator); - this.mouse_button_count = Math.min(enumerator.getButtonCount(), 4); - this.has_wheel = enumerator.hasWheel(); - mouse_state = BufferUtils.createByteBuffer(3*4 + 4); - temp_data_buffer = BufferUtils.createIntBuffer(BUFFER_SIZE*WindowsDirectInputDevice.DATA_SIZE); + this.mouse_button_count = WindowsDisplay.getSystemMetrics(WindowsDisplay.SM_CMOUSEBUTTONS); + this.has_wheel = WindowsDisplay.getSystemMetrics(WindowsDisplay.SM_MOUSEWHEELPRESENT) != 0; + this.blank_cursor = createBlankCursor(); + this.button_states = new byte[mouse_button_count]; + } + + private Object createBlankCursor() throws LWJGLException { + int width = WindowsDisplay.getSystemMetrics(WindowsDisplay.SM_CXCURSOR); + int height = WindowsDisplay.getSystemMetrics(WindowsDisplay.SM_CYCURSOR); + IntBuffer pixels = BufferUtils.createIntBuffer(width*height); + return WindowsDisplay.doCreateCursor(width, height, 0, 0, 1, pixels, null); + } + + public boolean isGrabbed() { + return mouse_grabbed; } public boolean hasWheel() { @@ -111,73 +92,24 @@ final class WindowsMouse { return mouse_button_count; } - private boolean acquire(int flags) { - try { - mouse.setCooperateLevel(hwnd, flags); - mouse.acquire(); - return true; - } catch (LWJGLException e) { - LWJGLUtil.log("Failed to acquire mouse: " + e); - return false; - } - } - - private boolean acquireNonExclusive() { - return acquire(WindowsDirectInputDevice.DISCL_NONEXCLUSIVE | WindowsDirectInputDevice.DISCL_FOREGROUND) || - acquire(WindowsDirectInputDevice.DISCL_NONEXCLUSIVE | WindowsDirectInputDevice.DISCL_BACKGROUND); - } - - public void destroy() { - mouse.unacquire(); - mouse.release(); - dinput.release(); - } - public void poll(IntBuffer coord_buffer, ByteBuffer buttons) { - int ret = mouse.acquire(); - if (ret != WindowsDirectInput.DI_OK && ret != WindowsDirectInput.DI_NOEFFECT) - return; - mouse.poll(); for (int i = 0; i < coord_buffer.remaining(); i++) coord_buffer.put(coord_buffer.position() + i, 0); - mouse_state.clear(); - ret = mouse.getDeviceState(mouse_state); - int mouse_state_lx = mouse_state.getInt(); - int mouse_state_ly = mouse_state.getInt(); - int mouse_state_lz = mouse_state.getInt(); int num_buttons = mouse_button_count; - if (mouse_grabbed || ret == WindowsDirectInput.DI_OK) { - if (ret != WindowsDirectInput.DI_OK) { - LWJGLUtil.log("Error getting mouse state: (0x" + Integer.toHexString(ret) + ")"); - return; - } - - coord_buffer.put(coord_buffer.position() + 2, mouse_state_lz); - if (num_buttons > buttons.remaining()) - num_buttons = buttons.remaining(); - for (int j = 0; j < num_buttons; j++) { - byte button_state = (mouse_state.get() & 0x80) != 0 ? (byte)1 : (byte)0; - buttons.put(buttons.position() + j, button_state); - // track the button state in the windows message buffer state array - // to get accurate button information when releasing a grab - win32_message_button_states[j] = button_state; - } - } else { - coord_buffer.put(coord_buffer.position() + 2, accum_dwheel); - if (num_buttons > win32_message_button_states.length) - num_buttons = win32_message_button_states.length; - for (int j = 0; j < num_buttons; j++) { - buttons.put(buttons.position() + j, win32_message_button_states[j]); - } + coord_buffer.put(coord_buffer.position() + 2, accum_dwheel); + if (num_buttons > button_states.length) + num_buttons = button_states.length; + for (int j = 0; j < num_buttons; j++) { + buttons.put(buttons.position() + j, button_states[j]); } - accum_dwheel = 0; - if (mouse_grabbed) { - coord_buffer.put(coord_buffer.position() + 0, mouse_state_lx); - coord_buffer.put(coord_buffer.position() + 1, -mouse_state_ly); + if (isGrabbed()) { + coord_buffer.put(coord_buffer.position() + 0, accum_dx); + coord_buffer.put(coord_buffer.position() + 1, accum_dy); } else { coord_buffer.put(coord_buffer.position() + 0, last_x); coord_buffer.put(coord_buffer.position() + 1, last_y); } + accum_dx = accum_dy = accum_dwheel = 0; } private void putMouseEventWithCoords(byte button, byte state, int coord1, int coord2, int dz, long nanos) { @@ -194,104 +126,30 @@ final class WindowsMouse { putMouseEventWithCoords(button, state, last_x, last_y, dz, nanos); } - private void copyDXEvents(IntBuffer buffer) { - int buffer_index = 0; - int dx = 0, dy = 0, dwheel = 0; - byte button_state; - int i; - long nanos = 0; - while (buffer.hasRemaining()) { - int dwOfs = buffer.get(); - int dwData = buffer.get(); - long dwTimeStamp = ((long)buffer.get()) & 0xFFFFFFFF; - nanos = dwTimeStamp*1000000; - button_state = (dwData & 0x80) != 0 ? (byte)1 : (byte)0; - switch (dwOfs) { - case DIMOFS_BUTTON0: - putMouseEventWithCoords((byte)0, button_state, dx, -dy, dwheel, nanos); - dx = dy = dwheel = 0; - break; - case DIMOFS_BUTTON1: - putMouseEventWithCoords((byte)1, button_state, dx, -dy, dwheel, nanos); - dx = dy = dwheel = 0; - break; - case DIMOFS_BUTTON2: - putMouseEventWithCoords((byte)2, button_state, dx, -dy, dwheel, nanos); - dx = dy = dwheel = 0; - break; - case DIMOFS_BUTTON3: - putMouseEventWithCoords((byte)3, button_state, dx, -dy, dwheel, nanos); - dx = dy = dwheel = 0; - break; - case DIMOFS_X: - dx += dwData; - break; - case DIMOFS_Y: - dy += dwData; - break; - case DIMOFS_Z: - dwheel += dwData; - break; - } - } - if (dx != 0 || dy != 0 || dwheel != 0) - putMouseEventWithCoords((byte)-1, (byte)0, dx, -dy, dwheel, nanos); - } - - private void readDXBuffer() { - int ret = mouse.acquire(); - if (ret != WindowsDirectInput.DI_OK && ret != WindowsDirectInput.DI_NOEFFECT) - return; - mouse.poll(); - temp_data_buffer.clear(); - ret = mouse.getDeviceData(temp_data_buffer); - - 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) { + + public Object getBlankCursor() { + return blank_cursor; + } + + public void grab(boolean grab, boolean should_center) { + if (grab) { if (!mouse_grabbed) { - flush(); mouse_grabbed = true; - mouse.unacquire(); - if (!acquire(WindowsDirectInputDevice.DISCL_EXCLUSIVE | WindowsDirectInputDevice.DISCL_FOREGROUND)) - LWJGLUtil.log("Failed to reset cooperative mode"); + try { + WindowsDisplay.setupCursorClipping(hwnd); + } catch (LWJGLException e) { + LWJGLUtil.log("Failed to setup cursor clipping: " + e); + } + if (should_center) + centerCursor(); } } else { if (mouse_grabbed) { mouse_grabbed = false; - mouse.unacquire(); - acquireNonExclusive(); + WindowsDisplay.resetCursorClipping(); } } event_queue.clearEvents(); @@ -302,52 +160,41 @@ final class WindowsMouse { putMouseEvent((byte)-1, (byte)0, event_dwheel, millis*1000000); } - public void handleMouseMoved(int x, int y, long millis) { - int dx; - int dy; - dx = x - last_x; - dy = y - last_y; - last_x = x; - last_y = y; - long nanos = millis*1000000; - if (mouse_grabbed) { - putMouseEventWithCoords((byte)-1, (byte)0, dx, dy, 0, nanos); - } else { - putMouseEventWithCoords((byte)-1, (byte)0, x, y, 0, nanos); - } + private void centerCursor() { + WindowsDisplay.centerCursor(hwnd); + } + + public void setPosition(int x, int y) { + this.last_x = x; + this.last_y = y; + } + + public void destroy() { + WindowsDisplay.doDestroyCursor(blank_cursor); + } + + public void handleMouseMoved(int x, int y, long millis, boolean should_center) { + int dx = x - last_x; + int dy = y - last_y; + if (dx != 0 || dy != 0) { + accum_dx += dx; + accum_dy += dy; + last_x = x; + last_y = y; + long nanos = millis*1000000; + if (mouse_grabbed) { + putMouseEventWithCoords((byte)-1, (byte)0, dx, dy, 0, nanos); + if (should_center) + centerCursor(); + } else { + putMouseEventWithCoords((byte)-1, (byte)0, x, y, 0, nanos); + } + } } public void handleMouseButton(byte button, byte state, long millis) { putMouseEvent(button, state, 0, millis*1000000); - if (button < BUTTON_STATES_SIZE) - win32_message_button_states[button] = state != 0 ? (byte)1 : (byte)0; - } - - private static class MouseEnumerator implements WindowsDirectInputDeviceObjectCallback { - private int button_count; - private boolean has_wheel; - - public int getButtonCount() { - return button_count; - } - - public boolean hasWheel() { - return has_wheel; - } - - public boolean nextObject(int type, String name) { - LWJGLUtil.log("Found mouse object: " + name); - switch (type) { - case WindowsDirectInputDevice.GUID_ZAxis: - has_wheel = true; - break; - case WindowsDirectInputDevice.GUID_Button: - button_count++; - break; - default: - break; - } - return true; - } + if (button < button_states.length) + button_states[button] = state != 0 ? (byte)1 : (byte)0; } } diff --git a/src/native/common/common_tools.c b/src/native/common/common_tools.c index d17b1cae..f63e68d2 100644 --- a/src/native/common/common_tools.c +++ b/src/native/common/common_tools.c @@ -141,6 +141,13 @@ void throwFMODException(JNIEnv * env, const char * err) { throwGeneralException(env, "org/lwjgl/fmod3/FMODException", err); } +void throwFormattedRuntimeException(JNIEnv * env, const char *format, ...) { + va_list ap; + va_start(ap, format); + throwFormattedGeneralException(env, "java/lang/RuntimeException", format, ap); + va_end(ap); +} + void throwFormattedException(JNIEnv * env, const char *format, ...) { va_list ap; va_start(ap, format); diff --git a/src/native/common/common_tools.h b/src/native/common/common_tools.h index a5d0925a..fd04049d 100644 --- a/src/native/common/common_tools.h +++ b/src/native/common/common_tools.h @@ -130,6 +130,7 @@ extern void putAttrib(attrib_list_t *list, int attrib); extern bool isDebugEnabled(void); extern jstring getVersionString(JNIEnv *env); extern void throwGeneralException(JNIEnv * env, const char *exception_name, const char * err); +extern void throwFormattedRuntimeException(JNIEnv * env, const char *format, ...); extern void throwException(JNIEnv *env, const char *msg); extern void throwFormattedException(JNIEnv * env, const char *format, ...); extern void throwFMODException(JNIEnv * env, const char * err); diff --git a/src/native/windows/org_lwjgl_input_Cursor.c b/src/native/windows/org_lwjgl_input_Cursor.c index 08351f5a..4371e706 100644 --- a/src/native/windows/org_lwjgl_input_Cursor.c +++ b/src/native/windows/org_lwjgl_input_Cursor.c @@ -45,7 +45,7 @@ #include "common_tools.h" JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_WindowsDisplay_nCreateCursor -(JNIEnv *env, jobject self, jint width, jint height, jint x_hotspot, jint y_hotspot, jint num_images, jobject image_buffer, jint images_offset, jobject delay_buffer, jint delays_offset) +(JNIEnv *env, jclass unused, jint width, jint height, jint x_hotspot, jint y_hotspot, jint num_images, jobject image_buffer, jint images_offset, jobject delay_buffer, jint delays_offset) { unsigned char col0, col1, col2, col3, col4, col5, col6, col7; unsigned char mask; @@ -154,8 +154,8 @@ JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_WindowsDisplay_nCreateCursor return handle_buffer; } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_WindowsDisplay_destroyCursor -(JNIEnv *env, jobject self, jobject handle_buffer) +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_WindowsDisplay_doDestroyCursor +(JNIEnv *env, jclass unused, jobject handle_buffer) { HCURSOR *cursor_handle = (HCURSOR *)(*env)->GetDirectBufferAddress(env, handle_buffer); DestroyCursor(*cursor_handle); diff --git a/src/native/windows/org_lwjgl_opengl_Display.c b/src/native/windows/org_lwjgl_opengl_Display.c index 3746894d..5530457a 100644 --- a/src/native/windows/org_lwjgl_opengl_Display.c +++ b/src/native/windows/org_lwjgl_opengl_Display.c @@ -210,17 +210,63 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_WindowsDisplay_nDestroyWindow(JNIEn freeSmallIcon(); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_WindowsDisplay_resetCursorClipping(JNIEnv *env, jclass unused) { - ClipCursor(NULL); +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_WindowsDisplay_clientToScreen(JNIEnv *env, jclass unused, jlong hwnd_int, jobject buffer_handle) { + HWND hwnd = (HWND)(INT_PTR)hwnd_int; + POINT point; + jint *buffer = (jint *)(*env)->GetDirectBufferAddress(env, buffer_handle); + jlong size = (*env)->GetDirectBufferCapacity(env, buffer_handle); + if (size < 2) { + throwFormattedRuntimeException(env, "Buffer size < 2", size); + return; + } + point.x = buffer[0]; + point.y = buffer[1]; + ClientToScreen(hwnd, &point); + buffer[0] = point.x; + buffer[1] = point.y; } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_WindowsDisplay_setupCursorClipping(JNIEnv *env, jclass unused, jlong hwnd_ptr) { - HWND hwnd = (HWND)(INT_PTR)hwnd_ptr; - RECT hwnd_client; - if (hwnd != NULL && GetWindowRect(hwnd, &hwnd_client) != 0) { - if (ClipCursor(&hwnd_client) == 0) - throwFormattedException(env, "ClipCursor failed (%d)", GetLastError()); +JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_WindowsDisplay_getDesktopWindow(JNIEnv *env, jclass unused) { + return (INT_PTR)GetDesktopWindow(); +} + +static void copyBufferToRect(JNIEnv *env, jobject buffer_handle, RECT *rect) { + jint *buffer = (jint *)(*env)->GetDirectBufferAddress(env, buffer_handle); + jlong size = (*env)->GetDirectBufferCapacity(env, buffer_handle); + if (size < 4) { + throwFormattedRuntimeException(env, "Buffer size < 4", size); + return; } + rect->top = buffer[0]; + rect->bottom = buffer[1]; + rect->left = buffer[2]; + rect->right = buffer[3]; +} + +static void copyRectToBuffer(JNIEnv *env, RECT *rect, jobject buffer_handle) { + jint *buffer = (jint *)(*env)->GetDirectBufferAddress(env, buffer_handle); + jlong size = (*env)->GetDirectBufferCapacity(env, buffer_handle); + if (size < 4) { + throwFormattedRuntimeException(env, "Buffer size < 4", size); + return; + } + buffer[0] = rect->top; + buffer[1] = rect->bottom; + buffer[2] = rect->left; + buffer[3] = rect->right; +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_WindowsDisplay_clipCursor(JNIEnv *env, jclass unused, jlong hwnd_ptr, jobject handle_buffer) { + HWND hwnd = (HWND)(INT_PTR)hwnd_ptr; + RECT clip_rect; + LPRECT clip_rect_ptr; + if (handle_buffer != NULL) { + copyBufferToRect(env, handle_buffer, &clip_rect); + clip_rect_ptr = &clip_rect; + } else + clip_rect_ptr = NULL; + if (ClipCursor(clip_rect_ptr) == 0) + throwFormattedException(env, "ClipCursor failed (%d)", GetLastError()); } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_WindowsDisplay_nSwitchDisplayMode(JNIEnv *env, jobject self, jobject mode) { @@ -452,64 +498,36 @@ JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_WindowsDisplay_nSetWindowIcon32 } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_WindowsDisplay_nSetCursorPosition -(JNIEnv * env, jclass unused, jint x, jint y, jboolean fullscreen) { - DWORD windowflags, exstyle; - int transformed_x, transformed_y; - RECT window_rect; - RECT client_rect; - RECT adjusted_client_rect; - - int left_border_width; - int bottom_border_width; - - getWindowFlags(&windowflags, &exstyle, fullscreen, getBooleanProperty(env, "org.lwjgl.opengl.Window.undecorated")); - if (!GetClientRect(getCurrentHWND(), &client_rect)) { - printfDebugJava(env, "GetClientRect failed"); - return; - } - - adjusted_client_rect = client_rect; - if (!AdjustWindowRectEx(&adjusted_client_rect, windowflags, FALSE, exstyle)) { - printfDebugJava(env, "AdjustWindowRectEx failed"); - return; - } - - if (!GetWindowRect(getCurrentHWND(), &window_rect)) { - printfDebugJava(env, "GetWindowRect failed"); - return; - } - left_border_width = -adjusted_client_rect.left; - bottom_border_width = adjusted_client_rect.bottom - client_rect.bottom; - - transformed_x = window_rect.left + left_border_width + x; - transformed_y = window_rect.bottom - bottom_border_width - 1 - y; - if (!SetCursorPos(transformed_x, transformed_y)) +(JNIEnv * env, jclass unused, jint x, jint y) { + if (!SetCursorPos(x, y)) printfDebugJava(env, "SetCursorPos failed"); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_WindowsDisplay_setNativeCursor - (JNIEnv *env, jobject self, jobject handle_buffer) +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_WindowsDisplay_getClientRect + (JNIEnv *env, jclass unused, jlong hwnd_int, jobject rect_buffer) { + HWND hwnd = (HWND)(INT_PTR)hwnd_int; + RECT clientRect; + GetClientRect(hwnd, &clientRect); + copyRectToBuffer(env, &clientRect, rect_buffer); +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_WindowsDisplay_nSetNativeCursor + (JNIEnv *env, jclass unused, jlong hwnd_int, jobject handle_buffer) { + HWND hwnd = (HWND)(INT_PTR)hwnd_int; HCURSOR *cursor_handle; HCURSOR cursor; if (handle_buffer != NULL) { cursor_handle = (HCURSOR *)(*env)->GetDirectBufferAddress(env, handle_buffer); cursor = *cursor_handle; - SetClassLongPtr(getCurrentHWND(), GCL_HCURSOR, (LONG_PTR)cursor); + SetClassLongPtr(hwnd, GCL_HCURSOR, (LONG_PTR)cursor); SetCursor(cursor); } else { - SetClassLongPtr(getCurrentHWND(), GCL_HCURSOR, (LONG_PTR)NULL); + SetClassLongPtr(hwnd, GCL_HCURSOR, (LONG_PTR)NULL); SetCursor(LoadCursor(NULL, IDC_ARROW)); } } -JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_WindowsDisplay_transformY(JNIEnv *env, jclass unused, jlong hwnd_int, jint y) { - HWND hwnd = (HWND)(INT_PTR)hwnd_int; - RECT clientRect; - GetClientRect(hwnd, &clientRect); - return (clientRect.bottom - clientRect.top) - 1 - y; -} - JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_WindowsDisplay_getSystemMetrics(JNIEnv *env, jclass unused, jint index) { return GetSystemMetrics(index); }