Input sticky buttons fixed

This commit is contained in:
serge_shubin 2026-03-21 20:51:28 +08:00
parent 043e3a2def
commit 9b0bd3c03f

View file

@ -343,13 +343,20 @@ void IN_DIMouse( int *mx, int *my ) {
DIMOUSESTATE2 state; DIMOUSESTATE2 state;
DWORD dwElements; DWORD dwElements;
HRESULT hr; HRESULT hr;
int value; int i, value;
static BYTE oldButtons[8];
static const int buttonKeys[5] = {
K_MOUSE1, K_MOUSE2, K_MOUSE3, K_MOUSE4, K_MOUSE5
};
if ( !g_pMouse ) { if ( !g_pMouse ) {
return; return;
} }
// fetch new events // flush the buffered data — we only use it for wheel events.
// buttons are handled via immediate state below to avoid
// stuck keys from buffer overflow.
for (;;) for (;;)
{ {
dwElements = 1; dwElements = 1;
@ -361,51 +368,11 @@ void IN_DIMouse( int *mx, int *my ) {
return; return;
} }
/* Unable to read data or no data available */ if ( FAILED(hr) || dwElements == 0 ) {
if ( FAILED(hr) ) {
break;
}
if ( dwElements == 0 ) {
break; break;
} }
switch (od.dwOfs) { switch (od.dwOfs) {
case DIMOFS_BUTTON0:
if (od.dwData & 0x80)
Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE1, qtrue, 0, NULL );
else
Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE1, qfalse, 0, NULL );
break;
case DIMOFS_BUTTON1:
if (od.dwData & 0x80)
Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE2, qtrue, 0, NULL );
else
Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE2, qfalse, 0, NULL );
break;
case DIMOFS_BUTTON2:
if (od.dwData & 0x80)
Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE3, qtrue, 0, NULL );
else
Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE3, qfalse, 0, NULL );
break;
case DIMOFS_BUTTON3:
if (od.dwData & 0x80)
Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE4, qtrue, 0, NULL );
else
Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE4, qfalse, 0, NULL );
break;
case DIMOFS_BUTTON4:
if (od.dwData & 0x80)
Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE5, qtrue, 0, NULL );
else
Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE5, qfalse, 0, NULL );
break;
case DIMOFS_Z: case DIMOFS_Z:
value = od.dwData; value = od.dwData;
if (value < 0) { if (value < 0) {
@ -419,16 +386,29 @@ void IN_DIMouse( int *mx, int *my ) {
} }
} }
// read the raw delta counter and ignore // read immediate device state for axes and buttons
// the individual sample time / values
hr = IDirectInputDevice8_GetDeviceState(g_pMouse, hr = IDirectInputDevice8_GetDeviceState(g_pMouse,
sizeof(DIMOUSESTATE2), &state); sizeof(DIMOUSESTATE2), &state);
if ( FAILED(hr) ) { if ( FAILED(hr) ) {
*mx = *my = 0; *mx = *my = 0;
return; return;
} }
*mx = state.lX; *mx = state.lX;
*my = state.lY; *my = state.lY;
// generate button press/release events from immediate state.
// comparing against previous state avoids stuck buttons entirely —
// if a press or release was missed in the buffer, the immediate
// state catches it next frame.
for ( i = 0; i < 5; i++ ) {
BYTE down = state.rgbButtons[i] & 0x80;
if ( down != oldButtons[i] ) {
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, buttonKeys[i],
down ? qtrue : qfalse, 0, NULL );
oldButtons[i] = down;
}
}
} }
/* /*