overlay: refactor overlay layering (#739)

## Link to GitHub Issue or related Pull Request, if one exists
n/a

## Description of change

Create three distinct layers for the overlay:

1. Bottommost persistent layer - non-interactable layer that is always
on. This was only for notifications, but now the FPS widget lives here
as well.
2. Overlay windows layer - most interactable windows go here.
3. Topmost main menu - this is reserved for the main menu (escape key)
and this is a modal dialog that occludes the layers below.

Why? 

- `toggle overlay` behavior with FPS widget *also* toggling on/off was a
bit confusing (now they're two separate keys)
- FPS widget is popular, but it caused the entire overlay to be active,
which affects how input is handled
- the main menu being a standalone window was a little awkward (now it's
a modal)

## Testing
This commit is contained in:
bicarus
2026-06-07 17:23:08 -07:00
committed by GitHub
parent bb87aa2944
commit 100caa0f5c
16 changed files with 348 additions and 102 deletions
+14 -1
View File
@@ -1182,7 +1182,20 @@ int main_implementation(int argc, char *argv[]) {
overlay::AUTO_SHOW_FPS = true;
}
if (options[launcher::Options::spice2x_FpsOpposite].value_bool()) {
overlay::FPS_SHOULD_FLIP = true;
// deprecated flag: equivalent to anchoring the FPS window top-left
overlay::FPS_LOCATION = overlay::FpsLocation::TopLeft;
}
if (options[launcher::Options::FpsLocation].is_active()) {
const auto txt = options[launcher::Options::FpsLocation].value_text();
if (txt == "topright") {
overlay::FPS_LOCATION = overlay::FpsLocation::TopRight;
} else if (txt == "topleft") {
overlay::FPS_LOCATION = overlay::FpsLocation::TopLeft;
} else if (txt == "bottomleft") {
overlay::FPS_LOCATION = overlay::FpsLocation::BottomLeft;
} else if (txt == "bottomright") {
overlay::FPS_LOCATION = overlay::FpsLocation::BottomRight;
}
}
if (options[launcher::Options::spice2x_SubScreenAutoShow].value_bool()) {
overlay::AUTO_SHOW_SUBSCREEN = true;
+18 -2
View File
@@ -496,12 +496,28 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
},
{
// spice2x_FpsOpposite
.title = "Show FPS/Clock top-left",
.title = "Show FPS/Clock top-left (DEPRECATED - use -fpslocation instead)",
.name = "fpsflip",
.desc = "Show FPS / clock / timer overlay on the top left of the screen instead of the top right.",
.desc = "Show FPS / clock / timer overlay on the top left of the screen instead of the top right. "
"Deprecated - use -fpslocation instead.",
.type = OptionType::Bool,
.hidden = true,
.category = "Overlay",
},
{
// FpsLocation
.title = "FPS/Clock Location",
.name = "fpslocation",
.desc = "Select which corner of the screen the FPS / clock / timer overlay appears in.",
.type = OptionType::Enum,
.category = "Overlay",
.elements = {
{"topright", ""},
{"topleft", ""},
{"bottomleft", ""},
{"bottomright", ""},
},
},
{
// spice2x_SubScreenAutoShow
.title = "Auto Show Subscreen",
+1
View File
@@ -56,6 +56,7 @@ namespace launcher {
NotificationPosition,
spice2x_FpsAutoShow,
spice2x_FpsOpposite,
FpsLocation,
spice2x_SubScreenAutoShow,
spice2x_IOPanelAutoShow,
spice2x_KeypadAutoShow,