Input device interface

Types of input devices

To set up an input device an lv_indev_drv_t variable has to be initialized:

lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);      /*Basic initialization*/
indev_drv.type =...                 /*See below.*/
indev_drv.read_cb =...              /*See below.*/
/*Register the driver in LittlevGL and save the created input device object*/
lv_indev_t * my_indev = lv_indev_drv_register(&indev_drv);

type can be

  • LV_INDEV_TYPE_POINTER touchpad or mouse

  • LV_INDEV_TYPE_KEYPAD keyboard or keypad

  • LV_INDEV_TYPE_ENCODER encoder with left, right, push options

  • LV_INDEV_TYPE_BUTTON external buttons pressing the screen

read_cb is a function pointer which will be called periodically to report the current state of an input device. It can also buffer data and return false when no more data to be read or true when the buffer is not empty.

Visit Input devices to learn more about input devices in general.

Touchpad, mouse or any pointer

Input devices which can click points of the screen belong to this category.

indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_input_read;


bool my_input_read(lv_indev_drv_t * drv, lv_indev_data_t*data)
    data->point.x = touchpad_x;
    data->point.y = touchpad_y;
    data->state = LV_INDEV_STATE_PR or LV_INDEV_STATE_REL;
    return false; /*No buffering now so no more data read*/


Touchpad drivers must return the last X/Y coordinates even when the state is LV_INDEV_STATE_REL.

To set a mouse cursor use lv_indev_set_cursor(my_indev, &img_cursor). (my_indev is the return value of lv_indev_drv_register)

Keypad or keyboard

Full keyboards with all the letters or simple keypads with a few navigation buttons belong here.

To use a keyboard/keypad:

  • Register a read_cb function with LV_INDEV_TYPE_KEYPAD type.

  • Enable LV_USE_GROUP in lv_conf.h

  • An object group has to be created: lv_group_t * g = lv_group_create() and objects have to be added to it with lv_group_add_obj(g, obj)

  • The created group has to be assigned to an input device: lv_indev_set_group(my_indev, g) (my_indev is the return value of lv_indev_drv_register)

  • Use LV_KEY_... to navigate among the objects in the group. See lv_core/lv_group.h for the available keys.

indev_drv.type = LV_INDEV_TYPE_KEYPAD;
indev_drv.read_cb = keyboard_read;


bool keyboard_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
  data->key = last_key();            /*Get the last pressed or released key*/

  if(key_pressed()) data->state = LV_INDEV_STATE_PR;
  else data->state = LV_INDEV_STATE_REL;

  return false; /*No buffering now so no more data read*/


With an encoder you can do 4 things:

  1. Press its button

  2. Long-press its button

  3. Turn left

  4. Turn right

In short, the Encoder input devices work like this:

  • By turning the encoder you can focus on the next/previous object.

  • When you press the encoder on a simple object (like a button), it will be clicked.

  • If you press the encoder on a complex object (like a list, message box, etc.) the object will go to edit mode whereby turning the encoder you can navigate inside the object.

  • To leave edit mode press long the button.

To use an Encoder (similarly to the Keypads) the objects should be added to groups.

indev_drv.type = LV_INDEV_TYPE_ENCODER;
indev_drv.read_cb = my_input_read;


bool encoder_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
  data->enc_diff = enc_get_new_moves();

  if(enc_pressed()) data->state = LV_INDEV_STATE_PR;
  else data->state = LV_INDEV_STATE_REL;

  return false; /*No buffering now so no more data read*/


Buttons mean external “hardware” buttons next to the screen which are assigned to specific coordinates of the screen. If a button is pressed it will simulate the pressing on the assigned coordinate. (Similarly to a touchpad)

To assign buttons to coordinates use lv_indev_set_button_points(my_indev, points_array).points_array should look like const lv_point_t points_array[] =  { {12,30},{60,90}, ...}


The points_array can’t go out of scope. Either declare it as a global variable or as a static variable inside a function.

indev_drv.type = LV_INDEV_TYPE_BUTTON;
indev_drv.read_cb = my_input_read;


