Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions config/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ tap = "mouse_side" # KEY_*, mouse_left/right/middle/side/extra
hold_timeout = 200 # ms before layer activates
gyro = { mode = "mouse", sensitivity = 2.0 }
stick_left = { mode = "scroll" } # gamepad / mouse / scroll
stick_right = { mode = "mouse", sensitivity = 1.0 } # gamepad / mouse
dpad = { mode = "arrows" } # gamepad / arrows / scroll
stick_right = { mode = "mouse", sensitivity = 1.0, suppress_gamepad = true }
dpad = { mode = "arrows", suppress_gamepad = true }
remap = { RB = "mouse_left", RT = "mouse_right", RM = "mouse_middle", A = "KEY_LEFTMETA" }

# Hold RM for stick mouse + arrows
[layer.mouse]
trigger = "RM"
hold_timeout = 150
stick_right = { mode = "mouse", sensitivity = 1.5 }
dpad = { mode = "arrows" }
remap = { A = "mouse_left", B = "mouse_right" }
stick_right = { mode = "mouse", sensitivity = 1.5, suppress_gamepad = true }
dpad = { mode = "arrows", suppress_gamepad = true }
remap = { A = "mouse_left", B = "mouse_right" }
2 changes: 2 additions & 0 deletions include/vader5/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ struct StickConfig {
Mode mode{Gamepad};
int deadzone{128};
float sensitivity{1.0F};
bool suppress_gamepad{false};
};

struct DpadConfig {
enum Mode { Gamepad, Arrows };
Mode mode{Gamepad};
bool suppress_gamepad{false};
};

struct LayerConfig {
Expand Down
10 changes: 10 additions & 0 deletions include/vader5/gamepad.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,16 @@ class Gamepad {
uint8_t injected_ext_{0};
uint16_t prev_injected_buttons_{0};
uint8_t prev_injected_ext_{0};
bool suppress_left_stick_{false};
bool suppress_right_stick_{false};
bool suppress_dpad_{false};
bool suppress_left_trigger_{false};
bool suppress_right_trigger_{false};
bool prev_suppress_left_stick_{false};
bool prev_suppress_right_stick_{false};
bool prev_suppress_dpad_{false};
bool prev_suppress_left_trigger_{false};
bool prev_suppress_right_trigger_{false};
};

} // namespace vader5
10 changes: 8 additions & 2 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,18 @@ void parse_stick(const toml::table& tbl, StickConfig& cfg) {
if (const auto* val = tbl["sensitivity"].as_floating_point()) {
cfg.sensitivity = static_cast<float>(val->get());
}
if (const auto* val = tbl["suppress_gamepad"].as_boolean()) {
cfg.suppress_gamepad = val->get();
}
}

void parse_dpad(const toml::table& tbl, DpadConfig& cfg) {
if (const auto* val = tbl["mode"].as_string()) {
cfg.mode = parse_dpad_mode(val->get());
}
if (const auto* val = tbl["suppress_gamepad"].as_boolean()) {
cfg.suppress_gamepad = val->get();
}
}

