InputCommon: Make hotkeys and input detection aware of Ctrl -> L_Ctrl / R_Ctrl hierarchy.
This commit is contained in:
parent
aae913fbc6
commit
d8ad8c3861
|
@ -93,6 +93,12 @@ QString DetectExpression(QPushButton* button, ciface::Core::DeviceContainer& dev
|
||||||
if (!full_expression.isEmpty())
|
if (!full_expression.isEmpty())
|
||||||
full_expression += QChar::fromLatin1('+');
|
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(
|
full_expression += MappingCommon::GetExpressionForControl(
|
||||||
QString::fromStdString(input->GetName()), device_qualifier, default_device, quote);
|
QString::fromStdString(input->GetName()), device_qualifier, default_device, quote);
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,9 +291,14 @@ bool HotkeySuppressions::IsSuppressedIgnoringModifiers(Device::Input* input,
|
||||||
auto it = m_suppressions.lower_bound({input, nullptr});
|
auto it = m_suppressions.lower_bound({input, nullptr});
|
||||||
auto it_end = m_suppressions.lower_bound({input + 1, 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::any_of(it, it_end, [&](auto& s) {
|
||||||
return std::none_of(begin(ignore_modifiers), end(ignore_modifiers),
|
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); });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,38 @@ namespace ciface::Core
|
||||||
// Note: Detect() logic assumes this is greater than 0.5.
|
// Note: Detect() logic assumes this is greater than 0.5.
|
||||||
constexpr ControlState INPUT_DETECT_THRESHOLD = 0.55;
|
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()
|
Device::~Device()
|
||||||
{
|
{
|
||||||
// delete inputs
|
// delete inputs
|
||||||
|
@ -52,6 +84,20 @@ std::string Device::GetQualifiedName() const
|
||||||
return fmt::format("{}/{}/{}", GetSource(), GetId(), GetName());
|
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
|
Device::Input* Device::FindInput(std::string_view name) const
|
||||||
{
|
{
|
||||||
for (Input* input : m_inputs)
|
for (Input* input : m_inputs)
|
||||||
|
@ -103,34 +149,6 @@ bool Device::FullAnalogSurface::IsMatchingName(std::string_view name) const
|
||||||
return old_name == name;
|
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)
|
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)}));
|
AddInput(new CombinedInput(std::move(name), {FindInput(inputs.first), FindInput(inputs.second)}));
|
||||||
|
|
|
@ -85,6 +85,11 @@ public:
|
||||||
virtual ControlState GetState() const = 0;
|
virtual ControlState GetState() const = 0;
|
||||||
|
|
||||||
Input* ToInput() override { return this; }
|
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<Input*>& Inputs() const { return m_inputs; }
|
||||||
const std::vector<Output*>& Outputs() const { return m_outputs; }
|
const std::vector<Output*>& Outputs() const { return m_outputs; }
|
||||||
|
|
||||||
|
Input* GetParentMostInput(Input* input) const;
|
||||||
|
|
||||||
Input* FindInput(std::string_view name) const;
|
Input* FindInput(std::string_view name) const;
|
||||||
Output* FindOutput(std::string_view name) const;
|
Output* FindOutput(std::string_view name) const;
|
||||||
|
|
||||||
|
@ -147,21 +154,6 @@ protected:
|
||||||
AddInput(new FullAnalogSurface(high, low));
|
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);
|
void AddCombinedInput(std::string name, const std::pair<std::string, std::string>& inputs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in New Issue