diff --git a/sunshine/input.cpp b/sunshine/input.cpp index f24eb9f1..20327f51 100644 --- a/sunshine/input.cpp +++ b/sunshine/input.cpp @@ -140,25 +140,51 @@ void passthrough(std::shared_ptr &input, PNV_MULTI_CONTROLLER_PACKET pa packet->rightStickY }; - bf = gamepad_state.buttonFlags ^ input->gamepad_state.buttonFlags; auto bf_new = gamepad_state.buttonFlags; + switch(input->back_button_state) { + case button_state_e::UP: + if(!(platf::BACK & bf_new)) { + input->back_button_state = button_state_e::NONE; + } + gamepad_state.buttonFlags &= ~platf::BACK; + break; + case button_state_e::DOWN: + if(platf::BACK & bf_new) { + input->back_button_state = button_state_e::NONE; + } + gamepad_state.buttonFlags |= platf::BACK; + break; + case button_state_e::NONE: + break; + } + + bf = gamepad_state.buttonFlags ^ input->gamepad_state.buttonFlags; + bf_new = gamepad_state.buttonFlags; - // up pressed == -1, down pressed == 1, else 0 if (platf::BACK & bf) { if (platf::BACK & bf_new) { - input->back_timeout_id = task_pool.pushDelayed([input]() { - auto &state = input->gamepad_state; - // Press Home button - state.buttonFlags |= platf::HOME; - platf::gamepad(input->input, state); + // Don't emulate home button if timeout < 0 + if(config::input.back_button_timeout >= 0ms) { + input->back_timeout_id = task_pool.pushDelayed([input]() { + auto &state = input->gamepad_state; - // Release Home button - state.buttonFlags &= ~platf::HOME; - platf::gamepad(input->input, state); + // Force the back button up + input->back_button_state = button_state_e::UP; + state.buttonFlags &= ~platf::BACK; + platf::gamepad(input->input, state); - input->back_timeout_id = nullptr; - }, config::input.back_button_timeout).task_id; + // Press Home button + state.buttonFlags |= platf::HOME; + platf::gamepad(input->input, state); + + // Release Home button + state.buttonFlags &= ~platf::HOME; + platf::gamepad(input->input, state); + + input->back_timeout_id = nullptr; + }, config::input.back_button_timeout).task_id; + } } else if (input->back_timeout_id) { task_pool.cancel(input->back_timeout_id); diff --git a/sunshine/input.h b/sunshine/input.h index 90ee2e44..99d9370e 100644 --- a/sunshine/input.h +++ b/sunshine/input.h @@ -9,6 +9,11 @@ #include "thread_pool.h" namespace input { +enum class button_state_e { + NONE, + DOWN, + UP +}; struct input_t { input_t(); @@ -19,6 +24,13 @@ struct input_t { util::ThreadPool::task_id_t back_timeout_id; platf::input_t input; + + // When emulating the HOME button, we may need to artificially release the back button. + // Afterwards, the gamepad state on sunshine won't match the state on Moonlight + // To prevent Sunshine from sending erronious input data to the active application, + // Sunshine forces the button to be in a specific state until the gamepad state matches that of + // Moonlight once more. + button_state_e back_button_state {button_state_e::NONE }; }; void print(void *input);