Implement LVGL with SDL for simulator (#16)
* Implemented LVGL with SDL for simulator * cleanup * added SDL to build * build fix * mutex fixes * sim app cleanup and improvements * docs updated * fix for sdl? * fix for SDL cmake setup
This commit is contained in:
committed by
GitHub
parent
18a5c5aa45
commit
d6baf40d0b
@@ -0,0 +1,273 @@
|
||||
//
|
||||
// Created by Mariotaku on 2021/10/14.
|
||||
//
|
||||
|
||||
#include "sdl_common.h"
|
||||
|
||||
#if USE_SDL || USE_SDL_GPU
|
||||
#include "sdl_common_internal.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#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';
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* USE_SDL || USD_SDL_GPU */
|
||||
Reference in New Issue
Block a user