acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
lv_indev.c (43669B)
1 /** 2 * @file lv_indev.c 3 * 4 */ 5 6 /********************* 7 * INCLUDES 8 ********************/ 9 #include "lv_indev.h" 10 #include "lv_disp.h" 11 #include "lv_obj.h" 12 #include "lv_indev_scroll.h" 13 #include "lv_group.h" 14 #include "lv_refr.h" 15 16 #include "../hal/lv_hal_tick.h" 17 #include "../misc/lv_timer.h" 18 #include "../misc/lv_math.h" 19 20 /********************* 21 * DEFINES 22 *********************/ 23 #if LV_INDEV_DEF_SCROLL_THROW <= 0 24 #warning "LV_INDEV_DRAG_THROW must be greater than 0" 25 #endif 26 27 /********************** 28 * TYPEDEFS 29 **********************/ 30 31 /********************** 32 * STATIC PROTOTYPES 33 **********************/ 34 static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data); 35 static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data); 36 static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data); 37 static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data); 38 static void indev_proc_press(_lv_indev_proc_t * proc); 39 static void indev_proc_release(_lv_indev_proc_t * proc); 40 static void indev_proc_reset_query_handler(lv_indev_t * indev); 41 static void indev_click_focus(_lv_indev_proc_t * proc); 42 static void indev_gesture(_lv_indev_proc_t * proc); 43 static bool indev_reset_check(_lv_indev_proc_t * proc); 44 45 /********************** 46 * STATIC VARIABLES 47 **********************/ 48 static lv_indev_t * indev_act; 49 static lv_obj_t * indev_obj_act = NULL; 50 51 /********************** 52 * MACROS 53 **********************/ 54 #if LV_LOG_TRACE_INDEV 55 #define INDEV_TRACE(...) LV_LOG_TRACE(__VA_ARGS__) 56 #else 57 #define INDEV_TRACE(...) 58 #endif 59 60 /********************** 61 * GLOBAL FUNCTIONS 62 **********************/ 63 64 void lv_indev_read_timer_cb(lv_timer_t * timer) 65 { 66 INDEV_TRACE("begin"); 67 68 lv_indev_data_t data; 69 70 indev_act = timer->user_data; 71 72 /*Read and process all indevs*/ 73 if(indev_act->driver->disp == NULL) return; /*Not assigned to any displays*/ 74 75 /*Handle reset query before processing the point*/ 76 indev_proc_reset_query_handler(indev_act); 77 78 if(indev_act->proc.disabled || 79 indev_act->driver->disp->prev_scr != NULL) return; /*Input disabled or screen animation active*/ 80 bool continue_reading; 81 do { 82 /*Read the data*/ 83 _lv_indev_read(indev_act, &data); 84 continue_reading = data.continue_reading; 85 86 /*The active object might be deleted even in the read function*/ 87 indev_proc_reset_query_handler(indev_act); 88 indev_obj_act = NULL; 89 90 indev_act->proc.state = data.state; 91 92 /*Save the last activity time*/ 93 if(indev_act->proc.state == LV_INDEV_STATE_PRESSED) { 94 indev_act->driver->disp->last_activity_time = lv_tick_get(); 95 } 96 else if(indev_act->driver->type == LV_INDEV_TYPE_ENCODER && data.enc_diff) { 97 indev_act->driver->disp->last_activity_time = lv_tick_get(); 98 } 99 100 if(indev_act->driver->type == LV_INDEV_TYPE_POINTER) { 101 indev_pointer_proc(indev_act, &data); 102 } 103 else if(indev_act->driver->type == LV_INDEV_TYPE_KEYPAD) { 104 indev_keypad_proc(indev_act, &data); 105 } 106 else if(indev_act->driver->type == LV_INDEV_TYPE_ENCODER) { 107 indev_encoder_proc(indev_act, &data); 108 } 109 else if(indev_act->driver->type == LV_INDEV_TYPE_BUTTON) { 110 indev_button_proc(indev_act, &data); 111 } 112 /*Handle reset query if it happened in during processing*/ 113 indev_proc_reset_query_handler(indev_act); 114 } while(continue_reading); 115 116 /*End of indev processing, so no act indev*/ 117 indev_act = NULL; 118 indev_obj_act = NULL; 119 120 INDEV_TRACE("finished"); 121 } 122 123 void lv_indev_enable(lv_indev_t * indev, bool en) 124 { 125 uint8_t enable = en ? 0 : 1; 126 127 if(indev) { 128 indev->proc.disabled = enable; 129 } 130 else { 131 lv_indev_t * i = lv_indev_get_next(NULL); 132 while(i) { 133 i->proc.disabled = enable; 134 i = lv_indev_get_next(i); 135 } 136 } 137 } 138 139 lv_indev_t * lv_indev_get_act(void) 140 { 141 return indev_act; 142 } 143 144 lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev) 145 { 146 if(indev == NULL) return LV_INDEV_TYPE_NONE; 147 148 return indev->driver->type; 149 } 150 151 void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj) 152 { 153 if(indev) { 154 indev->proc.reset_query = 1; 155 if(indev_act == indev) indev_obj_act = NULL; 156 if(indev->driver->type == LV_INDEV_TYPE_POINTER || indev->driver->type == LV_INDEV_TYPE_KEYPAD) { 157 if(obj == NULL || indev->proc.types.pointer.last_pressed == obj) { 158 indev->proc.types.pointer.last_pressed = NULL; 159 } 160 if(obj == NULL || indev->proc.types.pointer.act_obj == obj) { 161 indev->proc.types.pointer.act_obj = NULL; 162 } 163 if(obj == NULL || indev->proc.types.pointer.last_obj == obj) { 164 indev->proc.types.pointer.last_obj = NULL; 165 } 166 } 167 } 168 else { 169 lv_indev_t * i = lv_indev_get_next(NULL); 170 while(i) { 171 i->proc.reset_query = 1; 172 if(i->driver->type == LV_INDEV_TYPE_POINTER || i->driver->type == LV_INDEV_TYPE_KEYPAD) { 173 if(obj == NULL || i->proc.types.pointer.last_pressed == obj) { 174 i->proc.types.pointer.last_pressed = NULL; 175 } 176 if(obj == NULL || i->proc.types.pointer.act_obj == obj) { 177 i->proc.types.pointer.act_obj = NULL; 178 } 179 if(obj == NULL || i->proc.types.pointer.last_obj == obj) { 180 i->proc.types.pointer.last_obj = NULL; 181 } 182 } 183 i = lv_indev_get_next(i); 184 } 185 indev_obj_act = NULL; 186 } 187 } 188 189 void lv_indev_reset_long_press(lv_indev_t * indev) 190 { 191 indev->proc.long_pr_sent = 0; 192 indev->proc.longpr_rep_timestamp = lv_tick_get(); 193 indev->proc.pr_timestamp = lv_tick_get(); 194 } 195 196 void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj) 197 { 198 if(indev->driver->type != LV_INDEV_TYPE_POINTER) return; 199 200 indev->cursor = cur_obj; 201 lv_obj_set_parent(indev->cursor, lv_disp_get_layer_sys(indev->driver->disp)); 202 lv_obj_set_pos(indev->cursor, indev->proc.types.pointer.act_point.x, indev->proc.types.pointer.act_point.y); 203 lv_obj_clear_flag(indev->cursor, LV_OBJ_FLAG_CLICKABLE); 204 lv_obj_add_flag(indev->cursor, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_FLOATING); 205 } 206 207 void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group) 208 { 209 if(indev->driver->type == LV_INDEV_TYPE_KEYPAD || indev->driver->type == LV_INDEV_TYPE_ENCODER) { 210 indev->group = group; 211 } 212 } 213 214 void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[]) 215 { 216 if(indev->driver->type == LV_INDEV_TYPE_BUTTON) { 217 indev->btn_points = points; 218 } 219 } 220 221 void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point) 222 { 223 if(indev == NULL) { 224 point->x = 0; 225 point->y = 0; 226 return; 227 } 228 if(indev->driver->type != LV_INDEV_TYPE_POINTER && indev->driver->type != LV_INDEV_TYPE_BUTTON) { 229 point->x = -1; 230 point->y = -1; 231 } 232 else { 233 point->x = indev->proc.types.pointer.act_point.x; 234 point->y = indev->proc.types.pointer.act_point.y; 235 } 236 } 237 238 lv_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev) 239 { 240 return indev->proc.types.pointer.gesture_dir; 241 } 242 243 uint32_t lv_indev_get_key(const lv_indev_t * indev) 244 { 245 if(indev->driver->type != LV_INDEV_TYPE_KEYPAD) 246 return 0; 247 else 248 return indev->proc.types.keypad.last_key; 249 } 250 251 lv_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev) 252 { 253 if(indev == NULL) return false; 254 if(indev->driver->type != LV_INDEV_TYPE_POINTER && indev->driver->type != LV_INDEV_TYPE_BUTTON) return false; 255 return indev->proc.types.pointer.scroll_dir; 256 } 257 258 lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev) 259 { 260 if(indev == NULL) return NULL; 261 if(indev->driver->type != LV_INDEV_TYPE_POINTER && indev->driver->type != LV_INDEV_TYPE_BUTTON) return NULL; 262 return indev->proc.types.pointer.scroll_obj; 263 } 264 265 void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point) 266 { 267 point->x = 0; 268 point->y = 0; 269 270 if(indev == NULL) return; 271 272 if(indev->driver->type == LV_INDEV_TYPE_POINTER || indev->driver->type == LV_INDEV_TYPE_BUTTON) { 273 point->x = indev->proc.types.pointer.vect.x; 274 point->y = indev->proc.types.pointer.vect.y; 275 } 276 } 277 278 void lv_indev_wait_release(lv_indev_t * indev) 279 { 280 if(indev == NULL)return; 281 indev->proc.wait_until_release = 1; 282 } 283 284 lv_obj_t * lv_indev_get_obj_act(void) 285 { 286 return indev_obj_act; 287 } 288 289 lv_timer_t * lv_indev_get_read_timer(lv_disp_t * indev) 290 { 291 if(!indev) { 292 LV_LOG_WARN("lv_indev_get_read_timer: indev was NULL"); 293 return NULL; 294 } 295 296 return indev->refr_timer; 297 } 298 299 lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point) 300 { 301 lv_obj_t * found_p = NULL; 302 303 /*If this obj is hidden the children are hidden too so return immediately*/ 304 if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return NULL; 305 306 bool hit_test_ok = lv_obj_hit_test(obj, point); 307 308 /*If the point is on this object or has overflow visible check its children too*/ 309 if(_lv_area_is_point_on(&obj->coords, point, 0) || lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) { 310 int32_t i; 311 uint32_t child_cnt = lv_obj_get_child_cnt(obj); 312 /*If a child matches use it*/ 313 for(i = child_cnt - 1; i >= 0; i--) { 314 lv_obj_t * child = obj->spec_attr->children[i]; 315 found_p = lv_indev_search_obj(child, point); 316 if(found_p) return found_p; 317 } 318 } 319 320 /*If not return earlier for a clicked child and this obj's hittest was ok use it 321 *else return NULL*/ 322 if(hit_test_ok) return obj; 323 else return NULL; 324 } 325 326 /********************** 327 * STATIC FUNCTIONS 328 **********************/ 329 330 /** 331 * Process a new point from LV_INDEV_TYPE_POINTER input device 332 * @param i pointer to an input device 333 * @param data pointer to the data read from the input device 334 */ 335 static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data) 336 { 337 lv_disp_t * disp = i->driver->disp; 338 /*Save the raw points so they can be used again in _lv_indev_read*/ 339 i->proc.types.pointer.last_raw_point.x = data->point.x; 340 i->proc.types.pointer.last_raw_point.y = data->point.y; 341 342 if(disp->driver->rotated == LV_DISP_ROT_180 || disp->driver->rotated == LV_DISP_ROT_270) { 343 data->point.x = disp->driver->hor_res - data->point.x - 1; 344 data->point.y = disp->driver->ver_res - data->point.y - 1; 345 } 346 if(disp->driver->rotated == LV_DISP_ROT_90 || disp->driver->rotated == LV_DISP_ROT_270) { 347 lv_coord_t tmp = data->point.y; 348 data->point.y = data->point.x; 349 data->point.x = disp->driver->ver_res - tmp - 1; 350 } 351 352 /*Simple sanity check*/ 353 if(data->point.x < 0) { 354 LV_LOG_WARN("X is %d which is smaller than zero", data->point.x); 355 } 356 if(data->point.x >= lv_disp_get_hor_res(i->driver->disp)) { 357 LV_LOG_WARN("X is %d which is greater than hor. res", data->point.x); 358 } 359 if(data->point.y < 0) { 360 LV_LOG_WARN("Y is %d which is smaller than zero", data->point.y); 361 } 362 if(data->point.y >= lv_disp_get_ver_res(i->driver->disp)) { 363 LV_LOG_WARN("Y is %d which is greater than ver. res", data->point.y); 364 } 365 366 /*Move the cursor if set and moved*/ 367 if(i->cursor != NULL && 368 (i->proc.types.pointer.last_point.x != data->point.x || i->proc.types.pointer.last_point.y != data->point.y)) { 369 lv_obj_set_pos(i->cursor, data->point.x, data->point.y); 370 } 371 372 i->proc.types.pointer.act_point.x = data->point.x; 373 i->proc.types.pointer.act_point.y = data->point.y; 374 375 if(i->proc.state == LV_INDEV_STATE_PRESSED) { 376 indev_proc_press(&i->proc); 377 } 378 else { 379 indev_proc_release(&i->proc); 380 } 381 382 i->proc.types.pointer.last_point.x = i->proc.types.pointer.act_point.x; 383 i->proc.types.pointer.last_point.y = i->proc.types.pointer.act_point.y; 384 } 385 386 /** 387 * Process a new point from LV_INDEV_TYPE_KEYPAD input device 388 * @param i pointer to an input device 389 * @param data pointer to the data read from the input device 390 */ 391 static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data) 392 { 393 if(data->state == LV_INDEV_STATE_PRESSED && i->proc.wait_until_release) return; 394 395 if(i->proc.wait_until_release) { 396 i->proc.wait_until_release = 0; 397 i->proc.pr_timestamp = 0; 398 i->proc.long_pr_sent = 0; 399 i->proc.types.keypad.last_state = LV_INDEV_STATE_RELEASED; /*To skip the processing of release*/ 400 } 401 402 lv_group_t * g = i->group; 403 if(g == NULL) return; 404 405 indev_obj_act = lv_group_get_focused(g); 406 if(indev_obj_act == NULL) return; 407 408 bool dis = lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED); 409 410 /*Save the last key to compare it with the current latter on RELEASE*/ 411 uint32_t prev_key = i->proc.types.keypad.last_key; 412 413 /*Save the last key. 414 *It must be done here else `lv_indev_get_key` will return the last key in events*/ 415 i->proc.types.keypad.last_key = data->key; 416 417 /*Save the previous state so we can detect state changes below and also set the last state now 418 *so if any event handler on the way returns `LV_RES_INV` the last state is remembered 419 *for the next time*/ 420 uint32_t prev_state = i->proc.types.keypad.last_state; 421 i->proc.types.keypad.last_state = data->state; 422 423 /*Key press happened*/ 424 if(data->state == LV_INDEV_STATE_PRESSED && prev_state == LV_INDEV_STATE_RELEASED) { 425 LV_LOG_INFO("%" LV_PRIu32 " key is pressed", data->key); 426 i->proc.pr_timestamp = lv_tick_get(); 427 428 /*Move the focus on NEXT*/ 429 if(data->key == LV_KEY_NEXT) { 430 lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/ 431 lv_group_focus_next(g); 432 if(indev_reset_check(&i->proc)) return; 433 } 434 /*Move the focus on PREV*/ 435 else if(data->key == LV_KEY_PREV) { 436 lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/ 437 lv_group_focus_prev(g); 438 if(indev_reset_check(&i->proc)) return; 439 } 440 else if(!dis) { 441 /*Simulate a press on the object if ENTER was pressed*/ 442 if(data->key == LV_KEY_ENTER) { 443 /*Send the ENTER as a normal KEY*/ 444 lv_group_send_data(g, LV_KEY_ENTER); 445 if(indev_reset_check(&i->proc)) return; 446 447 if(!dis) lv_event_send(indev_obj_act, LV_EVENT_PRESSED, indev_act); 448 if(indev_reset_check(&i->proc)) return; 449 } 450 else if(data->key == LV_KEY_ESC) { 451 /*Send the ESC as a normal KEY*/ 452 lv_group_send_data(g, LV_KEY_ESC); 453 if(indev_reset_check(&i->proc)) return; 454 455 lv_event_send(indev_obj_act, LV_EVENT_CANCEL, indev_act); 456 if(indev_reset_check(&i->proc)) return; 457 } 458 /*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/ 459 else { 460 lv_group_send_data(g, data->key); 461 if(indev_reset_check(&i->proc)) return; 462 } 463 } 464 } 465 /*Pressing*/ 466 else if(!dis && data->state == LV_INDEV_STATE_PRESSED && prev_state == LV_INDEV_STATE_PRESSED) { 467 468 if(data->key == LV_KEY_ENTER) { 469 lv_event_send(indev_obj_act, LV_EVENT_PRESSING, indev_act); 470 if(indev_reset_check(&i->proc)) return; 471 } 472 473 /*Long press time has elapsed?*/ 474 if(i->proc.long_pr_sent == 0 && lv_tick_elaps(i->proc.pr_timestamp) > i->driver->long_press_time) { 475 i->proc.long_pr_sent = 1; 476 if(data->key == LV_KEY_ENTER) { 477 i->proc.longpr_rep_timestamp = lv_tick_get(); 478 lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, indev_act); 479 if(indev_reset_check(&i->proc)) return; 480 } 481 } 482 /*Long press repeated time has elapsed?*/ 483 else if(i->proc.long_pr_sent != 0 && 484 lv_tick_elaps(i->proc.longpr_rep_timestamp) > i->driver->long_press_repeat_time) { 485 486 i->proc.longpr_rep_timestamp = lv_tick_get(); 487 488 /*Send LONG_PRESS_REP on ENTER*/ 489 if(data->key == LV_KEY_ENTER) { 490 lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED_REPEAT, indev_act); 491 if(indev_reset_check(&i->proc)) return; 492 } 493 /*Move the focus on NEXT again*/ 494 else if(data->key == LV_KEY_NEXT) { 495 lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/ 496 lv_group_focus_next(g); 497 if(indev_reset_check(&i->proc)) return; 498 } 499 /*Move the focus on PREV again*/ 500 else if(data->key == LV_KEY_PREV) { 501 lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/ 502 lv_group_focus_prev(g); 503 if(indev_reset_check(&i->proc)) return; 504 } 505 /*Just send other keys again to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT)*/ 506 else { 507 lv_group_send_data(g, data->key); 508 if(indev_reset_check(&i->proc)) return; 509 } 510 } 511 } 512 /*Release happened*/ 513 else if(!dis && data->state == LV_INDEV_STATE_RELEASED && prev_state == LV_INDEV_STATE_PRESSED) { 514 LV_LOG_INFO("%" LV_PRIu32 " key is released", data->key); 515 /*The user might clear the key when it was released. Always release the pressed key*/ 516 data->key = prev_key; 517 if(data->key == LV_KEY_ENTER) { 518 519 lv_event_send(indev_obj_act, LV_EVENT_RELEASED, indev_act); 520 if(indev_reset_check(&i->proc)) return; 521 522 if(i->proc.long_pr_sent == 0) { 523 lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, indev_act); 524 if(indev_reset_check(&i->proc)) return; 525 } 526 527 lv_event_send(indev_obj_act, LV_EVENT_CLICKED, indev_act); 528 if(indev_reset_check(&i->proc)) return; 529 530 } 531 i->proc.pr_timestamp = 0; 532 i->proc.long_pr_sent = 0; 533 } 534 indev_obj_act = NULL; 535 } 536 537 /** 538 * Process a new point from LV_INDEV_TYPE_ENCODER input device 539 * @param i pointer to an input device 540 * @param data pointer to the data read from the input device 541 */ 542 static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) 543 { 544 if(data->state == LV_INDEV_STATE_PRESSED && i->proc.wait_until_release) return; 545 546 if(i->proc.wait_until_release) { 547 i->proc.wait_until_release = 0; 548 i->proc.pr_timestamp = 0; 549 i->proc.long_pr_sent = 0; 550 i->proc.types.keypad.last_state = LV_INDEV_STATE_RELEASED; /*To skip the processing of release*/ 551 } 552 553 /*Save the last keys before anything else. 554 *They need to be already saved if the function returns for any reason*/ 555 lv_indev_state_t last_state = i->proc.types.keypad.last_state; 556 i->proc.types.keypad.last_state = data->state; 557 i->proc.types.keypad.last_key = data->key; 558 559 lv_group_t * g = i->group; 560 if(g == NULL) return; 561 562 indev_obj_act = lv_group_get_focused(g); 563 if(indev_obj_act == NULL) return; 564 565 /*Process the steps they are valid only with released button*/ 566 if(data->state != LV_INDEV_STATE_RELEASED) { 567 data->enc_diff = 0; 568 } 569 570 /*Refresh the focused object. It might change due to lv_group_focus_prev/next*/ 571 indev_obj_act = lv_group_get_focused(g); 572 if(indev_obj_act == NULL) return; 573 574 /*Button press happened*/ 575 if(data->state == LV_INDEV_STATE_PRESSED && last_state == LV_INDEV_STATE_RELEASED) { 576 LV_LOG_INFO("pressed"); 577 578 i->proc.pr_timestamp = lv_tick_get(); 579 580 if(data->key == LV_KEY_ENTER) { 581 bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) || 582 lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE); 583 if(lv_group_get_editing(g) == true || editable_or_scrollable == false) { 584 lv_event_send(indev_obj_act, LV_EVENT_PRESSED, indev_act); 585 if(indev_reset_check(&i->proc)) return; 586 } 587 } 588 else if(data->key == LV_KEY_LEFT) { 589 /*emulate encoder left*/ 590 data->enc_diff--; 591 } 592 else if(data->key == LV_KEY_RIGHT) { 593 /*emulate encoder right*/ 594 data->enc_diff++; 595 } 596 else if(data->key == LV_KEY_ESC) { 597 /*Send the ESC as a normal KEY*/ 598 lv_group_send_data(g, LV_KEY_ESC); 599 if(indev_reset_check(&i->proc)) return; 600 601 lv_event_send(indev_obj_act, LV_EVENT_CANCEL, indev_act); 602 if(indev_reset_check(&i->proc)) return; 603 } 604 /*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/ 605 else { 606 lv_group_send_data(g, data->key); 607 if(indev_reset_check(&i->proc)) return; 608 } 609 } 610 /*Pressing*/ 611 else if(data->state == LV_INDEV_STATE_PRESSED && last_state == LV_INDEV_STATE_PRESSED) { 612 /*Long press*/ 613 if(i->proc.long_pr_sent == 0 && lv_tick_elaps(i->proc.pr_timestamp) > i->driver->long_press_time) { 614 615 i->proc.long_pr_sent = 1; 616 i->proc.longpr_rep_timestamp = lv_tick_get(); 617 618 if(data->key == LV_KEY_ENTER) { 619 bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) || 620 lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE); 621 622 /*On enter long press toggle edit mode.*/ 623 if(editable_or_scrollable) { 624 /*Don't leave edit mode if there is only one object (nowhere to navigate)*/ 625 if(lv_group_get_obj_count(g) > 1) { 626 LV_LOG_INFO("toggling edit mode"); 627 lv_group_set_editing(g, lv_group_get_editing(g) ? false : true); /*Toggle edit mode on long press*/ 628 lv_obj_clear_state(indev_obj_act, LV_STATE_PRESSED); /*Remove the pressed state manually*/ 629 } 630 } 631 /*If not editable then just send a long press Call the ancestor's event handler*/ 632 else { 633 lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, indev_act); 634 if(indev_reset_check(&i->proc)) return; 635 } 636 } 637 638 i->proc.long_pr_sent = 1; 639 } 640 /*Long press repeated time has elapsed?*/ 641 else if(i->proc.long_pr_sent != 0 && lv_tick_elaps(i->proc.longpr_rep_timestamp) > i->driver->long_press_repeat_time) { 642 643 i->proc.longpr_rep_timestamp = lv_tick_get(); 644 645 if(data->key == LV_KEY_ENTER) { 646 lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED_REPEAT, indev_act); 647 if(indev_reset_check(&i->proc)) return; 648 } 649 else if(data->key == LV_KEY_LEFT) { 650 /*emulate encoder left*/ 651 data->enc_diff--; 652 } 653 else if(data->key == LV_KEY_RIGHT) { 654 /*emulate encoder right*/ 655 data->enc_diff++; 656 } 657 else { 658 lv_group_send_data(g, data->key); 659 if(indev_reset_check(&i->proc)) return; 660 } 661 662 } 663 664 } 665 /*Release happened*/ 666 else if(data->state == LV_INDEV_STATE_RELEASED && last_state == LV_INDEV_STATE_PRESSED) { 667 LV_LOG_INFO("released"); 668 669 if(data->key == LV_KEY_ENTER) { 670 bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) || 671 lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE); 672 673 /*The button was released on a non-editable object. Just send enter*/ 674 if(editable_or_scrollable == false) { 675 lv_event_send(indev_obj_act, LV_EVENT_RELEASED, indev_act); 676 if(indev_reset_check(&i->proc)) return; 677 678 if(i->proc.long_pr_sent == 0) lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, indev_act); 679 if(indev_reset_check(&i->proc)) return; 680 681 lv_event_send(indev_obj_act, LV_EVENT_CLICKED, indev_act); 682 if(indev_reset_check(&i->proc)) return; 683 684 } 685 /*An object is being edited and the button is released.*/ 686 else if(lv_group_get_editing(g)) { 687 /*Ignore long pressed enter release because it comes from mode switch*/ 688 if(!i->proc.long_pr_sent || lv_group_get_obj_count(g) <= 1) { 689 lv_event_send(indev_obj_act, LV_EVENT_RELEASED, indev_act); 690 if(indev_reset_check(&i->proc)) return; 691 692 lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, indev_act); 693 if(indev_reset_check(&i->proc)) return; 694 695 lv_event_send(indev_obj_act, LV_EVENT_CLICKED, indev_act); 696 if(indev_reset_check(&i->proc)) return; 697 698 lv_group_send_data(g, LV_KEY_ENTER); 699 if(indev_reset_check(&i->proc)) return; 700 } 701 else { 702 lv_obj_clear_state(indev_obj_act, LV_STATE_PRESSED); /*Remove the pressed state manually*/ 703 } 704 } 705 /*If the focused object is editable and now in navigate mode then on enter switch edit 706 mode*/ 707 else if(!i->proc.long_pr_sent) { 708 LV_LOG_INFO("entering edit mode"); 709 lv_group_set_editing(g, true); /*Set edit mode*/ 710 } 711 } 712 713 i->proc.pr_timestamp = 0; 714 i->proc.long_pr_sent = 0; 715 } 716 indev_obj_act = NULL; 717 718 /*if encoder steps or simulated steps via left/right keys*/ 719 if(data->enc_diff != 0) { 720 /*In edit mode send LEFT/RIGHT keys*/ 721 if(lv_group_get_editing(g)) { 722 LV_LOG_INFO("rotated by %+d (edit)", data->enc_diff); 723 int32_t s; 724 if(data->enc_diff < 0) { 725 for(s = 0; s < -data->enc_diff; s++) { 726 lv_group_send_data(g, LV_KEY_LEFT); 727 if(indev_reset_check(&i->proc)) return; 728 } 729 } 730 else if(data->enc_diff > 0) { 731 for(s = 0; s < data->enc_diff; s++) { 732 lv_group_send_data(g, LV_KEY_RIGHT); 733 if(indev_reset_check(&i->proc)) return; 734 } 735 } 736 } 737 /*In navigate mode focus on the next/prev objects*/ 738 else { 739 LV_LOG_INFO("rotated by %+d (nav)", data->enc_diff); 740 int32_t s; 741 if(data->enc_diff < 0) { 742 for(s = 0; s < -data->enc_diff; s++) { 743 lv_group_focus_prev(g); 744 if(indev_reset_check(&i->proc)) return; 745 } 746 } 747 else if(data->enc_diff > 0) { 748 for(s = 0; s < data->enc_diff; s++) { 749 lv_group_focus_next(g); 750 if(indev_reset_check(&i->proc)) return; 751 } 752 } 753 } 754 } 755 } 756 757 /** 758 * Process new points from an input device. indev->state.pressed has to be set 759 * @param indev pointer to an input device state 760 * @param x x coordinate of the next point 761 * @param y y coordinate of the next point 762 */ 763 static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data) 764 { 765 /*Die gracefully if i->btn_points is NULL*/ 766 if(i->btn_points == NULL) { 767 LV_LOG_WARN("btn_points is NULL"); 768 return; 769 } 770 771 lv_coord_t x = i->btn_points[data->btn_id].x; 772 lv_coord_t y = i->btn_points[data->btn_id].y; 773 774 static lv_indev_state_t prev_state = LV_INDEV_STATE_RELEASED; 775 if(prev_state != data->state) { 776 if(data->state == LV_INDEV_STATE_PRESSED) { 777 LV_LOG_INFO("button %" LV_PRIu32 " is pressed (x:%d y:%d)", data->btn_id, x, y); 778 } 779 else { 780 LV_LOG_INFO("button %" LV_PRIu32 " is released (x:%d y:%d)", data->btn_id, x, y); 781 } 782 } 783 784 /*If a new point comes always make a release*/ 785 if(data->state == LV_INDEV_STATE_PRESSED) { 786 if(i->proc.types.pointer.last_point.x != x || 787 i->proc.types.pointer.last_point.y != y) { 788 indev_proc_release(&i->proc); 789 } 790 } 791 792 if(indev_reset_check(&i->proc)) return; 793 794 /*Save the new points*/ 795 i->proc.types.pointer.act_point.x = x; 796 i->proc.types.pointer.act_point.y = y; 797 798 if(data->state == LV_INDEV_STATE_PRESSED) indev_proc_press(&i->proc); 799 else indev_proc_release(&i->proc); 800 801 if(indev_reset_check(&i->proc)) return; 802 803 i->proc.types.pointer.last_point.x = i->proc.types.pointer.act_point.x; 804 i->proc.types.pointer.last_point.y = i->proc.types.pointer.act_point.y; 805 } 806 807 /** 808 * Process the pressed state of LV_INDEV_TYPE_POINTER input devices 809 * @param indev pointer to an input device 'proc' 810 * @return LV_RES_OK: no indev reset required; LV_RES_INV: indev reset is required 811 */ 812 static void indev_proc_press(_lv_indev_proc_t * proc) 813 { 814 LV_LOG_INFO("pressed at x:%d y:%d", proc->types.pointer.act_point.x, proc->types.pointer.act_point.y); 815 indev_obj_act = proc->types.pointer.act_obj; 816 817 if(proc->wait_until_release != 0) return; 818 819 lv_disp_t * disp = indev_act->driver->disp; 820 bool new_obj_searched = false; 821 822 /*If there is no last object then search*/ 823 if(indev_obj_act == NULL) { 824 indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point); 825 if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp), 826 &proc->types.pointer.act_point); 827 if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp), 828 &proc->types.pointer.act_point); 829 new_obj_searched = true; 830 } 831 /*If there is last object but it is not scrolled and not protected also search*/ 832 else if(proc->types.pointer.scroll_obj == NULL && 833 lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_PRESS_LOCK) == false) { 834 indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point); 835 if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp), 836 &proc->types.pointer.act_point); 837 if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp), 838 &proc->types.pointer.act_point); 839 new_obj_searched = true; 840 } 841 842 /*The last object might have scroll throw. Stop it manually*/ 843 if(new_obj_searched && proc->types.pointer.last_obj) { 844 proc->types.pointer.scroll_throw_vect.x = 0; 845 proc->types.pointer.scroll_throw_vect.y = 0; 846 _lv_indev_scroll_throw_handler(proc); 847 if(indev_reset_check(proc)) return; 848 } 849 850 /*If a new object was found reset some variables and send a pressed Call the ancestor's event handler*/ 851 if(indev_obj_act != proc->types.pointer.act_obj) { 852 proc->types.pointer.last_point.x = proc->types.pointer.act_point.x; 853 proc->types.pointer.last_point.y = proc->types.pointer.act_point.y; 854 855 /*If a new object found the previous was lost, so send a Call the ancestor's event handler*/ 856 if(proc->types.pointer.act_obj != NULL) { 857 /*Save the obj because in special cases `act_obj` can change in the Call the ancestor's event handler function*/ 858 lv_obj_t * last_obj = proc->types.pointer.act_obj; 859 860 lv_event_send(last_obj, LV_EVENT_PRESS_LOST, indev_act); 861 if(indev_reset_check(proc)) return; 862 } 863 864 proc->types.pointer.act_obj = indev_obj_act; /*Save the pressed object*/ 865 proc->types.pointer.last_obj = indev_obj_act; 866 867 if(indev_obj_act != NULL) { 868 /*Save the time when the obj pressed to count long press time.*/ 869 proc->pr_timestamp = lv_tick_get(); 870 proc->long_pr_sent = 0; 871 proc->types.pointer.scroll_sum.x = 0; 872 proc->types.pointer.scroll_sum.y = 0; 873 proc->types.pointer.scroll_dir = LV_DIR_NONE; 874 proc->types.pointer.gesture_dir = LV_DIR_NONE; 875 proc->types.pointer.gesture_sent = 0; 876 proc->types.pointer.gesture_sum.x = 0; 877 proc->types.pointer.gesture_sum.y = 0; 878 proc->types.pointer.vect.x = 0; 879 proc->types.pointer.vect.y = 0; 880 881 /*Call the ancestor's event handler about the press*/ 882 lv_event_send(indev_obj_act, LV_EVENT_PRESSED, indev_act); 883 if(indev_reset_check(proc)) return; 884 885 if(indev_act->proc.wait_until_release) return; 886 887 /*Handle focus*/ 888 indev_click_focus(&indev_act->proc); 889 if(indev_reset_check(proc)) return; 890 891 } 892 } 893 894 /*Calculate the vector and apply a low pass filter: new value = 0.5 * old_value + 0.5 * new_value*/ 895 proc->types.pointer.vect.x = proc->types.pointer.act_point.x - proc->types.pointer.last_point.x; 896 proc->types.pointer.vect.y = proc->types.pointer.act_point.y - proc->types.pointer.last_point.y; 897 898 proc->types.pointer.scroll_throw_vect.x = (proc->types.pointer.scroll_throw_vect.x * 4) >> 3; 899 proc->types.pointer.scroll_throw_vect.y = (proc->types.pointer.scroll_throw_vect.y * 4) >> 3; 900 901 proc->types.pointer.scroll_throw_vect.x += (proc->types.pointer.vect.x * 4) >> 3; 902 proc->types.pointer.scroll_throw_vect.y += (proc->types.pointer.vect.y * 4) >> 3; 903 904 proc->types.pointer.scroll_throw_vect_ori = proc->types.pointer.scroll_throw_vect; 905 906 if(indev_obj_act) { 907 lv_event_send(indev_obj_act, LV_EVENT_PRESSING, indev_act); 908 if(indev_reset_check(proc)) return; 909 910 if(indev_act->proc.wait_until_release) return; 911 912 _lv_indev_scroll_handler(proc); 913 if(indev_reset_check(proc)) return; 914 indev_gesture(proc); 915 if(indev_reset_check(proc)) return; 916 917 /*If there is no scrolling then check for long press time*/ 918 if(proc->types.pointer.scroll_obj == NULL && proc->long_pr_sent == 0) { 919 /*Call the ancestor's event handler about the long press if enough time elapsed*/ 920 if(lv_tick_elaps(proc->pr_timestamp) > indev_act->driver->long_press_time) { 921 lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, indev_act); 922 if(indev_reset_check(proc)) return; 923 924 /*Mark the Call the ancestor's event handler sending to do not send it again*/ 925 proc->long_pr_sent = 1; 926 927 /*Save the long press time stamp for the long press repeat handler*/ 928 proc->longpr_rep_timestamp = lv_tick_get(); 929 } 930 } 931 932 /*Send long press repeated Call the ancestor's event handler*/ 933 if(proc->types.pointer.scroll_obj == NULL && proc->long_pr_sent == 1) { 934 /*Call the ancestor's event handler about the long press repeat if enough time elapsed*/ 935 if(lv_tick_elaps(proc->longpr_rep_timestamp) > indev_act->driver->long_press_repeat_time) { 936 lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED_REPEAT, indev_act); 937 if(indev_reset_check(proc)) return; 938 proc->longpr_rep_timestamp = lv_tick_get(); 939 } 940 } 941 } 942 } 943 944 /** 945 * Process the released state of LV_INDEV_TYPE_POINTER input devices 946 * @param proc pointer to an input device 'proc' 947 */ 948 static void indev_proc_release(_lv_indev_proc_t * proc) 949 { 950 if(proc->wait_until_release != 0) { 951 proc->types.pointer.act_obj = NULL; 952 proc->types.pointer.last_obj = NULL; 953 proc->pr_timestamp = 0; 954 proc->longpr_rep_timestamp = 0; 955 proc->wait_until_release = 0; 956 } 957 indev_obj_act = proc->types.pointer.act_obj; 958 lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj; 959 960 /*Forget the act obj and send a released Call the ancestor's event handler*/ 961 if(indev_obj_act) { 962 LV_LOG_INFO("released"); 963 964 /*Send RELEASE Call the ancestor's event handler and event*/ 965 lv_event_send(indev_obj_act, LV_EVENT_RELEASED, indev_act); 966 if(indev_reset_check(proc)) return; 967 968 /*Send CLICK if no scrolling*/ 969 if(scroll_obj == NULL) { 970 if(proc->long_pr_sent == 0) { 971 lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, indev_act); 972 if(indev_reset_check(proc)) return; 973 } 974 975 lv_event_send(indev_obj_act, LV_EVENT_CLICKED, indev_act); 976 if(indev_reset_check(proc)) return; 977 } 978 979 proc->types.pointer.act_obj = NULL; 980 proc->pr_timestamp = 0; 981 proc->longpr_rep_timestamp = 0; 982 983 } 984 985 /*The reset can be set in the Call the ancestor's event handler function. 986 * In case of reset query ignore the remaining parts.*/ 987 if(scroll_obj) { 988 _lv_indev_scroll_throw_handler(proc); 989 if(indev_reset_check(proc)) return; 990 } 991 } 992 993 /** 994 * Process a new point from LV_INDEV_TYPE_BUTTON input device 995 * @param i pointer to an input device 996 * @param data pointer to the data read from the input device 997 * Reset input device if a reset query has been sent to it 998 * @param indev pointer to an input device 999 */ 1000 static void indev_proc_reset_query_handler(lv_indev_t * indev) 1001 { 1002 if(indev->proc.reset_query) { 1003 indev->proc.types.pointer.act_obj = NULL; 1004 indev->proc.types.pointer.last_obj = NULL; 1005 indev->proc.types.pointer.scroll_obj = NULL; 1006 indev->proc.long_pr_sent = 0; 1007 indev->proc.pr_timestamp = 0; 1008 indev->proc.longpr_rep_timestamp = 0; 1009 indev->proc.types.pointer.scroll_sum.x = 0; 1010 indev->proc.types.pointer.scroll_sum.y = 0; 1011 indev->proc.types.pointer.scroll_dir = LV_DIR_NONE; 1012 indev->proc.types.pointer.scroll_throw_vect.x = 0; 1013 indev->proc.types.pointer.scroll_throw_vect.y = 0; 1014 indev->proc.types.pointer.gesture_sum.x = 0; 1015 indev->proc.types.pointer.gesture_sum.y = 0; 1016 indev->proc.reset_query = 0; 1017 indev_obj_act = NULL; 1018 } 1019 } 1020 1021 /** 1022 * Handle focus/defocus on click for POINTER input devices 1023 * @param proc pointer to the state of the indev 1024 */ 1025 static void indev_click_focus(_lv_indev_proc_t * proc) 1026 { 1027 /*Handle click focus*/ 1028 if(lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_CLICK_FOCUSABLE) == false || 1029 proc->types.pointer.last_pressed == indev_obj_act) { 1030 return; 1031 } 1032 1033 lv_group_t * g_act = lv_obj_get_group(indev_obj_act); 1034 lv_group_t * g_prev = proc->types.pointer.last_pressed ? lv_obj_get_group(proc->types.pointer.last_pressed) : NULL; 1035 1036 /*If both the last and act. obj. are in the same group (or have no group)*/ 1037 if(g_act == g_prev) { 1038 /*The objects are in a group*/ 1039 if(g_act) { 1040 lv_group_focus_obj(indev_obj_act); 1041 if(indev_reset_check(proc)) return; 1042 } 1043 /*The object are not in group*/ 1044 else { 1045 if(proc->types.pointer.last_pressed) { 1046 lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act); 1047 if(indev_reset_check(proc)) return; 1048 } 1049 1050 lv_event_send(indev_obj_act, LV_EVENT_FOCUSED, indev_act); 1051 if(indev_reset_check(proc)) return; 1052 } 1053 } 1054 /*The object are not in the same group (in different groups or one has no group)*/ 1055 else { 1056 /*If the prev. obj. is not in a group then defocus it.*/ 1057 if(g_prev == NULL && proc->types.pointer.last_pressed) { 1058 lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act); 1059 if(indev_reset_check(proc)) return; 1060 } 1061 /*Focus on a non-group object*/ 1062 else { 1063 if(proc->types.pointer.last_pressed) { 1064 /*If the prev. object also wasn't in a group defocus it*/ 1065 if(g_prev == NULL) { 1066 lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act); 1067 if(indev_reset_check(proc)) return; 1068 } 1069 /*If the prev. object also was in a group at least "LEAVE" it instead of defocus*/ 1070 else { 1071 lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_LEAVE, indev_act); 1072 if(indev_reset_check(proc)) return; 1073 } 1074 } 1075 } 1076 1077 /*Focus to the act. in its group*/ 1078 if(g_act) { 1079 lv_group_focus_obj(indev_obj_act); 1080 if(indev_reset_check(proc)) return; 1081 } 1082 else { 1083 lv_event_send(indev_obj_act, LV_EVENT_FOCUSED, indev_act); 1084 if(indev_reset_check(proc)) return; 1085 } 1086 } 1087 proc->types.pointer.last_pressed = indev_obj_act; 1088 } 1089 1090 /** 1091 * Handle the gesture of indev_proc_p->types.pointer.act_obj 1092 * @param indev pointer to an input device state 1093 */ 1094 void indev_gesture(_lv_indev_proc_t * proc) 1095 { 1096 1097 if(proc->types.pointer.scroll_obj) return; 1098 if(proc->types.pointer.gesture_sent) return; 1099 1100 lv_obj_t * gesture_obj = proc->types.pointer.act_obj; 1101 1102 /*If gesture parent is active check recursively the gesture attribute*/ 1103 while(gesture_obj && lv_obj_has_flag(gesture_obj, LV_OBJ_FLAG_GESTURE_BUBBLE)) { 1104 gesture_obj = lv_obj_get_parent(gesture_obj); 1105 } 1106 1107 if(gesture_obj == NULL) return; 1108 1109 if((LV_ABS(proc->types.pointer.vect.x) < indev_act->driver->gesture_min_velocity) && 1110 (LV_ABS(proc->types.pointer.vect.y) < indev_act->driver->gesture_min_velocity)) { 1111 proc->types.pointer.gesture_sum.x = 0; 1112 proc->types.pointer.gesture_sum.y = 0; 1113 } 1114 1115 /*Count the movement by gesture*/ 1116 proc->types.pointer.gesture_sum.x += proc->types.pointer.vect.x; 1117 proc->types.pointer.gesture_sum.y += proc->types.pointer.vect.y; 1118 1119 if((LV_ABS(proc->types.pointer.gesture_sum.x) > indev_act->driver->gesture_limit) || 1120 (LV_ABS(proc->types.pointer.gesture_sum.y) > indev_act->driver->gesture_limit)) { 1121 1122 proc->types.pointer.gesture_sent = 1; 1123 1124 if(LV_ABS(proc->types.pointer.gesture_sum.x) > LV_ABS(proc->types.pointer.gesture_sum.y)) { 1125 if(proc->types.pointer.gesture_sum.x > 0) 1126 proc->types.pointer.gesture_dir = LV_DIR_RIGHT; 1127 else 1128 proc->types.pointer.gesture_dir = LV_DIR_LEFT; 1129 } 1130 else { 1131 if(proc->types.pointer.gesture_sum.y > 0) 1132 proc->types.pointer.gesture_dir = LV_DIR_BOTTOM; 1133 else 1134 proc->types.pointer.gesture_dir = LV_DIR_TOP; 1135 } 1136 1137 lv_event_send(gesture_obj, LV_EVENT_GESTURE, indev_act); 1138 if(indev_reset_check(proc)) return; 1139 } 1140 } 1141 1142 /** 1143 * Checks if the reset_query flag has been set. If so, perform necessary global indev cleanup actions 1144 * @param proc pointer to an input device 'proc' 1145 * @return true if indev query should be immediately truncated. 1146 */ 1147 static bool indev_reset_check(_lv_indev_proc_t * proc) 1148 { 1149 if(proc->reset_query) { 1150 indev_obj_act = NULL; 1151 } 1152 1153 return proc->reset_query ? true : false; 1154 }