Skip to content

Commit

Permalink
recovery: Allow key to repeat on hold.
Browse files Browse the repository at this point in the history
This implements the ability to hold a key and have it repeat.
This makes it possible to hold down the volume key to scroll
down to a file.

Enabling repeatable keys:

ro.cwm.enable_key_repeat=true

To control which keys can repeat, you can set this prop with
a list of key codes, like this:

ro.cwm.repeatable_keys=137,200,151,300

If you don't set ro.cwm.repeatable_keys only UP, DOWN, VOL UP
and VOL DOWN will be repeatable.

Patch-set 1:  First commit
Patch-set 2:  Re-worked a little
Patch-set 3:  Now uses system props.
Patch-set 4:  Fixed USB connection bug
Patch-set 5:  Compressed down a bit
Patch-set 6:  Fixed spacing derp
Patch-set 7:  Fix bug + increase speed
Patch-set 8:  Slow it down a tad
Patch-set 9:  Took care of inline comments
Patch-set 10: Added UP & DOWN to default repeatable keys
Patch-set 11: EV_REP compatibility + logic changes
Patch-set 12: EV_REP takes precedence
Patch-set 13: Fixed spacing derp
Patch-set 14: Fixed time overflow >_>
Patch-set 15: Remove a little whitespace
Patch-set 16: Removed *~
Patch-set 17: Reworked per koush's suggestion

Change-Id: I7c7ef035c89210212bf08f8aa97150222d948d0c
  • Loading branch information
FaultException authored and myfluxi committed Jul 3, 2012
1 parent 25e7cdb commit 2a809ea
Showing 1 changed file with 106 additions and 1 deletion.
107 changes: 106 additions & 1 deletion ui.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include "common.h"
#include <cutils/android_reboot.h>
#include <cutils/properties.h>
#include "minui/minui.h"
#include "recovery_ui.h"

Expand Down Expand Up @@ -62,6 +63,8 @@ static int gShowBackButton = 0;
//#define CHAR_HEIGHT BOARD_RECOVERY_CHAR_HEIGHT

#define UI_WAIT_KEY_TIMEOUT_SEC 3600
#define UI_KEY_REPEAT_INTERVAL 80
#define UI_KEY_WAIT_REPEAT 400

