/* * Copyright (c) 2002 Lightweight Java Game Library 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 '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 * "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. */ /** * $Id$ * * Win32 mouse handling. * * @author Brian Matzon * @version $Revision$ */ #define WIN32_LEAN_AND_MEAN #include "org_lwjgl_input_Mouse.h" #include #undef DIRECTINPUT_VERSION #define DIRECTINPUT_VERSION 0x0300 #include extern HINSTANCE dll_handle; 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 bool mFirstTimeInitialization = true; // boolean to determine first time initialization // 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) { mEnvironment = env; clsMouse = clazz; /* Cache fields in Mouse */ CacheMouseFields(); } /** * Called when the Mouse instance is to be created */ JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Mouse_nCreate(JNIEnv *env, jclass clazz) { HRESULT hr; mEnvironment = env; clsMouse = clazz; CacheMouseFields(); /* skip enumeration, since we only want system mouse */ CreateMouse(); //check for first time initialization - need to detect capabilities if (mFirstTimeInitialization) { mFirstTimeInitialization = false; /* Enumerate capabilities of Mouse */ EnumerateMouseCapabilities(); if (!mCreate_success) { #if _DEBUG printf("EnumerateMouseCapabilities failed\n"); #endif ShutdownMouse(); return JNI_FALSE; } /* Do setup of Mouse */ SetupMouse(); /* Set capabilities */ SetMouseCapabilities(); } else { if(mCreate_success) { /* Do setup of Mouse */ SetupMouse(); } } /* Aquire the Mouse */ hr = mDIDevice->Acquire(); if(FAILED(hr)) { #if _DEBUG printf("Failed to acquire mouse\n"); #endif } return mCreate_success ? JNI_TRUE : JNI_FALSE; } /* * Class: org_lwjgl_input_Mouse * Method: nDestroy * Signature: ()V */ JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nDestroy(JNIEnv *env, jclass clazz) { mEnvironment = env; clsMouse = clazz; ShutdownMouse(); } /* * Class: org_lwjgl_input_Controller * Method: nPoll * Signature: ()V */ JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nPoll(JNIEnv * env, jclass clazz) { mDIDevice->Acquire(); mEnvironment = env; clsMouse = clazz; UpdateMouseFields(); } /** * Shutdown DI */ void ShutdownMouse() { // release device if (mDIDevice != NULL) { mDIDevice->Unacquire(); mDIDevice->Release(); mDIDevice = NULL; } } /** * 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; } //check for > 4 buttons - need to clamp since we're using dx 5 if(mButtoncount > 4) { mButtoncount = 4; #ifdef _DEBUG printf("WARNING: Clamping to 4 mouse buttons"); #endif } 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; } /** * 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) { // Don't allow the mouse to drift when failed diMouseState.lX = 0; diMouseState.lY = 0; diMouseState.lZ = 0; // 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 } } mEnvironment->SetStaticIntField(clsMouse, fidMDX, (jint) diMouseState.lX); mEnvironment->SetStaticIntField(clsMouse, fidMDY, (jint) diMouseState.lY); mEnvironment->SetStaticIntField(clsMouse, fidMDWheel, (jint) diMouseState.lZ); for (int i = 0; i < mButtoncount; i++) { if (diMouseState.rgbButtons[i] != 0) { diMouseState.rgbButtons[i] = JNI_TRUE; } else { diMouseState.rgbButtons[i] = JNI_FALSE; } } jbooleanArray mButtonsArray = (jbooleanArray) mEnvironment->GetStaticObjectField(clsMouse, fidMButtons); mEnvironment->SetBooleanArrayRegion(mButtonsArray, 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"); }