Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
Jonathan Gordon | f787242 | 2006-08-16 08:07:59 +0000 | [diff] [blame] | 8 | * $Id$ |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 9 | * |
| 10 | * Copyright (C) 2006 Jonathan Gordon |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 11 | * |
Daniel Stenberg | 2acc0ac | 2008-06-28 18:10:04 +0000 | [diff] [blame] | 12 | * This program is free software; you can redistribute it and/or |
| 13 | * modify it under the terms of the GNU General Public License |
| 14 | * as published by the Free Software Foundation; either version 2 |
| 15 | * of the License, or (at your option) any later version. |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 16 | * |
| 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 18 | * KIND, either express or implied. |
| 19 | * |
| 20 | ****************************************************************************/ |
| 21 | #include <stdio.h> |
| 22 | #include <string.h> |
| 23 | #include <stdlib.h> |
| 24 | |
| 25 | #include "config.h" |
Jonathan Gordon | b973156 | 2006-08-17 13:31:34 +0000 | [diff] [blame] | 26 | #include "lang.h" |
| 27 | |
Jonathan Gordon | 8b9fdb5 | 2009-01-05 09:59:11 +0000 | [diff] [blame] | 28 | #include "appevents.h" |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 29 | #include "button.h" |
| 30 | #include "action.h" |
| 31 | #include "kernel.h" |
| 32 | #include "debug.h" |
Jonathan Gordon | f178131 | 2006-08-17 12:33:36 +0000 | [diff] [blame] | 33 | #include "splash.h" |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 34 | #include "settings.h" |
| 35 | #include "pcmbuf.h" |
Frank Gevaerts | c61076e | 2009-06-11 20:36:02 +0000 | [diff] [blame] | 36 | #include "misc.h" |
Tomer Shalev | f7bd725 | 2009-10-05 17:17:30 +0000 | [diff] [blame] | 37 | #if defined(HAVE_LCD_BITMAP) && !defined(BOOTLOADER) |
| 38 | #include "language.h" |
| 39 | #endif |
Thomas Martitz | 891c446 | 2009-10-11 20:11:48 +0000 | [diff] [blame] | 40 | #include "viewport.h" |
Jonathan Gordon | a398c28 | 2010-06-21 06:04:19 +0000 | [diff] [blame] | 41 | #ifdef HAVE_TOUCHSCREEN |
| 42 | #include "statusbar-skinned.h" |
| 43 | #endif |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 44 | |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 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 | |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 55 | static int last_button = BUTTON_NONE|BUTTON_REL; /* allow the ipod wheel to |
Jonathan Gordon | f7675a2 | 2007-07-22 06:05:53 +0000 | [diff] [blame] | 56 | work on startup */ |
Michael Sevakis | 873e0fd | 2007-07-22 21:02:24 +0000 | [diff] [blame] | 57 | static intptr_t last_data = 0; |
Jonathan Gordon | ca701bf | 2007-03-04 07:45:12 +0000 | [diff] [blame] | 58 | static int last_action = ACTION_NONE; |
| 59 | static bool repeated = false; |
Jonathan Gordon | 0e445fc | 2009-07-03 05:08:33 +0000 | [diff] [blame] | 60 | static bool wait_for_release = false; |
Jonathan Gordon | f178131 | 2006-08-17 12:33:36 +0000 | [diff] [blame] | 61 | |
Maurus Cuelenaere | 1392dc2 | 2008-08-23 09:46:38 +0000 | [diff] [blame] | 62 | #ifdef HAVE_TOUCHSCREEN |
Jonathan Gordon | fa13cbe | 2007-10-22 12:26:53 +0000 | [diff] [blame] | 63 | static bool short_press = false; |
| 64 | #endif |
| 65 | |
Andree Buschmann | afe6ee4 | 2011-03-24 18:42:27 +0000 | [diff] [blame] | 66 | #define REPEAT_WINDOW_TICKS HZ/4 |
Jonathan Gordon | 63c8511 | 2007-06-04 13:52:02 +0000 | [diff] [blame] | 67 | static int last_action_tick = 0; |
| 68 | |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 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 | |
Jonathan Gordon | f178131 | 2006-08-17 12:33:36 +0000 | [diff] [blame] | 82 | /* software keylock stuff */ |
| 83 | #ifndef HAS_BUTTON_HOLD |
Jens Arnold | a0f3113 | 2006-12-12 07:55:17 +0000 | [diff] [blame] | 84 | static bool keys_locked = false; |
Jens Arnold | a0f3113 | 2006-12-12 07:55:17 +0000 | [diff] [blame] | 85 | static bool screen_has_lock = false; |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 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); |
Jonathan Gordon | f178131 | 2006-08-17 12:33:36 +0000 | [diff] [blame] | 89 | #endif /* HAVE_SOFTWARE_KEYLOCK */ |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 90 | /* |
| 91 | * do_button_check is the worker function for get_default_action. |
| 92 | * returns ACTION_UNKNOWN or the requested return value from the list. |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 93 | * BE AWARE is_pre_button can miss pre buttons if a match is found first. |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 94 | */ |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 95 | static inline int do_button_check(const struct button_mapping *items,int button, |
| 96 | int last_button, int *start, bool *prebtn) |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 97 | { |
| 98 | int i = 0; |
| 99 | int ret = ACTION_UNKNOWN; |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 100 | |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 101 | while (items[i].button_code != BUTTON_NONE) |
| 102 | { |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 103 | if (items[i].button_code == button) |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 104 | { |
Udo Schläpfer | dbabd0d | 2015-02-02 21:44:29 +0100 | [diff] [blame] | 105 | /* |
| 106 | CAVEAT: This will allways return the action without pre_button_code if it has a |
| 107 | lower index in the list. |
| 108 | */ |
Jens Arnold | 1fdb5bf | 2006-08-16 00:32:45 +0000 | [diff] [blame] | 109 | if ((items[i].pre_button_code == BUTTON_NONE) |
| 110 | || (items[i].pre_button_code == last_button)) |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 111 | { |
| 112 | ret = items[i].action_code; |
| 113 | break; |
| 114 | } |
| 115 | } |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 116 | else if (items[i].pre_button_code & button) |
| 117 | *prebtn = true; /* determine if this could be another action */ |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 118 | i++; |
| 119 | } |
| 120 | *start = i; |
| 121 | return ret; |
| 122 | } |
| 123 | |
Tomer Shalev | a39be4b | 2009-10-05 17:53:45 +0000 | [diff] [blame] | 124 | #if defined(HAVE_LCD_BITMAP) && !defined(BOOTLOADER) |
| 125 | /* |
| 126 | * button is horizontally inverted to support RTL language if the given language |
| 127 | * and context combination require that |
| 128 | */ |
| 129 | static int button_flip_horizontally(int context, int button) |
| 130 | { |
| 131 | int newbutton; |
| 132 | |
| 133 | if (!(lang_is_rtl() && ((context == CONTEXT_STD) || |
Tomer Shalev | 694ea7e | 2009-10-08 22:19:36 +0000 | [diff] [blame] | 134 | (context == CONTEXT_TREE) || (context == CONTEXT_LIST) || |
| 135 | (context == CONTEXT_MAINMENU)))) |
Tomer Shalev | a39be4b | 2009-10-05 17:53:45 +0000 | [diff] [blame] | 136 | { |
| 137 | return button; |
| 138 | } |
| 139 | |
| 140 | newbutton = button & |
| 141 | ~(BUTTON_LEFT | BUTTON_RIGHT |
Tomer Shalev | 191ce8c | 2009-10-06 18:01:05 +0000 | [diff] [blame] | 142 | #if defined(BUTTON_SCROLL_BACK) && defined(BUTTON_SCROLL_FWD) && \ |
| 143 | !defined(SIMULATOR) |
Tomer Shalev | a39be4b | 2009-10-05 17:53:45 +0000 | [diff] [blame] | 144 | | BUTTON_SCROLL_BACK | BUTTON_SCROLL_FWD |
| 145 | #endif |
Tomer Shalev | 3deed06 | 2009-12-05 15:54:05 +0000 | [diff] [blame] | 146 | #if defined(BUTTON_MINUS) && defined(BUTTON_PLUS) && \ |
| 147 | !defined(SIMULATOR) |
| 148 | | BUTTON_MINUS | BUTTON_PLUS |
| 149 | #endif |
Tomer Shalev | a39be4b | 2009-10-05 17:53:45 +0000 | [diff] [blame] | 150 | ); |
| 151 | |
| 152 | if (button & BUTTON_LEFT) |
| 153 | newbutton |= BUTTON_RIGHT; |
| 154 | if (button & BUTTON_RIGHT) |
| 155 | newbutton |= BUTTON_LEFT; |
Tomer Shalev | 191ce8c | 2009-10-06 18:01:05 +0000 | [diff] [blame] | 156 | #if defined(BUTTON_SCROLL_BACK) && defined(BUTTON_SCROLL_FWD) && \ |
| 157 | !defined(SIMULATOR) |
Tomer Shalev | a39be4b | 2009-10-05 17:53:45 +0000 | [diff] [blame] | 158 | if (button & BUTTON_SCROLL_BACK) |
| 159 | newbutton |= BUTTON_SCROLL_FWD; |
| 160 | if (button & BUTTON_SCROLL_FWD) |
| 161 | newbutton |= BUTTON_SCROLL_BACK; |
| 162 | #endif |
Tomer Shalev | 3deed06 | 2009-12-05 15:54:05 +0000 | [diff] [blame] | 163 | #if defined(BUTTON_MINUS) && defined(BUTTON_PLUS) && \ |
| 164 | !defined(SIMULATOR) |
| 165 | if (button & BUTTON_MINUS) |
| 166 | newbutton |= BUTTON_PLUS; |
| 167 | if (button & BUTTON_PLUS) |
| 168 | newbutton |= BUTTON_MINUS; |
| 169 | #endif |
Tomer Shalev | a39be4b | 2009-10-05 17:53:45 +0000 | [diff] [blame] | 170 | |
| 171 | return newbutton; |
| 172 | } |
| 173 | #endif |
| 174 | |
Jens Arnold | a0f3113 | 2006-12-12 07:55:17 +0000 | [diff] [blame] | 175 | static inline int get_next_context(const struct button_mapping *items, int i) |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 176 | { |
| 177 | while (items[i].button_code != BUTTON_NONE) |
| 178 | i++; |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 179 | return (items[i].action_code == ACTION_NONE ) ? |
| 180 | CONTEXT_STD : |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 181 | items[i].action_code; |
| 182 | } |
Andree Buschmann | f1ee740 | 2011-11-11 19:40:32 +0000 | [diff] [blame] | 183 | |
Andree Buschmann | f1ee740 | 2011-11-11 19:40:32 +0000 | [diff] [blame] | 184 | |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 185 | /* |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 186 | * int get_action_worker(int context, int timeout, bool *is_pre_button, |
| 187 | struct button_mapping *user_mappings) |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 188 | This function searches the button list for the given context for the just |
| 189 | pressed button. |
| 190 | If there is a match it returns the value from the list. |
| 191 | If there is no match.. |
| 192 | the last item in the list "points" to the next context in a chain |
| 193 | so the "chain" is followed until the button is found. |
| 194 | putting ACTION_NONE will get CONTEXT_STD which is always the last list checked. |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 195 | BE AWARE is_pre_button can miss pre buttons if a match is found first. |
| 196 | it is more for actions that are not yet completed in the desired context |
| 197 | but are defined in a lower 'chained' context. |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 198 | Timeout can be TIMEOUT_NOBLOCK to return immediatly |
| 199 | TIMEOUT_BLOCK to wait for a button press |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 200 | Any number >0 to wait that many ticks for a press |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 201 | */ |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 202 | static int get_action_worker(int context, int timeout, bool *is_pre_button, |
Jens Arnold | a0f3113 | 2006-12-12 07:55:17 +0000 | [diff] [blame] | 203 | const struct button_mapping* (*get_context_map)(int) ) |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 204 | { |
Jens Arnold | 1fdb5bf | 2006-08-16 00:32:45 +0000 | [diff] [blame] | 205 | const struct button_mapping *items = NULL; |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 206 | int button; |
| 207 | int i=0; |
| 208 | int ret = ACTION_UNKNOWN; |
Jonathan Gordon | f7675a2 | 2007-07-22 06:05:53 +0000 | [diff] [blame] | 209 | static int last_context = CONTEXT_STD; |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 210 | |
Jonathan Gordon | 8b9fdb5 | 2009-01-05 09:59:11 +0000 | [diff] [blame] | 211 | send_event(GUI_EVENT_ACTIONUPDATE, NULL); |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 212 | |
Michael Sevakis | c6299b2 | 2017-01-21 08:09:48 -0500 | [diff] [blame] | 213 | button = button_get_w_tmo(timeout); |
Andree Buschmann | f1ee740 | 2011-11-11 19:40:32 +0000 | [diff] [blame] | 214 | |
Thomas Martitz | 49f1ec8 | 2010-10-31 15:32:57 +0000 | [diff] [blame] | 215 | /* Data from sys events can be pulled with button_get_data |
| 216 | * multimedia button presses don't go through the action system */ |
| 217 | if (button == BUTTON_NONE || button & (SYS_EVENT|BUTTON_MULTIMEDIA)) |
Thomas Martitz | 54e6baf | 2012-07-18 10:25:32 +0200 | [diff] [blame] | 218 | { |
| 219 | /* no button pressed so no point in waiting for release */ |
| 220 | if (button == BUTTON_NONE) |
| 221 | wait_for_release = false; |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 222 | return button; |
Thomas Martitz | 54e6baf | 2012-07-18 10:25:32 +0200 | [diff] [blame] | 223 | } |
| 224 | |
Thomas Martitz | bb0e4cc | 2012-04-05 13:00:05 +0200 | [diff] [blame] | 225 | /* the special redraw button should result in a screen refresh */ |
| 226 | if (button == BUTTON_REDRAW) |
| 227 | return ACTION_REDRAW; |
| 228 | |
Thomas Martitz | 54e6baf | 2012-07-18 10:25:32 +0200 | [diff] [blame] | 229 | /* if action_wait_for_release() was called without a button being pressed |
| 230 | * then actually waiting for release would do the wrong thing, i.e. |
| 231 | * the next key press is entirely ignored. So, if here comes a normal |
| 232 | * button press (neither release nor repeat) the press is a fresh one and |
| 233 | * no point in waiting for release |
| 234 | * |
| 235 | * This logic doesn't work for touchscreen which can send normal |
| 236 | * button events repeatedly before the first repeat (as in BUTTON_REPEAT). |
| 237 | * These cannot be distinguished from the very first touch |
| 238 | * but there's nothing we can do about it here */ |
| 239 | if ((button & (BUTTON_REPEAT|BUTTON_REL)) == 0) |
| 240 | wait_for_release = false; |
| 241 | |
Jonathan Gordon | 0e445fc | 2009-07-03 05:08:33 +0000 | [diff] [blame] | 242 | /* Don't send any buttons through untill we see the release event */ |
| 243 | if (wait_for_release) |
| 244 | { |
| 245 | if (button&BUTTON_REL) |
| 246 | { |
Thomas Martitz | 430ada0 | 2011-02-02 18:30:10 +0000 | [diff] [blame] | 247 | /* remember the button for the below button eating on context |
| 248 | * change */ |
| 249 | last_button = button; |
Jonathan Gordon | 0e445fc | 2009-07-03 05:08:33 +0000 | [diff] [blame] | 250 | wait_for_release = false; |
| 251 | } |
| 252 | return ACTION_NONE; |
| 253 | } |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 254 | |
Magnus Holmgren | 4480e3a | 2010-11-14 13:13:06 +0000 | [diff] [blame] | 255 | if ((context != last_context) && ((last_button & BUTTON_REL) == 0) |
| 256 | #ifdef HAVE_SCROLLWHEEL |
| 257 | /* Scrollwheel doesn't generate release events */ |
| 258 | && !(last_button & (BUTTON_SCROLL_BACK | BUTTON_SCROLL_FWD)) |
| 259 | #endif |
| 260 | ) |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 261 | { |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 262 | if (button & BUTTON_REL) |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 263 | { |
Jonathan Gordon | f7675a2 | 2007-07-22 06:05:53 +0000 | [diff] [blame] | 264 | last_button = button; |
| 265 | last_action = ACTION_NONE; |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 266 | } |
Jonathan Gordon | f7675a2 | 2007-07-22 06:05:53 +0000 | [diff] [blame] | 267 | /* eat all buttons until the previous button was |BUTTON_REL |
| 268 | (also eat the |BUTTON_REL button) */ |
Jonathan Gordon | 07d3db2 | 2006-08-17 09:28:04 +0000 | [diff] [blame] | 269 | return ACTION_NONE; /* "safest" return value */ |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 270 | } |
Jonathan Gordon | f7675a2 | 2007-07-22 06:05:53 +0000 | [diff] [blame] | 271 | last_context = context; |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 272 | |
Jonathan Gordon | f178131 | 2006-08-17 12:33:36 +0000 | [diff] [blame] | 273 | #ifndef HAS_BUTTON_HOLD |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 274 | screen_has_lock = ((context & ALLOW_SOFTLOCK) == ALLOW_SOFTLOCK); |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 275 | context &= ~ALLOW_SOFTLOCK; |
Wieland Hoffmann | 94177e6 | 2011-09-20 19:33:04 +0200 | [diff] [blame] | 276 | if (is_keys_locked()) |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 277 | { |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 278 | ret = do_softlock_unlock_combo(button, context); |
| 279 | if (!is_keys_locked()) |
| 280 | return ret; |
Jonathan Gordon | f178131 | 2006-08-17 12:33:36 +0000 | [diff] [blame] | 281 | } |
Jean-Louis Biasini | df6eb82 | 2013-09-02 11:03:56 +0200 | [diff] [blame] | 282 | #if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN) |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 283 | else if (!mask_has_flag(softlock_mask, SEL_ACTION_NOTOUCH)) |
Jean-Louis Biasini | df6eb82 | 2013-09-02 11:03:56 +0200 | [diff] [blame] | 284 | { |
| 285 | /* make sure touchpad get reactivated if we quit the screen */ |
| 286 | button_enable_touch(true); |
| 287 | } |
| 288 | #endif |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 289 | |
Jonathan Gordon | f178131 | 2006-08-17 12:33:36 +0000 | [diff] [blame] | 290 | #endif /* HAS_BUTTON_HOLD */ |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 291 | |
Maurus Cuelenaere | 7b1d12e | 2009-10-28 21:36:24 +0000 | [diff] [blame] | 292 | #ifdef HAVE_TOUCHSCREEN |
| 293 | if (button & BUTTON_TOUCHSCREEN) |
| 294 | { |
| 295 | repeated = false; |
| 296 | short_press = false; |
| 297 | if (last_button & BUTTON_TOUCHSCREEN) |
| 298 | { |
| 299 | if ((button & BUTTON_REL) && |
| 300 | ((last_button & BUTTON_REPEAT)==0)) |
| 301 | { |
| 302 | short_press = true; |
| 303 | } |
| 304 | else if (button & BUTTON_REPEAT) |
| 305 | repeated = true; |
| 306 | } |
| 307 | last_button = button; |
| 308 | return ACTION_TOUCHSCREEN; |
| 309 | } |
| 310 | #endif |
| 311 | |
Tomer Shalev | f7bd725 | 2009-10-05 17:17:30 +0000 | [diff] [blame] | 312 | #if defined(HAVE_LCD_BITMAP) && !defined(BOOTLOADER) |
Tomer Shalev | a39be4b | 2009-10-05 17:53:45 +0000 | [diff] [blame] | 313 | button = button_flip_horizontally(context, button); |
Tomer Shalev | f7bd725 | 2009-10-05 17:17:30 +0000 | [diff] [blame] | 314 | #endif |
| 315 | |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 316 | /* logf("%x,%x",last_button,button); */ |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 317 | *is_pre_button = false; /* could the button be another actions pre_button */ |
Michael Sevakis | e2a169b | 2009-02-03 10:55:30 +0000 | [diff] [blame] | 318 | while (1) |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 319 | { |
| 320 | /* logf("context = %x",context); */ |
| 321 | #if (BUTTON_REMOTE != 0) |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 322 | if (button & BUTTON_REMOTE) |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 323 | context |= CONTEXT_REMOTE; |
| 324 | #endif |
Andrew Mahone | 29d7db4 | 2009-05-31 17:47:56 +0000 | [diff] [blame] | 325 | if ((context & CONTEXT_PLUGIN) && get_context_map) |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 326 | items = get_context_map(context); |
| 327 | else |
| 328 | items = get_context_mapping(context); |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 329 | |
Michael Sevakis | e2a169b | 2009-02-03 10:55:30 +0000 | [diff] [blame] | 330 | if (items == NULL) |
Jonathan Gordon | 56a16d7 | 2006-08-21 11:28:29 +0000 | [diff] [blame] | 331 | break; |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 332 | |
William Wilgus | 6103d4d | 2017-01-17 23:50:38 +0100 | [diff] [blame] | 333 | ret = do_button_check(items, button, last_button, &i, is_pre_button); |
Michael Sevakis | e2a169b | 2009-02-03 10:55:30 +0000 | [diff] [blame] | 334 | |
| 335 | if (ret == ACTION_UNKNOWN) |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 336 | { |
| 337 | context = get_next_context(items,i); |
Michael Sevakis | e2a169b | 2009-02-03 10:55:30 +0000 | [diff] [blame] | 338 | |
| 339 | if (context != (int)CONTEXT_STOPSEARCHING) |
| 340 | { |
| 341 | i = 0; |
| 342 | continue; |
| 343 | } |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 344 | } |
Michael Sevakis | e2a169b | 2009-02-03 10:55:30 +0000 | [diff] [blame] | 345 | /* Action was found or STOPSEARCHING was specified */ |
| 346 | break; |
| 347 | } |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 348 | /* DEBUGF("ret = %x\n",ret); */ |
Jonathan Gordon | f178131 | 2006-08-17 12:33:36 +0000 | [diff] [blame] | 349 | #ifndef HAS_BUTTON_HOLD |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 350 | if(screen_has_lock && is_action_normal(ret)) |
| 351 | ret = do_softlock(button, ret, last_context & ~ALLOW_SOFTLOCK, is_pre_button); |
Jonathan Gordon | f178131 | 2006-08-17 12:33:36 +0000 | [diff] [blame] | 352 | #endif |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 353 | if ((current_tick - last_action_tick < REPEAT_WINDOW_TICKS) |
Jonathan Gordon | 63c8511 | 2007-06-04 13:52:02 +0000 | [diff] [blame] | 354 | && (ret == last_action)) |
Jonathan Gordon | ca701bf | 2007-03-04 07:45:12 +0000 | [diff] [blame] | 355 | repeated = true; |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 356 | else |
Jonathan Gordon | ca701bf | 2007-03-04 07:45:12 +0000 | [diff] [blame] | 357 | repeated = false; |
| 358 | |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 359 | last_button = button; |
Jonathan Gordon | 04ea446 | 2007-03-11 12:32:29 +0000 | [diff] [blame] | 360 | last_action = ret; |
Michael Sevakis | 873e0fd | 2007-07-22 21:02:24 +0000 | [diff] [blame] | 361 | last_data = button_get_data(); |
Jonathan Gordon | 63c8511 | 2007-06-04 13:52:02 +0000 | [diff] [blame] | 362 | last_action_tick = current_tick; |
Jonathan Gordon | eb2ea7f | 2012-01-12 22:28:36 +1100 | [diff] [blame] | 363 | |
| 364 | #if CONFIG_CODEC == SWCODEC |
| 365 | /* Produce keyclick */ |
Michael Sevakis | d05db0a | 2012-03-03 07:52:13 -0500 | [diff] [blame] | 366 | keyclick_click(false, ret); |
Jonathan Gordon | eb2ea7f | 2012-01-12 22:28:36 +1100 | [diff] [blame] | 367 | #endif |
| 368 | |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 369 | return ret; |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 370 | }/* get_action_worker */ |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 371 | |
| 372 | int get_action(int context, int timeout) |
| 373 | { |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 374 | bool is_pre_button = false; |
| 375 | int button = get_action_worker(context, timeout, &is_pre_button, NULL); |
| 376 | |
Jonathan Gordon | a398c28 | 2010-06-21 06:04:19 +0000 | [diff] [blame] | 377 | #ifdef HAVE_TOUCHSCREEN |
| 378 | if (button == ACTION_TOUCHSCREEN) |
| 379 | button = sb_touch_to_button(context); |
| 380 | #endif |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 381 | |
| 382 | #ifdef HAVE_BACKLIGHT |
| 383 | if (mask_has_flag(backlight_mask, SEL_ACTION_ENABLED) && |
| 384 | is_action_normal(button)) |
| 385 | button = do_backlight(button, context & ~ALLOW_SOFTLOCK, is_pre_button); |
| 386 | #endif |
| 387 | |
Jonathan Gordon | a398c28 | 2010-06-21 06:04:19 +0000 | [diff] [blame] | 388 | return button; |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 389 | } |
| 390 | |
| 391 | int get_custom_action(int context,int timeout, |
Jens Arnold | 1fdb5bf | 2006-08-16 00:32:45 +0000 | [diff] [blame] | 392 | const struct button_mapping* (*get_context_map)(int)) |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 393 | { |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 394 | bool is_pre_button = false; |
| 395 | return get_action_worker(context,timeout, &is_pre_button, get_context_map); |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 396 | } |
| 397 | |
| 398 | bool action_userabort(int timeout) |
| 399 | { |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 400 | bool is_pre_button = false; |
| 401 | int action = get_action_worker(CONTEXT_STD,timeout, &is_pre_button, NULL); |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 402 | bool ret = (action == ACTION_STD_CANCEL); |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 403 | if (!ret) |
Frank Gevaerts | c61076e | 2009-06-11 20:36:02 +0000 | [diff] [blame] | 404 | { |
| 405 | default_event_handler(action); |
| 406 | } |
Linus Nielsen Feltzing | 224c0a1 | 2006-08-15 12:27:07 +0000 | [diff] [blame] | 407 | return ret; |
| 408 | } |
| 409 | |
Michael Sevakis | 873e0fd | 2007-07-22 21:02:24 +0000 | [diff] [blame] | 410 | intptr_t get_action_data(void) |
| 411 | { |
| 412 | return last_data; |
| 413 | } |
| 414 | |
Jonathan Gordon | ca701bf | 2007-03-04 07:45:12 +0000 | [diff] [blame] | 415 | int get_action_statuscode(int *button) |
| 416 | { |
| 417 | int ret = 0; |
| 418 | if (button) |
| 419 | *button = last_button; |
| 420 | |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 421 | if (last_button & BUTTON_REMOTE) |
Jonathan Gordon | ca701bf | 2007-03-04 07:45:12 +0000 | [diff] [blame] | 422 | ret |= ACTION_REMOTE; |
| 423 | if (repeated) |
| 424 | ret |= ACTION_REPEAT; |
Jonathan Gordon | ca701bf | 2007-03-04 07:45:12 +0000 | [diff] [blame] | 425 | return ret; |
| 426 | } |
Jonathan Gordon | fa13cbe | 2007-10-22 12:26:53 +0000 | [diff] [blame] | 427 | |
Maurus Cuelenaere | 1392dc2 | 2008-08-23 09:46:38 +0000 | [diff] [blame] | 428 | #ifdef HAVE_TOUCHSCREEN |
Maurus Cuelenaere | cad30d3 | 2008-06-02 16:08:01 +0000 | [diff] [blame] | 429 | /* return BUTTON_NONE on error |
| 430 | * BUTTON_REPEAT if repeated press |
| 431 | * BUTTON_REPEAT|BUTTON_REL if release after repeated press |
Alexander Levin | 46854ed | 2010-04-19 19:49:42 +0000 | [diff] [blame] | 432 | * BUTTON_REL if it's a short press = release after press |
Maurus Cuelenaere | 1392dc2 | 2008-08-23 09:46:38 +0000 | [diff] [blame] | 433 | * BUTTON_TOUCHSCREEN if press |
Maurus Cuelenaere | cad30d3 | 2008-06-02 16:08:01 +0000 | [diff] [blame] | 434 | */ |
Maurus Cuelenaere | 1392dc2 | 2008-08-23 09:46:38 +0000 | [diff] [blame] | 435 | int action_get_touchscreen_press(short *x, short *y) |
Jonathan Gordon | fa13cbe | 2007-10-22 12:26:53 +0000 | [diff] [blame] | 436 | { |
| 437 | static int last_data = 0; |
| 438 | int data; |
Maurus Cuelenaere | 1392dc2 | 2008-08-23 09:46:38 +0000 | [diff] [blame] | 439 | if ((last_button & BUTTON_TOUCHSCREEN) == 0) |
Jonathan Gordon | fa13cbe | 2007-10-22 12:26:53 +0000 | [diff] [blame] | 440 | return BUTTON_NONE; |
| 441 | data = button_get_data(); |
Steve Bavin | ea358a1 | 2008-01-21 09:48:44 +0000 | [diff] [blame] | 442 | if (last_button & BUTTON_REL) |
Jonathan Gordon | fa13cbe | 2007-10-22 12:26:53 +0000 | [diff] [blame] | 443 | { |
| 444 | *x = (last_data&0xffff0000)>>16; |
| 445 | *y = (last_data&0xffff); |
| 446 | } |
| 447 | else |
| 448 | { |
| 449 | *x = (data&0xffff0000)>>16; |
| 450 | *y = (data&0xffff); |
| 451 | } |
| 452 | last_data = data; |
| 453 | if (repeated) |
| 454 | return BUTTON_REPEAT; |
| 455 | if (short_press) |
| 456 | return BUTTON_REL; |
Maurus Cuelenaere | cad30d3 | 2008-06-02 16:08:01 +0000 | [diff] [blame] | 457 | /* This is to return a BUTTON_REL after a BUTTON_REPEAT. */ |
Maurus Cuelenaere | 944219b | 2008-05-30 22:55:24 +0000 | [diff] [blame] | 458 | if (last_button & BUTTON_REL) |
Maurus Cuelenaere | 5dca53e | 2008-06-01 13:56:34 +0000 | [diff] [blame] | 459 | return BUTTON_REPEAT|BUTTON_REL; |
Maurus Cuelenaere | 1392dc2 | 2008-08-23 09:46:38 +0000 | [diff] [blame] | 460 | return BUTTON_TOUCHSCREEN; |
Jonathan Gordon | fa13cbe | 2007-10-22 12:26:53 +0000 | [diff] [blame] | 461 | } |
Thomas Martitz | 891c446 | 2009-10-11 20:11:48 +0000 | [diff] [blame] | 462 | |
| 463 | int action_get_touchscreen_press_in_vp(short *x1, short *y1, struct viewport *vp) |
| 464 | { |
| 465 | short x, y; |
| 466 | int ret; |
| 467 | |
| 468 | ret = action_get_touchscreen_press(&x, &y); |
| 469 | |
| 470 | if (ret != BUTTON_NONE && viewport_point_within_vp(vp, x, y)) |
| 471 | { |
| 472 | *x1 = x - vp->x; |
| 473 | *y1 = y - vp->y; |
| 474 | return ret; |
| 475 | } |
| 476 | if (ret & BUTTON_TOUCHSCREEN) |
| 477 | return ACTION_UNKNOWN; |
| 478 | return BUTTON_NONE; |
| 479 | } |
Jonathan Gordon | fa13cbe | 2007-10-22 12:26:53 +0000 | [diff] [blame] | 480 | #endif |
Jonathan Gordon | 0e445fc | 2009-07-03 05:08:33 +0000 | [diff] [blame] | 481 | |
Alexander Levin | 00e2252 | 2010-05-04 21:02:32 +0000 | [diff] [blame] | 482 | /* Don't let get_action*() return any ACTION_* values until the current buttons |
| 483 | * have been released. SYS_* and BUTTON_NONE will go through. |
| 484 | * Any actions relying on _RELEASE won't get seen. |
Thomas Martitz | 54e6baf | 2012-07-18 10:25:32 +0200 | [diff] [blame] | 485 | * |
| 486 | * Note this doesn't currently work for touchscreen targets if called |
| 487 | * when the screen isn't currently touched, because they can send normal |
| 488 | * (non-BUTTON_REPEAT) events repeatedly, if the touch coordinates change. |
| 489 | * This cannot be distinguished from normal buttons events. |
Jonathan Gordon | 0e445fc | 2009-07-03 05:08:33 +0000 | [diff] [blame] | 490 | */ |
| 491 | void action_wait_for_release(void) |
| 492 | { |
| 493 | wait_for_release = true; |
| 494 | } |
William Wilgus | dc87e9e | 2016-11-22 06:21:31 +0100 | [diff] [blame] | 495 | |
| 496 | #if defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD) |
| 497 | /* HELPER FUNCTIONS |
| 498 | * Selective softlock and backlight use this lookup based on mask to decide |
| 499 | * which actions are filtered, or could be filtered but not currently set. |
| 500 | * returns false if the action isn't found, true if the action is found |
| 501 | */ |
| 502 | static bool is_action_filtered(int action, unsigned int mask, int context) |
| 503 | { |
| 504 | bool match = false; |
| 505 | |
| 506 | switch (action) |
| 507 | { |
| 508 | case ACTION_NONE: |
| 509 | break; |
| 510 | /*Actions that are not mapped will not turn on the backlight option NOUNMAPPED*/ |
| 511 | case ACTION_UNKNOWN: |
| 512 | match = mask_has_flag(mask, SEL_ACTION_NOUNMAPPED); |
| 513 | break; |
| 514 | case ACTION_WPS_PLAY: |
| 515 | case ACTION_FM_PLAY: |
| 516 | match = mask_has_flag(mask, SEL_ACTION_PLAY); |
| 517 | break; |
| 518 | case ACTION_STD_PREVREPEAT: |
| 519 | case ACTION_STD_NEXTREPEAT: |
| 520 | case ACTION_WPS_SEEKBACK: |
| 521 | case ACTION_WPS_SEEKFWD: |
| 522 | case ACTION_WPS_STOPSEEK: |
| 523 | match = mask_has_flag(mask, SEL_ACTION_SEEK); |
| 524 | break; |
| 525 | case ACTION_STD_PREV: |
| 526 | case ACTION_STD_NEXT: |
| 527 | case ACTION_WPS_SKIPNEXT: |
| 528 | case ACTION_WPS_SKIPPREV: |
| 529 | case ACTION_FM_NEXT_PRESET: |
| 530 | case ACTION_FM_PREV_PRESET: |
| 531 | match = mask_has_flag(mask, SEL_ACTION_SKIP); |
| 532 | break; |
| 533 | case ACTION_WPS_VOLUP: |
| 534 | case ACTION_WPS_VOLDOWN: |
| 535 | match = mask_has_flag(mask, SEL_ACTION_VOL); |
| 536 | break; |
| 537 | case ACTION_SETTINGS_INC:/*FMS*/ |
| 538 | case ACTION_SETTINGS_INCREPEAT:/*FMS*/ |
| 539 | case ACTION_SETTINGS_DEC:/*FMS*/ |
| 540 | case ACTION_SETTINGS_DECREPEAT:/*FMS*/ |
| 541 | match = (context == CONTEXT_FM) && mask_has_flag(mask, SEL_ACTION_VOL); |
| 542 | break; |
| 543 | default: |
| 544 | /* display action code of unfiltered actions */ |
| 545 | logf ("unfiltered actions: context: %d action: %d, last btn: %d, \ |
| 546 | mask: %d", context, action, last_button, mask); |
| 547 | break; |
| 548 | }/*switch*/ |
| 549 | |
| 550 | return match; |
| 551 | } |
| 552 | /* compares mask to a flag return true if set false otherwise*/ |
| 553 | static inline bool mask_has_flag(unsigned int mask, unsigned int flag) |
| 554 | { |
| 555 | return ((mask & flag) != 0); |
| 556 | } |
| 557 | /* returns true if the supplied context is to be filtered by selective BL/SL*/ |
| 558 | static inline bool is_context_filtered(int context) |
| 559 | { |
| 560 | return (context == CONTEXT_FM || context == CONTEXT_WPS); |
| 561 | } |
| 562 | /* returns true if action can be passed on to selective backlight/softlock */ |
| 563 | static inline bool is_action_normal(int action) |
| 564 | { |
| 565 | return (action != ACTION_REDRAW && (action & SYS_EVENT) == 0); |
| 566 | } |
| 567 | /*returns true if Button & released, repeated; or won't generate those events*/ |
| 568 | static inline bool is_action_completed(int button) |
| 569 | { |
| 570 | return ((button & (BUTTON_REPEAT | BUTTON_REL)) != 0 |
| 571 | #ifdef HAVE_SCROLLWHEEL |
| 572 | /* Scrollwheel doesn't generate release events */ |
| 573 | || (button & (BUTTON_SCROLL_BACK | BUTTON_SCROLL_FWD)) != 0 |
| 574 | #endif |
| 575 | ); |
| 576 | } |
| 577 | |
| 578 | /* most every action takes two rounds through get_action_worker, |
| 579 | * once for the keypress and once for the key release, |
| 580 | * actions with pre_button codes take even more, some actions however, only |
| 581 | * take once; actions defined with only a button and no release/repeat event, |
| 582 | * these actions should be acted upon immediately except when we have |
| 583 | * selective backlighting/softlock enabled and in this case we only act upon |
| 584 | * them immediately if there is no chance they have another event tied to them |
| 585 | * determined using is_pre_button and is_action_completed() |
| 586 | *returns true if event was not filtered and false if it was |
| 587 | */ |
| 588 | static bool is_action_unfiltered(int action,int button, bool is_pre_button, |
| 589 | bool filtered, int *tick) |
| 590 | { |
| 591 | bool ret = false; |
| 592 | /*directly after a match a key release event may trigger another*/ |
| 593 | if (filtered && action != ACTION_UNKNOWN) |
| 594 | *tick = current_tick + LAST_FILTER_TICKS; |
| 595 | /* has button been rel/rep or is this the only action it could be */ |
| 596 | if (is_action_completed(button) || !is_pre_button) |
| 597 | { |
| 598 | /* reset last action , if the action is not filtered and |
| 599 | this isn't just a key release event then return true */ |
| 600 | if (!filtered && *tick < current_tick) |
| 601 | { |
| 602 | *tick = 0; |
| 603 | ret = true; |
| 604 | } |
| 605 | }/*is_action_completed() || !is_pre_button*/ |
| 606 | return ret; |
| 607 | } |
| 608 | #endif /*defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD) HELPER FUNCTIONS*/ |
| 609 | |
| 610 | #ifdef HAVE_BACKLIGHT |
| 611 | static void handle_backlight(bool backlight, bool ignore_next) |
| 612 | { |
| 613 | if (backlight) |
| 614 | { |
| 615 | backlight_on_ignore(false, 0); |
| 616 | backlight_on(); |
| 617 | #ifdef HAVE_BUTTON_LIGHT |
| 618 | buttonlight_on_ignore(false, 0); |
| 619 | buttonlight_on(); |
| 620 | } |
| 621 | buttonlight_on_ignore(ignore_next, 5*HZ);/* as a precautionary fallback */ |
| 622 | #else |
| 623 | } |
| 624 | #endif |
| 625 | backlight_on_ignore(ignore_next, 5*HZ);/*must be set everytime we handle bl*/ |
| 626 | } |
| 627 | |
| 628 | /* Need to look up actions before we can decide to turn on backlight, if |
| 629 | * selective backlighting is true filter first keypress events need to be |
| 630 | * taken into account as well |
| 631 | */ |
| 632 | static int do_backlight(int action, int context, bool is_pre_btn) |
| 633 | { |
| 634 | static int last_filtered_tick = 0; |
| 635 | |
| 636 | bool bl_is_active = is_backlight_on(false); |
| 637 | bool bl_activate = false; |
| 638 | bool filtered; |
| 639 | |
| 640 | #if CONFIG_CHARGING /* disable if on external power */ |
| 641 | if (!bl_is_active && is_context_filtered(context) && |
| 642 | !(mask_has_flag(backlight_mask, SEL_ACTION_NOEXT) && power_input_present())) |
| 643 | #else /* skip if backlight is on or incorrect context */ |
| 644 | if (!bl_is_active && is_context_filtered(context)) |
| 645 | #endif |
| 646 | { |
| 647 | filtered = is_action_filtered(action, backlight_mask, context); |
| 648 | bl_activate = is_action_unfiltered(action, last_button, is_pre_btn, |
| 649 | filtered, &last_filtered_tick); |
| 650 | }/*is_context_filtered(context)*/ |
| 651 | else |
| 652 | bl_activate = true; |
| 653 | |
| 654 | if (action != ACTION_NONE && bl_activate) |
| 655 | { |
| 656 | handle_backlight(true, true); |
| 657 | |
| 658 | if (mask_has_flag(backlight_mask, SEL_ACTION_FFKEYPRESS) && !bl_is_active) |
| 659 | { |
| 660 | action = ACTION_NONE; |
| 661 | last_button = BUTTON_NONE; |
| 662 | } |
| 663 | } |
| 664 | else |
| 665 | handle_backlight(false, true);/* set ignore next true */ |
| 666 | |
| 667 | return action; |
| 668 | } |
| 669 | |
| 670 | /* Enable selected actions to leave the backlight off */ |
| 671 | void set_selective_backlight_actions(bool selective, unsigned int mask, |
| 672 | bool filter_fkp) |
| 673 | { |
| 674 | handle_backlight(true, selective); |
| 675 | if (selective) /* we will handle filter_first_keypress here so turn it off*/ |
| 676 | { |
| 677 | set_backlight_filter_keypress(false);/* turnoff ffkp in button.c */ |
| 678 | backlight_mask = mask | SEL_ACTION_ENABLED; |
| 679 | if(filter_fkp) |
| 680 | backlight_mask |= SEL_ACTION_FFKEYPRESS; |
| 681 | } |
| 682 | else |
| 683 | { |
| 684 | set_backlight_filter_keypress(filter_fkp); |
| 685 | backlight_mask = SEL_ACTION_NONE; |
| 686 | } |
| 687 | } |
| 688 | #endif /* HAVE_BACKLIGHT */ |
| 689 | |
| 690 | #ifndef HAS_BUTTON_HOLD |
| 691 | bool is_keys_locked(void) |
| 692 | { |
| 693 | return (screen_has_lock && keys_locked); |
| 694 | } |
| 695 | |
| 696 | static inline void do_key_lock(bool lock) |
| 697 | { |
| 698 | keys_locked = lock; |
| 699 | last_button = BUTTON_NONE; |
| 700 | button_clear_queue(); |
| 701 | #if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN) |
| 702 | /* disable touch device on keylock if std behavior or selected disable touch */ |
| 703 | if (!mask_has_flag(softlock_mask, SEL_ACTION_ENABLED) || |
| 704 | mask_has_flag(softlock_mask, SEL_ACTION_NOTOUCH)) |
| 705 | button_enable_touch(!lock); |
| 706 | #endif |
| 707 | } |
| 708 | |
| 709 | /* user selected autolock based on backlight timeout; toggles autolock on / off |
| 710 | by ACTION_STD_KEYLOCK presses, Activates autolock if set on backlight timeout |
| 711 | */ |
| 712 | #ifdef HAVE_BACKLIGHT |
| 713 | static inline int do_auto_softlock(int button, int action, int *unlock_combo) |
| 714 | { |
| 715 | if(mask_has_flag(softlock_mask, SEL_ACTION_ALOCK_OK) && !is_backlight_on(false)) |
| 716 | do_key_lock(true); |
| 717 | |
| 718 | else if (action == ACTION_STD_KEYLOCK) |
| 719 | { |
| 720 | *unlock_combo = button;/* set unlock combo to allow unlock */ |
| 721 | softlock_mask ^= SEL_ACTION_ALOCK_OK; |
| 722 | handle_backlight(true, false); |
| 723 | /* If we don't wait for a moment for the backlight queue |
| 724 | * to process, the user will never see the message */ |
| 725 | if (!is_backlight_on(false)) |
| 726 | sleep(HZ/2); |
| 727 | |
| 728 | if (mask_has_flag(softlock_mask, SEL_ACTION_ALOCK_OK)) |
| 729 | { |
| 730 | splash(HZ/2, ID2P(LANG_ACTION_AUTOLOCK_ON)); |
| 731 | action = ACTION_REDRAW; |
| 732 | } |
| 733 | else |
| 734 | splash(HZ/2, ID2P(LANG_ACTION_AUTOLOCK_OFF)); |
| 735 | } |
| 736 | return action; |
| 737 | } |
| 738 | #endif |
| 739 | |
| 740 | /* Allows unlock softlock when action is not yet known but unlock_combo set*/ |
| 741 | static inline int do_softlock_unlock_combo(int button, int context) |
| 742 | { |
| 743 | return do_softlock(button, ACTION_NONE, context, false); |
| 744 | } |
| 745 | |
| 746 | /* Handles softlock once action is known */ |
| 747 | static int do_softlock(int button, int action, int context, bool is_pre_btn) |
| 748 | { |
| 749 | static int last_filtered_tick = 0; |
| 750 | static int unlock_combo = BUTTON_NONE; /*Moved from GLOBAL*/ |
| 751 | bool filtered = true; |
| 752 | bool notify_user = false; |
| 753 | bool sl_activate = true; /* standard softlock behavior */ |
| 754 | |
| 755 | #ifdef HAVE_BACKLIGHT |
| 756 | if (!keys_locked && mask_has_flag(softlock_mask, SEL_ACTION_AUTOLOCK)) |
| 757 | action = do_auto_softlock(button, action, &unlock_combo); |
| 758 | #endif |
| 759 | /* Lock/Unlock toggled by ACTION_STD_KEYLOCK presses*/ |
| 760 | if ((action == ACTION_STD_KEYLOCK) || (keys_locked && unlock_combo == button)) |
| 761 | { |
| 762 | unlock_combo = button; |
| 763 | do_key_lock(!keys_locked); |
| 764 | notify_user = true; |
| 765 | } |
| 766 | #if (BUTTON_REMOTE != 0)/* Allow remote actions through */ |
| 767 | else if (mask_has_flag(button, BUTTON_REMOTE)) |
| 768 | notify_user = false; |
| 769 | #endif |
| 770 | else if (keys_locked && action != ACTION_NONE && action != ACTION_REDRAW) |
| 771 | { |
| 772 | if (mask_has_flag(softlock_mask, SEL_ACTION_ENABLED)) |
| 773 | { |
| 774 | filtered = is_action_filtered(action, softlock_mask, context); |
| 775 | |
| 776 | sl_activate = is_action_unfiltered(action, button, is_pre_btn, |
| 777 | filtered, &last_filtered_tick); |
| 778 | } |
| 779 | /*All non-std softlock options are set to 0 if advanced sl is disabled*/ |
| 780 | if (sl_activate) |
| 781 | { |
| 782 | if (!mask_has_flag(softlock_mask, SEL_ACTION_NONOTIFY)) |
| 783 | { /* always true on standard softlock behavior*/ |
| 784 | notify_user = mask_has_flag(button, BUTTON_REL); |
| 785 | action = ACTION_REDRAW; |
| 786 | } |
| 787 | else |
| 788 | action = ACTION_NONE; |
| 789 | } |
| 790 | else if (!filtered)/*catch blocked actions on fast repeated presses*/ |
| 791 | action = ACTION_NONE; |
| 792 | } /* keys_locked */ |
| 793 | |
| 794 | #ifdef BUTTON_POWER /*always notify if power button pressed while keys locked*/ |
| 795 | notify_user |= (mask_has_flag(button, BUTTON_POWER) && keys_locked); |
| 796 | #endif |
| 797 | |
| 798 | if (notify_user) |
| 799 | { |
| 800 | #ifdef HAVE_BACKLIGHT |
| 801 | handle_backlight(true, false); |
| 802 | /* If we don't wait for a moment for the backlight queue |
| 803 | * to process, the user will never see the message */ |
| 804 | if (!is_backlight_on(false)) |
| 805 | sleep(HZ/2); |
| 806 | #endif |
| 807 | if (keys_locked) |
| 808 | splash(HZ/2, ID2P(LANG_KEYLOCK_ON)); |
| 809 | else |
| 810 | splash(HZ/2, ID2P(LANG_KEYLOCK_OFF)); |
| 811 | |
| 812 | last_button = BUTTON_NONE; |
| 813 | action = ACTION_REDRAW; |
| 814 | button_clear_queue(); |
| 815 | } |
| 816 | |
| 817 | return action; |
| 818 | } |
| 819 | |
| 820 | void set_selective_softlock_actions(bool selective, unsigned int mask) |
| 821 | { |
| 822 | keys_locked = false; |
| 823 | if(selective) |
| 824 | softlock_mask = mask | SEL_ACTION_ENABLED; |
| 825 | else |
| 826 | softlock_mask = SEL_ACTION_NONE; |
| 827 | } |
| 828 | |
| 829 | #endif /* HAS_BUTTON_HOLD */ |