Skip to content

Commit

Permalink
Add a setting to set the menubar mode.
Browse files Browse the repository at this point in the history
  • Loading branch information
Arignir committed Oct 12, 2024
1 parent bdfd0c1 commit 7245568
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 35 deletions.
26 changes: 22 additions & 4 deletions include/app/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@

struct ImGuiIO;

enum menubar_mode {
MENUBAR_MODE_FIXED_ABOVE_GAME = 0,
MENUBAR_MODE_HOVER_OVER_GAME = 1,

MENUBAR_MODE_LEN,
MENUBAR_MODE_MIN = 0,
MENUBAR_MODE_MAX = 1,
};

enum display_mode {
DISPLAY_MODE_WINDOWED = 0,
DISPLAY_MODE_BORDERLESS = 1,
Expand Down Expand Up @@ -258,6 +267,9 @@ struct settings {
} audio;

struct {
// Menubar mode (fixed above game or hover over game)
enum menubar_mode menubar_mode;

// Start the last played game on startup, when no game is provided
bool start_last_played_game_on_startup;

Expand Down Expand Up @@ -399,11 +411,17 @@ struct app {
// Temporary value used to measure the time since the last mouse movement (in ms)
float time_elapsed_since_last_mouse_motion_ms;

// Width of the FPS counter within the menubar.
float menubar_fps_width;
struct {
// 1.0 if the menubar is visible, 0.0 if not, and something in between if the
// menubar is fading away
float visibility;

// Width of the FPS counter within the menubar.
float fps_width;

// Size of the menu bar
ImVec2 menubar_size;
// Size of the menu bar
ImVec2 size;
} menubar;

struct {
// The game area is made of two sub areas: the inner game area and the outer game area.
Expand Down
8 changes: 8 additions & 0 deletions source/app/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,12 @@ app_config_load(
// Misc
{
int b;
double d;

if (mjson_get_number(data, data_len, "$.misc.menubar_mode", &d)) {
app->settings.misc.menubar_mode = (int)d;
app->settings.misc.menubar_mode = max(MENUBAR_MODE_MIN, min(app->settings.misc.menubar_mode, MENUBAR_MODE_MAX));
}

if (mjson_get_bool(data, data_len, "$.misc.start_last_played_game_on_startup", &b)) {
app->settings.misc.start_last_played_game_on_startup = b;
Expand Down Expand Up @@ -340,6 +346,7 @@ app_config_save(

// Misc
"misc": {
"menubar_mode": %d,
"start_last_played_game_on_startup": %B,
"pause_when_window_inactive": %B,
"pause_when_game_resets": %B,
Expand Down Expand Up @@ -375,6 +382,7 @@ app_config_save(
(int)app->settings.video.pixel_scaling_filter,
(int)app->settings.audio.mute,
app->settings.audio.level,
(int)app->settings.misc.menubar_mode,
(int)app->settings.misc.start_last_played_game_on_startup,
(int)app->settings.misc.pause_when_window_inactive,
(int)app->settings.misc.pause_when_game_resets,
Expand Down
45 changes: 37 additions & 8 deletions source/app/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ app_settings_default(
settings->video.pixel_scaling_filter = PIXEL_SCALING_FILTER_LCD_GRID;
settings->audio.mute = false;
settings->audio.level = 1.0f;
settings->misc.menubar_mode = MENUBAR_MODE_FIXED_ABOVE_GAME;
settings->misc.start_last_played_game_on_startup = false;
settings->misc.pause_when_window_inactive = false;
settings->misc.pause_when_game_resets = false;
settings->misc.hide_cursor_when_mouse_inactive = true;
}

Expand All @@ -99,6 +103,7 @@ main(
app.emulation.is_running = false;
app.audio.resample_frequency = 48000;
app.ui.display.request_resize = true;
app.ui.menubar.visibility = 1.0;
app_settings_default(&app.settings);
app_bindings_setup_default(&app);

Expand Down Expand Up @@ -245,21 +250,45 @@ main(
}
}

// Hide the cursor if the game is running and the mouse is inactive for a while
if (app.settings.misc.hide_cursor_when_mouse_inactive && app.emulation.is_started && app.emulation.is_running) {
int show_cursor;
// Handle all the stuff that must disappear after a few seconds if the UI isn't active
if (app.emulation.is_started && app.emulation.is_running && !igGetHoveredID() && !igGetFocusID() && !app.ui.settings.open) {

show_cursor = SDL_DISABLE;
if (app.ui.time_elapsed_since_last_mouse_motion_ms <= 2000.0) { // 2s
if (app.ui.time_elapsed_since_last_mouse_motion_ms <= 2000.0) {
app.ui.time_elapsed_since_last_mouse_motion_ms += elapsed_ms;
show_cursor = SDL_ENABLE;
}

if (SDL_ShowCursor(SDL_QUERY) != show_cursor) {
SDL_ShowCursor(show_cursor);
// Hide the cursor if the mouse is inactive for a while
if (app.settings.misc.hide_cursor_when_mouse_inactive) {
bool show_cursor;
bool is_cursor_visible;

is_cursor_visible = igGetMouseCursor() != ImGuiMouseCursor_None;
show_cursor = (app.ui.time_elapsed_since_last_mouse_motion_ms < 2000.0);

if (show_cursor != is_cursor_visible) {
igSetMouseCursor(show_cursor ? ImGuiMouseCursor_Arrow : ImGuiMouseCursor_None);
}
}

// Hide the menubar if it's hovering over the game, isn't focused and the mouse is inactive for a while
// We set `visibility` to go from 1.0 to 0.0 over 50ms, after the mouse is inactive after 1950ms.
if (app.settings.misc.menubar_mode == MENUBAR_MODE_HOVER_OVER_GAME) {
if (app.ui.time_elapsed_since_last_mouse_motion_ms < 1950.0) {
app.ui.menubar.visibility = 1.0f;
} else if (app.ui.time_elapsed_since_last_mouse_motion_ms >= 1950.0 && app.ui.time_elapsed_since_last_mouse_motion_ms <= 2000.0) {
app.ui.menubar.visibility = (2000.0 - app.ui.time_elapsed_since_last_mouse_motion_ms) / 50.0;
} else {
app.ui.menubar.visibility = 0.0f;
}
}
} else {
app.ui.time_elapsed_since_last_mouse_motion_ms = 0;

if (igGetMouseCursor() == ImGuiMouseCursor_None) {
igSetMouseCursor(ImGuiMouseCursor_Arrow);
}

app.ui.menubar.visibility = 1.0f;
}

// Flush the quick save cache
Expand Down
9 changes: 6 additions & 3 deletions source/app/sdl/video.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ app_sdl_video_init(
// unknown at this stage.
//
// The size given here is merely a guess as to what the real size will be, hence the magical +19.f for the window's height.
app->ui.menubar_size.y = 19.f;
app->ui.menubar.size.y = app->settings.misc.menubar_mode == MENUBAR_MODE_FIXED_ABOVE_GAME ? 19.f * app->ui.scale : 0.f;
app->ui.display.win.width = GBA_SCREEN_WIDTH * app->settings.video.display_size * app->ui.scale;
app->ui.display.win.height = (GBA_SCREEN_HEIGHT * app->settings.video.display_size + app->ui.menubar_size.y) * app->ui.scale;
app->ui.display.win.height = (GBA_SCREEN_HEIGHT * app->settings.video.display_size * app->ui.scale) + app->ui.menubar.size.y;
app_win_game_refresh_game_area(app);

win_flags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
Expand Down Expand Up @@ -206,7 +206,10 @@ app_sdl_video_resize_window(
uint32_t h;

w = GBA_SCREEN_WIDTH * app->settings.video.display_size * app->ui.scale;
h = GBA_SCREEN_HEIGHT * app->settings.video.display_size * app->ui.scale + app->ui.menubar_size.y;
h = GBA_SCREEN_HEIGHT * app->settings.video.display_size * app->ui.scale;

// If relevant, expand the window by the size of the menubar
h += app->settings.misc.menubar_mode == MENUBAR_MODE_FIXED_ABOVE_GAME ? app->ui.menubar.size.y : 0;

SDL_SetWindowSize(app->sdl.window, w, h);
}
Expand Down
9 changes: 8 additions & 1 deletion source/app/windows/game.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,15 @@ void
app_win_game_refresh_game_area(
struct app *app
) {

app->ui.display.game.outer.x = 0;
app->ui.display.game.outer.y = app->ui.menubar_size.y;
app->ui.display.game.outer.y = 0;

// Ensure the outer window is below the menubar
if (app->settings.misc.menubar_mode == MENUBAR_MODE_FIXED_ABOVE_GAME) {
app->ui.display.game.outer.y += app->ui.menubar.size.y * app->ui.menubar.visibility;
}

app->ui.display.game.outer.width = app->ui.display.win.width - app->ui.display.game.outer.x;
app->ui.display.game.outer.height = app->ui.display.win.height - app->ui.display.game.outer.y;

Expand Down
34 changes: 23 additions & 11 deletions source/app/windows/menubar.c
Original file line number Diff line number Diff line change
Expand Up @@ -495,40 +495,52 @@ app_win_menubar_fps_counter(

spacing = igGetStyle()->ItemSpacing.x;

igSameLine(igGetWindowWidth() - (app->ui.menubar_fps_width + spacing * 2), 1);
igSameLine(igGetWindowWidth() - (app->ui.menubar.fps_width + spacing * 2), 1);
igText("FPS: %.1f (%.1f%%)", app->emulation.fps, app->emulation.fps / 60.0 * 100.0);
igGetItemRectSize(&out);
app->ui.menubar_fps_width = out.x;
app->ui.menubar.fps_width = out.x;
}
}

void
app_win_menubar(
struct app *app
) {
if (igBeginMainMenuBar()) {
float vp_y;

if (app->ui.menubar.visibility <= 0.0f) {
return ;
}

/* File */
// Hacking ImGui a bit to nicely fade the menubar away
vp_y = igGetMainViewport()->Pos.y;
igGetMainViewport()->Pos.y -= (1.0f - app->ui.menubar.visibility) * app->ui.menubar.size.y;

if (igBeginMainMenuBar()) {
// File
app_win_menubar_file(app);

/* Emulation */
// Emulation
app_win_menubar_emulation(app);

/* Video */
// Video
app_win_menubar_video(app);

/* Audio */
// Audio
app_win_menubar_audio(app);

/* Help */
// Help
app_win_menubar_help(app);

/* FPS */
// FPS
app_win_menubar_fps_counter(app);

/* Capture the height of the menu bar */
igGetWindowSize(&app->ui.menubar_size);
// Capture the height of the menu bar
igGetWindowSize(&app->ui.menubar.size);

igEndMainMenuBar();
}

// Restore the viewport's position
igGetMainViewport()->Pos.y = vp_y;
}
28 changes: 20 additions & 8 deletions source/app/windows/settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ static char const *display_mode_names[DISPLAY_MODE_LEN] = {
[DISPLAY_MODE_FULLSCREEN] = "Fullscreen",
};

static char const *menubar_mode_names[MENUBAR_MODE_LEN] = {
[MENUBAR_MODE_FIXED_ABOVE_GAME] = "Fixed above game",
[MENUBAR_MODE_HOVER_OVER_GAME] = "Hover over game",
};

static char const * const display_size_names[] = {
"x1",
"x2",
Expand All @@ -73,8 +78,8 @@ char const * const binds_pretty_name[] = {
[BIND_EMULATOR_PAUSE] = "Pause",
[BIND_EMULATOR_STOP] = "Stop",
[BIND_EMULATOR_RESET] = "Reset",
[BIND_EMULATOR_SHOW_FPS] = "Show FPS",
[BIND_EMULATOR_SETTINGS] = "Settings",
[BIND_EMULATOR_SHOW_FPS] = "Toggle FPS",
[BIND_EMULATOR_SETTINGS] = "Toggle Settings",
[BIND_EMULATOR_ALT_SPEED_TOGGLE] = "Alt. Speed (Toggle)",
[BIND_EMULATOR_ALT_SPEED_HOLD] = "Alt. Speed (Hold)",
[BIND_EMULATOR_QUICKSAVE_1] = "Quicksave 1",
Expand Down Expand Up @@ -116,8 +121,8 @@ char const * const binds_slug[] = {
[BIND_EMULATOR_PAUSE] = "pause",
[BIND_EMULATOR_STOP] = "stop",
[BIND_EMULATOR_RESET] = "reset",
[BIND_EMULATOR_SHOW_FPS] = "show_fps",
[BIND_EMULATOR_SETTINGS] = "settings",
[BIND_EMULATOR_SHOW_FPS] = "toggle_show_fps",
[BIND_EMULATOR_SETTINGS] = "toggle_settings",
[BIND_EMULATOR_ALT_SPEED_TOGGLE] = "alternative_speed_toggle",
[BIND_EMULATOR_ALT_SPEED_HOLD] = "alternative_speed_hold",
[BIND_EMULATOR_QUICKSAVE_1] = "quicksave_1",
Expand Down Expand Up @@ -642,6 +647,16 @@ app_win_settings_misc(
igTableSetupColumn("##MiscSettingsInterfaceLabel", ImGuiTableColumnFlags_WidthFixed, vp->WorkSize.x / 5.f, 0);
igTableSetupColumn("##MiscSettingsInterfaceValue", ImGuiTableColumnFlags_WidthStretch, 0.f, 0);

// Menubar Mode
igTableNextRow(ImGuiTableRowFlags_None, 0.f);
igTableNextColumn();
igTextWrapped("Menubar Mode");

igTableNextColumn();
if (igCombo_Str_arr("##Menubar Mode", (int *)&app->settings.misc.menubar_mode, menubar_mode_names, array_length(menubar_mode_names), 0)) {
app->ui.display.request_resize = true;
}

// Start the last played game on startup, when no game is provided
igTableNextRow(ImGuiTableRowFlags_None, 0.f);
igTableNextColumn();
Expand Down Expand Up @@ -674,10 +689,7 @@ app_win_settings_misc(
igTextWrapped("Hide cursor when the mouse is inactive");

igTableNextColumn();
if (igCheckbox("##HideCursorWhenMouseInactive", &app->settings.misc.hide_cursor_when_mouse_inactive)) {
app->ui.time_elapsed_since_last_mouse_motion_ms = 0;
SDL_ShowCursor(SDL_ENABLE);
}
igCheckbox("##HideCursorWhenMouseInactive", &app->settings.misc.hide_cursor_when_mouse_inactive);

igEndTable();
}
Expand Down

0 comments on commit 7245568

Please sign in to comment.