auto parse_layer(const std::string& name, const toml::table& tbl) -> LayerConfig {
Expand Down Expand Up @@ -234,8 +240,8 @@ auto Config::load(const std::string& path) -> Result<Config> {
if (const auto* shift_tbl = tbl["mode_shift"].as_table()) {
for (const auto& [name, node] : *shift_tbl) {
if (const auto* sub = node.as_table()) {
std::cerr << "[WARN] [mode_shift." << name << "] deprecated, use [layer."
<< name << "]\n";
std::cerr << "[WARN] [mode_shift." << name << "] deprecated, use [layer." << name
<< "]\n";
auto layer = parse_layer(std::string(name), *sub);
if (layer.trigger.empty()) {
layer.trigger = std::string(name);
Expand Down
179 changes: 156 additions & 23 deletions src/gamepad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ auto needs_mouse(const Config& cfg) -> bool {
if (layer.stick_right && layer.stick_right->mode == StickConfig::Mouse) {
return true;
}
if (layer.stick_left && layer.stick_left->mode == StickConfig::Mouse) {
return true;
}
if (layer.stick_left && layer.stick_left->mode == StickConfig::Scroll) {
return true;
}
Expand Down Expand Up @@ -508,26 +511,66 @@ void Gamepad::process_mouse_stick(const GamepadState& state) {
return;
}

const auto& cfg = get_effective_stick_right();
if (cfg.mode != StickConfig::Mouse) {
const auto& right_cfg = get_effective_stick_right();
const bool right_mouse = right_cfg.mode == StickConfig::Mouse;

const auto& left_cfg = get_effective_stick_left();
const bool left_mouse = left_cfg.mode == StickConfig::Mouse;

if (!right_mouse && !left_mouse) {
return;
}

int rx = state.right_x;
int ry = state.right_y;
if (std::abs(rx) < cfg.deadzone) {
rx = 0;
const bool in_layer = get_active_layer() != nullptr;

if (right_mouse && right_cfg.suppress_gamepad && in_layer) {
suppress_right_stick_ = true;
}
if (std::abs(ry) < cfg.deadzone) {
ry = 0;

if (left_mouse && left_cfg.suppress_gamepad && in_layer) {
suppress_left_stick_ = true;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

const int dx = static_cast<int>(static_cast<float>(rx) * STICK_SCALE * cfg.sensitivity);
const int dy = static_cast<int>(static_cast<float>(ry) * STICK_SCALE * cfg.sensitivity);
if (right_mouse) {
int rx = state.right_x;
int ry = state.right_y;
if (std::abs(rx) < right_cfg.deadzone) {
rx = 0;
}
if (std::abs(ry) < right_cfg.deadzone) {
ry = 0;
}

if (dx != 0 || dy != 0) {
input_->move_mouse(dx, dy);
[[maybe_unused]] auto r1 = input_->sync();
const int dx =
static_cast<int>(static_cast<float>(rx) * STICK_SCALE * right_cfg.sensitivity);
const int dy =
static_cast<int>(static_cast<float>(ry) * STICK_SCALE * right_cfg.sensitivity);

if (dx != 0 || dy != 0) {
input_->move_mouse(dx, dy);
[[maybe_unused]] auto r1 = input_->sync();
}
}

if (left_mouse) {
int lx = state.left_x;
int ly = state.left_y;
if (std::abs(lx) < left_cfg.deadzone) {
lx = 0;
}
if (std::abs(ly) < left_cfg.deadzone) {
ly = 0;
}

const int dx =
static_cast<int>(static_cast<float>(lx) * STICK_SCALE * left_cfg.sensitivity);
const int dy =
static_cast<int>(static_cast<float>(ly) * STICK_SCALE * left_cfg.sensitivity);

if (dx != 0 || dy != 0) {
input_->move_mouse(dx, dy);
[[maybe_unused]] auto r1 = input_->sync();
}
}
}

Expand All @@ -536,23 +579,53 @@ void Gamepad::process_scroll_stick(const GamepadState& state) {
return;
}

const auto& cfg = get_effective_stick_left();
if (cfg.mode != StickConfig::Scroll) {
const auto& left_cfg = get_effective_stick_left();
const auto& right_cfg = get_effective_stick_right();
const bool left_scroll = left_cfg.mode == StickConfig::Scroll;
const bool right_scroll = right_cfg.mode == StickConfig::Scroll;

if (!left_scroll && !right_scroll) {
scroll_accum_v_ = scroll_accum_h_ = 0.0F;
return;
}

int lx = state.left_x;
int ly = state.left_y;
if (std::abs(lx) < cfg.deadzone) {
lx = 0;
const bool in_layer = get_active_layer() != nullptr;

if (left_scroll && left_cfg.suppress_gamepad && in_layer) {
suppress_left_stick_ = true;
}
if (std::abs(ly) < cfg.deadzone) {
ly = 0;

if (right_scroll && right_cfg.suppress_gamepad && in_layer) {
suppress_right_stick_ = true;
}

scroll_accum_v_ += static_cast<float>(-ly) * SCROLL_SCALE * cfg.sensitivity;
scroll_accum_h_ += static_cast<float>(lx) * SCROLL_SCALE * cfg.sensitivity;
if (left_scroll) {
int lx = state.left_x;
int ly = state.left_y;
if (std::abs(lx) < left_cfg.deadzone) {
lx = 0;
}
if (std::abs(ly) < left_cfg.deadzone) {
ly = 0;
}

scroll_accum_v_ += static_cast<float>(-ly) * SCROLL_SCALE * left_cfg.sensitivity;
scroll_accum_h_ += static_cast<float>(lx) * SCROLL_SCALE * left_cfg.sensitivity;
}

if (right_scroll) {
int rx = state.right_x;
int ry = state.right_y;
if (std::abs(rx) < right_cfg.deadzone) {
rx = 0;
}
if (std::abs(ry) < right_cfg.deadzone) {
ry = 0;
}

scroll_accum_v_ += static_cast<float>(-ry) * SCROLL_SCALE * right_cfg.sensitivity;
scroll_accum_h_ += static_cast<float>(rx) * SCROLL_SCALE * right_cfg.sensitivity;
}

const int scroll_v = static_cast<int>(scroll_accum_v_);
const int scroll_h = static_cast<int>(scroll_accum_h_);
Expand All @@ -573,6 +646,11 @@ void Gamepad::process_layer_dpad(const GamepadState& state) {
const auto& cfg = get_effective_dpad();
const bool active = cfg.mode == DpadConfig::Arrows;

const bool in_layer = get_active_layer() != nullptr;
if (active && cfg.suppress_gamepad && in_layer) {
suppress_dpad_ = true;
}

auto is_up = [](uint8_t dp) {
return dp == DPAD_UP || dp == DPAD_UP_LEFT || dp == DPAD_UP_RIGHT;
};
Expand Down Expand Up @@ -721,6 +799,11 @@ auto Gamepad::poll() -> Result<void> {
suppressed_ext_ = 0;
injected_buttons_ = 0;
injected_ext_ = 0;
suppress_left_stick_ = false;
suppress_right_stick_ = false;
suppress_dpad_ = false;
suppress_left_trigger_ = false;
suppress_right_trigger_ = false;

update_tap_hold(*state, prev_state_);
process_gyro(*state);
Expand All @@ -730,10 +813,38 @@ auto Gamepad::poll() -> Result<void> {
process_base_remaps(*state, prev_state_);
process_layer_buttons(*state, prev_state_);

const auto* layer = get_active_layer();
if (layer != nullptr) {
if (layer->remap.contains("LT")) {
suppress_left_trigger_ = true;
}
if (layer->remap.contains("RT")) {
suppress_right_trigger_ = true;
}
}

auto emit_state = *state;
emit_state.buttons = (emit_state.buttons & ~suppressed_buttons_) | injected_buttons_;
emit_state.ext_buttons = (emit_state.ext_buttons & ~suppressed_ext_) | injected_ext_;

if (suppress_left_stick_) {
emit_state.left_x = 0;
emit_state.left_y = 0;
}
if (suppress_right_stick_) {
emit_state.right_x = 0;
emit_state.right_y = 0;
}
if (suppress_dpad_) {
emit_state.dpad = DPAD_NONE;
}
if (suppress_left_trigger_) {
emit_state.left_trigger = 0;
}
if (suppress_right_trigger_) {
emit_state.right_trigger = 0;
}

if (get_effective_gyro().mode == GyroConfig::Joystick) {
emit_state.right_x = static_cast<int16_t>(gyro_stick_x_);
emit_state.right_y = static_cast<int16_t>(gyro_stick_y_);
Expand All @@ -744,13 +855,35 @@ auto Gamepad::poll() -> Result<void> {
(emit_prev.buttons & ~prev_suppressed_buttons_) | prev_injected_buttons_;
emit_prev.ext_buttons =
(emit_prev.ext_buttons & ~prev_suppressed_ext_) | prev_injected_ext_;
if (prev_suppress_left_stick_) {
emit_prev.left_x = 0;
emit_prev.left_y = 0;
}
if (prev_suppress_right_stick_) {
emit_prev.right_x = 0;
emit_prev.right_y = 0;
}
if (prev_suppress_dpad_) {
emit_prev.dpad = DPAD_NONE;
}
if (prev_suppress_left_trigger_) {
emit_prev.left_trigger = 0;
}
if (prev_suppress_right_trigger_) {
emit_prev.right_trigger = 0;
}

auto result = uinput_.emit(emit_state, emit_prev);
prev_state_ = *state;
prev_suppressed_buttons_ = suppressed_buttons_;
prev_suppressed_ext_ = suppressed_ext_;
prev_injected_buttons_ = injected_buttons_;
prev_injected_ext_ = injected_ext_;
prev_suppress_left_stick_ = suppress_left_stick_;
prev_suppress_right_stick_ = suppress_right_stick_;
prev_suppress_dpad_ = suppress_dpad_;
prev_suppress_left_trigger_ = suppress_left_trigger_;
prev_suppress_right_trigger_ = suppress_right_trigger_;
return result;
}
return {};
Expand Down
Loading