/* * int get_action_worker(int context, struct button_mapping *user_mappings, int timeout) This function searches the button list for the given context for the just pressed button. If there is a match it returns the value from the list. If there is no match.. the last item in the list "points" to the next context in a chain so the "chain" is followed until the button is found. putting ACTION_NONE will get CONTEXT_STD which is always the last list checked. Timeout can be TIMEOUT_NOBLOCK to return immediatly TIMEOUT_BLOCK to wait for a button press Any number >0 to wait that many ticks for a press */ static int get_action_worker(int context, int timeout, const struct button_mapping* (*get_context_map)(int) ) { const struct button_mapping *items = NULL; int button; int i=0; int ret = ACTION_UNKNOWN; static int last_context = CONTEXT_STD; send_event(GUI_EVENT_ACTIONUPDATE, NULL); if (timeout == TIMEOUT_NOBLOCK) button = button_get(false); else if (timeout == TIMEOUT_BLOCK) button = button_get(true); else button = button_get_w_tmo(timeout); #if defined(HAVE_GUI_BOOST) && defined(HAVE_ADJUSTABLE_CPU_FREQ) static struct timeout gui_unboost; /* Boost the CPU in case of wheel scrolling activity in the defined contexts. * Call unboost with a timeout of GUI_BOOST_TIMEOUT. */ if ((button&(BUTTON_SCROLL_BACK|BUTTON_SCROLL_FWD)) && (context == CONTEXT_STD || context == CONTEXT_LIST || context == CONTEXT_MAINMENU || context == CONTEXT_TREE)) { gui_boost(true); timeout_register(&gui_unboost, gui_unboost_callback, GUI_BOOST_TIMEOUT, 0); } #endif /* Data from sys events can be pulled with button_get_data * multimedia button presses don't go through the action system */ if (button == BUTTON_NONE || button & (SYS_EVENT|BUTTON_MULTIMEDIA)) return button; /* Don't send any buttons through untill we see the release event */ if (wait_for_release) { if (button&BUTTON_REL) { /* remember the button for the below button eating on context * change */ last_button = button; wait_for_release = false; } return ACTION_NONE; } #if CONFIG_CODEC == SWCODEC /* Produce keyclick */ keyclick_click(button); #endif if ((context != last_context) && ((last_button & BUTTON_REL) == 0) #ifdef HAVE_SCROLLWHEEL /* Scrollwheel doesn't generate release events */ && !(last_button & (BUTTON_SCROLL_BACK | BUTTON_SCROLL_FWD)) #endif ) { if (button & BUTTON_REL) { last_button = button; last_action = ACTION_NONE; } /* eat all buttons until the previous button was |BUTTON_REL (also eat the |BUTTON_REL button) */ return ACTION_NONE; /* "safest" return value */ } last_context = context; #ifndef HAS_BUTTON_HOLD screen_has_lock = ((context & ALLOW_SOFTLOCK) == ALLOW_SOFTLOCK); if (screen_has_lock && keys_locked) { if (button == unlock_combo) { last_button = BUTTON_NONE; keys_locked = false; splash(HZ/2, str(LANG_KEYLOCK_OFF)); return ACTION_REDRAW; } else #if (BUTTON_REMOTE != 0) if ((button & BUTTON_REMOTE) == 0) #endif { if ((button & BUTTON_REL)) splash(HZ/2, str(LANG_KEYLOCK_ON)); return ACTION_REDRAW; } } context &= ~ALLOW_SOFTLOCK; #endif /* HAS_BUTTON_HOLD */ #ifdef HAVE_TOUCHSCREEN if (button & BUTTON_TOUCHSCREEN) { repeated = false; short_press = false; if (last_button & BUTTON_TOUCHSCREEN) { if ((button & BUTTON_REL) && ((last_button & BUTTON_REPEAT)==0)) { short_press = true; } else if (button & BUTTON_REPEAT) repeated = true; } last_button = button; return ACTION_TOUCHSCREEN; } #endif #if defined(HAVE_LCD_BITMAP) && !defined(BOOTLOADER) button = button_flip_horizontally(context, button); #endif /* logf("%x,%x",last_button,button); */ while (1) { /* logf("context = %x",context); */ #if (BUTTON_REMOTE != 0) if (button & BUTTON_REMOTE) context |= CONTEXT_REMOTE; #endif if ((context & CONTEXT_PLUGIN) && get_context_map) items = get_context_map(context); else items = get_context_mapping(context); if (items == NULL) break; ret = do_button_check(items,button,last_button,&i); if (ret == ACTION_UNKNOWN) { context = get_next_context(items,i); if (context != (int)CONTEXT_STOPSEARCHING) { i = 0; continue; } } /* Action was found or STOPSEARCHING was specified */ break; } /* DEBUGF("ret = %x\n",ret); */ #ifndef HAS_BUTTON_HOLD if (screen_has_lock && (ret == ACTION_STD_KEYLOCK)) { unlock_combo = button; keys_locked = true; splash(HZ/2, str(LANG_KEYLOCK_ON)); button_clear_queue(); return ACTION_REDRAW; } #endif if ((current_tick - last_action_tick < REPEAT_WINDOW_TICKS) && (ret == last_action)) repeated = true; else repeated = false; last_button = button; last_action = ret; last_data = button_get_data(); last_action_tick = current_tick; return ret; }
/* * int get_action_worker(int context, struct button_mapping *user_mappings, int timeout) This function searches the button list for the given context for the just pressed button. If there is a match it returns the value from the list. If there is no match.. the last item in the list "points" to the next context in a chain so the "chain" is followed until the button is found. putting ACTION_NONE will get CONTEXT_STD which is always the last list checked. Timeout can be TIMEOUT_NOBLOCK to return immediatly TIMEOUT_BLOCK to wait for a button press Any number >0 to wait that many ticks for a press */ static int get_action_worker(int context, int timeout, const struct button_mapping* (*get_context_map)(int) ) { const struct button_mapping *items = NULL; int button; int i=0; int ret = ACTION_UNKNOWN; static int last_context = CONTEXT_STD; send_event(GUI_EVENT_ACTIONUPDATE, NULL); if (timeout == TIMEOUT_NOBLOCK) button = button_get(false); else if (timeout == TIMEOUT_BLOCK) button = button_get(true); else button = button_get_w_tmo(timeout); #if defined(HAVE_GUI_BOOST) && defined(HAVE_ADJUSTABLE_CPU_FREQ) static struct timeout gui_unboost; /* Boost the CPU in case of wheel scrolling activity in the defined contexts. * Call unboost with a timeout of GUI_BOOST_TIMEOUT. */ if ((button&(BUTTON_SCROLL_BACK|BUTTON_SCROLL_FWD)) && (context == CONTEXT_STD || context == CONTEXT_LIST || context == CONTEXT_MAINMENU || context == CONTEXT_TREE)) { gui_boost(true); timeout_register(&gui_unboost, gui_unboost_callback, GUI_BOOST_TIMEOUT, 0); } #endif /* Data from sys events can be pulled with button_get_data * multimedia button presses don't go through the action system */ if (button == BUTTON_NONE || button & (SYS_EVENT|BUTTON_MULTIMEDIA)) { /* no button pressed so no point in waiting for release */ if (button == BUTTON_NONE) wait_for_release = false; return button; } /* the special redraw button should result in a screen refresh */ if (button == BUTTON_REDRAW) return ACTION_REDRAW; /* if action_wait_for_release() was called without a button being pressed * then actually waiting for release would do the wrong thing, i.e. * the next key press is entirely ignored. So, if here comes a normal * button press (neither release nor repeat) the press is a fresh one and * no point in waiting for release * * This logic doesn't work for touchscreen which can send normal * button events repeatedly before the first repeat (as in BUTTON_REPEAT). * These cannot be distinguished from the very first touch * but there's nothing we can do about it here */ if ((button & (BUTTON_REPEAT|BUTTON_REL)) == 0) wait_for_release = false; /* Don't send any buttons through untill we see the release event */ if (wait_for_release) { if (button&BUTTON_REL) { /* remember the button for the below button eating on context * change */ last_button = button; wait_for_release = false; } return ACTION_NONE; } if ((context != last_context) && ((last_button & BUTTON_REL) == 0) #ifdef HAVE_SCROLLWHEEL /* Scrollwheel doesn't generate release events */ && !(last_button & (BUTTON_SCROLL_BACK | BUTTON_SCROLL_FWD)) #endif ) { if (button & BUTTON_REL) { last_button = button; last_action = ACTION_NONE; } /* eat all buttons until the previous button was |BUTTON_REL (also eat the |BUTTON_REL button) */ return ACTION_NONE; /* "safest" return value */ } last_context = context; #ifndef HAS_BUTTON_HOLD screen_has_lock = ((context & ALLOW_SOFTLOCK) == ALLOW_SOFTLOCK); if (is_keys_locked()) { if (button == unlock_combo) { last_button = BUTTON_NONE; keys_locked = false; #if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN) /* enable back touch device */ button_enable_touch(true); #endif splash(HZ/2, str(LANG_KEYLOCK_OFF)); return ACTION_REDRAW; } else #if (BUTTON_REMOTE != 0) if ((button & BUTTON_REMOTE) == 0) #endif { if ((button & BUTTON_REL)) splash(HZ/2, str(LANG_KEYLOCK_ON)); return ACTION_REDRAW; } } #if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN) else { /* make sure touchpad get reactivated if we quit the screen */ button_enable_touch(true); } #endif context &= ~ALLOW_SOFTLOCK; #endif /* HAS_BUTTON_HOLD */ #ifdef HAVE_TOUCHSCREEN if (button & BUTTON_TOUCHSCREEN) { repeated = false; short_press = false; if (last_button & BUTTON_TOUCHSCREEN) { if ((button & BUTTON_REL) && ((last_button & BUTTON_REPEAT)==0)) { short_press = true; } else if (button & BUTTON_REPEAT) repeated = true; } last_button = button; return ACTION_TOUCHSCREEN; } #endif #if defined(HAVE_LCD_BITMAP) && !defined(BOOTLOADER) button = button_flip_horizontally(context, button); #endif /* logf("%x,%x",last_button,button); */ while (1) { /* logf("context = %x",context); */ #if (BUTTON_REMOTE != 0) if (button & BUTTON_REMOTE) context |= CONTEXT_REMOTE; #endif if ((context & CONTEXT_PLUGIN) && get_context_map) items = get_context_map(context); else items = get_context_mapping(context); if (items == NULL) break; ret = do_button_check(items,button,last_button,&i); if (ret == ACTION_UNKNOWN) { context = get_next_context(items,i); if (context != (int)CONTEXT_STOPSEARCHING) { i = 0; continue; } } /* Action was found or STOPSEARCHING was specified */ break; } /* DEBUGF("ret = %x\n",ret); */ #ifndef HAS_BUTTON_HOLD if (screen_has_lock && (ret == ACTION_STD_KEYLOCK)) { unlock_combo = button; keys_locked = true; splash(HZ/2, str(LANG_KEYLOCK_ON)); #if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN) /* disable touch device on keylock */ button_enable_touch(false); #endif button_clear_queue(); return ACTION_REDRAW; } #endif if ((current_tick - last_action_tick < REPEAT_WINDOW_TICKS) && (ret == last_action)) repeated = true; else repeated = false; last_button = button; last_action = ret; last_data = button_get_data(); last_action_tick = current_tick; #if CONFIG_CODEC == SWCODEC /* Produce keyclick */ keyclick_click(false, ret); #endif return ret; }