Skip to content

Commit 4f10928

Browse files
committed
inputsystem: fix UB in touch events callback, make touch more responsive
1 parent 02a3c64 commit 4f10928

File tree

8 files changed

+58
-49
lines changed

8 files changed

+58
-49
lines changed

engine/sys_mainwind.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ void CGame::HandleMsg_Close( const InputEvent_t &event )
355355

356356
void CGame::DispatchInputEvent( const InputEvent_t &event )
357357
{
358-
switch( event.m_nType & 0xFFFF )
358+
switch( event.m_nType )
359359
{
360360
// Handle button events specially,
361361
// since we have all manner of crazy filtering going on when dealing with them

game/client/cdll_client_int.cpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,7 @@ class CHLClient : public IBaseClientDLL
729729
void PrecacheMaterial( const char *pMaterialName );
730730

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

734734
private:
735735
void UncacheAllMaterials( );
@@ -2637,24 +2637,20 @@ CSteamID GetSteamIDForPlayerIndex( int iPlayerIndex )
26372637
#endif
26382638

26392639

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

26452645
touch_event_t ev;
26462646

2647-
ev.type = data & 0xFFFF;
2648-
ev.fingerid = (data >> 16) & 0xFFFF;
2649-
ev.x = (double)((data2 >> 16) & 0xFFFF) / 0xFFFF;
2650-
ev.y = (double)(data2 & 0xFFFF) / 0xFFFF;
2647+
ev.type = type;
2648+
ev.fingerid = fingerId;
2649+
memcpy( &ev.x, &x, sizeof(ev.x) );
2650+
memcpy( &ev.y, &y, sizeof(ev.y) );
26512651

2652-
union{uint i;float f;} ifconv;
2653-
ifconv.i = data3;
2654-
ev.dx = ifconv.f;
2655-
2656-
ifconv.i = data4;
2657-
ev.dy = ifconv.f;
2652+
if( type == IE_FingerMotion )
2653+
inputsystem->GetTouchAccumulators( fingerId, ev.dx, ev.dy );
26582654

26592655
gTouch.ProcessEvent( &ev );
26602656
}

inputsystem/inputsystem.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,16 +1530,6 @@ bool CInputSystem::GetRawMouseAccumulators( int& accumX, int& accumY )
15301530
#endif
15311531
}
15321532

1533-
bool CInputSystem::GetTouchAccumulators( InputEventType_t &event, int &fingerId, int& accumX, int& accumY )
1534-
{
1535-
event = m_touchAccumEvent;
1536-
fingerId = m_touchAccumFingerId;
1537-
accumX = m_touchAccumX;
1538-
accumY = m_touchAccumY;
1539-
1540-
return m_bJoystickInitialized;
1541-
}
1542-
15431533
void CInputSystem::SetConsoleTextMode( bool bConsoleTextMode )
15441534
{
15451535
/* If someone calls this after init, shut it down. */

inputsystem/inputsystem.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444

4545
#include "steam/steam_api.h"
4646

47+
#define TOUCH_FINGER_MAX_COUNT 10
48+
4749
//-----------------------------------------------------------------------------
4850
// Implementation of the input system
4951
//-----------------------------------------------------------------------------
@@ -101,7 +103,7 @@ class CInputSystem : public CTier2AppSystem< IInputSystem >
101103
virtual void *GetHapticsInterfaceAddress() const { return NULL;}
102104
#endif
103105
bool GetRawMouseAccumulators( int& accumX, int& accumY );
104-
bool GetTouchAccumulators( InputEventType_t &event, int &fingerId, int& accumX, int& accumY );
106+
virtual bool GetTouchAccumulators( int fingerId, float &dx, float &dy );
105107

106108
virtual void SetConsoleTextMode( bool bConsoleTextMode );
107109

@@ -458,8 +460,7 @@ class CInputSystem : public CTier2AppSystem< IInputSystem >
458460
bool m_bRawInputSupported;
459461
int m_mouseRawAccumX, m_mouseRawAccumY;
460462

461-
InputEventType_t m_touchAccumEvent;
462-
int m_touchAccumFingerId, m_touchAccumX, m_touchAccumY;
463+
float m_touchAccumX[TOUCH_FINGER_MAX_COUNT], m_touchAccumY[TOUCH_FINGER_MAX_COUNT];
463464

464465
// For the 'SleepUntilInput' feature
465466
HANDLE m_hEvent;

inputsystem/touch_sdl.cpp

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ void CInputSystem::InitializeTouch( void )
4848
// abort startup if user requests no touch
4949
if ( CommandLine()->FindParm("-notouch") ) return;
5050

51+
memset( m_touchAccumX, 0, sizeof(m_touchAccumX) );
52+
memset( m_touchAccumY, 0, sizeof(m_touchAccumY) );
53+
5154
m_bJoystickInitialized = true;
5255
SDL_AddEventWatch(TouchSDLWatcher, this);
5356
}
@@ -61,20 +64,35 @@ void CInputSystem::ShutdownTouch()
6164
m_bTouchInitialized = false;
6265
}
6366

