diff --git a/src/core/lv_event.h b/src/core/lv_event.h index 20385fee9..d93921dba 100644 --- a/src/core/lv_event.h +++ b/src/core/lv_event.h @@ -51,6 +51,16 @@ typedef enum { LV_EVENT_DEFOCUSED, /**< The object is defocused*/ LV_EVENT_LEAVE, /**< The object is defocused but still selected*/ LV_EVENT_HIT_TEST, /**< Perform advanced hit-testing*/ + LV_EVENT_MOUSE_BTN_RIGHT_CLICKED, /**< The object has been right clicked by mouse button*/ + LV_EVENT_MOUSE_BTN_MIDDLE_CLICKED, /**< The object has been middle clicked by mouse button*/ + LV_EVENT_MOUSE_BTN_4_CLICKED, /**< The object has been clicked by mouse button 4*/ + LV_EVENT_MOUSE_BTN_5_CLICKED, /**< The object has been clicked by mouse button 5*/ + LV_EVENT_MOUSE_BTN_RIGHT_RELEASED, /**< The object has been right click released by mouse button*/ + LV_EVENT_MOUSE_BTN_MIDDLE_RELEASED, /**< The object has been middle click released by mouse button*/ + LV_EVENT_MOUSE_BTN_4_RELEASED, /**< The object has been click released by mouse button 4*/ + LV_EVENT_MOUSE_BTN_5_RELEASED, /**< The object has been click released by mouse button 5*/ + LV_EVENT_MOUSE_SCRL_UP, /**< The object has been scrolled up by mouse wheel*/ + LV_EVENT_MOUSE_SCRL_DN, /**< The object has been scrolled down by mouse wheel*/ /** Drawing events*/ LV_EVENT_COVER_CHECK, /**< Check if the object fully covers an area. The event parameter is `lv_cover_check_info_t *`.*/ diff --git a/src/core/lv_indev.c b/src/core/lv_indev.c index 064464256..ca134c6c6 100644 --- a/src/core/lv_indev.c +++ b/src/core/lv_indev.c @@ -36,6 +36,9 @@ static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data); static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data); static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data); static void indev_proc_press(_lv_indev_proc_t * proc); +static void indev_proc_mouse_press(_lv_indev_proc_t * proc, lv_indev_mouse_data_t *mouse); +static void indev_proc_mouse_release(_lv_indev_proc_t * proc, lv_indev_mouse_data_t *mouse); +static void indev_proc_mouse_scroll(_lv_indev_proc_t * proc, lv_indev_scroll_state_t dir); static void indev_proc_release(_lv_indev_proc_t * proc); static void indev_proc_reset_query_handler(lv_indev_t * indev); static void indev_click_focus(_lv_indev_proc_t * proc); @@ -384,6 +387,25 @@ static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data) indev_proc_release(&i->proc); } + if(data->mouse.btn_right == LV_INDEV_STATE_PRESSED || + data->mouse.btn_middle == LV_INDEV_STATE_PRESSED || + data->mouse.btn_4 == LV_INDEV_STATE_PRESSED || + data->mouse.btn_4 == LV_INDEV_STATE_PRESSED) { + indev_proc_mouse_press(&i->proc, &data->mouse); + } + if(data->mouse.btn_right == LV_INDEV_STATE_RELEASED || + data->mouse.btn_middle == LV_INDEV_STATE_RELEASED || + data->mouse.btn_4 == LV_INDEV_STATE_RELEASED || + data->mouse.btn_4 == LV_INDEV_STATE_RELEASED) { + indev_proc_mouse_release(&i->proc, &data->mouse); + } + if(data->mouse.scrl == LV_INDEV_STATE_SCROLL_WHEEL_UP || + data->mouse.scrl == LV_INDEV_STATE_SCROLL_WHEEL_DN) { + indev_proc_mouse_scroll(&i->proc, data->mouse.scrl); + } + + + i->proc.types.pointer.last_point.x = i->proc.types.pointer.act_point.x; i->proc.types.pointer.last_point.y = i->proc.types.pointer.act_point.y; } @@ -809,6 +831,241 @@ static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data) i->proc.types.pointer.last_point.y = i->proc.types.pointer.act_point.y; } +/** + * Process the pressed state of LV_INDEV_TYPE_POINTER input devices with additional mouse buttons + * @param indev pointer to an input device 'proc' + * @param indev mouse data pointer to additional mouse button states + * @return LV_RES_OK: no indev reset required; LV_RES_INV: indev reset is required + */ +static void indev_proc_mouse_press(_lv_indev_proc_t * proc, lv_indev_mouse_data_t *mouse) +{ + /* FIXME: Say which button */ + LV_LOG_INFO("mouse button pressed at x:%d y:%d", (int)proc->types.pointer.act_point.x, + (int)proc->types.pointer.act_point.y); + indev_obj_act = proc->types.pointer.act_obj; + + if(proc->wait_until_release != 0) return; + + lv_disp_t * disp = indev_act->driver->disp; + bool new_obj_searched = false; + + /*If there is no last object then search*/ + if(indev_obj_act == NULL) { + indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point); + if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp), + &proc->types.pointer.act_point); + if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp), + &proc->types.pointer.act_point); + new_obj_searched = true; + } + /*If there is last object but it is not scrolled and not protected also search*/ + else if(proc->types.pointer.scroll_obj == NULL && + lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_PRESS_LOCK) == false) { + indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point); + if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp), + &proc->types.pointer.act_point); + if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp), + &proc->types.pointer.act_point); + new_obj_searched = true; + } + + /*The last object might have scroll throw. Stop it manually*/ + if(new_obj_searched && proc->types.pointer.last_obj) { + proc->types.pointer.scroll_throw_vect.x = 0; + proc->types.pointer.scroll_throw_vect.y = 0; + _lv_indev_scroll_throw_handler(proc); + if(indev_reset_check(proc)) return; + } + + lv_obj_transform_point(indev_obj_act, &proc->types.pointer.act_point, true, true); + + /*If a new object was found reset some variables and send a pressed event handler*/ + if(indev_obj_act != proc->types.pointer.act_obj) { + + proc->types.pointer.act_obj = indev_obj_act; /*Save the pressed object*/ + proc->types.pointer.last_obj = indev_obj_act; + + if(indev_obj_act != NULL) { + + if(indev_reset_check(proc)) return; + + if(indev_act->proc.wait_until_release) return; + + /*Handle focus*/ + indev_click_focus(&indev_act->proc); + if(indev_reset_check(proc)) return; + + } + } + + if(indev_obj_act) { + + if (mouse->btn_right == LV_INDEV_STATE_PRESSED && + proc->types.pointer.mouse_state.btn_right == LV_INDEV_STATE_RELEASED) + { + proc->types.pointer.mouse_state.btn_right = LV_INDEV_STATE_PRESSED; + lv_event_send(indev_obj_act, LV_EVENT_MOUSE_BTN_RIGHT_CLICKED, indev_act); + } + if (mouse->btn_middle == LV_INDEV_STATE_PRESSED && + proc->types.pointer.mouse_state.btn_middle == LV_INDEV_STATE_RELEASED) + { + proc->types.pointer.mouse_state.btn_middle = LV_INDEV_STATE_PRESSED; + lv_event_send(indev_obj_act, LV_EVENT_MOUSE_BTN_MIDDLE_CLICKED, indev_act); + } + if (mouse->btn_4 == LV_INDEV_STATE_PRESSED && + proc->types.pointer.mouse_state.btn_4 == LV_INDEV_STATE_RELEASED) + { + proc->types.pointer.mouse_state.btn_4 = LV_INDEV_STATE_PRESSED; + lv_event_send(indev_obj_act, LV_EVENT_MOUSE_BTN_4_CLICKED, indev_act); + } + if (mouse->btn_5 == LV_INDEV_STATE_PRESSED && + proc->types.pointer.mouse_state.btn_5 == LV_INDEV_STATE_RELEASED) + { + proc->types.pointer.mouse_state.btn_5 = LV_INDEV_STATE_PRESSED; + lv_event_send(indev_obj_act, LV_EVENT_MOUSE_BTN_5_CLICKED, indev_act); + } + + indev_reset_check(proc); + + } +} + +/** + * Process the pressed state of LV_INDEV_TYPE_POINTER input devices with additional mouse buttons + * @param indev pointer to an input device 'proc' + * @param indev mouse data pointer to additional mouse button states + * @return LV_RES_OK: no indev reset required; LV_RES_INV: indev reset is required + */ +static void indev_proc_mouse_release(_lv_indev_proc_t * proc, lv_indev_mouse_data_t *mouse) +{ + indev_obj_act = proc->types.pointer.act_obj; + //lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj; + + /* FIXME: Say which button released */ + LV_LOG_INFO("released"); + + /*Send RELEASE Call the ancestor's event handler and event*/ + if (mouse->btn_right == LV_INDEV_STATE_RELEASED && + proc->types.pointer.mouse_state.btn_right == LV_INDEV_STATE_PRESSED) + { + proc->types.pointer.mouse_state.btn_right = LV_INDEV_STATE_RELEASED; + lv_event_send(indev_obj_act, LV_EVENT_MOUSE_BTN_RIGHT_RELEASED, indev_act); + } + + if (mouse->btn_middle == LV_INDEV_STATE_RELEASED && + proc->types.pointer.mouse_state.btn_middle == LV_INDEV_STATE_PRESSED) + { + proc->types.pointer.mouse_state.btn_middle = LV_INDEV_STATE_RELEASED; + lv_event_send(indev_obj_act, LV_EVENT_MOUSE_BTN_MIDDLE_RELEASED, indev_act); + } + + if (mouse->btn_4 == LV_INDEV_STATE_RELEASED && + proc->types.pointer.mouse_state.btn_4 == LV_INDEV_STATE_PRESSED) + { + proc->types.pointer.mouse_state.btn_4 = LV_INDEV_STATE_RELEASED; + lv_event_send(indev_obj_act, LV_EVENT_MOUSE_BTN_4_RELEASED, indev_act); + } + + if (mouse->btn_5 == LV_INDEV_STATE_RELEASED && + proc->types.pointer.mouse_state.btn_5 == LV_INDEV_STATE_PRESSED) + { + proc->types.pointer.mouse_state.btn_5 = LV_INDEV_STATE_RELEASED; + lv_event_send(indev_obj_act, LV_EVENT_MOUSE_BTN_5_RELEASED, indev_act); + } + +} + +/** + * Process the pressed state of LV_INDEV_TYPE_POINTER input devices with scroll wheel + * @param indev pointer to an input device 'proc' + * @param indev mouse scroll state direction + * @return LV_RES_OK: no indev reset required; LV_RES_INV: indev reset is required + */ +static void indev_proc_mouse_scroll(_lv_indev_proc_t * proc, lv_indev_scroll_state_t dir) +{ + LV_LOG_INFO("scrolled at x:%d y:%d", (int)proc->types.pointer.act_point.x, + (int)proc->types.pointer.act_point.y); + indev_obj_act = proc->types.pointer.act_obj; + + + lv_disp_t * disp = indev_act->driver->disp; + bool new_obj_searched = false; + + /*If there is no last object then search*/ + if(indev_obj_act == NULL) { + indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point); + if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp), + &proc->types.pointer.act_point); + if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp), + &proc->types.pointer.act_point); + new_obj_searched = true; + } + /*If there is last object but it is not scrolled and not protected also search*/ + else if(proc->types.pointer.scroll_obj == NULL && + lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_PRESS_LOCK) == false) { + indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point); + if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp), + &proc->types.pointer.act_point); + if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp), + &proc->types.pointer.act_point); + new_obj_searched = true; + } + + /*The last object might have scroll throw. Stop it manually*/ + if(new_obj_searched && proc->types.pointer.last_obj) { + proc->types.pointer.scroll_throw_vect.x = 0; + proc->types.pointer.scroll_throw_vect.y = 0; + _lv_indev_scroll_throw_handler(proc); + if(indev_reset_check(proc)) return; + } + + proc->types.pointer.scroll_throw_vect.y = 300; + _lv_indev_scroll_throw_handler(proc); + +#if 0 + lv_obj_transform_point(indev_obj_act, &proc->types.pointer.act_point, true, true); + + /*If a new object was found reset some variables and send a pressed event handler*/ + if(indev_obj_act != proc->types.pointer.act_obj) { + + proc->types.pointer.act_obj = indev_obj_act; /*Save the pressed object*/ + proc->types.pointer.last_obj = indev_obj_act; + + if(indev_obj_act != NULL) { + /*Save the time when the obj pressed to count long press time.*/ + proc->types.pointer.scroll_sum.x = 10; + if (dir == LV_INDEV_STATE_SCROLL_WHEEL_UP) + proc->types.pointer.scroll_dir = LV_DIR_BOTTOM; + else if (dir == LV_INDEV_STATE_SCROLL_WHEEL_DN) + proc->types.pointer.scroll_dir = LV_DIR_TOP; + + /*Handle focus*/ + indev_click_focus(&indev_act->proc); + if(indev_reset_check(proc)) return; + + } + } +#endif + +#if 0 + /*Calculate the vector and apply a low pass filter: new value = 0.5 * old_value + 0.5 * new_value*/ + proc->types.pointer.vect.x = proc->types.pointer.act_point.x - proc->types.pointer.last_point.x; + proc->types.pointer.vect.y = proc->types.pointer.act_point.y - proc->types.pointer.last_point.y; + + proc->types.pointer.scroll_throw_vect.x = (proc->types.pointer.scroll_throw_vect.x + proc->types.pointer.vect.x) / 2; + proc->types.pointer.scroll_throw_vect.y = (proc->types.pointer.scroll_throw_vect.y + proc->types.pointer.vect.y) / 2; + + proc->types.pointer.scroll_throw_vect_ori = proc->types.pointer.scroll_throw_vect; + + if(indev_obj_act) { + + _lv_indev_scroll_handler(proc); + if(indev_reset_check(proc)) return; + + } +#endif +} + /** * Process the pressed state of LV_INDEV_TYPE_POINTER input devices * @param indev pointer to an input device 'proc' diff --git a/src/hal/lv_hal_indev.h b/src/hal/lv_hal_indev.h index ca51a08c2..89868c6d6 100644 --- a/src/hal/lv_hal_indev.h +++ b/src/hal/lv_hal_indev.h @@ -73,9 +73,24 @@ typedef enum { LV_INDEV_STATE_PRESSED } lv_indev_state_t; +typedef enum { + LV_INDEV_STATE_SCROLL_WHEEL_NONE = 0, + LV_INDEV_STATE_SCROLL_WHEEL_UP, + LV_INDEV_STATE_SCROLL_WHEEL_DN +} lv_indev_scroll_state_t; + +typedef struct { + lv_indev_state_t btn_right; + lv_indev_state_t btn_middle; + lv_indev_state_t btn_4; + lv_indev_state_t btn_5; + lv_indev_scroll_state_t scrl; +} lv_indev_mouse_data_t; + /** Data structure passed to an input driver to fill*/ typedef struct { lv_point_t point; /**< For LV_INDEV_TYPE_POINTER the currently pressed point*/ + lv_indev_mouse_data_t mouse; /** For LV_INDEV_TYPE_POINTER to store additional mouse buttons and scroll data*/ 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*/ @@ -147,6 +162,7 @@ typedef struct _lv_indev_proc_t { lv_point_t scroll_sum; /*Count the dragged pixels to check LV_INDEV_DEF_SCROLL_LIMIT*/ lv_point_t scroll_throw_vect; lv_point_t scroll_throw_vect_ori; + lv_indev_mouse_data_t mouse_state; /* Current state of additional mouse buttons*/ struct _lv_obj_t * act_obj; /*The object being pressed*/ struct _lv_obj_t * last_obj; /*The last object which was pressed*/ struct _lv_obj_t * scroll_obj; /*The object being scrolled*/