141 lines
3.9 KiB
C++
141 lines
3.9 KiB
C++
#include "test_harness.h"
|
|
#include "../src/keybind_manager.h"
|
|
|
|
// Build a SDL_KEYDOWN event for the given key + modifier set.
|
|
static SDL_Event keyDownEvent(SDL_Keycode key, SDL_Keymod mod)
|
|
{
|
|
SDL_Event ev{};
|
|
ev.type = SDL_EVENT_KEY_DOWN;
|
|
ev.key.key = key;
|
|
ev.key.mod = mod;
|
|
return ev;
|
|
}
|
|
|
|
TEST(bare_bind_fires_without_modifiers)
|
|
{
|
|
KeybindManager kb;
|
|
int calls = 0;
|
|
kb.bind(SDLK_RETURN, "enter", [&calls]() { calls++; });
|
|
|
|
ASSERT_TRUE(kb.handleEvent(keyDownEvent(SDLK_RETURN, SDL_KMOD_NONE)));
|
|
ASSERT_EQ(calls, 1);
|
|
}
|
|
|
|
TEST(bare_bind_ignores_modifiers)
|
|
{
|
|
KeybindManager kb;
|
|
int calls = 0;
|
|
kb.bind(SDLK_RETURN, "enter", [&calls]() { calls++; });
|
|
|
|
// A plain bind fires even while a modifier is held.
|
|
ASSERT_TRUE(kb.handleEvent(keyDownEvent(SDLK_RETURN, SDL_KMOD_CTRL)));
|
|
ASSERT_EQ(calls, 1);
|
|
}
|
|
|
|
TEST(combo_requires_modifier)
|
|
{
|
|
KeybindManager kb;
|
|
int calls = 0;
|
|
kb.bind(SDLK_D, SDL_KMOD_CTRL, "clear", [&calls]() { calls++; });
|
|
|
|
// Without Ctrl held the combo must not fire.
|
|
ASSERT_FALSE(kb.handleEvent(keyDownEvent(SDLK_D, SDL_KMOD_NONE)));
|
|
ASSERT_EQ(calls, 0);
|
|
|
|
// With Ctrl held it fires.
|
|
ASSERT_TRUE(kb.handleEvent(keyDownEvent(SDLK_D, SDL_KMOD_CTRL)));
|
|
ASSERT_EQ(calls, 1);
|
|
}
|
|
|
|
// Regression: a physical press only sets ONE side of a paired modifier
|
|
// (e.g. SDL_KMOD_LCTRL), never the combined SDL_KMOD_CTRL mask. The raw
|
|
// bitwise check (pressed & required) == required therefore never matched and
|
|
// Ctrl+D silently did nothing on real hardware.
|
|
TEST(combo_fires_with_single_ctrl_key)
|
|
{
|
|
KeybindManager kb;
|
|
int calls = 0;
|
|
kb.bind(SDLK_D, SDL_KMOD_CTRL, "clear", [&calls]() { calls++; });
|
|
|
|
ASSERT_TRUE(kb.handleEvent(keyDownEvent(SDLK_D, SDL_KMOD_LCTRL)));
|
|
ASSERT_EQ(calls, 1);
|
|
|
|
ASSERT_TRUE(kb.handleEvent(keyDownEvent(SDLK_D, SDL_KMOD_RCTRL)));
|
|
ASSERT_EQ(calls, 2);
|
|
}
|
|
|
|
TEST(combo_tolerates_extra_modifiers)
|
|
{
|
|
KeybindManager kb;
|
|
int calls = 0;
|
|
kb.bind(SDLK_D, SDL_KMOD_CTRL, "clear", [&calls]() { calls++; });
|
|
|
|
// CapsLock being stuck on should not block the combo.
|
|
const SDL_Keymod extra = static_cast<SDL_Keymod>(SDL_KMOD_CTRL | SDL_KMOD_CAPS);
|
|
ASSERT_TRUE(kb.handleEvent(keyDownEvent(SDLK_D, extra)));
|
|
ASSERT_EQ(calls, 1);
|
|
}
|
|
|
|
TEST(combo_partial_modifiers_do_not_fire)
|
|
{
|
|
KeybindManager kb;
|
|
int calls = 0;
|
|
kb.bind(SDLK_D, static_cast<SDL_Keymod>(SDL_KMOD_CTRL | SDL_KMOD_SHIFT), "clear", [&calls]() { calls++; });
|
|
|
|
// Only Ctrl held, Shift missing: must not fire.
|
|
ASSERT_FALSE(kb.handleEvent(keyDownEvent(SDLK_D, SDL_KMOD_CTRL)));
|
|
ASSERT_EQ(calls, 0);
|
|
|
|
// Both held: fires.
|
|
ASSERT_TRUE(kb.handleEvent(keyDownEvent(SDLK_D, static_cast<SDL_Keymod>(SDL_KMOD_CTRL | SDL_KMOD_SHIFT))));
|
|
ASSERT_EQ(calls, 1);
|
|
}
|
|
|
|
TEST(unbind_removes_binding)
|
|
{
|
|
KeybindManager kb;
|
|
int calls = 0;
|
|
kb.bind(SDLK_D, SDL_KMOD_CTRL, "clear", [&calls]() { calls++; });
|
|
kb.unbind(SDLK_D);
|
|
|
|
ASSERT_FALSE(kb.isBound(SDLK_D));
|
|
ASSERT_FALSE(kb.handleEvent(keyDownEvent(SDLK_D, SDL_KMOD_CTRL)));
|
|
ASSERT_EQ(calls, 0);
|
|
}
|
|
|
|
TEST(unbind_all_removes_bindings)
|
|
{
|
|
KeybindManager kb;
|
|
int calls = 0;
|
|
kb.bind(SDLK_D, SDL_KMOD_CTRL, "clear", [&calls]() { calls++; });
|
|
kb.bind(SDLK_UP, "up", [&calls]() { calls++; });
|
|
kb.unbindAll();
|
|
|
|
ASSERT_FALSE(kb.isBound(SDLK_D));
|
|
ASSERT_FALSE(kb.isBound(SDLK_UP));
|
|
ASSERT_FALSE(kb.handleEvent(keyDownEvent(SDLK_D, SDL_KMOD_CTRL)));
|
|
ASSERT_EQ(calls, 0);
|
|
}
|
|
|
|
TEST(is_bound_reflects_bindings)
|
|
{
|
|
KeybindManager kb;
|
|
kb.bind(SDLK_D, SDL_KMOD_CTRL, "clear", []() {});
|
|
ASSERT_TRUE(kb.isBound(SDLK_D));
|
|
ASSERT_FALSE(kb.isBound(SDLK_UP));
|
|
}
|
|
|
|
TEST(non_keydown_event_is_ignored)
|
|
{
|
|
KeybindManager kb;
|
|
int calls = 0;
|
|
kb.bind(SDLK_D, SDL_KMOD_CTRL, "clear", [&calls]() { calls++; });
|
|
|
|
SDL_Event ev{};
|
|
ev.type = SDL_EVENT_KEY_UP;
|
|
ev.key.key = SDLK_D;
|
|
ev.key.mod = SDL_KMOD_CTRL;
|
|
ASSERT_FALSE(kb.handleEvent(ev));
|
|
ASSERT_EQ(calls, 0);
|
|
}
|