Add gamepad support in OTG mode
Implement gamepad support for OTG.
This commit is contained in:
parent
32c73a5448
commit
ab6732f32d
@ -12,6 +12,7 @@ struct scrcpy_otg {
|
|||||||
struct sc_aoa aoa;
|
struct sc_aoa aoa;
|
||||||
struct sc_keyboard_aoa keyboard;
|
struct sc_keyboard_aoa keyboard;
|
||||||
struct sc_mouse_aoa mouse;
|
struct sc_mouse_aoa mouse;
|
||||||
|
struct sc_gamepad_aoa gamepad;
|
||||||
|
|
||||||
struct sc_screen_otg screen_otg;
|
struct sc_screen_otg screen_otg;
|
||||||
};
|
};
|
||||||
@ -66,6 +67,13 @@ scrcpy_otg(struct scrcpy_options *options) {
|
|||||||
return SCRCPY_EXIT_FAILURE;
|
return SCRCPY_EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options->gamepad_input_mode != SC_GAMEPAD_INPUT_MODE_DISABLED) {
|
||||||
|
if (SDL_Init(SDL_INIT_GAMECONTROLLER)) {
|
||||||
|
LOGE("Could not initialize SDL controller: %s", SDL_GetError());
|
||||||
|
// Not fatal, keyboard/mouse should still work
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
atexit(SDL_Quit);
|
atexit(SDL_Quit);
|
||||||
|
|
||||||
if (!SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1")) {
|
if (!SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1")) {
|
||||||
@ -76,6 +84,7 @@ scrcpy_otg(struct scrcpy_options *options) {
|
|||||||
|
|
||||||
struct sc_keyboard_aoa *keyboard = NULL;
|
struct sc_keyboard_aoa *keyboard = NULL;
|
||||||
struct sc_mouse_aoa *mouse = NULL;
|
struct sc_mouse_aoa *mouse = NULL;
|
||||||
|
struct sc_gamepad_aoa *gamepad = NULL;
|
||||||
bool usb_device_initialized = false;
|
bool usb_device_initialized = false;
|
||||||
bool usb_connected = false;
|
bool usb_connected = false;
|
||||||
bool aoa_started = false;
|
bool aoa_started = false;
|
||||||
@ -122,11 +131,15 @@ scrcpy_otg(struct scrcpy_options *options) {
|
|||||||
|| options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_DISABLED);
|
|| options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_DISABLED);
|
||||||
assert(options->mouse_input_mode == SC_MOUSE_INPUT_MODE_AOA
|
assert(options->mouse_input_mode == SC_MOUSE_INPUT_MODE_AOA
|
||||||
|| options->mouse_input_mode == SC_MOUSE_INPUT_MODE_DISABLED);
|
|| options->mouse_input_mode == SC_MOUSE_INPUT_MODE_DISABLED);
|
||||||
|
assert(options->gamepad_input_mode == SC_GAMEPAD_INPUT_MODE_AOA
|
||||||
|
|| options->gamepad_input_mode == SC_GAMEPAD_INPUT_MODE_DISABLED);
|
||||||
|
|
||||||
bool enable_keyboard =
|
bool enable_keyboard =
|
||||||
options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_AOA;
|
options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_AOA;
|
||||||
bool enable_mouse =
|
bool enable_mouse =
|
||||||
options->mouse_input_mode == SC_MOUSE_INPUT_MODE_AOA;
|
options->mouse_input_mode == SC_MOUSE_INPUT_MODE_AOA;
|
||||||
|
bool enable_gamepad =
|
||||||
|
options->gamepad_input_mode == SC_GAMEPAD_INPUT_MODE_AOA;
|
||||||
|
|
||||||
if (enable_keyboard) {
|
if (enable_keyboard) {
|
||||||
ok = sc_keyboard_aoa_init(&s->keyboard, &s->aoa);
|
ok = sc_keyboard_aoa_init(&s->keyboard, &s->aoa);
|
||||||
@ -144,6 +157,11 @@ scrcpy_otg(struct scrcpy_options *options) {
|
|||||||
mouse = &s->mouse;
|
mouse = &s->mouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (enable_gamepad) {
|
||||||
|
sc_gamepad_aoa_init(&s->gamepad, &s->aoa);
|
||||||
|
gamepad = &s->gamepad;
|
||||||
|
}
|
||||||
|
|
||||||
ok = sc_aoa_start(&s->aoa);
|
ok = sc_aoa_start(&s->aoa);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
goto end;
|
goto end;
|
||||||
@ -158,6 +176,7 @@ scrcpy_otg(struct scrcpy_options *options) {
|
|||||||
struct sc_screen_otg_params params = {
|
struct sc_screen_otg_params params = {
|
||||||
.keyboard = keyboard,
|
.keyboard = keyboard,
|
||||||
.mouse = mouse,
|
.mouse = mouse,
|
||||||
|
.gamepad = gamepad,
|
||||||
.window_title = window_title,
|
.window_title = window_title,
|
||||||
.always_on_top = options->always_on_top,
|
.always_on_top = options->always_on_top,
|
||||||
.window_x = options->window_x,
|
.window_x = options->window_x,
|
||||||
@ -191,6 +210,9 @@ end:
|
|||||||
if (keyboard) {
|
if (keyboard) {
|
||||||
sc_keyboard_aoa_destroy(&s->keyboard);
|
sc_keyboard_aoa_destroy(&s->keyboard);
|
||||||
}
|
}
|
||||||
|
if (gamepad) {
|
||||||
|
sc_gamepad_aoa_destroy(&s->gamepad);
|
||||||
|
}
|
||||||
|
|
||||||
if (aoa_initialized) {
|
if (aoa_initialized) {
|
||||||
sc_aoa_join(&s->aoa);
|
sc_aoa_join(&s->aoa);
|
||||||
|
@ -59,6 +59,7 @@ sc_screen_otg_init(struct sc_screen_otg *screen,
|
|||||||
const struct sc_screen_otg_params *params) {
|
const struct sc_screen_otg_params *params) {
|
||||||
screen->keyboard = params->keyboard;
|
screen->keyboard = params->keyboard;
|
||||||
screen->mouse = params->mouse;
|
screen->mouse = params->mouse;
|
||||||
|
screen->gamepad = params->gamepad;
|
||||||
|
|
||||||
screen->mouse_capture_key_pressed = 0;
|
screen->mouse_capture_key_pressed = 0;
|
||||||
|
|
||||||
@ -214,6 +215,77 @@ sc_screen_otg_process_mouse_wheel(struct sc_screen_otg *screen,
|
|||||||
mp->ops->process_mouse_scroll(mp, &evt);
|
mp->ops->process_mouse_scroll(mp, &evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sc_screen_otg_process_gamepad_device(struct sc_screen_otg *screen,
|
||||||
|
const SDL_ControllerDeviceEvent *event) {
|
||||||
|
assert(screen->gamepad);
|
||||||
|
struct sc_gamepad_processor *gp = &screen->gamepad->gamepad_processor;
|
||||||
|
|
||||||
|
SDL_JoystickID id;
|
||||||
|
if (event->type == SDL_CONTROLLERDEVICEADDED) {
|
||||||
|
SDL_GameController *gc = SDL_GameControllerOpen(event->which);
|
||||||
|
if (!gc) {
|
||||||
|
LOGW("Could not open game controller");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gc);
|
||||||
|
if (!joystick) {
|
||||||
|
LOGW("Could not get controller joystick");
|
||||||
|
SDL_GameControllerClose(gc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
id = SDL_JoystickInstanceID(joystick);
|
||||||
|
} else if (event->type == SDL_CONTROLLERDEVICEREMOVED) {
|
||||||
|
id = event->which;
|
||||||
|
|
||||||
|
SDL_GameController *gc = SDL_GameControllerFromInstanceID(id);
|
||||||
|
if (gc) {
|
||||||
|
SDL_GameControllerClose(gc);
|
||||||
|
} else {
|
||||||
|
LOGW("Unknown gamepad device removed");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Nothing to do
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sc_gamepad_device_event evt = {
|
||||||
|
.type = sc_gamepad_device_event_type_from_sdl_type(event->type),
|
||||||
|
.gamepad_id = id,
|
||||||
|
};
|
||||||
|
gp->ops->process_gamepad_device(gp, &evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sc_screen_otg_process_gamepad_axis(struct sc_screen_otg *screen,
|
||||||
|
const SDL_ControllerAxisEvent *event) {
|
||||||
|
assert(screen->gamepad);
|
||||||
|
struct sc_gamepad_processor *gp = &screen->gamepad->gamepad_processor;
|
||||||
|
|
||||||
|
struct sc_gamepad_axis_event evt = {
|
||||||
|
.gamepad_id = event->which,
|
||||||
|
.axis = sc_gamepad_axis_from_sdl(event->axis),
|
||||||
|
.value = event->value,
|
||||||
|
};
|
||||||
|
gp->ops->process_gamepad_axis(gp, &evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sc_screen_otg_process_gamepad_button(struct sc_screen_otg *screen,
|
||||||
|
const SDL_ControllerButtonEvent *event) {
|
||||||
|
assert(screen->gamepad);
|
||||||
|
struct sc_gamepad_processor *gp = &screen->gamepad->gamepad_processor;
|
||||||
|
|
||||||
|
struct sc_gamepad_button_event evt = {
|
||||||
|
.gamepad_id = event->which,
|
||||||
|
.action = sc_action_from_sdl_controllerbutton_type(event->type),
|
||||||
|
.button = sc_gamepad_button_from_sdl(event->button),
|
||||||
|
};
|
||||||
|
gp->ops->process_gamepad_button(gp, &evt);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sc_screen_otg_handle_event(struct sc_screen_otg *screen, SDL_Event *event) {
|
sc_screen_otg_handle_event(struct sc_screen_otg *screen, SDL_Event *event) {
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
@ -293,5 +365,23 @@ sc_screen_otg_handle_event(struct sc_screen_otg *screen, SDL_Event *event) {
|
|||||||
sc_screen_otg_process_mouse_wheel(screen, &event->wheel);
|
sc_screen_otg_process_mouse_wheel(screen, &event->wheel);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SDL_CONTROLLERDEVICEADDED:
|
||||||
|
case SDL_CONTROLLERDEVICEREMOVED:
|
||||||
|
// Handle device added or removed even if paused
|
||||||
|
if (screen->gamepad) {
|
||||||
|
sc_screen_otg_process_gamepad_device(screen, &event->cdevice);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLERAXISMOTION:
|
||||||
|
if (screen->gamepad) {
|
||||||
|
sc_screen_otg_process_gamepad_axis(screen, &event->caxis);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLERBUTTONDOWN:
|
||||||
|
case SDL_CONTROLLERBUTTONUP:
|
||||||
|
if (screen->gamepad) {
|
||||||
|
sc_screen_otg_process_gamepad_button(screen, &event->cbutton);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,12 @@
|
|||||||
|
|
||||||
#include "keyboard_aoa.h"
|
#include "keyboard_aoa.h"
|
||||||
#include "mouse_aoa.h"
|
#include "mouse_aoa.h"
|
||||||
|
#include "gamepad_aoa.h"
|
||||||
|
|
||||||
struct sc_screen_otg {
|
struct sc_screen_otg {
|
||||||
struct sc_keyboard_aoa *keyboard;
|
struct sc_keyboard_aoa *keyboard;
|
||||||
struct sc_mouse_aoa *mouse;
|
struct sc_mouse_aoa *mouse;
|
||||||
|
struct sc_gamepad_aoa *gamepad;
|
||||||
|
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
SDL_Renderer *renderer;
|
SDL_Renderer *renderer;
|
||||||
@ -24,6 +26,7 @@ struct sc_screen_otg {
|
|||||||
struct sc_screen_otg_params {
|
struct sc_screen_otg_params {
|
||||||
struct sc_keyboard_aoa *keyboard;
|
struct sc_keyboard_aoa *keyboard;
|
||||||
struct sc_mouse_aoa *mouse;
|
struct sc_mouse_aoa *mouse;
|
||||||
|
struct sc_gamepad_aoa *gamepad;
|
||||||
|
|
||||||
const char *window_title;
|
const char *window_title;
|
||||||
bool always_on_top;
|
bool always_on_top;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user