Merge remote-tracking branch 'paulpv/feat-cpicker' into feat-cpicker

This commit is contained in:
Themba Dube
2019-10-27 09:10:41 -04:00
13 changed files with 283 additions and 74 deletions

View File

@@ -361,6 +361,12 @@ typedef void * lv_font_user_data_t;
# define lv_vsnprintf vsnprintf
#endif /*LV_SPRINTF_CUSTOM*/
/* Set the pixel order of the display.
* Important only if "subpx fonts" are used.
* With "normal" font it doesn't matter.
*/
#define LV_SUBPX_BGR 0
/*===================
* LV_OBJ SETTINGS
*==================*/

View File

@@ -504,6 +504,14 @@
#endif
#endif /*LV_SPRINTF_CUSTOM*/
/* Set the pixel order of the display.
* Important only if "subpx fonts" are used.
* With "normal" font it doesn't matter.
*/
#ifndef LV_SUBPX_BGR
#define LV_SUBPX_BGR 0
#endif
/*===================
* LV_OBJ SETTINGS
*==================*/

View File

@@ -56,6 +56,11 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
lv_coord_t thickness = style->line.width;
if(thickness > radius) thickness = radius;
#if LV_ANTIALIAS
thickness--;
radius--;
#endif
lv_coord_t r_out = radius;
lv_coord_t r_in = r_out - thickness;
int16_t deg_base;
@@ -72,17 +77,26 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
else
deg_test = deg_test_inv;
int middle_r_out = r_out;
#if !LV_ANTIALIAS
thickness--;
middle_r_out = r_out - 1;
#endif
if(deg_test(270, start_angle, end_angle))
hor_line(center_x - r_out + 1, center_y, mask, thickness - 1, color, opa); /*Left Middle*/
hor_line(center_x - middle_r_out, center_y, mask, thickness, color, opa); /*Left Middle*/
if(deg_test(90, start_angle, end_angle))
hor_line(center_x + r_in, center_y, mask, thickness - 1, color, opa); /*Right Middle*/
hor_line(center_x + r_in, center_y, mask, thickness, color, opa); /*Right Middle*/
if(deg_test(180, start_angle, end_angle))
ver_line(center_x, center_y - r_out + 1, mask, thickness - 1, color, opa); /*Top Middle*/
ver_line(center_x, center_y - middle_r_out, mask, thickness, color, opa); /*Top Middle*/
if(deg_test(0, start_angle, end_angle))
ver_line(center_x, center_y + r_in, mask, thickness - 1, color, opa); /*Bottom middle*/
ver_line(center_x, center_y + r_in, mask, thickness, color, opa); /*Bottom middle*/
uint32_t r_out_sqr = r_out * r_out;
uint32_t r_in_sqr = r_in * r_in;
#if LV_ANTIALIAS
uint32_t r_out_aa_sqr = (r_out + 1) * (r_out + 1);
uint32_t r_in_aa_sqr = (r_in - 1) * (r_in - 1);
#endif
int16_t xi;
int16_t yi;
for(yi = -r_out; yi < 0; yi++) {
@@ -94,13 +108,56 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
x_end[1] = LV_COORD_MIN;
x_end[2] = LV_COORD_MIN;
x_end[3] = LV_COORD_MIN;
int xe = 0;
for(xi = -r_out; xi < 0; xi++) {
uint32_t r_act_sqr = xi * xi + yi * yi;
#if LV_ANTIALIAS
if(r_act_sqr > r_out_aa_sqr) {
continue;
}
#else
if(r_act_sqr > r_out_sqr) continue;
#endif
deg_base = lv_atan2(xi, yi) - 180;
#if LV_ANTIALIAS
int opa = -1;
if(r_act_sqr > r_out_sqr) {
opa = LV_OPA_100 * (r_out + 1) - lv_sqrt(LV_OPA_100 * LV_OPA_100 * r_act_sqr);
if(opa < LV_OPA_0)
opa = LV_OPA_0;
else if(opa > LV_OPA_100)
opa = LV_OPA_100;
} else if(r_act_sqr < r_in_sqr) {
if(xe == 0) xe = xi;
opa = lv_sqrt(LV_OPA_100 * LV_OPA_100 * r_act_sqr) - LV_OPA_100 * (r_in - 1);
if(opa < LV_OPA_0)
opa = LV_OPA_0;
else if(opa > LV_OPA_100)
opa = LV_OPA_100;
if(r_act_sqr < r_in_aa_sqr)
break; /*No need to continue the iteration in x once we found the inner edge of the
arc*/
}
if(opa != -1) {
if(deg_test(180 + deg_base, start_angle, end_angle)) {
lv_draw_px(center_x + xi, center_y + yi, mask, color, opa);
}
if(deg_test(360 - deg_base, start_angle, end_angle)) {
lv_draw_px(center_x + xi, center_y - yi, mask, color, opa);
}
if(deg_test(180 - deg_base, start_angle, end_angle)) {
lv_draw_px(center_x - xi, center_y + yi, mask, color, opa);
}
if(deg_test(deg_base, start_angle, end_angle)) {
lv_draw_px(center_x - xi, center_y - yi, mask, color, opa);
}
continue;
}
#endif
deg = 180 + deg_base;
if(deg_test(deg, start_angle, end_angle)) {
if(x_start[0] == LV_COORD_MIN) x_start[0] = xi;
@@ -129,35 +186,32 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
x_end[3] = xi - 1;
}
if(r_act_sqr < r_in_sqr)
if(r_act_sqr < r_in_sqr) {
xe = xi;
break; /*No need to continue the iteration in x once we found the inner edge of the
arc*/
}
}
if(x_start[0] != LV_COORD_MIN) {
if(x_end[0] == LV_COORD_MIN) x_end[0] = xi - 1;
if(x_end[0] == LV_COORD_MIN) x_end[0] = xe - 1;
hor_line(center_x + x_start[0], center_y + yi, mask, x_end[0] - x_start[0], color, opa);
}
if(x_start[1] != LV_COORD_MIN) {
if(x_end[1] == LV_COORD_MIN) x_end[1] = xi - 1;
if(x_end[1] == LV_COORD_MIN) x_end[1] = xe - 1;
hor_line(center_x + x_start[1], center_y - yi, mask, x_end[1] - x_start[1], color, opa);
}
if(x_start[2] != LV_COORD_MIN) {
if(x_end[2] == LV_COORD_MIN) x_end[2] = xi - 1;
if(x_end[2] == LV_COORD_MIN) x_end[2] = xe - 1;
hor_line(center_x - x_end[2], center_y + yi, mask, LV_MATH_ABS(x_end[2] - x_start[2]), color, opa);
}
if(x_start[3] != LV_COORD_MIN) {
if(x_end[3] == LV_COORD_MIN) x_end[3] = xi - 1;
if(x_end[3] == LV_COORD_MIN) x_end[3] = xe - 1;
hor_line(center_x - x_end[3], center_y - yi, mask, LV_MATH_ABS(x_end[3] - x_start[3]), color, opa);
}
#if LV_ANTIALIAS
/*TODO*/
#endif
}
}

View File

@@ -252,6 +252,7 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0');
if(g_ret == false) return;
lv_coord_t pos_x = pos_p->x + g.ofs_x;
lv_coord_t pos_y = pos_p->y + (font_p->line_height - font_p->base_line) - g.box_h - g.ofs_y;
@@ -300,17 +301,32 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
if(g.box_w & 0x7) width_byte_scr++;
uint16_t width_bit = g.box_w * g.bpp; /*Letter width in bits*/
bool subpx = font_p->subpx == LV_FONT_SUBPX_NONE ? false : true;
/* Calculate the col/row start/end on the map*/
lv_coord_t col_start = pos_x >= mask_p->x1 ? 0 : mask_p->x1 - pos_x;
lv_coord_t col_end = pos_x + g.box_w <= mask_p->x2 ? g.box_w : mask_p->x2 - pos_x + 1;
lv_coord_t row_start = pos_y >= mask_p->y1 ? 0 : mask_p->y1 - pos_y;
lv_coord_t row_end = pos_y + g.box_h <= mask_p->y2 ? g.box_h : mask_p->y2 - pos_y + 1;
lv_coord_t col_start;
lv_coord_t col_end;
lv_coord_t row_start;
lv_coord_t row_end;
if(subpx == false) {
col_start = pos_x >= mask_p->x1 ? 0 : mask_p->x1 - pos_x;
col_end = pos_x + g.box_w <= mask_p->x2 ? g.box_w : mask_p->x2 - pos_x + 1;
row_start = pos_y >= mask_p->y1 ? 0 : mask_p->y1 - pos_y;
row_end = pos_y + g.box_h <= mask_p->y2 ? g.box_h : mask_p->y2 - pos_y + 1;
} else {
col_start = pos_x >= mask_p->x1 ? 0 : (mask_p->x1 - pos_x) * 3;
col_end = pos_x + g.box_w / 3 <= mask_p->x2 ? g.box_w : (mask_p->x2 - pos_x + 1) * 3;
row_start = pos_y >= mask_p->y1 ? 0 : mask_p->y1 - pos_y;
row_end = pos_y + g.box_h <= mask_p->y2 ? g.box_h : mask_p->y2 - pos_y + 1;
}
/*Set a pointer on VDB to the first pixel of the letter*/
vdb_buf_tmp += ((pos_y - vdb->area.y1) * vdb_width) + pos_x - vdb->area.x1;
/*If the letter is partially out of mask the move there on VDB*/
vdb_buf_tmp += (row_start * vdb_width) + col_start;
if(subpx) vdb_buf_tmp += (row_start * vdb_width) + col_start / 3;
else vdb_buf_tmp += (row_start * vdb_width) + col_start;
/*Move on the map too*/
uint32_t bit_ofs = (row_start * width_bit) + (col_start * g.bpp);
@@ -326,37 +342,107 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
scr_transp = disp->driver.screen_transp;
#endif
uint8_t font_rgb[3];
#if LV_COLOR_16_SWAP == 0
uint8_t txt_rgb[3] = {color.ch.red, color.ch.green, color.ch.blue};
#else
uint8_t txt_rgb[3] = {color.ch.red, (color.ch.green_h << 3) + color.ch.green_l, color.ch.blue};
#endif
for(row = row_start; row < row_end; row++) {
bitmask = bitmask_init >> col_bit;
uint8_t sub_px_cnt = 0;
for(col = col_start; col < col_end; col++) {
letter_px = (*map_p & bitmask) >> (8 - col_bit - g.bpp);
if(letter_px != 0) {
if(opa == LV_OPA_COVER) {
px_opa = g.bpp == 8 ? letter_px : bpp_opa_table[letter_px];
} else {
px_opa = g.bpp == 8 ? (uint16_t)((uint16_t)letter_px * opa) >> 8
: (uint16_t)((uint16_t)bpp_opa_table[letter_px] * opa) >> 8;
}
if(disp->driver.set_px_cb) {
disp->driver.set_px_cb(&disp->driver, (uint8_t *)vdb->buf_act, vdb_width,
(col + pos_x) - vdb->area.x1, (row + pos_y) - vdb->area.y1, color, px_opa);
} else if(vdb_buf_tmp->full != color.full) {
if(px_opa > LV_OPA_MAX)
*vdb_buf_tmp = color;
else if(px_opa > LV_OPA_MIN) {
if(scr_transp == false) {
*vdb_buf_tmp = lv_color_mix(color, *vdb_buf_tmp, px_opa);
} else {
/*subpx == 0*/
if(subpx == false) {
if(letter_px != 0) {
if(opa == LV_OPA_COVER) {
px_opa = g.bpp == 8 ? letter_px : bpp_opa_table[letter_px];
} else {
px_opa = g.bpp == 8 ? (uint16_t)((uint16_t)letter_px * opa) >> 8
: (uint16_t)((uint16_t)bpp_opa_table[letter_px] * opa) >> 8;
}
if(disp->driver.set_px_cb) {
disp->driver.set_px_cb(&disp->driver, (uint8_t *)vdb->buf_act, vdb_width,
(col + pos_x) - vdb->area.x1, (row + pos_y) - vdb->area.y1, color, px_opa);
} else if(vdb_buf_tmp->full != color.full) {
if(px_opa > LV_OPA_MAX) {
*vdb_buf_tmp = color;
} else if(px_opa > LV_OPA_MIN) {
if(scr_transp == false) {
*vdb_buf_tmp = lv_color_mix(color, *vdb_buf_tmp, px_opa);
} else {
#if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP
*vdb_buf_tmp = color_mix_2_alpha(*vdb_buf_tmp, (*vdb_buf_tmp).ch.alpha, color, px_opa);
*vdb_buf_tmp = color_mix_2_alpha(*vdb_buf_tmp, (*vdb_buf_tmp).ch.alpha, color, px_opa);
#endif
}
}
}
}
vdb_buf_tmp++;
}
/*Handle subpx drawing*/
else {
if(letter_px != 0) {
if(opa == LV_OPA_COVER) {
px_opa = g.bpp == 8 ? letter_px : bpp_opa_table[letter_px];
} else {
px_opa = g.bpp == 8 ? (uint16_t)((uint16_t)letter_px * opa) >> 8
: (uint16_t)((uint16_t)bpp_opa_table[letter_px] * opa) >> 8;
}
font_rgb[sub_px_cnt] = px_opa;
} else {
font_rgb[sub_px_cnt] = 0;
}
sub_px_cnt ++;
if(sub_px_cnt == 3) {
lv_color_t res_color;
if(font_rgb[0] == 0 && font_rgb[1] == 0 && font_rgb[2] == 0) {
res_color = *vdb_buf_tmp;
} else {
#if LV_COLOR_16_SWAP == 0
uint8_t bg_rgb[3] = {vdb_buf_tmp->ch.red, vdb_buf_tmp->ch.green, vdb_buf_tmp->ch.blue};
#else
uint8_t bg_rgb[3] = {vdb_buf_tmp->ch.red,
(vdb_buf_tmp->ch.green_h << 3) + vdb_buf_tmp->ch.green_l,
vdb_buf_tmp->ch.blue};
#endif
#if LV_SUBPX_BGR
res_color.ch.blue = (uint16_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[2] * (255 - font_rgb[0]))) >> 8;
res_color.ch.green = (uint16_t)((uint16_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8;
res_color.ch.red = (uint16_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[0] * (255 - font_rgb[2]))) >> 8;
#else
res_color.ch.red = (uint16_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8;
#if LV_COLOR_16_SWAP == 0
res_color.ch.green = (uint16_t)((uint16_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8;
#else
uint8_t green = (uint16_t)((uint16_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8;
res_color.ch.green_h = green >> 3;
res_color.ch.green_l = green & 0x7;
#endif
res_color.ch.blue = (uint16_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8;
#endif
}
if(scr_transp == false) {
vdb_buf_tmp->full = res_color.full;
#if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP
} else {
*vdb_buf_tmp = color_mix_2_alpha(*vdb_buf_tmp, (*vdb_buf_tmp).ch.alpha, color, px_opa);
#endif
}
sub_px_cnt = 0;
vdb_buf_tmp++;
}
}
vdb_buf_tmp++;
if(col_bit < 8 - g.bpp) {
col_bit += g.bpp;
@@ -367,11 +453,15 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
map_p++;
}
}
col_bit += ((g.box_w - col_end) + col_start) * g.bpp;
map_p += (col_bit >> 3);
col_bit = col_bit & 0x7;
vdb_buf_tmp += vdb_width - (col_end - col_start); /*Next row in VDB*/
/*Next row in VDB*/
if(subpx) vdb_buf_tmp += vdb_width - (col_end - col_start) / 3;
else vdb_buf_tmp += vdb_width - (col_end - col_start);
}
}

View File

@@ -53,7 +53,18 @@ typedef struct
uint8_t bpp; /**< Bit-per-pixel: 1, 2, 4, 8*/
}lv_font_glyph_dsc_t;
/*Describe the properties of a font*/
/** The bitmaps might be upscaled by 3 to achieve subpixel rendering. */
enum {
LV_FONT_SUBPX_NONE,
LV_FONT_SUBPX_HOR,
LV_FONT_SUBPX_VER,
LV_FONT_SUBPX_BOTH,
};
typedef uint8_t lv_font_subpx_t;
/** Describe the properties of a font*/
typedef struct _lv_font_struct
{
/** Get a glyph's descriptor from a font*/
@@ -65,10 +76,13 @@ typedef struct _lv_font_struct
/*Pointer to the font in a font pack (must have the same line height)*/
uint8_t line_height; /**< The real line height where any text fits*/
uint8_t base_line; /**< Base line measured from the top of the line_height*/
uint8_t subpx :2; /**< An element of `lv_font_subpx_t`*/
void * dsc; /**< Store implementation specific data here*/
#if LV_USE_USER_DATA
lv_font_user_data_t user_data; /**< Custom user data for font. */
#endif
} lv_font_t;
/**********************

View File

@@ -140,7 +140,9 @@ bool lv_font_get_glyph_dsc_fmt_txt(const lv_font_t * font, lv_font_glyph_dsc_t *
/*Put together a glyph dsc*/
const lv_font_fmt_txt_glyph_dsc_t * gdsc = &fdsc->glyph_dsc[gid];
uint32_t adv_w = gdsc->adv_w + ((int32_t)((int32_t)kvalue * fdsc->kern_scale) >> 4);
int32_t kv = ((int32_t)((int32_t)kvalue * fdsc->kern_scale) >> 4);
uint32_t adv_w = gdsc->adv_w + kv;
adv_w = (adv_w + (1 << 3)) >> 4;
dsc_out->adv_w = adv_w;

View File

@@ -191,6 +191,7 @@ typedef struct {
* from `lv_font_fmt_txt_bitmap_format_t`
*/
uint16_t bitmap_format :2;
uint16_t subpx :1;
/*Cache the last letter and is glyph id*/
uint32_t last_letter;

View File

@@ -303,21 +303,44 @@ static inline uint32_t lv_color_to32(lv_color_t color)
ret.ch.alpha = 0xFF;
return ret.full;
#elif LV_COLOR_DEPTH == 16
/**
* The floating point math for conversion is:
* valueto = valuefrom * ( (2^bitsto - 1) / (float)(2^bitsfrom - 1) )
* The faster integer math for conversion is:
* valueto = ( valuefrom * multiplier + adder ) >> divisor
* multiplier = FLOOR( ( (2^bitsto - 1) << divisor ) / (float)(2^bitsfrom - 1) )
*
* Find the first divisor where ( adder >> divisor ) <= 0
*
* 5-bit to 8-bit: ( 31 * multiplier + adder ) >> divisor = 255
* divisor multiplier adder min (0) max (31)
* 0 8 7 7 255
* 1 16 14 7 255
* 2 32 28 7 255
* 3 65 25 3 255
* 4 131 19 1 255
* 5 263 7 0 255
*
* 6-bit to 8-bit: 255 = ( 63 * multiplier + adder ) >> divisor
* divisor multiplier adder min (0) max (63)
* 0 4 3 3 255
* 1 8 6 3 255
* 2 16 12 3 255
* 3 32 24 3 255
* 4 64 48 3 255
* 5 129 33 1 255
* 6 259 3 0 255
*/
lv_color32_t ret;
ret.ch.red = ( color.ch.red * 263 + 7 ) >> 5;
#if LV_COLOR_16_SWAP == 0
lv_color32_t ret;
ret.ch.red = color.ch.red * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
ret.ch.green = color.ch.green * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/
ret.ch.blue = color.ch.blue * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
ret.ch.alpha = 0xFF;
return ret.full;
ret.ch.green = ( color.ch.green * 259 + 3 ) >> 6;
#else
lv_color32_t ret;
ret.ch.red = color.ch.red * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
ret.ch.green = ((color.ch.green_h << 3) + color.ch.green_l) * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/
ret.ch.blue = color.ch.blue * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
ret.ch.green = (((color.ch.green_h << 3) + color.ch.green_l) * 259 + 3 ) >> 6;
#endif
ret.ch.blue = ( color.ch.blue * 263 + 7 ) >> 5;
ret.ch.alpha = 0xFF;
return ret.full;
#endif
#elif LV_COLOR_DEPTH == 32
return color.full;
#endif

View File

@@ -176,26 +176,26 @@ uint16_t lv_atan2(int x, int y)
}
/**
* Calculate the sqrt of an integer.
* @param x
* @return the sqrt of x
* Calculate the integer square root of a number.
* @param num
* @return square root of 'num'
*/
uint16_t lv_sqrt(uint32_t x)
uint32_t lv_sqrt(uint32_t num)
{
uint16_t res=0;
uint16_t add= 0x8000;
int i;
for(i=0;i<16;i++)
{
uint16_t temp=res | add;
uint32_t g2=temp*temp;
if (x>=g2)
{
res=temp;
// http://www.codecodex.com/wiki/Calculate_an_integer_square_root#C
uint32_t root = 0;
uint32_t place = 0x40000000;
while(place > num) place >>= 2;
while(place) {
if(num >= root + place) {
num -= root + place;
root += (place << 1);
}
add>>=1;
root >>= 1;
place >>= 2;
}
return res;
return root;
}
/**********************

View File

@@ -63,11 +63,11 @@ int32_t lv_bezier3(uint32_t t, int32_t u0, int32_t u1, int32_t u2, int32_t u3);
uint16_t lv_atan2(int x, int y);
/**
* Calculate the sqrt of an integer.
* @param x
* @return the sqrt of x
* Calculate the integer square root of a number.
* @param num
* @return square root of 'num'
*/
uint16_t lv_sqrt(uint32_t x);
uint32_t lv_sqrt(uint32_t num);
/**********************
* MACROS

View File

@@ -855,6 +855,12 @@ static lv_res_t lv_btnm_signal(lv_obj_t * btnm, lv_signal_t sign, void * param)
#if LV_USE_GROUP
lv_indev_t * indev = lv_indev_get_act();
lv_indev_type_t indev_type = lv_indev_get_type(indev);
/*If not focused by an input device assume the last input device*/
if(indev_type == LV_INDEV_TYPE_NONE) {
indev_type = lv_indev_get_type(lv_indev_get_next(NULL));
}
if(indev_type == LV_INDEV_TYPE_POINTER) {
/*Select the clicked button*/
lv_point_t p1;

View File

@@ -950,6 +950,8 @@ static void next_color_mode(lv_obj_t * cpicker)
static void refr_indic_pos(lv_obj_t * cpicker)
{
invalidate_indic(cpicker);
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker);
lv_coord_t w = lv_obj_get_width(cpicker);
lv_coord_t h = lv_obj_get_height(cpicker);

View File

@@ -750,9 +750,12 @@ static lv_res_t lv_tabview_signal(lv_obj_t * tabview, lv_signal_t sign, void * p
}
if(sign == LV_SIGNAL_FOCUS) {
lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act());
/*If not focused by an input device assume the last input device*/
if(indev_type == LV_INDEV_TYPE_NONE) {
indev_type = lv_indev_get_type(lv_indev_get_next(NULL));
}
/*With ENCODER select the first button only in edit mode*/
if(indev_type == LV_INDEV_TYPE_ENCODER) {
#if LV_USE_GROUP