Index: ../firmware/export/button.h =================================================================== --- ../firmware/export/button.h (revision 14623) +++ ../firmware/export/button.h (working copy) @@ -59,5 +59,17 @@ /* Button modifiers */ #define BUTTON_REL 0x02000000 #define BUTTON_REPEAT 0x04000000 +#ifdef ACCEPT_DOUBLE_CLICK +#define BUTTON_DBL 0x08000000 +#endif +#ifdef ACCEPT_DOUBLE_CLICK +#define DC_DELAY_MIN 100 +#define DC_DELAY_MAX 500 +#define DC_DELAY_DEF 300 +#define DC_DELAY_START 30 + +void btn_set_double_click_delay(int delay); +#endif + #endif /* _BUTTON_H_ */ Index: ../firmware/drivers/button.c =================================================================== --- ../firmware/drivers/button.c (revision 14623) +++ ../firmware/drivers/button.c (working copy) @@ -64,6 +64,12 @@ bool phones_present = false; #endif +#ifdef ACCEPT_DOUBLE_CLICK +static int double_click_interval; +static int double_click_start; +static int double_click_count; +#endif + /* how long until repeat kicks in, in ticks */ #define REPEAT_START 30 @@ -82,6 +88,9 @@ static int repeat_count = 0; static bool repeat = false; static bool post = false; +#ifdef ACCEPT_DOUBLE_CLICK + static int lastbtn_pushed = 0; +#endif #ifdef HAVE_BACKLIGHT static bool skip_release = false; #ifdef HAVE_REMOTE_LCD @@ -90,7 +99,7 @@ #endif int diff; int btn; - + #ifdef HAS_SERIAL_REMOTE /* Post events for the remote control */ btn = remote_control_rx(); @@ -133,23 +142,66 @@ else #endif if(!skip_release) +#ifdef ACCEPT_DOUBLE_CLICK + { + /* if double_click is < start then a double click was + * detected and queued, now we must queue the release, and dbl + */ + if (lastbtn_pushed > 0 && double_click_count < double_click_start) + { + queue_post(&button_queue, BUTTON_DBL | lastbtn_pushed, 0); + queue_post(&button_queue, BUTTON_REL | lastbtn_pushed, 0); + double_click_count = double_click_interval; + lastbtn_pushed = 0; + } + } +#else /* !ACCEPT_DOUBLE_CLICK */ queue_post(&button_queue, BUTTON_REL | diff, 0); +#endif else skip_release = false; -#else +#else /* !HAVE_REMOTE_LCD */ +#ifdef ACCEPT_DOUBLE_CLICK + /* see above section comment */ + if (lastbtn_pushed > 0 && double_click_count < double_click_start) + { + queue_post(&button_queue, BUTTON_DBL | lastbtn_pushed, 0); + queue_post(&button_queue, BUTTON_REL | lastbtn_pushed, 0); + double_click_count = double_click_interval; + lastbtn_pushed = 0; + } +#else /* !ACCEPT_DOUBLE_CLICK */ queue_post(&button_queue, BUTTON_REL | diff, 0); #endif +#endif } else { if ( btn ) { +#ifdef ACCEPT_DOUBLE_CLICK + /* check for double click */ + /* double clicked if lastbtn == 0, and we've waited long enough */ + if (lastbtn == 0 && btn == lastbtn_pushed && double_click_count < double_click_start) + { + /* double clicked now wait for button to be released + * cannot post yet, as the second click could be a hold */ + post = false; + double_click_count = 0; + } + else +#endif /* normal keypress */ if ( btn != lastbtn ) { post = true; repeat = false; repeat_speed = REPEAT_INTERVAL_START; +#ifdef ACCEPT_DOUBLE_CLICK + /* diff btn - reset double click, no post */ + post = false; + double_click_count = double_click_interval; +#endif } else /* repeat? */ { @@ -201,6 +253,18 @@ repeat_count = 0; /* initial repeat */ count = REPEAT_INTERVAL_START; +#ifdef ACCEPT_DOUBLE_CLICK + /* post original button press and release */ + if (double_click_count == 0) + { + queue_post(&button_queue, btn, 0); + queue_post(&button_queue, BUTTON_REL | btn, 0); + } + /* post current button press */ + queue_post(&button_queue, btn, 0); + /* reset double click detection */ + double_click_count = double_click_interval; +#endif } } } @@ -243,7 +307,9 @@ || (btn&BUTTON_REMOTE) #endif ) + { queue_post(&button_queue, btn, 0); + } else skip_release = true; #else /* no backlight, nothing to skip */ @@ -263,11 +329,35 @@ } else { +#ifdef ACCEPT_DOUBLE_CLICK + /* if we've waited longer than double_click_interval + * then it isn't a double click, so queue the button + * we also know it isn't a double click if repeat is true + */ + if (repeat || (lastbtn_pushed && --double_click_count <= 0)) + { + /* queue both the original press if not repeating, + * and the release + */ + if (!repeat) + queue_post(&button_queue, lastbtn_pushed, 0); + queue_post(&button_queue, BUTTON_REL | lastbtn_pushed, 0); + double_click_count = double_click_interval; + lastbtn_pushed = 0; + } +#endif repeat = false; count = 0; } } + +#ifdef ACCEPT_DOUBLE_CLICK + lastbtn = btn & ~(BUTTON_REL | BUTTON_REPEAT | BUTTON_DBL); + if (lastbtn) + lastbtn_pushed = lastbtn; +#else lastbtn = btn & ~(BUTTON_REL | BUTTON_REPEAT); +#endif } #ifdef HAVE_ADJUSTABLE_CPU_FREQ @@ -369,6 +459,10 @@ remote_filter_first_keypress = false; #endif #endif + +#ifdef ACCEPT_DOUBLE_CLICK + btn_set_double_click_delay(DC_DELAY_DEF); +#endif } #ifdef HAVE_LCD_BITMAP /* only bitmap displays can be flipped */ @@ -514,3 +608,17 @@ return delta; } #endif /* HAVE_SCROLLWHEEL */ + +#ifdef ACCEPT_DOUBLE_CLICK +void btn_set_double_click_delay(int delay) +{ + if (delay < DC_DELAY_MIN || + delay > DC_DELAY_MAX) + delay = DC_DELAY_DEF; + + double_click_interval = delay / 10; // convert to ticks + double_click_start = (delay - DC_DELAY_START) / 10; // conver to ticks + double_click_count = double_click_interval; +} +#endif + Index: ../firmware/export/config-ipodvideo.h =================================================================== --- ../firmware/export/config-ipodvideo.h (revision 14623) +++ ../firmware/export/config-ipodvideo.h (working copy) @@ -159,4 +159,7 @@ #define ICODE_ATTR_TREMOR_NOT_MDCT +/* define this to turn on double click captures */ +#define ACCEPT_DOUBLE_CLICK + #endif Index: ../apps/menus/settings_menu.c =================================================================== --- ../apps/menus/settings_menu.c (revision 14623) +++ ../apps/menus/settings_menu.c (working copy) @@ -344,6 +344,10 @@ MENUITEM_SETTING(buttonlight_brightness, &global_settings.buttonlight_brightness, NULL); #endif +#ifdef ACCEPT_DOUBLE_CLICK +MENUITEM_SETTING(btn_double_click_delay, &global_settings.btn_double_click_delay, NULL); +#endif + MAKE_MENU(system_menu, ID2P(LANG_SYSTEM), 0, Icon_System_menu, &start_screen, @@ -374,8 +378,11 @@ &button_light_timeout, #endif #ifdef HAVE_BUTTONLIGHT_BRIGHTNESS - &buttonlight_brightness + &buttonlight_brightness, #endif +#ifdef ACCEPT_DOUBLE_CLICK + &btn_double_click_delay +#endif ); /* SYSTEM MENU */ Index: ../apps/settings_list.c =================================================================== --- ../apps/settings_list.c (revision 14623) +++ ../apps/settings_list.c (working copy) @@ -1263,6 +1263,12 @@ 3, "list_accel_wait", UNIT_SEC, 1, 10, 1, scanaccel_formatter, scanaccel_getlang, NULL), #endif /* HAVE_SCROLLWHEEL */ +#ifdef ACCEPT_DOUBLE_CLICK + INT_SETTING(0, btn_double_click_delay, LANG_DOUBLE_CLICK_DELAY, DC_DELAY_DEF, + "dbl click delay", UNIT_MS, DC_DELAY_MIN, DC_DELAY_MAX, 20, + NULL, NULL, btn_set_double_click_delay), +#endif + #ifdef HAVE_USBSTACK CHOICE_SETTING(0, usb_stack_mode, LANG_USBSTACK_MODE, 0, "usb mode", "device,host", Index: ../apps/settings.h =================================================================== --- ../apps/settings.h (revision 14623) +++ ../apps/settings.h (working copy) @@ -748,6 +760,10 @@ int list_accel_start_delay; /* ms before we start increaseing step size */ int list_accel_wait; /* ms between increases */ #endif +#ifdef ACCEPT_DOUBLE_CLICK + int btn_double_click_delay; +#endif + #ifdef HAVE_USBSTACK int usb_stack_mode; /* device or host */ unsigned char usb_stack_device_driver[32]; /* usb device driver to load */ Index: ../apps/lang/english.lang =================================================================== --- ../apps/lang/english.lang (revision 14623) +++ ../apps/lang/english.lang (working copy) @@ -11027,6 +11027,20 @@ + + id: LANG_DOUBLE_CLICK_DELAY + desc: set delay in ms between clicks to detect double click + user: + + *: "Set Double-Click Delay" + + + *: "Set Double-Click Delay" + + + *: "Set Double-Click Delay" + + id: LANG_EXT_ONLY_VIEW_ALL desc: in settings_menu user: