#ifndef SC_INPUT_EVENTS_H #define SC_INPUT_EVENTS_H #include "common.h" #include #include #include #include #include "coords.h" /* The representation of input events in scrcpy is very close to the SDL API, * for simplicity. * * This scrcpy input events API is designed to be consumed by input event * processors (sc_key_processor and sc_mouse_processor, see app/src/trait/). * * One major semantic difference between SDL input events and scrcpy input * events is their frame of reference (for mouse and touch events): SDL events * coordinates are expressed in SDL window coordinates (the visible UI), while * scrcpy events are expressed in device frame coordinates. * * In particular, the window may be visually scaled or rotated (with --rotation * or MOD+Left/Right), but this does not impact scrcpy input events (contrary * to SDL input events). This allows to abstract these display details from the * input event processors (and to make them independent from the "screen"). * * For many enums below, the values are purposely the same as the SDL * constants (though not all SDL values are represented), so that the * implementation to convert from the SDL version to the scrcpy version is * straightforward. * * In practice, there are 3 levels of input events: * 1. SDL input events (as received from SDL) * 2. scrcpy input events (this API) * 3. the key/mouse processors input events (Android API or HID events) * * An input event is first received (1), then (if accepted) converted to an * scrcpy input event (2), then submitted to the relevant key/mouse processor, * which (if accepted) is converted to an Android event (to be sent to the * server) or to an HID event (to be sent over USB/AOA directly). */ enum sc_mod { SC_MOD_LSHIFT = KMOD_LSHIFT, SC_MOD_RSHIFT = KMOD_RSHIFT, SC_MOD_LCTRL = KMOD_LCTRL, SC_MOD_RCTRL = KMOD_RCTRL, SC_MOD_LALT = KMOD_LALT, SC_MOD_RALT = KMOD_RALT, SC_MOD_LGUI = KMOD_LGUI, SC_MOD_RGUI = KMOD_RGUI, SC_MOD_NUM = KMOD_NUM, SC_MOD_CAPS = KMOD_CAPS, }; enum sc_action { SC_ACTION_DOWN, // key or button pressed SC_ACTION_UP, // key or button released }; enum sc_keycode { SC_KEYCODE_UNKNOWN = SDLK_UNKNOWN, SC_KEYCODE_RETURN = SDLK_RETURN, SC_KEYCODE_ESCAPE = SDLK_ESCAPE, SC_KEYCODE_BACKSPACE = SDLK_BACKSPACE, SC_KEYCODE_TAB = SDLK_TAB, SC_KEYCODE_SPACE = SDLK_SPACE, SC_KEYCODE_EXCLAIM = SDLK_EXCLAIM, SC_KEYCODE_QUOTEDBL = SDLK_QUOTEDBL, SC_KEYCODE_HASH = SDLK_HASH, SC_KEYCODE_PERCENT = SDLK_PERCENT, SC_KEYCODE_DOLLAR = SDLK_DOLLAR, SC_KEYCODE_AMPERSAND = SDLK_AMPERSAND, SC_KEYCODE_QUOTE = SDLK_QUOTE, SC_KEYCODE_LEFTPAREN = SDLK_LEFTPAREN, SC_KEYCODE_RIGHTPAREN = SDLK_RIGHTPAREN, SC_KEYCODE_ASTERISK = SDLK_ASTERISK, SC_KEYCODE_PLUS = SDLK_PLUS, SC_KEYCODE_COMMA = SDLK_COMMA, SC_KEYCODE_MINUS = SDLK_MINUS, SC_KEYCODE_PERIOD = SDLK_PERIOD, SC_KEYCODE_SLASH = SDLK_SLASH, SC_KEYCODE_0 = SDLK_0, SC_KEYCODE_1 = SDLK_1, SC_KEYCODE_2 = SDLK_2, SC_KEYCODE_3 = SDLK_3, SC_KEYCODE_4 = SDLK_4, SC_KEYCODE_5 = SDLK_5, SC_KEYCODE_6 = SDLK_6, SC_KEYCODE_7 = SDLK_7, SC_KEYCODE_8 = SDLK_8, SC_KEYCODE_9 = SDLK_9, SC_KEYCODE_COLON = SDLK_COLON, SC_KEYCODE_SEMICOLON = SDLK_SEMICOLON, SC_KEYCODE_LESS = SDLK_LESS, SC_KEYCODE_EQUALS = SDLK_EQUALS, SC_KEYCODE_GREATER = SDLK_GREATER, SC_KEYCODE_QUESTION = SDLK_QUESTION, SC_KEYCODE_AT = SDLK_AT, SC_KEYCODE_LEFTBRACKET = SDLK_LEFTBRACKET, SC_KEYCODE_BACKSLASH = SDLK_BACKSLASH, SC_KEYCODE_RIGHTBRACKET = SDLK_RIGHTBRACKET, SC_KEYCODE_CARET = SDLK_CARET, SC_KEYCODE_UNDERSCORE = SDLK_UNDERSCORE, SC_KEYCODE_BACKQUOTE = SDLK_BACKQUOTE, SC_KEYCODE_a = SDLK_a, SC_KEYCODE_b = SDLK_b, SC_KEYCODE_c = SDLK_c, SC_KEYCODE_d = SDLK_d, SC_KEYCODE_e = SDLK_e, SC_KEYCODE_f = SDLK_f, SC_KEYCODE_g = SDLK_g, SC_KEYCODE_h = SDLK_h, SC_KEYCODE_i = SDLK_i, SC_KEYCODE_j = SDLK_j, SC_KEYCODE_k = SDLK_k, SC_KEYCODE_l = SDLK_l, SC_KEYCODE_m = SDLK_m, SC_KEYCODE_n = SDLK_n, SC_KEYCODE_o = SDLK_o, SC_KEYCODE_p = SDLK_p, SC_KEYCODE_q = SDLK_q, SC_KEYCODE_r = SDLK_r, SC_KEYCODE_s = SDLK_s, SC_KEYCODE_t = SDLK_t, SC_KEYCODE_u = SDLK_u, SC_KEYCODE_v = SDLK_v, SC_KEYCODE_w = SDLK_w, SC_KEYCODE_x = SDLK_x, SC_KEYCODE_y = SDLK_y, SC_KEYCODE_z = SDLK_z, SC_KEYCODE_CAPSLOCK = SDLK_CAPSLOCK, SC_KEYCODE_F1 = SDLK_F1, SC_KEYCODE_F2 = SDLK_F2, SC_KEYCODE_F3 = SDLK_F3, SC_KEYCODE_F4 = SDLK_F4, SC_KEYCODE_F5 = SDLK_F5, SC_KEYCODE_F6 = SDLK_F6, SC_KEYCODE_F7 = SDLK_F7, SC_KEYCODE_F8 = SDLK_F8, SC_KEYCODE_F9 = SDLK_F9, SC_KEYCODE_F10 = SDLK_F10, SC_KEYCODE_F11 = SDLK_F11, SC_KEYCODE_F12 = SDLK_F12, SC_KEYCODE_PRINTSCREEN = SDLK_PRINTSCREEN, SC_KEYCODE_SCROLLLOCK = SDLK_SCROLLLOCK, SC_KEYCODE_PAUSE = SDLK_PAUSE, SC_KEYCODE_INSERT = SDLK_INSERT, SC_KEYCODE_HOME = SDLK_HOME, SC_KEYCODE_PAGEUP = SDLK_PAGEUP, SC_KEYCODE_DELETE = SDLK_DELETE, SC_KEYCODE_END = SDLK_END, SC_KEYCODE_PAGEDOWN = SDLK_PAGEDOWN, SC_KEYCODE_RIGHT = SDLK_RIGHT, SC_KEYCODE_LEFT = SDLK_LEFT, SC_KEYCODE_DOWN = SDLK_DOWN, SC_KEYCODE_UP = SDLK_UP, SC_KEYCODE_KP_DIVIDE = SDLK_KP_DIVIDE, SC_KEYCODE_KP_MULTIPLY = SDLK_KP_MULTIPLY, SC_KEYCODE_KP_MINUS = SDLK_KP_MINUS, SC_KEYCODE_KP_PLUS = SDLK_KP_PLUS, SC_KEYCODE_KP_ENTER = SDLK_KP_ENTER, SC_KEYCODE_KP_1 = SDLK_KP_1, SC_KEYCODE_KP_2 = SDLK_KP_2, SC_KEYCODE_KP_3 = SDLK_KP_3, SC_KEYCODE_KP_4 = SDLK_KP_4, SC_KEYCODE_KP_5 = SDLK_KP_5, SC_KEYCODE_KP_6 = SDLK_KP_6, SC_KEYCODE_KP_7 = SDLK_KP_7, SC_KEYCODE_KP_8 = SDLK_KP_8, SC_KEYCODE_KP_9 = SDLK_KP_9, SC_KEYCODE_KP_0 = SDLK_KP_0, SC_KEYCODE_KP_PERIOD = SDLK_KP_PERIOD, SC_KEYCODE_KP_EQUALS = SDLK_KP_EQUALS, SC_KEYCODE_KP_LEFTPAREN = SDLK_KP_LEFTPAREN, SC_KEYCODE_KP_RIGHTPAREN = SDLK_KP_RIGHTPAREN, SC_KEYCODE_LCTRL = SDLK_LCTRL, SC_KEYCODE_LSHIFT = SDLK_LSHIFT, SC_KEYCODE_LALT = SDLK_LALT, SC_KEYCODE_LGUI = SDLK_LGUI, SC_KEYCODE_RCTRL = SDLK_RCTRL, SC_KEYCODE_RSHIFT = SDLK_RSHIFT, SC_KEYCODE_RALT = SDLK_RALT, SC_KEYCODE_RGUI = SDLK_RGUI, }; enum sc_scancode { SC_SCANCODE_UNKNOWN = SDL_SCANCODE_UNKNOWN, SC_SCANCODE_A = SDL_SCANCODE_A, SC_SCANCODE_B = SDL_SCANCODE_B, SC_SCANCODE_C = SDL_SCANCODE_C, SC_SCANCODE_D = SDL_SCANCODE_D, SC_SCANCODE_E = SDL_SCANCODE_E, SC_SCANCODE_F = SDL_SCANCODE_F, SC_SCANCODE_G = SDL_SCANCODE_G, SC_SCANCODE_H = SDL_SCANCODE_H, SC_SCANCODE_I = SDL_SCANCODE_I, SC_SCANCODE_J = SDL_SCANCODE_J, SC_SCANCODE_K = SDL_SCANCODE_K, SC_SCANCODE_L = SDL_SCANCODE_L, SC_SCANCODE_M = SDL_SCANCODE_M, SC_SCANCODE_N = SDL_SCANCODE_N, SC_SCANCODE_O = SDL_SCANCODE_O, SC_SCANCODE_P = SDL_SCANCODE_P, SC_SCANCODE_Q = SDL_SCANCODE_Q, SC_SCANCODE_R = SDL_SCANCODE_R, SC_SCANCODE_S = SDL_SCANCODE_S, SC_SCANCODE_T = SDL_SCANCODE_T, SC_SCANCODE_U = SDL_SCANCODE_U, SC_SCANCODE_V = SDL_SCANCODE_V, SC_SCANCODE_W = SDL_SCANCODE_W, SC_SCANCODE_X = SDL_SCANCODE_X, SC_SCANCODE_Y = SDL_SCANCODE_Y, SC_SCANCODE_Z = SDL_SCANCODE_Z, SC_SCANCODE_1 = SDL_SCANCODE_1, SC_SCANCODE_2 = SDL_SCANCODE_2, SC_SCANCODE_3 = SDL_SCANCODE_3, SC_SCANCODE_4 = SDL_SCANCODE_4, SC_SCANCODE_5 = SDL_SCANCODE_5, SC_SCANCODE_6 = SDL_SCANCODE_6, SC_SCANCODE_7 = SDL_SCANCODE_7, SC_SCANCODE_8 = SDL_SCANCODE_8, SC_SCANCODE_9 = SDL_SCANCODE_9, SC_SCANCODE_0 = SDL_SCANCODE_0, SC_SCANCODE_RETURN = SDL_SCANCODE_RETURN, SC_SCANCODE_ESCAPE = SDL_SCANCODE_ESCAPE, SC_SCANCODE_BACKSPACE = SDL_SCANCODE_BACKSPACE, SC_SCANCODE_TAB = SDL_SCANCODE_TAB, SC_SCANCODE_SPACE = SDL_SCANCODE_SPACE, SC_SCANCODE_MINUS = SDL_SCANCODE_MINUS, SC_SCANCODE_EQUALS = SDL_SCANCODE_EQUALS, SC_SCANCODE_LEFTBRACKET = SDL_SCANCODE_LEFTBRACKET, SC_SCANCODE_RIGHTBRACKET = SDL_SCANCODE_RIGHTBRACKET, SC_SCANCODE_BACKSLASH = SDL_SCANCODE_BACKSLASH, SC_SCANCODE_NONUSHASH = SDL_SCANCODE_NONUSHASH, SC_SCANCODE_SEMICOLON = SDL_SCANCODE_SEMICOLON, SC_SCANCODE_APOSTROPHE = SDL_SCANCODE_APOSTROPHE, SC_SCANCODE_GRAVE = SDL_SCANCODE_GRAVE, SC_SCANCODE_COMMA = SDL_SCANCODE_COMMA, SC_SCANCODE_PERIOD = SDL_SCANCODE_PERIOD, SC_SCANCODE_SLASH = SDL_SCANCODE_SLASH, SC_SCANCODE_CAPSLOCK = SDL_SCANCODE_CAPSLOCK, SC_SCANCODE_F1 = SDL_SCANCODE_F1, SC_SCANCODE_F2 = SDL_SCANCODE_F2, SC_SCANCODE_F3 = SDL_SCANCODE_F3, SC_SCANCODE_F4 = SDL_SCANCODE_F4, SC_SCANCODE_F5 = SDL_SCANCODE_F5, SC_SCANCODE_F6 = SDL_SCANCODE_F6, SC_SCANCODE_F7 = SDL_SCANCODE_F7, SC_SCANCODE_F8 = SDL_SCANCODE_F8, SC_SCANCODE_F9 = SDL_SCANCODE_F9, SC_SCANCODE_F10 = SDL_SCANCODE_F10, SC_SCANCODE_F11 = SDL_SCANCODE_F11, SC_SCANCODE_F12 = SDL_SCANCODE_F12, SC_SCANCODE_PRINTSCREEN = SDL_SCANCODE_PRINTSCREEN, SC_SCANCODE_SCROLLLOCK = SDL_SCANCODE_SCROLLLOCK, SC_SCANCODE_PAUSE = SDL_SCANCODE_PAUSE, SC_SCANCODE_INSERT = SDL_SCANCODE_INSERT, SC_SCANCODE_HOME = SDL_SCANCODE_HOME, SC_SCANCODE_PAGEUP = SDL_SCANCODE_PAGEUP, SC_SCANCODE_DELETE = SDL_SCANCODE_DELETE, SC_SCANCODE_END = SDL_SCANCODE_END, SC_SCANCODE_PAGEDOWN = SDL_SCANCODE_PAGEDOWN, SC_SCANCODE_RIGHT = SDL_SCANCODE_RIGHT, SC_SCANCODE_LEFT = SDL_SCANCODE_LEFT, SC_SCANCODE_DOWN = SDL_SCANCODE_DOWN, SC_SCANCODE_UP = SDL_SCANCODE_UP, SC_SCANCODE_NUMLOCK = SDL_SCANCODE_NUMLOCKCLEAR, SC_SCANCODE_KP_DIVIDE = SDL_SCANCODE_KP_DIVIDE, SC_SCANCODE_KP_MULTIPLY = SDL_SCANCODE_KP_MULTIPLY, SC_SCANCODE_KP_MINUS = SDL_SCANCODE_KP_MINUS, SC_SCANCODE_KP_PLUS = SDL_SCANCODE_KP_PLUS, SC_SCANCODE_KP_ENTER = SDL_SCANCODE_KP_ENTER, SC_SCANCODE_KP_1 = SDL_SCANCODE_KP_1, SC_SCANCODE_KP_2 = SDL_SCANCODE_KP_2, SC_SCANCODE_KP_3 = SDL_SCANCODE_KP_3, SC_SCANCODE_KP_4 = SDL_SCANCODE_KP_4, SC_SCANCODE_KP_5 = SDL_SCANCODE_KP_5, SC_SCANCODE_KP_6 = SDL_SCANCODE_KP_6, SC_SCANCODE_KP_7 = SDL_SCANCODE_KP_7, SC_SCANCODE_KP_8 = SDL_SCANCODE_KP_8, SC_SCANCODE_KP_9 = SDL_SCANCODE_KP_9, SC_SCANCODE_KP_0 = SDL_SCANCODE_KP_0, SC_SCANCODE_KP_PERIOD = SDL_SCANCODE_KP_PERIOD, SC_SCANCODE_LCTRL = SDL_SCANCODE_LCTRL, SC_SCANCODE_LSHIFT = SDL_SCANCODE_LSHIFT, SC_SCANCODE_LALT = SDL_SCANCODE_LALT, SC_SCANCODE_LGUI = SDL_SCANCODE_LGUI, SC_SCANCODE_RCTRL = SDL_SCANCODE_RCTRL, SC_SCANCODE_RSHIFT = SDL_SCANCODE_RSHIFT, SC_SCANCODE_RALT = SDL_SCANCODE_RALT, SC_SCANCODE_RGUI = SDL_SCANCODE_RGUI, }; // On purpose, only use the "mask" values (1, 2, 4, 8, 16) for a single button, // to avoid unnecessary conversions (and confusion). enum sc_mouse_button { SC_MOUSE_BUTTON_UNKNOWN = 0, SC_MOUSE_BUTTON_LEFT = SDL_BUTTON(SDL_BUTTON_LEFT), SC_MOUSE_BUTTON_RIGHT = SDL_BUTTON(SDL_BUTTON_RIGHT), SC_MOUSE_BUTTON_MIDDLE = SDL_BUTTON(SDL_BUTTON_MIDDLE), SC_MOUSE_BUTTON_X1 = SDL_BUTTON(SDL_BUTTON_X1), SC_MOUSE_BUTTON_X2 = SDL_BUTTON(SDL_BUTTON_X2), }; static_assert(sizeof(enum sc_mod) >= sizeof(SDL_Keymod), "SDL_Keymod must be convertible to sc_mod"); static_assert(sizeof(enum sc_keycode) >= sizeof(SDL_Keycode), "SDL_Keycode must be convertible to sc_keycode"); static_assert(sizeof(enum sc_scancode) >= sizeof(SDL_Scancode), "SDL_Scancode must be convertible to sc_scancode"); enum sc_touch_action { SC_TOUCH_ACTION_MOVE, SC_TOUCH_ACTION_DOWN, SC_TOUCH_ACTION_UP, }; struct sc_key_event { enum sc_action action; enum sc_keycode keycode; enum sc_scancode scancode; uint16_t mods_state; // bitwise-OR of sc_mod values bool repeat; }; struct sc_text_event { const char *text; // not owned }; struct sc_mouse_click_event { struct sc_position position; enum sc_action action; enum sc_mouse_button button; uint64_t pointer_id; uint8_t buttons_state; // bitwise-OR of sc_mouse_button values }; struct sc_mouse_scroll_event { struct sc_position position; float hscroll; float vscroll; uint8_t buttons_state; // bitwise-OR of sc_mouse_button values }; struct sc_mouse_motion_event { struct sc_position position; uint64_t pointer_id; int32_t xrel; int32_t yrel; uint8_t buttons_state; // bitwise-OR of sc_mouse_button values }; struct sc_touch_event { struct sc_position position; enum sc_touch_action action; uint64_t pointer_id; float pressure; }; static inline uint16_t sc_mods_state_from_sdl(uint16_t mods_state) { return mods_state; } static inline enum sc_keycode sc_keycode_from_sdl(SDL_Keycode keycode) { return (enum sc_keycode) keycode; } static inline enum sc_scancode sc_scancode_from_sdl(SDL_Scancode scancode) { return (enum sc_scancode) scancode; } static inline enum sc_action sc_action_from_sdl_keyboard_type(uint32_t type) { assert(type == SDL_KEYDOWN || type == SDL_KEYUP); if (type == SDL_KEYDOWN) { return SC_ACTION_DOWN; } return SC_ACTION_UP; } static inline enum sc_action sc_action_from_sdl_mousebutton_type(uint32_t type) { assert(type == SDL_MOUSEBUTTONDOWN || type == SDL_MOUSEBUTTONUP); if (type == SDL_MOUSEBUTTONDOWN) { return SC_ACTION_DOWN; } return SC_ACTION_UP; } static inline enum sc_touch_action sc_touch_action_from_sdl(uint32_t type) { assert(type == SDL_FINGERMOTION || type == SDL_FINGERDOWN || type == SDL_FINGERUP); if (type == SDL_FINGERMOTION) { return SC_TOUCH_ACTION_MOVE; } if (type == SDL_FINGERDOWN) { return SC_TOUCH_ACTION_DOWN; } return SC_TOUCH_ACTION_UP; } static inline enum sc_mouse_button sc_mouse_button_from_sdl(uint8_t button) { if (button >= SDL_BUTTON_LEFT && button <= SDL_BUTTON_X2) { // SC_MOUSE_BUTTON_* constants are initialized from SDL_BUTTON(index) return SDL_BUTTON(button); } return SC_MOUSE_BUTTON_UNKNOWN; } static inline uint8_t sc_mouse_buttons_state_from_sdl(uint32_t buttons_state, bool forward_all_clicks) { assert(buttons_state < 0x100); // fits in uint8_t uint8_t mask = SC_MOUSE_BUTTON_LEFT; if (forward_all_clicks) { mask |= SC_MOUSE_BUTTON_RIGHT | SC_MOUSE_BUTTON_MIDDLE | SC_MOUSE_BUTTON_X1 | SC_MOUSE_BUTTON_X2; } return buttons_state & mask; } #endif