mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-15 16:51:31 +00:00
- SetCursorState() now calls ShowCursor() again, because capturing the mouse
with RIDEV_NOLEGACY apparently prevents SetCursor() from doing anything. - Split mouse code off from i_input.cpp into i_mouse.cpp and added raw mouse handling. (WM_INPUT obsoleted most of DirectInput for XP.) - Fixed: Similar to the Win32 mouse, using the DirectInput mouse in windowed mode, if you alt-tabbed away and then clicked on the window's title bar, mouse input would be frozen until the mouse was ungrabbed again. SVN r1601 (trunk)
This commit is contained in:
parent
273758344f
commit
0c4c90ac89
10 changed files with 1316 additions and 798 deletions
|
@ -1,4 +1,13 @@
|
|||
May 23, 2009 (Changes by Graf Zahl)
|
||||
May 23, 2009
|
||||
- SetCursorState() now calls ShowCursor() again, because capturing the mouse
|
||||
with RIDEV_NOLEGACY apparently prevents SetCursor() from doing anything.
|
||||
- Split mouse code off from i_input.cpp into i_mouse.cpp and added raw mouse
|
||||
handling. (WM_INPUT obsoleted most of DirectInput for XP.)
|
||||
- Fixed: Similar to the Win32 mouse, using the DirectInput mouse in windowed
|
||||
mode, if you alt-tabbed away and then clicked on the window's title bar,
|
||||
mouse input would be frozen until the mouse was ungrabbed again.
|
||||
|
||||
May 23, 2009 (Changes by Graf Zahl)
|
||||
- Fixed: When setting up a deep water sector with Transfer_Heights the floorclip
|
||||
information of all actors in the sector needs to be updated.
|
||||
|
||||
|
@ -6,6 +15,7 @@ May 22, 2009 (Changes by Graf Zahl)
|
|||
- Fixed: A_CountdownArg and A_Die must ensure a certain kill.
|
||||
|
||||
May 22, 2009
|
||||
- Moved SetSoundPaused() out of i_input.cpp and into s_sound.cpp.
|
||||
- Fixed: When using Win32 mouse, windowed mode, alt-tabbing away and then
|
||||
clicking on the window's title bar moved it practically off the screen.
|
||||
- Beginnings of i_input.cpp rewrite: Win32 and DirectInput mouse handling has
|
||||
|
|
|
@ -398,6 +398,7 @@ if( WIN32 )
|
|||
win32/i_cd.cpp
|
||||
win32/i_crash.cpp
|
||||
win32/i_input.cpp
|
||||
win32/i_mouse.cpp
|
||||
win32/i_main.cpp
|
||||
win32/i_movie.cpp
|
||||
win32/i_system.cpp
|
||||
|
|
|
@ -112,6 +112,9 @@ typedef enum
|
|||
BT_USER4 = 1<<24,
|
||||
} buttoncode_t;
|
||||
|
||||
// Called by IO functions when input is detected.
|
||||
void D_PostEvent (const event_t* ev);
|
||||
|
||||
|
||||
//
|
||||
// GLOBAL VARIABLES
|
||||
|
|
|
@ -38,8 +38,6 @@ struct event_t;
|
|||
//
|
||||
void D_DoomMain (void);
|
||||
|
||||
// Called by IO functions when input is detected.
|
||||
void D_PostEvent (const event_t* ev);
|
||||
|
||||
void D_Display ();
|
||||
|
||||
|
|
|
@ -21,8 +21,7 @@
|
|||
static void I_CheckGUICapture ();
|
||||
static void I_CheckNativeMouse ();
|
||||
|
||||
static bool GUICapture;
|
||||
static bool NativeMouse = true;
|
||||
bool GUICapture;
|
||||
|
||||
extern int paused;
|
||||
|
||||
|
|
|
@ -103,34 +103,14 @@
|
|||
#include "d_event.h"
|
||||
#include "v_text.h"
|
||||
|
||||
#define DINPUT_BUFFERSIZE 32
|
||||
// Prototypes and declarations.
|
||||
#include "rawinput.h"
|
||||
// Definitions
|
||||
#define RIF(name, ret, args) \
|
||||
name##Proto My##name;
|
||||
#include "rawinput.h"
|
||||
|
||||
|
||||
class FInputDevice
|
||||
{
|
||||
public:
|
||||
virtual bool GetDevice() = 0;
|
||||
virtual void ProcessInput() = 0;
|
||||
virtual bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
|
||||
};
|
||||
|
||||
class FMouse : public FInputDevice
|
||||
{
|
||||
public:
|
||||
FMouse();
|
||||
|
||||
virtual void Grab() = 0;
|
||||
virtual void Ungrab() = 0;
|
||||
|
||||
protected:
|
||||
void PostMouseMove(int x, int y);
|
||||
void WheelMoved(int wheelmove);
|
||||
void PostButtonEvent(int button, bool down);
|
||||
void ClearButtonState();
|
||||
|
||||
int LastX, LastY; // for m_filter
|
||||
WORD ButtonState; // bit mask of current button states (1=down, 0=up)
|
||||
};
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define INGAME_PRIORITY_CLASS NORMAL_PRIORITY_CLASS
|
||||
|
@ -139,6 +119,7 @@ protected:
|
|||
#define INGAME_PRIORITY_CLASS NORMAL_PRIORITY_CLASS
|
||||
#endif
|
||||
|
||||
static void FindRawInputFunctions();
|
||||
BOOL DI_InitJoy (void);
|
||||
|
||||
extern HINSTANCE g_hInst;
|
||||
|
@ -151,15 +132,10 @@ static HMODULE DInputDLL;
|
|||
|
||||
static void KeyRead ();
|
||||
static BOOL I_StartupKeyboard ();
|
||||
static void I_StartupMouse ();
|
||||
static void CenterMouse_Win32 (LONG curx, LONG cury);
|
||||
static void DI_Acquire (LPDIRECTINPUTDEVICE8 mouse);
|
||||
static void DI_Unacquire (LPDIRECTINPUTDEVICE8 mouse);
|
||||
static void SetCursorState (bool visible);
|
||||
static HRESULT InitJoystick ();
|
||||
|
||||
static bool GUICapture;
|
||||
static bool NativeMouse;
|
||||
bool GUICapture;
|
||||
extern FMouse *Mouse;
|
||||
|
||||
bool VidResizing;
|
||||
|
||||
|
@ -175,15 +151,12 @@ EXTERN_CVAR (String, language)
|
|||
EXTERN_CVAR (Bool, lookstrafe)
|
||||
|
||||
|
||||
typedef enum { none, win32, dinput } mousemode_t;
|
||||
static mousemode_t mousemode = none;
|
||||
|
||||
extern BOOL paused;
|
||||
static bool HaveFocus = false;
|
||||
bool HaveFocus;
|
||||
static bool noidle = false;
|
||||
|
||||
static LPDIRECTINPUT8 g_pdi;
|
||||
static LPDIRECTINPUT g_pdi3;
|
||||
LPDIRECTINPUT8 g_pdi;
|
||||
LPDIRECTINPUT g_pdi3;
|
||||
|
||||
static LPDIRECTINPUTDEVICE8 g_pJoy;
|
||||
|
||||
|
@ -194,10 +167,6 @@ static LPDIRECTINPUTDEVICE8 g_pJoy;
|
|||
|
||||
static LPDIRECTINPUTDEVICE8 g_pKey;
|
||||
|
||||
FMouse *Mouse;
|
||||
|
||||
HCURSOR TheArrowCursor, TheInvisibleCursor;
|
||||
|
||||
TArray<GUIDName> JoystickNames;
|
||||
|
||||
static DIDEVCAPS JoystickCaps;
|
||||
|
@ -225,10 +194,6 @@ static const BYTE POVButtons[9] = { 0x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x
|
|||
BOOL AppActive = TRUE;
|
||||
int SessionState = 0;
|
||||
|
||||
CVAR (Bool, use_mouse, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, m_noprescale, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, m_filter, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
||||
CVAR (Bool, use_joystick, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
||||
CUSTOM_CVAR (GUID, joy_guid, NULL, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
|
||||
|
@ -347,26 +312,6 @@ static FBaseCVar * const JoyConfigVars[] =
|
|||
&joy_upspeed
|
||||
};
|
||||
|
||||
CUSTOM_CVAR (Int, in_mouse, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
|
||||
{
|
||||
if (self < 0)
|
||||
{
|
||||
self = 0;
|
||||
}
|
||||
else if (self > 2)
|
||||
{
|
||||
self = 2;
|
||||
}
|
||||
else if (g_pdi == NULL && g_pdi3 == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
I_StartupMouse();
|
||||
}
|
||||
}
|
||||
|
||||
static BYTE KeyState[256];
|
||||
static BYTE DIKState[2][NUM_KEYS];
|
||||
static int KeysReadCount;
|
||||
|
@ -439,53 +384,11 @@ static void I_CheckGUICapture ()
|
|||
}
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Int, mouse_capturemode, 1, CVAR_GLOBALCONFIG|CVAR_ARCHIVE)
|
||||
{
|
||||
if (self < 0) self = 0;
|
||||
else if (self > 2) self = 2;
|
||||
}
|
||||
|
||||
static bool inGame()
|
||||
{
|
||||
switch (mouse_capturemode)
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
return gamestate == GS_LEVEL;
|
||||
case 1:
|
||||
return gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_FINALE;
|
||||
case 2:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void I_CheckNativeMouse(bool preferNative)
|
||||
{
|
||||
bool wantNative = !HaveFocus ||
|
||||
((!screen || !screen->IsFullscreen()) &&
|
||||
(!inGame() || GUICapture || paused || preferNative || !use_mouse || demoplayback));
|
||||
|
||||
//Printf ("%d %d %d\n", wantNative, preferNative, NativeMouse);
|
||||
|
||||
if (wantNative != NativeMouse)
|
||||
{
|
||||
if (wantNative)
|
||||
{
|
||||
Mouse->Ungrab();
|
||||
}
|
||||
else
|
||||
{
|
||||
Mouse->Grab();
|
||||
}
|
||||
NativeMouse = wantNative;
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
|
@ -507,6 +410,8 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
case WM_HOTKEY:
|
||||
break;
|
||||
|
||||
case WM_INPUT:
|
||||
|
||||
case WM_PAINT:
|
||||
if (screen != NULL && 0)
|
||||
{
|
||||
|
@ -1278,14 +1183,13 @@ bool I_InitInput (void *hwnd)
|
|||
Printf ("I_InitInput\n");
|
||||
atterm (I_ShutdownInput);
|
||||
|
||||
NativeMouse = true;
|
||||
|
||||
noidle = !!Args->CheckParm ("-noidle");
|
||||
g_pdi = NULL;
|
||||
g_pdi3 = NULL;
|
||||
|
||||
// Try for DirectInput 8 first, then DirectInput 3 for NT 4's benefit.
|
||||
FindRawInputFunctions();
|
||||
|
||||
// Try for DirectInput 8 first, then DirectInput 3 for NT 4's benefit.
|
||||
DInputDLL = LoadLibrary("dinput8.dll");
|
||||
if (DInputDLL != NULL)
|
||||
{
|
||||
|
@ -1383,16 +1287,6 @@ void I_ShutdownInput ()
|
|||
}
|
||||
}
|
||||
|
||||
static void SetCursorState(bool visible)
|
||||
{
|
||||
HCURSOR usingCursor = visible ? TheArrowCursor : TheInvisibleCursor;
|
||||
SetClassLongPtr(Window, GCLP_HCURSOR, (LONG_PTR)usingCursor);
|
||||
if (HaveFocus)
|
||||
{
|
||||
SetCursor(usingCursor);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the keyboard
|
||||
static BOOL I_StartupKeyboard (void)
|
||||
{
|
||||
|
@ -1619,6 +1513,16 @@ CCMD (playmovie)
|
|||
I_PlayMovie (argv[1]);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FInputDevice - Destructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FInputDevice::~FInputDevice()
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FInputDevice :: WndProcHook
|
||||
|
@ -1634,678 +1538,21 @@ bool FInputDevice::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMouse - Constructor
|
||||
// FindRawInputFunctions
|
||||
//
|
||||
// Finds functions for raw input, if available.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FMouse::FMouse()
|
||||
static void FindRawInputFunctions()
|
||||
{
|
||||
LastX = LastY = 0;
|
||||
ButtonState = 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMouse :: PostMouseMove
|
||||
//
|
||||
// Posts a mouse movement event, potentially averaging it with the previous
|
||||
// movement. If there is no movement to post, then no event is generated.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FMouse::PostMouseMove(int x, int y)
|
||||
{
|
||||
event_t ev = { 0 };
|
||||
|
||||
if (m_filter)
|
||||
{
|
||||
ev.x = (x + LastX) / 2;
|
||||
ev.y = (y + LastY) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ev.x = x;
|
||||
ev.y = y;
|
||||
}
|
||||
LastX = x;
|
||||
LastY = y;
|
||||
if (ev.x | ev.y)
|
||||
{
|
||||
ev.type = EV_Mouse;
|
||||
D_PostEvent(&ev);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMouse :: WheelMoved
|
||||
//
|
||||
// Generates events for a wheel move. Events are generated for every
|
||||
// WHEEL_DELTA units that the wheel has moved. In normal mode, each move
|
||||
// generates both a key down and a key up event. In GUI mode, only one
|
||||
// event is generated for each unit of movement.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FMouse::WheelMoved(int wheelmove)
|
||||
{
|
||||
event_t ev = { 0 };
|
||||
int dir;
|
||||
|
||||
if (GUICapture)
|
||||
{
|
||||
ev.type = EV_GUI_Event;
|
||||
if (wheelmove < 0)
|
||||
{
|
||||
dir = WHEEL_DELTA;
|
||||
ev.subtype = EV_GUI_WheelDown;
|
||||
}
|
||||
else
|
||||
{
|
||||
dir = -WHEEL_DELTA;
|
||||
ev.subtype = EV_GUI_WheelUp;
|
||||
}
|
||||
ev.data3 = ((KeyState[VK_SHIFT]&128) ? GKM_SHIFT : 0) |
|
||||
((KeyState[VK_CONTROL]&128) ? GKM_CTRL : 0) |
|
||||
((KeyState[VK_MENU]&128) ? GKM_ALT : 0);
|
||||
while (abs(wheelmove) >= WHEEL_DELTA)
|
||||
{
|
||||
D_PostEvent(&ev);
|
||||
wheelmove += dir;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wheelmove < 0)
|
||||
{
|
||||
dir = WHEEL_DELTA;
|
||||
ev.data1 = KEY_MWHEELDOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
dir = -WHEEL_DELTA;
|
||||
ev.data1 = KEY_MWHEELUP;
|
||||
}
|
||||
while (abs(wheelmove) >= WHEEL_DELTA)
|
||||
{
|
||||
ev.type = EV_KeyDown;
|
||||
D_PostEvent(&ev);
|
||||
ev.type = EV_KeyUp;
|
||||
D_PostEvent(&ev);
|
||||
wheelmove += dir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMouse :: PostButtonEvent
|
||||
//
|
||||
// Posts a mouse button up/down event. Down events are always posted. Up
|
||||
// events will only be sent if the button is currently marked as down.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FMouse::PostButtonEvent(int button, bool down)
|
||||
{
|
||||
event_t ev = { 0 };
|
||||
int mask = 1 << button;
|
||||
|
||||
ev.data1 = KEY_MOUSE1 + button;
|
||||
if (down)
|
||||
{
|
||||
ButtonState |= mask;
|
||||
ev.type = EV_KeyDown;
|
||||
D_PostEvent(&ev);
|
||||
}
|
||||
else if (ButtonState & mask)
|
||||
{
|
||||
ButtonState &= ~mask;
|
||||
ev.type = EV_KeyUp;
|
||||
D_PostEvent(&ev);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMouse :: ClearButtonState
|
||||
//
|
||||
// Sends key up events for all buttons that are currently down and marks
|
||||
// them as up. Used when focus is lost and we can no longer track up events,
|
||||
// so get them marked up right away.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FMouse::ClearButtonState()
|
||||
{
|
||||
if (ButtonState != 0)
|
||||
{
|
||||
int i, mask;
|
||||
event_t ev = { 0 };
|
||||
|
||||
ev.type = EV_KeyUp;
|
||||
for (i = sizeof(ButtonState) * 8, mask = 1; i > 0; --i, mask <<= 1)
|
||||
{
|
||||
if (ButtonState & mask)
|
||||
{
|
||||
ev.data1 = KEY_MOUSE1 + (int)sizeof(ButtonState) * 8 - i;
|
||||
D_PostEvent(&ev);
|
||||
}
|
||||
}
|
||||
ButtonState = 0;
|
||||
}
|
||||
}
|
||||
|
||||
class FDInputMouse : public FMouse
|
||||
{
|
||||
public:
|
||||
FDInputMouse();
|
||||
~FDInputMouse();
|
||||
|
||||
bool GetDevice();
|
||||
void ProcessInput();
|
||||
void Grab();
|
||||
void Ungrab();
|
||||
|
||||
protected:
|
||||
LPDIRECTINPUTDEVICE8 Device;
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FDInputMouse - Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FDInputMouse::FDInputMouse()
|
||||
{
|
||||
Device = NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FDInputMouse - Destructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FDInputMouse::~FDInputMouse()
|
||||
{
|
||||
if (Device != NULL)
|
||||
{
|
||||
Device->Release();
|
||||
Device = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FDInputMouse :: GetDevice
|
||||
//
|
||||
// Create the device interface and initialize it.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FDInputMouse::GetDevice()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (g_pdi3)
|
||||
{ // DirectInput3 interface
|
||||
hr = g_pdi3->CreateDevice(GUID_SysMouse, (LPDIRECTINPUTDEVICE*)&Device, NULL);
|
||||
}
|
||||
else
|
||||
{ // DirectInput8 interface
|
||||
hr = g_pdi->CreateDevice(GUID_SysMouse, &Device, NULL);
|
||||
}
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// How many buttons does this mouse have?
|
||||
DIDEVCAPS_DX3 caps = { sizeof(caps) };
|
||||
hr = Device->GetCapabilities((DIDEVCAPS *)&caps);
|
||||
// If that failed, just assume four buttons.
|
||||
if (FAILED(hr))
|
||||
{
|
||||
caps.dwButtons = 4;
|
||||
}
|
||||
// Now select the data format with enough buttons for this mouse.
|
||||
// (Can we use c_dfDIMouse2 with DirectInput3? If so, then we could just set
|
||||
// that unconditionally.)
|
||||
hr = Device->SetDataFormat(caps.dwButtons <= 4 ? &c_dfDIMouse : &c_dfDIMouse2);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ufailit:
|
||||
Device->Release();
|
||||
Device = NULL;
|
||||
return false;
|
||||
}
|
||||
// Set cooperative level.
|
||||
hr = Device->SetCooperativeLevel(Window, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
|
||||
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;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FDInputMouse :: ProcessInput
|
||||
//
|
||||
// Posts any events that have accumulated since the previous call.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FDInputMouse::ProcessInput()
|
||||
{
|
||||
DIDEVICEOBJECTDATA od;
|
||||
DWORD dwElements;
|
||||
HRESULT hr;
|
||||
int count = 0;
|
||||
int dx, dy;
|
||||
|
||||
dx = 0;
|
||||
dy = 0;
|
||||
|
||||
if (!HaveFocus || NativeMouse)
|
||||
return;
|
||||
|
||||
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)
|
||||
{
|
||||
Grab();
|
||||
hr = Device->GetDeviceData(cbObjectData, &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 */
|
||||
// GCC does not like putting the DIMOFS_ macros in case statements,
|
||||
// so use ifs instead.
|
||||
if (od.dwOfs == (DWORD)DIMOFS_X)
|
||||
{
|
||||
dx += od.dwData;
|
||||
}
|
||||
else if (od.dwOfs == (DWORD)DIMOFS_Y)
|
||||
{
|
||||
dy += od.dwData;
|
||||
}
|
||||
else if (od.dwOfs == (DWORD)DIMOFS_Z)
|
||||
{
|
||||
WheelMoved(od.dwData);
|
||||
}
|
||||
else if (od.dwOfs >= (DWORD)DIMOFS_BUTTON0 && od.dwOfs <= (DWORD)DIMOFS_BUTTON7)
|
||||
{
|
||||
/* [RH] Mouse button events mimic keydown/up events */
|
||||
if (!GUICapture)
|
||||
{
|
||||
PostButtonEvent(od.dwOfs - DIMOFS_BUTTON0, !!(od.dwData & 0x80));
|
||||
}
|
||||
}
|
||||
}
|
||||
PostMouseMove(m_noprescale ? dx : dx<<2, -dy);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FDInputMouse :: Grab
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FDInputMouse::Grab()
|
||||
{
|
||||
Device->Acquire();
|
||||
SetCursorState(NativeMouse);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FDInputMouse :: Ungrab
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FDInputMouse::Ungrab()
|
||||
{
|
||||
Device->Unacquire();
|
||||
SetCursorState(true);
|
||||
ClearButtonState();
|
||||
}
|
||||
|
||||
class FWin32Mouse : public FMouse
|
||||
{
|
||||
public:
|
||||
FWin32Mouse();
|
||||
~FWin32Mouse();
|
||||
|
||||
bool GetDevice();
|
||||
void ProcessInput();
|
||||
bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
|
||||
void Grab();
|
||||
void Ungrab();
|
||||
|
||||
protected:
|
||||
void CenterMouse(int x, int y);
|
||||
|
||||
POINT UngrabbedPointerPos;
|
||||
LONG PrevX, PrevY;
|
||||
bool Grabbed;
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FWin32Mouse - Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FWin32Mouse::FWin32Mouse()
|
||||
{
|
||||
GetCursorPos(&UngrabbedPointerPos);
|
||||
Grabbed = false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FWin32Mouse - Destructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FWin32Mouse::~FWin32Mouse()
|
||||
{
|
||||
Ungrab();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FWin32Mouse :: GetDevice
|
||||
//
|
||||
// The Win32 mouse is always available, since it is the lowest common
|
||||
// denominator. (Even if it's not connected, it is still considered as
|
||||
// "available"; it just won't generate any events.)
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FWin32Mouse::GetDevice()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FWin32Mouse :: ProcessInput
|
||||
//
|
||||
// Get current mouse position and post events if the mouse has moved from
|
||||
// last time.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FWin32Mouse::ProcessInput()
|
||||
{
|
||||
POINT pt;
|
||||
int x, y;
|
||||
|
||||
if (!HaveFocus || !Grabbed || !GetCursorPos(&pt))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
x = pt.x - PrevX;
|
||||
y = PrevY - pt.y;
|
||||
|
||||
if (!m_noprescale)
|
||||
{
|
||||
x *= 3;
|
||||
y *= 2;
|
||||
}
|
||||
if (x | y)
|
||||
{
|
||||
CenterMouse(pt.x, pt.y);
|
||||
}
|
||||
PostMouseMove(x, y);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FWin32Mouse :: WndProcHook
|
||||
//
|
||||
// Intercepts mouse-related window messages if the mouse is grabbed.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FWin32Mouse::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
|
||||
{
|
||||
if (!Grabbed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (message == WM_SIZE)
|
||||
{
|
||||
if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED)
|
||||
{
|
||||
CenterMouse(-1, -1);
|
||||
*result = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (message == WM_MOVE)
|
||||
{
|
||||
CenterMouse(-1, -1);
|
||||
*result = 0;
|
||||
return true;
|
||||
}
|
||||
else if (message == WM_SYSCOMMAND)
|
||||
{
|
||||
// Do not enter the window moving and sizing modes while grabbed,
|
||||
// because those require the mouse.
|
||||
wParam &= 0xFFF0;
|
||||
if (wParam == SC_MOVE || wParam == SC_SIZE)
|
||||
{
|
||||
*result = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (message == WM_MOUSEWHEEL)
|
||||
{
|
||||
WheelMoved(HIWORD(wParam));
|
||||
return true;
|
||||
}
|
||||
else if (message >= WM_LBUTTONDOWN && message <= WM_MBUTTONUP)
|
||||
{
|
||||
int action = (message - WM_LBUTTONDOWN) % 3;
|
||||
int button = (message - WM_LBUTTONDOWN) / 3;
|
||||
|
||||
if (action == 2)
|
||||
{ // double clicking we care not about.
|
||||
return false;
|
||||
}
|
||||
event_t ev = { 0 };
|
||||
ev.type = action ? EV_KeyUp : EV_KeyDown;
|
||||
ev.data1 = KEY_MOUSE1 + button;
|
||||
if (action)
|
||||
{
|
||||
ButtonState &= ~(1 << button);
|
||||
}
|
||||
else
|
||||
{
|
||||
ButtonState |= 1 << button;
|
||||
}
|
||||
D_PostEvent(&ev);
|
||||
return true;
|
||||
}
|
||||
else if (message >= WM_XBUTTONDOWN && message <= WM_XBUTTONUP)
|
||||
{
|
||||
// Microsoft's (lack of) documentation for the X buttons is unclear on whether
|
||||
// or not simultaneous pressing of multiple X buttons will ever be merged into
|
||||
// a single message. Winuser.h describes the button field as being filled with
|
||||
// flags, which suggests that it could merge them. My testing
|
||||
// indicates it does not, but I will assume it might in the future.
|
||||
WORD xbuttons = GET_XBUTTON_WPARAM(wParam);
|
||||
event_t ev = { 0 };
|
||||
|
||||
ev.type = (message == WM_XBUTTONDOWN) ? EV_KeyDown : EV_KeyUp;
|
||||
|
||||
// There are only two X buttons defined presently, so I extrapolate from
|
||||
// the current winuser.h values to support up to 8 mouse buttons.
|
||||
for (int i = 0; i < 5; ++i, xbuttons >>= 1)
|
||||
{
|
||||
if (xbuttons & 1)
|
||||
{
|
||||
ev.data1 = KEY_MOUSE4 + i;
|
||||
if (ev.type == EV_KeyDown)
|
||||
{
|
||||
ButtonState |= 1 << (i + 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
ButtonState &= ~(1 << (i + 4));
|
||||
}
|
||||
D_PostEvent(&ev);
|
||||
}
|
||||
}
|
||||
*result = TRUE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FWin32Mouse :: Grab
|
||||
//
|
||||
// Hides the mouse and locks it inside the window boundaries.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FWin32Mouse::Grab()
|
||||
{
|
||||
RECT rect;
|
||||
|
||||
if (Grabbed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GetCursorPos(&UngrabbedPointerPos);
|
||||
ClipCursor(NULL); // helps with Win95?
|
||||
GetClientRect(Window, &rect);
|
||||
|
||||
// Reposition the rect so that it only covers the client area.
|
||||
ClientToScreen(Window, (LPPOINT)&rect.left);
|
||||
ClientToScreen(Window, (LPPOINT)&rect.right);
|
||||
|
||||
ClipCursor(&rect);
|
||||
SetCursorState(false);
|
||||
CenterMouse(-1, -1);
|
||||
Grabbed = true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FWin32Mouse :: Ungrab
|
||||
//
|
||||
// Shows the mouse and lets it roam free.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FWin32Mouse::Ungrab()
|
||||
{
|
||||
if (!Grabbed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ClipCursor(NULL);
|
||||
SetCursorPos(UngrabbedPointerPos.x, UngrabbedPointerPos.y);
|
||||
SetCursorState(true);
|
||||
Grabbed = false;
|
||||
ClearButtonState();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FWin32Mouse :: CenterMouse
|
||||
//
|
||||
// Moves the mouse to the center of the window, but only if the current
|
||||
// position isn't already in the center.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FWin32Mouse::CenterMouse(int curx, int cury)
|
||||
{
|
||||
RECT rect;
|
||||
|
||||
GetWindowRect (Window, &rect);
|
||||
|
||||
int centx = (rect.left + rect.right) >> 1;
|
||||
int centy = (rect.top + rect.bottom) >> 1;
|
||||
|
||||
// Reduce the number of WM_MOUSEMOVE messages that get sent
|
||||
// by only calling SetCursorPos when we really need to.
|
||||
if (centx != curx || centy != cury)
|
||||
{
|
||||
PrevX = centx;
|
||||
PrevY = centy;
|
||||
SetCursorPos (centx, centy);
|
||||
}
|
||||
}
|
||||
|
||||
static void I_StartupMouse ()
|
||||
{
|
||||
mousemode_t new_mousemode;
|
||||
|
||||
if (in_mouse == 1 || (in_mouse == 0 && OSPlatform == os_WinNT4))
|
||||
new_mousemode = win32;
|
||||
else
|
||||
new_mousemode = dinput;
|
||||
|
||||
if (new_mousemode != mousemode)
|
||||
{
|
||||
if (new_mousemode == dinput)
|
||||
{
|
||||
Mouse = new FDInputMouse();
|
||||
}
|
||||
else
|
||||
{
|
||||
Mouse = new FWin32Mouse();
|
||||
}
|
||||
if (!Mouse->GetDevice())
|
||||
{
|
||||
delete Mouse;
|
||||
if (new_mousemode == dinput)
|
||||
{
|
||||
new_mousemode = win32;
|
||||
Mouse = new FWin32Mouse();
|
||||
if (!Mouse->GetDevice())
|
||||
{
|
||||
Mouse = NULL;
|
||||
new_mousemode = none;
|
||||
}
|
||||
}
|
||||
}
|
||||
mousemode = new_mousemode;
|
||||
}
|
||||
HaveFocus = GetFocus() == Window;
|
||||
HMODULE user32 = GetModuleHandle("user32.dll");
|
||||
|
||||
if (user32 == NULL)
|
||||
{
|
||||
return; // WTF kind of broken system are we running on?
|
||||
}
|
||||
#define RIF(name,ret,args) \
|
||||
My##name = (name##Proto)GetProcAddress(user32, #name);
|
||||
#include "rawinput.h"
|
||||
}
|
||||
|
|
|
@ -54,4 +54,67 @@ extern char *JoyAxisNames[8];
|
|||
|
||||
extern void DI_EnumJoy ();
|
||||
|
||||
#ifdef USE_WINDOWS_DWORD
|
||||
// Don't make these definitions available to the main body of the source code.
|
||||
|
||||
class FInputDevice
|
||||
{
|
||||
public:
|
||||
virtual ~FInputDevice() = 0;
|
||||
virtual bool GetDevice() = 0;
|
||||
virtual void ProcessInput() = 0;
|
||||
virtual bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
|
||||
};
|
||||
|
||||
class FMouse : public FInputDevice
|
||||
{
|
||||
public:
|
||||
FMouse();
|
||||
|
||||
virtual void Grab() = 0;
|
||||
virtual void Ungrab() = 0;
|
||||
|
||||
protected:
|
||||
void PostMouseMove(int x, int y);
|
||||
void WheelMoved(int wheelmove);
|
||||
void PostButtonEvent(int button, bool down);
|
||||
void ClearButtonState();
|
||||
|
||||
int LastX, LastY; // for m_filter
|
||||
WORD ButtonState; // bit mask of current button states (1=down, 0=up)
|
||||
};
|
||||
|
||||
void I_StartupMouse();
|
||||
void I_CheckNativeMouse(bool prefer_native);
|
||||
|
||||
// USB HID usage page numbers
|
||||
#define HID_GENERIC_DESKTOP_PAGE 0x01
|
||||
#define HID_SIMULATION_CONTROLS_PAGE 0x02
|
||||
#define HID_VR_CONTROLS_PAGE 0x03
|
||||
#define HID_SPORT_CONTROLS_PAGE 0x04
|
||||
#define HID_GAME_CONTROLS_PAGE 0x05
|
||||
#define HID_GENERIC_DEVICE_CONTROLS_PAGE 0x06
|
||||
#define HID_KEYBOARD_PAGE 0x07
|
||||
#define HID_LED_PAGE 0x08
|
||||
#define HID_BUTTON_PAGE 0x09
|
||||
#define HID_ORDINAL_PAGE 0x0a
|
||||
#define HID_TELEPHONY_DEVICE_PAGE 0x0b
|
||||
#define HID_CONSUMER_PAGE 0x0c
|
||||
#define HID_DIGITIZERS_PAGE 0x0d
|
||||
#define HID_UNICODE_PAGE 0x10
|
||||
#define HID_ALPHANUMERIC_DISPLAY_PAGE 0x14
|
||||
#define HID_MEDICAL_INSTRUMENT_PAGE 0x40
|
||||
|
||||
// HID Generic Desktop Page usages
|
||||
#define HID_GDP_UNDEFINED 0x00
|
||||
#define HID_GDP_POINTER 0x01
|
||||
#define HID_GDP_MOUSE 0x02
|
||||
#define HID_GDP_JOYSTICK 0x04
|
||||
#define HID_GDP_GAMEPAD 0x05
|
||||
#define HID_GDP_KEYBOARD 0x06
|
||||
#define HID_GDP_KEYPAD 0x07
|
||||
#define HID_GDP_MULTIAXIS_CONTROLLER 0x08
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
1171
src/win32/i_mouse.cpp
Normal file
1171
src/win32/i_mouse.cpp
Normal file
File diff suppressed because it is too large
Load diff
18
src/win32/rawinput.h
Normal file
18
src/win32/rawinput.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
// Pointers to raw-input related functions. They were introduced with XP,
|
||||
// so we can't use static linking with them.
|
||||
#ifndef RIF
|
||||
#define RIF(name,ret,args) \
|
||||
typedef ret (WINAPI *name##Proto)args; \
|
||||
extern name##Proto My##name;
|
||||
#endif
|
||||
|
||||
RIF(DefRawInputProc, LRESULT, (PRAWINPUT *paRawInput, INT nInput, UINT cbSizeHeader))
|
||||
RIF(GetRawInputBuffer, UINT, (PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader))
|
||||
RIF(GetRawInputData, UINT, (HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader))
|
||||
RIF(GetRawInputDeviceInfoA, UINT, (HANDLE hDevice, UINT uiCommand, LPVOID pData, PUINT pcbSize))
|
||||
RIF(GetRawInputDeviceInfoW, UINT, (HANDLE hDevice, UINT uiCommand, LPVOID pData, PUINT pcbSize))
|
||||
RIF(GetRawInputDeviceList, UINT, (PRAWINPUTDEVICELIST pRawInputDeviceList, PUINT puiNumDevices, UINT cbSize))
|
||||
RIF(GetRegisteredRawInputDevices, UINT, (PRAWINPUTDEVICE pRawInputDevices, PUINT puiNumDevices, UINT cbSize))
|
||||
RIF(RegisterRawInputDevices, BOOL, (PCRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize))
|
||||
|
||||
#undef RIF
|
|
@ -1980,6 +1980,10 @@
|
|||
RelativePath=".\src\win32\i_main.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\win32\i_mouse.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\win32\i_movie.cpp"
|
||||
>
|
||||
|
@ -2000,6 +2004,10 @@
|
|||
RelativePath=".\src\win32\icon2.ico"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\win32\rawinput.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\win32\resource.h"
|
||||
>
|
||||
|
|
Loading…
Reference in a new issue