summaryrefslogtreecommitdiff
path: root/apps/action.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/action.c')
-rw-r--r--apps/action.c466
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
45static int last_button = BUTTON_NONE|BUTTON_REL; /* allow the ipod wheel to 55static int last_button = BUTTON_NONE|BUTTON_REL; /* allow the ipod wheel to
46 work on startup */ 56 work on startup */
47static intptr_t last_data = 0; 57static 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
57static int last_action_tick = 0; 67static int last_action_tick = 0;
58 68
69#if defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD)
70static inline bool is_action_normal(int action);
71static inline bool mask_has_flag(unsigned int mask, unsigned int flag);
72static 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
77static unsigned int backlight_mask = SEL_ACTION_NONE;
78static int do_backlight(int action, int context, bool is_pre_btn);
79static 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
61static bool keys_locked = false; 84static bool keys_locked = false;
62static int unlock_combo = BUTTON_NONE;
63static bool screen_has_lock = false; 85static bool screen_has_lock = false;
86static unsigned int softlock_mask = SEL_ACTION_NONE;
87static inline int do_softlock_unlock_combo(int button, int context);
88static 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 */
70static inline int do_button_check(const struct button_mapping *items, 95static 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)
164static void gui_boost(bool want_to_boost) 191static 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. */
182static int gui_unboost_callback(struct timeout *tmo) 209static 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 */
205static int get_action_worker(int context, int timeout, 234static 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
416int get_action(int context, int timeout) 420int 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
426int get_custom_action(int context,int timeout, 439int 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
432bool action_userabort(int timeout) 446bool 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
444bool is_keys_locked(void)
445{
446 return (screen_has_lock && keys_locked);
447}
448#endif
449
450intptr_t get_action_data(void) 458intptr_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*/
550static 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*/
601static 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*/
606static 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 */
611static 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*/
616static 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*/
636static 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
659static 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 */
680static 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 */
719void 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
739bool is_keys_locked(void)
740{
741 return (screen_has_lock && keys_locked);
742}
743
744static 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
761static 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*/
789static inline int do_softlock_unlock_combo(int button, int context)
790{
791return do_softlock(button, ACTION_NONE, context, false);
792}
793
794/* Handles softlock once action is known */
795static 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
868void 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 */