// // Created by Mariotaku on 2021/10/14. // #include "sdl_drivers/sdl_common.h" #ifndef KEYBOARD_BUFFER_SIZE #define KEYBOARD_BUFFER_SIZE SDL_TEXTINPUTEVENT_TEXT_SIZE #endif /********************** * STATIC PROTOTYPES **********************/ /********************** * STATIC VARIABLES **********************/ volatile bool sdl_quit_qry = false; static bool left_button_down = false; static int16_t last_x = 0; static int16_t last_y = 0; static int16_t wheel_diff = 0; static lv_indev_state_t wheel_state = LV_INDEV_STATE_RELEASED; static char buf[KEYBOARD_BUFFER_SIZE]; /********************** * GLOBAL FUNCTIONS **********************/ /** * Get the current position and state of the mouse * @param indev_drv pointer to the related input device driver * @param data store the mouse data here */ void sdl_mouse_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) { (void) indev_drv; /*Unused*/ /*Store the collected data*/ data->point.x = last_x; data->point.y = last_y; data->state = left_button_down ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; } /** * Get encoder (i.e. mouse wheel) ticks difference and pressed state * @param indev_drv pointer to the related input device driver * @param data store the read data here */ void sdl_mousewheel_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) { (void) indev_drv; /*Unused*/ data->state = wheel_state; data->enc_diff = wheel_diff; wheel_diff = 0; } /** * Get input from the keyboard. * @param indev_drv pointer to the related input device driver * @param data store the red data here */ void sdl_keyboard_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) { (void) indev_drv; /*Unused*/ static bool dummy_read = false; const size_t len = strlen(buf); /*Send a release manually*/ if (dummy_read) { dummy_read = false; data->state = LV_INDEV_STATE_RELEASED; data->continue_reading = len > 0; } /*Send the pressed character*/ else if (len > 0) { dummy_read = true; data->state = LV_INDEV_STATE_PRESSED; data->key = buf[0]; memmove(buf, buf + 1, len); data->continue_reading = true; } } /********************** * STATIC FUNCTIONS **********************/ int quit_filter(void * userdata, SDL_Event * event) { (void)userdata; if(event->type == SDL_QUIT) { sdl_quit_qry = true; } return 1; } void mouse_handler(SDL_Event * event) { switch(event->type) { case SDL_MOUSEBUTTONUP: if(event->button.button == SDL_BUTTON_LEFT) left_button_down = false; break; case SDL_MOUSEBUTTONDOWN: if(event->button.button == SDL_BUTTON_LEFT) { left_button_down = true; last_x = event->motion.x / SDL_ZOOM; last_y = event->motion.y / SDL_ZOOM; } break; case SDL_MOUSEMOTION: last_x = event->motion.x / SDL_ZOOM; last_y = event->motion.y / SDL_ZOOM; break; case SDL_FINGERUP: left_button_down = false; last_x = LV_HOR_RES * event->tfinger.x / SDL_ZOOM; last_y = LV_VER_RES * event->tfinger.y / SDL_ZOOM; break; case SDL_FINGERDOWN: left_button_down = true; last_x = LV_HOR_RES * event->tfinger.x / SDL_ZOOM; last_y = LV_VER_RES * event->tfinger.y / SDL_ZOOM; break; case SDL_FINGERMOTION: last_x = LV_HOR_RES * event->tfinger.x / SDL_ZOOM; last_y = LV_VER_RES * event->tfinger.y / SDL_ZOOM; break; } } /** * It is called periodically from the SDL thread to check mouse wheel state * @param event describes the event */ void mousewheel_handler(SDL_Event * event) { switch(event->type) { case SDL_MOUSEWHEEL: // Scroll down (y = -1) means positive encoder turn, // so invert it #ifdef __EMSCRIPTEN__ /*Escripten scales it wrong*/ if(event->wheel.y < 0) wheel_diff++; if(event->wheel.y > 0) wheel_diff--; #else wheel_diff = -event->wheel.y; #endif break; case SDL_MOUSEBUTTONDOWN: if(event->button.button == SDL_BUTTON_MIDDLE) { wheel_state = LV_INDEV_STATE_PRESSED; } break; case SDL_MOUSEBUTTONUP: if(event->button.button == SDL_BUTTON_MIDDLE) { wheel_state = LV_INDEV_STATE_RELEASED; } break; default: break; } } /** * Called periodically from the SDL thread, store text input or control characters in the buffer. * @param event describes the event */ void keyboard_handler(SDL_Event * event) { /* We only care about SDL_KEYDOWN and SDL_TEXTINPUT events */ switch(event->type) { case SDL_KEYDOWN: /*Button press*/ { const uint32_t ctrl_key = keycode_to_ctrl_key(event->key.keysym.sym); if (ctrl_key == '\0') return; const size_t len = strlen(buf); if (len < KEYBOARD_BUFFER_SIZE - 1) { buf[len] = ctrl_key; buf[len + 1] = '\0'; } break; } case SDL_TEXTINPUT: /*Text input*/ { const size_t len = strlen(buf) + strlen(event->text.text); if (len < KEYBOARD_BUFFER_SIZE - 1) strcat(buf, event->text.text); } break; default: break; } } /** * Convert a SDL key code to it's LV_KEY_* counterpart or return '\0' if it's not a control character. * @param sdl_key the key code * @return LV_KEY_* control character or '\0' */ uint32_t keycode_to_ctrl_key(SDL_Keycode sdl_key) { /*Remap some key to LV_KEY_... to manage groups*/ SDL_Keymod mode = SDL_GetModState(); switch(sdl_key) { case SDLK_RIGHT: case SDLK_KP_PLUS: return LV_KEY_RIGHT; case SDLK_LEFT: case SDLK_KP_MINUS: return LV_KEY_LEFT; case SDLK_UP: return LV_KEY_UP; case SDLK_DOWN: return LV_KEY_DOWN; case SDLK_ESCAPE: return LV_KEY_ESC; case SDLK_BACKSPACE: return LV_KEY_BACKSPACE; case SDLK_DELETE: return LV_KEY_DEL; case SDLK_KP_ENTER: case '\r': return LV_KEY_ENTER; case SDLK_TAB: return (mode & KMOD_SHIFT)? LV_KEY_PREV: LV_KEY_NEXT; case SDLK_PAGEDOWN: return LV_KEY_NEXT; case SDLK_PAGEUP: return LV_KEY_PREV; default: return '\0'; } }