Skip to content
Open
Show file tree
Hide file tree
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
75 changes: 40 additions & 35 deletions src/unix/linux/x11/evdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h

#define EVDEV_FD_MAX 33
#define EVDEV_EVENTS_MAX 256 /* Max number of input events per read */

struct evdev {
bool init_scan;
Expand Down Expand Up @@ -264,56 +265,60 @@ static void evdev_joystick_event(struct evdev *ctx, int32_t fd, EVDEV_REPORT rep
return;

MTY_ControllerEvent *c = &edev->state;
struct input_event event = {0};
struct input_event event_list[EVDEV_EVENTS_MAX] = {0};

if (read(fd, &event, sizeof(struct input_event)) != sizeof(struct input_event))
ssize_t size_read;
if ((size_read = read(fd, event_list, sizeof(event_list))) < (ssize_t)sizeof(struct input_event))
return;

if (event.type == EV_KEY) {
if (event.code >= 0x130 && event.code < 0x140)
edev->gamepad = true;
for (unsigned int event_index = 0; event_index < size_read/sizeof(struct input_event); event_index++) {

MTY_CButton cb = evdev_button(event.code);
if (event_list[event_index].type == EV_KEY) {
if (event_list[event_index].code >= 0x130 && event_list[event_index].code < 0x140)
edev->gamepad = true;

if (cb >= 0) {
if (cb >= MTY_CBUTTON_MAX)
return;
MTY_CButton cb = evdev_button(event_list[event_index].code);

c->buttons[cb] = event.value != 0;
report(edev, ctx->opaque);
}
if (cb >= 0) {
if (cb >= MTY_CBUTTON_MAX)
continue;

} else if (event.type == EV_ABS) {
// D-pad
if (event.code == ABS_HAT0X) {
c->buttons[MTY_CBUTTON_DPAD_RIGHT] = event.value > 0;
c->buttons[MTY_CBUTTON_DPAD_LEFT] = event.value < 0;
c->buttons[cb] = event_list[event_index].value != 0;
report(edev, ctx->opaque);
}

} else if (event.code == ABS_HAT0Y) {
c->buttons[MTY_CBUTTON_DPAD_UP] = event.value < 0;
c->buttons[MTY_CBUTTON_DPAD_DOWN] = event.value > 0;
} else if (event_list[event_index].type == EV_ABS) {
// D-pad
if (event_list[event_index].code == ABS_HAT0X) {
c->buttons[MTY_CBUTTON_DPAD_RIGHT] = event_list[event_index].value > 0;
c->buttons[MTY_CBUTTON_DPAD_LEFT] = event_list[event_index].value < 0;

// Axes
} else {
uint16_t usage = edev->gamepad ? evdev_gamepad_usage(edev, event.code, &event) :
evdev_joystick_usage(edev, event.code, &event);
} else if (event_list[event_index].code == ABS_HAT0Y) {
c->buttons[MTY_CBUTTON_DPAD_UP] = event_list[event_index].value < 0;
c->buttons[MTY_CBUTTON_DPAD_DOWN] = event_list[event_index].value > 0;

// Axes
} else {
uint16_t usage = edev->gamepad ? evdev_gamepad_usage(edev, event_list[event_index].code, event_list + event_index) :
evdev_joystick_usage(edev, event_list[event_index].code, event_list + event_index);

if (usage > 0) {
uint8_t slot = edev->ainfo[event.code].slot;
if (usage > 0) {
uint8_t slot = edev->ainfo[event_list[event_index].code].slot;

if (slot >= MTY_CAXIS_MAX)
return;
if (slot >= MTY_CAXIS_MAX)
continue;

c->axes[slot].value = event.value;
c->axes[slot].usage = usage;
c->axes[slot].min = edev->ainfo[event.code].min;
c->axes[slot].max = edev->ainfo[event.code].max;
c->axes[slot].value = event_list[event_index].value;
c->axes[slot].usage = usage;
c->axes[slot].min = edev->ainfo[event_list[event_index].code].min;
c->axes[slot].max = edev->ainfo[event_list[event_index].code].max;
}
}
}
}

if (event.type != EV_SYN)
report(edev, ctx->opaque);
if (event_list[event_index].type != EV_SYN)
report(edev, ctx->opaque);
}
}

static void evdev_initial_scan(struct evdev *ctx)
Expand Down
51 changes: 51 additions & 0 deletions test/src/reproduce_problem.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <unistd.h>
#include "matoya.h"
// Your top level application context
struct context {
MTY_App *app;
bool quit;
};

// This function will fire for each event
static void event_func(const MTY_Event *evt, void *opaque)
{
struct context *ctx = opaque;

MTY_PrintEvent(evt);

if (evt->type == MTY_EVENT_CLOSE)
ctx->quit = true;
}

// This function fires once per "cycle", either blocked by a
// call to MTY_WindowPresent or limited by MTY_AppSetTimeout
static bool app_func(void *opaque)
{
struct context *ctx = opaque;

MTY_WindowPresent(ctx->app, 0);
usleep(1000); /* simulate the 1ms sleep in parsec app loop */

return !ctx->quit;
}

int main(int argc, char **argv)
{
// Set up the application object and attach it to your context
struct context ctx = {0};
ctx.app = MTY_AppCreate(0, app_func, event_func, &ctx);
if (!ctx.app)
return 1;

// Create a window
MTY_WindowCreate(ctx.app, "My Window", NULL, 0);

// Set the graphics API
MTY_WindowSetGFX(ctx.app, 0, MTY_GetDefaultGFX(), true);

// Run the app -- blocks until your app_func returns false
MTY_AppRun(ctx.app);
MTY_AppDestroy(&ctx.app);

return 0;
}