summaryrefslogtreecommitdiff
path: root/source/in_dx.c
diff options
context:
space:
mode:
authorAndrey Nazarov <skuller@skuller.net>2007-08-14 20:18:08 +0000
committerAndrey Nazarov <skuller@skuller.net>2007-08-14 20:18:08 +0000
commitf294db4ccf45f6274e65260dd6f9a2c5faa94313 (patch)
treee8cf1ba2bfe9c8417eec17faf912442f52fc4ef2 /source/in_dx.c
Initial import of the new Q2PRO tree.
Diffstat (limited to 'source/in_dx.c')
-rw-r--r--source/in_dx.c331
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