mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-05-02 15:31:03 +00:00
908 lines
20 KiB
C
908 lines
20 KiB
C
#define DIRECTINPUT_VERSION 0x300
|
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#define __BYTEBOOL__
|
|
#include <windows.h>
|
|
#include <mmsystem.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
|
|
#include <dinput.h>
|
|
|
|
#include "m_argv.h"
|
|
#include "i_input.h"
|
|
#include "v_video.h"
|
|
|
|
#include "i_music.h"
|
|
|
|
#include "d_main.h"
|
|
#include "c_cvars.h"
|
|
#include "i_system.h"
|
|
#include "i_video.h"
|
|
|
|
#include "s_sound.h"
|
|
|
|
|
|
#define DINPUT_BUFFERSIZE 32
|
|
|
|
extern HINSTANCE g_hInst; /* My instance handle */
|
|
|
|
static void KeyRead (void);
|
|
static BOOL DI_Init2 (void);
|
|
static void MouseRead_DI (void);
|
|
static void MouseRead_Win32 (void);
|
|
static void GrabMouse_Win32 (void);
|
|
static void UngrabMouse_Win32 (void);
|
|
static BOOL I_GetDIMouse (void);
|
|
static void I_GetWin32Mouse (void);
|
|
static void CenterMouse_Win32 (void);
|
|
|
|
static BOOL WindowActive;
|
|
static BOOL MakeMouseEvents;
|
|
|
|
extern BOOL vidactive;
|
|
extern HWND Window;
|
|
|
|
|
|
// [RH] As of 1.14, ZDoom no longer needs to be linked with dinput.lib.
|
|
// We now go straight to the DLL ourselves.
|
|
|
|
#ifndef __CYGNUS__
|
|
typedef HRESULT (WINAPI *DIRECTINPUTCREATE_FUNCTION) (HINSTANCE, DWORD, LPDIRECTINPUT*, LPUNKNOWN);
|
|
#else
|
|
typedef HRESULT WINAPI (*DIRECTINPUTCREATE_FUNCTION) (HINSTANCE, DWORD, LPDIRECTINPUT*, LPUNKNOWN);
|
|
#endif
|
|
|
|
static HMODULE DirectInputInstance;
|
|
|
|
extern void InitKeyboardObjectData (void);
|
|
|
|
typedef enum { win32, dinput } mousemode_t;
|
|
static mousemode_t mousemode;
|
|
|
|
extern BOOL paused;
|
|
static BOOL havefocus = FALSE;
|
|
static BOOL noidle = FALSE;
|
|
|
|
// Used by the console for making keys repeat
|
|
int KeyRepeatDelay;
|
|
int KeyRepeatRate;
|
|
|
|
LPDIRECTINPUT g_pdi;
|
|
LPDIRECTINPUTDEVICE g_pKey;
|
|
LPDIRECTINPUTDEVICE g_pMouse;
|
|
|
|
//Other globals
|
|
int MouseCurX,MouseCurY,GDx,GDy;
|
|
|
|
cvar_t *i_remapkeypad;
|
|
cvar_t *usejoystick;
|
|
cvar_t *usemouse;
|
|
cvar_t *in_mouse;
|
|
|
|
// Convert DIK_* code to ASCII using Qwerty keymap
|
|
static const byte Convert []={
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 8, 9, // 0
|
|
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 13, 0, 'a', 's', // 1
|
|
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', 39, '`', 0,'\\', 'z', 'x', 'c', 'v', // 2
|
|
'b', 'n', 'm', ',', '.', '/', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, // 3
|
|
0, 0, 0, 0, 0, 0, 0, '7', '8', '9', '-', '4', '5', '6', '+', '1', // 4
|
|
'2', '3', '0', '.', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '=', 0, 0, // 8
|
|
0, '@', ':', '_', 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, // 9
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|
0, 0, 0, ',', 0, '/', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|
0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
// Convert DIK_* code to ASCII using user keymap (built at run-time)
|
|
static byte Convert2[256];
|
|
|
|
static BOOL altdown = FALSE;
|
|
|
|
LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
event_t event;
|
|
|
|
event.data1 = event.data2 = event.data3 = 0;
|
|
|
|
switch(message) {
|
|
case WM_DESTROY:
|
|
PostQuitMessage (0);
|
|
break;
|
|
|
|
case WM_HOTKEY:
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
if (!vidactive) {
|
|
I_PaintConsole ();
|
|
} else {
|
|
return DefWindowProc (hWnd, message, wParam, lParam);
|
|
}
|
|
break;
|
|
|
|
case MM_MCINOTIFY:
|
|
if (wParam == MCI_NOTIFY_SUCCESSFUL)
|
|
I_RestartSong ();
|
|
break;
|
|
|
|
case WM_KILLFOCUS:
|
|
if (g_pKey) IDirectInputDevice_Unacquire (g_pKey);
|
|
if (g_pMouse) IDirectInputDevice_Unacquire (g_pMouse);
|
|
if (altdown) {
|
|
altdown = FALSE;
|
|
event.type = ev_keyup;
|
|
event.data1 = DIK_LALT;
|
|
D_PostEvent (&event);
|
|
}
|
|
havefocus = FALSE;
|
|
if (!paused)
|
|
S_PauseSound ();
|
|
if (!noidle)
|
|
SetPriorityClass (GetCurrentProcess(), IDLE_PRIORITY_CLASS);
|
|
break;
|
|
|
|
case WM_SETFOCUS:
|
|
SetPriorityClass (GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
|
|
if (g_pKey) IDirectInputDevice_Acquire (g_pKey);
|
|
havefocus = TRUE;
|
|
if ((Fullscreen || (!paused && !menuactive)) && g_pMouse) {
|
|
IDirectInputDevice_Acquire (g_pMouse);
|
|
}
|
|
if (!paused)
|
|
S_ResumeSound ();
|
|
break;
|
|
|
|
case WM_ACTIVATE:
|
|
if (LOWORD(wParam)) {
|
|
WindowActive = TRUE;
|
|
if (mousemode == win32 && MakeMouseEvents) {
|
|
GrabMouse_Win32 ();
|
|
}
|
|
} else {
|
|
WindowActive = FALSE;
|
|
if (mousemode == win32) {
|
|
UngrabMouse_Win32 ();
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Being forced to separate my keyboard input handler into
|
|
// two pieces like this really stinks. (IMHO)
|
|
case WM_KEYDOWN:
|
|
case WM_KEYUP:
|
|
if (message == WM_KEYUP) {
|
|
event.type = ev_keyup;
|
|
} else {
|
|
if (lParam & 0x40000000)
|
|
return 0;
|
|
else
|
|
event.type = ev_keydown;
|
|
}
|
|
|
|
switch (wParam) {
|
|
case VK_PAUSE:
|
|
event.data1 = KEY_PAUSE;
|
|
break;
|
|
case VK_TAB:
|
|
event.data1 = DIK_TAB;
|
|
break;
|
|
case VK_NUMLOCK:
|
|
event.data1 = DIK_NUMLOCK;
|
|
break;
|
|
case VK_SHIFT:
|
|
event.data1 = KEY_LSHIFT;
|
|
break;
|
|
case VK_CONTROL:
|
|
event.data1 = KEY_LCTRL;
|
|
break;
|
|
}
|
|
if (event.data1)
|
|
D_PostEvent (&event);
|
|
break;
|
|
|
|
case WM_SYSKEYDOWN:
|
|
SendMessage (hWnd, WM_KEYDOWN, wParam, lParam);
|
|
break;
|
|
|
|
case WM_SYSKEYUP:
|
|
SendMessage (hWnd, WM_KEYUP, wParam, lParam);
|
|
break;
|
|
|
|
case WM_SYSCOMMAND:
|
|
{
|
|
WPARAM cmdType = wParam & 0xfff0;
|
|
|
|
if (cmdType != SC_KEYMENU)
|
|
return DefWindowProc (hWnd, message, wParam, lParam);
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
case WM_LBUTTONUP:
|
|
case WM_RBUTTONDOWN:
|
|
case WM_RBUTTONUP:
|
|
case WM_MBUTTONDOWN:
|
|
case WM_MBUTTONUP:
|
|
if (MakeMouseEvents && mousemode == win32) {
|
|
event.type = ((message - WM_LBUTTONDOWN) % 3) ? ev_keyup : ev_keydown;
|
|
event.data1 = KEY_MOUSE1 + (message - WM_LBUTTONDOWN) / 3;
|
|
event.data2 = event.data3 = 0;
|
|
D_PostEvent (&event);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return DefWindowProc (hWnd, message, wParam, lParam);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void BuildCvt2Table (void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
Convert2[i] = tolower ((byte)MapVirtualKey (MapVirtualKey (i, 1), 2));
|
|
}
|
|
|
|
/****** Stuff from Andy Bay's myjoy.c ******/
|
|
|
|
struct {
|
|
int X,Y,Z,R,U,V;
|
|
} JoyBias;
|
|
int JoyActive;
|
|
JOYINFOEX JoyStats;
|
|
JOYCAPS JoyCaps;
|
|
|
|
|
|
void JoyFixBias (void)
|
|
{
|
|
JoyBias.X = (JoyCaps.wXmin + JoyCaps.wXmax) >> 1;
|
|
JoyBias.Y = (JoyCaps.wYmin + JoyCaps.wYmax) >> 1;
|
|
JoyBias.Z = (JoyCaps.wZmin + JoyCaps.wZmax) >> 1;
|
|
JoyBias.R = (JoyCaps.wRmin + JoyCaps.wRmax) >> 1;
|
|
JoyBias.U = (JoyCaps.wUmin + JoyCaps.wUmax) >> 1;
|
|
JoyBias.V = (JoyCaps.wVmin + JoyCaps.wVmax) >> 1;
|
|
}
|
|
|
|
void DI_JoyCheck (void)
|
|
{
|
|
event_t joyevent;
|
|
|
|
if (JoyActive) {
|
|
JoyStats.dwFlags = JOY_RETURNALL;
|
|
if (joyGetPosEx (0, &JoyStats)) {
|
|
JoyActive = 0;
|
|
return;
|
|
}
|
|
|
|
joyevent.type = ev_joystick;
|
|
joyevent.data1 = 0;
|
|
joyevent.data2 = JoyStats.dwXpos - JoyBias.X;
|
|
|
|
//Doom thinks it is digital. ugh.
|
|
if (joyevent.data2 > JoyBias.X / 2){
|
|
joyevent.data2 = 1;
|
|
}
|
|
else if(joyevent.data2 < -JoyBias.X / 2){
|
|
joyevent.data2 = -1;
|
|
}
|
|
else
|
|
joyevent.data2 = 0;
|
|
|
|
joyevent.data3 = JoyStats.dwYpos - JoyBias.Y;
|
|
if (joyevent.data3 > JoyBias.Y / 2) {
|
|
joyevent.data3 = 1;
|
|
}
|
|
else if (joyevent.data3 < -JoyBias.Y / 2) {
|
|
joyevent.data3 = -1;
|
|
}
|
|
else
|
|
joyevent.data3 = 0;
|
|
|
|
D_PostEvent (&joyevent);
|
|
|
|
{ /* Send out button up/down events */
|
|
static DWORD oldButtons = 0;
|
|
int i;
|
|
DWORD buttons, mask;
|
|
|
|
buttons = JoyStats.dwButtons;
|
|
mask = buttons ^ oldButtons;
|
|
|
|
joyevent.data2 = joyevent.data3 = 0;
|
|
for (i = 0; i < 32; i++, buttons >>= 1, mask >>= 1) {
|
|
if (mask & 1) {
|
|
joyevent.data1 = KEY_JOY1 + i;
|
|
if (buttons & 1)
|
|
joyevent.type = ev_keydown;
|
|
else
|
|
joyevent.type = ev_keyup;
|
|
D_PostEvent (&joyevent);
|
|
}
|
|
}
|
|
oldButtons = JoyStats.dwButtons;
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL DI_InitJoy (void)
|
|
{
|
|
Printf ("DI_InitJoy: Initialize joystick\n");
|
|
JoyActive = joyGetNumDevs ();
|
|
if (JoyActive) {
|
|
JoyStats.dwSize = sizeof(JOYINFOEX);
|
|
joyGetDevCaps (0, &JoyCaps, sizeof(JOYCAPS));
|
|
JoyFixBias();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void I_PauseMouse (void)
|
|
{
|
|
if (Fullscreen)
|
|
return;
|
|
|
|
if (g_pMouse) {
|
|
IDirectInputDevice_Unacquire (g_pMouse);
|
|
} else {
|
|
UngrabMouse_Win32 ();
|
|
}
|
|
}
|
|
|
|
void I_ResumeMouse (void)
|
|
{
|
|
if (!g_pMouse) {
|
|
GrabMouse_Win32 ();
|
|
} else {
|
|
IDirectInputDevice_Acquire (g_pMouse);
|
|
}
|
|
}
|
|
|
|
/****** Stuff from Andy Bay's mymouse.c ******
|
|
|
|
/****************************************************************************
|
|
*
|
|
* DIInit
|
|
*
|
|
* Initialize the DirectInput variables.
|
|
*
|
|
****************************************************************************/
|
|
|
|
// [RH] Obtain the mouse using standard Win32 calls. Should always work.
|
|
static void I_GetWin32Mouse (void)
|
|
{
|
|
mousemode = win32;
|
|
|
|
if (g_pMouse) {
|
|
IDirectInputDevice_Unacquire (g_pMouse);
|
|
IDirectInputDevice_Release (g_pMouse);
|
|
g_pMouse = NULL;
|
|
}
|
|
GrabMouse_Win32 ();
|
|
}
|
|
|
|
// [RH] Used to obtain DirectInput access to the mouse.
|
|
// (Preferred for Win95, but buggy under NT.)
|
|
static BOOL I_GetDIMouse (void)
|
|
{
|
|
HRESULT hr;
|
|
DIPROPDWORD dipdw =
|
|
{
|
|
{
|
|
sizeof(DIPROPDWORD), // diph.dwSize
|
|
sizeof(DIPROPHEADER), // diph.dwHeaderSize
|
|
0, // diph.dwObj
|
|
DIPH_DEVICE, // diph.dwHow
|
|
},
|
|
DINPUT_BUFFERSIZE, // dwData
|
|
};
|
|
|
|
if (mousemode == dinput)
|
|
return FALSE;
|
|
|
|
mousemode = win32; // Assume failure
|
|
UngrabMouse_Win32 ();
|
|
|
|
if (in_mouse->value == 1 || (in_mouse->value == 0 && OSPlatform == os_WinNT))
|
|
return FALSE;
|
|
|
|
// Obtain an interface to the system mouse device.
|
|
hr = IDirectInput_CreateDevice (g_pdi, &GUID_SysMouse, &g_pMouse, NULL);
|
|
|
|
if (FAILED(hr))
|
|
return FALSE;
|
|
|
|
// Set the data format to "mouse format".
|
|
hr = IDirectInputDevice_SetDataFormat (g_pMouse, &c_dfDIMouse);
|
|
|
|
if (FAILED(hr)) {
|
|
IDirectInputDevice_Release (g_pMouse);
|
|
g_pMouse = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
// Set the cooperative level.
|
|
hr = IDirectInputDevice_SetCooperativeLevel (g_pMouse,(HWND)Window,
|
|
DISCL_EXCLUSIVE | DISCL_FOREGROUND);
|
|
|
|
if (FAILED(hr)) {
|
|
IDirectInputDevice_Release (g_pMouse);
|
|
g_pMouse = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// Set the buffer size to DINPUT_BUFFERSIZE elements.
|
|
// The buffer size is a DWORD property associated with the device.
|
|
hr = IDirectInputDevice_SetProperty (g_pMouse, DIPROP_BUFFERSIZE, &dipdw.diph);
|
|
|
|
if (FAILED(hr)) {
|
|
Printf ("Could not set mouse buffer size");
|
|
IDirectInputDevice_Release (g_pMouse);
|
|
g_pMouse = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
IDirectInputDevice_Acquire (g_pMouse);
|
|
|
|
mousemode = dinput;
|
|
return TRUE;
|
|
}
|
|
|
|
static void in_mouse_changed (cvar_t *var)
|
|
{
|
|
if (var->value < 0) {
|
|
SetCVarFloat (var, 0);
|
|
} else if (var->value > 2) {
|
|
SetCVarFloat (var, 2);
|
|
} else {
|
|
int new_mousemode;
|
|
|
|
if (var->value == 1 || (var->value == 0 && OSPlatform == os_WinNT))
|
|
new_mousemode = win32;
|
|
else
|
|
new_mousemode = dinput;
|
|
|
|
if (new_mousemode != mousemode) {
|
|
if (new_mousemode == win32)
|
|
I_GetWin32Mouse ();
|
|
else
|
|
if (!I_GetDIMouse ())
|
|
I_GetWin32Mouse ();
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL I_InitInput (void *hwnd)
|
|
{
|
|
DIRECTINPUTCREATE_FUNCTION DirectInputCreateFunction;
|
|
HRESULT hr;
|
|
|
|
noidle = M_CheckParm ("-noidle");
|
|
|
|
in_mouse = cvar ("in_mouse", "0", CVAR_ARCHIVE|CVAR_CALLBACK);
|
|
in_mouse->u.callback = in_mouse_changed;
|
|
|
|
Printf ("I_InitInput: Initialize DirectInput\n");
|
|
|
|
// [RH] Removed dependence on existance of dinput.lib when linking.
|
|
|
|
DirectInputInstance = (HMODULE)LoadLibrary ("dinput.dll");
|
|
if (!DirectInputInstance)
|
|
I_FatalError ("Sorry, you need Microsoft's DirectX installed.\n\n"
|
|
"Go grab it at http://www.microsoft.com/directx\n");
|
|
|
|
DirectInputCreateFunction = (DIRECTINPUTCREATE_FUNCTION)GetProcAddress (DirectInputInstance, "DirectInputCreateA");
|
|
if (!DirectInputCreateFunction)
|
|
I_FatalError ("Could not get address of DirectInputCreateA");
|
|
|
|
// Register with DirectInput and get an IDirectInput to play with.
|
|
hr = DirectInputCreateFunction (g_hInst, DIRECTINPUT_VERSION, &g_pdi, NULL);
|
|
|
|
if (FAILED(hr))
|
|
I_FatalError ("Could not obtain DirectInput interface");
|
|
|
|
if (!I_GetDIMouse ())
|
|
I_GetWin32Mouse ();
|
|
|
|
DI_Init2();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Free all input resources
|
|
void I_ShutdownInput (void)
|
|
{
|
|
if (g_pKey) {
|
|
IDirectInputDevice_Unacquire (g_pKey);
|
|
IDirectInputDevice_Release (g_pKey);
|
|
g_pKey = NULL;
|
|
}
|
|
if (g_pMouse) {
|
|
IDirectInputDevice_Unacquire (g_pMouse);
|
|
IDirectInputDevice_Release (g_pMouse);
|
|
g_pMouse = NULL;
|
|
}
|
|
UngrabMouse_Win32 ();
|
|
if (g_pdi) {
|
|
IDirectInput_Release(g_pdi);
|
|
g_pdi = NULL;
|
|
}
|
|
// [RH] Close dinput.dll
|
|
if (DirectInputInstance) {
|
|
FreeLibrary (DirectInputInstance);
|
|
DirectInputInstance = NULL;
|
|
}
|
|
}
|
|
|
|
static LONG PrevX, PrevY;
|
|
|
|
static void CenterMouse_Win32 (void) {
|
|
RECT rect;
|
|
|
|
GetWindowRect (Window, &rect);
|
|
PrevX = (rect.left + rect.right) >> 1;
|
|
PrevY = (rect.top + rect.bottom) >> 1;
|
|
SetCursorPos (PrevX, PrevY);
|
|
}
|
|
|
|
static int showcount = 1;
|
|
|
|
static void GrabMouse_Win32 (void) {
|
|
RECT rect;
|
|
|
|
ClipCursor (NULL); // helps with Win95?
|
|
GetWindowRect (Window, &rect);
|
|
ClipCursor (&rect);
|
|
if (showcount) {
|
|
ShowCursor (FALSE);
|
|
showcount--;
|
|
}
|
|
CenterMouse_Win32 ();
|
|
MakeMouseEvents = TRUE;
|
|
}
|
|
|
|
static void UngrabMouse_Win32 (void) {
|
|
ClipCursor (NULL);
|
|
if (!showcount) {
|
|
ShowCursor (TRUE);
|
|
showcount++;
|
|
}
|
|
MakeMouseEvents = FALSE;
|
|
}
|
|
|
|
static void MouseRead_Win32 (void) {
|
|
POINT pt;
|
|
event_t ev;
|
|
|
|
if (!WindowActive || !MakeMouseEvents || !GetCursorPos (&pt))
|
|
return;
|
|
|
|
ev.data2 = (pt.x - PrevX) * 3;
|
|
ev.data3 = (PrevY - pt.y) << 1;
|
|
|
|
CenterMouse_Win32 ();
|
|
|
|
if (ev.data2 || ev.data3) {
|
|
ev.type = ev_mouse;
|
|
ev.data1 = 0;
|
|
D_PostEvent (&ev);
|
|
}
|
|
}
|
|
|
|
static void MouseRead_DI (void) {
|
|
static int lastx = 0, lasty = 0;
|
|
DIDEVICEOBJECTDATA od;
|
|
DWORD dwElements;
|
|
HRESULT hr;
|
|
int count = 0;
|
|
|
|
event_t event;
|
|
GDx=0;
|
|
GDy=0;
|
|
|
|
if (!g_pMouse)
|
|
return;
|
|
|
|
event.data2 = event.data3 = 0;
|
|
while (1) {
|
|
dwElements = 1;
|
|
hr = IDirectInputDevice_GetDeviceData (g_pMouse,
|
|
sizeof(DIDEVICEOBJECTDATA), &od,
|
|
&dwElements,
|
|
0);
|
|
if (hr == DIERR_INPUTLOST) {
|
|
IDirectInputDevice_Acquire (g_pMouse);
|
|
hr = IDirectInputDevice_GetDeviceData (g_pMouse,
|
|
sizeof(DIDEVICEOBJECTDATA), &od,
|
|
&dwElements,
|
|
0);
|
|
}
|
|
|
|
/* Unable to read data or no data available */
|
|
if (FAILED(hr) || !dwElements)
|
|
break;
|
|
|
|
count++;
|
|
|
|
/* Look at the element to see what happened */
|
|
switch (od.dwOfs) {
|
|
|
|
/* DIMOFS_X: Mouse horizontal motion */
|
|
case DIMOFS_X:
|
|
GDx += od.dwData;
|
|
break;
|
|
/* DIMOFS_Y: Mouse vertical motion */
|
|
case DIMOFS_Y:
|
|
GDy += od.dwData;
|
|
break;
|
|
|
|
/* [RH] Mouse button events now mimic keydown/up events */
|
|
case DIMOFS_BUTTON0:
|
|
if(od.dwData & 0x80) {
|
|
event.type = ev_keydown;
|
|
} else {
|
|
event.type = ev_keyup;
|
|
}
|
|
event.data1 = KEY_MOUSE1;
|
|
D_PostEvent (&event);
|
|
break;
|
|
case DIMOFS_BUTTON1:
|
|
if(od.dwData & 0x80) {
|
|
event.type = ev_keydown;
|
|
} else {
|
|
event.type = ev_keyup;
|
|
}
|
|
event.data1 = KEY_MOUSE2;
|
|
D_PostEvent (&event);
|
|
break;
|
|
case DIMOFS_BUTTON2:
|
|
if(od.dwData & 0x80) {
|
|
event.type = ev_keydown;
|
|
} else {
|
|
event.type = ev_keyup;
|
|
}
|
|
event.data1 = KEY_MOUSE3;
|
|
D_PostEvent (&event);
|
|
break;
|
|
case DIMOFS_BUTTON3:
|
|
if(od.dwData & 0x80) {
|
|
event.type = ev_keydown;
|
|
} else {
|
|
event.type = ev_keyup;
|
|
}
|
|
event.data1 = KEY_MOUSE4;
|
|
D_PostEvent (&event);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (count) {
|
|
event.type = ev_mouse;
|
|
event.data1 = 0;
|
|
event.data2 = GDx<<2;
|
|
event.data3 = -GDy;
|
|
D_PostEvent (&event);
|
|
}
|
|
}
|
|
|
|
// Initialize the keyboard
|
|
static BOOL DI_Init2 (void)
|
|
{
|
|
int hr;
|
|
DWORD repeatStuff;
|
|
DIPROPDWORD dipdw =
|
|
{
|
|
{
|
|
sizeof(DIPROPDWORD), // diph.dwSize
|
|
sizeof(DIPROPHEADER), // diph.dwHeaderSize
|
|
0, // diph.dwObj
|
|
DIPH_DEVICE, // diph.dwHow
|
|
},
|
|
DINPUT_BUFFERSIZE, // dwData
|
|
};
|
|
|
|
Printf ("DI_Init2: Initialize keyboard\n");
|
|
|
|
BuildCvt2Table ();
|
|
|
|
// [RH] The timing values for these SPI_* parameters are described in
|
|
// MS Knowledge Base article Q102978.
|
|
if (SystemParametersInfo (SPI_GETKEYBOARDDELAY, 0, &repeatStuff, 0)) {
|
|
// 0 = 250 ms, 3 = 1000 ms
|
|
KeyRepeatDelay = ((repeatStuff * 250 + 250) * TICRATE) / 1000;
|
|
} else {
|
|
KeyRepeatDelay = (250 * TICRATE) / 1000;
|
|
}
|
|
DPrintf ("KeyRepeatDelay = %u tics\n", KeyRepeatDelay);
|
|
|
|
if (SystemParametersInfo (SPI_GETKEYBOARDSPEED, 0, &repeatStuff, 0)) {
|
|
// 0 = 2/sec, 31 = 30/sec
|
|
KeyRepeatRate = TICRATE / (2 + repeatStuff);
|
|
} else {
|
|
KeyRepeatRate = TICRATE / 15;
|
|
}
|
|
DPrintf ("KeyRepeatRate = %u tics\n", KeyRepeatRate);
|
|
|
|
// Obtain an interface to the system key device.
|
|
hr = IDirectInput_CreateDevice (g_pdi, &GUID_SysKeyboard, &g_pKey, NULL);
|
|
|
|
if (FAILED(hr)) {
|
|
I_FatalError ("Could not create keyboard device");
|
|
}
|
|
|
|
// [RH] Prepare c_dfDIKeyboard for use.
|
|
InitKeyboardObjectData ();
|
|
|
|
// Set the data format to "keyboard format".
|
|
hr = IDirectInputDevice_SetDataFormat (g_pKey,&c_dfDIKeyboard);
|
|
|
|
if (FAILED(hr)) {
|
|
I_FatalError ("Could not set keyboard data format");
|
|
}
|
|
|
|
|
|
// Set the cooperative level.
|
|
hr = IDirectInputDevice_SetCooperativeLevel(g_pKey, Window,
|
|
DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
|
|
|
|
if (FAILED(hr)) {
|
|
I_FatalError("Could not set keyboard cooperative level");
|
|
}
|
|
|
|
// Set the buffer size to DINPUT_BUFFERSIZE elements.
|
|
// The buffer size is a DWORD property associated with the device.
|
|
hr = IDirectInputDevice_SetProperty (g_pKey, DIPROP_BUFFERSIZE, &dipdw.diph);
|
|
|
|
if (FAILED(hr)) {
|
|
I_FatalError ("Could not set keyboard buffer size");
|
|
}
|
|
|
|
IDirectInputDevice_Acquire (g_pKey);
|
|
|
|
DI_InitJoy ();
|
|
return TRUE;
|
|
}
|
|
|
|
static void KeyRead (void) {
|
|
HRESULT hr;
|
|
event_t event;
|
|
|
|
DIDEVICEOBJECTDATA data[DINPUT_BUFFERSIZE];
|
|
DWORD dwElements, elem;
|
|
|
|
do {
|
|
dwElements = DINPUT_BUFFERSIZE;
|
|
|
|
hr = IDirectInputDevice_GetDeviceData (g_pKey, sizeof(DIDEVICEOBJECTDATA), data, &dwElements, 0);
|
|
if (hr == DIERR_INPUTLOST) {
|
|
hr = IDirectInputDevice_Acquire (g_pKey);
|
|
hr = IDirectInputDevice_GetDeviceData (g_pKey, sizeof(DIDEVICEOBJECTDATA), data, &dwElements, 0);
|
|
}
|
|
|
|
if (SUCCEEDED (hr) && dwElements) {
|
|
int key;
|
|
|
|
for (elem = 0; elem < dwElements; elem++) {
|
|
key = data[elem].dwOfs;
|
|
|
|
if (data[elem].dwData & 0x80) {
|
|
event.type = ev_keydown;
|
|
} else {
|
|
event.type = ev_keyup;
|
|
}
|
|
|
|
event.data3 = Convert2[key];
|
|
switch (key) {
|
|
case DIK_NUMPADENTER: // These keys always translated
|
|
key = DIK_RETURN;
|
|
break;
|
|
case DIK_RMENU:
|
|
key = DIK_LMENU;
|
|
break;
|
|
case DIK_RCONTROL: // These keys are handled by the message handler
|
|
case DIK_LCONTROL:
|
|
case DIK_RSHIFT:
|
|
case DIK_LSHIFT:
|
|
case DIK_TAB:
|
|
case DIK_NUMLOCK:
|
|
key = 0;
|
|
break;
|
|
default:
|
|
if (i_remapkeypad->value) {
|
|
switch (key) {
|
|
case DIK_NUMPAD4:
|
|
key = DIK_LEFT;
|
|
break;
|
|
case DIK_NUMPAD6:
|
|
key = DIK_RIGHT;
|
|
break;
|
|
case DIK_NUMPAD8:
|
|
key = DIK_UP;
|
|
break;
|
|
case DIK_NUMPAD2:
|
|
key = DIK_DOWN;
|
|
break;
|
|
case DIK_NUMPAD7:
|
|
key = DIK_HOME;
|
|
break;
|
|
case DIK_NUMPAD9:
|
|
key = DIK_PRIOR;
|
|
break;
|
|
case DIK_NUMPAD3:
|
|
key = DIK_NEXT;
|
|
break;
|
|
case DIK_NUMPAD1:
|
|
key = DIK_END;
|
|
break;
|
|
case DIK_NUMPAD0:
|
|
key = DIK_INSERT;
|
|
break;
|
|
case DIK_DECIMAL:
|
|
key = DIK_DELETE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (key) {
|
|
event.data1 = key;
|
|
event.data2 = Convert[key];
|
|
event.data3 = Convert2[key];
|
|
D_PostEvent (&event);
|
|
if (key == DIK_LALT)
|
|
altdown = (event.type == ev_keydown);
|
|
}
|
|
}
|
|
}
|
|
} while (SUCCEEDED (hr) && dwElements);
|
|
}
|
|
|
|
void I_GetEvent(void)
|
|
{
|
|
MSG mess;
|
|
|
|
// while (1) {
|
|
while (PeekMessage (&mess, NULL, 0, 0, PM_REMOVE)) {
|
|
if (mess.message == WM_QUIT)
|
|
I_Quit ();
|
|
TranslateMessage (&mess);
|
|
DispatchMessage (&mess);
|
|
}
|
|
// if (havefocus || netgame || gamestate != GS_LEVEL)
|
|
// break;
|
|
// }
|
|
|
|
KeyRead ();
|
|
|
|
if (usemouse->value) {
|
|
if (mousemode == dinput)
|
|
MouseRead_DI ();
|
|
else
|
|
MouseRead_Win32 ();
|
|
}
|
|
|
|
if (usejoystick->value)
|
|
DI_JoyCheck ();
|
|
}
|
|
|
|
|
|
//
|
|
// I_StartTic
|
|
//
|
|
void I_StartTic (void)
|
|
{
|
|
I_GetEvent ();
|
|
}
|