@ -189,6 +189,7 @@
# include <unistd.h> // POSIX standard function definitions - read(), close(), STDIN_FILENO
# include <termios.h> // POSIX terminal control definitions - tcgetattr(), tcsetattr()
# include <pthread.h> // POSIX threads management (mouse input)
# include <dirent.h> // POSIX directory browsing
# include <sys/ioctl.h> // UNIX System call for device-specific input/output operations - ioctl()
# include <linux/kd.h> // Linux: KDSKBMODE, K_MEDIUMRAM constants definition
@ -223,9 +224,8 @@
# if defined(PLATFORM_RPI)
/ / Old device inputs system
# define DEFAULT_KEYBOARD_DEV STDIN_FILENO / / Standard input
# define DEFAULT_MOUSE_DEV " / dev / input / mouse0" / / Mouse input
# define DEFAULT_TOUCH_DEV " / dev / input / event4" / / Touch input virtual device (created by ts_uinput)
# define DEFAULT_GAMEPAD_DEV " / dev / input / js" / / Gamepad input (base dev for all gamepads: js0, js1, ...)
# define DEFAULT_EVDEV_PATH " / dev / input / " / / Path to the linux input events
/ / New device input events ( evdev ) ( must be detected )
/ / # define DEFAULT_KEYBOARD_DEV " /dev/input/eventN "
@ -329,11 +329,22 @@ static int currentMouseWheelY = 0; // Registers current mouse wheel
# if defined(PLATFORM_RPI)
static int mouseStream = - 1 ; / / Mouse device file descriptor
static bool mouseReady = false ; / / Flag to know if mouse is ready
static pthread_t mouseThreadId ; / / Mouse reading thread id
static int touchStream = - 1 ; / / Touch device file descriptor
static bool touchReady = false ; / / Flag to know if touch interface is ready
static pthread_t touchThreadId ; / / Touch reading thread id
static char currentMouseStateEvdev [ 3 ] = { 0 } ; / / Holds the new mouse state for the next polling event to grab ( Can ' t be written directly due to multithreading , app could miss the update )
typedef struct {
pthread_t threadId ; / / Event reading thread id
int fd ; / / File descriptor to the device it is assigned to
float sensitivity ; / / Sensitivitzy multiplier for relative mouse movements
Rectangle absRange ; / / Range of values for absolute pointing devices ( touchscreens )
int touchSlot ; / / Hold the touch slot number of the currently being sent multitouch block
bool isMouse ; / / True if device supports relative X Y movements
bool isTouch ; / / True if device supports absolute X Y movements and has BTN_TOUCH
bool isMultitouch ; / / True if device supports multiple absolute movevents and has BTN_TOUCH
bool isKeyboard ; / / True if device has letter keycodes
bool isGamepad ; / / True if device has gamepad buttons
} InputEventWorker ;
static InputEventWorker eventWorkers [ 10 ] ; / / List of worker threads for every monitored " /dev/input/event<N> "
# endif
# if defined(PLATFORM_WEB)
static bool toggleCursorLock = false ; / / Ask for cursor pointer lock on next click
@ -447,9 +458,8 @@ static void InitKeyboard(void); // Init raw keyboard sys
static void ProcessKeyboard ( void ) ; / / Process keyboard events
static void RestoreKeyboard ( void ) ; / / Restore keyboard system
static void InitMouse ( void ) ; / / Mouse initialization ( including mouse thread )
static void * MouseThread ( void * arg ) ; / / Mouse reading thread
static void InitTouch ( void ) ; / / Touch device initialization ( including touch thread )
static void * TouchThread ( void * arg ) ; / / Touch device reading thread
static void EventThreadSpawn ( char * device ) ; / / Indetifies a input device and spawns a thread to handle it if needed
static void * EventThread ( void * arg ) ; / / Input device event reading thread
static void InitGamepad ( void ) ; / / Init raw gamepad input
static void * GamepadThread ( void * arg ) ; / / Mouse reading thread
# endif
@ -566,7 +576,6 @@ void InitWindow(int width, int height, const char *title)
# if defined(PLATFORM_RPI)
/ / Init raw input system
InitMouse ( ) ; / / Mouse init
InitTouch ( ) ; / / Touch init
InitKeyboard ( ) ; / / Keyboard init
InitGamepad ( ) ; / / Gamepad init
# endif
@ -661,8 +670,13 @@ void CloseWindow(void)
windowShouldClose = true ; / / Added to force threads to exit when the close window is called
pthread_join ( mouseThreadId , NULL ) ;
pthread_join ( touchThreadId , NULL ) ;
for ( int i = 0 ; i < sizeof ( eventWorkers ) / sizeof ( InputEventWorker ) ; + + i )
{
if ( eventWorkers [ i ] . threadId = = 0 )
{
pthread_join ( eventWorkers [ i ] . threadId , NULL ) ;
}
}
pthread_join ( gamepadThreadId , NULL ) ;
# endif
@ -1984,7 +1998,7 @@ bool IsMouseButtonPressed(int button)
# else
if ( ( currentMouseState [ button ] ! = previousMouseState [ button ] ) & & ( currentMouseState [ button ] = = 1 ) ) pressed = true ;
# endif
return pressed ;
}
@ -2128,7 +2142,9 @@ Vector2 GetTouchPosition(int index)
position . x = position . x * ( ( float ) renderWidth / ( float ) displayWidth ) - renderOffsetX / 2 ;
position . y = position . y * ( ( float ) renderHeight / ( float ) displayHeight ) - renderOffsetY / 2 ;
}
# else / / PLATFORM_DESKTOP, PLATFORM_RPI
# elif defined(PLATFORM_RPI)
position = touchPosition [ index ] ;
# else / / PLATFORM_DESKTOP
if ( index = = 0 ) position = GetMousePosition ( ) ;
# endif
@ -2895,6 +2911,21 @@ static void PollInputEvents(void)
gamepadAxisCount = 0 ;
# endif
# if defined(PLATFORM_RPI)
/ / Register previous keys states
for ( int i = 0 ; i < 512 ; i + + ) previousKeyState [ i ] = currentKeyState [ i ] ;
/ / Register previous mouse states
previousMouseWheelY = currentMouseWheelY ;
currentMouseWheelY = 0 ;
for ( int i = 0 ; i < 3 ; i + + )
{
previousMouseState [ i ] = currentMouseState [ i ] ;
currentMouseState [ i ] = currentMouseStateEvdev [ i ] ;
}
# endif
# if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
/ / Mouse input polling
double mouseX ;
@ -3829,182 +3860,351 @@ static void RestoreKeyboard(void)
/ / Mouse initialization ( including mouse thread )
static void InitMouse ( void )
{
/ / NOTE : We can use / dev / input / mice to read from all available mice
if ( ( mouseStream = open ( DEFAULT_MOUSE_DEV , O_RDONLY | O_NONBLOCK ) ) < 0 )
char Path [ 256 ] ;
DIR * d ;
struct dirent * dir ;
/ / Reset variables
for ( int i = 0 ; i < MAX_TOUCH_POINTS ; + + i )
{
touchPosition [ i ] . x = - 1 ;
touchPosition [ i ] . y = - 1 ;
}
/ / Open the linux directory of " /dev/input "
d = opendir ( DEFAULT_EVDEV_PATH ) ;
if ( d )
{
TraceLog ( LOG_WARNING , " Mouse device could not be opened, no mouse available " ) ;
while ( ( dir = readdir ( d ) ) ! = NULL )
{
if ( strncmp ( " event " , dir - > d_name , strlen ( " event " ) ) = = 0 ) / / Search for devices named " event* "
{
sprintf ( Path , " %s%s " , DEFAULT_EVDEV_PATH , dir - > d_name ) ;
EventThreadSpawn ( Path ) ; / / Identify the device and spawn a thread for it
}
}
closedir ( d ) ;
}
else
{
mouseReady = true ;
int error = pthread_create ( & mouseThreadId , NULL , & MouseThread , NULL ) ;
if ( error ! = 0 ) TraceLog ( LOG_WARNING , " Error creating mouse input event thread " ) ;
else TraceLog ( LOG_INFO , " Mouse device initialized successfully " ) ;
TraceLog ( LOG_WARNING , " Unable to open linux event directory %s " , DEFAULT_EVDEV_PATH ) ;
}
}
/ / Mouse reading thread
/ / NOTE : We need a separate thread to avoid loosing mouse events ,
/ / if too much time passes between reads , queue gets full and new events override older ones . . .
static void * MouseThread ( void * arg )
{
const unsigned char XSIGN = ( 1 < < 4 ) ;
const unsigned char YSIGN = ( 1 < < 5 ) ;
typedef struct {
char buttons ;
char dx , dy ;
} MouseEvent ;
MouseEvent mouse ;
static void EventThreadSpawn ( char * device )
{
# define BITS_PER_LONG (sizeof(long) * 8)
# define NBITS(x) ((((x)-1) / BITS_PER_LONG)+1)
# define OFF(x) ((x)%BITS_PER_LONG)
# define BIT(x) (1UL<<OFF(x))
# define LONG(x) ((x) / BITS_PER_LONG)
# define TEST_BIT(array, bit) ((array[LONG(bit)] >> OFF(bit)) & 1)
struct input_absinfo absinfo ;
unsigned long ev_bits [ NBITS ( EV_MAX ) ] ;
unsigned long abs_bits [ NBITS ( ABS_MAX ) ] ;
unsigned long rel_bits [ NBITS ( REL_MAX ) ] ;
unsigned long key_bits [ NBITS ( KEY_MAX ) ] ;
bool hasAbs = false ;
bool hasRel = false ;
bool hasAbsMulti = false ;
int FreeWorkerId = - 1 ;
int fd = - 1 ;
InputEventWorker * Worker ;
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / Open the device and allocate worker / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
/ / Find a free spot in the workers array
for ( int i = 0 ; i < sizeof ( eventWorkers ) / sizeof ( InputEventWorker ) ; + + i )
{
if ( eventWorkers [ i ] . threadId = = 0 )
{
FreeWorkerId = i ;
break ;
}
}
int mouseRelX = 0 ;
int mouseRelY = 0 ;
/ / Select the free worker from array
if ( FreeWorkerId > = 0 )
{
Worker = & ( eventWorkers [ FreeWorkerId ] ) ; / / Grab a pointer to the worker
memset ( Worker , 0 , sizeof ( InputEventWorker ) ) ; / / Clear the worker
}
else
{
TraceLog ( LOG_WARNING , " Error creating input device thread for '%s': Out of worker slots " , device ) ;
return ;
}
while ( ! windowShouldClose )
/ / Open the device
fd = open ( device , O_RDONLY | O_NONBLOCK ) ;
if ( fd < 0 )
{
if ( read ( mouseStream , & mouse , sizeof ( MouseEvent ) ) = = ( int ) sizeof ( MouseEvent ) )
{
if ( ( mouse . buttons & 0x08 ) = = 0 ) break ; / / This bit should always be set
TraceLog ( LOG_WARNING , " Error creating input device thread for '%s': Can't open device (Err: %d) " , device , Worker - > fd ) ;
return ;
}
Worker - > fd = fd ;
/ / Check Left button pressed
if ( ( mouse . buttons & 0x01 ) > 0 ) currentMouseState [ 0 ] = 1 ;
else currentMouseState [ 0 ] = 0 ;
/ / At this point we have a connection to the device ,
/ / but we don ' t yet know what the device is ( Could be
/ / many things , even as simple as a power button )
/ / Check Right button pressed
if ( ( mouse . buttons & 0x02 ) > 0 ) currentMouseState [ 1 ] = 1 ;
else currentMouseState [ 1 ] = 0 ;
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / Identify the device / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
/ / Check Middle button pressed
if ( ( mouse . buttons & 0x04 ) > 0 ) currentMouseState [ 2 ] = 1 ;
else currentMouseState [ 2 ] = 0 ;
ioctl ( fd , EVIOCGBIT ( 0 , sizeof ( ev_bits ) ) , ev_bits ) ; / / Read a bitfield of the avalable device properties
/ / Check for absolute input devices
if ( TEST_BIT ( ev_bits , EV_ABS ) )
{
ioctl ( fd , EVIOCGBIT ( EV_ABS , sizeof ( abs_bits ) ) , abs_bits ) ;
mouseRelX = ( int ) mouse . dx ;
mouseRelY = ( int ) mouse . dy ;
/ / Check for absolute movement support ( usualy touchscreens , but also joysticks )
if ( TEST_BIT ( abs_bits , ABS_X ) & & TEST_BIT ( abs_bits , ABS_Y ) )
{
hasAbs = true ;
/ / Get the scaling values
ioctl ( fd , EVIOCGABS ( ABS_X ) , & absinfo ) ;
Worker - > absRange . x = absinfo . minimum ;
Worker - > absRange . width = absinfo . maximum - absinfo . minimum ;
ioctl ( fd , EVIOCGABS ( ABS_Y ) , & absinfo ) ;
Worker - > absRange . y = absinfo . minimum ;
Worker - > absRange . height = absinfo . maximum - absinfo . minimum ;
}
/ / Check for multiple absolute movement support ( usualy multitouch touchscreens )
if ( TEST_BIT ( abs_bits , ABS_MT_POSITION_X ) & & TEST_BIT ( abs_bits , ABS_MT_POSITION_Y ) )
{
hasAbsMulti = true ;
/ / Get the scaling values
ioctl ( fd , EVIOCGABS ( ABS_X ) , & absinfo ) ;
Worker - > absRange . x = absinfo . minimum ;
Worker - > absRange . width = absinfo . maximum - absinfo . minimum ;
ioctl ( fd , EVIOCGABS ( ABS_Y ) , & absinfo ) ;
Worker - > absRange . y = absinfo . minimum ;
Worker - > absRange . height = absinfo . maximum - absinfo . minimum ;
}
}
if ( ( mouse . buttons & XSIGN ) > 0 ) mouseRelX = - 1 * ( 255 - mouseRelX ) ;
if ( ( mouse . buttons & YSIGN ) > 0 ) mouseRelY = - 1 * ( 255 - mouseRelY ) ;
/ / Check for relative movement support ( usualy mouse )
if ( TEST_BIT ( ev_bits , EV_REL ) )
{
ioctl ( fd , EVIOCGBIT ( EV_REL , sizeof ( rel_bits ) ) , rel_bits ) ;
if ( TEST_BIT ( rel_bits , REL_X ) & & TEST_BIT ( rel_bits , REL_Y ) )
{
hasRel = true ;
}
}
/ / NOTE : Mouse movement is normalized to not be screen resolution dependant
/ / We suppose 2 * 255 ( max relative movement ) is equivalent to screenWidth ( max pixels width )
/ / Result after normalization is multiplied by MOUSE_SENSITIVITY factor
/ / Check for button support to determine the device type ( usualy on all input devices )
if ( TEST_BIT ( ev_bits , EV_KEY ) )
{
ioctl ( fd , EVIOCGBIT ( EV_KEY , sizeof ( key_bits ) ) , key_bits ) ;
mousePosition . x + = ( float ) mouseRelX * ( ( float ) screenWidth / ( 2 * 255 ) ) * MOUSE_SENSITIVITY ;
mousePosition . y - = ( float ) mouseRelY * ( ( float ) screenHeight / ( 2 * 255 ) ) * MOUSE_SENSITIVITY ;
if ( hasAbs | | hasAbsMulti )
{
if ( TEST_BIT ( key_bits , BTN_TOUCH ) )
Worker - > isTouch = true ; / / This is a touchscreen
if ( TEST_BIT ( key_bits , BTN_TOOL_FINGER ) )
Worker - > isTouch = true ; / / This is a drawing tablet
if ( TEST_BIT ( key_bits , BTN_TOOL_PEN ) )
Worker - > isTouch = true ; / / This is a drawing tablet
if ( TEST_BIT ( key_bits , BTN_STYLUS ) )
Worker - > isTouch = true ; / / This is a drawing tablet
if ( Worker - > isTouch | | hasAbsMulti )
Worker - > isMultitouch = true ; / / This is a multitouch capable device
}
if ( mousePosition . x < 0 ) mousePosition . x = 0 ;
if ( mousePosition . y < 0 ) mousePosition . y = 0 ;
if ( hasRel )
{
if ( TEST_BIT ( key_bits , BTN_LEFT ) )
Worker - > isMouse = true ; / / This is a mouse
if ( TEST_BIT ( key_bits , BTN_RIGHT ) )
Worker - > isMouse = true ; / / This is a mouse
}
if ( mousePosition . x > screenWidth ) mousePosition . x = screenWidth ;
if ( mousePosition . y > screenHeight ) mousePosition . y = screenHeight ;
}
/ / else read ( mouseStream , & mouse , 1 ) ; / / Try to sync up again
if ( TEST_BIT ( key_bits , BTN_A ) )
Worker - > isGamepad = true ; / / This is a gamepad
if ( TEST_BIT ( key_bits , BTN_TRIGGER ) )
Worker - > isGamepad = true ; / / This is a gamepad
if ( TEST_BIT ( key_bits , BTN_START ) )
Worker - > isGamepad = true ; / / This is a gamepad
if ( TEST_BIT ( key_bits , BTN_TL ) )
Worker - > isGamepad = true ; / / This is a gamepad
if ( TEST_BIT ( key_bits , BTN_TL ) )
Worker - > isGamepad = true ; / / This is a gamepad
if ( TEST_BIT ( key_bits , KEY_SPACE ) )
Worker - > isKeyboard = true ; / / This is a keyboard
}
return NULL ;
}
/ / Touch initialization ( including touch thread )
static void InitTouch ( void )
{
if ( ( touchStream = open ( DEFAULT_TOUCH_DEV , O_RDONLY | O_NONBLOCK ) ) < 0 )
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / Decide what to do with the device / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
if ( Worker - > isTouch | | Worker - > isMouse )
{
TraceLog ( LOG_WARNING , " Touch device could not be opened, no touchscreen available " ) ;
/ / Looks like a interesting device
TraceLog ( LOG_INFO , " Opening input device '%s' (%s%s%s%s%s) " , device ,
Worker - > isMouse ? " mouse " : " " ,
Worker - > isMultitouch ? " multitouch " : " " ,
Worker - > isTouch ? " touchscreen " : " " ,
Worker - > isGamepad ? " gamepad " : " " ,
Worker - > isKeyboard ? " keyboard " : " "
) ;
/ / Create a thread for this device
int error = pthread_create ( & Worker - > threadId , NULL , & EventThread , ( void * ) Worker ) ;
if ( error ! = 0 )
{
TraceLog ( LOG_WARNING , " Error creating input device thread for '%s': Can't create thread (Err: %d) " , device , error ) ;
Worker - > threadId = 0 ;
close ( fd ) ;
}
}
else
{
touchReady = true ;
int error = pthread_create ( & touchThreadId , NULL , & TouchThread , NULL ) ;
if ( error ! = 0 ) TraceLog ( LOG_WARNING , " Error creating touch input event thread " ) ;
else TraceLog ( LOG_INFO , " Touch device initialized successfully " ) ;
/ / We are not interested in this device
close ( fd ) ;
}
}
/ / Touch reading thread .
/ / This reads from a Virtual Input Event / dev / input / event4 which is
/ / created by the ts_uinput daemon . This takes , filters and scales
/ / raw input from the Touchscreen ( which appears in / dev / input / event3 )
/ / based on the Calibration data referenced by tslib .
static void * TouchThread ( void * arg )
static void * EventThread ( void * arg )
{
struct input_event ev ;
GestureEvent gestureEvent ;
InputEventWorker * Worker = ( InputEventWorker * ) arg ;
bool GestureNeedsUpdate = false ;
while ( ! windowShouldClose )
{
if ( read ( touchStream , & ev , sizeof ( ev ) ) = = ( int ) sizeof ( ev ) )
if ( read ( Worker - > fd , & ev , sizeof ( ev ) ) = = ( int ) sizeof ( ev ) )
{
/ / if pressure > 0 then simulate left mouse button click
if ( ev . type = = EV_ABS & & ev . code = = 24 & & ev . value = = 0 & & currentMouseState [ 0 ] = = 1 )
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / Relative movement parsing / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
if ( ev . type = = EV_REL )
{
currentMouseState [ 0 ] = 0 ;
gestureEvent . touchAction = TOUCH_UP ;
gestureEvent . pointCount = 1 ;
gestureEvent . pointerId [ 0 ] = 0 ;
gestureEvent . pointerId [ 1 ] = 1 ;
gestureEvent . position [ 0 ] = ( Vector2 ) { mousePosition . x , mousePosition . y } ;
gestureEvent . position [ 1 ] = ( Vector2 ) { mousePosition . x , mousePosition . y } ;
gestureEvent . position [ 0 ] . x / = ( float ) GetScreenWidth ( ) ;
gestureEvent . position [ 0 ] . y / = ( float ) GetScreenHeight ( ) ;
gestureEvent . position [ 1 ] . x / = ( float ) GetScreenWidth ( ) ;
gestureEvent . position [ 1 ] . y / = ( float ) GetScreenHeight ( ) ;
ProcessGestureEvent ( gestureEvent ) ;
if ( ev . code = = REL_X )
{
mousePosition . x + = ev . value ;
touchPosition [ 0 ] . x = mousePosition . x ;
gestureEvent . touchAction = TOUCH_MOVE ;
GestureNeedsUpdate = true ;
}
if ( ev . code = = REL_Y )
{
mousePosition . y + = ev . value ;
touchPosition [ 0 ] . y = mousePosition . y ;
gestureEvent . touchAction = TOUCH_MOVE ;
GestureNeedsUpdate = true ;
}
if ( ev . code = = REL_WHEEL )
{
currentMouseWheelY + = ev . value ;
}
}
if ( ev . type = = EV_ABS & & ev . code = = 24 & & ev . value > 0 & & currentMouseState [ 0 ] = = 0 )
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / Absolute movement parsing / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
if ( ev . type = = EV_ABS )
{
currentMouseState [ 0 ] = 1 ;
gestureEvent . touchAction = TOUCH_DOWN ;
gestureEvent . pointCount = 1 ;
gestureEvent . pointerId [ 0 ] = 0 ;
gestureEvent . pointerId [ 1 ] = 1 ;
gestureEvent . position [ 0 ] = ( Vector2 ) { mousePosition . x , mousePosition . y } ;
gestureEvent . position [ 1 ] = ( Vector2 ) { mousePosition . x , mousePosition . y } ;
gestureEvent . position [ 0 ] . x / = ( float ) GetScreenWidth ( ) ;
gestureEvent . position [ 0 ] . y / = ( float ) GetScreenHeight ( ) ;
gestureEvent . position [ 1 ] . x / = ( float ) GetScreenWidth ( ) ;
gestureEvent . position [ 1 ] . y / = ( float ) GetScreenHeight ( ) ;
ProcessGestureEvent ( gestureEvent ) ;
/ / Basic movement
if ( ev . code = = ABS_X )
{
mousePosition . x = ( ev . value - Worker - > absRange . x ) * screenWidth / Worker - > absRange . width ; / / Scale acording to absRange
gestureEvent . touchAction = TOUCH_MOVE ;
GestureNeedsUpdate = true ;
}
if ( ev . code = = ABS_Y )
{
mousePosition . y = ( ev . value - Worker - > absRange . y ) * screenHeight / Worker - > absRange . height ; / / Scale acording to absRange
gestureEvent . touchAction = TOUCH_MOVE ;
GestureNeedsUpdate = true ;
}
/ / Multitouch movement
if ( ev . code = = ABS_MT_SLOT )
{
Worker - > touchSlot = ev . value ; / / Remeber the slot number for the folowing events
}
if ( ev . code = = ABS_MT_POSITION_X )
{
if ( Worker - > touchSlot < MAX_TOUCH_POINTS )
touchPosition [ Worker - > touchSlot ] . x = ( ev . value - Worker - > absRange . x ) * screenWidth / Worker - > absRange . width ; / / Scale acording to absRange
}
if ( ev . code = = ABS_MT_POSITION_Y )
{
if ( Worker - > touchSlot < MAX_TOUCH_POINTS )
touchPosition [ Worker - > touchSlot ] . y = ( ev . value - Worker - > absRange . y ) * screenHeight / Worker - > absRange . height ; / / Scale acording to absRange
}
if ( ev . code = = ABS_MT_TRACKING_ID )
{
if ( ( ev . value < 0 ) & & ( Worker - > touchSlot < MAX_TOUCH_POINTS ) )
{
/ / Touch has ended for this point
touchPosition [ Worker - > touchSlot ] . x = - 1 ;
touchPosition [ Worker - > touchSlot ] . y = - 1 ;
}
}
}
/ / x & y values supplied by event4 have been scaled & de - jittered using tslib calibration data
if ( ev . type = = EV_ABS & & ev . code = = 0 )
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / Button parsing / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
if ( ev . type = = EV_KEY )
{
mousePosition . x = ev . value ;
if ( mousePosition . x < 0 ) mousePosition . x = 0 ;
if ( mousePosition . x > screenWidth ) mousePosition . x = screenWidth ;
gestureEvent . touchAction = TOUCH_MOVE ;
gestureEvent . pointCount = 1 ;
gestureEvent . pointerId [ 0 ] = 0 ;
gestureEvent . pointerId [ 1 ] = 1 ;
gestureEvent . position [ 0 ] = ( Vector2 ) { mousePosition . x , mousePosition . y } ;
gestureEvent . position [ 1 ] = ( Vector2 ) { mousePosition . x , mousePosition . y } ;
gestureEvent . position [ 0 ] . x / = ( float ) GetScreenWidth ( ) ;
gestureEvent . position [ 0 ] . y / = ( float ) GetScreenHeight ( ) ;
gestureEvent . position [ 1 ] . x / = ( float ) GetScreenWidth ( ) ;
gestureEvent . position [ 1 ] . y / = ( float ) GetScreenHeight ( ) ;
ProcessGestureEvent ( gestureEvent ) ;
if ( ( ev . code = = BTN_TOUCH ) | | ( ev . code = = BTN_LEFT ) )
{
currentMouseStateEvdev [ MOUSE_LEFT_BUTTON ] = ev . value ;
if ( ev . value > 0 )
gestureEvent . touchAction = TOUCH_DOWN ;
else
gestureEvent . touchAction = TOUCH_UP ;
GestureNeedsUpdate = true ;
}
if ( ev . code = = BTN_RIGHT )
{
currentMouseStateEvdev [ MOUSE_RIGHT_BUTTON ] = ev . value ;
}
if ( ev . code = = BTN_MIDDLE )
{
currentMouseStateEvdev [ MOUSE_MIDDLE_BUTTON ] = ev . value ;
}
}
if ( ev . type = = EV_ABS & & ev . code = = 1 )
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / Screen confinement / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
if ( mousePosition . x < 0 )
mousePosition . x = 0 ;
if ( mousePosition . x > screenWidth / mouseScale )
mousePosition . x = screenWidth / mouseScale ;
if ( mousePosition . y < 0 )
mousePosition . y = 0 ;
if ( mousePosition . y > screenHeight / mouseScale )
mousePosition . y = screenHeight / mouseScale ;
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / Gesture update / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
if ( GestureNeedsUpdate )
{
mousePosition . y = ev . value ;
if ( mousePosition . y < 0 ) mousePosition . y = 0 ;
if ( mousePosition . y > screenHeight ) mousePosition . y = screenHeight ;
gestureEvent . touchAction = TOUCH_MOVE ;
gestureEvent . pointCount = 1 ;
gestureEvent . pointCount = 0 ;
if ( touchPosition [ 0 ] . x > = 0 ) gestureEvent . pointCount + + ;
if ( touchPosition [ 1 ] . x > = 0 ) gestureEvent . pointCount + + ;
k">if ( touchPosition [ 2 ] . x > = 0 ) gestureEvent . pointCount + + ;
k">if ( touchPosition [ 3 ] . x > = 0 ) gestureEvent . pointCount + + ;
gestureEvent . pointerId [ 0 ] = 0 ;
gestureEvent . pointerId [ 1 ] = 1 ;
gestureEvent . position [ 0 ] = ( Vector2 ) { mousePosition . x , mousePosition . y } ;
gestureEvent . position [ 1 ] = ( Vector2 ) { mousePosition . x , mousePosition . y } ;
gestureEvent . position [ 0 ] . x / = ( float ) GetScreenWidth ( ) ;
gestureEvent . position [ 0 ] . y / = ( float ) GetScreenHeight ( ) ;
gestureEvent . position [ 1 ] . x / = ( float ) GetScreenWidth ( ) ;
gestureEvent . position [ 1 ] . y / = ( float ) GetScreenHeight ( ) ;
gestureEvent . pointerId [ 2 ] = 2 ;
gestureEvent . pointerId [ 3 ] = 3 ;
gestureEvent . position [ 0 ] = touchPosition [ 0 ] ;
gestureEvent . position [ 1 ] = touchPosition [ 1 ] ;
gestureEvent . position [ 2 ] = touchPosition [ 2 ] ;
gestureEvent . position [ 3 ] = touchPosition [ 3 ] ;
ProcessGestureEvent ( gestureEvent ) ;
}
}
else
{
usleep ( 5000 ) ; / / Sleep for 5 ms to avoid hogging CPU time
}
}
return NULL ;
@ -4090,6 +4290,10 @@ static void *GamepadThread(void *arg)
}
}
}
else
{
usleep ( 1000 ) ; / / Sleep for 1 ms to avoid hogging CPU time
}
}
}