Add experimental RGUI keyboard search feature.

Type '/' to start search, then type search string (case sensitive for
now due to strcasestr being GNU ext). When done, type return.
This commit is contained in:
Themaister 2013-12-09 16:18:58 +01:00
parent 40861aa17d
commit 84c93ef94a
8 changed files with 119 additions and 13 deletions

View File

@ -492,6 +492,7 @@ typedef struct driver
#endif
bool stdin_claimed;
bool block_hotkey;
bool block_input;
bool nonblock_state;
// Opaque handles to currently running window.

View File

@ -26,11 +26,9 @@ struct item_file
size_t directory_ptr;
};
void file_list_push(void *userdata,
void file_list_push(file_list_t *list,
const char *path, unsigned type, size_t directory_ptr)
{
file_list_t *list = (file_list_t*)userdata;
if (!list)
return;
@ -120,3 +118,23 @@ void file_list_get_last(const file_list_t *list,
if (list->size)
file_list_get_at_offset(list, list->size - 1, path, file_type);
}
bool file_list_search(const file_list_t *list, const char *needle, size_t *index)
{
size_t i;
const char *alt;
for (i = 0; i < list->size; i++)
{
file_list_get_alt_at_offset(list, i, &alt);
if (!alt)
continue;
if (strstr(alt, needle))
{
*index = i;
return true;
}
}
return false;
}

View File

@ -21,6 +21,8 @@
extern "C" {
#endif
#include "boolean.h"
struct item_file;
typedef struct file_list
{
@ -32,7 +34,7 @@ typedef struct file_list
void file_list_free(file_list_t *list);
void file_list_push(void *userdata, const char *path,
void file_list_push(file_list_t *userdata, const char *path,
unsigned type, size_t current_directory_ptr);
void file_list_pop(file_list_t *list, size_t *directory_ptr);
void file_list_clear(file_list_t *list);
@ -50,6 +52,8 @@ void file_list_get_alt_at_offset(const file_list_t *list, size_t index,
void file_list_sort_on_alt(file_list_t *list);
bool file_list_search(const file_list_t *list, const char *needle, size_t *index);
#ifdef __cplusplus
}
#endif

View File

@ -510,6 +510,13 @@ static void rgui_render(void *data)
rgui_render_messagebox(rgui, message_queue);
#endif
if (rgui->display_keyboard)
{
char msg[1024];
snprintf(msg, sizeof(msg), "Search: %s", rgui->keyboard.buffer ? rgui->keyboard.buffer : "");
rgui_render_messagebox(rgui, msg);
}
}
static void *rgui_init(void)

View File

@ -426,6 +426,8 @@ void menu_free(void)
rom_history_free(rgui->history);
core_info_list_free(rgui->core_info);
menu_keyboard_state_clear(&rgui->keyboard);
free(rgui);
}
@ -1382,6 +1384,7 @@ bool menu_iterate(void)
rgui->old_input_state |= 1ULL << RARCH_MENU_TOGGLE;
}
rarch_check_block_hotkey();
rarch_input_poll();
#ifdef HAVE_OVERLAY
rarch_check_overlay();
@ -1423,6 +1426,9 @@ bool menu_iterate(void)
rgui->delay_count++;
rgui->old_input_state = input_state;
if (driver.block_input)
rgui->trigger_state = 0;
action = RGUI_ACTION_NOOP;
// don't run anything first frame, only capture held inputs for old_input_state
@ -1718,13 +1724,69 @@ bool menu_poll_find_trigger(struct rgui_bind_state *state, struct rgui_bind_stat
return false;
}
bool menu_keyboard_state_event(struct rgui_keyboard_state *state,
bool down, enum retro_key key, uint32_t character)
{
// Treat extended chars as ? as we cannot support printable characters for unicode stuff.
char c = character >= 128 ? '?' : character;
if (c == '\r' || c == '\n')
return true;
if (c == '\b')
{
if (state->ptr)
{
memmove(state->buffer + state->ptr - 1, state->buffer + state->ptr,
state->size - state->ptr + 1);
state->ptr--;
state->size--;
}
}
// Handle left/right here when suitable
else if (isprint(c))
{
char *newbuf = (char*)realloc(state->buffer, state->size + 2);
if (!newbuf)
return false;
memmove(newbuf + state->ptr + 1, newbuf + state->ptr, state->size - state->ptr + 1);
newbuf[state->ptr] = c;
state->ptr++;
state->size++;
newbuf[state->size] = '\0';
state->buffer = newbuf;
}
return false;
}
void menu_keyboard_state_clear(struct rgui_keyboard_state *state)
{
free(state->buffer);
memset(state, 0, sizeof(*state));
}
void menu_key_event(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers)
{
// TODO: Do something with this. Stub for now.
(void)down;
(void)keycode;
(void)character;
(void)key_modifiers;
if (!driver.block_input && character == '/')
{
driver.block_input = true;
rgui->display_keyboard = true;
menu_keyboard_state_clear(&rgui->keyboard);
return;
}
if (driver.block_input && menu_keyboard_state_event(&rgui->keyboard, down, keycode, character) && rgui->keyboard.buffer)
{
file_list_search(rgui->selection_buf, rgui->keyboard.buffer, &rgui->selection_ptr);
menu_keyboard_state_clear(&rgui->keyboard);
driver.block_input = false;
rgui->display_keyboard = false;
rgui->old_input_state = -1ull; // Avoid triggering states on pressing return.
}
}
static inline int menu_list_get_first_char(file_list_t *buf, unsigned offset)

View File

@ -242,6 +242,17 @@ void menu_poll_bind_get_rested_axes(struct rgui_bind_state *state);
void menu_poll_bind_state(struct rgui_bind_state *state);
bool menu_poll_find_trigger(struct rgui_bind_state *state, struct rgui_bind_state *new_state);
struct rgui_keyboard_state
{
char *buffer;
size_t ptr;
size_t size;
};
void menu_keyboard_state_clear(struct rgui_keyboard_state *state);
bool menu_keyboard_state_event(struct rgui_keyboard_state *state,
bool down, enum retro_key key, uint32_t character);
#ifdef GEKKO
enum
{
@ -324,6 +335,8 @@ typedef struct
rarch_time_t last_time; // Used to throttle RGUI in case VSync is broken.
struct rgui_bind_state binds;
struct rgui_keyboard_state keyboard;
bool display_keyboard;
} rgui_handle_t;
extern rgui_handle_t *rgui;

View File

@ -678,6 +678,7 @@ void rarch_init_msg_queue(void);
void rarch_deinit_msg_queue(void);
void rarch_input_poll(void);
void rarch_check_overlay(void);
void rarch_check_block_hotkey(void);
void rarch_init_rewind(void);
void rarch_deinit_rewind(void);
void rarch_set_fullscreen(bool fullscreen);

View File

@ -2690,17 +2690,17 @@ static void check_netplay_flip(void)
}
#endif
static void check_block_hotkey(void)
void rarch_check_block_hotkey(void)
{
driver.block_hotkey = false;
driver.block_hotkey = driver.block_input;
// If we haven't bound anything to this,
// always allow hotkeys.
static const struct retro_keybind *bind = &g_settings.input.binds[0][RARCH_ENABLE_HOTKEY];
if (bind->key == RETROK_UNKNOWN && bind->joykey == NO_BTN && bind->joyaxis == AXIS_NONE)
if (!driver.block_hotkey && bind->key == RETROK_UNKNOWN && bind->joykey == NO_BTN && bind->joyaxis == AXIS_NONE)
return;
driver.block_hotkey = !input_key_pressed_func(RARCH_ENABLE_HOTKEY);
driver.block_hotkey = driver.block_input || !input_key_pressed_func(RARCH_ENABLE_HOTKEY);
}
#ifdef HAVE_OVERLAY
@ -2743,7 +2743,7 @@ static void check_grab_mouse_toggle(void)
static void do_state_checks(void)
{
check_block_hotkey();
rarch_check_block_hotkey();
#if defined(HAVE_SCREENSHOTS) && !defined(_XBOX)
check_screenshot();