Skip to content

Commit

Permalink
Fix mouse/touch/gestures for PLATFORM_DRM (#3515)
Browse files Browse the repository at this point in the history
  • Loading branch information
ubkp authored Nov 7, 2023
1 parent a57ac0b commit 9a2b735
Showing 1 changed file with 199 additions and 31 deletions.
230 changes: 199 additions & 31 deletions src/platforms/rcore_drm.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ typedef struct {
// NOTE: currentButtonState[] can't be written directly due to multithreading, app could miss the update
char currentButtonStateEvdev[MAX_MOUSE_BUTTONS]; // Holds the new mouse state for the next polling event to grab
bool cursorRelative; // Relative cursor mode
int mouseFd; // File descriptor for the evdev mouse/touch/gestures
Rectangle absRange; // Range of values for absolute pointing devices (touchscreens)
int touchSlot; // Hold the touch slot number of the currently being sent multitouch block

// Gamepad data
pthread_t gamepadThreadId; // Gamepad reading thread id
Expand Down Expand Up @@ -170,11 +173,6 @@ static const int EvkeyToUnicodeLUT[] = {
// LUT currently incomplete, just mapped the most essential keys
};

#if defined(SUPPORT_GESTURES_SYSTEM)
GestureEvent gestureEvent = { 0 }; // Gesture event to hold data between EventThread() and PollInputEvents()
bool newGesture = false; // Var to trigger ProcessGestureEvent(gestureEvent) on PollInputEvents()
#endif

//----------------------------------------------------------------------------------
// Module Internal Functions Declaration
//----------------------------------------------------------------------------------
Expand Down Expand Up @@ -448,7 +446,7 @@ void EnableCursor(void)
void DisableCursor(void)
{
// Set cursor position in the middle
SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
SetMousePosition(0, 0);

platform.cursorRelative = true;
CORE.Input.Mouse.cursorHidden = true;
Expand Down Expand Up @@ -565,11 +563,8 @@ void PollInputEvents(void)
PollKeyboardEvents();

// Register previous mouse position
if (platform.cursorRelative)
{
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f };
}
if (platform.cursorRelative) CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f };
else CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;

// Register previous mouse states
CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove;
Expand Down Expand Up @@ -600,15 +595,6 @@ void PollInputEvents(void)
// Map touch position to mouse position for convenience
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;

#if defined(SUPPORT_GESTURES_SYSTEM)
// Call the ProcessGestureEvent here instead of on EventThread() to workaround the threads not matching
if (newGesture)
{
ProcessGestureEvent(gestureEvent);
newGesture = false;
}
#endif

#if defined(SUPPORT_SSH_KEYBOARD_RPI)
// NOTE: Keyboard reading could be done using input_event(s) or just read from stdin, both methods are used here.
// stdin reading is still used for legacy purposes, it allows keyboard input trough SSH console
Expand All @@ -618,6 +604,183 @@ void PollInputEvents(void)
// NOTE: Mouse input events polling is done asynchronously in another pthread - EventThread()
// NOTE: Gamepad (Joystick) input events polling is done asynchonously in another pthread - GamepadThread()
#endif

// Handle the mouse/touch/gestures events:
// NOTE: Replaces the EventThread handling that is now commented.
{
int fd = platform.mouseFd;
if (fd == -1) return;

struct input_event event = { 0 };

int touchAction = -1; // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE
bool gestureUpdate = false; // Flag to note gestures require to update

// Try to read data from the mouse/touch/gesture and only continue if successful
while (read(fd, &event, sizeof(event)) == (int)sizeof(event))
{
// Relative movement parsing
if (event.type == EV_REL)
{
if (event.code == REL_X)
{
if (platform.cursorRelative)
{
CORE.Input.Mouse.currentPosition.x = event.value;
CORE.Input.Mouse.previousPosition.x = 0.0f;
}
else CORE.Input.Mouse.currentPosition.x += event.value;
CORE.Input.Touch.position[0].x = CORE.Input.Mouse.currentPosition.x;

touchAction = 2; // TOUCH_ACTION_MOVE
gestureUpdate = true;
}

if (event.code == REL_Y)
{
if (platform.cursorRelative)
{
CORE.Input.Mouse.currentPosition.y = event.value;
CORE.Input.Mouse.previousPosition.y = 0.0f;
}
else CORE.Input.Mouse.currentPosition.y += event.value;
CORE.Input.Touch.position[0].y = CORE.Input.Mouse.currentPosition.y;

touchAction = 2; // TOUCH_ACTION_MOVE
gestureUpdate = true;
}

if (event.code == REL_WHEEL) platform.eventWheelMove.y += event.value;
}

// Absolute movement parsing
if (event.type == EV_ABS)
{
// Basic movement
if (event.code == ABS_X)
{
CORE.Input.Mouse.currentPosition.x = (event.value - platform.absRange.x)*CORE.Window.screen.width/platform.absRange.width; // Scale according to absRange
CORE.Input.Touch.position[0].x = (event.value - platform.absRange.x)*CORE.Window.screen.width/platform.absRange.width; // Scale according to absRange

touchAction = 2; // TOUCH_ACTION_MOVE
gestureUpdate = true;
}

if (event.code == ABS_Y)
{
CORE.Input.Mouse.currentPosition.y = (event.value - platform.absRange.y)*CORE.Window.screen.height/platform.absRange.height; // Scale according to absRange
CORE.Input.Touch.position[0].y = (event.value - platform.absRange.y)*CORE.Window.screen.height/platform.absRange.height; // Scale according to absRange

touchAction = 2; // TOUCH_ACTION_MOVE
gestureUpdate = true;
}

// Multitouch movement
if (event.code == ABS_MT_SLOT) platform.touchSlot = event.value; // Remember the slot number for the folowing events

if (event.code == ABS_MT_POSITION_X)
{
if (platform.touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[platform.touchSlot].x = (event.value - platform.absRange.x)*CORE.Window.screen.width/platform.absRange.width; // Scale according to absRange
}

if (event.code == ABS_MT_POSITION_Y)
{
if (platform.touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[platform.touchSlot].y = (event.value - platform.absRange.y)*CORE.Window.screen.height/platform.absRange.height; // Scale according to absRange
}

if (event.code == ABS_MT_TRACKING_ID)
{
if ((event.value < 0) && (platform.touchSlot < MAX_TOUCH_POINTS))
{
// Touch has ended for this point
CORE.Input.Touch.position[platform.touchSlot].x = -1;
CORE.Input.Touch.position[platform.touchSlot].y = -1;
}
}

// Touchscreen tap
if (event.code == ABS_PRESSURE)
{
int previousMouseLeftButtonState = platform.currentButtonStateEvdev[MOUSE_BUTTON_LEFT];

if (!event.value && previousMouseLeftButtonState)
{
platform.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = 0;

touchAction = 0; // TOUCH_ACTION_UP
gestureUpdate = true;
}

if (event.value && !previousMouseLeftButtonState)
{
platform.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = 1;

touchAction = 1; // TOUCH_ACTION_DOWN
gestureUpdate = true;
}
}

}

// Button parsing
if (event.type == EV_KEY)
{
// Mouse button parsing
if ((event.code == BTN_TOUCH) || (event.code == BTN_LEFT))
{
platform.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = event.value;

if (event.value > 0) touchAction = 1; // TOUCH_ACTION_DOWN
else touchAction = 0; // TOUCH_ACTION_UP
gestureUpdate = true;
}

if (event.code == BTN_RIGHT) platform.currentButtonStateEvdev[MOUSE_BUTTON_RIGHT] = event.value;
if (event.code == BTN_MIDDLE) platform.currentButtonStateEvdev[MOUSE_BUTTON_MIDDLE] = event.value;
if (event.code == BTN_SIDE) platform.currentButtonStateEvdev[MOUSE_BUTTON_SIDE] = event.value;
if (event.code == BTN_EXTRA) platform.currentButtonStateEvdev[MOUSE_BUTTON_EXTRA] = event.value;
if (event.code == BTN_FORWARD) platform.currentButtonStateEvdev[MOUSE_BUTTON_FORWARD] = event.value;
if (event.code == BTN_BACK) platform.currentButtonStateEvdev[MOUSE_BUTTON_BACK] = event.value;
}

// Screen confinement
if (!CORE.Input.Mouse.cursorHidden)
{
if (CORE.Input.Mouse.currentPosition.x < 0) CORE.Input.Mouse.currentPosition.x = 0;
if (CORE.Input.Mouse.currentPosition.x > CORE.Window.screen.width/CORE.Input.Mouse.scale.x) CORE.Input.Mouse.currentPosition.x = CORE.Window.screen.width/CORE.Input.Mouse.scale.x;

if (CORE.Input.Mouse.currentPosition.y < 0) CORE.Input.Mouse.currentPosition.y = 0;
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;
}

// Update touch point count
CORE.Input.Touch.pointCount = 0;
for (int i = 0; i < MAX_TOUCH_POINTS; i++)
{
if (CORE.Input.Touch.position[i].x >= 0) CORE.Input.Touch.pointCount++;
}

#if defined(SUPPORT_GESTURES_SYSTEM)
if (gestureUpdate)
{
GestureEvent gestureEvent = { 0 };

gestureEvent.touchAction = touchAction;
gestureEvent.pointCount = CORE.Input.Touch.pointCount;

for (int i = 0; i < MAX_TOUCH_POINTS; i++)
{
gestureEvent.pointId[i] = i;
gestureEvent.position[i] = CORE.Input.Touch.position[i];
}

ProcessGestureEvent(gestureEvent);

gestureUpdate = false;
}
#endif
}
}
}

//----------------------------------------------------------------------------------
Expand Down Expand Up @@ -1462,15 +1625,20 @@ static void ConfigureEvdevDevice(char *device)
worker->isMultitouch? "multitouch " : "",
worker->isTouch? "touchscreen " : "",
worker->isGamepad? "gamepad " : "");
platform.mouseFd = worker->fd;

// NOTE: moved the mouse/touch/gesture input to PollInputEvents()/
// so added the "platform.mouseFd = worker->fd;" line above
// and commented the thread code below:

// Create a thread for this device
int error = pthread_create(&worker->threadId, NULL, &EventThread, (void *)worker);
if (error != 0)
{
TRACELOG(LOG_WARNING, "RPI: Failed to create input device thread: %s (error: %d)", device, error);
worker->threadId = 0;
close(fd);
}
//int error = pthread_create(&worker->threadId, NULL, &EventThread, (void *)worker);
//if (error != 0)
//{
// TRACELOG(LOG_WARNING, "RPI: Failed to create input device thread: %s (error: %d)", device, error);
// worker->threadId = 0;
// close(fd);
//}

#if defined(USE_LAST_TOUCH_DEVICE)
// Find touchscreen with the highest index
Expand Down Expand Up @@ -1570,6 +1738,7 @@ static void PollKeyboardEvents(void)
// Input device events reading thread
static void *EventThread(void *arg)
{
/*
struct input_event event = { 0 };
InputEventWorker *worker = (InputEventWorker *)arg;
Expand Down Expand Up @@ -1731,7 +1900,7 @@ static void *EventThread(void *arg)
#if defined(SUPPORT_GESTURES_SYSTEM)
if (gestureUpdate)
{
//GestureEvent gestureEvent = { 0 };
GestureEvent gestureEvent = { 0 };
gestureEvent.touchAction = touchAction;
gestureEvent.pointCount = CORE.Input.Touch.pointCount;
Expand All @@ -1742,8 +1911,7 @@ static void *EventThread(void *arg)
gestureEvent.position[i] = CORE.Input.Touch.position[i];
}
//ProcessGestureEvent(gestureEvent);
newGesture = true;
ProcessGestureEvent(gestureEvent);
}
#endif
}
Expand All @@ -1752,7 +1920,7 @@ static void *EventThread(void *arg)
}
close(worker->fd);

*/
return NULL;
}

Expand Down

0 comments on commit 9a2b735

Please sign in to comment.