bool button_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
    static uint32_t last_btn = 0;   /*Store the last pressed button*/
    int btn_pr = my_btn_read();     /*Get the ID (0,1,2...) of the pressed button*/
    if(btn_pr >= 0) {               /*Is there a button press? (E.g. -1 indicated no button was pressed)*/
       last_btn = btn_pr;           /*Save the ID of the pressed button*/
       data->state = LV_INDEV_STATE_PR;  /*Set the pressed state*/
    } else {
       data->state = LV_INDEV_STATE_REL; /*Set the released state*/

    data->btn = last_btn;            /*Save the last button*/

    return false;                    /*No buffering now so no more data read*/

Other features

Besides read_cb a feedback_cb callback can be also specified in lv_indev_drv_t. feedback_cb is called when any type of event is sent by the input devices. (independently from its type). It allows making feedback for the user e.g. to play a sound on LV_EVENT_CLICK.

The default value of the following parameters can be set in lv_conf.h but the default value can be overwritten in lv_indev_drv_t:

  • drag_limit Number of pixels to slide before actually drag the object

  • drag_throw Drag throw slow-down in [%]. Greater value means faster slow-down

  • long_press_time Press time to send LV_EVENT_LONG_PRESSED (in milliseconds)

  • long_press_rep_time Interval of sending LV_EVENT_LONG_PRESSED_REPEAT (in milliseconds)

  • read_task pointer to the lv_task which reads the input device. Its parameters can be changed by lv_task_...() functions

Every Input device is associated with a display. By default, a new input device is added to the lastly created or the explicitly selected (using lv_disp_set_default()) display. The associated display is stored and can be changed in disp field of the driver.


Input Device HAL interface layer header file


typedef uint8_t lv_indev_type_t
typedef uint8_t lv_indev_state_t
typedef struct _lv_indev_drv_t lv_indev_drv_t

Initialized by the user and registered by ‘lv_indev_add()’

typedef struct _lv_indev_proc_t lv_indev_proc_t

Run time data of input devices Internally used by the library, you should not need to touch it.

typedef struct _lv_indev_t lv_indev_t

The main input device descriptor with driver, runtime data (‘proc’) and some additional information


enum [anonymous]

Possible input device types



Uninitialized state


Touch pad, mouse, external button


Keypad or keyboard


External (hardware button) which is assigned to a specific point of the screen


Encoder with only Left, Right turn and a Button

enum [anonymous]

States for input devices




void lv_indev_drv_init(lv_indev_drv_t *driver)

Initialize an input device driver with default values. It is used to surly have known values in the fields ant not memory junk. After it you can set the fields.

  • driver: pointer to driver variable to initialize

lv_indev_t *lv_indev_drv_register(lv_indev_drv_t *driver)

Register an initialized input device driver.


pointer to the new input device or NULL on error

  • driver: pointer to an initialized ‘lv_indev_drv_t’ variable (can be local variable)

void lv_indev_drv_update(lv_indev_t *indev, lv_indev_drv_t *new_drv)

Update the driver in run time.

  • indev: pointer to a input device. (return value of lv_indev_drv_register)

  • new_drv: pointer to the new driver

lv_indev_t *lv_indev_get_next(lv_indev_t *indev)

Get the next input device.


the next input devise or NULL if no more. Give the first input device when the parameter is NULL

  • indev: pointer to the current input device. NULL to initialize.

bool lv_indev_read(lv_indev_t *indev, lv_indev_data_t *data)

Read data from an input device.


false: no more data; true: there more data to read (buffered)

  • indev: pointer to an input device

  • data: input device will write its data here

struct lv_indev_data_t
#include <lv_hal_indev.h>

Data structure passed to an input driver to fill

Public Members

lv_point_t point

For LV_INDEV_TYPE_POINTER the currently pressed point

uint32_t key

For LV_INDEV_TYPE_KEYPAD the currently pressed key

uint32_t btn_id

For LV_INDEV_TYPE_BUTTON the currently pressed button

int16_t enc_diff

For LV_INDEV_TYPE_ENCODER number of steps since the previous read

lv_indev_state_t state


struct _lv_indev_drv_t
#include <lv_hal_indev.h>

Initialized by the user and registered by ‘lv_indev_add()’

Public Members

lv_indev_type_t type

< Input device type Function pointer to read input device data. Return ‘true’ if there is more data to be read (buffered). Most drivers can safely return ‘false’

bool (*read_cb)(struct _lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
void (*feedback_cb)(struct _lv_indev_drv_t *, uint8_t)

Called when an action happened on the input device. The second parameter is the event from lv_event_t

lv_indev_drv_user_data_t user_data
struct _disp_t *disp

< Pointer to the assigned display Task to read the periodically read the input device

lv_task_t *read_task

Number of pixels to slide before actually drag the object

uint8_t drag_limit

Drag throw slow-down in [%]. Greater value means faster slow-down

uint8_t drag_throw

Long press time in milliseconds

uint16_t long_press_time

Repeated trigger period in long press [ms]

uint16_t long_press_rep_time
struct _lv_indev_proc_t
#include <lv_hal_indev.h>

Run time data of input devices Internally used by the library, you should not need to touch it.

Public Members

lv_indev_state_t state

Current state of the input device.

lv_point_t act_point

Current point of input device.

lv_point_t last_point

Last point of input device.

lv_point_t vect

Difference between act_point and last_point.

lv_point_t drag_sum
lv_point_t drag_throw_vect
struct _lv_obj_t *act_obj
struct _lv_obj_t *last_obj
struct _lv_obj_t *last_pressed
uint8_t drag_limit_out
uint8_t drag_in_prog
struct _lv_indev_proc_t::[anonymous]::[anonymous] pointer
lv_indev_state_t last_state
uint32_t last_key
struct _lv_indev_proc_t::[anonymous]::[anonymous] keypad
union _lv_indev_proc_t::[anonymous] types
uint32_t pr_timestamp

Pressed time stamp

uint32_t longpr_rep_timestamp

Long press repeat time stamp

uint8_t long_pr_sent
uint8_t reset_query
uint8_t disabled
uint8_t wait_until_release
struct _lv_indev_t
#include <lv_hal_indev.h>

The main input device descriptor with driver, runtime data (‘proc’) and some additional information

Public Members

lv_indev_drv_t driver
lv_indev_proc_t proc
struct _lv_obj_t *cursor


struct _lv_group_t *group

Keypad destination group

const lv_point_t *btn_points

Array points assigned to the button ()screen will be pressed here by the buttons