UIParameters ui_parameters = {
6, // indeterminate progress bar frames
Expand All @@ -82,6 +85,9 @@ static int ui_log_stdout = 1;
int touch_disable = 0;
time_t last_touch = 0;

static int boardEnableKeyRepeat = 0;
static int boardRepeatableKeys[64], boardNumRepeatableKeys = 0;

static const struct { gr_surface* surface; const char *name; } BITMAPS[] = {
{ &gBackgroundIcon[BACKGROUND_ICON_INSTALLING], "icon_clockwork" },
{ &gBackgroundIcon[BACKGROUND_ICON_ERROR], "icon_clockwork" },
Expand Down Expand Up @@ -127,6 +133,7 @@ static int max_menu_rows;
static pthread_mutex_t key_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t key_queue_cond = PTHREAD_COND_INITIALIZER;
static int key_queue[256], key_queue_len = 0;
static unsigned long key_last_repeat[KEY_MAX + 1], key_press_time[KEY_MAX + 1];
static volatile char key_pressed[KEY_MAX + 1];

// Return the current time as a double (including fractions of a second).
Expand Down Expand Up @@ -515,7 +522,7 @@ static int input_callback(int fd, short revents, void *data)
//finger lifted! lets run with this
ev.type = EV_KEY; //touch panel support!!!
if (!touch_disable) {
if (touch_y < (gr_fb_height() - gr_get_height(surface)) && touch_x > 0) {
if (touch_y < (gr_fb_height() - gr_get_height(surface)) && touch_x > 0 && touch_y > 0) {
// they lifted above the touch panel region
// touch to select
if ((diff_x == TOUCH_VALUE) && (diff_y == TOUCH_VALUE)) {
Expand Down Expand Up @@ -608,6 +615,10 @@ static int input_callback(int fd, short revents, void *data)
if (ev.type != EV_KEY || ev.code > KEY_MAX)
return 0;

if (ev.value == 2) {
boardEnableKeyRepeat = 0;
}

pthread_mutex_lock(&key_queue_mutex);
if (!fake_key) {
// our "fake" keys only report a key-down event (no
Expand All @@ -618,6 +629,15 @@ static int input_callback(int fd, short revents, void *data)
const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]);
if (ev.value > 0 && key_queue_len < queue_max) {
key_queue[key_queue_len++] = ev.code;

if (boardEnableKeyRepeat) {
struct timeval now;
gettimeofday(&now, NULL);

key_press_time[ev.code] = (now.tv_sec * 1000) + (now.tv_usec / 1000);
key_last_repeat[ev.code] = 0;
}

pthread_cond_signal(&key_queue_cond);
}
pthread_mutex_unlock(&key_queue_mutex);
Expand Down Expand Up @@ -713,6 +733,27 @@ void ui_init(void)
gInstallationOverlay = NULL;
}

char enable_key_repeat[PROPERTY_VALUE_MAX];
property_get("ro.cwm.enable_key_repeat", enable_key_repeat, "");
if (!strcmp(enable_key_repeat, "true") || !strcmp(enable_key_repeat, "1")) {
boardEnableKeyRepeat = 1;

char key_list[PROPERTY_VALUE_MAX];
property_get("ro.cwm.repeatable_keys", key_list, "");
if (strlen(key_list) == 0) {
boardRepeatableKeys[boardNumRepeatableKeys++] = KEY_UP;
boardRepeatableKeys[boardNumRepeatableKeys++] = KEY_DOWN;
boardRepeatableKeys[boardNumRepeatableKeys++] = KEY_VOLUMEUP;
boardRepeatableKeys[boardNumRepeatableKeys++] = KEY_VOLUMEDOWN;
} else {
char *pch = strtok(key_list, ",");
while (pch != NULL) {
boardRepeatableKeys[boardNumRepeatableKeys++] = atoi(pch);
pch = strtok(NULL, ",");
}
}
}

pthread_t t;
pthread_create(&t, NULL, progress_thread, NULL);
pthread_create(&t, NULL, input_thread, NULL);
Expand Down Expand Up @@ -976,6 +1017,7 @@ static int usb_connected() {

int ui_wait_key()
{
if (boardEnableKeyRepeat) return ui_wait_key_with_repeat();
pthread_mutex_lock(&key_queue_mutex);

// Time out after UI_WAIT_KEY_TIMEOUT_SEC, unless a USB cable is
Expand Down Expand Up @@ -1004,6 +1046,69 @@ int ui_wait_key()
return key;
}

int ui_wait_key_with_repeat()
{
int key = -1;

do {
struct timeval now;
struct timespec timeout;
gettimeofday(&now, NULL);
timeout.tv_sec = now.tv_sec;
timeout.tv_nsec = now.tv_usec * 1000;
timeout.tv_sec += UI_WAIT_KEY_TIMEOUT_SEC;

int rc = 0;
while (key_queue_len == 0 && rc != ETIMEDOUT) {
pthread_mutex_lock(&key_queue_mutex);
rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex,
&timeout);
pthread_mutex_unlock(&key_queue_mutex);
}
if (rc == ETIMEDOUT && !usb_connected()) return -1;

while (key_queue_len > 0) {
unsigned long now_msec;
usleep(1);

gettimeofday(&now, NULL);
now_msec = (now.tv_sec * 1000) + (now.tv_usec / 1000);

key = key_queue[0];

pthread_mutex_lock(&key_queue_mutex);
memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len);
pthread_mutex_unlock(&key_queue_mutex);

if (!key_pressed[key]) {
if (key_last_repeat[key] > 0) continue;
else return key;
}

int k = 0;
for (;k < boardNumRepeatableKeys; ++k) {
if (boardRepeatableKeys[k] == key) {
break;
}
}
if (k < boardNumRepeatableKeys) {
key_queue[key_queue_len] = key;
key_queue_len++;

if ((now_msec > key_press_time[key] + UI_KEY_WAIT_REPEAT &&
now_msec > key_last_repeat[key] + UI_KEY_REPEAT_INTERVAL) ||
key_last_repeat[key] == 0) {
key_last_repeat[key] = now_msec;
} else if (key_last_repeat[key] > 0) {
continue;
}
}
return key;
}
} while (key_queue_len == 0);
return key;
}

int ui_key_pressed(int key)
{
// This is a volatile static array, don't bother locking
Expand Down

0 comments on commit 2a809ea

Please sign in to comment.