Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core] Fix mouse/touch/gestures for PLATFORM_DRM #3515

Merged
merged 1 commit into from Nov 7, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading