diff --git a/src/java/org/lwjgl/input/Mouse.java b/src/java/org/lwjgl/input/Mouse.java index 83d1e9fc..08364700 100644 --- a/src/java/org/lwjgl/input/Mouse.java +++ b/src/java/org/lwjgl/input/Mouse.java @@ -32,8 +32,6 @@ package org.lwjgl.input; -import java.nio.ByteBuffer; - import org.lwjgl.Display; import org.lwjgl.Sys; @@ -59,7 +57,7 @@ public class Mouse { private static boolean created; /** The mouse buttons status from the last poll */ - private static boolean[] button = new boolean[8]; + private static boolean[] buttons; /** Delta X */ public static int dx; @@ -68,22 +66,11 @@ public class Mouse { public static int dy; /** Delta Z */ - public static int dz; - - /** - * The mouse events from the last read: a sequence of Events - */ - private static ByteBuffer readBuffer; - - /** Address of the read buffer */ - private static int readBufferAddress; - - /** The size in bytes of a single mouse event */ - private static final int MOUSE_EVENT_SIZE = 20; - - /** The stride in bytes of a single mouse event */ - private static final int MOUSE_EVENT_STRIDE = 32; - + public static int dwheel; + + /* Mouse capabilities */ + public static int buttonCount = -1; + public static boolean hasWheel = false; /** * Mouse cannot be constructed. @@ -152,109 +139,15 @@ public class Mouse { * Native method to poll the mouse */ private static native void nPoll(); - - /** - * Queries the number of buttons the mouse has - * @return the number of buttons the mouse has - */ - public static int getNumButtons() { - assert created : "The mouse has not been created."; - return nGetNumButtons(); - } - - /** - * Native implementation of getNumButtons() - */ - private static native int nGetNumButtons(); - - /** - * Queries whether the mouse has a Z value - * @return true if the mouse has a Z value - */ - public static boolean hasZValue() { - assert created : "The mouse has not been created."; - return nHasZValue(); - } - - /** - * Native implementation of hasZValue() - */ - private static native boolean nHasZValue(); /** * See if a particular mouse button is down. * - * @param button The index of the button you wish to test (0..getNumButtons()) + * @param button The index of the button you wish to test (0..buttonCount) * @return true if the specified button is down - * @see #getNumButtons() */ public static boolean isButtonDown(int button) { assert created : "The mouse has not been created."; - return Mouse.button[button]; + return Mouse.buttons[button]; } - -// /** -// * Enable mouse buffering. Must be called after the mouse is created. -// * @return the size of the mouse buffer in events, or 0 if no buffering -// * can be enabled for any reason -// */ -// public static int enableBuffer() { -// assert created : "The mouse has not been created."; -// return nEnableBuffer(); -// } -// -// -// /** -// * Native method to enable the buffer -// * @return the size of the buffer allocated, in events (1 event is 2 bytes), -// * or 0 if no buffer can be allocated -// */ -// private static native int nEnableBuffer(); - - - /** - * Gets the next mouse event. This returns its results as if a poll() had - * been called. - * - * @return true if a mouse event was read, false otherwise - */ - public static boolean next() { - assert created : "The mouse has not been created."; - assert readBuffer != null : "Mouse buffering has not been enabled."; - - if (readBuffer.hasRemaining()) { - dx = readBuffer.getInt(); - dy = readBuffer.getInt(); - dz = readBuffer.getInt(); - for (int i = 0; i < button.length; i ++) - button[i] = readBuffer.get() != (byte)0; - readBuffer.position(readBuffer.position() + (MOUSE_EVENT_STRIDE - MOUSE_EVENT_SIZE)); - return true; - } else - return false; - - } - - - /** - * Native method to read the gamepad buffer - * - * @param readBufferAddress the address of the mouse buffer - * @return the number of mouse events read - */ - private static native int nRead(int readBufferAddress); - - - /** - * Reads the mouse buffer. - */ - public static void read() { - assert created : "The mouse has not been created."; - assert readBuffer != null : "Mouse buffering has not been enabled."; - readBuffer.clear(); - readBuffer.limit(nRead(readBufferAddress) * MOUSE_EVENT_SIZE); - } - - - -} +} \ No newline at end of file diff --git a/src/native/common/org_lwjgl_input_Mouse.h b/src/native/common/org_lwjgl_input_Mouse.h index 7d006a6e..7e3e3cfd 100644 --- a/src/native/common/org_lwjgl_input_Mouse.h +++ b/src/native/common/org_lwjgl_input_Mouse.h @@ -9,16 +9,12 @@ extern "C" { #endif /* Inaccessible static: _00024assertionsDisabled */ /* Inaccessible static: created */ -/* Inaccessible static: button */ +/* Inaccessible static: buttons */ /* Inaccessible static: dx */ /* Inaccessible static: dy */ -/* Inaccessible static: dz */ -/* Inaccessible static: readBuffer */ -/* Inaccessible static: readBufferAddress */ -#undef org_lwjgl_input_Mouse_MOUSE_EVENT_SIZE -#define org_lwjgl_input_Mouse_MOUSE_EVENT_SIZE 20L -#undef org_lwjgl_input_Mouse_MOUSE_EVENT_STRIDE -#define org_lwjgl_input_Mouse_MOUSE_EVENT_STRIDE 32L +/* Inaccessible static: dwheel */ +/* Inaccessible static: buttonCount */ +/* Inaccessible static: hasWheel */ /* Inaccessible static: class_000240 */ /* * Class: org_lwjgl_input_Mouse @@ -52,38 +48,6 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nDestroy JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nPoll (JNIEnv *, jclass); -/* - * Class: org_lwjgl_input_Mouse - * Method: nGetNumButtons - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_org_lwjgl_input_Mouse_nGetNumButtons - (JNIEnv *, jclass); - -/* - * Class: org_lwjgl_input_Mouse - * Method: nHasZValue - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Mouse_nHasZValue - (JNIEnv *, jclass); - -/* - * Class: org_lwjgl_input_Mouse - * Method: nEnableBuffer - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_org_lwjgl_input_Mouse_nEnableBuffer - (JNIEnv *, jclass); - -/* - * Class: org_lwjgl_input_Mouse - * Method: nRead - * Signature: (I)I - */ -JNIEXPORT jint JNICALL Java_org_lwjgl_input_Mouse_nRead - (JNIEnv *, jclass, jint); - #ifdef __cplusplus } #endif diff --git a/src/native/win32/org_lwjgl_input_Mouse.cpp b/src/native/win32/org_lwjgl_input_Mouse.cpp index 5bbe5021..b451a99a 100644 --- a/src/native/win32/org_lwjgl_input_Mouse.cpp +++ b/src/native/win32/org_lwjgl_input_Mouse.cpp @@ -1,5 +1,5 @@ -/* - * Copyright (c) 2002 Light Weight Java Game Library Project +/* + * Copyright (c) 2002 Lightweight Java Game Library Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -16,8 +16,7 @@ * * Neither the name of 'Light Weight Java Game Library' 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 + * * 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 @@ -35,107 +34,112 @@ * * Win32 mouse handling. * - * @author cix_foo + * @author Brian Matzon * @version $Revision$ */ - #define WIN32_LEAN_AND_MEAN - -#include #include "org_lwjgl_input_Mouse.h" +#include #undef DIRECTINPUT_VERSION #define DIRECTINPUT_VERSION 0x0300 #include -extern LPDIRECTINPUT lpdi; -LPDIRECTINPUTDEVICE lpdiMouse; -extern HWND hwnd; // The display, which must have been created -jfieldID fid_button; -jfieldID fid_dx; -jfieldID fid_dy; -jfieldID fid_dz; +extern HINSTANCE dll_handle; -/* - * Class: org_lwjgl_input_Mouse - * Method: initIDs - * Signature: ()V +extern HWND hwnd; // Handle to window + +extern LPDIRECTINPUT lpdi; // DI instance +LPDIRECTINPUTDEVICE mDIDevice; // DI Device instance +DIMOUSESTATE diMouseState; // State of Mouse + +int mButtoncount = 0; // Temporary buttoncount +bool mHaswheel; // Temporary wheel check + +JNIEnv* mEnvironment; // JNIEnvironment copy + +bool mCreate_success; // bool used to determine successfull creation + +// Cached fields of Mouse.java +jclass clsMouse; +jfieldID fidMButtonCount; +jfieldID fidMButtons; +jfieldID fidMDX; +jfieldID fidMDY; +jfieldID fidMDWheel; +jfieldID fidMHasWheel; + +// Function prototypes (defined in the cpp file, since header file is generic across platforms +void EnumerateMouseCapabilities(); +BOOL CALLBACK EnumMouseObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef); +void ShutdownMouse(); +void CreateMouse(); +void SetupMouse(); +void InitializeMouseFields(); +void CacheMouseFields(); +void UpdateMouseFields(); +void SetMouseCapabilities(); + +/** + * Initializes any field ids */ -JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_initIDs - (JNIEnv * env, jclass clazz) -{ - // Get a global class instance, just to be sure - static jobject globalClassLock = NULL; +JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_initIDs(JNIEnv * env, jclass clazz) { + mEnvironment = env; + clsMouse = clazz; - if (globalClassLock == NULL) { - globalClassLock = env->NewGlobalRef(clazz); - } - - // Now cache the field IDs: - if (fid_button == NULL) { - fid_button = env->GetStaticFieldID(clazz, "button", "[Z"); - } - if (fid_dx == NULL) { - fid_dx = env->GetStaticFieldID(clazz, "dx", "I"); - } - if (fid_dy == NULL) { - fid_dy = env->GetStaticFieldID(clazz, "dy", "I"); - } - if (fid_dz == NULL) { - fid_dz = env->GetStaticFieldID(clazz, "dz", "I"); - } + /* Cache fields in Mouse */ + CacheMouseFields(); } -/* - * Class: org_lwjgl_input_Mouse - * Method: nCreate - * Signature: ()Z +/** + * Called when the Mouse instance is to be created */ -JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Mouse_nCreate - (JNIEnv * env, jclass clazz) -{ - // Check to see if we're already initialized - if (lpdiMouse != NULL) { - printf("Mouse already created.\n"); - return JNI_FALSE; - } - - if (hwnd == NULL) { - printf("No window\n"); - return JNI_FALSE; - } - - // First get reference to directinput: - if (lpdi == NULL) { - HRESULT ret = DirectInputCreate((HINSTANCE)GetCurrentProcess(), DIRECTINPUT_VERSION, &lpdi, NULL); - if (ret != DI_OK && ret != DIERR_BETADIRECTINPUTVERSION ) { - printf("Failed to create directinput\n"); - return JNI_FALSE; - } - } - - // Get mouse device - if (lpdi->CreateDevice(GUID_SysMouse, &lpdiMouse, NULL) != DI_OK) { - printf("Failed to create mouse\n"); - return JNI_FALSE; - } - - // Grab non-exclusive foreground access to device - if (lpdiMouse->SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND) != DI_OK) { - printf("Failed to set mouse coop\n"); - return JNI_FALSE; - } - - // Tell 'em wot format to be in (the default "you are a mouse and keyboard" format) - lpdiMouse->SetDataFormat(&c_dfDIMouse); - - HRESULT ret = lpdiMouse->Acquire(); - if (ret != DI_OK && ret != S_FALSE) { -#ifdef _DEBUG - printf("Failed to acquire mouse\n"); +JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Mouse_nCreate(JNIEnv *env, jclass clazz) { + // Create the DirectInput object. + HRESULT hr; + hr = DirectInputCreate(dll_handle, DIRECTINPUT_VERSION, &lpdi, NULL); + if (FAILED(hr)) { +#if _DEBUG + printf("DirectInputCreate failed\n"); #endif - } - return JNI_TRUE; + ShutdownMouse(); + return JNI_FALSE; + } + + /* skip enumeration, since we only want system mouse */ + CreateMouse(); + + /* Enumerate capabilities of Mouse */ + EnumerateMouseCapabilities(); + if (!mCreate_success) { +#if _DEBUG + printf("EnumerateMouseCapabilities failed\n"); +#endif + ShutdownMouse(); + return JNI_FALSE; + } + + if(mCreate_success) { + /* Do setup of Mouse */ + SetupMouse(); + } + + /* Initialize any fields on the Mouse */ + InitializeMouseFields(); + + /* Set capabilities */ + SetMouseCapabilities(); + + /* Aquire the Mouse */ + hr = mDIDevice->Acquire(); + if(FAILED(hr)) { +#if _DEBUG + printf("Acquire failed\n"); +#endif + ShutdownMouse(); + return JNI_FALSE; + } + return mCreate_success; } /* @@ -143,51 +147,174 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Mouse_nCreate * Method: nDestroy * Signature: ()V */ -JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nDestroy - (JNIEnv * env, jclass clazz) -{ - - // Release mouse - if (lpdiMouse != NULL) { - lpdiMouse->Unacquire(); - lpdiMouse->Release(); - lpdiMouse = NULL; - } - +JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nDestroy(JNIEnv *env, jclass clazz) { + ShutdownMouse(); } /* - * Class: org_lwjgl_input_Mouse + * Class: org_lwjgl_input_Controller * Method: nPoll * Signature: ()V */ -JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nPoll - (JNIEnv * env, jclass clazz) -{ - DIMOUSESTATE diMouseState; - HRESULT ret; - while (ret = lpdiMouse->GetDeviceState(sizeof(diMouseState), &diMouseState) != DI_OK) { - ret = lpdiMouse->Acquire(); - if (ret != DI_OK && ret != S_FALSE) { - return; - } - } - - if (ret == DI_OK) { - env->SetStaticIntField(clazz, fid_dx, (jint)diMouseState.lX); - env->SetStaticIntField(clazz, fid_dy, (jint)diMouseState.lY); - env->SetStaticIntField(clazz, fid_dz, (jint)diMouseState.lZ); - jbooleanArray buttonsArray = (jbooleanArray) env->GetStaticObjectField(clazz, fid_button); - for (int i = 0; i < 4; i++) - if (diMouseState.rgbButtons[i] != 0) - diMouseState.rgbButtons[i] = JNI_TRUE; - else - diMouseState.rgbButtons[i] = JNI_FALSE; - env->SetBooleanArrayRegion(buttonsArray, 0, 4, diMouseState.rgbButtons); - } else { -#ifdef _DEBUG - printf("Failed to get mouse device state\n"); -#endif - } - +JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nPoll(JNIEnv * env, jclass clazz) { + UpdateMouseFields(); } + +/** + * Shutdown DI + */ +void ShutdownMouse() { + // release device + if (mDIDevice != NULL) { + mDIDevice->Unacquire(); + mDIDevice->Release(); + } +} +/** + * Enumerates the capabilities of the Mouse attached to the system + */ +void EnumerateMouseCapabilities() { + HRESULT hr; + hr = mDIDevice->EnumObjects(EnumMouseObjectsCallback, NULL, DIDFT_ALL); + if FAILED(hr) { +#if _DEBUG + printf("EnumObjects failed\n"); +#endif + mCreate_success = false; + return; + } + mCreate_success = true; +} + +/** + * Callback from EnumObjects. Called for each "object" on the Mouse. + */ +BOOL CALLBACK EnumMouseObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) { +#if _DEBUG + printf("found %s\n", lpddoi->tszName); +#endif + if(lpddoi->guidType == GUID_Button) { + mButtoncount++; + } else if(lpddoi->guidType == GUID_XAxis) { + } else if(lpddoi->guidType == GUID_YAxis) { + } else if(lpddoi->guidType == GUID_ZAxis) { + mHaswheel = true; +#if _DEBUG + } else { + printf("Unhandled object found: %s\n", lpddoi->tszName); +#endif + } + return DIENUM_CONTINUE; +} + +/** + * Creates the specified device as a Mouse + */ +void CreateMouse() { + HRESULT hr; + hr = lpdi->CreateDevice(GUID_SysMouse, &mDIDevice, NULL); + if FAILED(hr) { +#if _DEBUG + printf("CreateDevice failed\n"); +#endif + mCreate_success = false; + return; + } + mCreate_success = true; +} + +/** + * Sets up the Mouse properties + */ +void SetupMouse() { + // set Mouse data format + if(mDIDevice->SetDataFormat(&c_dfDIMouse) != DI_OK) { +#if _DEBUG + printf("SetDataFormat failed\n"); +#endif + mCreate_success = false; + return; + } + + // set the cooperative level + if(mDIDevice->SetCooperativeLevel(hwnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND) != DI_OK) { +#if _DEBUG + printf("SetCooperativeLevel failed\n"); +#endif + mCreate_success = false; + return; + } + mCreate_success = true; +} + +/** + * Sets the fields on the Mouse + */ +void InitializeMouseFields() { + //set buttons array + jbooleanArray buttonsArray = mEnvironment->NewBooleanArray(mButtoncount); + mEnvironment->SetStaticObjectField(clsMouse, fidMButtons, buttonsArray); +} + +/** + * Updates the fields on the Mouse + */ +void UpdateMouseFields() { + HRESULT hRes; + + // get data from the Mouse + hRes = mDIDevice->GetDeviceState(sizeof(DIMOUSESTATE), &diMouseState); + + if (hRes != DI_OK) { + // did the read fail because we lost input for some reason? + // if so, then attempt to reacquire. + if(hRes == DIERR_INPUTLOST || hRes == DIERR_NOTACQUIRED) { + mDIDevice->Acquire(); +#if _DEBUG + printf("DIERR_INPUTLOST, reaquiring input : mCreate_success=%d\n", mCreate_success); +#endif + } else { +#if _DEBUG + printf("Error getting mouse state: %d\n", hRes); +#endif + } + return; + } + + mEnvironment->SetStaticIntField(clsMouse, fidMDX, (jint) diMouseState.lX); + mEnvironment->SetStaticIntField(clsMouse, fidMDY, (jint) diMouseState.lY); + mEnvironment->SetStaticIntField(clsMouse, fidMDWheel, (jint) diMouseState.lZ); + + jbooleanArray buttonsArray = (jbooleanArray) mEnvironment->GetStaticObjectField(clsMouse, fidMButtons); + for (int i = 0; i < mButtoncount; i++) { + if (diMouseState.rgbButtons[i] != 0) { + diMouseState.rgbButtons[i] = JNI_TRUE; + } else { + diMouseState.rgbButtons[i] = JNI_FALSE; + } + } + mEnvironment->SetBooleanArrayRegion(buttonsArray, 0, mButtoncount, diMouseState.rgbButtons); +} + +/** + * Sets the capabilities of the Mouse + */ +void SetMouseCapabilities() { + //set buttoncount + mEnvironment->SetStaticIntField(clsMouse, fidMButtonCount, mButtoncount); + + //set wheel + mEnvironment->SetStaticBooleanField(clsMouse, fidMHasWheel, mHaswheel); +} + +/** + * Caches the field ids for quicker access + */ +void CacheMouseFields() { + fidMButtonCount = mEnvironment->GetStaticFieldID(clsMouse, "buttonCount", "I"); + fidMHasWheel = mEnvironment->GetStaticFieldID(clsMouse, "hasWheel", "Z"); + fidMButtons = mEnvironment->GetStaticFieldID(clsMouse, "buttons", "[Z"); + fidMDX = mEnvironment->GetStaticFieldID(clsMouse, "dx", "I"); + fidMDY = mEnvironment->GetStaticFieldID(clsMouse, "dy", "I"); + fidMDWheel = mEnvironment->GetStaticFieldID(clsMouse, "dwheel", "I"); +} \ No newline at end of file