diff options
Diffstat (limited to 'apps/action.c')
-rw-r--r-- | apps/action.c | 466 |
1 files changed, 404 insertions, 62 deletions
diff --git a/apps/action.c b/apps/action.c index eae00f5d18..d153bc6140 100644 --- a/apps/action.c +++ b/apps/action.c | |||
@@ -42,6 +42,16 @@ | |||
42 | #include "statusbar-skinned.h" | 42 | #include "statusbar-skinned.h" |
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | #ifdef HAVE_BACKLIGHT | ||
46 | #include "backlight.h" | ||
47 | #if CONFIG_CHARGING | ||
48 | #include "power.h" | ||
49 | #endif | ||
50 | #endif /* HAVE_BACKLIGHT */ | ||
51 | |||
52 | #define LOGF_ENABLE | ||
53 | #include "logf.h" | ||
54 | |||
45 | static int last_button = BUTTON_NONE|BUTTON_REL; /* allow the ipod wheel to | 55 | static int last_button = BUTTON_NONE|BUTTON_REL; /* allow the ipod wheel to |
46 | work on startup */ | 56 | work on startup */ |
47 | static intptr_t last_data = 0; | 57 | static intptr_t last_data = 0; |
@@ -56,19 +66,34 @@ static bool short_press = false; | |||
56 | #define REPEAT_WINDOW_TICKS HZ/4 | 66 | #define REPEAT_WINDOW_TICKS HZ/4 |
57 | static int last_action_tick = 0; | 67 | static int last_action_tick = 0; |
58 | 68 | ||
69 | #if defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD) | ||
70 | static inline bool is_action_normal(int action); | ||
71 | static inline bool mask_has_flag(unsigned int mask, unsigned int flag); | ||
72 | static inline bool is_action_completed(int button); | ||
73 | #define LAST_FILTER_TICKS HZ/2 /* timeout between filtered actions */ | ||
74 | #endif /* defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD) */ | ||
75 | |||
76 | #ifdef HAVE_BACKLIGHT | ||
77 | static unsigned int backlight_mask = SEL_ACTION_NONE; | ||
78 | static int do_backlight(int action, int context, bool is_pre_btn); | ||
79 | static void handle_backlight(bool backlight, bool ignore_next); | ||
80 | #endif /* HAVE_BACKLIGHT */ | ||
81 | |||
59 | /* software keylock stuff */ | 82 | /* software keylock stuff */ |
60 | #ifndef HAS_BUTTON_HOLD | 83 | #ifndef HAS_BUTTON_HOLD |
61 | static bool keys_locked = false; | 84 | static bool keys_locked = false; |
62 | static int unlock_combo = BUTTON_NONE; | ||
63 | static bool screen_has_lock = false; | 85 | static bool screen_has_lock = false; |
86 | static unsigned int softlock_mask = SEL_ACTION_NONE; | ||
87 | static inline int do_softlock_unlock_combo(int button, int context); | ||
88 | static int do_softlock(int button, int action, int context, bool is_pre_btn); | ||
64 | #endif /* HAVE_SOFTWARE_KEYLOCK */ | 89 | #endif /* HAVE_SOFTWARE_KEYLOCK */ |
65 | |||
66 | /* | 90 | /* |
67 | * do_button_check is the worker function for get_default_action. | 91 | * do_button_check is the worker function for get_default_action. |
68 | * returns ACTION_UNKNOWN or the requested return value from the list. | 92 | * returns ACTION_UNKNOWN or the requested return value from the list. |
93 | * BE AWARE is_pre_button can miss pre buttons if a match is found first. | ||
69 | */ | 94 | */ |
70 | static inline int do_button_check(const struct button_mapping *items, | 95 | static inline int do_button_check(const struct button_mapping *items,int button, |
71 | int button, int last_button, int *start) | 96 | int last_button, int *start, bool *prebtn) |
72 | { | 97 | { |
73 | int i = 0; | 98 | int i = 0; |
74 | int ret = ACTION_UNKNOWN; | 99 | int ret = ACTION_UNKNOWN; |
@@ -88,6 +113,8 @@ static inline int do_button_check(const struct button_mapping *items, | |||
88 | break; | 113 | break; |
89 | } | 114 | } |
90 | } | 115 | } |
116 | else if (items[i].pre_button_code & button) | ||
117 | *prebtn = true; /* determine if this could be another action */ | ||
91 | i++; | 118 | i++; |
92 | } | 119 | } |
93 | *start = i; | 120 | *start = i; |
@@ -164,7 +191,7 @@ static inline int get_next_context(const struct button_mapping *items, int i) | |||
164 | static void gui_boost(bool want_to_boost) | 191 | static void gui_boost(bool want_to_boost) |
165 | { | 192 | { |
166 | static bool boosted = false; | 193 | static bool boosted = false; |
167 | 194 | ||
168 | if (want_to_boost && !boosted) | 195 | if (want_to_boost && !boosted) |
169 | { | 196 | { |
170 | cpu_boost(true); | 197 | cpu_boost(true); |
@@ -177,7 +204,7 @@ static void gui_boost(bool want_to_boost) | |||
177 | } | 204 | } |
178 | } | 205 | } |
179 | 206 | ||
180 | /* gui_unboost_callback() is called GUI_BOOST_TIMEOUT seconds after the | 207 | /* gui_unboost_callback() is called GUI_BOOST_TIMEOUT seconds after the |
181 | * last wheel scrolling event. */ | 208 | * last wheel scrolling event. */ |
182 | static int gui_unboost_callback(struct timeout *tmo) | 209 | static int gui_unboost_callback(struct timeout *tmo) |
183 | { | 210 | { |
@@ -188,8 +215,8 @@ static int gui_unboost_callback(struct timeout *tmo) | |||
188 | #endif | 215 | #endif |
189 | 216 | ||
190 | /* | 217 | /* |
191 | * int get_action_worker(int context, struct button_mapping *user_mappings, | 218 | * int get_action_worker(int context, int timeout, bool *is_pre_button, |
192 | int timeout) | 219 | struct button_mapping *user_mappings) |
193 | This function searches the button list for the given context for the just | 220 | This function searches the button list for the given context for the just |
194 | pressed button. | 221 | pressed button. |
195 | If there is a match it returns the value from the list. | 222 | If there is a match it returns the value from the list. |
@@ -197,12 +224,14 @@ static int gui_unboost_callback(struct timeout *tmo) | |||
197 | the last item in the list "points" to the next context in a chain | 224 | the last item in the list "points" to the next context in a chain |
198 | so the "chain" is followed until the button is found. | 225 | so the "chain" is followed until the button is found. |
199 | putting ACTION_NONE will get CONTEXT_STD which is always the last list checked. | 226 | putting ACTION_NONE will get CONTEXT_STD which is always the last list checked. |
200 | 227 | BE AWARE is_pre_button can miss pre buttons if a match is found first. | |
228 | it is more for actions that are not yet completed in the desired context | ||
229 | but are defined in a lower 'chained' context. | ||
201 | Timeout can be TIMEOUT_NOBLOCK to return immediatly | 230 | Timeout can be TIMEOUT_NOBLOCK to return immediatly |
202 | TIMEOUT_BLOCK to wait for a button press | 231 | TIMEOUT_BLOCK to wait for a button press |
203 | Any number >0 to wait that many ticks for a press | 232 | Any number >0 to wait that many ticks for a press |
204 | */ | 233 | */ |
205 | static int get_action_worker(int context, int timeout, | 234 | static int get_action_worker(int context, int timeout, bool *is_pre_button, |
206 | const struct button_mapping* (*get_context_map)(int) ) | 235 | const struct button_mapping* (*get_context_map)(int) ) |
207 | { | 236 | { |
208 | const struct button_mapping *items = NULL; | 237 | const struct button_mapping *items = NULL; |
@@ -210,7 +239,7 @@ static int get_action_worker(int context, int timeout, | |||
210 | int i=0; | 239 | int i=0; |
211 | int ret = ACTION_UNKNOWN; | 240 | int ret = ACTION_UNKNOWN; |
212 | static int last_context = CONTEXT_STD; | 241 | static int last_context = CONTEXT_STD; |
213 | 242 | ||
214 | send_event(GUI_EVENT_ACTIONUPDATE, NULL); | 243 | send_event(GUI_EVENT_ACTIONUPDATE, NULL); |
215 | 244 | ||
216 | if (timeout == TIMEOUT_NOBLOCK) | 245 | if (timeout == TIMEOUT_NOBLOCK) |
@@ -222,7 +251,7 @@ static int get_action_worker(int context, int timeout, | |||
222 | 251 | ||
223 | #if defined(HAVE_GUI_BOOST) && defined(HAVE_ADJUSTABLE_CPU_FREQ) | 252 | #if defined(HAVE_GUI_BOOST) && defined(HAVE_ADJUSTABLE_CPU_FREQ) |
224 | static struct timeout gui_unboost; | 253 | static struct timeout gui_unboost; |
225 | /* Boost the CPU in case of wheel scrolling activity in the defined contexts. | 254 | /* Boost the CPU in case of wheel scrolling activity in the defined contexts. |
226 | * Call unboost with a timeout of GUI_BOOST_TIMEOUT. */ | 255 | * Call unboost with a timeout of GUI_BOOST_TIMEOUT. */ |
227 | if (button != BUTTON_NONE) | 256 | if (button != BUTTON_NONE) |
228 | { | 257 | { |
@@ -270,7 +299,7 @@ static int get_action_worker(int context, int timeout, | |||
270 | } | 299 | } |
271 | return ACTION_NONE; | 300 | return ACTION_NONE; |
272 | } | 301 | } |
273 | 302 | ||
274 | if ((context != last_context) && ((last_button & BUTTON_REL) == 0) | 303 | if ((context != last_context) && ((last_button & BUTTON_REL) == 0) |
275 | #ifdef HAVE_SCROLLWHEEL | 304 | #ifdef HAVE_SCROLLWHEEL |
276 | /* Scrollwheel doesn't generate release events */ | 305 | /* Scrollwheel doesn't generate release events */ |
@@ -288,39 +317,24 @@ static int get_action_worker(int context, int timeout, | |||
288 | return ACTION_NONE; /* "safest" return value */ | 317 | return ACTION_NONE; /* "safest" return value */ |
289 | } | 318 | } |
290 | last_context = context; | 319 | last_context = context; |
320 | |||
291 | #ifndef HAS_BUTTON_HOLD | 321 | #ifndef HAS_BUTTON_HOLD |
292 | screen_has_lock = ((context & ALLOW_SOFTLOCK) == ALLOW_SOFTLOCK); | 322 | screen_has_lock = ((context & ALLOW_SOFTLOCK) == ALLOW_SOFTLOCK); |
323 | context &= ~ALLOW_SOFTLOCK; | ||
293 | if (is_keys_locked()) | 324 | if (is_keys_locked()) |
294 | { | 325 | { |
295 | if (button == unlock_combo) | 326 | ret = do_softlock_unlock_combo(button, context); |
296 | { | 327 | if (!is_keys_locked()) |
297 | last_button = BUTTON_NONE; | 328 | return ret; |
298 | keys_locked = false; | ||
299 | #if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN) | ||
300 | /* enable back touch device */ | ||
301 | button_enable_touch(true); | ||
302 | #endif | ||
303 | splash(HZ/2, str(LANG_KEYLOCK_OFF)); | ||
304 | return ACTION_REDRAW; | ||
305 | } | ||
306 | else | ||
307 | #if (BUTTON_REMOTE != 0) | ||
308 | if ((button & BUTTON_REMOTE) == 0) | ||
309 | #endif | ||
310 | { | ||
311 | if ((button & BUTTON_REL)) | ||
312 | splash(HZ/2, str(LANG_KEYLOCK_ON)); | ||
313 | return ACTION_REDRAW; | ||
314 | } | ||
315 | } | 329 | } |
316 | #if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN) | 330 | #if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN) |
317 | else | 331 | else if (!mask_has_flag(softlock_mask, SEL_ACTION_NOTOUCH)) |
318 | { | 332 | { |
319 | /* make sure touchpad get reactivated if we quit the screen */ | 333 | /* make sure touchpad get reactivated if we quit the screen */ |
320 | button_enable_touch(true); | 334 | button_enable_touch(true); |
321 | } | 335 | } |
322 | #endif | 336 | #endif |
323 | context &= ~ALLOW_SOFTLOCK; | 337 | |
324 | #endif /* HAS_BUTTON_HOLD */ | 338 | #endif /* HAS_BUTTON_HOLD */ |
325 | 339 | ||
326 | #ifdef HAVE_TOUCHSCREEN | 340 | #ifdef HAVE_TOUCHSCREEN |
@@ -348,6 +362,7 @@ static int get_action_worker(int context, int timeout, | |||
348 | #endif | 362 | #endif |
349 | 363 | ||
350 | /* logf("%x,%x",last_button,button); */ | 364 | /* logf("%x,%x",last_button,button); */ |
365 | *is_pre_button = false; /* could the button be another actions pre_button */ | ||
351 | while (1) | 366 | while (1) |
352 | { | 367 | { |
353 | /* logf("context = %x",context); */ | 368 | /* logf("context = %x",context); */ |
@@ -363,7 +378,7 @@ static int get_action_worker(int context, int timeout, | |||
363 | if (items == NULL) | 378 | if (items == NULL) |
364 | break; | 379 | break; |
365 | 380 | ||
366 | ret = do_button_check(items,button,last_button,&i); | 381 | ret = do_button_check(items, button, last_button, &i, is_pre_button); |
367 | 382 | ||
368 | if (ret == ACTION_UNKNOWN) | 383 | if (ret == ACTION_UNKNOWN) |
369 | { | 384 | { |
@@ -375,24 +390,13 @@ static int get_action_worker(int context, int timeout, | |||
375 | continue; | 390 | continue; |
376 | } | 391 | } |
377 | } | 392 | } |
378 | |||
379 | /* Action was found or STOPSEARCHING was specified */ | 393 | /* Action was found or STOPSEARCHING was specified */ |
380 | break; | 394 | break; |
381 | } | 395 | } |
382 | /* DEBUGF("ret = %x\n",ret); */ | 396 | /* DEBUGF("ret = %x\n",ret); */ |
383 | #ifndef HAS_BUTTON_HOLD | 397 | #ifndef HAS_BUTTON_HOLD |
384 | if (screen_has_lock && (ret == ACTION_STD_KEYLOCK)) | 398 | if(screen_has_lock && is_action_normal(ret)) |
385 | { | 399 | ret = do_softlock(button, ret, last_context & ~ALLOW_SOFTLOCK, is_pre_button); |
386 | unlock_combo = button; | ||
387 | keys_locked = true; | ||
388 | splash(HZ/2, str(LANG_KEYLOCK_ON)); | ||
389 | #if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN) | ||
390 | /* disable touch device on keylock */ | ||
391 | button_enable_touch(false); | ||
392 | #endif | ||
393 | button_clear_queue(); | ||
394 | return ACTION_REDRAW; | ||
395 | } | ||
396 | #endif | 400 | #endif |
397 | if ((current_tick - last_action_tick < REPEAT_WINDOW_TICKS) | 401 | if ((current_tick - last_action_tick < REPEAT_WINDOW_TICKS) |
398 | && (ret == last_action)) | 402 | && (ret == last_action)) |
@@ -411,42 +415,46 @@ static int get_action_worker(int context, int timeout, | |||
411 | #endif | 415 | #endif |
412 | 416 | ||
413 | return ret; | 417 | return ret; |
414 | } | 418 | }/* get_action_worker */ |
415 | 419 | ||
416 | int get_action(int context, int timeout) | 420 | int get_action(int context, int timeout) |
417 | { | 421 | { |
418 | int button = get_action_worker(context,timeout,NULL); | 422 | bool is_pre_button = false; |
423 | int button = get_action_worker(context, timeout, &is_pre_button, NULL); | ||
424 | |||
419 | #ifdef HAVE_TOUCHSCREEN | 425 | #ifdef HAVE_TOUCHSCREEN |
420 | if (button == ACTION_TOUCHSCREEN) | 426 | if (button == ACTION_TOUCHSCREEN) |
421 | button = sb_touch_to_button(context); | 427 | button = sb_touch_to_button(context); |
422 | #endif | 428 | #endif |
429 | |||
430 | #ifdef HAVE_BACKLIGHT | ||
431 | if (mask_has_flag(backlight_mask, SEL_ACTION_ENABLED) && | ||
432 | is_action_normal(button)) | ||
433 | button = do_backlight(button, context & ~ALLOW_SOFTLOCK, is_pre_button); | ||
434 | #endif | ||
435 | |||
423 | return button; | 436 | return button; |
424 | } | 437 | } |
425 | 438 | ||
426 | int get_custom_action(int context,int timeout, | 439 | int get_custom_action(int context,int timeout, |
427 | const struct button_mapping* (*get_context_map)(int)) | 440 | const struct button_mapping* (*get_context_map)(int)) |
428 | { | 441 | { |
429 | return get_action_worker(context,timeout,get_context_map); | 442 | bool is_pre_button = false; |
443 | return get_action_worker(context,timeout, &is_pre_button, get_context_map); | ||
430 | } | 444 | } |
431 | 445 | ||
432 | bool action_userabort(int timeout) | 446 | bool action_userabort(int timeout) |
433 | { | 447 | { |
434 | int action = get_action_worker(CONTEXT_STD,timeout,NULL); | 448 | bool is_pre_button = false; |
449 | int action = get_action_worker(CONTEXT_STD,timeout, &is_pre_button, NULL); | ||
435 | bool ret = (action == ACTION_STD_CANCEL); | 450 | bool ret = (action == ACTION_STD_CANCEL); |
436 | if(!ret) | 451 | if (!ret) |
437 | { | 452 | { |
438 | default_event_handler(action); | 453 | default_event_handler(action); |
439 | } | 454 | } |
440 | return ret; | 455 | return ret; |
441 | } | 456 | } |
442 | 457 | ||
443 | #ifndef HAS_BUTTON_HOLD | ||
444 | bool is_keys_locked(void) | ||
445 | { | ||
446 | return (screen_has_lock && keys_locked); | ||
447 | } | ||
448 | #endif | ||
449 | |||
450 | intptr_t get_action_data(void) | 458 | intptr_t get_action_data(void) |
451 | { | 459 | { |
452 | return last_data; | 460 | return last_data; |
@@ -532,4 +540,338 @@ void action_wait_for_release(void) | |||
532 | { | 540 | { |
533 | wait_for_release = true; | 541 | wait_for_release = true; |
534 | } | 542 | } |
535 | 543 | ||
544 | #if defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD) | ||
545 | /* HELPER FUNCTIONS | ||
546 | * Selective softlock and backlight use this lookup based on mask to decide | ||
547 | * which actions are filtered, or could be filtered but not currently set. | ||
548 | * returns false if the action isn't found, true if the action is found | ||
549 | */ | ||
550 | static bool is_action_filtered(int action, unsigned int mask, int context) | ||
551 | { | ||
552 | bool match = false; | ||
553 | |||
554 | switch (action) | ||
555 | { | ||
556 | case ACTION_NONE: | ||
557 | break; | ||
558 | /*Actions that are not mapped will not turn on the backlight option NOUNMAPPED*/ | ||
559 | case ACTION_UNKNOWN: | ||
560 | match = mask_has_flag(mask, SEL_ACTION_NOUNMAPPED); | ||
561 | break; | ||
562 | case ACTION_WPS_PLAY: | ||
563 | case ACTION_FM_PLAY: | ||
564 | match = mask_has_flag(mask, SEL_ACTION_PLAY); | ||
565 | break; | ||
566 | case ACTION_STD_PREVREPEAT: | ||
567 | case ACTION_STD_NEXTREPEAT: | ||
568 | case ACTION_WPS_SEEKBACK: | ||
569 | case ACTION_WPS_SEEKFWD: | ||
570 | case ACTION_WPS_STOPSEEK: | ||
571 | match = mask_has_flag(mask, SEL_ACTION_SEEK); | ||
572 | break; | ||
573 | case ACTION_STD_PREV: | ||
574 | case ACTION_STD_NEXT: | ||
575 | case ACTION_WPS_SKIPNEXT: | ||
576 | case ACTION_WPS_SKIPPREV: | ||
577 | case ACTION_FM_NEXT_PRESET: | ||
578 | case ACTION_FM_PREV_PRESET: | ||
579 | match = mask_has_flag(mask, SEL_ACTION_SKIP); | ||
580 | break; | ||
581 | case ACTION_WPS_VOLUP: | ||
582 | case ACTION_WPS_VOLDOWN: | ||
583 | match = mask_has_flag(mask, SEL_ACTION_VOL); | ||
584 | break; | ||
585 | case ACTION_SETTINGS_INC:/*FMS*/ | ||
586 | case ACTION_SETTINGS_INCREPEAT:/*FMS*/ | ||
587 | case ACTION_SETTINGS_DEC:/*FMS*/ | ||
588 | case ACTION_SETTINGS_DECREPEAT:/*FMS*/ | ||
589 | match = (context == CONTEXT_FM) && mask_has_flag(mask, SEL_ACTION_VOL); | ||
590 | break; | ||
591 | default: | ||
592 | /* display action code of unfiltered actions */ | ||
593 | logf ("unfiltered actions: context: %d action: %d, last btn: %d, \ | ||
594 | mask: %d", context, action, last_button, mask); | ||
595 | break; | ||
596 | }/*switch*/ | ||
597 | |||
598 | return match; | ||
599 | } | ||
600 | /* compares mask to a flag return true if set false otherwise*/ | ||
601 | static inline bool mask_has_flag(unsigned int mask, unsigned int flag) | ||
602 | { | ||
603 | return ((mask & flag) != 0); | ||
604 | } | ||
605 | /* returns true if the supplied context is to be filtered by selective BL/SL*/ | ||
606 | static inline bool is_context_filtered(int context) | ||
607 | { | ||
608 | return (context == CONTEXT_FM || context == CONTEXT_WPS); | ||
609 | } | ||
610 | /* returns true if action can be passed on to selective backlight/softlock */ | ||
611 | static inline bool is_action_normal(int action) | ||
612 | { | ||
613 | return (action != ACTION_REDRAW && (action & SYS_EVENT) == 0); | ||
614 | } | ||
615 | /*returns true if Button & released, repeated; or won't generate those events*/ | ||
616 | static inline bool is_action_completed(int button) | ||
617 | { | ||
618 | return ((button & (BUTTON_REPEAT | BUTTON_REL)) != 0 | ||
619 | #ifdef HAVE_SCROLLWHEEL | ||
620 | /* Scrollwheel doesn't generate release events */ | ||
621 | || (button & (BUTTON_SCROLL_BACK | BUTTON_SCROLL_FWD)) != 0 | ||
622 | #endif | ||
623 | ); | ||
624 | } | ||
625 | |||
626 | /* most every action takes two rounds through get_action_worker, | ||
627 | * once for the keypress and once for the key release, | ||
628 | * actions with pre_button codes take even more, some actions however, only | ||
629 | * take once; actions defined with only a button and no release/repeat event, | ||
630 | * these actions should be acted upon immediately except when we have | ||
631 | * selective backlighting/softlock enabled and in this case we only act upon | ||
632 | * them immediately if there is no chance they have another event tied to them | ||
633 | * determined using is_pre_button and is_action_completed() | ||
634 | *returns true if event was not filtered and false if it was | ||
635 | */ | ||
636 | static bool is_action_unfiltered(int action,int button, bool is_pre_button, | ||
637 | bool filtered, int *tick) | ||
638 | { | ||
639 | bool ret = false; | ||
640 | /*directly after a match a key release event may trigger another*/ | ||
641 | if (filtered && action != ACTION_UNKNOWN) | ||
642 | *tick = current_tick + LAST_FILTER_TICKS; | ||
643 | /* has button been rel/rep or is this the only action it could be */ | ||
644 | if (is_action_completed(button) || !is_pre_button) | ||
645 | { | ||
646 | /* reset last action , if the action is not filtered and | ||
647 | this isn't just a key release event then return true */ | ||
648 | if (!filtered && *tick < current_tick) | ||
649 | { | ||
650 | *tick = 0; | ||
651 | ret = true; | ||
652 | } | ||
653 | }/*is_action_completed() || !is_pre_button*/ | ||
654 | return ret; | ||
655 | } | ||
656 | #endif /*defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD) HELPER FUNCTIONS*/ | ||
657 | |||
658 | #ifdef HAVE_BACKLIGHT | ||
659 | static void handle_backlight(bool backlight, bool ignore_next) | ||
660 | { | ||
661 | if (backlight) | ||
662 | { | ||
663 | backlight_on_ignore(false, 0); | ||
664 | backlight_on(); | ||
665 | #ifdef HAVE_BUTTON_LIGHT | ||
666 | buttonlight_on_ignore(false, 0); | ||
667 | buttonlight_on(); | ||
668 | } | ||
669 | buttonlight_on_ignore(ignore_next, 5*HZ);/* as a precautionary fallback */ | ||
670 | #else | ||
671 | } | ||
672 | #endif | ||
673 | backlight_on_ignore(ignore_next, 5*HZ);/*must be set everytime we handle bl*/ | ||
674 | } | ||
675 | |||
676 | /* Need to look up actions before we can decide to turn on backlight, if | ||
677 | * selective backlighting is true filter first keypress events need to be | ||
678 | * taken into account as well | ||
679 | */ | ||
680 | static int do_backlight(int action, int context, bool is_pre_btn) | ||
681 | { | ||
682 | static int last_filtered_tick = 0; | ||
683 | |||
684 | bool bl_is_active = is_backlight_on(false); | ||
685 | bool bl_activate = false; | ||
686 | bool filtered; | ||
687 | |||
688 | #if CONFIG_CHARGING /* disable if on external power */ | ||
689 | if (!bl_is_active && is_context_filtered(context) && | ||
690 | !(mask_has_flag(backlight_mask, SEL_ACTION_NOEXT) && power_input_present())) | ||
691 | #else /* skip if backlight is on or incorrect context */ | ||
692 | if (!bl_is_active && is_context_filtered(context)) | ||
693 | #endif | ||
694 | { | ||
695 | filtered = is_action_filtered(action, backlight_mask, context); | ||
696 | bl_activate = is_action_unfiltered(action, last_button, is_pre_btn, | ||
697 | filtered, &last_filtered_tick); | ||
698 | }/*is_context_filtered(context)*/ | ||
699 | else | ||
700 | bl_activate = true; | ||
701 | |||
702 | if (action != ACTION_NONE && bl_activate) | ||
703 | { | ||
704 | handle_backlight(true, true); | ||
705 | |||
706 | if (mask_has_flag(backlight_mask, SEL_ACTION_FFKEYPRESS) && !bl_is_active) | ||
707 | { | ||
708 | action = ACTION_NONE; | ||
709 | last_button = BUTTON_NONE; | ||
710 | } | ||
711 | } | ||
712 | else | ||
713 | handle_backlight(false, true);/* set ignore next true */ | ||
714 | |||
715 | return action; | ||
716 | } | ||
717 | |||
718 | /* Enable selected actions to leave the backlight off */ | ||
719 | void set_selective_backlight_actions(bool selective, unsigned int mask, | ||
720 | bool filter_fkp) | ||
721 | { | ||
722 | handle_backlight(true, selective); | ||
723 | if (selective) /* we will handle filter_first_keypress here so turn it off*/ | ||
724 | { | ||
725 | set_backlight_filter_keypress(false);/* turnoff ffkp in button.c */ | ||
726 | backlight_mask = mask | SEL_ACTION_ENABLED; | ||
727 | if(filter_fkp) | ||
728 | backlight_mask |= SEL_ACTION_FFKEYPRESS; | ||
729 | } | ||
730 | else | ||
731 | { | ||
732 | set_backlight_filter_keypress(filter_fkp); | ||
733 | backlight_mask = SEL_ACTION_NONE; | ||
734 | } | ||
735 | } | ||
736 | #endif /* HAVE_BACKLIGHT */ | ||
737 | |||
738 | #ifndef HAS_BUTTON_HOLD | ||
739 | bool is_keys_locked(void) | ||
740 | { | ||
741 | return (screen_has_lock && keys_locked); | ||
742 | } | ||
743 | |||
744 | static inline void do_key_lock(bool lock) | ||
745 | { | ||
746 | keys_locked = lock; | ||
747 | last_button = BUTTON_NONE; | ||
748 | button_clear_queue(); | ||
749 | #if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN) | ||
750 | /* disable touch device on keylock if std behavior or selected disable touch */ | ||
751 | if (!mask_has_flag(softlock_mask, SEL_ACTION_ENABLED) || | ||
752 | mask_has_flag(softlock_mask, SEL_ACTION_NOTOUCH)) | ||
753 | button_enable_touch(!lock); | ||
754 | #endif | ||
755 | } | ||
756 | |||
757 | /* user selected autolock based on backlight timeout; toggles autolock on / off | ||
758 | by ACTION_STD_KEYLOCK presses, Activates autolock if set on backlight timeout | ||
759 | */ | ||
760 | #ifdef HAVE_BACKLIGHT | ||
761 | static inline int do_auto_softlock(int button, int action, int *unlock_combo) | ||
762 | { | ||
763 | if(mask_has_flag(softlock_mask, SEL_ACTION_ALOCK_OK) && !is_backlight_on(false)) | ||
764 | do_key_lock(true); | ||
765 | |||
766 | else if (action == ACTION_STD_KEYLOCK) | ||
767 | { | ||
768 | *unlock_combo = button;/* set unlock combo to allow unlock */ | ||
769 | softlock_mask ^= SEL_ACTION_ALOCK_OK; | ||
770 | handle_backlight(true, false); | ||
771 | /* If we don't wait for a moment for the backlight queue | ||
772 | * to process, the user will never see the message */ | ||
773 | if (!is_backlight_on(false)) | ||
774 | sleep(HZ/2); | ||
775 | |||
776 | if (mask_has_flag(softlock_mask, SEL_ACTION_ALOCK_OK)) | ||
777 | { | ||
778 | splash(HZ/2, ID2P(LANG_ACTION_AUTOLOCK_ON)); | ||
779 | action = ACTION_REDRAW; | ||
780 | } | ||
781 | else | ||
782 | splash(HZ/2, ID2P(LANG_ACTION_AUTOLOCK_OFF)); | ||
783 | } | ||
784 | return action; | ||
785 | } | ||
786 | #endif | ||
787 | |||
788 | /* Allows unlock softlock when action is not yet known but unlock_combo set*/ | ||
789 | static inline int do_softlock_unlock_combo(int button, int context) | ||
790 | { | ||
791 | return do_softlock(button, ACTION_NONE, context, false); | ||
792 | } | ||
793 | |||
794 | /* Handles softlock once action is known */ | ||
795 | static int do_softlock(int button, int action, int context, bool is_pre_btn) | ||
796 | { | ||
797 | static int last_filtered_tick = 0; | ||
798 | static int unlock_combo = BUTTON_NONE; /*Moved from GLOBAL*/ | ||
799 | bool filtered = true; | ||
800 | bool notify_user = false; | ||
801 | bool sl_activate = true; /* standard softlock behavior */ | ||
802 | |||
803 | #ifdef HAVE_BACKLIGHT | ||
804 | if (!keys_locked && mask_has_flag(softlock_mask, SEL_ACTION_AUTOLOCK)) | ||
805 | action = do_auto_softlock(button, action, &unlock_combo); | ||
806 | #endif | ||
807 | /* Lock/Unlock toggled by ACTION_STD_KEYLOCK presses*/ | ||
808 | if ((action == ACTION_STD_KEYLOCK) || (keys_locked && unlock_combo == button)) | ||
809 | { | ||
810 | unlock_combo = button; | ||
811 | do_key_lock(!keys_locked); | ||
812 | notify_user = true; | ||
813 | } | ||
814 | #if (BUTTON_REMOTE != 0)/* Allow remote actions through */ | ||
815 | else if (mask_has_flag(button, BUTTON_REMOTE)) | ||
816 | notify_user = false; | ||
817 | #endif | ||
818 | else if (keys_locked && action != ACTION_NONE && action != ACTION_REDRAW) | ||
819 | { | ||
820 | if (mask_has_flag(softlock_mask, SEL_ACTION_ENABLED)) | ||
821 | { | ||
822 | filtered = is_action_filtered(action, softlock_mask, context); | ||
823 | |||
824 | sl_activate = is_action_unfiltered(action, button, is_pre_btn, | ||
825 | filtered, &last_filtered_tick); | ||
826 | } | ||
827 | /*All non-std softlock options are set to 0 if advanced sl is disabled*/ | ||
828 | if (sl_activate) | ||
829 | { | ||
830 | if (!mask_has_flag(softlock_mask, SEL_ACTION_NONOTIFY)) | ||
831 | { /* always true on standard softlock behavior*/ | ||
832 | notify_user = mask_has_flag(button, BUTTON_REL); | ||
833 | action = ACTION_REDRAW; | ||
834 | } | ||
835 | else | ||
836 | action = ACTION_NONE; | ||
837 | } | ||
838 | else if (!filtered)/*catch blocked actions on fast repeated presses*/ | ||
839 | action = ACTION_NONE; | ||
840 | } /* keys_locked */ | ||
841 | |||
842 | #ifdef BUTTON_POWER /*always notify if power button pressed while keys locked*/ | ||
843 | notify_user |= (mask_has_flag(button, BUTTON_POWER) && keys_locked); | ||
844 | #endif | ||
845 | |||
846 | if (notify_user) | ||
847 | { | ||
848 | #ifdef HAVE_BACKLIGHT | ||
849 | handle_backlight(true, false); | ||
850 | /* If we don't wait for a moment for the backlight queue | ||
851 | * to process, the user will never see the message */ | ||
852 | if (!is_backlight_on(false)) | ||
853 | sleep(HZ/2); | ||
854 | #endif | ||
855 | if (keys_locked) | ||
856 | splash(HZ/2, ID2P(LANG_KEYLOCK_ON)); | ||
857 | else | ||
858 | splash(HZ/2, ID2P(LANG_KEYLOCK_OFF)); | ||
859 | |||
860 | last_button = BUTTON_NONE; | ||
861 | action = ACTION_REDRAW; | ||
862 | button_clear_queue(); | ||
863 | } | ||
864 | |||
865 | return action; | ||
866 | } | ||
867 | |||
868 | void set_selective_softlock_actions(bool selective, unsigned int mask) | ||
869 | { | ||
870 | keys_locked = false; | ||
871 | if(selective) | ||
872 | softlock_mask = mask | SEL_ACTION_ENABLED; | ||
873 | else | ||
874 | softlock_mask = SEL_ACTION_NONE; | ||
875 | } | ||
876 | |||
877 | #endif /* HAS_BUTTON_HOLD */ | ||