Skip to content

Commit

Permalink
inputsystem: fix UB in touch events callback, make touch more responsive
Browse files Browse the repository at this point in the history
  • Loading branch information
nillerusr committed Aug 17, 2023
1 parent 02a3c64 commit 4f10928
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 49 deletions.
2 changes: 1 addition & 1 deletion engine/sys_mainwind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ void CGame::HandleMsg_Close( const InputEvent_t &event )

void CGame::DispatchInputEvent( const InputEvent_t &event )
{
switch( event.m_nType & 0xFFFF )
switch( event.m_nType )
{
// Handle button events specially,
// since we have all manner of crazy filtering going on when dealing with them
Expand Down
20 changes: 8 additions & 12 deletions game/client/cdll_client_int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ class CHLClient : public IBaseClientDLL
void PrecacheMaterial( const char *pMaterialName );

virtual bool IsConnectedUserInfoChangeAllowed( IConVar *pCvar );
virtual void IN_TouchEvent( uint data, uint data2, uint data3, uint data4 );
virtual void IN_TouchEvent( int type, int fingerId, int x, int y );

private:
void UncacheAllMaterials( );
Expand Down Expand Up @@ -2637,24 +2637,20 @@ CSteamID GetSteamIDForPlayerIndex( int iPlayerIndex )
#endif


void CHLClient::IN_TouchEvent( uint data, uint data2, uint data3, uint data4 )
void CHLClient::IN_TouchEvent( int type, int fingerId, int x, int y )
{
if( enginevgui->IsGameUIVisible() )
return;

touch_event_t ev;

ev.type = data & 0xFFFF;
ev.fingerid = (data >> 16) & 0xFFFF;
ev.x = (double)((data2 >> 16) & 0xFFFF) / 0xFFFF;
ev.y = (double)(data2 & 0xFFFF) / 0xFFFF;
ev.type = type;
ev.fingerid = fingerId;
memcpy( &ev.x, &x, sizeof(ev.x) );
memcpy( &ev.y, &y, sizeof(ev.y) );

union{uint i;float f;} ifconv;
ifconv.i = data3;
ev.dx = ifconv.f;

ifconv.i = data4;
ev.dy = ifconv.f;
if( type == IE_FingerMotion )
inputsystem->GetTouchAccumulators( fingerId, ev.dx, ev.dy );

gTouch.ProcessEvent( &ev );
}
10 changes: 0 additions & 10 deletions inputsystem/inputsystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1530,16 +1530,6 @@ bool CInputSystem::GetRawMouseAccumulators( int& accumX, int& accumY )
#endif
}

bool CInputSystem::GetTouchAccumulators( InputEventType_t &event, int &fingerId, int& accumX, int& accumY )
{
event = m_touchAccumEvent;
fingerId = m_touchAccumFingerId;
accumX = m_touchAccumX;
accumY = m_touchAccumY;

return m_bJoystickInitialized;
}

void CInputSystem::SetConsoleTextMode( bool bConsoleTextMode )
{
/* If someone calls this after init, shut it down. */
Expand Down
7 changes: 4 additions & 3 deletions inputsystem/inputsystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@

#include "steam/steam_api.h"

#define TOUCH_FINGER_MAX_COUNT 10

//-----------------------------------------------------------------------------
// Implementation of the input system
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -101,7 +103,7 @@ class CInputSystem : public CTier2AppSystem< IInputSystem >
virtual void *GetHapticsInterfaceAddress() const { return NULL;}
#endif
bool GetRawMouseAccumulators( int& accumX, int& accumY );
bool GetTouchAccumulators( InputEventType_t &event, int &fingerId, int& accumX, int& accumY );
virtual bool GetTouchAccumulators( int fingerId, float &dx, float &dy );

virtual void SetConsoleTextMode( bool bConsoleTextMode );

Expand Down Expand Up @@ -458,8 +460,7 @@ class CInputSystem : public CTier2AppSystem< IInputSystem >
bool m_bRawInputSupported;
int m_mouseRawAccumX, m_mouseRawAccumY;

InputEventType_t m_touchAccumEvent;
int m_touchAccumFingerId, m_touchAccumX, m_touchAccumY;
float m_touchAccumX[TOUCH_FINGER_MAX_COUNT], m_touchAccumY[TOUCH_FINGER_MAX_COUNT];

// For the 'SleepUntilInput' feature
HANDLE m_hEvent;
Expand Down
42 changes: 30 additions & 12 deletions inputsystem/touch_sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ void CInputSystem::InitializeTouch( void )
// abort startup if user requests no touch
if ( CommandLine()->FindParm("-notouch") ) return;

memset( m_touchAccumX, 0, sizeof(m_touchAccumX) );
memset( m_touchAccumY, 0, sizeof(m_touchAccumY) );

m_bJoystickInitialized = true;
SDL_AddEventWatch(TouchSDLWatcher, this);
}
Expand All @@ -61,20 +64,35 @@ void CInputSystem::ShutdownTouch()
m_bTouchInitialized = false;
}

