From 602c0475628e52c17476d5a8c264d509bb28f344 Mon Sep 17 00:00:00 2001 From: houmain Date: Thu, 18 Jul 2024 11:21:30 +0200 Subject: [PATCH] Prevent infinite loop when two ContextActive toggle each other --- src/server/ServerState.cpp | 8 ++++++-- src/test/test4_Server.cpp | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/server/ServerState.cpp b/src/server/ServerState.cpp index 49774ec..f1be3c9 100644 --- a/src/server/ServerState.cpp +++ b/src/server/ServerState.cpp @@ -271,6 +271,7 @@ bool ServerState::flush_send_buffer() { auto succeeded = true; auto i = size_t{ }; + auto toggled_virtual_keys = 0; for (; i < m_send_buffer.size(); ++i) { const auto& event = m_send_buffer[i]; @@ -282,8 +283,11 @@ bool ServerState::flush_send_buffer() { } if (is_virtual_key(event.key)) { - if (event.state == KeyState::Down) - toggle_virtual_key(event.key); + if (event.state == KeyState::Down) { + // prevent infinite loop (when two ContextActive toggle each other) + if (++toggled_virtual_keys < 10) + toggle_virtual_key(event.key); + } continue; } diff --git a/src/test/test4_Server.cpp b/src/test/test4_Server.cpp index 5ac8d31..27313a8 100644 --- a/src/test/test4_Server.cpp +++ b/src/test/test4_Server.cpp @@ -152,7 +152,6 @@ TEST_CASE("Minimal configuration", "[Server]") { CHECK(state.apply_input("-A") == "-B"); } - //-------------------------------------------------------------------- TEST_CASE("Modifier filter and no might match (infinite loop bug)", "[Server]") { @@ -170,6 +169,41 @@ TEST_CASE("Modifier filter and no might match (infinite loop bug)", "[Server]") //-------------------------------------------------------------------- +TEST_CASE("Modifier filter toggled in ContextActive", "[Server]") { + auto state = create_state(R"( + X >> Virtual1 + + [modifier = Virtual1] + ContextActive >> A Virtual1 + )"); + CHECK(state.apply_input("+X") == "+A -A"); + CHECK(state.apply_input("-X") == ""); + CHECK(state.apply_input("+X") == "+A -A"); + CHECK(state.apply_input("-X") == ""); +} + +//-------------------------------------------------------------------- + +TEST_CASE("Modifier filter toggled in two ContextActive (prevent infinite loop)", "[Server]") { + auto state = create_state(R"( + C >> Virtual1 + + [modifier = Virtual1] + ContextActive >> A Virtual1 + + [modifier = "!Virtual1"] + ContextActive >> B Virtual1 + )", false); + CHECK(state.set_active_contexts({ 0, 1, 2 }) == "+B -B +A -A +B -B +A -A +B -B +A -A +B -B +A -A +B -B +A -A"); + CHECK(state.apply_input("+A -A") == "+A -A"); + CHECK(state.apply_input("+B -B") == "+B -B"); + CHECK(state.apply_input("+C") == "+B -B +A -A +B -B +A -A +B -B +A -A +B -B +A -A +B -B"); + CHECK(state.apply_input("+A -A") == "+A -A"); + CHECK(state.apply_input("+B -B") == "+B -B"); +} + +//-------------------------------------------------------------------- + TEST_CASE("Trigger Not Timeout", "[Server]") { auto state = create_state(R"( ShiftLeft{!200ms} >> B