Skip to content

Commit d85db97

Browse files
committed
Adds search filter for Settings, native iOS keyboard support
1 parent 4c2c177 commit d85db97

9 files changed

Lines changed: 551 additions & 22 deletions

File tree

input/drivers/cocoa_input.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333

3434
#include "../drivers_keyboard/keyboard_event_apple.h"
3535
#include "../../ui/drivers/cocoa/cocoa_common.h"
36+
#if TARGET_OS_IPHONE
37+
#include "../../ui/drivers/cocoa/apple_platform.h"
38+
#endif
3639
#include "../../ui/ui_companion_driver.h"
3740

3841
#ifdef HAVE_COREMOTION
@@ -321,6 +324,12 @@ void apple_input_keyboard_event(bool down,
321324
bool small_keyboard_enable = settings->bools.input_small_keyboard_enable;
322325
unsigned original_code = code;
323326

327+
if (ios_keyboard_active())
328+
{
329+
apple_input_keyboard_reset();
330+
return;
331+
}
332+
324333
if (keyboard_gamepad_enable)
325334
{
326335
if (apple_input_handle_icade_event(

menu/cbs/menu_cbs_title.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,11 @@ static int action_get_title_group_settings(const char *path, const char *label,
913913
action_get_title_fill_search_filter_default(
914914
info_list[i].val, s, len);
915915
else
916+
{
916917
strlcpy(s, msg_hash_to_str(info_list[i].val), len);
918+
if (info_list[i].type == MENU_ENUM_LABEL_SETTINGS_TAB)
919+
menu_entries_search_append_terms_string(s, len);
920+
}
917921
return 0;
918922
}
919923
}

menu/drivers/materialui.c

Lines changed: 224 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@
4343
#include "../menu_driver.h"
4444
#include "../menu_screensaver.h"
4545

46+
#ifdef HAVE_COCOATOUCH
47+
#include "../../ui/drivers/cocoa/apple_platform.h"
48+
#endif
49+
4650
#include "../../gfx/gfx_animation.h"
4751
#include "../../gfx/gfx_thumbnail.h"
4852
#include "../../msg_hash_lbl_str.h"
@@ -6785,6 +6789,10 @@ static void materialui_render_entry_touch_feedback(
67856789
}
67866790
}
67876791

6792+
static bool materialui_search_filter_enabled(void);
6793+
static bool materialui_settings_search_filter_enabled(void);
6794+
static const char *materialui_search_filter_get_value(void);
6795+
67886796
static void materialui_render_header(
67896797
materialui_handle_t *mui,
67906798
const uintptr_t *tex_list,
@@ -6808,7 +6816,10 @@ static void materialui_render_header(
68086816
bool show_search_icon =
68096817
(mui->flags & MUI_FLAG_IS_PLAYLIST)
68106818
|| (mui->flags & MUI_FLAG_IS_FILE_LIST)
6811-
|| (mui->flags & MUI_FLAG_IS_CORE_UPDATER_LIST);
6819+
|| (mui->flags & MUI_FLAG_IS_CORE_UPDATER_LIST)
6820+
|| materialui_search_filter_enabled();
6821+
bool show_search_field =
6822+
materialui_settings_search_filter_enabled();
68126823
bool show_switch_view_icon =
68136824
(mui->flags & MUI_FLAG_IS_PLAYLIST)
68146825
&& (mui->flags & MUI_FLAG_PRIMARY_THUMBNAIL_AVAILABLE);
@@ -7085,20 +7096,145 @@ static void materialui_render_header(
70857096
/* > Draw 'search' icon, if required */
70867097
if (show_search_icon)
70877098
{
7088-
materialui_draw_icon(
7089-
userdata, p_disp,
7090-
video_width,
7091-
video_height,
7092-
mui->icon_size,
7093-
tex_list[MUI_TEXTURE_SEARCH],
7094-
(int)video_width - (int)mui->icon_size - (int)mui->nav_bar_layout_width,
7095-
(int)mui->sys_bar_height,
7096-
0,
7097-
1,
7098-
mui->colors.header_icon,
7099-
mymat);
7099+
int search_icon_x = (int)video_width - (int)mui->icon_size
7100+
- (int)mui->nav_bar_layout_width;
7101+
bool draw_search_icon = true;
7102+
7103+
if (show_search_field)
7104+
{
7105+
const char *search_value = materialui_search_filter_get_value();
7106+
bool search_has_value = !string_is_empty(search_value);
7107+
const char *search_label = search_has_value
7108+
? search_value
7109+
: msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SEARCH);
7110+
unsigned search_field_width = mui->icon_size * 4;
7111+
unsigned search_field_height = mui->title_bar_height;
7112+
int search_field_x = (int)video_width - (int)search_field_width
7113+
- (int)mui->nav_bar_layout_width;
7114+
int search_field_y = (int)mui->sys_bar_height + (int)(mui->margin >> 2);
7115+
unsigned search_text_width = search_field_width
7116+
- mui->icon_size - mui->margin;
7117+
char search_label_buf[NAME_MAX_LENGTH];
7118+
7119+
search_label_buf[0] = '\0';
7120+
7121+
if (mui->title_bar_height > (mui->margin >> 1))
7122+
search_field_height = mui->title_bar_height - (mui->margin >> 1);
7123+
7124+
gfx_display_draw_quad(
7125+
p_disp,
7126+
userdata,
7127+
video_width,
7128+
video_height,
7129+
search_field_x,
7130+
search_field_y,
7131+
search_field_width,
7132+
search_field_height,
7133+
video_width,
7134+
video_height,
7135+
mui->colors.sys_bar_background,
7136+
NULL);
7137+
7138+
mui->ticker.s = search_label_buf;
7139+
mui->ticker.len = (unsigned)(search_text_width / mui->font_data.hint.glyph_width);
7140+
if (mui->ticker.len < 1)
7141+
mui->ticker.len = 1;
7142+
mui->ticker.str = search_label;
7143+
mui->ticker.selected = true;
71007144

7101-
usable_title_bar_width -= mui->icon_size;
7145+
gfx_animation_ticker(&mui->ticker);
7146+
7147+
gfx_display_draw_text(mui->font_data.hint.font,
7148+
search_label_buf,
7149+
search_field_x + (int)(mui->margin >> 1),
7150+
(int)(mui->sys_bar_height + (mui->title_bar_height / 2.0f) + mui->font_data.hint.line_centre_offset),
7151+
video_width, video_height, mui->colors.header_text,
7152+
TEXT_ALIGN_LEFT, 1.0f, false, 0.0f, false);
7153+
7154+
if (menu_input_dialog_get_display_kb())
7155+
{
7156+
retro_time_t caret_time = menu_driver_get_current_time();
7157+
if (((caret_time / 500000) % 2) == 0)
7158+
{
7159+
int caret_x;
7160+
unsigned caret_h = (unsigned)(mui->font_data.hint.line_height * 0.8f);
7161+
int caret_y = (int)(mui->sys_bar_height
7162+
+ (mui->title_bar_height / 2.0f))
7163+
- (int)(caret_h / 2);
7164+
7165+
if (search_has_value)
7166+
{
7167+
unsigned text_w = font_driver_get_message_width(
7168+
mui->font_data.hint.font,
7169+
search_label_buf,
7170+
strlen(search_label_buf),
7171+
1.0f);
7172+
caret_x = search_field_x + (int)(mui->margin >> 1) + (int)text_w;
7173+
if (caret_x > search_field_x + (int)search_text_width)
7174+
caret_x = search_field_x + (int)search_text_width;
7175+
}
7176+
else
7177+
caret_x = search_field_x + (int)(mui->margin >> 1);
7178+
7179+
gfx_display_draw_quad(
7180+
p_disp,
7181+
userdata,
7182+
video_width,
7183+
video_height,
7184+
caret_x,
7185+
caret_y,
7186+
2,
7187+
caret_h,
7188+
video_width,
7189+
video_height,
7190+
mui->colors.header_icon,
7191+
NULL);
7192+
}
7193+
}
7194+
7195+
search_icon_x = search_field_x + (int)search_field_width
7196+
- (int)mui->icon_size;
7197+
usable_title_bar_width -= search_field_width;
7198+
7199+
if (search_has_value)
7200+
{
7201+
unsigned clear_icon_size = (mui->icon_size * 2) / 3;
7202+
int clear_icon_x = search_icon_x
7203+
+ ((int)mui->icon_size - (int)clear_icon_size) / 2;
7204+
int clear_icon_y = (int)mui->sys_bar_height
7205+
+ ((int)mui->title_bar_height - (int)clear_icon_size) / 2;
7206+
7207+
materialui_draw_icon(
7208+
userdata, p_disp,
7209+
video_width,
7210+
video_height,
7211+
clear_icon_size,
7212+
tex_list[MUI_TEXTURE_CLOSE],
7213+
clear_icon_x,
7214+
clear_icon_y,
7215+
0,
7216+
1,
7217+
mui->colors.header_icon,
7218+
mymat);
7219+
draw_search_icon = false;
7220+
}
7221+
}
7222+
else
7223+
usable_title_bar_width -= mui->icon_size;
7224+
7225+
if (draw_search_icon)
7226+
materialui_draw_icon(
7227+
userdata, p_disp,
7228+
video_width,
7229+
video_height,
7230+
mui->icon_size,
7231+
tex_list[MUI_TEXTURE_SEARCH],
7232+
search_icon_x,
7233+
(int)mui->sys_bar_height,
7234+
0,
7235+
1,
7236+
mui->colors.header_icon,
7237+
mymat);
71027238

71037239
/* > Draw 'switch view' icon, if required
71047240
* Note: We can take a shortcut here because
@@ -7207,6 +7343,41 @@ static void materialui_render_header(
72077343
TEXT_ALIGN_LEFT, 1.0f, false, 0.0f, false);
72087344
}
72097345

7346+
static bool materialui_search_filter_enabled(void)
7347+
{
7348+
const char *label = NULL;
7349+
unsigned type = MENU_SETTINGS_NONE;
7350+
7351+
menu_entries_get_last_stack(NULL, &label, &type, NULL, NULL);
7352+
7353+
return menu_driver_search_filter_enabled(label, type);
7354+
}
7355+
7356+
static bool materialui_settings_search_filter_enabled(void)
7357+
{
7358+
const char *label = NULL;
7359+
unsigned type = MENU_SETTINGS_NONE;
7360+
7361+
menu_entries_get_last_stack(NULL, &label, &type, NULL, NULL);
7362+
7363+
return !string_is_empty(label)
7364+
&& string_is_equal(label, MENU_ENUM_LABEL_SETTINGS_TAB_STR)
7365+
&& menu_driver_search_filter_enabled(label, type);
7366+
}
7367+
7368+
static const char *materialui_search_filter_get_value(void)
7369+
{
7370+
menu_search_terms_t *search_terms = menu_entries_search_get_terms();
7371+
7372+
if (menu_input_dialog_get_display_kb())
7373+
return menu_input_dialog_get_buffer();
7374+
7375+
if (search_terms && search_terms->size > 0)
7376+
return search_terms->terms[search_terms->size - 1];
7377+
7378+
return "";
7379+
}
7380+
72107381
/* Use separate functions for bottom/right navigation
72117382
* bars. This involves substantial code duplication, but if
72127383
* we try to handle this with a single function then
@@ -8380,6 +8551,7 @@ static void materialui_frame(void *data, video_frame_info_t *video_info)
83808551
font_flush(video_width, video_height, &mui->font_data.title);
83818552
font_flush(video_width, video_height, &mui->font_data.hint);
83828553

8554+
#ifndef HAVE_COCOATOUCH
83838555
/* Handle onscreen keyboard */
83848556
if (menu_input_dialog_get_display_kb())
83858557
{
@@ -8432,6 +8604,7 @@ static void materialui_frame(void *data, video_frame_info_t *video_info)
84328604
* > Message box & osk only use list font */
84338605
font_flush(video_width, video_height, &mui->font_data.list);
84348606
}
8607+
#endif
84358608

84368609
/* Draw message box */
84378610
if (*mui->msgbox)
@@ -10493,6 +10666,15 @@ static int materialui_switch_tabs(materialui_handle_t *mui,
1049310666
if (!selection_buf)
1049410667
return -1;
1049510668

10669+
/* Dismiss keyboard if search was active on the current tab */
10670+
if (menu_input_dialog_get_display_kb())
10671+
menu_input_dialog_end();
10672+
10673+
/* Clear any active search filter when switching tabs — search
10674+
* terms are global and would otherwise leak into other tabs
10675+
* (playlists, core manager, etc.) */
10676+
menu_entries_search_set_term("");
10677+
1049610678
/* Perform pre-switch operations */
1049710679
stack_flushed = materialui_preswitch_tabs(mui, target_tab);
1049810680

@@ -11387,25 +11569,46 @@ static int materialui_pointer_up(void *userdata,
1138711569
/* Tap/press header: Menu back/cancel, or search/switch view */
1138811570
else if (y < header_height)
1138911571
{
11390-
/* If this is a playlist, file list or core
11391-
* updater list, enable search functionality */
11392-
if ( (mui->flags & MUI_FLAG_IS_PLAYLIST)
11572+
/* If this list supports search filtering,
11573+
* enable search functionality */
11574+
if ( materialui_search_filter_enabled()
11575+
|| (mui->flags & MUI_FLAG_IS_PLAYLIST)
1139311576
|| (mui->flags & MUI_FLAG_IS_FILE_LIST)
1139411577
|| (mui->flags & MUI_FLAG_IS_CORE_UPDATER_LIST))
1139511578
{
11579+
bool settings_search_enabled =
11580+
materialui_settings_search_filter_enabled();
11581+
bool search_has_value = settings_search_enabled
11582+
&& !string_is_empty(materialui_search_filter_get_value());
1139611583
bool switch_view_enabled =
1139711584
(mui->flags & MUI_FLAG_IS_PLAYLIST)
1139811585
&& (mui->flags & MUI_FLAG_PRIMARY_THUMBNAIL_AVAILABLE);
11586+
unsigned search_width = settings_search_enabled
11587+
? mui->icon_size * 4
11588+
: mui->icon_size;
1139911589
/* Note: We add a little extra padding to minimise
1140011590
* the risk of accidentally triggering a cancel */
1140111591
unsigned back_x_threshold =
1140211592
width -
11403-
((switch_view_enabled ? 3 : 2) * mui->icon_size) -
11404-
mui->nav_bar_layout_width;
11593+
(switch_view_enabled ? (search_width + 2 * mui->icon_size)
11594+
: (search_width + mui->icon_size)) -
11595+
mui->nav_bar_layout_width;
1140511596

11406-
/* Check if user has touched search icon */
11407-
if (x > width - mui->icon_size - mui->nav_bar_layout_width)
11597+
/* Check if user has touched search affordance */
11598+
if (x > width - search_width - mui->nav_bar_layout_width)
11599+
{
11600+
if ( settings_search_enabled
11601+
&& search_has_value
11602+
&& x > width - mui->icon_size - mui->nav_bar_layout_width)
11603+
{
11604+
menu_driver_search_filter_update("");
11605+
#ifdef HAVE_COCOATOUCH
11606+
ios_keyboard_set_text("");
11607+
#endif
11608+
return 0;
11609+
}
1140811610
return menu_input_dialog_start_search() ? 0 : -1;
11611+
}
1140911612
/* Check if user has touched switch view icon */
1141011613
else if (switch_view_enabled &&
1141111614
x > width - (2 * mui->icon_size) - mui->nav_bar_layout_width)

0 commit comments

Comments
 (0)