diff --git a/hw/xbox/xid.c b/hw/xbox/xid.c index 516e349257..86f34f7de2 100644 --- a/hw/xbox/xid.c +++ b/hw/xbox/xid.c @@ -214,6 +214,7 @@ static void update_input(USBXIDState *s) ControllerState *state = xemu_input_get_bound(s->device_index); assert(state); + xemu_input_update_controller(state); const int button_map_analog[6][2] = { { GAMEPAD_A, CONTROLLER_BUTTON_A }, diff --git a/ui/xemu-input.c b/ui/xemu-input.c index 08a10b44ec..1c29507085 100644 --- a/ui/xemu-input.c +++ b/ui/xemu-input.c @@ -26,6 +26,7 @@ #include "monitor/qdev.h" #include "qapi/qmp/qdict.h" #include "qemu/option.h" +#include "qemu/timer.h" #include "qemu/config-file.h" #include "xemu-input.h" @@ -42,6 +43,9 @@ do { } while (0) #endif +#define XEMU_INPUT_MIN_INPUT_UPDATE_INTERVAL_US 2500 +#define XEMU_INPUT_MIN_HAPTIC_UPDATE_INTERVAL_US 2500 + ControllerStateList available_controllers = QTAILQ_HEAD_INITIALIZER(available_controllers); ControllerState *bound_controllers[4] = { NULL, NULL, NULL, NULL }; @@ -217,16 +221,31 @@ void xemu_input_process_sdl_events(const SDL_Event *event) } } +void xemu_input_update_controller(ControllerState *state) +{ + int64_t now = qemu_clock_get_us(QEMU_CLOCK_REALTIME); + if (ABS(now - state->last_input_updated_ts) < + XEMU_INPUT_MIN_INPUT_UPDATE_INTERVAL_US) { + return; + } + + if (state->type == INPUT_DEVICE_SDL_KEYBOARD) { + xemu_input_update_sdl_kbd_controller_state(state); + } else if (state->type == INPUT_DEVICE_SDL_GAMECONTROLLER) { + xemu_input_update_sdl_controller_state(state); + } + + state->last_input_updated_ts = qemu_clock_get_us(QEMU_CLOCK_REALTIME); +} + void xemu_input_update_controllers(void) { ControllerState *iter; QTAILQ_FOREACH(iter, &available_controllers, entry) { - if (iter->type == INPUT_DEVICE_SDL_KEYBOARD) { - xemu_input_update_sdl_kbd_controller_state(iter); - } else if (iter->type == INPUT_DEVICE_SDL_GAMECONTROLLER) { - xemu_input_update_sdl_controller_state(iter); - xemu_input_update_rumble(iter); - } + xemu_input_update_controller(iter); + } + QTAILQ_FOREACH(iter, &available_controllers, entry) { + xemu_input_update_rumble(iter); } } @@ -335,6 +354,12 @@ void xemu_input_update_rumble(ControllerState *state) return; } + int64_t now = qemu_clock_get_us(QEMU_CLOCK_REALTIME); + if (ABS(now - state->last_haptic_updated_ts) < + XEMU_INPUT_MIN_HAPTIC_UPDATE_INTERVAL_US) { + return; + } + memset(&state->sdl_haptic_effect, 0, sizeof(state->sdl_haptic_effect)); state->sdl_haptic_effect.type = SDL_HAPTIC_LEFTRIGHT; state->sdl_haptic_effect.leftright.length = SDL_HAPTIC_INFINITY; @@ -346,6 +371,8 @@ void xemu_input_update_rumble(ControllerState *state) } else { SDL_HapticUpdateEffect(state->sdl_haptic, state->sdl_haptic_effect_id, &state->sdl_haptic_effect); } + + state->last_haptic_updated_ts = qemu_clock_get_us(QEMU_CLOCK_REALTIME); } ControllerState *xemu_input_get_bound(int index) diff --git a/ui/xemu-input.h b/ui/xemu-input.h index e570757aa7..a21a06fac7 100644 --- a/ui/xemu-input.h +++ b/ui/xemu-input.h @@ -66,6 +66,9 @@ enum controller_input_device_type { typedef struct ControllerState { QTAILQ_ENTRY(ControllerState) entry; + int64_t last_input_updated_ts; + int64_t last_haptic_updated_ts; + // Input state uint16_t buttons; int16_t axis[CONTROLLER_AXIS__COUNT]; @@ -102,6 +105,7 @@ extern "C" { void xemu_input_init(void); void xemu_input_process_sdl_events(const SDL_Event *event); // SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEREMOVED void xemu_input_update_controllers(void); +void xemu_input_update_controller(ControllerState *state); void xemu_input_update_sdl_kbd_controller_state(ControllerState *state); void xemu_input_update_sdl_controller_state(ControllerState *state); void xemu_input_update_rumble(ControllerState *state);