|
|
|
@ -138,6 +138,7 @@ typedef struct { |
|
|
|
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 touchActive[MAX_TOUCH_POINTS]; // Track which touch points are currently active |
|
|
|
int touchLastUpdate[MAX_TOUCH_POINTS]; // Frame counter for last update (to detect stale touches) |
|
|
|
|
|
|
|
// Gamepad data |
|
|
|
int gamepadStreamFd[MAX_GAMEPADS]; // Gamepad device file descriptor |
|
|
|
@ -164,6 +165,7 @@ static bool crtcSet = false; |
|
|
|
extern CoreData CORE; // Global CORE state context |
|
|
|
|
|
|
|
static PlatformData platform = { 0 }; // Platform specific data |
|
|
|
static int frameCounter = 0; // Frame counter for touch cleanup |
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------- |
|
|
|
// Global Variables Definition |
|
|
|
@ -1069,6 +1071,27 @@ void PollInputEvents(void) |
|
|
|
UpdateGestures(); |
|
|
|
#endif |
|
|
|
|
|
|
|
// Periodic cleanup to prevent ghost touches (every 60 frames ~ 1 second at 60fps) |
|
|
|
frameCounter++; |
|
|
|
if (frameCounter > 3600) frameCounter = 1800; // Reset after 1 minute to prevent overflow, keeping reasonable gap |
|
|
|
|
|
|
|
if (frameCounter % 60 == 0) { |
|
|
|
// Clean up stale touches that haven't been updated recently (likely ghost touches) |
|
|
|
for (int i = 0; i < MAX_TOUCH_POINTS; i++) { |
|
|
|
if (platform.touchActive[i]) { |
|
|
|
// If a touch hasn't been updated in the last 30 frames (~0.5 sec), consider it stale |
|
|
|
int framesSinceUpdate = frameCounter - platform.touchLastUpdate[i]; |
|
|
|
if (framesSinceUpdate > 30) { |
|
|
|
TRACELOG(LOG_DEBUG, "TOUCH: Cleaning up stale touch point %d (frames since update: %d)", i, framesSinceUpdate); |
|
|
|
platform.touchActive[i] = false; |
|
|
|
platform.touchLastUpdate[i] = 0; |
|
|
|
CORE.Input.Touch.position[i].x = -1; |
|
|
|
CORE.Input.Touch.position[i].y = -1; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Reset keys/chars pressed registered |
|
|
|
CORE.Input.Keyboard.keyPressedQueueCount = 0; |
|
|
|
CORE.Input.Keyboard.charPressedQueueCount = 0; |
|
|
|
@ -1883,6 +1906,7 @@ static void InitEvdevInput(void) |
|
|
|
CORE.Input.Touch.position[i].x = -1; |
|
|
|
CORE.Input.Touch.position[i].y = -1; |
|
|
|
platform.touchActive[i] = false; |
|
|
|
platform.touchLastUpdate[i] = 0; |
|
|
|
} |
|
|
|
|
|
|
|
// Initialize touch slot |
|
|
|
@ -2305,6 +2329,7 @@ static void PollMouseEvents(void) |
|
|
|
{ |
|
|
|
if (platform.touchSlot < MAX_TOUCH_POINTS && platform.touchActive[platform.touchSlot]) { |
|
|
|
CORE.Input.Touch.position[platform.touchSlot].x = (event.value - platform.absRange.x)*CORE.Window.screen.width/platform.absRange.width; |
|
|
|
platform.touchLastUpdate[platform.touchSlot] = frameCounter; |
|
|
|
touchAction = 2; // TOUCH_ACTION_MOVE |
|
|
|
} |
|
|
|
} |
|
|
|
@ -2313,6 +2338,7 @@ static void PollMouseEvents(void) |
|
|
|
{ |
|
|
|
if (platform.touchSlot < MAX_TOUCH_POINTS && platform.touchActive[platform.touchSlot]) { |
|
|
|
CORE.Input.Touch.position[platform.touchSlot].y = (event.value - platform.absRange.y)*CORE.Window.screen.height/platform.absRange.height; |
|
|
|
platform.touchLastUpdate[platform.touchSlot] = frameCounter; |
|
|
|
touchAction = 2; // TOUCH_ACTION_MOVE |
|
|
|
} |
|
|
|
} |
|
|
|
@ -2325,17 +2351,17 @@ static void PollMouseEvents(void) |
|
|
|
{ |
|
|
|
// Touch has started for this point |
|
|
|
platform.touchActive[platform.touchSlot] = true; |
|
|
|
platform.touchLastUpdate[platform.touchSlot] = frameCounter; |
|
|
|
touchAction = 1; // TOUCH_ACTION_DOWN |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// Touch has ended for this point |
|
|
|
platform.touchActive[platform.touchSlot] = false; |
|
|
|
platform.touchLastUpdate[platform.touchSlot] = 0; |
|
|
|
CORE.Input.Touch.position[platform.touchSlot].x = -1; |
|
|
|
CORE.Input.Touch.position[platform.touchSlot].y = -1; |
|
|
|
touchAction = 0; // TOUCH_ACTION_UP |
|
|
|
|
|
|
|
// Note: CompactTouchPoints() will be called after all events are processed |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -2404,9 +2430,8 @@ static void PollMouseEvents(void) |
|
|
|
if (CORE.Input.Mouse.currentPosition.y > CORE.Window.screen.height/CORE.Input.Mouse.scale.y) CORE.Input.Mouse.currentPosition.y = CORE.Window.screen.height/CORE.Input.Mouse.scale.y; |
|
|
|
} |
|
|
|
|
|
|
|
// Compact touch points if any were removed |
|
|
|
static bool needsCompaction = false; |
|
|
|
if (touchAction == 0) needsCompaction = true; // Touch up event |
|
|
|
// Clean up any invalid touch points |
|
|
|
CompactTouchPoints(); |
|
|
|
|
|
|
|
// Update touch point count |
|
|
|
CORE.Input.Touch.pointCount = 0; |
|
|
|
@ -2415,18 +2440,25 @@ static void PollMouseEvents(void) |
|
|
|
if (platform.touchActive[i]) CORE.Input.Touch.pointCount++; |
|
|
|
} |
|
|
|
|
|
|
|
// n">Compact after counting to avoid disrupting gesture events |
|
|
|
if (needsCompaction && touchAction != 1) { // Don't compact during touch down |
|
|
|
n">CompactTouchPoints(); |
|
|
|
needsCompaction = false; |
|
|
|
|
|
|
|
// Recount after compaction |
|
|
|
CORE.Input.Touch.pointCount = 0; |
|
|
|
for (int i = 0; i < MAX_TOUCH_POINTS; i++) |
|
|
|
{ |
|
|
|
k">if (platform.touchActive[i]) CORE.Input.Touch.pointCount++; |
|
|
|
// k">if no touches are active but positions exist, clean it up |
|
|
|
if (CORE.Input.Touch.pointCount == 0) { |
|
|
|
k">for (int i = 0; i < MAX_TOUCH_POINTS; i++) { |
|
|
|
if (platform.touchActive[i] || CORE.Input.Touch.position[i].x != -1) { |
|
|
|
TRACELOG(LOG_DEBUG, "TOUCH: Force cleaning ghost touch at slot %d", i); |
|
|
|
platform.touchActive[i] = false; |
|
|
|
platform.touchLastUpdate[i] = 0; |
|
|
|
CORE.Input.Touch.position[i].x = -1; |
|
|
|
CORE.Input.Touch.position[i].y = -1; |
|
|
|
p">} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Debug logging |
|
|
|
static int lastTouchCount = 0; |
|
|
|
if (CORE.Input.Touch.pointCount != lastTouchCount && (touchAction == 0 || touchAction == 1)) { |
|
|
|
TRACELOG(LOG_DEBUG, "TOUCH: Count changed from %d to %d (action: %d)", lastTouchCount, CORE.Input.Touch.pointCount, touchAction); |
|
|
|
lastTouchCount = CORE.Input.Touch.pointCount; |
|
|
|
} |
|
|
|
|
|
|
|
#if defined(SUPPORT_GESTURES_SYSTEM) |
|
|
|
if (touchAction > -1) |
|
|
|
@ -2450,29 +2482,16 @@ static void PollMouseEvents(void) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Compact touch points to remove gaps when touches are removed |
|
|
|
// Clean up inactive touch points to prevent ghost touches |
|
|
|
static void CompactTouchPoints(void) |
|
|
|
{ |
|
|
|
// This function ensures that active touch points are contiguous |
|
|
|
// starting from index 0, which helps with proper touch counting |
|
|
|
int writeIndex = 0; |
|
|
|
|
|
|
|
for (int readIndex = 0; readIndex < MAX_TOUCH_POINTS; readIndex++) |
|
|
|
|
|
|
|
for (int i = 0; i < MAX_TOUCH_POINTS; i++) |
|
|
|
{ |
|
|
|
if (platform.touchActive[readIndex]) |
|
|
|
if (!platform.touchActive[i]) |
|
|
|
{ |
|
|
|
if (writeIndex != readIndex) |
|
|
|
{ |
|
|
|
// Move the active touch point to fill the gap |
|
|
|
platform.touchActive[writeIndex] = true; |
|
|
|
CORE.Input.Touch.position[writeIndex] = CORE.Input.Touch.position[readIndex]; |
|
|
|
|
|
|
|
// Clear the old position |
|
|
|
platform.touchActive[readIndex] = false; |
|
|
|
CORE.Input.Touch.position[readIndex].x = -1; |
|
|
|
CORE.Input.Touch.position[readIndex].y = -1; |
|
|
|
} |
|
|
|
writeIndex++; |
|
|
|
CORE.Input.Touch.position[i].x = -1; |
|
|
|
CORE.Input.Touch.position[i].y = -1; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|