mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-02-28 12:40:33 +00:00
Support keyboard key repeats
This commit is contained in:
parent
1862662b3a
commit
8d735e5611
@ -65,6 +65,14 @@
|
||||
# If back_button_timeout < 0, then the Home/Guide button will not be emulated
|
||||
# back_button_timeout = 2000
|
||||
|
||||
# !! Windows only !!
|
||||
# Control how fast keys will repeat themselves
|
||||
# The initial delay in milliseconds before repeating keys
|
||||
# key_repeat_delay = 500
|
||||
#
|
||||
# How often keys repeat every second
|
||||
# This configurable option supports decimals
|
||||
# key_repeat_frequency = 24.9
|
||||
|
||||
# The name of the audio sink used for Audio Loopback
|
||||
# If you do not specify this variable, pulseaudio will select the default monitor device.
|
||||
|
@ -129,7 +129,9 @@ nvhttp_t nvhttp {
|
||||
};
|
||||
|
||||
input_t input {
|
||||
2s
|
||||
2s, // back_button_timeout
|
||||
500ms, // key_repeat_delay
|
||||
std::chrono::duration<double> { 1 / 24.9 } // key_repeat_period
|
||||
};
|
||||
|
||||
sunshine_t sunshine {
|
||||
@ -271,9 +273,7 @@ bool to_bool(std::string &boolean) {
|
||||
}
|
||||
void bool_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input) {
|
||||
std::string tmp;
|
||||
string_restricted_f(vars, name, tmp, {
|
||||
"enable"sv, "dis"
|
||||
});
|
||||
string_f(vars, name, tmp);
|
||||
|
||||
if(tmp.empty()) {
|
||||
return;
|
||||
@ -282,6 +282,35 @@ void bool_f(std::unordered_map<std::string, std::string> &vars, const std::strin
|
||||
input = to_bool(tmp) ? 1 : 0;
|
||||
}
|
||||
|
||||
void double_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, double &input) {
|
||||
std::string tmp;
|
||||
string_f(vars, name, tmp);
|
||||
|
||||
if(tmp.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *c_str_p;
|
||||
auto val = std::strtod(tmp.c_str(), &c_str_p);
|
||||
|
||||
if(c_str_p == tmp.c_str()) {
|
||||
return;
|
||||
}
|
||||
|
||||
input = val;
|
||||
}
|
||||
|
||||
void double_between_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, double &input, const std::pair<double, double> &range) {
|
||||
double temp = input;
|
||||
|
||||
double_f(vars, name, temp);
|
||||
|
||||
TUPLE_2D_REF(lower, upper, range);
|
||||
if(temp >= lower && temp <= upper) {
|
||||
input = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void print_help(const char *name) {
|
||||
std::cout <<
|
||||
"Usage: "sv << name << " [options] [/path/to/configuration_file]"sv << std::endl <<
|
||||
@ -370,6 +399,21 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
|
||||
input.back_button_timeout = std::chrono::milliseconds { to };
|
||||
}
|
||||
|
||||
double repeat_frequency { 0 };
|
||||
double_between_f(vars, "key_repeat_frequency", repeat_frequency, {
|
||||
0, std::numeric_limits<double>::max()
|
||||
});
|
||||
|
||||
if(repeat_frequency > 0) {
|
||||
config::input.key_repeat_period = std::chrono::duration<double> {1 / repeat_frequency };
|
||||
}
|
||||
|
||||
to = -1;
|
||||
int_f(vars, "key_repeat_delay", to);
|
||||
if(to >= 0) {
|
||||
input.key_repeat_delay = std::chrono::milliseconds { to };
|
||||
}
|
||||
|
||||
std::string log_level_string;
|
||||
string_restricted_f(vars, "min_log_level", log_level_string, {
|
||||
"verbose"sv, "debug"sv, "info"sv, "warning"sv, "error"sv, "fatal"sv, "none"sv
|
||||
|
@ -63,6 +63,8 @@ struct nvhttp_t {
|
||||
|
||||
struct input_t {
|
||||
std::chrono::milliseconds back_button_timeout;
|
||||
std::chrono::milliseconds key_repeat_delay;
|
||||
std::chrono::duration<double> key_repeat_period;
|
||||
};
|
||||
|
||||
namespace flag {
|
||||
|
@ -40,6 +40,7 @@ void free_id(std::bitset<N> &gamepad_mask, int id) {
|
||||
gamepad_mask[id] = false;
|
||||
}
|
||||
|
||||
static util::TaskPool::task_id_t task_id {};
|
||||
static std::unordered_map<short, bool> key_press {};
|
||||
static std::array<std::uint8_t, 5> mouse_press {};
|
||||
|
||||
@ -180,11 +181,46 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_MOUSE_BUTTON_PACKET packet
|
||||
platf::button_mouse(platf_input, button, packet->action == BUTTON_RELEASED);
|
||||
}
|
||||
|
||||
void repeat_key(short key_code) {
|
||||
// If key no longer pressed, stop repeating
|
||||
if(!key_press[key_code]) {
|
||||
task_id = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
platf::keyboard(platf_input, key_code & 0x00FF, false);
|
||||
|
||||
task_id = task_pool.pushDelayed(repeat_key, config::input.key_repeat_period, key_code).task_id;
|
||||
}
|
||||
|
||||
void passthrough(std::shared_ptr<input_t> &input, PNV_KEYBOARD_PACKET packet) {
|
||||
auto constexpr BUTTON_RELEASED = 0x04;
|
||||
|
||||
key_press[packet->keyCode] = packet->keyAction != BUTTON_RELEASED;
|
||||
platf::keyboard(platf_input, packet->keyCode & 0x00FF, packet->keyAction == BUTTON_RELEASED);
|
||||
auto release = packet->keyAction == BUTTON_RELEASED;
|
||||
|
||||
auto &pressed = key_press[packet->keyCode];
|
||||
if(!pressed) {
|
||||
if(!release) {
|
||||
if(task_id) {
|
||||
task_pool.cancel(task_id);
|
||||
}
|
||||
|
||||
if(config::input.key_repeat_delay.count() > 0) {
|
||||
task_id = task_pool.pushDelayed(repeat_key, config::input.key_repeat_delay, packet->keyCode).task_id;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Already released
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(!release) {
|
||||
// Already pressed down key
|
||||
return;
|
||||
}
|
||||
|
||||
pressed = !release;
|
||||
platf::keyboard(platf_input, packet->keyCode & 0x00FF, release);
|
||||
}
|
||||
|
||||
void passthrough(platf::input_t &input, PNV_SCROLL_PACKET packet) {
|
||||
|
@ -112,8 +112,14 @@ public:
|
||||
|
||||
using __return = std::invoke_result_t<Function, Args &&...>;
|
||||
using task_t = std::packaged_task<__return()>;
|
||||
|
||||
__time_point time_point = std::chrono::steady_clock::now() + duration;
|
||||
|
||||
__time_point time_point;
|
||||
if constexpr (std::is_floating_point_v<X>) {
|
||||
time_point = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::nanoseconds>(duration);
|
||||
}
|
||||
else {
|
||||
time_point = std::chrono::steady_clock::now() + duration;
|
||||
}
|
||||
|
||||
auto bind = [task = std::forward<Function>(newTask), tuple_args = std::make_tuple(std::forward<Args>(args)...)]() mutable {
|
||||
return std::apply(task, std::move(tuple_args));
|
||||
|
Loading…
x
Reference in New Issue
Block a user