[client] input: add platform-neutral keycodes

This commit is contained in:
Geoffrey McRae
2026-09-12 10:12:18 +10:00
parent 382f35e503
commit 7ea69f3d1c
26 changed files with 1412 additions and 1000 deletions

View File

@@ -49,6 +49,16 @@ if(LG_CLIENT_PLATFORM_LINUX)
set_tests_properties(lgmp-platform-tests PROPERTIES
TIMEOUT 10
)
add_executable(keycode-tests
keycode_test.c
)
add_test(NAME keycode-tests
COMMAND keycode-tests
)
set_tests_properties(keycode-tests PROPERTIES
TIMEOUT 10
)
endif()
if(LG_CLIENT_PLATFORM_WINDOWS)

View File

@@ -81,15 +81,15 @@ struct CursorState g_cursor;
struct AppParams g_params;
_Atomic(enum RunState) p_appState;
const char * linux_to_display[KEY_MAX] =
const char * lg_keycode_to_display[LG_KEY_MAX] =
{
[KEY_ESC] = "Esc",
[KEY_A] = "A",
[KEY_B] = "B",
[KEY_C] = "C",
[LG_KEY_ESC] = "Esc",
[LG_KEY_A] = "A",
[LG_KEY_B] = "B",
[LG_KEY_C] = "C",
};
const int linux_to_imgui[KEY_MAX] = { 0 };
const int lg_keycode_to_imgui[LG_KEY_MAX] = { 0 };
static bool getFullscreen(void)
{
@@ -136,7 +136,7 @@ static void init(void)
g_state.ds = &ds;
g_state.focused = true;
g_params.escapeKey = KEY_ESC;
g_params.escapeKey = LG_KEY_ESC;
atomic_store(&p_appState, APP_STATE_RUNNING);
CHECK(g_state.bindings);
@@ -256,12 +256,12 @@ static void checkKey(unsigned int index, bool down, int key)
static void testInvalid(void)
{
init();
CHECK(!app_registerKeybind(KEY_RESERVED, count, &t, "reserved"));
CHECK(!app_registerKeybind(KEY_MAX, count, &t, "past-end"));
CHECK(!app_registerKeybind(KEY_MAX - 1, count, &t, "unmapped"));
CHECK(!app_registerKeybind(LG_KEY_RESERVED, count, &t, "reserved"));
CHECK(!app_registerKeybind(LG_KEY_MAX, count, &t, "past-end"));
CHECK(!app_registerKeybind(LG_KEY_MAX - 1, count, &t, "unmapped"));
CHECK(ll_count(g_state.bindings) == 0);
KeybindHandle handle = app_registerKeybind(KEY_A, count, &t, "valid");
KeybindHandle handle = app_registerKeybind(LG_KEY_A, count, &t, "valid");
CHECK(handle);
CHECK(ll_count(g_state.bindings) == 1);
fini();
@@ -270,7 +270,7 @@ static void testInvalid(void)
static void testNullCallback(void)
{
init();
CHECK(!app_registerKeybind(KEY_A, NULL, NULL, "null callback"));
CHECK(!app_registerKeybind(LG_KEY_A, NULL, NULL, "null callback"));
CHECK(ll_count(g_state.bindings) == 0);
fini();
}
@@ -278,9 +278,9 @@ static void testNullCallback(void)
static void testDuplicate(void)
{
init();
KeybindHandle first = app_registerKeybind(KEY_A, count, &t, "first");
KeybindHandle first = app_registerKeybind(LG_KEY_A, count, &t, "first");
CHECK(first);
CHECK(!app_registerKeybind(KEY_A, count, &t, "duplicate"));
CHECK(!app_registerKeybind(LG_KEY_A, count, &t, "duplicate"));
CHECK(ll_count(g_state.bindings) == 1);
app_releaseKeybind(&first);
@@ -289,7 +289,7 @@ static void testDuplicate(void)
app_releaseKeybind(&first);
CHECK(!first);
first = app_registerKeybind(KEY_A, count, &t, "replacement");
first = app_registerKeybind(LG_KEY_A, count, &t, "replacement");
CHECK(first);
CHECK(ll_count(g_state.bindings) == 1);
fini();
@@ -298,23 +298,23 @@ static void testDuplicate(void)
static void testNormal(void)
{
init();
app_handleKeyPress(KEY_A);
app_handleKeyPress(KEY_A);
app_handleKeyRelease(KEY_A);
app_handleKeyPress(LG_KEY_A);
app_handleKeyPress(LG_KEY_A);
app_handleKeyRelease(LG_KEY_A);
CHECK(t.keyN == 3);
checkKey(0, true , KEY_A);
checkKey(1, true , KEY_A);
checkKey(2, false, KEY_A);
checkKey(0, true , LG_KEY_A);
checkKey(1, true , LG_KEY_A);
checkKey(2, false, LG_KEY_A);
t.exclusive = true;
app_handleKeyPress(KEY_B);
app_handleKeyRelease(KEY_B);
app_handleKeyPress(LG_KEY_B);
app_handleKeyRelease(LG_KEY_B);
CHECK(t.keyN == 3);
t.exclusive = false;
g_params.ignoreWindowsKeys = true;
app_handleKeyPress(KEY_LEFTMETA);
app_handleKeyRelease(KEY_LEFTMETA);
app_handleKeyPress(LG_KEY_LEFTMETA);
app_handleKeyRelease(LG_KEY_LEFTMETA);
CHECK(t.keyN == 3);
fini();
}
@@ -322,21 +322,21 @@ static void testNormal(void)
static void testDispatch(void)
{
init();
CHECK(app_registerKeybind(KEY_A, count, &t, "action"));
app_handleKeyPress(KEY_ESC);
CHECK(app_registerKeybind(LG_KEY_A, count, &t, "action"));
app_handleKeyPress(LG_KEY_ESC);
CHECK(g_state.escapeActive);
CHECK(g_state.escapeAction == -1);
CHECK(t.keyN == 0);
app_handleKeyPress(KEY_A);
app_handleKeyPress(KEY_A);
app_handleKeyPress(LG_KEY_A);
app_handleKeyPress(LG_KEY_A);
CHECK(t.cbN == 2);
CHECK(t.cbKey == KEY_A);
CHECK(g_state.escapeAction == KEY_A);
CHECK(t.cbKey == LG_KEY_A);
CHECK(g_state.escapeAction == LG_KEY_A);
CHECK(t.keyN == 0);
app_handleKeyRelease(KEY_A);
app_handleKeyRelease(KEY_ESC);
app_handleKeyRelease(LG_KEY_A);
app_handleKeyRelease(LG_KEY_ESC);
CHECK(!g_state.escapeActive);
CHECK(t.cbN == 2);
CHECK(t.keyN == 0);
@@ -346,16 +346,16 @@ static void testDispatch(void)
static void testReleaseAll(void)
{
init();
CHECK(app_registerKeybind(KEY_A, count, &t, "a"));
CHECK(app_registerKeybind(KEY_B, count, &t, "b"));
CHECK(app_registerKeybind(KEY_C, count, &t, "c"));
CHECK(app_registerKeybind(LG_KEY_A, count, &t, "a"));
CHECK(app_registerKeybind(LG_KEY_B, count, &t, "b"));
CHECK(app_registerKeybind(LG_KEY_C, count, &t, "c"));
CHECK(ll_count(g_state.bindings) == 3);
app_releaseAllKeybinds();
CHECK(ll_count(g_state.bindings) == 0);
app_releaseAllKeybinds();
CHECK(ll_count(g_state.bindings) == 0);
CHECK(app_registerKeybind(KEY_A, count, &t, "again"));
CHECK(app_registerKeybind(LG_KEY_A, count, &t, "again"));
CHECK(ll_count(g_state.bindings) == 1);
fini();
}
@@ -405,16 +405,16 @@ static void testFocus(void)
static void testReentrant(void)
{
init();
re.handle = app_registerKeybind(KEY_A, replace, &re, "old");
re.handle = app_registerKeybind(LG_KEY_A, replace, &re, "old");
CHECK(re.handle);
app_handleKeyPress(KEY_ESC);
app_handleKeyPress(KEY_A);
app_handleKeyPress(LG_KEY_ESC);
app_handleKeyPress(LG_KEY_A);
CHECK(re.oldN == 1);
CHECK(re.newN == 0);
CHECK(re.handle);
CHECK(ll_count(g_state.bindings) == 1);
app_handleKeyPress(KEY_A);
app_handleKeyPress(LG_KEY_A);
CHECK(re.oldN == 1);
CHECK(re.newN == 1);
CHECK(ll_count(g_state.bindings) == 1);

View File

@@ -59,10 +59,10 @@ struct AppState g_state;
struct CursorState g_cursor;
struct AppParams g_params;
const char * linux_to_str[KEY_MAX] =
const char * lg_keycode_to_name[LG_KEY_MAX] =
{
[KEY_A] = "KEY_A",
[KEY_RIGHTCTRL] = "KEY_RIGHTCTRL",
[LG_KEY_A] = "KEY_A",
[LG_KEY_RIGHTCTRL] = "KEY_RIGHTCTRL",
};
static const char * renAName(void)
@@ -352,7 +352,7 @@ static void testCfgValues(void)
struct Option * key = opt("input", "escapeKey");
CHECK(key->parser(key, "KEY_A"));
CHECK(key->value.x_int == KEY_A);
CHECK(key->value.x_int == LG_KEY_A);
char * keyName = key->toString(key);
CHECK(keyName);
CHECK(strstr(keyName, "KEY_A"));

View File

@@ -22,7 +22,7 @@
#include "common/debug.h"
#include <linux/input.h>
#include "input/keycodes.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
@@ -70,7 +70,7 @@ typedef struct FakeInput
RetiredListener retired[TEST_RETIRED_LISTENERS];
unsigned retiredCount;
FakeCalls calls;
bool remoteKeys[KEY_MAX];
bool remoteKeys[LG_KEY_MAX];
uint32_t remoteButtons;
int lastKeyDown;
int lastKeyUp;
@@ -167,7 +167,7 @@ static bool fakeKeyDown(void * opaque, int key)
FakeInput * input = opaque;
if (!fakeAlive(input))
return false;
if (key < 0 || key >= KEY_MAX)
if (key < 0 || key >= LG_KEY_MAX)
{
++input->calls.fault;
return false;
@@ -186,7 +186,7 @@ static bool fakeKeyUp(void * opaque, int key)
FakeInput * input = opaque;
if (!fakeAlive(input))
return false;
if (key < 0 || key >= KEY_MAX)
if (key < 0 || key >= LG_KEY_MAX)
{
++input->calls.fault;
return false;
@@ -410,9 +410,9 @@ static bool testHandoff(TestState * state)
{
CHECK(bindBoth(state));
CHECK(lgInput_keyDown(KEY_A));
CHECK(lgInput_keyDown(LG_KEY_A));
CHECK(lgInput_mousePress(1));
CHECK(state->transport.remoteKeys[KEY_A]);
CHECK(state->transport.remoteKeys[LG_KEY_A]);
CHECK(state->transport.remoteButtons & (UINT32_C(1) << 1));
const unsigned transportKeyUp = state->transport.calls.keyUp;
@@ -421,42 +421,42 @@ static bool testHandoff(TestState * state)
const unsigned fallbackReset = state->fallback.calls.reset;
CHECK(setAvailable(&state->transport, false));
CHECK(state->transport.calls.keyUp == transportKeyUp + 1);
CHECK(state->transport.lastKeyUp == KEY_A);
CHECK(state->transport.lastKeyUp == LG_KEY_A);
CHECK(state->transport.calls.release == transportRelease + 1);
CHECK(state->transport.lastRelease == 1);
CHECK(state->transport.calls.reset == transportReset + 1);
CHECK(state->fallback.calls.reset == fallbackReset + 1);
CHECK(!state->transport.remoteKeys[KEY_A]);
CHECK(!state->transport.remoteKeys[LG_KEY_A]);
CHECK(state->transport.remoteButtons == 0);
const unsigned fallbackKeyUp = state->fallback.calls.keyUp;
const unsigned fallbackRelease = state->fallback.calls.release;
CHECK(lgInput_keyUp(KEY_A));
CHECK(lgInput_keyUp(LG_KEY_A));
CHECK(lgInput_mouseRelease(1));
CHECK(state->fallback.calls.keyUp == fallbackKeyUp);
CHECK(state->fallback.calls.release == fallbackRelease);
CHECK(lgInput_keyDown(KEY_B));
CHECK(lgInput_keyDown(LG_KEY_B));
CHECK(lgInput_mousePress(2));
CHECK(state->fallback.remoteKeys[KEY_B]);
CHECK(state->fallback.remoteKeys[LG_KEY_B]);
CHECK(setAvailable(&state->transport, true));
CHECK(state->fallback.calls.keyUp == fallbackKeyUp + 1);
CHECK(state->fallback.lastKeyUp == KEY_B);
CHECK(state->fallback.lastKeyUp == LG_KEY_B);
CHECK(state->fallback.calls.release == fallbackRelease + 1);
CHECK(state->fallback.lastRelease == 2);
CHECK(!state->fallback.remoteKeys[KEY_B]);
CHECK(!state->fallback.remoteKeys[LG_KEY_B]);
CHECK(state->fallback.remoteButtons == 0);
CHECK(lgInput_keyDown(KEY_C));
CHECK(lgInput_keyDown(LG_KEY_C));
CHECK(lgInput_mousePress(3));
const unsigned secondTransportKeyUp = state->transport.calls.keyUp;
const unsigned secondTransportRelease = state->transport.calls.release;
lgInput_useTransport(false);
CHECK(state->transport.calls.keyUp == secondTransportKeyUp + 1);
CHECK(state->transport.lastKeyUp == KEY_C);
CHECK(state->transport.lastKeyUp == LG_KEY_C);
CHECK(state->transport.calls.release == secondTransportRelease + 1);
CHECK(state->transport.lastRelease == 3);
CHECK(!state->transport.remoteKeys[KEY_C]);
CHECK(!state->transport.remoteKeys[LG_KEY_C]);
CHECK(state->transport.remoteButtons == 0);
return true;
}
@@ -492,7 +492,7 @@ static bool testStale(TestState * state)
static bool testDeadDrop(TestState * state)
{
CHECK(bindBoth(state));
CHECK(lgInput_keyDown(KEY_A));
CHECK(lgInput_keyDown(LG_KEY_A));
CHECK(lgInput_mousePress(1));
LG_InputStatusFn stale = state->transport.listener;
@@ -509,13 +509,13 @@ static bool testDeadDrop(TestState * state)
CHECK(state->transport.calls.reset == reset);
CHECK(state->transport.calls.listenerClear == listenerClear);
CHECK(state->transport.calls.dead == 0);
CHECK(state->transport.remoteKeys[KEY_A]);
CHECK(state->transport.remoteKeys[LG_KEY_A]);
CHECK(state->transport.remoteButtons & (UINT32_C(1) << 1));
CHECK(lgInput_available());
const unsigned fallbackKeyUp = state->fallback.calls.keyUp;
const unsigned fallbackRelease = state->fallback.calls.release;
CHECK(lgInput_keyUp(KEY_A));
CHECK(lgInput_keyUp(LG_KEY_A));
CHECK(lgInput_mouseRelease(1));
CHECK(state->fallback.calls.keyUp == fallbackKeyUp);
CHECK(state->fallback.calls.release == fallbackRelease);
@@ -541,23 +541,23 @@ static bool testRollback(TestState * state)
CHECK(lgInput_available());
state->transport.keyDownResult = false;
CHECK(!lgInput_keyDown(KEY_A));
CHECK(!lgInput_keyDown(LG_KEY_A));
CHECK(state->transport.calls.keyDown == 1);
state->transport.keyDownResult = true;
CHECK(lgInput_keyDown(KEY_A));
CHECK(lgInput_keyDown(LG_KEY_A));
CHECK(state->transport.calls.keyDown == 2);
CHECK(lgInput_keyDown(KEY_A));
CHECK(lgInput_keyDown(LG_KEY_A));
CHECK(state->transport.calls.keyDown == 2);
state->transport.keyUpResult = false;
CHECK(!lgInput_keyUp(KEY_A));
CHECK(!lgInput_keyUp(LG_KEY_A));
CHECK(state->transport.calls.keyUp == 1);
CHECK(state->transport.remoteKeys[KEY_A]);
CHECK(state->transport.remoteKeys[LG_KEY_A]);
state->transport.keyUpResult = true;
CHECK(lgInput_keyUp(KEY_A));
CHECK(lgInput_keyUp(LG_KEY_A));
CHECK(state->transport.calls.keyUp == 2);
CHECK(!state->transport.remoteKeys[KEY_A]);
CHECK(lgInput_keyUp(KEY_A));
CHECK(!state->transport.remoteKeys[LG_KEY_A]);
CHECK(lgInput_keyUp(LG_KEY_A));
CHECK(state->transport.calls.keyUp == 2);
state->transport.pressResult = false;
@@ -588,9 +588,9 @@ static bool testDuplicate(TestState * state)
CHECK(lgInput_available());
CHECK(!lgInput_keyDown(-1));
CHECK(!lgInput_keyDown(KEY_MAX));
CHECK(!lgInput_keyDown(LG_KEY_MAX));
CHECK(!lgInput_keyUp(-1));
CHECK(!lgInput_keyUp(KEY_MAX));
CHECK(!lgInput_keyUp(LG_KEY_MAX));
CHECK(!lgInput_mousePress(0));
CHECK(!lgInput_mousePress(32));
CHECK(!lgInput_mouseRelease(0));
@@ -600,11 +600,11 @@ static bool testDuplicate(TestState * state)
CHECK(state->transport.calls.press == 0);
CHECK(state->transport.calls.release == 0);
CHECK(lgInput_keyDown(KEY_A));
CHECK(lgInput_keyDown(KEY_A));
CHECK(lgInput_keyDown(LG_KEY_A));
CHECK(lgInput_keyDown(LG_KEY_A));
CHECK(state->transport.calls.keyDown == 1);
CHECK(lgInput_keyUp(KEY_A));
CHECK(lgInput_keyUp(KEY_A));
CHECK(lgInput_keyUp(LG_KEY_A));
CHECK(lgInput_keyUp(LG_KEY_A));
CHECK(state->transport.calls.keyUp == 1);
CHECK(lgInput_mousePress(1));
@@ -614,13 +614,13 @@ static bool testDuplicate(TestState * state)
CHECK(lgInput_mouseRelease(1));
CHECK(state->transport.calls.release == 1);
CHECK(lgInput_keyDown(KEY_B));
CHECK(lgInput_keyDown(KEY_C));
CHECK(lgInput_keyDown(LG_KEY_B));
CHECK(lgInput_keyDown(LG_KEY_C));
const unsigned keyUp = state->transport.calls.keyUp;
lgInput_releaseKeys();
CHECK(state->transport.calls.keyUp == keyUp + 2);
CHECK(!state->transport.remoteKeys[KEY_B]);
CHECK(!state->transport.remoteKeys[KEY_C]);
CHECK(!state->transport.remoteKeys[LG_KEY_B]);
CHECK(!state->transport.remoteKeys[LG_KEY_C]);
lgInput_releaseKeys();
CHECK(state->transport.calls.keyUp == keyUp + 2);
return true;

View File

@@ -93,9 +93,9 @@ void app_setState(enum RunState state)
static const int fKeys[] =
{
KEY_F1 , KEY_F2 , KEY_F3 , KEY_F4,
KEY_F5 , KEY_F6 , KEY_F7 , KEY_F8,
KEY_F9 , KEY_F10, KEY_F11, KEY_F12,
LG_KEY_F1 , LG_KEY_F2 , LG_KEY_F3 , LG_KEY_F4,
LG_KEY_F5 , LG_KEY_F6 , LG_KEY_F7 , LG_KEY_F8,
LG_KEY_F9 , LG_KEY_F10, LG_KEY_F11, LG_KEY_F12,
};
static void realign(void)
@@ -134,7 +134,7 @@ static void call(int sc)
KeybindHandle app_registerKeybind(int sc, KeybindFn callback, void * opaque,
const char * description)
{
CHECK(sc > KEY_RESERVED && sc < KEY_MAX);
CHECK(sc > LG_KEY_RESERVED && sc < LG_KEY_MAX);
CHECK(callback);
CHECK(description);
++t.tryN;
@@ -286,12 +286,12 @@ static void testCommon(void)
CHECK(t.tryN == 6);
CHECK(t.activeN == 6);
CHECK(t.collisionN == 0);
checkBind(0, KEY_F, "Full screen toggle");
checkBind(1, KEY_V, "Video stream toggle");
checkBind(2, KEY_R, "Rotate the output clockwise by 90° increments");
checkBind(3, KEY_Q, "Quit");
checkBind(4, KEY_O, "Toggle overlay");
checkBind(5, KEY_EQUAL,
checkBind(0, LG_KEY_F, "Full screen toggle");
checkBind(1, LG_KEY_V, "Video stream toggle");
checkBind(2, LG_KEY_R, "Rotate the output clockwise by 90° increments");
checkBind(3, LG_KEY_Q, "Quit");
checkBind(4, LG_KEY_O, "Toggle overlay");
checkBind(5, LG_KEY_EQUAL,
"Set guest resolution to match window size");
keybind_commonRegister();
@@ -303,28 +303,28 @@ static void testCommon(void)
static void testOS(void)
{
reset();
CHECK(app_registerKeybind(KEY_F1, nop, NULL, "external"));
CHECK(app_registerKeybind(LG_KEY_F1, nop, NULL, "external"));
t.isLinux = true;
keybind_inputRegister();
CHECK(t.tryN == 21);
CHECK(t.activeN == 20);
CHECK(t.collisionN == 1);
CHECK(find(KEY_I));
CHECK(find(KEY_LEFTMETA));
CHECK(find(KEY_RIGHTMETA));
CHECK(find(LG_KEY_I));
CHECK(find(LG_KEY_LEFTMETA));
CHECK(find(LG_KEY_RIGHTMETA));
for (unsigned int i = 0; i < ARRAY_LENGTH(fKeys); ++i)
CHECK(find(fKeys[i]));
struct Bind * fixed = find(KEY_I);
struct Bind * oldF2 = find(KEY_F2);
struct Bind * fixed = find(LG_KEY_I);
struct Bind * oldF2 = find(LG_KEY_F2);
const unsigned int op = t.opN;
keybind_inputRegister();
CHECK(t.activeN == 20);
CHECK(t.releaseN == 11);
CHECK(t.collisionN == 2);
CHECK(find(KEY_I) == fixed);
CHECK(find(KEY_F2) != oldF2);
CHECK(find(LG_KEY_I) == fixed);
CHECK(find(LG_KEY_F2) != oldF2);
CHECK(!oldF2->active);
CHECK(t.opN == op + 22);
for (unsigned int i = 0; i < 11; ++i)
@@ -337,8 +337,8 @@ static void testOS(void)
keybind_inputRegister();
CHECK(t.activeN == 9);
CHECK(t.releaseN == 22);
CHECK(find(KEY_I) == fixed);
CHECK(strcmp(find(KEY_F1)->handle.description, "external") == 0);
CHECK(find(LG_KEY_I) == fixed);
CHECK(strcmp(find(LG_KEY_F1)->handle.description, "external") == 0);
for (unsigned int i = 1; i < ARRAY_LENGTH(fKeys); ++i)
CHECK(!find(fKeys[i]));
@@ -353,35 +353,35 @@ static void testOrder(void)
reset();
t.isLinux = true;
keybind_inputRegister();
call(KEY_F5);
call(LG_KEY_F5);
CHECK(t.keyN == 6);
checkKey(0, true , KEY_LEFTCTRL);
checkKey(1, true , KEY_LEFTALT );
checkKey(2, true , KEY_F5 );
checkKey(3, false, KEY_F5 );
checkKey(4, false, KEY_LEFTALT );
checkKey(5, false, KEY_LEFTCTRL);
checkKey(0, true , LG_KEY_LEFTCTRL);
checkKey(1, true , LG_KEY_LEFTALT );
checkKey(2, true , LG_KEY_F5 );
checkKey(3, false, LG_KEY_F5 );
checkKey(4, false, LG_KEY_LEFTALT );
checkKey(5, false, LG_KEY_LEFTCTRL);
}
static void testRepeat(void)
{
reset();
keybind_inputRegister();
call(KEY_LEFTMETA);
call(KEY_LEFTMETA);
call(KEY_UP);
call(KEY_UP);
call(LG_KEY_LEFTMETA);
call(LG_KEY_LEFTMETA);
call(LG_KEY_UP);
call(LG_KEY_UP);
CHECK(t.keyN == 8);
checkKey(0, true , KEY_LEFTMETA);
checkKey(1, false, KEY_LEFTMETA);
checkKey(2, true , KEY_LEFTMETA);
checkKey(3, false, KEY_LEFTMETA);
checkKey(4, true , KEY_VOLUMEUP);
checkKey(5, false, KEY_VOLUMEUP);
checkKey(6, true , KEY_VOLUMEUP);
checkKey(7, false, KEY_VOLUMEUP);
checkKey(0, true , LG_KEY_LEFTMETA);
checkKey(1, false, LG_KEY_LEFTMETA);
checkKey(2, true , LG_KEY_LEFTMETA);
checkKey(3, false, LG_KEY_LEFTMETA);
checkKey(4, true , LG_KEY_VOLUMEUP);
checkKey(5, false, LG_KEY_VOLUMEUP);
checkKey(6, true , LG_KEY_VOLUMEUP);
checkKey(7, false, LG_KEY_VOLUMEUP);
}
static void testActions(void)
@@ -390,66 +390,66 @@ static void testActions(void)
keybind_commonRegister();
keybind_inputRegister();
call(KEY_F);
call(LG_KEY_F);
CHECK(t.fullscreen);
call(KEY_F);
call(LG_KEY_F);
CHECK(!t.fullscreen);
call(KEY_V);
call(LG_KEY_V);
CHECK(g_state.stopVideo);
call(KEY_V);
call(LG_KEY_V);
CHECK(!g_state.stopVideo);
CHECK(t.videoN == 2);
g_params.winRotate = LG_ROTATE_MAX - 1;
call(KEY_R);
call(LG_KEY_R);
CHECK(g_params.winRotate == 0);
call(KEY_R);
call(LG_KEY_R);
CHECK(g_params.winRotate == 1);
CHECK(t.posN == 2);
call(KEY_O);
call(LG_KEY_O);
CHECK(g_state.overlayInput);
call(KEY_O);
call(LG_KEY_O);
CHECK(!g_state.overlayInput);
CHECK(t.overlayN == 2);
g_state.ignoreInput = false;
call(KEY_I);
call(LG_KEY_I);
CHECK(g_state.ignoreInput);
CHECK(t.cursorN == 1);
CHECK(!t.cursorInView);
CHECK(strcmp(t.alert, "Input Disabled") == 0);
call(KEY_I);
call(LG_KEY_I);
CHECK(!g_state.ignoreInput);
CHECK(t.realignN == 1);
CHECK(strcmp(t.alert, "Input Enabled") == 0);
g_cursor.sens = 8;
call(KEY_INSERT);
call(KEY_INSERT);
call(LG_KEY_INSERT);
call(LG_KEY_INSERT);
CHECK(g_cursor.sens == 9);
CHECK(strcmp(t.alert, "Sensitivity: +9") == 0);
g_cursor.sens = -8;
call(KEY_DELETE);
call(KEY_DELETE);
call(LG_KEY_DELETE);
call(LG_KEY_DELETE);
CHECK(g_cursor.sens == -9);
CHECK(strcmp(t.alert, "Sensitivity: -9") == 0);
g_state.windowW = 1920;
g_state.windowH = 1080;
call(KEY_EQUAL);
call(LG_KEY_EQUAL);
CHECK(t.msgN == 0);
CHECK(strcmp(t.alert,
"The guest doesn't support this feature") == 0);
g_state.transportFeatures = LG_TRANSPORT_FEATURE_WINDOW_SIZE;
call(KEY_EQUAL);
call(LG_KEY_EQUAL);
CHECK(t.msgN == 1);
CHECK(t.msg.type == LG_MSG_WINDOWSIZE);
CHECK(t.msg.windowSize.width == 1920);
CHECK(t.msg.windowSize.height == 1080);
call(KEY_Q);
call(LG_KEY_Q);
CHECK(app_getState() == APP_STATE_SHUTDOWN);
}

196
client/tests/keycode_test.c Normal file
View File

@@ -0,0 +1,196 @@
/**
* Looking Glass
* Copyright © 2017-2026 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "input/keycodes.h"
#include "test.h"
#include <linux/input-event-codes.h>
#define CHECK_KEY(name) CHECK((int)LG_KEY_##name == KEY_##name)
int main(void)
{
CHECK_KEY(RESERVED);
CHECK_KEY(ESC);
CHECK_KEY(1);
CHECK_KEY(2);
CHECK_KEY(3);
CHECK_KEY(4);
CHECK_KEY(5);
CHECK_KEY(6);
CHECK_KEY(7);
CHECK_KEY(8);
CHECK_KEY(9);
CHECK_KEY(0);
CHECK_KEY(MINUS);
CHECK_KEY(EQUAL);
CHECK_KEY(BACKSPACE);
CHECK_KEY(TAB);
CHECK_KEY(Q);
CHECK_KEY(W);
CHECK_KEY(E);
CHECK_KEY(R);
CHECK_KEY(T);
CHECK_KEY(Y);
CHECK_KEY(U);
CHECK_KEY(I);
CHECK_KEY(O);
CHECK_KEY(P);
CHECK_KEY(LEFTBRACE);
CHECK_KEY(RIGHTBRACE);
CHECK_KEY(ENTER);
CHECK_KEY(LEFTCTRL);
CHECK_KEY(A);
CHECK_KEY(S);
CHECK_KEY(D);
CHECK_KEY(F);
CHECK_KEY(G);
CHECK_KEY(H);
CHECK_KEY(J);
CHECK_KEY(K);
CHECK_KEY(L);
CHECK_KEY(SEMICOLON);
CHECK_KEY(APOSTROPHE);
CHECK_KEY(GRAVE);
CHECK_KEY(LEFTSHIFT);
CHECK_KEY(BACKSLASH);
CHECK_KEY(Z);
CHECK_KEY(X);
CHECK_KEY(C);
CHECK_KEY(V);
CHECK_KEY(B);
CHECK_KEY(N);
CHECK_KEY(M);
CHECK_KEY(COMMA);
CHECK_KEY(DOT);
CHECK_KEY(SLASH);
CHECK_KEY(RIGHTSHIFT);
CHECK_KEY(KPASTERISK);
CHECK_KEY(LEFTALT);
CHECK_KEY(SPACE);
CHECK_KEY(CAPSLOCK);
CHECK_KEY(F1);
CHECK_KEY(F2);
CHECK_KEY(F3);
CHECK_KEY(F4);
CHECK_KEY(F5);
CHECK_KEY(F6);
CHECK_KEY(F7);
CHECK_KEY(F8);
CHECK_KEY(F9);
CHECK_KEY(F10);
CHECK_KEY(NUMLOCK);
CHECK_KEY(SCROLLLOCK);
CHECK_KEY(KP7);
CHECK_KEY(KP8);
CHECK_KEY(KP9);
CHECK_KEY(KPMINUS);
CHECK_KEY(KP4);
CHECK_KEY(KP5);
CHECK_KEY(KP6);
CHECK_KEY(KPPLUS);
CHECK_KEY(KP1);
CHECK_KEY(KP2);
CHECK_KEY(KP3);
CHECK_KEY(KP0);
CHECK_KEY(KPDOT);
CHECK_KEY(ZENKAKUHANKAKU);
CHECK_KEY(102ND);
CHECK_KEY(F11);
CHECK_KEY(F12);
CHECK_KEY(RO);
CHECK_KEY(KATAKANA);
CHECK_KEY(HIRAGANA);
CHECK_KEY(HENKAN);
CHECK_KEY(KATAKANAHIRAGANA);
CHECK_KEY(MUHENKAN);
CHECK_KEY(KPJPCOMMA);
CHECK_KEY(KPENTER);
CHECK_KEY(RIGHTCTRL);
CHECK_KEY(KPSLASH);
CHECK_KEY(SYSRQ);
CHECK_KEY(RIGHTALT);
CHECK_KEY(HOME);
CHECK_KEY(UP);
CHECK_KEY(PAGEUP);
CHECK_KEY(LEFT);
CHECK_KEY(RIGHT);
CHECK_KEY(END);
CHECK_KEY(DOWN);
CHECK_KEY(PAGEDOWN);
CHECK_KEY(INSERT);
CHECK_KEY(DELETE);
CHECK_KEY(MUTE);
CHECK_KEY(VOLUMEDOWN);
CHECK_KEY(VOLUMEUP);
CHECK_KEY(POWER);
CHECK_KEY(KPEQUAL);
CHECK_KEY(PAUSE);
CHECK_KEY(KPCOMMA);
CHECK_KEY(HANGEUL);
CHECK_KEY(HANJA);
CHECK_KEY(YEN);
CHECK_KEY(LEFTMETA);
CHECK_KEY(RIGHTMETA);
CHECK_KEY(COMPOSE);
CHECK_KEY(STOP);
CHECK_KEY(AGAIN);
CHECK_KEY(UNDO);
CHECK_KEY(FRONT);
CHECK_KEY(COPY);
CHECK_KEY(OPEN);
CHECK_KEY(PASTE);
CHECK_KEY(FIND);
CHECK_KEY(CUT);
CHECK_KEY(HELP);
CHECK_KEY(MENU);
CHECK_KEY(CALC);
CHECK_KEY(SLEEP);
CHECK_KEY(WWW);
CHECK_KEY(SCREENLOCK);
CHECK_KEY(BACK);
CHECK_KEY(FORWARD);
CHECK_KEY(EJECTCD);
CHECK_KEY(NEXTSONG);
CHECK_KEY(PLAYPAUSE);
CHECK_KEY(PREVIOUSSONG);
CHECK_KEY(STOPCD);
CHECK_KEY(REFRESH);
CHECK_KEY(EDIT);
CHECK_KEY(SCROLLUP);
CHECK_KEY(SCROLLDOWN);
CHECK_KEY(KPLEFTPAREN);
CHECK_KEY(KPRIGHTPAREN);
CHECK_KEY(F13);
CHECK_KEY(F14);
CHECK_KEY(F15);
CHECK_KEY(F16);
CHECK_KEY(F17);
CHECK_KEY(F18);
CHECK_KEY(F19);
CHECK_KEY(F20);
CHECK_KEY(F21);
CHECK_KEY(F22);
CHECK_KEY(F23);
CHECK_KEY(F24);
CHECK_KEY(PRINT);
CHECK_KEY(MAX);
return 0;
}

View File

@@ -28,7 +28,7 @@
#include <lgmp/host.h>
#include <lgmp/stream.h>
#include <linux/input.h>
#include "input/keycodes.h"
#include <pthread.h>
#include <stdatomic.h>
#include <stdint.h>
@@ -359,7 +359,7 @@ static bool testClaim(TestState * state)
CHECK(postAvailable(state, 10));
CHECK(state->ops->supports(state->input,
LG_INPUT_SUPPORT_MOUSE_ABSOLUTE));
CHECK(state->ops->keyDown(state->input, KEY_A));
CHECK(state->ops->keyDown(state->input, LG_KEY_A));
KVMFRInputMessage claim;
KVMFRInputMessage keyboard;
@@ -371,7 +371,7 @@ static bool testClaim(TestState * state)
CHECK(keyboardHas(&keyboard, 4));
CHECK(postOwner(state, 10, state->clientID, claim.generation));
CHECK(state->ops->keyUp(state->input, KEY_A));
CHECK(state->ops->keyUp(state->input, LG_KEY_A));
CHECK(expectType(state, KVMFR_INPUT_MESSAGE_KEYBOARD, &keyboard));
CHECK(keyboard.generation == claim.generation);
CHECK(keyboard.sequence == 3);
@@ -389,7 +389,7 @@ static bool testBlocked(TestState * state)
CHECK(postStatus(state, 20, otherClient, 77));
CHECK(waitStatus(state, 2, true, 20));
CHECK(state->ops->keyDown(state->input, KEY_A));
CHECK(state->ops->keyDown(state->input, LG_KEY_A));
CHECK(state->ops->mousePress(state->input, 1));
CHECK(expectNoInput(state));
@@ -413,7 +413,7 @@ static bool testBlocked(TestState * state)
static bool testRestart(TestState * state)
{
CHECK(postAvailable(state, 30));
CHECK(state->ops->keyDown(state->input, KEY_A));
CHECK(state->ops->keyDown(state->input, LG_KEY_A));
CHECK(state->ops->mousePress(state->input, 1));
KVMFRInputMessage oldClaim;
@@ -504,7 +504,7 @@ static bool testPressure(TestState * state)
static bool testIdle(TestState * state)
{
CHECK(postAvailable(state, 50));
CHECK(state->ops->keyDown(state->input, KEY_A));
CHECK(state->ops->keyDown(state->input, LG_KEY_A));
KVMFRInputMessage claim;
KVMFRInputMessage message;
@@ -517,7 +517,7 @@ static bool testIdle(TestState * state)
CHECK(message.generation == claim.generation);
CHECK(message.sequence > 2);
CHECK(state->ops->keyUp(state->input, KEY_A));
CHECK(state->ops->keyUp(state->input, LG_KEY_A));
CHECK(readUntilType(state, KVMFR_INPUT_MESSAGE_KEYBOARD, 8,
&message, &skipped));
CHECK(keyboardEmpty(&message));