mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-28 06:53:40 +00:00
- Split DirectInput keyboard handling into a separate file and class. I also
switched it to buffered input, and the pause key seems to be properly cooked, so I don't need to look for it with WM_KEYDOWN/UP. Tab doesn't need to be special-cased either, because buffered input never passes on the Tab key when you press Alt+Tab. I have no idea why I special-cased Num Lock, but it seems to be working fine. By setting the exclusive mode to background, I can also avoid special code for releasing all keys when the window loses focus, because I'll still receive those events while the window is in the background. SVN r1613 (trunk)
This commit is contained in:
parent
0a310b9832
commit
7fea07dff7
9 changed files with 350 additions and 163 deletions
|
@ -1,4 +1,13 @@
|
||||||
May 26, 2009
|
May 26, 2009
|
||||||
|
- Split DirectInput keyboard handling into a separate file and class. I also
|
||||||
|
switched it to buffered input, and the pause key seems to be properly
|
||||||
|
cooked, so I don't need to look for it with WM_KEYDOWN/UP. Tab doesn't
|
||||||
|
need to be special-cased either, because buffered input never passes on
|
||||||
|
the Tab key when you press Alt+Tab. I have no idea why I special-cased
|
||||||
|
Num Lock, but it seems to be working fine. By setting the exclusive mode
|
||||||
|
to background, I can also avoid special code for releasing all keys when
|
||||||
|
the window loses focus, because I'll still receive those events while the
|
||||||
|
window is in the background.
|
||||||
- Fixed: The Heretic "take weapons" cheat did not remove all the weapons at
|
- Fixed: The Heretic "take weapons" cheat did not remove all the weapons at
|
||||||
once. This is because destroying one weapon has a potential to destroy a
|
once. This is because destroying one weapon has a potential to destroy a
|
||||||
sister weapon as well. If the sister weapon is the next one in line (as it
|
sister weapon as well. If the sister weapon is the next one in line (as it
|
||||||
|
|
|
@ -398,6 +398,7 @@ if( WIN32 )
|
||||||
win32/i_cd.cpp
|
win32/i_cd.cpp
|
||||||
win32/i_crash.cpp
|
win32/i_crash.cpp
|
||||||
win32/i_input.cpp
|
win32/i_input.cpp
|
||||||
|
win32/i_keyboard.cpp
|
||||||
win32/i_mouse.cpp
|
win32/i_mouse.cpp
|
||||||
win32/i_main.cpp
|
win32/i_main.cpp
|
||||||
win32/i_movie.cpp
|
win32/i_movie.cpp
|
||||||
|
|
|
@ -191,14 +191,14 @@ const char *KeyNames[NUM_KEYS] =
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, "voldown", NULL, //A8
|
NULL, NULL, NULL, NULL, NULL, NULL, "voldown", NULL, //A8
|
||||||
"volup", NULL, "webhome", "kp,", NULL, "kp/", NULL, "sysrq", //B0
|
"volup", NULL, "webhome", "kp,", NULL, "kp/", NULL, "sysrq", //B0
|
||||||
"ralt", NULL, NULL, NULL, NULL, NULL, NULL, NULL, //B8
|
"ralt", NULL, NULL, NULL, NULL, NULL, NULL, NULL, //B8
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, "home", //C0
|
NULL, NULL, NULL, NULL, NULL, "pause", NULL, "home", //C0
|
||||||
"uparrow", "pgup", NULL, "leftarrow",NULL, "rightarrow",NULL, "end", //C8
|
"uparrow", "pgup", NULL, "leftarrow",NULL, "rightarrow",NULL, "end", //C8
|
||||||
"downarrow","pgdn", "ins", "del", NULL, NULL, NULL, NULL, //D0
|
"downarrow","pgdn", "ins", "del", NULL, NULL, NULL, NULL, //D0
|
||||||
NULL, NULL, NULL, "lwin", "rwin", "apps", "power", "sleep", //D8
|
NULL, NULL, NULL, "lwin", "rwin", "apps", "power", "sleep", //D8
|
||||||
NULL, NULL, NULL, "wake", NULL, "search", "favorites","refresh", //E0
|
NULL, NULL, NULL, "wake", NULL, "search", "favorites","refresh", //E0
|
||||||
"webstop", "webforward","webback", "mycomputer","mail", "mediaselect",NULL, NULL, //E8
|
"webstop", "webforward","webback", "mycomputer","mail", "mediaselect",NULL, NULL, //E8
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //F0
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //F0
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, "pause", //F8
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //F8
|
||||||
|
|
||||||
// non-keyboard buttons that can be bound
|
// non-keyboard buttons that can be bound
|
||||||
"mouse1", "mouse2", "mouse3", "mouse4", // 8 mouse buttons
|
"mouse1", "mouse2", "mouse3", "mouse4", // 8 mouse buttons
|
||||||
|
|
|
@ -104,6 +104,7 @@ enum ESkillLevels
|
||||||
// DOOM keyboard definition. Everything below 0x100 matches
|
// DOOM keyboard definition. Everything below 0x100 matches
|
||||||
// a DirectInput key code.
|
// a DirectInput key code.
|
||||||
//
|
//
|
||||||
|
#define KEY_PAUSE 0xc5 // DIK_PAUSE
|
||||||
#define KEY_RIGHTARROW 0xcd // DIK_RIGHT
|
#define KEY_RIGHTARROW 0xcd // DIK_RIGHT
|
||||||
#define KEY_LEFTARROW 0xcb // DIK_LEFT
|
#define KEY_LEFTARROW 0xcb // DIK_LEFT
|
||||||
#define KEY_UPARROW 0xc8 // DIK_UP
|
#define KEY_UPARROW 0xc8 // DIK_UP
|
||||||
|
@ -126,7 +127,6 @@ enum ESkillLevels
|
||||||
#define KEY_F12 0x58 // DIK_F12
|
#define KEY_F12 0x58 // DIK_F12
|
||||||
|
|
||||||
#define KEY_BACKSPACE 0x0e // DIK_BACK
|
#define KEY_BACKSPACE 0x0e // DIK_BACK
|
||||||
#define KEY_PAUSE 0xff
|
|
||||||
|
|
||||||
#define KEY_EQUALS 0x0d // DIK_EQUALS
|
#define KEY_EQUALS 0x0d // DIK_EQUALS
|
||||||
#define KEY_MINUS 0x0c // DIK_MINUS
|
#define KEY_MINUS 0x0c // DIK_MINUS
|
||||||
|
|
|
@ -124,12 +124,11 @@ extern bool SpawnEAXWindow;
|
||||||
|
|
||||||
static HMODULE DInputDLL;
|
static HMODULE DInputDLL;
|
||||||
|
|
||||||
static void KeyRead ();
|
|
||||||
static BOOL I_StartupKeyboard ();
|
|
||||||
static HRESULT InitJoystick ();
|
static HRESULT InitJoystick ();
|
||||||
|
|
||||||
bool GUICapture;
|
bool GUICapture;
|
||||||
extern FMouse *Mouse;
|
extern FMouse *Mouse;
|
||||||
|
extern FInputDevice *Keyboard;
|
||||||
|
|
||||||
bool VidResizing;
|
bool VidResizing;
|
||||||
|
|
||||||
|
@ -294,8 +293,6 @@ CVAR (Float, joy_forwardspeed, -1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
CVAR (Float, joy_sidespeed, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR (Float, joy_sidespeed, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
CVAR (Float, joy_upspeed, -1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR (Float, joy_upspeed, -1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
|
|
||||||
// set this to false to make keypad-enter a usable separate key!
|
|
||||||
CVAR (Bool, k_mergekeys, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|
||||||
CVAR (Bool, k_allowfullscreentoggle, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR (Bool, k_allowfullscreentoggle, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
|
|
||||||
static FBaseCVar * const JoyConfigVars[] =
|
static FBaseCVar * const JoyConfigVars[] =
|
||||||
|
@ -307,31 +304,9 @@ static FBaseCVar * const JoyConfigVars[] =
|
||||||
};
|
};
|
||||||
|
|
||||||
static BYTE KeyState[256];
|
static BYTE KeyState[256];
|
||||||
static BYTE DIKState[2][NUM_KEYS];
|
/*static BYTE DIKState[2][NUM_KEYS];
|
||||||
static int KeysReadCount;
|
|
||||||
static int ActiveDIKState;
|
static int ActiveDIKState;
|
||||||
|
|
||||||
// Convert DIK_* code to ASCII using Qwerty keymap
|
|
||||||
static const BYTE Convert [256] =
|
|
||||||
{
|
|
||||||
// 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
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
static void FlushDIKState (int low=0, int high=NUM_KEYS-1)
|
static void FlushDIKState (int low=0, int high=NUM_KEYS-1)
|
||||||
{
|
{
|
||||||
|
@ -352,7 +327,7 @@ static void FlushDIKState (int low=0, int high=NUM_KEYS-1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
extern int chatmodeon;
|
extern int chatmodeon;
|
||||||
|
|
||||||
static void I_CheckGUICapture ()
|
static void I_CheckGUICapture ()
|
||||||
|
@ -373,21 +348,32 @@ static void I_CheckGUICapture ()
|
||||||
GUICapture = wantCapt;
|
GUICapture = wantCapt;
|
||||||
if (wantCapt)
|
if (wantCapt)
|
||||||
{
|
{
|
||||||
FlushDIKState ();
|
// FlushDIKState ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CallHook(FInputDevice *device, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
|
||||||
|
{
|
||||||
|
if (device == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*result = 0;
|
||||||
|
return device->WndProcHook(hWnd, message, wParam, lParam, result);
|
||||||
|
}
|
||||||
|
|
||||||
LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
if (Mouse != NULL)
|
LRESULT result;
|
||||||
{
|
|
||||||
LRESULT result = 0;
|
|
||||||
|
|
||||||
if (Mouse->WndProcHook(hWnd, message, wParam, lParam, &result))
|
if (CallHook(Keyboard, hWnd, message, wParam, lParam, &result))
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
if (CallHook(Mouse, hWnd, message, wParam, lParam, &result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
event_t event;
|
event_t event;
|
||||||
|
|
||||||
|
@ -424,7 +410,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
case WM_KILLFOCUS:
|
case WM_KILLFOCUS:
|
||||||
if (g_pKey) g_pKey->Unacquire ();
|
if (g_pKey) g_pKey->Unacquire ();
|
||||||
|
|
||||||
FlushDIKState ();
|
// FlushDIKState ();
|
||||||
HaveFocus = false;
|
HaveFocus = false;
|
||||||
I_CheckNativeMouse (true); // Make sure mouse gets released right away
|
I_CheckNativeMouse (true); // Make sure mouse gets released right away
|
||||||
break;
|
break;
|
||||||
|
@ -510,6 +496,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
if (message == WM_KEYUP)
|
if (message == WM_KEYUP)
|
||||||
{
|
{
|
||||||
event.type = EV_KeyUp;
|
event.type = EV_KeyUp;
|
||||||
|
@ -544,6 +531,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
DIKState[ActiveDIKState][event.data1] = (event.type == EV_KeyDown);
|
DIKState[ActiveDIKState][event.data1] = (event.type == EV_KeyDown);
|
||||||
D_PostEvent (&event);
|
D_PostEvent (&event);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1248,11 +1236,9 @@ bool I_InitInput (void *hwnd)
|
||||||
// Free all input resources
|
// Free all input resources
|
||||||
void I_ShutdownInput ()
|
void I_ShutdownInput ()
|
||||||
{
|
{
|
||||||
if (g_pKey)
|
if (Keyboard != NULL)
|
||||||
{
|
{
|
||||||
g_pKey->Unacquire ();
|
delete Keyboard;
|
||||||
g_pKey->Release ();
|
|
||||||
g_pKey = NULL;
|
|
||||||
}
|
}
|
||||||
if (Mouse != NULL)
|
if (Mouse != NULL)
|
||||||
{
|
{
|
||||||
|
@ -1281,120 +1267,6 @@ void I_ShutdownInput ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the keyboard
|
|
||||||
static BOOL I_StartupKeyboard (void)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
// Obtain an interface to the system key device.
|
|
||||||
if (g_pdi3)
|
|
||||||
{
|
|
||||||
hr = g_pdi3->CreateDevice (GUID_SysKeyboard, (LPDIRECTINPUTDEVICE*)&g_pKey, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = g_pdi->CreateDevice (GUID_SysKeyboard, &g_pKey, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
I_FatalError ("Could not create keyboard device");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the data format to "keyboard format".
|
|
||||||
hr = g_pKey->SetDataFormat (&c_dfDIKeyboard);
|
|
||||||
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
I_FatalError ("Could not set keyboard data format");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the cooperative level.
|
|
||||||
hr = g_pKey->SetCooperativeLevel (Window, DISCL_FOREGROUND|DISCL_NONEXCLUSIVE);
|
|
||||||
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
I_FatalError("Could not set keyboard cooperative level");
|
|
||||||
}
|
|
||||||
|
|
||||||
g_pKey->Acquire ();
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void KeyRead ()
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
event_t event;
|
|
||||||
BYTE *fromState, *toState;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (g_pKey == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset (&event, 0, sizeof(event));
|
|
||||||
fromState = DIKState[ActiveDIKState];
|
|
||||||
toState = DIKState[ActiveDIKState ^ 1];
|
|
||||||
|
|
||||||
hr = g_pKey->GetDeviceState (256, toState);
|
|
||||||
if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED)
|
|
||||||
{
|
|
||||||
hr = g_pKey->Acquire ();
|
|
||||||
if (hr != DI_OK)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
hr = g_pKey->GetDeviceState (256, toState);
|
|
||||||
}
|
|
||||||
if (hr != DI_OK)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Successfully got the buffer
|
|
||||||
KeysReadCount++;
|
|
||||||
ActiveDIKState ^= 1;
|
|
||||||
|
|
||||||
// Copy key states not handled here from the old to the new buffer
|
|
||||||
memcpy (toState + 256, fromState + 256, NUM_KEYS - 256);
|
|
||||||
toState[DIK_TAB] = fromState[DIK_TAB];
|
|
||||||
toState[DIK_NUMLOCK] = fromState[DIK_NUMLOCK];
|
|
||||||
|
|
||||||
if (k_mergekeys)
|
|
||||||
{
|
|
||||||
// "Merge" multiple keys that are considered to be the same.
|
|
||||||
// Also clear out the alternate versions after merging.
|
|
||||||
toState[DIK_RETURN] |= toState[DIK_NUMPADENTER];
|
|
||||||
toState[DIK_LMENU] |= toState[DIK_RMENU];
|
|
||||||
toState[DIK_LCONTROL] |= toState[DIK_RCONTROL];
|
|
||||||
toState[DIK_LSHIFT] |= toState[DIK_RSHIFT];
|
|
||||||
|
|
||||||
toState[DIK_NUMPADENTER] = 0;
|
|
||||||
toState[DIK_RMENU] = 0;
|
|
||||||
toState[DIK_RCONTROL] = 0;
|
|
||||||
toState[DIK_RSHIFT] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now generate events for any keys that differ between the states
|
|
||||||
if (!GUICapture)
|
|
||||||
{
|
|
||||||
for (i = 1; i < 256; i++)
|
|
||||||
{
|
|
||||||
if (toState[i] != fromState[i])
|
|
||||||
{
|
|
||||||
event.type = toState[i] ? EV_KeyDown : EV_KeyUp;
|
|
||||||
event.data1 = i;
|
|
||||||
event.data2 = Convert[i];
|
|
||||||
event.data3 = (toState[DIK_LSHIFT] ? GKM_SHIFT : 0) |
|
|
||||||
(toState[DIK_LCONTROL] ? GKM_CTRL : 0) |
|
|
||||||
(toState[DIK_LMENU] ? GKM_ALT : 0);
|
|
||||||
D_PostEvent (&event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void I_GetEvent ()
|
void I_GetEvent ()
|
||||||
{
|
{
|
||||||
MSG mess;
|
MSG mess;
|
||||||
|
@ -1414,8 +1286,10 @@ void I_GetEvent ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyRead ();
|
if (Keyboard != NULL)
|
||||||
|
{
|
||||||
|
Keyboard->ProcessInput();
|
||||||
|
}
|
||||||
if (Mouse != NULL)
|
if (Mouse != NULL)
|
||||||
{
|
{
|
||||||
Mouse->ProcessInput();
|
Mouse->ProcessInput();
|
||||||
|
|
|
@ -86,6 +86,7 @@ protected:
|
||||||
|
|
||||||
void I_StartupMouse();
|
void I_StartupMouse();
|
||||||
void I_CheckNativeMouse(bool prefer_native);
|
void I_CheckNativeMouse(bool prefer_native);
|
||||||
|
void I_StartupKeyboard();
|
||||||
|
|
||||||
// USB HID usage page numbers
|
// USB HID usage page numbers
|
||||||
#define HID_GENERIC_DESKTOP_PAGE 0x01
|
#define HID_GENERIC_DESKTOP_PAGE 0x01
|
||||||
|
|
301
src/win32/i_keyboard.cpp
Normal file
301
src/win32/i_keyboard.cpp
Normal file
|
@ -0,0 +1,301 @@
|
||||||
|
// HEADER FILES ------------------------------------------------------------
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#define DIRECTINPUT_VERSION 0x800
|
||||||
|
#define _WIN32_WINNT 0x0501
|
||||||
|
#include <windows.h>
|
||||||
|
#include <dinput.h>
|
||||||
|
|
||||||
|
#define USE_WINDOWS_DWORD
|
||||||
|
#include "i_input.h"
|
||||||
|
#include "i_system.h"
|
||||||
|
#include "d_event.h"
|
||||||
|
#include "d_gui.h"
|
||||||
|
#include "c_cvars.h"
|
||||||
|
#include "doomdef.h"
|
||||||
|
#include "doomstat.h"
|
||||||
|
#include "win32iface.h"
|
||||||
|
#include "rawinput.h"
|
||||||
|
|
||||||
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define DINPUT_BUFFERSIZE 32
|
||||||
|
|
||||||
|
// TYPES -------------------------------------------------------------------
|
||||||
|
|
||||||
|
class FDInputKeyboard : public FInputDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FDInputKeyboard();
|
||||||
|
~FDInputKeyboard();
|
||||||
|
|
||||||
|
bool GetDevice();
|
||||||
|
void ProcessInput();
|
||||||
|
bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
LPDIRECTINPUTDEVICE8 Device;
|
||||||
|
BYTE KeyStates[256/8];
|
||||||
|
|
||||||
|
int CheckKey(int keynum) const
|
||||||
|
{
|
||||||
|
return KeyStates[keynum >> 3] & (1 << (keynum & 7));
|
||||||
|
}
|
||||||
|
void SetKey(int keynum, bool down)
|
||||||
|
{
|
||||||
|
if (down)
|
||||||
|
{
|
||||||
|
KeyStates[keynum >> 3] |= 1 << (keynum & 7);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KeyStates[keynum >> 3] &= ~(1 << (keynum & 7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
|
||||||
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||||
|
|
||||||
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||||
|
|
||||||
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
|
extern HWND Window;
|
||||||
|
extern LPDIRECTINPUT8 g_pdi;
|
||||||
|
extern LPDIRECTINPUT g_pdi3;
|
||||||
|
extern bool GUICapture;
|
||||||
|
extern bool HaveFocus;
|
||||||
|
|
||||||
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
|
// Convert DIK_* code to ASCII using Qwerty keymap
|
||||||
|
static const BYTE Convert [256] =
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
|
FInputDevice *Keyboard;
|
||||||
|
|
||||||
|
// Set this to false to make keypad-enter a usable separate key.
|
||||||
|
CVAR (Bool, k_mergekeys, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
|
|
||||||
|
// CODE --------------------------------------------------------------------
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FDInputKeyboard - Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FDInputKeyboard::FDInputKeyboard()
|
||||||
|
{
|
||||||
|
Device = NULL;
|
||||||
|
memset(KeyStates, 0, sizeof(KeyStates));
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FDInputKeyboard - Destructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FDInputKeyboard::~FDInputKeyboard()
|
||||||
|
{
|
||||||
|
if (Device != NULL)
|
||||||
|
{
|
||||||
|
Device->Release();
|
||||||
|
Device = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FDInputKeyboard :: GetDevice
|
||||||
|
//
|
||||||
|
// Create the device interface and initialize it.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool FDInputKeyboard::GetDevice()
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
if (g_pdi3 != NULL)
|
||||||
|
{ // DirectInput3 interface
|
||||||
|
hr = g_pdi3->CreateDevice(GUID_SysKeyboard, (LPDIRECTINPUTDEVICE*)&Device, NULL);
|
||||||
|
}
|
||||||
|
else if (g_pdi != NULL)
|
||||||
|
{ // DirectInput8 interface
|
||||||
|
hr = g_pdi->CreateDevice(GUID_SysKeyboard, &Device, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = -1;
|
||||||
|
}
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Yes, this is a keyboard.
|
||||||
|
hr = Device->SetDataFormat(&c_dfDIKeyboard);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
ufailit:
|
||||||
|
Device->Release();
|
||||||
|
Device = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Set cooperative level.
|
||||||
|
hr = Device->SetCooperativeLevel(Window, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto ufailit;
|
||||||
|
}
|
||||||
|
// Set buffer size so we can use buffered input.
|
||||||
|
DIPROPDWORD prop;
|
||||||
|
prop.diph.dwSize = sizeof(prop);
|
||||||
|
prop.diph.dwHeaderSize = sizeof(prop.diph);
|
||||||
|
prop.diph.dwObj = 0;
|
||||||
|
prop.diph.dwHow = DIPH_DEVICE;
|
||||||
|
prop.dwData = DINPUT_BUFFERSIZE;
|
||||||
|
hr = Device->SetProperty(DIPROP_BUFFERSIZE, &prop.diph);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto ufailit;
|
||||||
|
}
|
||||||
|
Device->Acquire();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FDInputKeyboard :: ProcessInput
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FDInputKeyboard::ProcessInput()
|
||||||
|
{
|
||||||
|
DIDEVICEOBJECTDATA od;
|
||||||
|
DWORD dwElements;
|
||||||
|
HRESULT hr;
|
||||||
|
int key;
|
||||||
|
bool foreground = (GetForegroundWindow() == Window);
|
||||||
|
|
||||||
|
event_t ev = { 0 };
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
DWORD cbObjectData = g_pdi3 ? sizeof(DIDEVICEOBJECTDATA_DX3) : sizeof(DIDEVICEOBJECTDATA);
|
||||||
|
dwElements = 1;
|
||||||
|
hr = Device->GetDeviceData(cbObjectData, &od, &dwElements, 0);
|
||||||
|
if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED)
|
||||||
|
{
|
||||||
|
Device->Acquire();
|
||||||
|
hr = Device->GetDeviceData(cbObjectData, &od, &dwElements, 0);
|
||||||
|
}
|
||||||
|
if (FAILED(hr) || !dwElements)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = od.dwOfs;
|
||||||
|
// Printf("buffer ofs=%02x data=%02x\n", od.dwOfs, od.dwData);
|
||||||
|
if (key >= 1 && key <= 255)
|
||||||
|
{
|
||||||
|
if (k_mergekeys)
|
||||||
|
{
|
||||||
|
// "Merge" multiple keys that are considered to be the same.
|
||||||
|
if (key == DIK_NUMPADENTER)
|
||||||
|
{
|
||||||
|
key = DIK_RETURN;
|
||||||
|
}
|
||||||
|
else if (key == DIK_RMENU)
|
||||||
|
{
|
||||||
|
key = DIK_LMENU;
|
||||||
|
}
|
||||||
|
else if (key == DIK_RCONTROL)
|
||||||
|
{
|
||||||
|
key = DIK_LCONTROL;
|
||||||
|
}
|
||||||
|
else if (key == DIK_RSHIFT)
|
||||||
|
{
|
||||||
|
key = DIK_LSHIFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Generate an event, but only if it isn't a repeat of the existing state.
|
||||||
|
if (od.dwData & 0x80)
|
||||||
|
{
|
||||||
|
if (!foreground || GUICapture)
|
||||||
|
{ // Do not generate key down events if we are in the background
|
||||||
|
// or in "GUI Capture" mode.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (CheckKey(key))
|
||||||
|
{ // Key is already down.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SetKey(key, true);
|
||||||
|
ev.type = EV_KeyDown;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!CheckKey(key))
|
||||||
|
{ // Key is already up.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SetKey(key, false);
|
||||||
|
ev.type = EV_KeyUp;
|
||||||
|
}
|
||||||
|
ev.data1 = key;
|
||||||
|
ev.data2 = Convert[key];
|
||||||
|
D_PostEvent(&ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FDInputKeyboard :: WndProcHook
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool FDInputKeyboard::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// I_StartupKeyboard
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void I_StartupKeyboard()
|
||||||
|
{
|
||||||
|
Keyboard = new FDInputKeyboard;
|
||||||
|
if (!Keyboard->GetDevice())
|
||||||
|
{
|
||||||
|
delete Keyboard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -762,7 +762,6 @@ void FDInputMouse::ProcessInput()
|
||||||
DIDEVICEOBJECTDATA od;
|
DIDEVICEOBJECTDATA od;
|
||||||
DWORD dwElements;
|
DWORD dwElements;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
int count = 0;
|
|
||||||
int dx, dy;
|
int dx, dy;
|
||||||
|
|
||||||
dx = 0;
|
dx = 0;
|
||||||
|
@ -787,8 +786,6 @@ void FDInputMouse::ProcessInput()
|
||||||
if (FAILED(hr) || !dwElements)
|
if (FAILED(hr) || !dwElements)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
count++;
|
|
||||||
|
|
||||||
/* Look at the element to see what happened */
|
/* Look at the element to see what happened */
|
||||||
// GCC does not like putting the DIMOFS_ macros in case statements,
|
// GCC does not like putting the DIMOFS_ macros in case statements,
|
||||||
// so use ifs instead.
|
// so use ifs instead.
|
||||||
|
|
|
@ -1976,6 +1976,10 @@
|
||||||
RelativePath=".\src\win32\i_input.h"
|
RelativePath=".\src\win32\i_input.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\win32\i_keyboard.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\win32\i_main.cpp"
|
RelativePath=".\src\win32\i_main.cpp"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in a new issue