64-
void CInputSystem::FingerEvent(int eventType, int fingerId, float x, float y, float dx, float dy)
67+
bool CInputSystem::GetTouchAccumulators( int fingerId, float &dx, float &dy )
6568
{
66-
// Shit, but should work with arm/x86
69+
dx = m_touchAccumX[fingerId];
70+
dy = m_touchAccumY[fingerId];
6771

68-
int data0 = fingerId << 16 | eventType;
69-
int _x = (int)((double)x*0xFFFF);
70-
int _y = (int)((double)y*0xFFFF);
71-
int data1 = _x << 16 | (_y & 0xFFFF);
72+
m_touchAccumX[fingerId] = m_touchAccumY[fingerId] = 0.f;
7273

73-
union{int i;float f;} ifconv;
74-
ifconv.f = dx;
75-
int _dx = ifconv.i;
76-
ifconv.f = dy;
77-
int _dy = ifconv.i;
74+
return true;
75+
}
7876

79-
PostEvent(data0, m_nLastSampleTick, data1, _dx, _dy);
77+
void CInputSystem::FingerEvent(int eventType, int fingerId, float x, float y, float dx, float dy)
78+
{
79+
if( fingerId >= TOUCH_FINGER_MAX_COUNT )
80+
return;
81+
82+
if( eventType == IE_FingerUp )
83+
{
84+
m_touchAccumX[fingerId] = 0.f;
85+
m_touchAccumY[fingerId] = 0.f;
86+
}
87+
else
88+
{
89+
m_touchAccumX[fingerId] += dx;
90+
m_touchAccumY[fingerId] += dy;
91+
}
92+
93+
int _x,_y;
94+
memcpy( &_x, &x, sizeof(float) );
95+
memcpy( &_y, &y, sizeof(float) );
96+
PostEvent(eventType, m_nLastSampleTick, fingerId, _x, _y);
8097
}
98+

public/cdll_int.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ abstract_class IBaseClientDLL
790790

791791
virtual bool IsConnectedUserInfoChangeAllowed( IConVar *pCvar ) = 0;
792792

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

796796
#define CLIENT_DLL_INTERFACE_VERSION "VClient017"

public/inputsystem/iinputsystem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ abstract_class IInputSystem : public IAppSystem
119119

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

123124
// tell the input system that we're not a game, we're console text mode.
124125
// this is used for dedicated servers to not initialize joystick system.

vguimatsurface/Input.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ static vgui::MouseCode ButtonCodeToMouseCode( ButtonCode_t buttonCode )
376376
//-----------------------------------------------------------------------------
377377
bool InputHandleInputEvent( const InputEvent_t &event )
378378
{
379-
switch( event.m_nType & 0xFFFF )
379+
switch( event.m_nType )
380380
{
381381
case IE_ButtonPressed:
382382
{
@@ -428,9 +428,10 @@ bool InputHandleInputEvent( const InputEvent_t &event )
428428
case IE_FingerDown:
429429
{
430430
int w,h,x,y; g_MatSystemSurface.GetScreenSize(w, h);
431-
uint data = (uint)event.m_nData;
432-
x = w*((double)((data >> 16) & 0xFFFF) / 0xFFFF);
433-
y = h*((double)(data & 0xFFFF) / 0xFFFF);
431+
float _x, _y;
432+
memcpy( &_x, &event.m_nData2, sizeof(_x) );
433+
memcpy( &_y, &event.m_nData3, sizeof(_y) );
434+
x = w*_x; y = h*_y;
434435
g_pIInput->UpdateCursorPosInternal( x, y );
435436
g_pIInput->SetMouseCodeState( MOUSE_LEFT, vgui::BUTTON_PRESSED );
436437
g_pIInput->InternalMousePressed( MOUSE_LEFT );
@@ -439,9 +440,10 @@ bool InputHandleInputEvent( const InputEvent_t &event )
439440
case IE_FingerUp:
440441
{
441442
int w,h,x,y; g_MatSystemSurface.GetScreenSize(w, h);
442-
uint data = (uint)event.m_nData;
443-
x = w*((double)((data >> 16) & 0xFFFF) / 0xFFFF);
444-
y = h*((double)(data & 0xFFFF) / 0xFFFF);
443+
float _x, _y;
444+
memcpy( &_x, &event.m_nData2, sizeof(_x) );
445+
memcpy( &_y, &event.m_nData3, sizeof(_y) );
446+
x = w*_x; y = h*_y;
445447
g_pIInput->UpdateCursorPosInternal( x, y );
446448
g_pIInput->SetMouseCodeState( MOUSE_LEFT, vgui::BUTTON_RELEASED );
447449
g_pIInput->InternalMouseReleased( MOUSE_LEFT );
@@ -450,9 +452,10 @@ bool InputHandleInputEvent( const InputEvent_t &event )
450452
case IE_FingerMotion:
451453
{
452454
int w,h,x,y; g_MatSystemSurface.GetScreenSize(w, h);
453-
uint data = (uint)event.m_nData;
454-
x = w*((double)((data >> 16) & 0xFFFF) / 0xFFFF);
455-
y = h*((double)(data & 0xFFFF) / 0xFFFF);
455+
float _x, _y;
456+
memcpy( &_x, &event.m_nData2, sizeof(_x) );
457+
memcpy( &_y, &event.m_nData3, sizeof(_y) );
458+
x = w*_x; y = h*_y;
456459
g_pIInput->InternalCursorMoved( x, y );
457460
}
458461
return true;

0 commit comments

Comments
 (0)