Public Access
Keys: which ones are held, not only which were pressed
Apps heard a key once, when it went down. A Game that moves something for as long as a key is held (issue #101) asks the key mapper instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0162FokPdvY2KsS4NBfwyWPk
This commit is contained in:
@@ -54,6 +54,24 @@ KeyEvent keyEvent(Key key, const RawKeys& keys) {
|
||||
|
||||
} // namespace
|
||||
|
||||
bool KeyMapper::heldChar(char c) const {
|
||||
return std::find(previous_.chars.begin(), previous_.chars.end(), c) != previous_.chars.end();
|
||||
}
|
||||
|
||||
bool KeyMapper::held(Key key) const {
|
||||
bool arrows = previous_.fn || !textEntry_;
|
||||
switch (key) {
|
||||
case Key::Up: return arrows && heldChar(';');
|
||||
case Key::Down: return arrows && heldChar('.');
|
||||
case Key::Left: return arrows && heldChar(',');
|
||||
case Key::Right: return arrows && heldChar('/');
|
||||
case Key::Select: return previous_.enter;
|
||||
case Key::Delete: return previous_.del;
|
||||
case Key::Tab: return previous_.tab;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<KeyEvent> KeyMapper::update(const RawKeys& keys) {
|
||||
std::vector<KeyEvent> out;
|
||||
|
||||
|
||||
@@ -33,6 +33,12 @@ class KeyMapper {
|
||||
// don't need Fn.
|
||||
void setTextEntry(bool active) { textEntry_ = active; }
|
||||
|
||||
// Is this key down right now, as of the last update()? Events only say when a key goes down:
|
||||
// a Game that moves something for as long as a key is held asks this (issue #101). The arrows
|
||||
// are ; . , / as for events: alone outside Text Entry, with Fn anywhere.
|
||||
bool held(Key key) const;
|
||||
bool heldChar(char c) const; // a character key, as it types
|
||||
|
||||
// 0 when idle, '*' when opt was pressed, or the accent character waiting for its letter.
|
||||
char pendingCompose() const { return compose_; }
|
||||
|
||||
|
||||
@@ -301,6 +301,56 @@ void test_question_mark_is_help_only_when_not_typing() {
|
||||
TEST_ASSERT_EQUAL('?', ev[0].ch);
|
||||
}
|
||||
|
||||
void test_held_keys_are_known_between_events() {
|
||||
KeyMapper m;
|
||||
m.setTextEntry(false);
|
||||
TEST_ASSERT_FALSE(m.held(Key::Up));
|
||||
RawKeys keys;
|
||||
keys.chars = {';'};
|
||||
TEST_ASSERT_EQUAL(1, m.update(keys).size()); // the press, once
|
||||
TEST_ASSERT_TRUE(m.held(Key::Up));
|
||||
TEST_ASSERT_FALSE(m.held(Key::Down));
|
||||
TEST_ASSERT_EQUAL(0, m.update(keys).size()); // still held: no new event, still held
|
||||
TEST_ASSERT_TRUE(m.held(Key::Up));
|
||||
keys.chars = {';', '/'}; // a second key with it
|
||||
m.update(keys);
|
||||
TEST_ASSERT_TRUE(m.held(Key::Up));
|
||||
TEST_ASSERT_TRUE(m.held(Key::Right));
|
||||
keys.chars = {'/'};
|
||||
m.update(keys);
|
||||
TEST_ASSERT_FALSE(m.held(Key::Up));
|
||||
TEST_ASSERT_TRUE(m.held(Key::Right));
|
||||
m.update(RawKeys());
|
||||
TEST_ASSERT_FALSE(m.held(Key::Right));
|
||||
}
|
||||
|
||||
void test_held_arrows_need_fn_while_typing() {
|
||||
KeyMapper m;
|
||||
m.setTextEntry(true);
|
||||
RawKeys keys;
|
||||
keys.chars = {'.'};
|
||||
m.update(keys);
|
||||
TEST_ASSERT_FALSE(m.held(Key::Down)); // it types a full stop
|
||||
TEST_ASSERT_TRUE(m.heldChar('.'));
|
||||
keys.fn = true;
|
||||
m.update(keys);
|
||||
TEST_ASSERT_TRUE(m.held(Key::Down));
|
||||
}
|
||||
|
||||
void test_held_characters_and_enter() {
|
||||
KeyMapper m;
|
||||
m.setTextEntry(false);
|
||||
RawKeys keys;
|
||||
keys.chars = {'z', ' '};
|
||||
keys.enter = true;
|
||||
m.update(keys);
|
||||
TEST_ASSERT_TRUE(m.heldChar('z'));
|
||||
TEST_ASSERT_TRUE(m.heldChar(' '));
|
||||
TEST_ASSERT_FALSE(m.heldChar('x'));
|
||||
TEST_ASSERT_TRUE(m.held(Key::Select));
|
||||
TEST_ASSERT_FALSE(m.held(Key::Back)); // not asked for by anything: only what a Game steers with
|
||||
}
|
||||
|
||||
int main() {
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_plain_character);
|
||||
@@ -327,5 +377,8 @@ int main() {
|
||||
RUN_TEST(test_fn_p_is_a_screenshot_in_both_modes);
|
||||
RUN_TEST(test_plain_h_still_types);
|
||||
RUN_TEST(test_question_mark_is_help_only_when_not_typing);
|
||||
RUN_TEST(test_held_keys_are_known_between_events);
|
||||
RUN_TEST(test_held_arrows_need_fn_while_typing);
|
||||
RUN_TEST(test_held_characters_and_enter);
|
||||
return UNITY_END();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user