mirror of
https://github.com/hyprwm/Hyprland.git
synced 2026-08-24 10:04:19 -05:00
240 lines
7.8 KiB
C++
240 lines
7.8 KiB
C++
#include <keybinds/Bind.hpp>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <array>
|
|
|
|
using namespace Keybinds;
|
|
using namespace Input;
|
|
|
|
static SResolvedKey resolvedKey(const char* name, xkb_keycode_t code, std::optional<Input::eKeyboardModifiers> modifier = std::nullopt) {
|
|
return {
|
|
.sym = xkb_keysym_from_name(name, XKB_KEYSYM_CASE_INSENSITIVE),
|
|
.code = code,
|
|
.modifier = modifier,
|
|
};
|
|
}
|
|
|
|
static std::expected<CBind, std::string> makeBind(std::vector<std::string>&& keys, eBindFlags flags = sc<eBindFlags>(0)) {
|
|
return CBind::make(std::move(keys), flags, [] { return SBindResult{}; });
|
|
}
|
|
|
|
TEST(Keybinds, SidedModifierMatchesCorrectSide) {
|
|
auto result = makeBind({"SHIFT_L", "K"});
|
|
ASSERT_TRUE(result.has_value());
|
|
|
|
const auto LEFT_SHIFT = resolvedKey("SHIFT_L", 50, HL_MODIFIER_SHIFT);
|
|
const auto RIGHT_SHIFT = resolvedKey("SHIFT_R", 62, HL_MODIFIER_SHIFT);
|
|
const auto K = resolvedKey("K", 45);
|
|
|
|
const std::array leftHeld = {LEFT_SHIFT, K};
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = leftHeld,
|
|
.trigger = K,
|
|
.modifiersNow = HL_MODIFIER_SHIFT,
|
|
}),
|
|
BIND_MATCH_FULL);
|
|
|
|
const std::array rightHeld = {RIGHT_SHIFT, K};
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = rightHeld,
|
|
.trigger = K,
|
|
.modifiersNow = HL_MODIFIER_SHIFT,
|
|
}),
|
|
BIND_MATCH_NONE);
|
|
|
|
const std::array bothHeld = {LEFT_SHIFT, RIGHT_SHIFT, K};
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = bothHeld,
|
|
.trigger = K,
|
|
.modifiersNow = HL_MODIFIER_SHIFT,
|
|
}),
|
|
BIND_MATCH_NONE);
|
|
}
|
|
|
|
TEST(Keybinds, SidedModifierCanPartiallyMatch) {
|
|
auto result = makeBind({"SHIFT_L", "K"});
|
|
ASSERT_TRUE(result.has_value());
|
|
|
|
const auto LEFT_SHIFT = resolvedKey("SHIFT_L", 50, HL_MODIFIER_SHIFT);
|
|
const std::array held = {LEFT_SHIFT};
|
|
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = held,
|
|
.trigger = LEFT_SHIFT,
|
|
.modifiersNow = Input::HL_MODIFIER_NONE,
|
|
}),
|
|
BIND_MATCH_PARTIAL);
|
|
}
|
|
|
|
TEST(Keybinds, UnsidedModifierMatchesEitherSide) {
|
|
auto result = makeBind({"SHIFT", "K"});
|
|
ASSERT_TRUE(result.has_value());
|
|
|
|
const auto RIGHT_SHIFT = resolvedKey("SHIFT_R", 62, HL_MODIFIER_SHIFT);
|
|
const auto K = resolvedKey("K", 45);
|
|
const std::array held = {RIGHT_SHIFT, K};
|
|
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = held,
|
|
.trigger = K,
|
|
.modifiersNow = HL_MODIFIER_SHIFT,
|
|
}),
|
|
BIND_MATCH_FULL);
|
|
}
|
|
|
|
TEST(Keybinds, UnsidedModifierAloneDoesNotPartiallyMatch) {
|
|
auto result = makeBind({"SUPER", "K"});
|
|
ASSERT_TRUE(result.has_value());
|
|
|
|
const auto SUPER = resolvedKey("SUPER_L", 133, HL_MODIFIER_META);
|
|
const std::array held = {SUPER};
|
|
EXPECT_EQ(result->matches({.heldKeys = held, .trigger = SUPER, .modifiersNow = HL_MODIFIER_META}), BIND_MATCH_NONE);
|
|
}
|
|
|
|
TEST(Keybinds, SingleKeyAllowsOtherHeldKeys) {
|
|
auto result = makeBind({"K"});
|
|
ASSERT_TRUE(result.has_value());
|
|
|
|
const auto A = resolvedKey("A", 38);
|
|
const auto K = resolvedKey("K", 45);
|
|
const std::array held = {A, K};
|
|
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = held,
|
|
.trigger = K,
|
|
}),
|
|
BIND_MATCH_FULL);
|
|
}
|
|
|
|
TEST(Keybinds, MultiKeyMatchingIsExactAndOrdered) {
|
|
auto result = makeBind({"A", "K"});
|
|
ASSERT_TRUE(result.has_value());
|
|
|
|
const auto A = resolvedKey("A", 38);
|
|
const auto K = resolvedKey("K", 45);
|
|
const auto X = resolvedKey("X", 53);
|
|
const std::array partial = {A};
|
|
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = partial,
|
|
.trigger = A,
|
|
}),
|
|
BIND_MATCH_PARTIAL);
|
|
|
|
const std::array full = {A, K};
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = full,
|
|
.trigger = K,
|
|
}),
|
|
BIND_MATCH_FULL);
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = full,
|
|
.trigger = A,
|
|
}),
|
|
BIND_MATCH_NONE);
|
|
|
|
const std::array extra = {A, K, X};
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = extra,
|
|
.trigger = K,
|
|
}),
|
|
BIND_MATCH_PARTIAL);
|
|
}
|
|
|
|
TEST(Keybinds, OneHeldKeyCannotSatisfyTwoPatterns) {
|
|
auto result = makeBind({"A", "code:38"});
|
|
ASSERT_TRUE(result.has_value());
|
|
|
|
const auto A = resolvedKey("A", 38);
|
|
const std::array held = {A};
|
|
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = held,
|
|
.trigger = A,
|
|
}),
|
|
BIND_MATCH_PARTIAL);
|
|
}
|
|
|
|
TEST(Keybinds, ReleaseBindCompletesOnRelease) {
|
|
auto result = makeBind({"K"}, BIND_FLAG_RELEASE);
|
|
ASSERT_TRUE(result.has_value());
|
|
|
|
const auto K = resolvedKey("K", 45);
|
|
const std::array held = {K};
|
|
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = held,
|
|
.trigger = K,
|
|
.pressed = true,
|
|
}),
|
|
BIND_MATCH_PARTIAL);
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = held,
|
|
.trigger = K,
|
|
.pressed = false,
|
|
}),
|
|
BIND_MATCH_FULL);
|
|
}
|
|
|
|
TEST(Keybinds, ReleaseBindUsesModifiersAtPress) {
|
|
auto result = makeBind({"SUPER", "K"}, BIND_FLAG_RELEASE);
|
|
ASSERT_TRUE(result.has_value());
|
|
|
|
const auto K = resolvedKey("K", 45);
|
|
const std::array held = {K};
|
|
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = held,
|
|
.trigger = K,
|
|
.modifiersNow = HL_MODIFIER_NONE,
|
|
.modifiersAtPress = HL_MODIFIER_META,
|
|
.pressed = false,
|
|
}),
|
|
BIND_MATCH_FULL);
|
|
}
|
|
|
|
TEST(Keybinds, ReleaseBindIgnoresModifiersPressedAfterTrigger) {
|
|
auto result = makeBind({"SUPER", "K"}, BIND_FLAG_RELEASE);
|
|
ASSERT_TRUE(result.has_value());
|
|
|
|
const auto SUPER = resolvedKey("SUPER_L", 133, HL_MODIFIER_META);
|
|
const auto K = resolvedKey("K", 45);
|
|
const std::array held = {K, SUPER};
|
|
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = held,
|
|
.trigger = K,
|
|
.modifiersNow = HL_MODIFIER_META,
|
|
.modifiersAtPress = HL_MODIFIER_NONE,
|
|
.pressed = false,
|
|
}),
|
|
BIND_MATCH_NONE);
|
|
}
|
|
|
|
TEST(Keybinds, ModifierReleaseBindIncludesTriggerModifier) {
|
|
auto result = makeBind({"SUPER", "SUPER_L"}, BIND_FLAG_RELEASE);
|
|
ASSERT_TRUE(result.has_value());
|
|
|
|
const auto SUPER = resolvedKey("SUPER_L", 133, HL_MODIFIER_META);
|
|
const std::array held = {SUPER};
|
|
|
|
EXPECT_EQ(result->matches({
|
|
.heldKeys = held,
|
|
.trigger = SUPER,
|
|
.modifiersNow = HL_MODIFIER_NONE,
|
|
.modifiersAtPress = HL_MODIFIER_NONE,
|
|
.pressed = false,
|
|
}),
|
|
BIND_MATCH_FULL);
|
|
}
|
|
|
|
TEST(Keybinds, CatchAllContextHonorsSubmapAndModifiers) {
|
|
auto result = CBind::make({"SUPER", "catchall"}, BIND_FLAG_CATCH_ALL, [] { return SBindResult{}; }, {.metadata = {.submap = "resize"}});
|
|
ASSERT_TRUE(result.has_value());
|
|
|
|
EXPECT_TRUE(result->matchesContext({.modifiersNow = HL_MODIFIER_META, .submap = "resize"}));
|
|
EXPECT_FALSE(result->matchesContext({.modifiersNow = HL_MODIFIER_META, .submap = "other"}));
|
|
EXPECT_FALSE(result->matchesContext({.submap = "resize"}));
|
|
}
|