From 371d0b7395055577c61e2f7f88b42a35e34ad50c Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Thu, 1 Apr 2021 17:25:45 +0100 Subject: [PATCH 1/2] Add optional menu screensaver --- config.def.h | 7 + configuration.c | 2 + configuration.h | 2 + gfx/gfx_widgets.c | 5 + intl/msg_hash_lbl.h | 8 + intl/msg_hash_us.h | 16 ++ menu/cbs/menu_cbs_sublabel.c | 8 + menu/drivers/materialui.c | 49 +++++- menu/drivers/ozone/ozone.c | 35 +++++ menu/drivers/ozone/ozone.h | 2 + menu/drivers/rgui.c | 127 +++++++++++---- menu/drivers/xmb.c | 48 +++++- menu/menu_defines.h | 2 + menu/menu_displaylist.c | 19 ++- menu/menu_driver.h | 2 + menu/menu_setting.c | 50 +++++- msg_hash.h | 2 + retroarch.c | 294 +++++++++++++++++++++++++++-------- retroarch.h | 1 + retroarch_data.h | 6 + 20 files changed, 579 insertions(+), 106 deletions(-) diff --git a/config.def.h b/config.def.h index 4f199f3b02..c5bc18f575 100644 --- a/config.def.h +++ b/config.def.h @@ -574,6 +574,12 @@ static const bool menu_savestate_resume = false; #define DEFAULT_QUIT_ON_CLOSE_CONTENT QUIT_ON_CLOSE_CONTENT_DISABLED +/* While the menu is active, supported drivers + * will display a screensaver after SCREENSAVER_TIMEOUT + * seconds of inactivity. A timeout of zero disables + * the screensaver */ +#define DEFAULT_MENU_SCREENSAVER_TIMEOUT 0 + static const bool content_show_settings = true; static const bool content_show_favorites = true; #ifdef HAVE_IMAGEVIEWER @@ -655,6 +661,7 @@ static const unsigned rgui_aspect_lock = RGUI_ASPECT_RATIO_LOCK_NONE; static const bool rgui_shadows = false; static const unsigned rgui_particle_effect = RGUI_PARTICLE_EFFECT_NONE; #define DEFAULT_RGUI_PARTICLE_EFFECT_SPEED 1.0f +#define DEFAULT_RGUI_PARTICLE_EFFECT_SCREENSAVER true static const bool rgui_extended_ascii = false; #define DEFAULT_RGUI_SWITCH_ICONS true #endif diff --git a/configuration.c b/configuration.c index 82f2c32b00..5628c71df5 100644 --- a/configuration.c +++ b/configuration.c @@ -1676,6 +1676,7 @@ static struct config_bool_setting *populate_settings_bool( SETTING_BOOL("rgui_swap_thumbnails", &settings->bools.menu_rgui_swap_thumbnails, true, rgui_swap_thumbnails, false); SETTING_BOOL("rgui_extended_ascii", &settings->bools.menu_rgui_extended_ascii, true, rgui_extended_ascii, false); SETTING_BOOL("rgui_switch_icons", &settings->bools.menu_rgui_switch_icons, true, DEFAULT_RGUI_SWITCH_ICONS, false); + SETTING_BOOL("rgui_particle_effect_screensaver", &settings->bools.menu_rgui_particle_effect_screensaver, true, DEFAULT_RGUI_PARTICLE_EFFECT_SCREENSAVER, false); #endif #ifdef HAVE_XMB SETTING_BOOL("xmb_shadows_enable", &settings->bools.menu_xmb_shadows_enable, true, DEFAULT_XMB_SHADOWS_ENABLE, false); @@ -1933,6 +1934,7 @@ static struct config_uint_setting *populate_settings_uint( SETTING_UINT("menu_ticker_type", &settings->uints.menu_ticker_type, true, DEFAULT_MENU_TICKER_TYPE, false); SETTING_UINT("menu_scroll_delay", &settings->uints.menu_scroll_delay, true, DEFAULT_MENU_SCROLL_DELAY, false); SETTING_UINT("content_show_add_entry", &settings->uints.menu_content_show_add_entry, true, DEFAULT_MENU_CONTENT_SHOW_ADD_ENTRY, false); + SETTING_UINT("menu_screensaver_timeout", &settings->uints.menu_screensaver_timeout, true, DEFAULT_MENU_SCREENSAVER_TIMEOUT, false); #ifdef HAVE_RGUI SETTING_UINT("rgui_menu_color_theme", &settings->uints.menu_rgui_color_theme, true, DEFAULT_RGUI_COLOR_THEME, false); SETTING_UINT("rgui_thumbnail_downscaler", &settings->uints.menu_rgui_thumbnail_downscaler, true, rgui_thumbnail_downscaler, false); diff --git a/configuration.h b/configuration.h index 660d2db105..6784853a6f 100644 --- a/configuration.h +++ b/configuration.h @@ -249,6 +249,7 @@ typedef struct settings unsigned menu_ticker_type; unsigned menu_scroll_delay; unsigned menu_content_show_add_entry; + unsigned menu_screensaver_timeout; unsigned playlist_entry_remove_enable; unsigned playlist_show_inline_core_name; @@ -610,6 +611,7 @@ typedef struct settings bool menu_rgui_swap_thumbnails; bool menu_rgui_extended_ascii; bool menu_rgui_switch_icons; + bool menu_rgui_particle_effect_screensaver; bool menu_xmb_shadows_enable; bool menu_xmb_vertical_thumbnails; bool menu_content_show_settings; diff --git a/gfx/gfx_widgets.c b/gfx/gfx_widgets.c index 2e630944f1..c4cf5783ff 100644 --- a/gfx/gfx_widgets.c +++ b/gfx/gfx_widgets.c @@ -1598,10 +1598,15 @@ void gfx_widgets_frame(void *data) bool widgets_is_fastforwarding = video_info->widgets_is_fast_forwarding; bool widgets_is_rewinding = video_info->widgets_is_rewinding; bool runloop_is_slowmotion = video_info->runloop_is_slowmotion; + bool menu_screensaver_active = video_info->menu_screensaver_active; int top_right_x_advance = video_width; p_dispwidget->gfx_widgets_frame_count++; + /* If menu screensaver is active, draw nothing */ + if (menu_screensaver_active) + return; + video_driver_set_viewport(video_width, video_height, true, false); /* Font setup */ diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index 709f1d708c..a8234cd6e9 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -2162,6 +2162,10 @@ MSG_HASH( MENU_ENUM_LABEL_PAUSE_NONACTIVE, "pause_nonactive" ) +MSG_HASH( + MENU_ENUM_LABEL_MENU_SCREENSAVER_TIMEOUT, + "menu_screensaver_timeout" + ) MSG_HASH( MENU_ENUM_LABEL_PERFCNT_ENABLE, "perfcnt_enable" @@ -4138,6 +4142,10 @@ MSG_HASH( MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT_SPEED, "rgui_particle_effect_speed" ) +MSG_HASH( + MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT_SCREENSAVER, + "rgui_particle_effect_screensaver" + ) MSG_HASH( MENU_ENUM_LABEL_MENU_RGUI_EXTENDED_ASCII, "rgui_extended_ascii" diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 2e0df9d1cb..da4d0aefe7 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -3939,6 +3939,14 @@ MSG_HASH( MENU_ENUM_SUBLABEL_QUIT_ON_CLOSE_CONTENT, "Automatically quit RetroArch when closing content. 'CLI' quits only when content is launched via command line." ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_MENU_SCREENSAVER_TIMEOUT, + "Menu Screensaver Timeout" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_MENU_SCREENSAVER_TIMEOUT, + "While menu is active, a screensaver will be displayed after the specified period of inactivity." + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_MOUSE_ENABLE, "Mouse Support" @@ -8184,6 +8192,14 @@ MSG_HASH( MENU_ENUM_SUBLABEL_MENU_RGUI_PARTICLE_EFFECT_SPEED, "Adjust speed of background particle animation effects." ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_MENU_RGUI_PARTICLE_EFFECT_SCREENSAVER, + "Screensaver Background Animation" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_MENU_RGUI_PARTICLE_EFFECT_SCREENSAVER, + "Display background particle animation effect while menu screensaver is active." + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_MENU_RGUI_INLINE_THUMBNAILS, "Show Playlist Thumbnails" diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 9875942d7a..6d8a890b70 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -523,6 +523,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_pause_libretro, MENU_ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_savestate_resume, MENU_ENUM_SUBLABEL_MENU_SAVESTATE_RESUME) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_insert_disk_resume, MENU_ENUM_SUBLABEL_MENU_INSERT_DISK_RESUME) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_quit_on_close_content, MENU_ENUM_SUBLABEL_QUIT_ON_CLOSE_CONTENT) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_screensaver_timeout, MENU_ENUM_SUBLABEL_MENU_SCREENSAVER_TIMEOUT) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_driver, MENU_ENUM_SUBLABEL_VIDEO_DRIVER) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_audio_driver, MENU_ENUM_SUBLABEL_AUDIO_DRIVER) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_driver, MENU_ENUM_SUBLABEL_INPUT_DRIVER) @@ -910,6 +911,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_rgui_menu_theme_preset, DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_rgui_shadows, MENU_ENUM_SUBLABEL_MENU_RGUI_SHADOWS) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_rgui_particle_effect, MENU_ENUM_SUBLABEL_MENU_RGUI_PARTICLE_EFFECT) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_rgui_particle_effect_speed, MENU_ENUM_SUBLABEL_MENU_RGUI_PARTICLE_EFFECT_SPEED) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_rgui_particle_effect_screensaver, MENU_ENUM_SUBLABEL_MENU_RGUI_PARTICLE_EFFECT_SCREENSAVER) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_rgui_inline_thumbnails, MENU_ENUM_SUBLABEL_MENU_RGUI_INLINE_THUMBNAILS) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_rgui_swap_thumbnails, MENU_ENUM_SUBLABEL_MENU_RGUI_SWAP_THUMBNAILS) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_rgui_thumbnail_downscaler, MENU_ENUM_SUBLABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER) @@ -2917,6 +2919,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_QUIT_ON_CLOSE_CONTENT: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_quit_on_close_content); break; + case MENU_ENUM_LABEL_MENU_SCREENSAVER_TIMEOUT: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_screensaver_timeout); + break; case MENU_ENUM_LABEL_MENU_INPUT_SWAP_OK_CANCEL: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_swap_ok_cancel); break; @@ -4021,6 +4026,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT_SPEED: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_particle_effect_speed); break; + case MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT_SCREENSAVER: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_particle_effect_screensaver); + break; case MENU_ENUM_LABEL_MENU_RGUI_INLINE_THUMBNAILS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_inline_thumbnails); break; diff --git a/menu/drivers/materialui.c b/menu/drivers/materialui.c index 4713afeaea..8366012483 100644 --- a/menu/drivers/materialui.c +++ b/menu/drivers/materialui.c @@ -1155,6 +1155,7 @@ typedef struct float divider[16]; float entry_divider[16]; float screen_fade[16]; + float screensaver_bg[16]; float missing_thumbnail_icon[16]; float landscape_border_shadow_opacity; float status_bar_shadow_opacity; @@ -1645,7 +1646,8 @@ typedef struct materialui_handle char fullscreen_thumbnail_label[255]; bool is_portrait; bool need_compute; - bool mouse_show; + bool show_mouse; + bool show_screensaver; bool is_playlist_tab; bool is_playlist; bool is_file_list; @@ -1848,6 +1850,10 @@ static void materialui_prepare_colors( current_theme->screen_fade, mui->colors.screen_fade, mui->colors.screen_fade_opacity); + /* Screensaver background is always pure black, + * 100% opacity */ + hex32_to_rgba_normalized(0x000000, mui->colors.screensaver_bg, 1.0f); + /* Shadow colours require special handling * (since they are gradients) */ mui->colors.header_shadow[11] = current_theme->header_shadow_opacity; @@ -3524,6 +3530,11 @@ static void materialui_render(void *data, /* Read pointer state */ menu_input_get_pointer_state(&mui->pointer); + /* If menu screensaver is active, no further + * action is required */ + if (mui->show_screensaver) + return; + /* Need to adjust/range-check scroll position first, * otherwise cannot determine correct entry index for * MENU_ENTRIES_CTL_SET_START */ @@ -6677,6 +6688,23 @@ static void materialui_frame(void *data, video_frame_info_t *video_info) video_driver_set_viewport(video_width, video_height, true, false); + /* If menu screensaver is active, blank the + * screen and skip drawing menu elements */ + if (mui->show_screensaver) + { + gfx_display_draw_quad( + p_disp, + userdata, + video_width, + video_height, + 0, 0, + video_width, video_height, + video_width, video_height, + mui->colors.screensaver_bg); + video_driver_set_viewport(video_width, video_height, false, true); + return; + } + /* Clear text */ materialui_font_bind(&mui->font_data.title); materialui_font_bind(&mui->font_data.list); @@ -6865,7 +6893,7 @@ static void materialui_frame(void *data, video_frame_info_t *video_info) } /* Draw mouse cursor */ - if (mui->mouse_show && (mui->pointer.type != MENU_POINTER_DISABLED)) + if (mui->show_mouse && (mui->pointer.type != MENU_POINTER_DISABLED)) { float color_white[16] = { 1.0f, 1.0f, 1.0f, 1.0f, @@ -7744,6 +7772,9 @@ static void *materialui_init(void **userdata, bool video_is_threaded) mui->last_show_nav_bar = settings->bools.menu_materialui_show_nav_bar; mui->last_auto_rotate_nav_bar = settings->bools.menu_materialui_auto_rotate_nav_bar; + mui->show_mouse = false; + mui->show_screensaver = false; + mui->need_compute = false; mui->is_playlist_tab = false; mui->is_playlist = false; @@ -8397,10 +8428,10 @@ static int materialui_environ(enum menu_environ_cb type, switch (type) { case MENU_ENVIRON_ENABLE_MOUSE_CURSOR: - mui->mouse_show = true; + mui->show_mouse = true; break; case MENU_ENVIRON_DISABLE_MOUSE_CURSOR: - mui->mouse_show = false; + mui->show_mouse = false; break; case MENU_ENVIRON_RESET_HORIZONTAL_LIST: { @@ -8421,11 +8452,17 @@ static int materialui_environ(enum menu_environ_cb type, } } break; - default: + case MENU_ENVIRON_ENABLE_SCREENSAVER: + mui->show_screensaver = true; break; + case MENU_ENVIRON_DISABLE_SCREENSAVER: + mui->show_screensaver = false; + break; + default: + return -1; } - return -1; + return 0; } /* Called before we push the new list after: diff --git a/menu/drivers/ozone/ozone.c b/menu/drivers/ozone/ozone.c index 6fb9ae0ca2..d1798b704b 100644 --- a/menu/drivers/ozone/ozone.c +++ b/menu/drivers/ozone/ozone.c @@ -705,7 +705,10 @@ static void *ozone_init(void **userdata, bool video_is_threaded) *userdata = ozone; for (i = 0; i < 15; i++) + { ozone->pure_white[i] = 1.00f; + ozone->pure_black[i] = 0.00f; + } ozone->last_width = width; ozone->last_height = height; @@ -721,6 +724,7 @@ static void *ozone_init(void **userdata, bool video_is_threaded) ozone->categories_selection_ptr = 0; ozone->pending_message = NULL; ozone->show_cursor = false; + ozone->show_screensaver = false; ozone->first_frame = true; ozone->cursor_mode = false; @@ -1782,6 +1786,14 @@ static void ozone_render(void *data, /* Read pointer state */ menu_input_get_pointer_state(&ozone->pointer); + /* If menu screensaver is active, no further + * action is required */ + if (ozone->show_screensaver) + { + GFX_ANIMATION_CLEAR_ACTIVE(p_anim); + return; + } + /* Check whether pointer is enabled */ if (ozone->pointer.type != MENU_POINTER_DISABLED) { @@ -2944,6 +2956,23 @@ static void ozone_frame(void *data, video_frame_info_t *video_info) video_driver_set_viewport(video_width, video_height, true, false); + /* If menu screensaver is active, blank the + * screen and skip drawing menu elements */ + if (ozone->show_screensaver) + { + gfx_display_set_alpha(ozone->pure_black, 1.0f); + gfx_display_draw_quad( + p_disp, + userdata, + video_width, + video_height, + 0, 0, video_width, video_height, + video_width, video_height, + ozone->pure_black); + video_driver_set_viewport(video_width, video_height, false, true); + return; + } + /* Clear text */ ozone_font_bind(&ozone->fonts.footer); ozone_font_bind(&ozone->fonts.title); @@ -3635,6 +3664,12 @@ static int ozone_environ_cb(enum menu_environ_cb type, void *data, void *userdat ozone_refresh_horizontal_list(ozone, settings); } break; + case MENU_ENVIRON_ENABLE_SCREENSAVER: + ozone->show_screensaver = true; + break; + case MENU_ENVIRON_DISABLE_SCREENSAVER: + ozone->show_screensaver = false; + break; default: return -1; } diff --git a/menu/drivers/ozone/ozone.h b/menu/drivers/ozone/ozone.h index fb4d6e0f8a..a9e27d1aea 100644 --- a/menu/drivers/ozone/ozone.h +++ b/menu/drivers/ozone/ozone.h @@ -212,6 +212,7 @@ struct ozone_handle float sidebar_offset; float last_scale_factor; float pure_white[16]; + float pure_black[16]; struct { @@ -287,6 +288,7 @@ struct ozone_handle bool pointer_in_sidebar; bool last_pointer_in_sidebar; bool show_cursor; + bool show_screensaver; bool cursor_mode; bool sidebar_collapsed; bool show_thumbnail_bar; diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index e6bdd34a50..3eaed31537 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -523,6 +523,9 @@ typedef struct uint16_t border_light_color; uint16_t shadow_color; uint16_t particle_color; + /* Screensaver colors */ + uint16_t ss_bg_color; + uint16_t ss_particle_color; } rgui_colors_t; typedef struct @@ -653,7 +656,8 @@ typedef struct bool bg_modified; bool force_redraw; - bool mouse_show; + bool show_mouse; + bool show_screensaver; bool ignore_resize_events; bool bg_thickness; bool border_thickness; @@ -1630,13 +1634,21 @@ static void rgui_render_particle_effect( unsigned fb_height) { size_t i; + uint16_t particle_color; /* Give speed factor a long, awkward name to minimise * risk of clashing with specific particle effect * implementation variables... */ - float global_speed_factor = 1.0f; - settings_t *settings = config_get_ptr(); - float particle_effect_speed = settings ? settings->floats.menu_rgui_particle_effect_speed : 0.0f; - uint16_t *frame_buf_data = NULL; + float global_speed_factor = 1.0f; + settings_t *settings = config_get_ptr(); + float particle_effect_speed = 0.0f; + bool particle_effect_screensaver = false; + uint16_t *frame_buf_data = NULL; + + if (settings) + { + particle_effect_speed = settings->floats.menu_rgui_particle_effect_speed; + particle_effect_screensaver = settings->bools.menu_rgui_particle_effect_screensaver; + } /* Sanity check */ if (!rgui || !rgui->frame_buf.data) @@ -1644,10 +1656,22 @@ static void rgui_render_particle_effect( frame_buf_data = rgui->frame_buf.data; + /* Check whether screensaver is currently active */ + if (rgui->show_screensaver) + { + /* Return early if screensaver animation is + * disabled */ + if (!particle_effect_screensaver) + return; + particle_color = rgui->colors.ss_particle_color; + } + else + particle_color = rgui->colors.particle_color; + /* Adjust global animation speed */ /* > Apply user configured speed multiplier */ if (particle_effect_speed > 0.0001f) - global_speed_factor = particle_effect_speed ; + global_speed_factor = particle_effect_speed; /* > Account for non-standard frame times * (high/low refresh rates, or frame drops) */ @@ -1715,7 +1739,7 @@ static void rgui_render_particle_effect( /* Draw particle */ on_screen = rgui_draw_particle(frame_buf_data, fb_width, fb_height, (int)particle->a, (int)particle->b, - particle_size, particle_size, rgui->colors.particle_color); + particle_size, particle_size, particle_color); /* Reset particle if it has fallen off screen */ if (!on_screen) @@ -1750,7 +1774,7 @@ static void rgui_render_particle_effect( /* Draw particle */ on_screen = rgui_draw_particle(frame_buf_data, fb_width, fb_height, (int)particle->a, (int)particle->b, - 2, (unsigned)particle->c, rgui->colors.particle_color); + 2, (unsigned)particle->c, particle_color); /* Update y pos */ particle->b += particle->d * global_speed_factor; @@ -1793,7 +1817,7 @@ static void rgui_render_particle_effect( /* Draw particle */ rgui_draw_particle(frame_buf_data, fb_width, fb_height, - x, y, particle_size, particle_size, rgui->colors.particle_color); + x, y, particle_size, particle_size, particle_color); /* Update particle speed */ r_speed = particle->c * global_speed_factor; @@ -1853,7 +1877,7 @@ static void rgui_render_particle_effect( /* Draw particle */ on_screen = rgui_draw_particle(frame_buf_data, fb_width, fb_height, - x, y, particle_size, particle_size, rgui->colors.particle_color); + x, y, particle_size, particle_size, particle_color); /* Update depth */ particle->c -= particle->d * global_speed_factor; @@ -1887,7 +1911,9 @@ static void rgui_render_particle_effect( /* If border is enabled, it must be drawn *above* * particle effect * (Wastes CPU cycles, but nothing we can do about it...) */ - if (rgui->border_enable && !rgui->show_wallpaper) + if (rgui->border_enable && + !rgui->show_wallpaper && + !rgui->show_screensaver) rgui_render_border(rgui, frame_buf_data, fb_width, fb_height); } @@ -2220,15 +2246,27 @@ static void rgui_render_background(rgui_t *rgui, frame_buf_t *frame_buf = &rgui->frame_buf; frame_buf_t *background_buf = &rgui->background_buf; - if (frame_buf->data && background_buf->data) - { - /* Sanity check */ - if ((fb_width != frame_buf->width) || (fb_height != frame_buf->height) || (fb_pitch != frame_buf->width << 1)) - return; + /* Sanity check */ + if (!frame_buf->data || + (fb_width != frame_buf->width) || + (fb_height != frame_buf->height) || + (fb_pitch != frame_buf->width << 1)) + return; - /* Copy background to framebuffer */ - memcpy(frame_buf->data, background_buf->data, frame_buf->width * frame_buf->height * sizeof(uint16_t)); + /* If screensaver is active, 'zero out' framebuffer */ + if (rgui->show_screensaver) + { + size_t i; + uint16_t ss_bg_color = rgui->colors.ss_bg_color; + uint16_t *frame_buf_ptr = frame_buf->data; + + for (i = 0; i < frame_buf->width * frame_buf->height; i++) + *(frame_buf_ptr++) = ss_bg_color; } + /* Otherwise copy background to framebuffer */ + else if (background_buf->data) + memcpy(frame_buf->data, background_buf->data, + frame_buf->width * frame_buf->height * sizeof(uint16_t)); } static void rgui_render_fs_thumbnail(rgui_t *rgui, @@ -2647,6 +2685,7 @@ static void rgui_cache_background(rgui_t *rgui, static void prepare_rgui_colors(rgui_t *rgui, settings_t *settings) { rgui_theme_t theme_colors; + uint32_t ss_particle_color_argb32; unsigned rgui_color_theme = settings->uints.menu_rgui_color_theme; const char *rgui_theme_preset = settings->paths.path_rgui_theme_preset; @@ -2684,6 +2723,19 @@ static void prepare_rgui_colors(rgui_t *rgui, settings_t *settings) rgui->colors.shadow_color = argb32_to_pixel_platform_format(theme_colors.shadow_color); rgui->colors.particle_color = argb32_to_pixel_platform_format(theme_colors.particle_color); + /* Screensaver background is black, 100% opacity */ + rgui->colors.ss_bg_color = argb32_to_pixel_platform_format(0xFF000000); + /* Screensaver particles are a 75:25 mix of + * regular background animation particle colour + * and black, with 100% opacity */ + ss_particle_color_argb32 = (theme_colors.particle_color + + (theme_colors.particle_color & 0x1010101)) >> 1; + ss_particle_color_argb32 = (theme_colors.particle_color + + ss_particle_color_argb32 + + ((theme_colors.particle_color ^ ss_particle_color_argb32) & 0x1010101)) >> 1; + rgui->colors.ss_particle_color = argb32_to_pixel_platform_format( + ss_particle_color_argb32 | 0xFF000000); + rgui->bg_modified = true; rgui->force_redraw = true; } @@ -4063,6 +4115,11 @@ static void rgui_render(void *data, if (rgui->particle_effect != RGUI_PARTICLE_EFFECT_NONE) rgui_render_particle_effect(rgui, p_anim, fb_width, fb_height); + /* If screensaver is active, skip drawing of + * text/thumbnails */ + if (rgui->show_screensaver) + return; + /* We use a single ticker for all text animations, * with the following configuration: */ if (use_smooth_ticker) @@ -4634,7 +4691,7 @@ static void rgui_render(void *data, rgui->force_redraw = true; } - if (rgui->mouse_show) + if (rgui->show_mouse) { bool cursor_visible = video_fullscreen && menu_mouse_enable; @@ -5293,6 +5350,9 @@ static void *rgui_init(void **userdata, bool video_is_threaded) rgui->last_width = rgui->frame_buf.width; rgui->last_height = rgui->frame_buf.height; + rgui->show_mouse = false; + rgui->show_screensaver = false; + /* Initialise particle effect, if required */ if (rgui->particle_effect != RGUI_PARTICLE_EFFECT_NONE) rgui_init_particle_effect(rgui, p_disp); @@ -5909,26 +5969,32 @@ static int rgui_environ(enum menu_environ_cb type, rgui_t *rgui = (rgui_t*)userdata; gfx_display_t *p_disp = disp_get_ptr(); + if (!rgui) + return -1; + switch (type) { case MENU_ENVIRON_ENABLE_MOUSE_CURSOR: - if (!rgui) - return -1; - rgui->mouse_show = true; + rgui->show_mouse = true; p_disp->framebuf_dirty = true; break; case MENU_ENVIRON_DISABLE_MOUSE_CURSOR: - if (!rgui) - return -1; - rgui->mouse_show = false; + rgui->show_mouse = false; p_disp->framebuf_dirty = false; break; - case 0: - default: + case MENU_ENVIRON_ENABLE_SCREENSAVER: + rgui->show_screensaver = true; + rgui->force_redraw = true; break; + case MENU_ENVIRON_DISABLE_SCREENSAVER: + rgui->show_screensaver = false; + rgui->force_redraw = true; + break; + default: + return -1; } - return -1; + return 0; } /* Forward declaration */ @@ -6067,7 +6133,8 @@ static void rgui_frame(void *data, video_frame_info_t *video_info) rgui->force_redraw = true; } - if (rgui->particle_effect != RGUI_PARTICLE_EFFECT_NONE) + if ((rgui->particle_effect != RGUI_PARTICLE_EFFECT_NONE) && + (!rgui->show_screensaver || settings->bools.menu_rgui_particle_effect_screensaver)) rgui->force_redraw = true; if (settings->bools.menu_rgui_extended_ascii != rgui->extended_ascii_enable) @@ -6203,7 +6270,7 @@ static void rgui_frame(void *data, video_frame_info_t *video_info) } /* Read pointer input */ - if ( settings->bools.menu_mouse_enable || + if ( settings->bools.menu_mouse_enable || settings->bools.menu_pointer_enable) { menu_input_get_pointer_state(&rgui->pointer); diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index 9cee3f649b..943d5387d1 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -370,7 +370,8 @@ typedef struct xmb_handle bool fullscreen_thumbnails_available; bool show_fullscreen_thumbnails; - bool mouse_show; + bool show_mouse; + bool show_screensaver; bool use_ps3_layout; bool last_use_ps3_layout; bool assets_missing; @@ -2286,14 +2287,20 @@ static int xmb_environ(enum menu_environ_cb type, void *data, void *userdata) switch (type) { case MENU_ENVIRON_ENABLE_MOUSE_CURSOR: - xmb->mouse_show = true; + xmb->show_mouse = true; break; case MENU_ENVIRON_DISABLE_MOUSE_CURSOR: - xmb->mouse_show = false; + xmb->show_mouse = false; break; case MENU_ENVIRON_RESET_HORIZONTAL_LIST: xmb_refresh_horizontal_list(xmb); break; + case MENU_ENVIRON_ENABLE_SCREENSAVER: + xmb->show_screensaver = true; + break; + case MENU_ENVIRON_DISABLE_SCREENSAVER: + xmb->show_screensaver = false; + break; default: return -1; } @@ -3895,6 +3902,13 @@ static void xmb_render(void *data, /* Read pointer state */ menu_input_get_pointer_state(&xmb->pointer); + /* If menu screensaver is active, no further + * action is required */ + if (xmb->show_screensaver) + { + GFX_ANIMATION_CLEAR_ACTIVE(p_anim); + return; + } if (xmb->pointer.type != MENU_POINTER_DISABLED) { @@ -4078,7 +4092,6 @@ static void xmb_draw_bg( if (dispctx && dispctx->blend_begin) dispctx->blend_begin(userdata); - video_driver_set_viewport(video_width, video_height, true, false); #ifdef HAVE_SHADERPIPELINE if (menu_shader_pipeline > XMB_SHADER_PIPELINE_WALLPAPER @@ -4699,6 +4712,31 @@ static void xmb_frame(void *data, video_frame_info_t *video_info) title_msg[0] = '\0'; title_truncated[0] = '\0'; + video_driver_set_viewport(video_width, video_height, true, false); + + /* If menu screensaver is active, blank the + * screen and skip drawing menu elements */ + if (xmb->show_screensaver) + { + float black[16] = { + 0, 0, 0, 1, + 0, 0, 0, 1, + 0, 0, 0, 1, + 0, 0, 0, 1, + }; + gfx_display_draw_quad( + p_disp, + userdata, + video_width, + video_height, + 0, 0, + video_width, video_height, + video_width, video_height, + black); + video_driver_set_viewport(video_width, video_height, false, true); + return; + } + pseudo_font_length = xmb->icon_spacing_horizontal * 4 - xmb->icon_size / 4.0f; left_thumbnail_margin_width = xmb->icon_size * 3.4f; right_thumbnail_margin_width = @@ -5327,7 +5365,7 @@ static void xmb_frame(void *data, video_frame_info_t *video_info) } /* Cursor image */ - if (xmb->mouse_show) + if (xmb->show_mouse) { bool cursor_visible = (video_fullscreen || mouse_grabbed) && menu_mouse_enable; diff --git a/menu/menu_defines.h b/menu/menu_defines.h index 6968cbce00..494f322f4a 100644 --- a/menu/menu_defines.h +++ b/menu/menu_defines.h @@ -40,6 +40,8 @@ enum menu_environ_cb MENU_ENVIRON_RESET_HORIZONTAL_LIST, MENU_ENVIRON_ENABLE_MOUSE_CURSOR, MENU_ENVIRON_DISABLE_MOUSE_CURSOR, + MENU_ENVIRON_ENABLE_SCREENSAVER, + MENU_ENVIRON_DISABLE_SCREENSAVER, MENU_ENVIRON_LAST }; diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 32d6890f85..44bae10f69 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -7309,6 +7309,7 @@ unsigned menu_displaylist_build_list( {MENU_ENUM_LABEL_MENU_SAVESTATE_RESUME, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_INSERT_DISK_RESUME, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_QUIT_ON_CLOSE_CONTENT, PARSE_ONLY_UINT, true}, + {MENU_ENUM_LABEL_MENU_SCREENSAVER_TIMEOUT, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_MOUSE_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_POINTER_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_THREADED_DATA_RUNLOOP_ENABLE, PARSE_ONLY_BOOL, true}, @@ -7330,6 +7331,10 @@ unsigned menu_displaylist_build_list( if (kiosk_mode_enable) build_list[i].checked = true; break; + case MENU_ENUM_LABEL_MENU_SCREENSAVER_TIMEOUT: + if (menu_driver_screensaver_supported()) + build_list[i].checked = true; + break; case MENU_ENUM_LABEL_UI_COMPANION_TOGGLE: if (desktop_menu_enable) build_list[i].checked = true; @@ -8820,6 +8825,8 @@ unsigned menu_displaylist_build_list( bool menu_materialui_icons_enable = settings->bools.menu_materialui_icons_enable; bool menu_materialui_show_nav_bar = settings->bools.menu_materialui_show_nav_bar; bool menu_use_preferred_system_color_theme = settings->bools.menu_use_preferred_system_color_theme; + unsigned menu_rgui_particle_effect = settings->uints.menu_rgui_particle_effect; + unsigned menu_screensaver_timeout = settings->uints.menu_screensaver_timeout; menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_MENU_SCALE_FACTOR, PARSE_ONLY_FLOAT, true}, @@ -8843,7 +8850,8 @@ unsigned menu_displaylist_build_list( {MENU_ENUM_LABEL_RGUI_MENU_THEME_PRESET, PARSE_ONLY_PATH, true}, {MENU_ENUM_LABEL_MENU_RGUI_SHADOWS, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT, PARSE_ONLY_UINT, true}, - {MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT_SPEED, PARSE_ONLY_FLOAT, true}, + {MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT_SPEED, PARSE_ONLY_FLOAT, false}, + {MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT_SCREENSAVER, PARSE_ONLY_BOOL, false}, {MENU_ENUM_LABEL_XMB_ALPHA_FACTOR, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_XMB_FONT, PARSE_ONLY_PATH, true}, {MENU_ENUM_LABEL_MENU_FONT_COLOR_RED, PARSE_ONLY_UINT, true}, @@ -8897,6 +8905,15 @@ unsigned menu_displaylist_build_list( if (menu_horizontal_animation) build_list[i].checked = true; break; + case MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT_SPEED: + if (menu_rgui_particle_effect != RGUI_PARTICLE_EFFECT_NONE) + build_list[i].checked = true; + break; + case MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT_SCREENSAVER: + if ((menu_screensaver_timeout != 0) && + (menu_rgui_particle_effect != RGUI_PARTICLE_EFFECT_NONE)) + build_list[i].checked = true; + break; case MENU_ENUM_LABEL_MATERIALUI_PLAYLIST_ICONS_ENABLE: if (menu_materialui_icons_enable) build_list[i].checked = true; diff --git a/menu/menu_driver.h b/menu/menu_driver.h index 245ac1a2ea..0fa5eb1243 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -469,6 +469,8 @@ bool menu_driver_list_get_entry(menu_ctx_list_t *list); bool menu_driver_list_get_size(menu_ctx_list_t *list); +bool menu_driver_screensaver_supported(void); + retro_time_t menu_driver_get_current_time(void); size_t menu_navigation_get_selection(void); diff --git a/menu/menu_setting.c b/menu/menu_setting.c index c154a675cd..21d707dfab 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -6461,6 +6461,21 @@ static void setting_get_string_representation_uint_quit_on_close_content( } } +static void setting_get_string_representation_uint_menu_screensaver_timeout( + rarch_setting_t *setting, + char *s, size_t len) +{ + if (!setting) + return; + + if (*setting->value.target.unsigned_integer == 0) + strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF), len); + else + snprintf(s, len, "%u %s", + *setting->value.target.unsigned_integer, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SECONDS)); +} + enum setting_type menu_setting_get_browser_selection_type(rarch_setting_t *setting) { if (!setting) @@ -14123,6 +14138,22 @@ static bool setting_append_list( &setting_get_string_representation_uint_quit_on_close_content; menu_settings_list_current_add_range(list, list_info, 0, QUIT_ON_CLOSE_CONTENT_LAST-1, 1, true, true); + CONFIG_UINT( + list, list_info, + &settings->uints.menu_screensaver_timeout, + MENU_ENUM_LABEL_MENU_SCREENSAVER_TIMEOUT, + MENU_ENUM_LABEL_VALUE_MENU_SCREENSAVER_TIMEOUT, + DEFAULT_MENU_SCREENSAVER_TIMEOUT, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint_special; + (*list)[list_info->index - 1].get_string_representation = + &setting_get_string_representation_uint_menu_screensaver_timeout; + menu_settings_list_current_add_range(list, list_info, 0, 1800, 10, true, true); + CONFIG_BOOL( list, list_info, &settings->bools.menu_mouse_enable, @@ -14353,7 +14384,9 @@ static bool setting_append_list( parent_group, general_write_handler, general_read_handler); - (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint; + (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint; + (*list)[list_info->index - 1].action_left = &setting_uint_action_left_with_refresh; + (*list)[list_info->index - 1].action_right = &setting_uint_action_right_with_refresh; (*list)[list_info->index - 1].get_string_representation = &setting_get_string_representation_uint_rgui_particle_effect; menu_settings_list_current_add_range(list, list_info, 0, RGUI_PARTICLE_EFFECT_LAST-1, 1, true, true); @@ -14374,6 +14407,21 @@ static bool setting_append_list( (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint; menu_settings_list_current_add_range(list, list_info, 0.1, 10.0, 0.1, true, true); + CONFIG_BOOL( + list, list_info, + &settings->bools.menu_rgui_particle_effect_screensaver, + MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT_SCREENSAVER, + MENU_ENUM_LABEL_VALUE_MENU_RGUI_PARTICLE_EFFECT_SCREENSAVER, + DEFAULT_RGUI_PARTICLE_EFFECT_SCREENSAVER, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE); + CONFIG_BOOL( list, list_info, &settings->bools.menu_rgui_extended_ascii, diff --git a/msg_hash.h b/msg_hash.h index 811c01e473..cc808d6e21 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -1100,6 +1100,7 @@ enum msg_hash_enums MENU_LABEL(MENU_WALLPAPER), MENU_LABEL(DYNAMIC_WALLPAPER), MENU_LABEL(PAUSE_NONACTIVE), + MENU_LABEL(MENU_SCREENSAVER_TIMEOUT), MENU_LABEL(MOUSE_ENABLE), MENU_LABEL(POINTER_ENABLE), MENU_LABEL(MENU_RGUI_BORDER_FILLER_ENABLE), @@ -1112,6 +1113,7 @@ enum msg_hash_enums MENU_LABEL(MENU_RGUI_SHADOWS), MENU_LABEL(MENU_RGUI_PARTICLE_EFFECT), MENU_LABEL(MENU_RGUI_PARTICLE_EFFECT_SPEED), + MENU_LABEL(MENU_RGUI_PARTICLE_EFFECT_SCREENSAVER), MENU_LABEL(MENU_RGUI_EXTENDED_ASCII), MENU_LABEL(MENU_RGUI_SWITCH_ICONS), MENU_LABEL(MENU_LINEAR_FILTER), diff --git a/retroarch.c b/retroarch.c index 27bc08293f..ed581f081c 100644 --- a/retroarch.c +++ b/retroarch.c @@ -1414,6 +1414,7 @@ static bool menu_input_key_bind_iterate( settings_t *settings = p_rarch->configuration_settings; struct menu_bind_state *_binds = &p_rarch->menu_input_binds; menu_input_t *menu_input = &p_rarch->menu_input_state; + struct menu_state *menu_st = &p_rarch->menu_driver_state; uint64_t input_bind_hold_us = settings->uints.input_bind_hold * 1000000; uint64_t input_bind_timeout_us = settings->uints.input_bind_timeout * 1000000; @@ -1563,6 +1564,10 @@ static bool menu_input_key_bind_iterate( menu_input->select_inhibit = true; menu_input->cancel_inhibit = true; + /* Menu screensaver should be inhibited on each + * frame that the bind operation is active */ + menu_st->input_last_time_us = menu_st->current_time_us; + return false; } @@ -4453,6 +4458,9 @@ static bool menu_driver_init_internal( settings_t *settings, bool video_is_threaded) { + struct menu_state *menu_st = &p_rarch->menu_driver_state; + menu_ctx_environment_t menu_environ; + if (p_rarch->menu_driver_ctx) { const char *ident = p_rarch->menu_driver_ctx->ident; @@ -4476,7 +4484,7 @@ static bool menu_driver_init_internal( } if (!p_rarch->menu_driver_data || !menu_init( - &p_rarch->menu_driver_state, + menu_st, &p_rarch->dialog_st, p_rarch->menu_driver_ctx, &p_rarch->menu_input_state, @@ -4496,7 +4504,14 @@ static bool menu_driver_init_internal( return false; } else - generic_menu_init_list(&p_rarch->menu_driver_state, settings); + generic_menu_init_list(menu_st, settings); + + /* Initialise menu screensaver */ + menu_environ.type = MENU_ENVIRON_DISABLE_SCREENSAVER; + menu_environ.data = NULL; + menu_st->input_last_time_us = cpu_features_get_time_usec(); + menu_st->screensaver_active = false; + menu_st->screensaver_supported = menu_driver_ctl(RARCH_MENU_CTL_ENVIRONMENT, &menu_environ); return true; } @@ -4642,6 +4657,13 @@ bool menu_driver_list_get_size(menu_ctx_list_t *list) return true; } +bool menu_driver_screensaver_supported(void) +{ + struct rarch_state *p_rarch = &rarch_st; + struct menu_state *menu_st = &p_rarch->menu_driver_state; + return menu_st->screensaver_supported; +} + retro_time_t menu_driver_get_current_time(void) { struct rarch_state *p_rarch = &rarch_st; @@ -23714,6 +23736,100 @@ static unsigned menu_event( ok_old = ok_current; + /* Get pointer (mouse + touchscreen) input + * Note: Must be done regardless of menu screensaver + * state */ + + /* > If pointer input is disabled, do nothing */ + if (!menu_mouse_enable && !menu_pointer_enable) + menu_input->pointer.type = MENU_POINTER_DISABLED; + else + { + menu_input_pointer_hw_state_t mouse_hw_state = {0}; + menu_input_pointer_hw_state_t touchscreen_hw_state = {0}; + + /* Read mouse */ + if (menu_mouse_enable) + menu_input_get_mouse_hw_state(p_rarch, &mouse_hw_state); + + /* Read touchscreen + * Note: Could forgo this if mouse is currently active, + * but this is 'cleaner' code... (if performance is a + * concern - and it isn't - user can just disable touch + * screen support) */ + if (menu_pointer_enable) + menu_input_get_touchscreen_hw_state( + p_rarch, &touchscreen_hw_state); + + /* Mouse takes precedence */ + if (mouse_hw_state.active) + menu_input->pointer.type = MENU_POINTER_MOUSE; + else if (touchscreen_hw_state.active) + menu_input->pointer.type = MENU_POINTER_TOUCHSCREEN; + + /* Copy input from the current device */ + if (menu_input->pointer.type == MENU_POINTER_MOUSE) + memcpy(pointer_hw_state, &mouse_hw_state, sizeof(menu_input_pointer_hw_state_t)); + else if (menu_input->pointer.type == MENU_POINTER_TOUCHSCREEN) + memcpy(pointer_hw_state, &touchscreen_hw_state, sizeof(menu_input_pointer_hw_state_t)); + + if (pointer_hw_state->active) + menu_st->input_last_time_us = menu_st->current_time_us; + } + + /* Populate menu_input_state + * Note: dx, dy, ptr, y_accel, etc. entries are set elsewhere */ + menu_input->pointer.x = pointer_hw_state->x; + menu_input->pointer.y = pointer_hw_state->y; + if (menu_input->select_inhibit || menu_input->cancel_inhibit) + { + menu_input->pointer.active = false; + menu_input->pointer.pressed = false; + } + else + { + menu_input->pointer.active = pointer_hw_state->active; + menu_input->pointer.pressed = pointer_hw_state->select_pressed; + } + + /* If menu screensaver is active, any input + * is intercepted and used to switch it off */ + if (menu_st->screensaver_active) + { + /* Check pointer input */ + bool input_active = (menu_input->pointer.type != MENU_POINTER_DISABLED) && + menu_input->pointer.active; + + /* Check regular input */ + if (!input_active) + input_active = bits_any_set(p_input->data, ARRAY_SIZE(p_input->data)); + + if (!input_active) + input_active = bits_any_set(p_trigger_input->data, ARRAY_SIZE(p_trigger_input->data)); + + /* Disable screensaver if required */ + if (input_active) + { + menu_ctx_environment_t menu_environ; + menu_environ.type = MENU_ENVIRON_DISABLE_SCREENSAVER; + menu_environ.data = NULL; + menu_st->screensaver_active = false; + menu_st->input_last_time_us = menu_st->current_time_us; + menu_driver_ctl(RARCH_MENU_CTL_ENVIRONMENT, &menu_environ); + } + + /* Annul received input */ + menu_input->pointer.active = false; + menu_input->pointer.pressed = false; + menu_input->select_inhibit = true; + menu_input->cancel_inhibit = true; + pointer_hw_state->up_pressed = false; + pointer_hw_state->down_pressed = false; + pointer_hw_state->left_pressed = false; + pointer_hw_state->right_pressed = false; + return MENU_ACTION_NOOP; + } + /* Accelerate only navigation buttons */ for (i = 0; i < 6; i++) navigation_current |= BIT256_GET_PTR(p_input, navigation_buttons[i]); @@ -23772,30 +23888,35 @@ static unsigned menu_event( if (BIT256_GET_PTR(p_trigger_input, RETRO_DEVICE_ID_JOYPAD_DOWN)) { + menu_st->input_last_time_us = menu_st->current_time_us; if (p_rarch->osk_ptr < 33) p_rarch->osk_ptr += OSK_CHARS_PER_LINE; } if (BIT256_GET_PTR(p_trigger_input, RETRO_DEVICE_ID_JOYPAD_UP)) { + menu_st->input_last_time_us = menu_st->current_time_us; if (p_rarch->osk_ptr >= OSK_CHARS_PER_LINE) p_rarch->osk_ptr -= OSK_CHARS_PER_LINE; } if (BIT256_GET_PTR(p_trigger_input, RETRO_DEVICE_ID_JOYPAD_RIGHT)) { + menu_st->input_last_time_us = menu_st->current_time_us; if (p_rarch->osk_ptr < 43) p_rarch->osk_ptr += 1; } if (BIT256_GET_PTR(p_trigger_input, RETRO_DEVICE_ID_JOYPAD_LEFT)) { + menu_st->input_last_time_us = menu_st->current_time_us; if (p_rarch->osk_ptr >= 1) p_rarch->osk_ptr -= 1; } if (BIT256_GET_PTR(p_trigger_input, RETRO_DEVICE_ID_JOYPAD_L)) { + menu_st->input_last_time_us = menu_st->current_time_us; if (p_rarch->osk_idx > OSK_TYPE_UNKNOWN + 1) p_rarch->osk_idx = ((enum osk_type) (p_rarch->osk_idx - 1)); @@ -23807,6 +23928,7 @@ static unsigned menu_event( if (BIT256_GET_PTR(p_trigger_input, RETRO_DEVICE_ID_JOYPAD_R)) { + menu_st->input_last_time_us = menu_st->current_time_us; if (p_rarch->osk_idx < (show_osk_symbols ? OSK_TYPE_LAST - 1 : OSK_SYMBOLS_PAGE1)) @@ -23865,59 +23987,9 @@ static unsigned menu_event( ret = MENU_ACTION_INFO; else if (BIT256_GET_PTR(p_trigger_input, RARCH_MENU_TOGGLE)) ret = MENU_ACTION_TOGGLE; - } - /* Get pointer (mouse + touchscreen) input */ - - /* > If pointer input is disabled, do nothing */ - if (!menu_mouse_enable && !menu_pointer_enable) - menu_input->pointer.type = MENU_POINTER_DISABLED; - else - { - menu_input_pointer_hw_state_t mouse_hw_state = {0}; - menu_input_pointer_hw_state_t touchscreen_hw_state = {0}; - - /* Read mouse */ - if (menu_mouse_enable) - menu_input_get_mouse_hw_state(p_rarch, &mouse_hw_state); - - /* Read touchscreen - * Note: Could forgo this if mouse is currently active, - * but this is 'cleaner' code... (if performance is a - * concern - and it isn't - user can just disable touch - * screen support) */ - if (menu_pointer_enable) - menu_input_get_touchscreen_hw_state( - p_rarch, &touchscreen_hw_state); - - /* Mouse takes precedence */ - if (mouse_hw_state.active) - menu_input->pointer.type = MENU_POINTER_MOUSE; - else if (touchscreen_hw_state.active) - menu_input->pointer.type = MENU_POINTER_TOUCHSCREEN; - - /* Copy input from the current device */ - if (menu_input->pointer.type == MENU_POINTER_MOUSE) - memcpy(pointer_hw_state, &mouse_hw_state, sizeof(menu_input_pointer_hw_state_t)); - else if (menu_input->pointer.type == MENU_POINTER_TOUCHSCREEN) - memcpy(pointer_hw_state, &touchscreen_hw_state, sizeof(menu_input_pointer_hw_state_t)); - } - - /* Populate menu_input_state - * Note: dx, dy, ptr, y_accel, etc. entries are set elsewhere */ - if (menu_input->select_inhibit || menu_input->cancel_inhibit) - { - menu_input->pointer.active = false; - menu_input->pointer.pressed = false; - menu_input->pointer.x = 0; - menu_input->pointer.y = 0; - } - else - { - menu_input->pointer.active = pointer_hw_state->active; - menu_input->pointer.pressed = pointer_hw_state->select_pressed; - menu_input->pointer.x = pointer_hw_state->x; - menu_input->pointer.y = pointer_hw_state->y; + if (ret != MENU_ACTION_NOOP) + menu_st->input_last_time_us = menu_st->current_time_us; } return ret; @@ -25661,8 +25733,59 @@ void input_keyboard_event(bool down, unsigned code, static bool deferred_wait_keys; struct rarch_state *p_rarch = &rarch_st; -#ifdef HAVE_ACCESSIBILITY #ifdef HAVE_MENU + struct menu_state *menu_st = &p_rarch->menu_driver_state; + + /* If screensaver is active, then it should be + * disabled if: + * - Key is down AND + * - OSK is active, OR: + * - Key is *not* mapped to RetroPad input (these + * inputs are handled in menu_event() - if we + * allow mapped RetroPad keys to toggle off + * the screensaver, then we end up with a 'duplicate' + * input that will trigger unwanted menu action) + * - For extra amusement, a number of keyboard keys + * are hard-coded to RetroPad inputs (while the menu + * is running) in such a way that they cannot be + * detected via the regular 'keyboard_mapping_bits' + * record. We therefore have to check each of these + * explicitly... + * Otherwise, input is ignored whenever screensaver + * is active */ + if (menu_st->screensaver_active) + { + if (down && + (code != RETROK_UNKNOWN) && + (menu_input_dialog_get_display_kb() || + !((code == RETROK_SPACE) || /* RETRO_DEVICE_ID_JOYPAD_START */ + (code == RETROK_SLASH) || /* RETRO_DEVICE_ID_JOYPAD_X */ + (code == RETROK_RSHIFT) || /* RETRO_DEVICE_ID_JOYPAD_SELECT */ + (code == RETROK_RIGHT) || /* RETRO_DEVICE_ID_JOYPAD_RIGHT */ + (code == RETROK_LEFT) || /* RETRO_DEVICE_ID_JOYPAD_LEFT */ + (code == RETROK_DOWN) || /* RETRO_DEVICE_ID_JOYPAD_DOWN */ + (code == RETROK_UP) || /* RETRO_DEVICE_ID_JOYPAD_UP */ + (code == RETROK_PAGEUP) || /* RETRO_DEVICE_ID_JOYPAD_L */ + (code == RETROK_PAGEDOWN) || /* RETRO_DEVICE_ID_JOYPAD_R */ + (code == RETROK_BACKSPACE) || /* RETRO_DEVICE_ID_JOYPAD_B */ + (code == RETROK_RETURN) || /* RETRO_DEVICE_ID_JOYPAD_A */ + (code == RETROK_DELETE) || /* RETRO_DEVICE_ID_JOYPAD_Y */ + BIT512_GET(p_rarch->keyboard_mapping_bits, code)))) + { + menu_ctx_environment_t menu_environ; + menu_environ.type = MENU_ENVIRON_DISABLE_SCREENSAVER; + menu_environ.data = NULL; + menu_st->screensaver_active = false; + menu_st->input_last_time_us = menu_st->current_time_us; + menu_driver_ctl(RARCH_MENU_CTL_ENVIRONMENT, &menu_environ); + } + return; + } + + if (down) + menu_st->input_last_time_us = menu_st->current_time_us; + +#ifdef HAVE_ACCESSIBILITY if (menu_input_dialog_get_display_kb() && down && is_accessibility_enabled(p_rarch)) { @@ -31586,17 +31709,20 @@ static void video_driver_frame(const void *data, unsigned width, if (p_rarch->current_video && p_rarch->current_video->frame) p_rarch->video_driver_active = p_rarch->current_video->frame( p_rarch->video_driver_data, data, width, height, - p_rarch->video_driver_frame_count, - (unsigned)pitch, video_driver_msg, &video_info); + p_rarch->video_driver_frame_count, (unsigned)pitch, + video_info.menu_screensaver_active ? "" : video_driver_msg, + &video_info); p_rarch->video_driver_frame_count++; /* Display the status text, with a higher priority. */ - if ( video_info.fps_show - || video_info.framecount_show - || video_info.memory_show - || video_info.core_status_msg_show + if ( ( video_info.fps_show + || video_info.framecount_show + || video_info.memory_show + || video_info.core_status_msg_show ) + && !video_info.menu_screensaver_active + ) { #if defined(HAVE_GFX_WIDGETS) if (widgets_active) @@ -31809,6 +31935,7 @@ void video_driver_build_info(video_frame_info_t *video_info) #ifdef HAVE_MENU video_info->menu_is_alive = p_rarch->menu_driver_alive; + video_info->menu_screensaver_active = p_rarch->menu_driver_state.screensaver_active; video_info->menu_footer_opacity = settings->floats.menu_footer_opacity; video_info->menu_header_opacity = settings->floats.menu_header_opacity; video_info->materialui_color_theme = settings->uints.menu_materialui_color_theme; @@ -31830,6 +31957,7 @@ void video_driver_build_info(video_frame_info_t *video_info) video_info->libretro_running = p_rarch->current_core.game_loaded; #else video_info->menu_is_alive = false; + video_info->menu_screensaver_active = false; video_info->menu_footer_opacity = 0.0f; video_info->menu_header_opacity = 0.0f; video_info->materialui_color_theme = 0; @@ -35436,6 +35564,7 @@ void retroarch_menu_running(void) #ifdef HAVE_MENU menu_handle_t *menu = p_rarch->menu_driver_data; + struct menu_state *menu_st = &p_rarch->menu_driver_state; if (menu) menu_driver_toggle(p_rarch, menu, settings, &p_rarch->runloop_key_event, @@ -35459,6 +35588,18 @@ void retroarch_menu_running(void) enum input_game_focus_cmd_type game_focus_cmd = GAME_FOCUS_CMD_OFF; command_event(CMD_EVENT_GAME_FOCUS_TOGGLE, &game_focus_cmd); } + + /* Ensure that menu screensaver is disabled when + * first switching to the menu */ + if (menu_st->screensaver_active) + { + menu_ctx_environment_t menu_environ; + menu_environ.type = MENU_ENVIRON_DISABLE_SCREENSAVER; + menu_environ.data = NULL; + menu_st->screensaver_active = false; + menu_driver_ctl(RARCH_MENU_CTL_ENVIRONMENT, &menu_environ); + } + menu_st->input_last_time_us = cpu_features_get_time_usec(); #endif #ifdef HAVE_OVERLAY @@ -35475,6 +35616,7 @@ void retroarch_menu_running_finished(bool quit) #endif #ifdef HAVE_MENU menu_handle_t *menu = p_rarch->menu_driver_data; + struct menu_state *menu_st = &p_rarch->menu_driver_state; if (menu) menu_driver_toggle(p_rarch, menu, settings, &p_rarch->runloop_key_event, @@ -35510,6 +35652,17 @@ void retroarch_menu_running_finished(bool quit) command_event(CMD_EVENT_GAME_FOCUS_TOGGLE, &game_focus_cmd); } } + + /* Ensure that menu screensaver is disabled when + * switching off the menu */ + if (menu_st->screensaver_active) + { + menu_ctx_environment_t menu_environ; + menu_environ.type = MENU_ENVIRON_DISABLE_SCREENSAVER; + menu_environ.data = NULL; + menu_st->screensaver_active = false; + menu_driver_ctl(RARCH_MENU_CTL_ENVIRONMENT, &menu_environ); + } #endif video_driver_set_texture_enable(false, false); #ifdef HAVE_OVERLAY @@ -37287,6 +37440,10 @@ static enum runloop_state runloop_check_state( bool focused = false; input_bits_t trigger_input = current_bits; global_t *global = &p_rarch->g_extern; + unsigned screensaver_timeout = settings->uints.menu_screensaver_timeout; + + /* Get current time */ + menu_st->current_time_us = current_time; cbs->poll_cb(); @@ -37340,8 +37497,19 @@ static enum runloop_state runloop_check_state( } } - /* Get current time */ - menu_st->current_time_us = current_time; + /* Check whether menu screensaver should be enabled */ + if ((screensaver_timeout > 0) && + menu_st->screensaver_supported && + !menu_st->screensaver_active && + ((menu_st->current_time_us - menu_st->input_last_time_us) > + ((retro_time_t)screensaver_timeout * 1000000))) + { + menu_ctx_environment_t menu_environ; + menu_environ.type = MENU_ENVIRON_ENABLE_SCREENSAVER; + menu_environ.data = NULL; + menu_st->screensaver_active = true; + menu_driver_ctl(RARCH_MENU_CTL_ENVIRONMENT, &menu_environ); + } /* Iterate the menu driver for one frame. */ diff --git a/retroarch.h b/retroarch.h index e63f980fe7..c338eb5938 100644 --- a/retroarch.h +++ b/retroarch.h @@ -1200,6 +1200,7 @@ typedef struct video_frame_info bool runloop_is_slowmotion; bool runloop_is_paused; bool menu_is_alive; + bool menu_screensaver_active; bool msg_bgcolor_enable; } video_frame_info_t; diff --git a/retroarch_data.h b/retroarch_data.h index 73b45ca730..400fa1e704 100644 --- a/retroarch_data.h +++ b/retroarch_data.h @@ -1594,6 +1594,7 @@ struct menu_state retro_time_t current_time_us; retro_time_t powerstate_last_time_us; retro_time_t datetime_last_time_us; + retro_time_t input_last_time_us; struct { @@ -1632,6 +1633,11 @@ struct menu_state bool entries_nonblocking_refresh; /* 'Close Content'-hotkey menu resetting */ bool pending_close_content; + /* Screensaver status + * - Does menu driver support screensaver functionality? + * - Is screensaver currently active? */ + bool screensaver_supported; + bool screensaver_active; }; struct menu_bind_state_port From 72f08bb1b4f4c09bd297e7e1bf2f7beaaea34904 Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Fri, 2 Apr 2021 10:16:47 +0100 Subject: [PATCH 2/2] (RGUI) Fix LGTM warning - 'Multiplication result converted to larger type' --- menu/drivers/rgui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index 3eaed31537..2646210c44 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -2266,7 +2266,7 @@ static void rgui_render_background(rgui_t *rgui, /* Otherwise copy background to framebuffer */ else if (background_buf->data) memcpy(frame_buf->data, background_buf->data, - frame_buf->width * frame_buf->height * sizeof(uint16_t)); + (size_t)frame_buf->width * (size_t)frame_buf->height * sizeof(uint16_t)); } static void rgui_render_fs_thumbnail(rgui_t *rgui,