void CInputSystem::FingerEvent(int eventType, int fingerId, float x, float y, float dx, float dy)
bool CInputSystem::GetTouchAccumulators( int fingerId, float &dx, float &dy )
{
// Shit, but should work with arm/x86
dx = m_touchAccumX[fingerId];
dy = m_touchAccumY[fingerId];

int data0 = fingerId << 16 | eventType;
int _x = (int)((double)x*0xFFFF);
int _y = (int)((double)y*0xFFFF);
int data1 = _x << 16 | (_y & 0xFFFF);
m_touchAccumX[fingerId] = m_touchAccumY[fingerId] = 0.f;

union{int i;float f;} ifconv;
ifconv.f = dx;
int _dx = ifconv.i;
ifconv.f = dy;
int _dy = ifconv.i;
return true;
}

PostEvent(data0, m_nLastSampleTick, data1, _dx, _dy);
void CInputSystem::FingerEvent(int eventType, int fingerId, float x, float y, float dx, float dy)
{
if( fingerId >= TOUCH_FINGER_MAX_COUNT )
return;

if( eventType == IE_FingerUp )
{
m_touchAccumX[fingerId] = 0.f;
m_touchAccumY[fingerId] = 0.f;
}
else
{
m_touchAccumX[fingerId] += dx;
m_touchAccumY[fingerId] += dy;
}

int _x,_y;
memcpy( &_x, &x, sizeof(float) );
memcpy( &_y, &y, sizeof(float) );
PostEvent(eventType, m_nLastSampleTick, fingerId, _x, _y);
}

2 changes: 1 addition & 1 deletion public/cdll_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,7 @@ abstract_class IBaseClientDLL

virtual bool IsConnectedUserInfoChangeAllowed( IConVar *pCvar ) = 0;

virtual void IN_TouchEvent( uint data, uint data2, uint data3, uint data4 ) = 0;
virtual void IN_TouchEvent( int type, int fingerId, int x, int y ) = 0;
};

#define CLIENT_DLL_INTERFACE_VERSION "VClient017"
Expand Down
1 change: 1 addition & 0 deletions public/inputsystem/iinputsystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ abstract_class IInputSystem : public IAppSystem

// read and clear accumulated raw input values
virtual bool GetRawMouseAccumulators( int& accumX, int& accumY ) = 0;
virtual bool GetTouchAccumulators( int fingerId, float &dx, float &dy ) = 0;

// tell the input system that we're not a game, we're console text mode.
// this is used for dedicated servers to not initialize joystick system.
Expand Down
23 changes: 13 additions & 10 deletions vguimatsurface/Input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ static vgui::MouseCode ButtonCodeToMouseCode( ButtonCode_t buttonCode )
//-----------------------------------------------------------------------------
bool InputHandleInputEvent( const InputEvent_t &event )
{
switch( event.m_nType & 0xFFFF )
switch( event.m_nType )
{
case IE_ButtonPressed:
{
Expand Down Expand Up @@ -428,9 +428,10 @@ bool InputHandleInputEvent( const InputEvent_t &event )
case IE_FingerDown:
{
int w,h,x,y; g_MatSystemSurface.GetScreenSize(w, h);
uint data = (uint)event.m_nData;
x = w*((double)((data >> 16) & 0xFFFF) / 0xFFFF);
y = h*((double)(data & 0xFFFF) / 0xFFFF);
float _x, _y;
memcpy( &_x, &event.m_nData2, sizeof(_x) );
memcpy( &_y, &event.m_nData3, sizeof(_y) );
x = w*_x; y = h*_y;
g_pIInput->UpdateCursorPosInternal( x, y );
g_pIInput->SetMouseCodeState( MOUSE_LEFT, vgui::BUTTON_PRESSED );
g_pIInput->InternalMousePressed( MOUSE_LEFT );
Expand All @@ -439,9 +440,10 @@ bool InputHandleInputEvent( const InputEvent_t &event )
case IE_FingerUp:
{
int w,h,x,y; g_MatSystemSurface.GetScreenSize(w, h);
uint data = (uint)event.m_nData;
x = w*((double)((data >> 16) & 0xFFFF) / 0xFFFF);
y = h*((double)(data & 0xFFFF) / 0xFFFF);
float _x, _y;
memcpy( &_x, &event.m_nData2, sizeof(_x) );
memcpy( &_y, &event.m_nData3, sizeof(_y) );
x = w*_x; y = h*_y;
g_pIInput->UpdateCursorPosInternal( x, y );
g_pIInput->SetMouseCodeState( MOUSE_LEFT, vgui::BUTTON_RELEASED );
g_pIInput->InternalMouseReleased( MOUSE_LEFT );
Expand All @@ -450,9 +452,10 @@ bool InputHandleInputEvent( const InputEvent_t &event )
case IE_FingerMotion:
{
int w,h,x,y; g_MatSystemSurface.GetScreenSize(w, h);
uint data = (uint)event.m_nData;
x = w*((double)((data >> 16) & 0xFFFF) / 0xFFFF);
y = h*((double)(data & 0xFFFF) / 0xFFFF);
float _x, _y;
memcpy( &_x, &event.m_nData2, sizeof(_x) );
memcpy( &_y, &event.m_nData3, sizeof(_y) );
x = w*_x; y = h*_y;
g_pIInput->InternalCursorMoved( x, y );
}
return true;
Expand Down

0 comments on commit 4f10928

Please sign in to comment.