Use static maps to convert input events
This improves readability (hopefully). PR #2831 <https://github.com/Genymobile/scrcpy/pull/2831>
This commit is contained in:
parent
c96505200a
commit
0c0f62e4ab
5 changed files with 160 additions and 76 deletions
|
@ -28,6 +28,7 @@ src = [
|
||||||
'src/video_buffer.c',
|
'src/video_buffer.c',
|
||||||
'src/util/acksync.c',
|
'src/util/acksync.c',
|
||||||
'src/util/file.c',
|
'src/util/file.c',
|
||||||
|
'src/util/intmap.c',
|
||||||
'src/util/intr.c',
|
'src/util/intr.c',
|
||||||
'src/util/log.c',
|
'src/util/log.c',
|
||||||
'src/util/net.c',
|
'src/util/net.c',
|
||||||
|
|
|
@ -6,60 +6,115 @@
|
||||||
#include "android/input.h"
|
#include "android/input.h"
|
||||||
#include "control_msg.h"
|
#include "control_msg.h"
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
|
#include "util/intmap.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
|
||||||
/** Downcast key processor to sc_keyboard_inject */
|
/** Downcast key processor to sc_keyboard_inject */
|
||||||
#define DOWNCAST(KP) container_of(KP, struct sc_keyboard_inject, key_processor)
|
#define DOWNCAST(KP) container_of(KP, struct sc_keyboard_inject, key_processor)
|
||||||
|
|
||||||
#define MAP(FROM, TO) case FROM: *to = TO; return true
|
|
||||||
#define FAIL default: return false
|
|
||||||
static bool
|
static bool
|
||||||
convert_keycode_action(SDL_EventType from, enum android_keyevent_action *to) {
|
convert_keycode_action(SDL_EventType from, enum android_keyevent_action *to) {
|
||||||
switch (from) {
|
static const struct sc_intmap_entry actions[] = {
|
||||||
MAP(SDL_KEYDOWN, AKEY_EVENT_ACTION_DOWN);
|
{SDL_KEYDOWN, AKEY_EVENT_ACTION_DOWN},
|
||||||
MAP(SDL_KEYUP, AKEY_EVENT_ACTION_UP);
|
{SDL_KEYUP, AKEY_EVENT_ACTION_UP},
|
||||||
FAIL;
|
};
|
||||||
|
|
||||||
|
const struct sc_intmap_entry *entry = SC_INTMAP_FIND_ENTRY(actions, from);
|
||||||
|
if (entry) {
|
||||||
|
*to = entry->value;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod,
|
convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod,
|
||||||
bool prefer_text) {
|
bool prefer_text) {
|
||||||
switch (from) {
|
// Navigation keys and ENTER.
|
||||||
MAP(SDLK_RETURN, AKEYCODE_ENTER);
|
// Used in all modes.
|
||||||
MAP(SDLK_KP_ENTER, AKEYCODE_NUMPAD_ENTER);
|
static const struct sc_intmap_entry special_keys[] = {
|
||||||
MAP(SDLK_ESCAPE, AKEYCODE_ESCAPE);
|
{SDLK_RETURN, AKEYCODE_ENTER},
|
||||||
MAP(SDLK_BACKSPACE, AKEYCODE_DEL);
|
{SDLK_KP_ENTER, AKEYCODE_NUMPAD_ENTER},
|
||||||
MAP(SDLK_TAB, AKEYCODE_TAB);
|
{SDLK_ESCAPE, AKEYCODE_ESCAPE},
|
||||||
MAP(SDLK_PAGEUP, AKEYCODE_PAGE_UP);
|
{SDLK_BACKSPACE, AKEYCODE_DEL},
|
||||||
MAP(SDLK_DELETE, AKEYCODE_FORWARD_DEL);
|
{SDLK_TAB, AKEYCODE_TAB},
|
||||||
MAP(SDLK_HOME, AKEYCODE_MOVE_HOME);
|
{SDLK_PAGEUP, AKEYCODE_PAGE_UP},
|
||||||
MAP(SDLK_END, AKEYCODE_MOVE_END);
|
{SDLK_DELETE, AKEYCODE_FORWARD_DEL},
|
||||||
MAP(SDLK_PAGEDOWN, AKEYCODE_PAGE_DOWN);
|
{SDLK_HOME, AKEYCODE_MOVE_HOME},
|
||||||
MAP(SDLK_RIGHT, AKEYCODE_DPAD_RIGHT);
|
{SDLK_END, AKEYCODE_MOVE_END},
|
||||||
MAP(SDLK_LEFT, AKEYCODE_DPAD_LEFT);
|
{SDLK_PAGEDOWN, AKEYCODE_PAGE_DOWN},
|
||||||
MAP(SDLK_DOWN, AKEYCODE_DPAD_DOWN);
|
{SDLK_RIGHT, AKEYCODE_DPAD_RIGHT},
|
||||||
MAP(SDLK_UP, AKEYCODE_DPAD_UP);
|
{SDLK_LEFT, AKEYCODE_DPAD_LEFT},
|
||||||
MAP(SDLK_LCTRL, AKEYCODE_CTRL_LEFT);
|
{SDLK_DOWN, AKEYCODE_DPAD_DOWN},
|
||||||
MAP(SDLK_RCTRL, AKEYCODE_CTRL_RIGHT);
|
{SDLK_UP, AKEYCODE_DPAD_UP},
|
||||||
MAP(SDLK_LSHIFT, AKEYCODE_SHIFT_LEFT);
|
{SDLK_LCTRL, AKEYCODE_CTRL_LEFT},
|
||||||
MAP(SDLK_RSHIFT, AKEYCODE_SHIFT_RIGHT);
|
{SDLK_RCTRL, AKEYCODE_CTRL_RIGHT},
|
||||||
|
{SDLK_LSHIFT, AKEYCODE_SHIFT_LEFT},
|
||||||
|
{SDLK_RSHIFT, AKEYCODE_SHIFT_RIGHT},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Numpad navigation keys.
|
||||||
|
// Used in all modes, when NumLock and Shift are disabled.
|
||||||
|
static const struct sc_intmap_entry kp_nav_keys[] = {
|
||||||
|
{SDLK_KP_0, AKEYCODE_INSERT},
|
||||||
|
{SDLK_KP_1, AKEYCODE_MOVE_END},
|
||||||
|
{SDLK_KP_2, AKEYCODE_DPAD_DOWN},
|
||||||
|
{SDLK_KP_3, AKEYCODE_PAGE_DOWN},
|
||||||
|
{SDLK_KP_4, AKEYCODE_DPAD_LEFT},
|
||||||
|
{SDLK_KP_6, AKEYCODE_DPAD_RIGHT},
|
||||||
|
{SDLK_KP_7, AKEYCODE_MOVE_HOME},
|
||||||
|
{SDLK_KP_8, AKEYCODE_DPAD_UP},
|
||||||
|
{SDLK_KP_9, AKEYCODE_PAGE_UP},
|
||||||
|
{SDLK_KP_PERIOD, AKEYCODE_FORWARD_DEL},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Letters and space.
|
||||||
|
// Used in non-text mode.
|
||||||
|
static const struct sc_intmap_entry alphaspace_keys[] = {
|
||||||
|
{SDLK_a, AKEYCODE_A},
|
||||||
|
{SDLK_b, AKEYCODE_B},
|
||||||
|
{SDLK_c, AKEYCODE_C},
|
||||||
|
{SDLK_d, AKEYCODE_D},
|
||||||
|
{SDLK_e, AKEYCODE_E},
|
||||||
|
{SDLK_f, AKEYCODE_F},
|
||||||
|
{SDLK_g, AKEYCODE_G},
|
||||||
|
{SDLK_h, AKEYCODE_H},
|
||||||
|
{SDLK_i, AKEYCODE_I},
|
||||||
|
{SDLK_j, AKEYCODE_J},
|
||||||
|
{SDLK_k, AKEYCODE_K},
|
||||||
|
{SDLK_l, AKEYCODE_L},
|
||||||
|
{SDLK_m, AKEYCODE_M},
|
||||||
|
{SDLK_n, AKEYCODE_N},
|
||||||
|
{SDLK_o, AKEYCODE_O},
|
||||||
|
{SDLK_p, AKEYCODE_P},
|
||||||
|
{SDLK_q, AKEYCODE_Q},
|
||||||
|
{SDLK_r, AKEYCODE_R},
|
||||||
|
{SDLK_s, AKEYCODE_S},
|
||||||
|
{SDLK_t, AKEYCODE_T},
|
||||||
|
{SDLK_u, AKEYCODE_U},
|
||||||
|
{SDLK_v, AKEYCODE_V},
|
||||||
|
{SDLK_w, AKEYCODE_W},
|
||||||
|
{SDLK_x, AKEYCODE_X},
|
||||||
|
{SDLK_y, AKEYCODE_Y},
|
||||||
|
{SDLK_z, AKEYCODE_Z},
|
||||||
|
{SDLK_SPACE, AKEYCODE_SPACE},
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct sc_intmap_entry *entry =
|
||||||
|
SC_INTMAP_FIND_ENTRY(special_keys, from);
|
||||||
|
if (entry) {
|
||||||
|
*to = entry->value;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(mod & (KMOD_NUM | KMOD_SHIFT))) {
|
if (!(mod & (KMOD_NUM | KMOD_SHIFT))) {
|
||||||
// Handle Numpad events when Num Lock is disabled
|
// Handle Numpad events when Num Lock is disabled
|
||||||
// If SHIFT is pressed, a text event will be sent instead
|
// If SHIFT is pressed, a text event will be sent instead
|
||||||
switch(from) {
|
entry = SC_INTMAP_FIND_ENTRY(kp_nav_keys, from);
|
||||||
MAP(SDLK_KP_0, AKEYCODE_INSERT);
|
if (entry) {
|
||||||
MAP(SDLK_KP_1, AKEYCODE_MOVE_END);
|
*to = entry->value;
|
||||||
MAP(SDLK_KP_2, AKEYCODE_DPAD_DOWN);
|
return true;
|
||||||
MAP(SDLK_KP_3, AKEYCODE_PAGE_DOWN);
|
|
||||||
MAP(SDLK_KP_4, AKEYCODE_DPAD_LEFT);
|
|
||||||
MAP(SDLK_KP_6, AKEYCODE_DPAD_RIGHT);
|
|
||||||
MAP(SDLK_KP_7, AKEYCODE_MOVE_HOME);
|
|
||||||
MAP(SDLK_KP_8, AKEYCODE_DPAD_UP);
|
|
||||||
MAP(SDLK_KP_9, AKEYCODE_PAGE_UP);
|
|
||||||
MAP(SDLK_KP_PERIOD, AKEYCODE_FORWARD_DEL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,37 +126,15 @@ convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod,
|
||||||
if (mod & (KMOD_LALT | KMOD_RALT | KMOD_LGUI | KMOD_RGUI)) {
|
if (mod & (KMOD_LALT | KMOD_RALT | KMOD_LGUI | KMOD_RGUI)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if ALT and META are not pressed, also handle letters and space
|
// if ALT and META are not pressed, also handle letters and space
|
||||||
switch (from) {
|
entry = SC_INTMAP_FIND_ENTRY(alphaspace_keys, from);
|
||||||
MAP(SDLK_a, AKEYCODE_A);
|
if (entry) {
|
||||||
MAP(SDLK_b, AKEYCODE_B);
|
*to = entry->value;
|
||||||
MAP(SDLK_c, AKEYCODE_C);
|
return true;
|
||||||
MAP(SDLK_d, AKEYCODE_D);
|
|
||||||
MAP(SDLK_e, AKEYCODE_E);
|
|
||||||
MAP(SDLK_f, AKEYCODE_F);
|
|
||||||
MAP(SDLK_g, AKEYCODE_G);
|
|
||||||
MAP(SDLK_h, AKEYCODE_H);
|
|
||||||
MAP(SDLK_i, AKEYCODE_I);
|
|
||||||
MAP(SDLK_j, AKEYCODE_J);
|
|
||||||
MAP(SDLK_k, AKEYCODE_K);
|
|
||||||
MAP(SDLK_l, AKEYCODE_L);
|
|
||||||
MAP(SDLK_m, AKEYCODE_M);
|
|
||||||
MAP(SDLK_n, AKEYCODE_N);
|
|
||||||
MAP(SDLK_o, AKEYCODE_O);
|
|
||||||
MAP(SDLK_p, AKEYCODE_P);
|
|
||||||
MAP(SDLK_q, AKEYCODE_Q);
|
|
||||||
MAP(SDLK_r, AKEYCODE_R);
|
|
||||||
MAP(SDLK_s, AKEYCODE_S);
|
|
||||||
MAP(SDLK_t, AKEYCODE_T);
|
|
||||||
MAP(SDLK_u, AKEYCODE_U);
|
|
||||||
MAP(SDLK_v, AKEYCODE_V);
|
|
||||||
MAP(SDLK_w, AKEYCODE_W);
|
|
||||||
MAP(SDLK_x, AKEYCODE_X);
|
|
||||||
MAP(SDLK_y, AKEYCODE_Y);
|
|
||||||
MAP(SDLK_z, AKEYCODE_Z);
|
|
||||||
MAP(SDLK_SPACE, AKEYCODE_SPACE);
|
|
||||||
FAIL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum android_metastate
|
static enum android_metastate
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "android/input.h"
|
#include "android/input.h"
|
||||||
#include "control_msg.h"
|
#include "control_msg.h"
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
|
#include "util/intmap.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
|
||||||
/** Downcast mouse processor to sc_mouse_inject */
|
/** Downcast mouse processor to sc_mouse_inject */
|
||||||
|
@ -32,25 +33,37 @@ convert_mouse_buttons(uint32_t state) {
|
||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAP(FROM, TO) case FROM: *to = TO; return true
|
|
||||||
#define FAIL default: return false
|
|
||||||
static bool
|
static bool
|
||||||
convert_mouse_action(SDL_EventType from, enum android_motionevent_action *to) {
|
convert_mouse_action(SDL_EventType from, enum android_motionevent_action *to) {
|
||||||
switch (from) {
|
static const struct sc_intmap_entry actions[] = {
|
||||||
MAP(SDL_MOUSEBUTTONDOWN, AMOTION_EVENT_ACTION_DOWN);
|
{SDL_MOUSEBUTTONDOWN, AMOTION_EVENT_ACTION_DOWN},
|
||||||
MAP(SDL_MOUSEBUTTONUP, AMOTION_EVENT_ACTION_UP);
|
{SDL_MOUSEBUTTONUP, AMOTION_EVENT_ACTION_UP},
|
||||||
FAIL;
|
};
|
||||||
|
|
||||||
|
const struct sc_intmap_entry *entry = SC_INTMAP_FIND_ENTRY(actions, from);
|
||||||
|
if (entry) {
|
||||||
|
*to = entry->value;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
convert_touch_action(SDL_EventType from, enum android_motionevent_action *to) {
|
convert_touch_action(SDL_EventType from, enum android_motionevent_action *to) {
|
||||||
switch (from) {
|
static const struct sc_intmap_entry actions[] = {
|
||||||
MAP(SDL_FINGERMOTION, AMOTION_EVENT_ACTION_MOVE);
|
{SDL_FINGERMOTION, AMOTION_EVENT_ACTION_MOVE},
|
||||||
MAP(SDL_FINGERDOWN, AMOTION_EVENT_ACTION_DOWN);
|
{SDL_FINGERDOWN, AMOTION_EVENT_ACTION_DOWN},
|
||||||
MAP(SDL_FINGERUP, AMOTION_EVENT_ACTION_UP);
|
{SDL_FINGERUP, AMOTION_EVENT_ACTION_UP},
|
||||||
FAIL;
|
};
|
||||||
|
|
||||||
|
const struct sc_intmap_entry *entry = SC_INTMAP_FIND_ENTRY(actions, from);
|
||||||
|
if (entry) {
|
||||||
|
*to = entry->value;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
|
13
app/src/util/intmap.c
Normal file
13
app/src/util/intmap.c
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#include "intmap.h"
|
||||||
|
|
||||||
|
const struct sc_intmap_entry *
|
||||||
|
sc_intmap_find_entry(const struct sc_intmap_entry entries[], size_t len,
|
||||||
|
int32_t key) {
|
||||||
|
for (size_t i = 0; i < len; ++i) {
|
||||||
|
const struct sc_intmap_entry *entry = &entries[i];
|
||||||
|
if (entry->key == key) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
24
app/src/util/intmap.h
Normal file
24
app/src/util/intmap.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef SC_ARRAYMAP_H
|
||||||
|
#define SC_ARRAYMAP_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct sc_intmap_entry {
|
||||||
|
int32_t key;
|
||||||
|
int32_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct sc_intmap_entry *
|
||||||
|
sc_intmap_find_entry(const struct sc_intmap_entry entries[], size_t len,
|
||||||
|
int32_t key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MAP is expected to be a static array of sc_intmap_entry, so that
|
||||||
|
* ARRAY_LEN(MAP) can be computed statically.
|
||||||
|
*/
|
||||||
|
#define SC_INTMAP_FIND_ENTRY(MAP, KEY) \
|
||||||
|
sc_intmap_find_entry(MAP, ARRAY_LEN(MAP), KEY)
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue