1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

improve states and focus handling

This commit is contained in:
Gabor Kiss-Vamosi 2020-01-28 22:15:45 +01:00
parent e7af52be14
commit 286491b847
11 changed files with 90 additions and 74 deletions

View File

@ -64,7 +64,7 @@ static lv_obj_t * indev_obj_act = NULL;
*/
void lv_indev_init(void)
{
lv_indev_reset(NULL); /*Reset all input devices*/
lv_indev_reset(NULL, NULL); /*Reset all input devices*/
}
/**
@ -145,19 +145,26 @@ lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev)
return indev->driver.type;
}
/**
* Reset one or all input devices
* @param indev pointer to an input device to reset or NULL to reset all of them
* @param obj pointer to an object which triggers the reset.
*/
void lv_indev_reset(lv_indev_t * indev)
void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj)
{
if(indev)
if(indev) {
indev->proc.reset_query = 1;
else {
if(obj == NULL || indev->proc.types.pointer.last_pressed == obj) {
indev->proc.types.pointer.last_pressed = NULL;
}
} else {
lv_indev_t * i = lv_indev_get_next(NULL);
while(i) {
i->proc.reset_query = 1;
if(obj == NULL || i->proc.types.pointer.last_pressed == obj) {
i->proc.types.pointer.last_pressed = NULL;
}
i = lv_indev_get_next(i);
}
}
@ -938,7 +945,8 @@ static void indev_proc_release(lv_indev_proc_t * proc)
if(indev_reset_check(proc)) return;
/*Handle click focus*/
if(lv_obj_is_protected(indev_obj_act, LV_PROTECT_CLICK_FOCUS) == false) {
if(lv_obj_is_protected(indev_obj_act, LV_PROTECT_CLICK_FOCUS) == false &&
proc->types.pointer.last_pressed != indev_obj_act) {
#if LV_USE_GROUP
lv_group_t * g_act = lv_obj_get_group(indev_obj_act);
lv_group_t * g_prev = proc->types.pointer.last_pressed ? lv_obj_get_group(proc->types.pointer.last_pressed) : NULL;
@ -967,11 +975,18 @@ static void indev_proc_release(lv_indev_proc_t * proc)
}
/*The object are not in the same group (in different group or one in not a group)*/
else {
/*Leave the object focused in the previous group and focus to the act. its group*/
/*Focus to the act. its group*/
if(g_act) {
lv_group_focus_obj(indev_obj_act);
if(indev_reset_check(proc)) return;
}
/*If the prev. obj. is not in a group then defocus it.*/
if(g_prev == NULL && proc->types.pointer.last_pressed) {
lv_signal_send(proc->types.pointer.last_pressed, LV_SIGNAL_DEFOCUS, NULL);
if(indev_reset_check(proc)) return;
lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, NULL);
if(indev_reset_check(proc)) return;
}
/*Focus on a non-group object*/
else {
if(proc->types.pointer.last_pressed) {
@ -1051,7 +1066,6 @@ static void indev_proc_reset_query_handler(lv_indev_t * indev)
if(indev->proc.reset_query) {
indev->proc.types.pointer.act_obj = NULL;
indev->proc.types.pointer.last_obj = NULL;
indev->proc.types.pointer.last_pressed = NULL;
indev->proc.types.pointer.drag_limit_out = 0;
indev->proc.types.pointer.drag_in_prog = 0;
indev->proc.long_pr_sent = 0;
@ -1398,7 +1412,7 @@ static void indev_gesture(lv_indev_proc_t * proc)
/**
* Checks if the reset_query flag has been set. If so, perform necessary global indev cleanup actions
* @param proc pointer to an input device 'proc'
* return true if indev query should be immediately truncated.
* @return true if indev query should be immediately truncated.
*/
static bool indev_reset_check(lv_indev_proc_t * proc)
{

View File

@ -57,8 +57,9 @@ lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev);
/**
* Reset one or all input devices
* @param indev pointer to an input device to reset or NULL to reset all of them
* @param obj pointer to an object which triggers the reset.
*/
void lv_indev_reset(lv_indev_t * indev);
void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj);
/**
* Reset the long press state of an input device

View File

@ -409,7 +409,7 @@ lv_res_t lv_obj_del(lv_obj_t * obj)
lv_indev_t * indev = lv_indev_get_next(NULL);
while(indev) {
if(indev->proc.types.pointer.act_obj == obj || indev->proc.types.pointer.last_obj == obj) {
lv_indev_reset(indev);
lv_indev_reset(indev, obj);
}
if(indev->proc.types.pointer.last_pressed == obj) {
indev->proc.types.pointer.last_pressed = NULL;
@ -417,7 +417,7 @@ lv_res_t lv_obj_del(lv_obj_t * obj)
#if LV_USE_GROUP
if(indev->group == group && obj == lv_indev_get_obj_act()) {
lv_indev_reset(indev);
lv_indev_reset(indev, obj);
}
#endif
indev = lv_indev_get_next(indev);
@ -1454,33 +1454,42 @@ void lv_obj_clear_protect(lv_obj_t * obj, uint8_t prot)
obj->protect &= prot;
}
void lv_obj_set_state(lv_obj_t * obj, lv_obj_state_t state)
void lv_obj_set_state(lv_obj_t * obj, lv_obj_state_t new_state)
{
if(obj->state_dsc.act == new_state) return;
LV_ASSERT_OBJ(obj, LV_OBJX_NAME);
lv_style_int_t t = lv_obj_get_style_int(obj, LV_OBJ_PART_MAIN, LV_STYLE_TRANSITION_TIME);
if(t == 0) {
lv_anim_del(obj, obj_state_anim_cb);
obj->state_dsc.act = new_state;
obj->state_dsc.prev = new_state;
obj->state_dsc.anim = 0;
lv_obj_refresh_style(obj);
}
/*Set the new state for prev state too to get the TRANSITION_TIME for the new state*/
else {
obj->state_dsc.prev = obj->state_dsc.act;
obj->state_dsc.act = new_state;
obj->state_dsc.anim = 0;
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_exec_cb(&a, obj, obj_state_anim_cb);
lv_anim_set_values(&a, 0, 255);
lv_anim_set_time(&a, t, 0);
lv_anim_create(&a);
}
}
void lv_obj_add_state(lv_obj_t * obj, lv_obj_state_t state)
{
LV_ASSERT_OBJ(obj, LV_OBJX_NAME);
lv_obj_state_t new_state = obj->state_dsc.act | state;
if(obj->state_dsc.act != new_state) {
lv_style_int_t t = lv_obj_get_style_int(obj, LV_OBJ_PART_MAIN, LV_STYLE_TRANSITION_TIME);
if(t == 0) {
lv_anim_del(obj, obj_state_anim_cb);
obj->state_dsc.act = new_state;
obj->state_dsc.prev = new_state;
obj->state_dsc.anim = 0;
lv_obj_refresh_style(obj);
}
/*Set the new state for prev state too to get the TRANSITION_TIME for the new state*/
else {
obj->state_dsc.prev = obj->state_dsc.act;
obj->state_dsc.act = new_state;
obj->state_dsc.anim = 0;
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_exec_cb(&a, obj, obj_state_anim_cb);
lv_anim_set_values(&a, 0, 255);
lv_anim_set_time(&a, t, 0);
lv_anim_create(&a);
}
lv_obj_set_state(obj, new_state);
}
}
@ -1490,27 +1499,7 @@ void lv_obj_clear_state(lv_obj_t * obj, lv_obj_state_t state)
lv_obj_state_t new_state = obj->state_dsc.act & (~state);
if(obj->state_dsc.act != new_state) {
lv_style_int_t t = lv_obj_get_style_int(obj, LV_OBJ_PART_MAIN, LV_STYLE_TRANSITION_TIME);
if(t == 0) {
lv_anim_del(obj, obj_state_anim_cb);
obj->state_dsc.act = new_state;
obj->state_dsc.prev = new_state;
obj->state_dsc.anim = 0;
lv_obj_refresh_style(obj);
}
/*Set the new state for prev state too to get the TRANSITION_TIME for the new state*/
else {
obj->state_dsc.prev = obj->state_dsc.act;
obj->state_dsc.act = new_state;
obj->state_dsc.anim = 0;
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_exec_cb(&a, obj, obj_state_anim_cb);
lv_anim_set_values(&a, 0, 255);
lv_anim_set_time(&a, t, 0);
lv_anim_create(&a);
}
lv_obj_set_state(obj, new_state);
}
}
/**
@ -2889,9 +2878,9 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param)
if(lv_group_get_editing(lv_obj_get_group(obj))) {
uint8_t state = LV_OBJ_STATE_FOCUS;
state |= LV_OBJ_STATE_EDIT;
lv_obj_set_state(obj, state);
lv_obj_add_state(obj, state);
} else {
lv_obj_set_state(obj, LV_OBJ_STATE_FOCUS);
lv_obj_add_state(obj, LV_OBJ_STATE_FOCUS);
lv_obj_clear_state(obj, LV_OBJ_STATE_EDIT);
}
} else if(sign == LV_SIGNAL_DEFOCUS) {
@ -3025,7 +3014,7 @@ static void delete_children(lv_obj_t * obj)
lv_indev_t * indev = lv_indev_get_next(NULL);
while(indev) {
if(indev->proc.types.pointer.act_obj == obj || indev->proc.types.pointer.last_obj == obj) {
lv_indev_reset(indev);
lv_indev_reset(indev, obj);
}
if(indev->proc.types.pointer.last_pressed == obj) {
@ -3033,7 +3022,7 @@ static void delete_children(lv_obj_t * obj)
}
#if LV_USE_GROUP
if(indev->group == group && obj == lv_indev_get_obj_act()) {
lv_indev_reset(indev);
lv_indev_reset(indev, obj);
}
#endif
indev = lv_indev_get_next(indev);

View File

@ -641,6 +641,8 @@ void lv_obj_clear_protect(lv_obj_t * obj, uint8_t prot);
void lv_obj_set_state(lv_obj_t * obj, lv_obj_state_t state);
void lv_obj_add_state(lv_obj_t * obj, lv_obj_state_t state);
void lv_obj_clear_state(lv_obj_t * obj, lv_obj_state_t state);
/**

View File

@ -156,7 +156,7 @@ enum {
LV_STYLE_STATE_HOVER = (1 << (3 + LV_STYLE_STATE_POS)),
LV_STYLE_STATE_PRESSED = (1 << (4 + LV_STYLE_STATE_POS)),
LV_STYLE_STATE_DISABLED = (1 << (6 + LV_STYLE_STATE_POS)),
LV_STYLE_STATE_ALL = (0x7F << LV_STYLE_STATE_POS)
LV_STYLE_STATE_ALL = (0x7F << LV_STYLE_STATE_POS),
};
typedef uint16_t lv_style_state_t;

View File

@ -138,17 +138,17 @@ void lv_btn_set_state(lv_obj_t * btn, lv_btn_state_t state)
break;
case LV_BTN_STATE_PR:
lv_obj_clear_state(btn, LV_OBJ_STATE_CHECKED);
lv_obj_set_state(btn, LV_OBJ_STATE_PRESSED);
lv_obj_add_state(btn, LV_OBJ_STATE_PRESSED);
break;
case LV_BTN_STATE_TGL_REL:
lv_obj_set_state(btn, LV_OBJ_STATE_CHECKED);
lv_obj_add_state(btn, LV_OBJ_STATE_CHECKED);
lv_obj_clear_state(btn, LV_OBJ_STATE_PRESSED);
break;
case LV_BTN_STATE_TGL_PR:
lv_obj_set_state(btn, LV_OBJ_STATE_PRESSED | LV_OBJ_STATE_CHECKED);
lv_obj_add_state(btn, LV_OBJ_STATE_PRESSED | LV_OBJ_STATE_CHECKED);
break;
case LV_BTN_STATE_INA:
lv_obj_set_state(btn, LV_OBJ_STATE_DISABLED);
lv_obj_add_state(btn, LV_OBJ_STATE_DISABLED);
break;
}
@ -169,7 +169,7 @@ void lv_btn_toggle(lv_obj_t * btn)
if(lv_obj_get_state(btn, LV_BTN_PART_MAIN) & LV_OBJ_STATE_CHECKED) {
lv_obj_clear_state(btn, LV_OBJ_STATE_CHECKED);
} else {
lv_obj_set_state(btn, LV_OBJ_STATE_CHECKED);
lv_obj_add_state(btn, LV_OBJ_STATE_CHECKED);
}
}

View File

@ -677,16 +677,19 @@ static lv_design_res_t lv_btnm_design(lv_obj_t * btnm, const lv_area_t * clip_ar
}
/*Focused and/or pressed + checked or released button*/
else {
btnm->state_dsc.act = LV_OBJ_STATE_NORMAL;
if(tgl_state) btnm->state_dsc.act = LV_OBJ_STATE_CHECKED;
if(ext->btn_id_pr == btn_i) btnm->state_dsc.act |= LV_OBJ_STATE_PRESSED;
if(ext->btn_id_focused == btn_i) btnm->state_dsc.act |= LV_OBJ_STATE_FOCUS;
btnm->state_dsc.prev = btnm->state_dsc.act;
lv_draw_rect_dsc_init(&draw_rect_tmp_dsc);
lv_draw_label_dsc_init(&draw_label_tmp_dsc);
lv_obj_init_draw_rect_dsc(btnm, LV_BTNM_PART_BTN, &draw_rect_tmp_dsc);
lv_obj_init_draw_label_dsc(btnm, LV_BTNM_PART_BTN, &draw_label_tmp_dsc);
draw_rect_dsc_act = &draw_rect_tmp_dsc;
draw_label_dsc_act = &draw_label_tmp_dsc;
btnm->state_dsc = state_ori;
}
@ -850,7 +853,7 @@ static lv_res_t lv_btnm_signal(lv_obj_t * btnm, lv_signal_t sign, void * param)
res = lv_event_send(btnm, LV_EVENT_VALUE_CHANGED, &b);
}
}
} else if(sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_DEFOCUS) {
} else if(sign == LV_SIGNAL_PRESS_LOST) {
ext->btn_id_pr = LV_BTNM_BTN_NONE;
ext->btn_id_act = LV_BTNM_BTN_NONE;
lv_obj_invalidate(btnm);

View File

@ -181,10 +181,13 @@ static lv_res_t lv_cb_signal(lv_obj_t * cb, lv_signal_t sign, void * param)
const lv_font_t * font = lv_obj_get_style_ptr(ext->label, LV_LABEL_PART_MAIN, LV_STYLE_FONT);
lv_coord_t line_height = lv_font_get_line_height(font);
lv_obj_set_size(ext->bullet, line_height, line_height);
lv_btn_set_state(ext->bullet, lv_btn_get_state(cb));
} else if(sign == LV_SIGNAL_PRESSED || sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) {
lv_btn_set_state(ext->bullet, lv_btn_get_state(cb));
} else if(sign == LV_SIGNAL_CONTROL) {
lv_obj_set_state(ext->bullet, lv_obj_get_state(cb, LV_CB_PART_BG));
} else if(sign == LV_SIGNAL_PRESSED || sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST ||
sign == LV_SIGNAL_FOCUS || sign == LV_SIGNAL_DEFOCUS) {
lv_obj_set_state(ext->bullet, lv_obj_get_state(cb, LV_CB_PART_BG));
} else if(sign == LV_SIGNAL_PRESSED || sign == LV_SIGNAL_RELEASED) {
}else if(sign == LV_SIGNAL_CONTROL) {
char c = *((char *)param);
if(c == LV_KEY_RIGHT || c == LV_KEY_DOWN || c == LV_KEY_LEFT || c == LV_KEY_UP) {
/*Follow the backgrounds state with the bullet*/

View File

@ -49,8 +49,8 @@ typedef struct
/** Checkbox styles. */
enum {
LV_CB_PART_BG, /**< Style of object background. */
LV_CB_PART_BULLET, /**< Style of box (released). */
LV_CB_PART_BG = LV_BTN_PART_MAIN, /**< Style of object background. */
LV_CB_PART_BULLET = _LV_BTN_PART_REAL_LAST, /**< Style of box (released). */
};
typedef uint8_t lv_cb_style_t;

View File

@ -127,7 +127,7 @@ void lv_sw_on(lv_obj_t * sw, lv_anim_enable_t anim)
lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
ext->state = 1;
lv_bar_set_value(sw, 1, anim);
lv_obj_set_state(sw, LV_OBJ_STATE_CHECKED);
lv_obj_add_state(sw, LV_OBJ_STATE_CHECKED);
}
/**

View File

@ -235,6 +235,7 @@ static void slider_init(void)
lv_style_set_int(&slider_knob, LV_STYLE_PAD_BOTTOM, LV_DPI/20);
lv_style_set_int(&slider_knob, LV_STYLE_PAD_LEFT, LV_DPI/20);
lv_style_set_int(&slider_knob, LV_STYLE_PAD_RIGHT, LV_DPI/20);
lv_style_set_color(&slider_knob, LV_STYLE_BG_COLOR | LV_STYLE_STATE_FOCUS, LV_COLOR_RED);
#endif
}
@ -249,6 +250,7 @@ static void sw_init(void)
lv_style_set_int(&sw_knob, LV_STYLE_PAD_BOTTOM, - LV_DPI/20);
lv_style_set_int(&sw_knob, LV_STYLE_PAD_LEFT, - LV_DPI/20);
lv_style_set_int(&sw_knob, LV_STYLE_PAD_RIGHT, - LV_DPI/20);
lv_style_set_color(&sw_knob, LV_STYLE_BG_COLOR | LV_STYLE_STATE_FOCUS, LV_COLOR_RED);
#endif
}
@ -363,10 +365,12 @@ static void cb_init(void)
lv_style_set_int(&cb_bullet, LV_STYLE_BORDER_WIDTH , 2);
lv_style_set_color(&cb_bullet, LV_STYLE_BORDER_COLOR , lv_color_hex(0x52555a));
lv_style_set_color(&cb_bullet, LV_STYLE_BORDER_COLOR | LV_STYLE_STATE_PRESSED , lv_color_darken(lv_color_hex(0x52555a), LV_OPA_30));
lv_style_set_color(&cb_bullet, LV_STYLE_BORDER_COLOR | LV_STYLE_STATE_FOCUS, LV_COLOR_RED);
lv_style_set_color(&cb_bullet, LV_STYLE_BORDER_COLOR | LV_STYLE_STATE_FOCUS | LV_STYLE_STATE_PRESSED, LV_COLOR_LIME);
lv_style_set_color(&cb_bullet, LV_STYLE_BG_COLOR, COLOR_ACCENT);
lv_style_set_opa(&cb_bullet, LV_STYLE_BG_OPA | LV_STYLE_STATE_CHECKED , LV_OPA_COVER);
lv_style_set_opa(&cb_bullet, LV_STYLE_BORDER_OPA | LV_STYLE_STATE_CHECKED , LV_OPA_80);
lv_style_set_int(&cb_bullet, LV_STYLE_TRANSITION_TIME , 100);
lv_style_set_int(&cb_bullet, LV_STYLE_TRANSITION_TIME , 1000);