community icon indicating copy to clipboard operation
community copied to clipboard

inputs - add disconnect/connect events, change JOYSTICK to GAMEPAD api

Open NomadDemon opened this issue 5 months ago • 2 comments

There are 2 APIs for "joystick" inputs, JOYSTICK and GAMEPAD, gamepad is more modern approach, and gamepads are unified with mappings, (e.g. on joystick on gamepad brand A, bumpers are 4 and 5, on brand B they are 6 and 8 - on GAMEPAD they are mapped exactly the same way)

also, gamepads are initialized ONLY at start of app, when pad gets disconnected you need to restart app - this PR change it, app can detect disconnect and connect, and reopen the connection for it

and you can call "open_gamepads" on demand tested on linux desktop and android

how to test?

#!/usr/bin/env python

from kivy.app import App
from kivy.core.window import Window
from kivy.uix.button import Button


class GamepadApp(App):
    def build(self):
        self.button = Button(text="Manual connect gamepads...")
        self.button.bind(on_release=self.on_button)
        self._bind_events()
        return self.button

    def on_button(self, *largs):
        Window._open_gamepad(-1)

    def _bind_events(self):
        Window.bind(on_joy_added=self.on_joy_added)
        Window.bind(on_joy_removed=self.on_joy_removed)
        Window.bind(on_joy_hat=self.on_joy_hat)
        Window.bind(on_joy_ball=self.on_joy_ball)
        Window.bind(on_joy_axis=self.on_joy_axis)
        Window.bind(on_joy_button_up=self.on_joy_button_up)
        Window.bind(on_joy_button_down=self.on_joy_button_down)

    def joy_motion(self, event, id, axis, value):
        print(event, id, axis, value)

    def on_joy_added(self, win, device_id):
        print(f"Gamepads {device_id} connected")
        Window._open_gamepad(device_id)

    def on_joy_removed(self, win, device_id):
        print(f"Gamepads {device_id} disconnected")
        Window._close_gamepad(device_id)

    def on_joy_axis(self, win, stickid, axisid, value):
        self.joy_motion('axis', stickid, axisid, value)

    def on_joy_ball(self, win, stickid, ballid, xvalue, yvalue):
        self.joy_motion('ball', stickid, ballid, (xvalue, yvalue))

    def on_joy_hat(self, win, stickid, hatid, value):
        self.joy_motion('hat', stickid, hatid, value)

    def on_joy_button_down(self, win, stickid, buttonid):
        print('button_down', stickid, buttonid)

    def on_joy_button_up(self, win, stickid, buttonid):
        print('button_up', stickid, buttonid)


if __name__ == "__main__":
    GamepadApp().run()

Maintainer merge checklist

  • [ ] Title is descriptive/clear for inclusion in release notes.
  • [ ] Applied a Component: xxx label.
  • [ ] Applied the api-deprecation or api-break label.
  • [ ] Applied the release-highlight label to be highlighted in release notes.
  • [ ] Added to the milestone version it was merged into.
  • [ ] Unittests are included in PR.
  • [ ] Properly documented, including versionadded, versionchanged as needed.

NomadDemon avatar Sep 13 '25 18:09 NomadDemon

how to test? With Buildozer: requirements.source.kivy = /home/user/kivy/

kuzeyron avatar Sep 14 '25 14:09 kuzeyron

how to test? With Buildozer: requirements.source.kivy = /home/user/kivy/

i used copy of kivy recipe and changes URL to SRC, same like "android package"

NomadDemon avatar Sep 14 '25 18:09 NomadDemon