InputCommon: Make hotkeys and input detection aware of Ctrl -> L_Ctrl / R_Ctrl hierarchy.

This commit is contained in:
Jordan Woyak 2020-01-26 13:58:20 -06:00
parent aae913fbc6
commit d8ad8c3861
4 changed files with 65 additions and 44 deletions

View File

@ -93,6 +93,12 @@ QString DetectExpression(QPushButton* button, ciface::Core::DeviceContainer& dev
if (!full_expression.isEmpty())
full_expression += QChar::fromLatin1('+');
// Return the parent-most name if there is one for better hotkey strings.
// Detection of L/R_Ctrl will be changed to just Ctrl.
// Users can manually map L_Ctrl if they so desire.
if (quote == Quote::On)
input = device->GetParentMostInput(input);
full_expression += MappingCommon::GetExpressionForControl(
QString::fromStdString(input->GetName()), device_qualifier, default_device, quote);
}

View File

@ -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); });
});
}

View File

@ -21,6 +21,38 @@ namespace ciface::Core
// Note: Detect() logic assumes this is greater than 0.5.
constexpr ControlState INPUT_DETECT_THRESHOLD = 0.55;
class CombinedInput final : public Device::Input
{
public:
using Inputs = std::pair<Device::Input*, Device::Input*>;
CombinedInput(std::string name, const Inputs& inputs) : m_name(std::move(name)), m_inputs(inputs)
{
}
ControlState GetState() const override
{
ControlState result = 0;
if (m_inputs.first)
result = m_inputs.first->GetState();
if (m_inputs.second)
result = std::max(result, m_inputs.second->GetState());
return result;
}
std::string GetName() const override { return m_name; }
bool IsDetectable() const override { return false; }
bool IsChild(const Input* input) const override
{
return m_inputs.first == input || m_inputs.second == input;
}
private:
const std::string m_name;
const std::pair<Device::Input*, Device::Input*> m_inputs;
};
Device::~Device()
{
// delete inputs
@ -52,6 +84,20 @@ std::string Device::GetQualifiedName() const
return fmt::format("{}/{}/{}", GetSource(), GetId(), GetName());
}
auto Device::GetParentMostInput(Input* child) const -> Input*
{
for (auto* input : m_inputs)
{
if (input->IsChild(child))
{
// Running recursively is currently unnecessary but it doesn't hurt.
return GetParentMostInput(input);
}
}
return child;
}
Device::Input* Device::FindInput(std::string_view name) const
{
for (Input* input : m_inputs)
@ -103,34 +149,6 @@ bool Device::FullAnalogSurface::IsMatchingName(std::string_view name) const
return old_name == name;
}
Device::CombinedInput::CombinedInput(std::string name, const Inputs& inputs)
: m_name(std::move(name)), m_inputs(inputs)
{
}
ControlState Device::CombinedInput::GetState() const
{
ControlState result = 0;
if (m_inputs.first)
result = m_inputs.first->GetState();
if (m_inputs.second)
result = std::max(result, m_inputs.second->GetState());
return result;
}
std::string Device::CombinedInput::GetName() const
{
return m_name;
}
bool Device::CombinedInput::IsDetectable()
{
return false;
}
void Device::AddCombinedInput(std::string name, const std::pair<std::string, std::string>& inputs)
{
AddInput(new CombinedInput(std::move(name), {FindInput(inputs.first), FindInput(inputs.second)}));

View File

@ -85,6 +85,11 @@ public:
virtual ControlState GetState() const = 0;
Input* ToInput() override { return this; }
// Overridden by CombinedInput,
// so hotkey logic knows Ctrl, L_Ctrl, and R_Ctrl are the same,
// and so input detection can return the parent name.
virtual bool IsChild(const Input*) const { return false; }
};
//
@ -119,6 +124,8 @@ public:
const std::vector<Input*>& Inputs() const { return m_inputs; }
const std::vector<Output*>& Outputs() const { return m_outputs; }
Input* GetParentMostInput(Input* input) const;
Input* FindInput(std::string_view name) const;
Output* FindOutput(std::string_view name) const;
@ -147,21 +154,6 @@ protected:
AddInput(new FullAnalogSurface(high, low));
}
class CombinedInput final : public Input
{
public:
using Inputs = std::pair<Input*, Input*>;
CombinedInput(std::string name, const Inputs& inputs);
ControlState GetState() const override;
std::string GetName() const override;
bool IsDetectable() override;
private:
const std::string m_name;
const std::pair<Input*, Input*> m_inputs;
};
void AddCombinedInput(std::string name, const std::pair<std::string, std::string>& inputs);
private: