207 lines
5.2 KiB
C
207 lines
5.2 KiB
C
/**
|
|
* @file lv_sdl_keyboard.c
|
|
*
|
|
*/
|
|
|
|
/*********************
|
|
* INCLUDES
|
|
*********************/
|
|
#include "lv_sdl_keyboard.h"
|
|
#if LV_USE_SDL
|
|
|
|
#include "../../indev/lv_indev.h"
|
|
#include "../../core/lv_group.h"
|
|
#include "../../stdlib/lv_string.h"
|
|
#include LV_SDL_INCLUDE_PATH
|
|
|
|
/*********************
|
|
* DEFINES
|
|
*********************/
|
|
|
|
/**********************
|
|
* TYPEDEFS
|
|
**********************/
|
|
typedef struct {
|
|
char buf[KEYBOARD_BUFFER_SIZE];
|
|
bool dummy_read;
|
|
} lv_sdl_keyboard_t;
|
|
|
|
/**********************
|
|
* STATIC PROTOTYPES
|
|
**********************/
|
|
static void sdl_keyboard_read(lv_indev_t * indev, lv_indev_data_t * data);
|
|
static uint32_t keycode_to_ctrl_key(SDL_Keycode sdl_key);
|
|
static void release_indev_cb(lv_event_t * e);
|
|
|
|
/**********************
|
|
* STATIC VARIABLES
|
|
**********************/
|
|
|
|
/**********************
|
|
* GLOBAL FUNCTIONS
|
|
**********************/
|
|
|
|
lv_indev_t * lv_sdl_keyboard_create(void)
|
|
{
|
|
lv_sdl_keyboard_t * dsc = lv_malloc_zeroed(sizeof(lv_sdl_keyboard_t));
|
|
LV_ASSERT_MALLOC(dsc);
|
|
if(dsc == NULL) return NULL;
|
|
|
|
lv_indev_t * indev = lv_indev_create();
|
|
LV_ASSERT_MALLOC(indev);
|
|
if(indev == NULL) {
|
|
lv_free(dsc);
|
|
return NULL;
|
|
}
|
|
|
|
lv_indev_set_type(indev, LV_INDEV_TYPE_KEYPAD);
|
|
lv_indev_set_read_cb(indev, sdl_keyboard_read);
|
|
lv_indev_set_driver_data(indev, dsc);
|
|
lv_indev_set_mode(indev, LV_INDEV_MODE_EVENT);
|
|
lv_indev_add_event_cb(indev, release_indev_cb, LV_EVENT_DELETE, indev);
|
|
|
|
return indev;
|
|
}
|
|
|
|
/**********************
|
|
* STATIC FUNCTIONS
|
|
**********************/
|
|
|
|
static void sdl_keyboard_read(lv_indev_t * indev, lv_indev_data_t * data)
|
|
{
|
|
lv_sdl_keyboard_t * dev = lv_indev_get_driver_data(indev);
|
|
|
|
const size_t len = lv_strlen(dev->buf);
|
|
|
|
/*Send a release manually*/
|
|
if(dev->dummy_read) {
|
|
dev->dummy_read = false;
|
|
data->state = LV_INDEV_STATE_RELEASED;
|
|
data->continue_reading = len > 0;
|
|
}
|
|
/*Send the pressed character*/
|
|
else if(len > 0) {
|
|
dev->dummy_read = true;
|
|
data->state = LV_INDEV_STATE_PRESSED;
|
|
data->key = dev->buf[0];
|
|
memmove(dev->buf, dev->buf + 1, len);
|
|
data->continue_reading = true;
|
|
}
|
|
}
|
|
|
|
static void release_indev_cb(lv_event_t * e)
|
|
{
|
|
lv_indev_t * indev = (lv_indev_t *) lv_event_get_user_data(e);
|
|
lv_sdl_keyboard_t * dev = lv_indev_get_driver_data(indev);
|
|
if(dev) {
|
|
lv_indev_set_driver_data(indev, NULL);
|
|
lv_indev_set_read_cb(indev, NULL);
|
|
lv_free(dev);
|
|
LV_LOG_INFO("done");
|
|
}
|
|
}
|
|
|
|
void _lv_sdl_keyboard_handler(SDL_Event * event)
|
|
{
|
|
uint32_t win_id = UINT32_MAX;
|
|
switch(event->type) {
|
|
case SDL_KEYDOWN:
|
|
win_id = event->key.windowID;
|
|
break;
|
|
case SDL_TEXTINPUT:
|
|
win_id = event->text.windowID;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
lv_display_t * disp = _lv_sdl_get_disp_from_win_id(win_id);
|
|
|
|
/*Find a suitable indev*/
|
|
lv_indev_t * indev = lv_indev_get_next(NULL);
|
|
while(indev) {
|
|
if(lv_indev_get_display(indev) == disp && lv_indev_get_type(indev) == LV_INDEV_TYPE_KEYPAD) {
|
|
break;
|
|
}
|
|
indev = lv_indev_get_next(indev);
|
|
}
|
|
|
|
if(indev == NULL) return;
|
|
lv_sdl_keyboard_t * dsc = lv_indev_get_driver_data(indev);
|
|
|
|
/* 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 = lv_strlen(dsc->buf);
|
|
if(len < KEYBOARD_BUFFER_SIZE - 1) {
|
|
dsc->buf[len] = ctrl_key;
|
|
dsc->buf[len + 1] = '\0';
|
|
}
|
|
break;
|
|
}
|
|
case SDL_TEXTINPUT: { /*Text input*/
|
|
const size_t len = lv_strlen(dsc->buf) + lv_strlen(event->text.text);
|
|
if(len < KEYBOARD_BUFFER_SIZE - 1)
|
|
strcat(dsc->buf, event->text.text);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
|
|
}
|
|
lv_indev_read(indev);
|
|
}
|
|
|
|
/**
|
|
* 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'
|
|
*/
|
|
static uint32_t keycode_to_ctrl_key(SDL_Keycode sdl_key)
|
|
{
|
|
/*Remap some key to LV_KEY_... to manage groups*/
|
|
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:
|
|
case SDLK_PAGEDOWN:
|
|
return LV_KEY_NEXT;
|
|
|
|
case SDLK_PAGEUP:
|
|
return LV_KEY_PREV;
|
|
|
|
default:
|
|
return '\0';
|
|
}
|
|
}
|
|
|
|
#endif /*LV_USE_SDL*/
|