diff options
author | Andrey Nazarov <skuller@skuller.net> | 2007-08-14 20:18:08 +0000 |
---|---|---|
committer | Andrey Nazarov <skuller@skuller.net> | 2007-08-14 20:18:08 +0000 |
commit | f294db4ccf45f6274e65260dd6f9a2c5faa94313 (patch) | |
tree | e8cf1ba2bfe9c8417eec17faf912442f52fc4ef2 /source/in_dx.c |
Initial import of the new Q2PRO tree.
Diffstat (limited to 'source/in_dx.c')
-rw-r--r-- | source/in_dx.c | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/source/in_dx.c b/source/in_dx.c new file mode 100644 index 0000000..839925a --- /dev/null +++ b/source/in_dx.c @@ -0,0 +1,331 @@ +/* +Copyright (C) 2003-2006 Andrey Nazarov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// +// win_dinput.c - DirectInput 7 mouse driver +// + +#if USE_DINPUT + +#include "win_local.h" + +#define DIRECTINPUT_VERSION 0x0700 +#include <dinput.h> + +#ifndef DIDFT_OPTIONAL +#define DIDFT_OPTIONAL 0x80000000 +#endif + +static HMODULE hDirectInput; + +typedef HRESULT (WINAPI *LPDIRECTINPUTCREATE)( HINSTANCE, DWORD, LPDIRECTINPUT *, LPUNKNOWN ); + +static LPDIRECTINPUTCREATE pDirectInputCreate; + +static qboolean di_active; // qfalse when not focus app +static qboolean di_initialized; +static LPDIRECTINPUT di; +static LPDIRECTINPUTDEVICE di_mouse; + +static DIOBJECTDATAFORMAT mouseObjectDataFormat[] = { + { &GUID_XAxis, DIMOFS_X, DIDFT_RELAXIS|DIDFT_ANYINSTANCE, 0 }, + { &GUID_YAxis, DIMOFS_Y, DIDFT_RELAXIS|DIDFT_ANYINSTANCE, 0 }, + { &GUID_ZAxis, DIMOFS_Z, DIDFT_RELAXIS|DIDFT_ANYINSTANCE|DIDFT_OPTIONAL, 0 }, + { NULL, DIMOFS_BUTTON0, DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, DIMOFS_BUTTON1, DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, DIMOFS_BUTTON2, DIDFT_BUTTON|DIDFT_ANYINSTANCE|DIDFT_OPTIONAL, 0 }, + { NULL, DIMOFS_BUTTON3, DIDFT_BUTTON|DIDFT_ANYINSTANCE|DIDFT_OPTIONAL, 0 }, + { NULL, DIMOFS_BUTTON4, DIDFT_BUTTON|DIDFT_ANYINSTANCE|DIDFT_OPTIONAL, 0 }, + { NULL, DIMOFS_BUTTON5, DIDFT_BUTTON|DIDFT_ANYINSTANCE|DIDFT_OPTIONAL, 0 }, + { NULL, DIMOFS_BUTTON6, DIDFT_BUTTON|DIDFT_ANYINSTANCE|DIDFT_OPTIONAL, 0 }, + { NULL, DIMOFS_BUTTON7, DIDFT_BUTTON|DIDFT_ANYINSTANCE|DIDFT_OPTIONAL, 0 } +}; + +static DIDATAFORMAT mouseDataFormat = { + sizeof( DIDATAFORMAT ), + sizeof( DIOBJECTDATAFORMAT ), + DIDF_RELAXIS, + sizeof( DIMOUSESTATE2 ), + sizeof( mouseObjectDataFormat ) / sizeof( mouseObjectDataFormat[0] ), + mouseObjectDataFormat +}; + +static DIPROPDWORD mouseBufferSize = { + { + sizeof( DIPROPDWORD ), + sizeof( DIPROPHEADER ), + 0, + DIPH_DEVICE + }, + 32 +}; + +#ifdef DEFINE_GUID +#undef DEFINE_GUID +#endif + +#define DEFINE_GUID( name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8 ) \ + const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } + +DEFINE_GUID( GUID_SysMouse, 0x6F1D2B60, 0xD5A0, 0x11CF, 0xBF, 0xC7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 ); +DEFINE_GUID( GUID_XAxis, 0xA36D02E0, 0xC9F3, 0x11CF, 0xBF, 0xC7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 ); +DEFINE_GUID( GUID_YAxis, 0xA36D02E1, 0xC9F3, 0x11CF, 0xBF, 0xC7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 ); +DEFINE_GUID( GUID_ZAxis, 0xA36D02E2, 0xC9F3, 0x11CF, 0xBF, 0xC7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 ); + +/* +=========== +DI_SendMouseMoveEvents +=========== +*/ +void DI_SendMouseMoveEvents( void ) { + DIDEVICEOBJECTDATA data[16]; + LPDIDEVICEOBJECTDATA p, last; + DIMOUSESTATE2 state; + DWORD numElements, button; + int value; + HRESULT hr; + + if( !di_initialized ) { + return; + } + + if( !di_active ) { + return; + } + + do { + numElements = 16; + hr = IDirectInputDevice_GetDeviceData( di_mouse, sizeof( data[0] ), data, &numElements, 0 ); + if( hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED ) { + IDirectInputDevice_Acquire( di_mouse ); + return; + } + if( FAILED( hr ) ) { + Com_EPrintf( "GetDeviceData failed with error 0x%lX\n", hr ); + return; + } + last = data + numElements; + for( p = data; p != last; p++ ) { + switch( p->dwOfs ) { + case DIMOFS_BUTTON0: + case DIMOFS_BUTTON1: + case DIMOFS_BUTTON2: + case DIMOFS_BUTTON3: + case DIMOFS_BUTTON4: + case DIMOFS_BUTTON5: + case DIMOFS_BUTTON6: + case DIMOFS_BUTTON7: + button = p->dwOfs - DIMOFS_BUTTON0; + if( p->dwData & 0x80 ) { + Key_Event( K_MOUSE1 + button, qtrue, p->dwTimeStamp ); + } else { + Key_Event( K_MOUSE1 + button, qfalse, p->dwTimeStamp ); + } + break; + case DIMOFS_Z: + value = p->dwData; + if( !value ) { + break; + } + if( value > 0 ) { + Key_Event( K_MWHEELUP, qtrue, p->dwTimeStamp ); + Key_Event( K_MWHEELUP, qfalse, p->dwTimeStamp ); + } else { + Key_Event( K_MWHEELDOWN, qtrue, p->dwTimeStamp ); + Key_Event( K_MWHEELDOWN, qfalse, p->dwTimeStamp ); + } + break; + default: + break; + } + } + } while( hr == DI_BUFFEROVERFLOW ); + + hr = IDirectInputDevice_GetDeviceState( di_mouse, sizeof( state ), &state ); + if( FAILED( hr ) ) { + Com_EPrintf( "GetDeviceState failed with error 0x%lX\n", hr ); + return; + } + + if( state.lX || state.lY ) { + CL_MouseEvent( state.lX, state.lY ); + } + +} + +/* +=========== +DI_ShutdownMouse +=========== +*/ +static void DI_ShutdownMouse( void ) { + Com_Printf( "Shutting down DirectInput\n" ); + + if( di_mouse ) { + if( di_active ) { + IDirectInputDevice_Unacquire( di_mouse ); + } + IDirectInputDevice_Release( di_mouse ); + di_mouse = NULL; + } + if( di ) { + IDirectInput_Release( di ); + di = NULL; + } + di_active = qfalse; + di_initialized = qfalse; + +} + +/* +=========== +DI_StartupMouse +=========== +*/ +static qboolean DI_InitMouse( void ) { + HRESULT hr; + + if( !win.wnd ) { + return qfalse; + } + + Com_Printf( "Initializing DirectInput\n" ); + + if( !hDirectInput ) { + hDirectInput = LoadLibrary( "dinput.dll" ); + if( !hDirectInput ) { + Com_EPrintf( "Failed to load dinput.dll\n" ); + return qfalse; + } + + pDirectInputCreate = ( LPDIRECTINPUTCREATE ) + GetProcAddress( hDirectInput, "DirectInputCreateA" ); + if( !pDirectInputCreate ) { + Com_EPrintf( "Failed to obtain DirectInputCreate\n" ); + goto fail; + } + } + + hr = pDirectInputCreate( hGlobalInstance, DIRECTINPUT_VERSION, &di, NULL ); + if( FAILED( hr ) ) { + Com_EPrintf( "DirectInputCreate failed with error 0x%lX\n", hr ); + goto fail; + } + + hr = IDirectInput_CreateDevice( di, &GUID_SysMouse, &di_mouse, NULL ); + if( FAILED( hr ) ) { + Com_EPrintf( "CreateDevice failed with error 0x%lX\n", hr ); + goto fail; + } + + hr = IDirectInputDevice_SetDataFormat( di_mouse, &mouseDataFormat ); + if( FAILED( hr ) ) { + Com_EPrintf( "SetDataFormat failed with error 0x%lX\n", hr ); + goto fail; + } + + hr = IDirectInputDevice_SetCooperativeLevel( di_mouse, win.wnd, DISCL_EXCLUSIVE|DISCL_FOREGROUND ); + if( FAILED( hr ) ) { + Com_EPrintf( "SetCooperativeLevel failed with error 0x%lX\n", hr ); + goto fail; + } + + hr = IDirectInputDevice_SetProperty( di_mouse, DIPROP_BUFFERSIZE, &mouseBufferSize.diph ); + if( FAILED( hr ) ) { + Com_EPrintf( "SetProperty failed with error 0x%lX\n", hr ); + goto fail; + } + + di_initialized = qtrue; + + return qtrue; + +fail: + if( di_mouse ) { + IDirectInputDevice_Release( di_mouse ); + di_mouse = NULL; + } + if( di ) { + IDirectInput_Release( di ); + di = NULL; + } + return qfalse; +} + +/* +=========== +DI_ActivateMouse + +Called when the main window gains or loses focus. +The window may have been destroyed and recreated +between a deactivate and an activate. +=========== +*/ +static void DI_ActivateMouse( qboolean active ) { + HRESULT hr; + + if( !di_initialized ) { + return; + } + + if( di_active == active ) { + return; + } + + if( active ) { + Com_DPrintf( "IDirectInputDevice_Acquire\n" ); + hr = IDirectInputDevice_Acquire( di_mouse ); + if( FAILED( hr ) ) { + Com_EPrintf( "Failed to acquire mouse, error 0x%lX\n", hr ); + } + } else { + Com_DPrintf( "IDirectInputDevice_Unacquire\n" ); + hr = IDirectInputDevice_Unacquire( di_mouse ); + if( FAILED( hr ) ) { + Com_EPrintf( "Failed to unacquire mouse, error 0x%lX\n", hr ); + } + } + + di_active = active; + +} + +/* +=================== +DI_ClearMouseStates +=================== +*/ +static void DI_ClearMouseStates( void ) { +} + +/* +@@@@@@@@@@@@@@@@@@@ +DI_FillAPI +@@@@@@@@@@@@@@@@@@@ +*/ +void DI_FillAPI( inputAPI_t *api ) { + api->Init = DI_InitMouse; + api->Shutdown = DI_ShutdownMouse; + api->Activate = DI_ActivateMouse; + api->Frame = DI_SendMouseMoveEvents; + api->ClearStates = DI_ClearMouseStates; +} + +#endif // USE_DINPUT |