From 52547379c99f290118641f29168cfae5cc94db51 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Tue, 22 Oct 2019 19:12:55 -0500 Subject: ExpressionParser: Add Hotkey syntax. --- .../ControlReference/ExpressionParser.cpp | 97 ++++++++++++++++++++++ 1 file changed, 97 insertions(+) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 1b1a24753c..0533b88a16 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include #include #include #include @@ -112,6 +113,8 @@ Token Lexer::NextToken() return Token(TOK_LPAREN); case ')': return Token(TOK_RPAREN); + case '@': + return Token(TOK_HOTKEY); case '&': return Token(TOK_AND); case '|': @@ -374,6 +377,63 @@ protected: ControlState* m_value_ptr{}; }; +class HotkeyExpression : public Expression +{ +public: + HotkeyExpression(std::vector> inputs) + : m_inputs(std::move(inputs)) + { + } + + ControlState GetValue() const override + { + if (m_inputs.empty()) + return 0; + + const bool modifiers_pressed = std::all_of(m_inputs.begin(), std::prev(m_inputs.end()), + [](const std::unique_ptr& input) { + // TODO: kill magic number. + return input->GetValue() > 0.5; + }); + + if (modifiers_pressed) + { + // TODO: kill magic number. + const bool final_input_pressed = (**m_inputs.rbegin()).GetValue() > 0.5; + + if (m_is_ready) + return final_input_pressed; + + if (!final_input_pressed) + m_is_ready = true; + } + else + m_is_ready = false; + + return 0; + } + + void SetValue(ControlState) override {} + + int CountNumControls() const override + { + int result = 0; + for (auto& input : m_inputs) + result += input->CountNumControls(); + return result; + } + + void UpdateReferences(ControlEnvironment& env) override + { + for (auto& input : m_inputs) + input->UpdateReferences(env); + } + +private: + std::vector> m_inputs; + mutable bool m_is_ready = false; +}; + // This class proxies all methods to its either left-hand child if it has bound controls, or its // right-hand child. Its intended use is for supporting old-style barewords expressions. class CoalesceExpression : public Expression @@ -600,6 +660,10 @@ private: { return ParseParens(); } + case TOK_HOTKEY: + { + return ParseHotkeys(); + } case TOK_SUB: { // An atom was expected but we got a subtraction symbol. @@ -684,6 +748,39 @@ private: return result; } + ParseResult ParseHotkeys() + { + Token tok = Chew(); + if (tok.type != TOK_LPAREN) + return ParseResult::MakeErrorResult(tok, _trans("Expected opening paren.")); + + std::vector> inputs; + + while (true) + { + tok = Chew(); + + if (tok.type != TOK_CONTROL && tok.type != TOK_BAREWORD) + return ParseResult::MakeErrorResult(tok, _trans("Expected name of input.")); + + ControlQualifier cq; + cq.FromString(tok.data); + inputs.emplace_back(std::make_unique(std::move(cq))); + + tok = Chew(); + + if (tok.type == TOK_ADD) + continue; + + if (tok.type == TOK_RPAREN) + break; + + return ParseResult::MakeErrorResult(tok, _trans("Expected + or closing paren.")); + } + + return ParseResult::MakeSuccessfulResult(std::make_unique(std::move(inputs))); + } + ParseResult ParseToplevel() { return ParseBinary(); } }; // namespace ExpressionParser -- cgit v1.2.3 From e6ba495486b2c7ac337fa4ecd62597a0f9a56e51 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 23 Oct 2019 16:45:21 -0500 Subject: ExpressionParser: Suppress inputs when hotkey modifiers are pressed. --- .../ControlReference/ExpressionParser.cpp | 57 ++++++++++++++++++++-- 1 file changed, 52 insertions(+), 5 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 0533b88a16..04ddef976e 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -13,6 +14,7 @@ #include #include "Common/Common.h" +#include "Common/ScopeGuard.h" #include "Common/StringUtil.h" #include "InputCommon/ControlReference/ExpressionParser.h" @@ -22,6 +24,32 @@ namespace ciface::ExpressionParser { using namespace ciface::Core; +class HotkeySuppressions +{ +public: + bool IsSuppressed(Device::Input* input) const { return m_suppressions.count(input) != 0; } + + using Suppressor = std::unique_ptr; + + Suppressor MakeSuppressor(Device::Input* input) + { + ++m_suppressions[input]; + return std::make_unique([this, input]() { RemoveSuppression(input); }); + } + +private: + void RemoveSuppression(Device::Input* input) + { + auto it = m_suppressions.find(input); + if (--(it->second) == 0) + m_suppressions.erase(it); + } + + std::map m_suppressions; +}; + +static HotkeySuppressions s_hotkey_suppressions; + Token::Token(TokenType type_) : type(type_) { } @@ -201,7 +229,7 @@ public: explicit ControlExpression(ControlQualifier qualifier_) : qualifier(qualifier_) {} ControlState GetValue() const override { - if (!input) + if (!input || s_hotkey_suppressions.IsSuppressed(input)) return 0.0; // Note: Inputs may return negative values in situations where opposing directions are @@ -225,6 +253,8 @@ public: output = env.FindOutput(qualifier); } + Device::Input* GetInput() const { return input; }; + private: ControlQualifier qualifier; Device::Input* input = nullptr; @@ -398,17 +428,31 @@ public: if (modifiers_pressed) { + auto& final_input = **m_inputs.rbegin(); + + // Remove supression before getting value. + m_suppressor = {}; + + const ControlState final_input_state = final_input.GetValue(); + // TODO: kill magic number. - const bool final_input_pressed = (**m_inputs.rbegin()).GetValue() > 0.5; + if (final_input_state < 0.5) + m_is_ready = true; if (m_is_ready) - return final_input_pressed; + { + // Only suppress input when we have at least one modifier. + if (m_inputs.size() > 1) + m_suppressor = s_hotkey_suppressions.MakeSuppressor(final_input.GetInput()); - if (!final_input_pressed) - m_is_ready = true; + return final_input_state; + } } else + { + m_suppressor = {}; m_is_ready = false; + } return 0; } @@ -425,12 +469,15 @@ public: void UpdateReferences(ControlEnvironment& env) override { + m_suppressor = {}; + for (auto& input : m_inputs) input->UpdateReferences(env); } private: std::vector> m_inputs; + mutable HotkeySuppressions::Suppressor m_suppressor; mutable bool m_is_ready = false; }; -- cgit v1.2.3 From d2729df281485651cbc3c27e4c9419f43fe61408 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Fri, 25 Oct 2019 18:49:06 -0500 Subject: ExpressionParser: Allow duplicate and superset modifier hotkeys to function. --- .../ControlReference/ExpressionParser.cpp | 134 +++++++++++++++------ 1 file changed, 100 insertions(+), 34 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 04ddef976e..7747ae956d 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -24,28 +24,43 @@ namespace ciface::ExpressionParser { using namespace ciface::Core; +class ControlExpression; + class HotkeySuppressions { public: - bool IsSuppressed(Device::Input* input) const { return m_suppressions.count(input) != 0; } - using Suppressor = std::unique_ptr; - Suppressor MakeSuppressor(Device::Input* input) + bool IsSuppressed(Device::Input* input) const { - ++m_suppressions[input]; - return std::make_unique([this, input]() { RemoveSuppression(input); }); + // An input is suppressed if it exists in the map (with any modifier). + auto it = m_suppressions.lower_bound({input, nullptr}); + return it != m_suppressions.end() && (it->first.first == input); } + // Suppresses each input + modifier pair. + // The returned object removes the suppression on destruction. + Suppressor MakeSuppressor(const std::vector>& modifiers, + const std::unique_ptr& final_input); + + // Removes suppression for each input + modifier pair. + // The returned object restores the original suppression on destruction. + Suppressor MakeAntiSuppressor(const std::vector>& modifiers, + const std::unique_ptr& final_input); + private: - void RemoveSuppression(Device::Input* input) + using Suppression = std::pair; + using SuppressionLevel = u16; + + void RemoveSuppression(Device::Input* modifier, Device::Input* final_input) { - auto it = m_suppressions.find(input); - if (--(it->second) == 0) + auto it = m_suppressions.find({final_input, modifier}); + if ((--it->second) == 0) m_suppressions.erase(it); } - std::map m_suppressions; + // Holds counts of suppressions for each input/modifier pair. + std::map m_suppressions; }; static HotkeySuppressions s_hotkey_suppressions; @@ -227,9 +242,18 @@ public: std::shared_ptr m_device; explicit ControlExpression(ControlQualifier qualifier_) : qualifier(qualifier_) {} + ControlState GetValue() const override { - if (!input || s_hotkey_suppressions.IsSuppressed(input)) + if (s_hotkey_suppressions.IsSuppressed(input)) + return 0; + else + return GetValueIgnoringSuppression(); + } + + ControlState GetValueIgnoringSuppression() const + { + if (!input) return 0.0; // Note: Inputs may return negative values in situations where opposing directions are @@ -261,6 +285,35 @@ private: Device::Output* output = nullptr; }; +HotkeySuppressions::Suppressor +HotkeySuppressions::MakeSuppressor(const std::vector>& modifiers, + const std::unique_ptr& final_input) +{ + for (auto& modifier : modifiers) + ++m_suppressions[{final_input->GetInput(), modifier->GetInput()}]; + + return std::make_unique([this, &modifiers, &final_input]() { + for (auto& modifier : modifiers) + RemoveSuppression(modifier->GetInput(), final_input->GetInput()); + }); +} + +HotkeySuppressions::Suppressor HotkeySuppressions::MakeAntiSuppressor( + const std::vector>& modifiers, + const std::unique_ptr& final_input) +{ + decltype(m_suppressions) unsuppressed_modifiers; + + for (auto& modifier : modifiers) + unsuppressed_modifiers.insert( + m_suppressions.extract({final_input->GetInput(), modifier->GetInput()})); + + return std::make_unique( + [this, unsuppressed_modifiers{std::move(unsuppressed_modifiers)}]() mutable { + m_suppressions.merge(unsuppressed_modifiers); + }); +} + class BinaryExpression : public Expression { public: @@ -411,42 +464,45 @@ class HotkeyExpression : public Expression { public: HotkeyExpression(std::vector> inputs) - : m_inputs(std::move(inputs)) + : m_modifiers(std::move(inputs)) { + m_final_input = std::move(m_modifiers.back()); + m_modifiers.pop_back(); } ControlState GetValue() const override { - if (m_inputs.empty()) - return 0; - - const bool modifiers_pressed = std::all_of(m_inputs.begin(), std::prev(m_inputs.end()), + const bool modifiers_pressed = std::all_of(m_modifiers.begin(), m_modifiers.end(), [](const std::unique_ptr& input) { // TODO: kill magic number. return input->GetValue() > 0.5; }); + const auto final_input_state = m_final_input->GetValueIgnoringSuppression(); + if (modifiers_pressed) { - auto& final_input = **m_inputs.rbegin(); + if (final_input_state < 0.5) + { + if (!m_suppressor) + EnableSuppression(); - // Remove supression before getting value. - m_suppressor = {}; + m_is_ready = true; + } - const ControlState final_input_state = final_input.GetValue(); + // Ignore suppression of our own modifiers. This also allows superset modifiers to function. + const auto anti_suppression = + s_hotkey_suppressions.MakeAntiSuppressor(m_modifiers, m_final_input); - // TODO: kill magic number. - if (final_input_state < 0.5) - m_is_ready = true; + const bool is_suppressed = s_hotkey_suppressions.IsSuppressed(m_final_input->GetInput()); - if (m_is_ready) - { - // Only suppress input when we have at least one modifier. - if (m_inputs.size() > 1) - m_suppressor = s_hotkey_suppressions.MakeSuppressor(final_input.GetInput()); + // If some other hotkey suppressed us, require a release of final input to be ready again. + if (is_suppressed) + m_is_ready = false; + // Our modifiers are active. Pass through the final input. + if (m_is_ready) return final_input_state; - } } else { @@ -462,21 +518,31 @@ public: int CountNumControls() const override { int result = 0; - for (auto& input : m_inputs) + for (auto& input : m_modifiers) result += input->CountNumControls(); - return result; + return result + m_final_input->CountNumControls(); } void UpdateReferences(ControlEnvironment& env) override { - m_suppressor = {}; - - for (auto& input : m_inputs) + for (auto& input : m_modifiers) input->UpdateReferences(env); + + m_final_input->UpdateReferences(env); + + // We must update our suppression with valid pointers. + if (m_suppressor) + EnableSuppression(); } private: - std::vector> m_inputs; + void EnableSuppression() const + { + m_suppressor = s_hotkey_suppressions.MakeSuppressor(m_modifiers, m_final_input); + } + + std::vector> m_modifiers; + std::unique_ptr m_final_input; mutable HotkeySuppressions::Suppressor m_suppressor; mutable bool m_is_ready = false; }; -- cgit v1.2.3 From aae913fbc6da714b3777e3a3c20fd06d1e423a0e Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sat, 2 Nov 2019 09:55:45 -0500 Subject: InputCommon: Clean up modifier ignoring logic. --- .../ControlReference/ExpressionParser.cpp | 71 ++++++++++------------ 1 file changed, 32 insertions(+), 39 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 7747ae956d..9e36c49a05 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -14,6 +14,7 @@ #include #include "Common/Common.h" +#include "Common/Logging/Log.h" #include "Common/ScopeGuard.h" #include "Common/StringUtil.h" @@ -29,24 +30,22 @@ class ControlExpression; class HotkeySuppressions { public: + using Modifiers = std::vector>; using Suppressor = std::unique_ptr; bool IsSuppressed(Device::Input* input) const { - // An input is suppressed if it exists in the map (with any modifier). - auto it = m_suppressions.lower_bound({input, nullptr}); - return it != m_suppressions.end() && (it->first.first == input); + // Input is suppressed if it exists in the map at all. + return m_suppressions.lower_bound({input, nullptr}) != + m_suppressions.lower_bound({input + 1, nullptr}); } + bool IsSuppressedIgnoringModifiers(Device::Input* input, const Modifiers& ignore_modifiers) const; + // Suppresses each input + modifier pair. // The returned object removes the suppression on destruction. - Suppressor MakeSuppressor(const std::vector>& modifiers, - const std::unique_ptr& final_input); - - // Removes suppression for each input + modifier pair. - // The returned object restores the original suppression on destruction. - Suppressor MakeAntiSuppressor(const std::vector>& modifiers, - const std::unique_ptr& final_input); + Suppressor MakeSuppressor(const Modifiers* modifiers, + const std::unique_ptr* final_input); private: using Suppression = std::pair; @@ -285,33 +284,30 @@ private: Device::Output* output = nullptr; }; -HotkeySuppressions::Suppressor -HotkeySuppressions::MakeSuppressor(const std::vector>& modifiers, - const std::unique_ptr& final_input) +bool HotkeySuppressions::IsSuppressedIgnoringModifiers(Device::Input* input, + const Modifiers& ignore_modifiers) const { - for (auto& modifier : modifiers) - ++m_suppressions[{final_input->GetInput(), modifier->GetInput()}]; + // Input is suppressed if it exists in the map with a modifier that we aren't ignoring. + auto it = m_suppressions.lower_bound({input, nullptr}); + auto it_end = m_suppressions.lower_bound({input + 1, nullptr}); - return std::make_unique([this, &modifiers, &final_input]() { - for (auto& modifier : modifiers) - RemoveSuppression(modifier->GetInput(), final_input->GetInput()); + return std::any_of(it, it_end, [&](auto& s) { + return std::none_of(begin(ignore_modifiers), end(ignore_modifiers), + [&](auto& m) { return m->GetInput() == s.first.second; }); }); } -HotkeySuppressions::Suppressor HotkeySuppressions::MakeAntiSuppressor( - const std::vector>& modifiers, - const std::unique_ptr& final_input) +HotkeySuppressions::Suppressor +HotkeySuppressions::MakeSuppressor(const Modifiers* modifiers, + const std::unique_ptr* final_input) { - decltype(m_suppressions) unsuppressed_modifiers; + for (auto& modifier : *modifiers) + ++m_suppressions[{(*final_input)->GetInput(), modifier->GetInput()}]; - for (auto& modifier : modifiers) - unsuppressed_modifiers.insert( - m_suppressions.extract({final_input->GetInput(), modifier->GetInput()})); - - return std::make_unique( - [this, unsuppressed_modifiers{std::move(unsuppressed_modifiers)}]() mutable { - m_suppressions.merge(unsuppressed_modifiers); - }); + return std::make_unique([this, modifiers, final_input]() { + for (auto& modifier : *modifiers) + RemoveSuppression(modifier->GetInput(), (*final_input)->GetInput()); + }); } class BinaryExpression : public Expression @@ -474,15 +470,14 @@ public: { const bool modifiers_pressed = std::all_of(m_modifiers.begin(), m_modifiers.end(), [](const std::unique_ptr& input) { - // TODO: kill magic number. - return input->GetValue() > 0.5; + return input->GetValue() > CONDITION_THRESHOLD; }); const auto final_input_state = m_final_input->GetValueIgnoringSuppression(); if (modifiers_pressed) { - if (final_input_state < 0.5) + if (final_input_state < CONDITION_THRESHOLD) { if (!m_suppressor) EnableSuppression(); @@ -491,10 +486,8 @@ public: } // Ignore suppression of our own modifiers. This also allows superset modifiers to function. - const auto anti_suppression = - s_hotkey_suppressions.MakeAntiSuppressor(m_modifiers, m_final_input); - - const bool is_suppressed = s_hotkey_suppressions.IsSuppressed(m_final_input->GetInput()); + const bool is_suppressed = s_hotkey_suppressions.IsSuppressedIgnoringModifiers( + m_final_input->GetInput(), m_modifiers); // If some other hotkey suppressed us, require a release of final input to be ready again. if (is_suppressed) @@ -538,10 +531,10 @@ public: private: void EnableSuppression() const { - m_suppressor = s_hotkey_suppressions.MakeSuppressor(m_modifiers, m_final_input); + m_suppressor = s_hotkey_suppressions.MakeSuppressor(&m_modifiers, &m_final_input); } - std::vector> m_modifiers; + HotkeySuppressions::Modifiers m_modifiers; std::unique_ptr m_final_input; mutable HotkeySuppressions::Suppressor m_suppressor; mutable bool m_is_ready = false; -- cgit v1.2.3 From d8ad8c386121e9c937360b102289231d86693dd1 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 26 Jan 2020 13:58:20 -0600 Subject: InputCommon: Make hotkeys and input detection aware of Ctrl -> L_Ctrl / R_Ctrl hierarchy. --- Source/Core/InputCommon/ControlReference/ExpressionParser.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 9e36c49a05..cbc4a1462b 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -291,9 +291,14 @@ bool HotkeySuppressions::IsSuppressedIgnoringModifiers(Device::Input* input, auto it = m_suppressions.lower_bound({input, nullptr}); auto it_end = m_suppressions.lower_bound({input + 1, nullptr}); + // We need to ignore L_Ctrl R_Ctrl when supplied Ctrl and vice-versa. + const auto is_same_modifier = [](Device::Input* i1, Device::Input* i2) { + return i1 == i2 || i1->IsChild(i2) || i2->IsChild(i1); + }; + return std::any_of(it, it_end, [&](auto& s) { return std::none_of(begin(ignore_modifiers), end(ignore_modifiers), - [&](auto& m) { return m->GetInput() == s.first.second; }); + [&](auto& m) { return is_same_modifier(m->GetInput(), s.first.second); }); }); } -- cgit v1.2.3 From 44927da420e8715cf041a50a38de08bc649e6685 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 16 Feb 2020 13:09:12 -0600 Subject: ExpressionParser: Replace ScopeGuard with custom deleter unique_ptr. --- .../ControlReference/ExpressionParser.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index cbc4a1462b..7636f6f1aa 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -15,7 +15,6 @@ #include "Common/Common.h" #include "Common/Logging/Log.h" -#include "Common/ScopeGuard.h" #include "Common/StringUtil.h" #include "InputCommon/ControlReference/ExpressionParser.h" @@ -31,7 +30,17 @@ class HotkeySuppressions { public: using Modifiers = std::vector>; - using Suppressor = std::unique_ptr; + + struct InvokingDeleter + { + template + void operator()(T* func) + { + (*func)(); + } + }; + + using Suppressor = std::unique_ptr, InvokingDeleter>; bool IsSuppressed(Device::Input* input) const { @@ -309,10 +318,11 @@ HotkeySuppressions::MakeSuppressor(const Modifiers* modifiers, for (auto& modifier : *modifiers) ++m_suppressions[{(*final_input)->GetInput(), modifier->GetInput()}]; - return std::make_unique([this, modifiers, final_input]() { - for (auto& modifier : *modifiers) - RemoveSuppression(modifier->GetInput(), (*final_input)->GetInput()); - }); + return Suppressor(std::make_unique>([this, modifiers, final_input]() { + for (auto& modifier : *modifiers) + RemoveSuppression(modifier->GetInput(), (*final_input)->GetInput()); + }).release(), + InvokingDeleter{}); } class BinaryExpression : public Expression -- cgit v1.2.3 From 431eb4d60d8a413ad9a4a72b1305f8090410a741 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 30 Aug 2020 19:25:35 -0500 Subject: ExpressionParser: Improve hotkey suppression logic. Allow activation with simultaneous press of modifier and final input. --- .../ControlReference/ExpressionParser.cpp | 29 +++++++++++----------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 7636f6f1aa..d4f93450e3 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -14,7 +14,6 @@ #include #include "Common/Common.h" -#include "Common/Logging/Log.h" #include "Common/StringUtil.h" #include "InputCommon/ControlReference/ExpressionParser.h" @@ -492,30 +491,29 @@ public: if (modifiers_pressed) { - if (final_input_state < CONDITION_THRESHOLD) - { - if (!m_suppressor) - EnableSuppression(); - - m_is_ready = true; - } - // Ignore suppression of our own modifiers. This also allows superset modifiers to function. const bool is_suppressed = s_hotkey_suppressions.IsSuppressedIgnoringModifiers( m_final_input->GetInput(), m_modifiers); + if (final_input_state < CONDITION_THRESHOLD) + m_is_blocked = false; + // If some other hotkey suppressed us, require a release of final input to be ready again. if (is_suppressed) - m_is_ready = false; + m_is_blocked = true; + + if (m_is_blocked) + return 0; + + EnableSuppression(); // Our modifiers are active. Pass through the final input. - if (m_is_ready) - return final_input_state; + return final_input_state; } else { m_suppressor = {}; - m_is_ready = false; + m_is_blocked = final_input_state > CONDITION_THRESHOLD; } return 0; @@ -546,13 +544,14 @@ public: private: void EnableSuppression() const { - m_suppressor = s_hotkey_suppressions.MakeSuppressor(&m_modifiers, &m_final_input); + if (!m_suppressor) + m_suppressor = s_hotkey_suppressions.MakeSuppressor(&m_modifiers, &m_final_input); } HotkeySuppressions::Modifiers m_modifiers; std::unique_ptr m_final_input; mutable HotkeySuppressions::Suppressor m_suppressor; - mutable bool m_is_ready = false; + mutable bool m_is_blocked = false; }; // This class proxies all methods to its either left-hand child if it has bound controls, or its -- cgit v1.2.3