pygame does not detect events from virtual uinput device (Ubuntu Jammy)

I am currently working on the PR that ports vgamepad to Linux. vgamepad emulates virtual gamepads in python.
On Linux, the PR uses libevdev which in turns creates a uinput device.
In order to check consistency of the library across platforms, I am trying to use pygame for checking the state of vgamepad‘s virtual gamepads.
The code for these unit tests is available here.
They all pass on Windows, and fail on Linux.

(You can test on your system: clone the repo, checkout the yb/linux branch, follow the prerequisite instructions for Linux, install locally with pip install -e . and run the python script in the test directory)

On Linux, pygame correctly detects the uinput device with its expected characteristics, and thus the following tests are successful:

# Check that only one gamepad is connected:
self.assertTrue(len(self.joysticks) == 1)
j = self.joysticks[0]

# Check that gamepad properties are correct:
name = j.get_name()
nb_axes = j.get_numaxes()
nb_balls = j.get_numballs()
nb_buttons = j.get_numbuttons()
nb_hats = j.get_numhats()
self.assertTrue(name == "Xbox 360 Controller")
self.assertEqual(nb_axes, 6)
self.assertEqual(nb_balls, 0)
self.assertEqual(nb_buttons, 11)
self.assertEqual(nb_hats, 1)

However, further events are not correctly detected, and thus this test fails:

_ = pygame.event.get()

self.g.press_button(button=v_button)
self.g.update()
time.sleep(WAIT_S)

event = pygame.event.get()
print(event)
self.assertTrue(j.get_button(j_button))

At this point, the A button is supposed to be detected as pressed, and in fact the gamepad tester website does correctly show button A as pressed.
Yet, pygame does not see the event and the print that I have added here prints [].

Finally, I have manually tried a modded version of the same code using a real gamepad, and this time the test passed correctly.

Does anyone know why this might happen, please?

Thank you for your help!

EDIT: I have also tried creating a display with pygame.display.set_mode((500, 500)) and focusing the created window before sending the uinput events, but got the same behavior: no uinput events were detected by pygame, only the mouse events corresponding to me focusing the window.

The pygame.event module an pygame.event.get() requires an initialized display on the same device in the same thread:

Pygame handles all its event messaging through an event queue. The routines in this module help you manage that event queue. The input queue is heavily dependent on the pygame.display module. If the display has not been initialized and a video mode not set, the event queue may not work properly.

pygame.event.pump() / pygame.event.get()

Caution: This function should only be called in the thread that initialized pygame.display

Leave a Comment