mirror of https://github.com/mgba-emu/mgba.git
Scripting: Clear down keys when the window is deactivated
This commit is contained in:
parent
f27ce8d82e
commit
e95bd06321
|
@ -249,6 +249,7 @@ mSCRIPT_DECLARE_STRUCT(mScriptGamepad);
|
||||||
void mScriptContextAttachInput(struct mScriptContext* context);
|
void mScriptContextAttachInput(struct mScriptContext* context);
|
||||||
|
|
||||||
void mScriptContextFireEvent(struct mScriptContext*, struct mScriptEvent*);
|
void mScriptContextFireEvent(struct mScriptContext*, struct mScriptEvent*);
|
||||||
|
void mScriptContextClearKeys(struct mScriptContext*);
|
||||||
|
|
||||||
int mScriptContextGamepadAttach(struct mScriptContext*, struct mScriptGamepad*);
|
int mScriptContextGamepadAttach(struct mScriptContext*, struct mScriptGamepad*);
|
||||||
bool mScriptContextGamepadDetach(struct mScriptContext*, int pad);
|
bool mScriptContextGamepadDetach(struct mScriptContext*, int pad);
|
||||||
|
|
|
@ -155,6 +155,10 @@ void ScriptingController::event(QObject* obj, QEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (event->type()) {
|
switch (event->type()) {
|
||||||
|
case QEvent::FocusOut:
|
||||||
|
case QEvent::WindowDeactivate:
|
||||||
|
mScriptContextClearKeys(&m_scriptContext);
|
||||||
|
return;
|
||||||
case QEvent::KeyPress:
|
case QEvent::KeyPress:
|
||||||
case QEvent::KeyRelease: {
|
case QEvent::KeyRelease: {
|
||||||
struct mScriptKeyEvent ev{mSCRIPT_EV_TYPE_KEY};
|
struct mScriptKeyEvent ev{mSCRIPT_EV_TYPE_KEY};
|
||||||
|
|
|
@ -427,6 +427,44 @@ void mScriptContextFireEvent(struct mScriptContext* context, struct mScriptEvent
|
||||||
mScriptListDeinit(&args);
|
mScriptListDeinit(&args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mScriptContextClearKeys(struct mScriptContext* context) {
|
||||||
|
struct mScriptValue* input = mScriptContextGetGlobal(context, "input");
|
||||||
|
if (!input) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct mScriptInputContext* inputContext = input->value.opaque;
|
||||||
|
size_t keyCount = TableSize(&inputContext->activeKeys);
|
||||||
|
uint32_t* keys = calloc(keyCount, sizeof(uint32_t));
|
||||||
|
struct TableIterator iter;
|
||||||
|
size_t i = 0;
|
||||||
|
if (!TableIteratorStart(&inputContext->activeKeys, &iter)) {
|
||||||
|
free(keys);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
keys[i] = TableIteratorGetKey(&inputContext->activeKeys, &iter);
|
||||||
|
++i;
|
||||||
|
} while (TableIteratorNext(&inputContext->activeKeys, &iter));
|
||||||
|
|
||||||
|
struct mScriptKeyEvent event = {
|
||||||
|
.d = {
|
||||||
|
.type = mSCRIPT_EV_TYPE_KEY
|
||||||
|
},
|
||||||
|
.state = mSCRIPT_INPUT_STATE_UP,
|
||||||
|
.modifiers = 0
|
||||||
|
};
|
||||||
|
for (i = 0; i < keyCount; ++i) {
|
||||||
|
event.key = keys[i];
|
||||||
|
intptr_t value = (intptr_t) TableLookup(&inputContext->activeKeys, event.key);
|
||||||
|
if (value > 1) {
|
||||||
|
TableInsert(&inputContext->activeKeys, event.key, (void*) 1);
|
||||||
|
}
|
||||||
|
mScriptContextFireEvent(context, &event.d);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(keys);
|
||||||
|
}
|
||||||
|
|
||||||
int mScriptContextGamepadAttach(struct mScriptContext* context, struct mScriptGamepad* pad) {
|
int mScriptContextGamepadAttach(struct mScriptContext* context, struct mScriptGamepad* pad) {
|
||||||
struct mScriptValue* input = mScriptContextGetGlobal(context, "input");
|
struct mScriptValue* input = mScriptContextGetGlobal(context, "input");
|
||||||
if (!input) {
|
if (!input) {
|
||||||
|
|
|
@ -131,6 +131,50 @@ M_TEST_DEFINE(activeKeys) {
|
||||||
mScriptContextDeinit(&context);
|
mScriptContextDeinit(&context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
M_TEST_DEFINE(clearKeys) {
|
||||||
|
SETUP_LUA;
|
||||||
|
|
||||||
|
TEST_PROGRAM("assert(not input:isKeyActive('a'))");
|
||||||
|
TEST_PROGRAM("assert(not input:isKeyActive('b'))");
|
||||||
|
TEST_PROGRAM("assert(#input:activeKeys() == 0)");
|
||||||
|
|
||||||
|
struct mScriptKeyEvent keyEvent = {
|
||||||
|
.d = { .type = mSCRIPT_EV_TYPE_KEY },
|
||||||
|
.state = mSCRIPT_INPUT_STATE_DOWN,
|
||||||
|
.key = 'a'
|
||||||
|
};
|
||||||
|
mScriptContextFireEvent(&context, &keyEvent.d);
|
||||||
|
// This changes it to STATE_HELD, but increments the down counter
|
||||||
|
mScriptContextFireEvent(&context, &keyEvent.d);
|
||||||
|
keyEvent.state = mSCRIPT_INPUT_STATE_DOWN;
|
||||||
|
keyEvent.key = 'b';
|
||||||
|
mScriptContextFireEvent(&context, &keyEvent.d);
|
||||||
|
|
||||||
|
TEST_PROGRAM("assert(input:isKeyActive('a'))");
|
||||||
|
TEST_PROGRAM("assert(input:isKeyActive('b'))");
|
||||||
|
TEST_PROGRAM("assert(#input:activeKeys() == 2)");
|
||||||
|
|
||||||
|
TEST_PROGRAM(
|
||||||
|
"up = {}\n"
|
||||||
|
"function cb(ev)\n"
|
||||||
|
" assert(ev.type == C.EV_TYPE.KEY)\n"
|
||||||
|
" assert(ev.state == C.INPUT_STATE.UP)\n"
|
||||||
|
" table.insert(up, ev.key)\n"
|
||||||
|
"end\n"
|
||||||
|
"id = callbacks:add('key', cb)\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
mScriptContextClearKeys(&context);
|
||||||
|
|
||||||
|
TEST_PROGRAM("assert(not input:isKeyActive('a'))");
|
||||||
|
TEST_PROGRAM("assert(not input:isKeyActive('b'))");
|
||||||
|
TEST_PROGRAM("assert(#input:activeKeys() == 0)");
|
||||||
|
TEST_PROGRAM("assert(#up == 2)");
|
||||||
|
|
||||||
|
mScriptContextDeinit(&context);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
M_TEST_DEFINE(gamepadExport) {
|
M_TEST_DEFINE(gamepadExport) {
|
||||||
SETUP_LUA;
|
SETUP_LUA;
|
||||||
|
|
||||||
|
@ -176,5 +220,6 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptInput,
|
||||||
cmocka_unit_test(seq),
|
cmocka_unit_test(seq),
|
||||||
cmocka_unit_test(fireKey),
|
cmocka_unit_test(fireKey),
|
||||||
cmocka_unit_test(activeKeys),
|
cmocka_unit_test(activeKeys),
|
||||||
|
cmocka_unit_test(clearKeys),
|
||||||
cmocka_unit_test(gamepadExport),
|
cmocka_unit_test(gamepadExport),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue