diff --git a/UI/DisplayLayoutScreen.cpp b/UI/DisplayLayoutScreen.cpp index f6a4717f57..c4ba612fb4 100644 --- a/UI/DisplayLayoutScreen.cpp +++ b/UI/DisplayLayoutScreen.cpp @@ -147,11 +147,7 @@ void DisplayLayoutScreen::dialogFinished(const Screen *dialog, DialogResult resu RecreateViews(); } -UI::EventReturn DisplayLayoutScreen::OnPostProcShaderChange(UI::EventParams &e) { - // Remove the virtual "Off" entry. TODO: Get rid of it generally. - g_Config.vPostShaderNames.erase(std::remove(g_Config.vPostShaderNames.begin(), g_Config.vPostShaderNames.end(), "Off"), g_Config.vPostShaderNames.end()); - FixPostShaderOrder(&g_Config.vPostShaderNames); - +static void NotifyPostChanges() { System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); // To deal with shaders that can change render resolution like upscaling. System_PostUIMessage(UIMessage::POSTSHADER_UPDATED); @@ -159,6 +155,13 @@ UI::EventReturn DisplayLayoutScreen::OnPostProcShaderChange(UI::EventParams &e) if (gpu) { gpu->NotifyConfigChanged(); } +} + +UI::EventReturn DisplayLayoutScreen::OnPostProcShaderChange(UI::EventParams &e) { + // Remove the virtual "Off" entry. TODO: Get rid of it generally. + g_Config.vPostShaderNames.erase(std::remove(g_Config.vPostShaderNames.begin(), g_Config.vPostShaderNames.end(), "Off"), g_Config.vPostShaderNames.end()); + FixPostShaderOrder(&g_Config.vPostShaderNames); + NotifyPostChanges(); return UI::EVENT_DONE; } @@ -378,14 +381,23 @@ void DisplayLayoutScreen::CreateViews() { auto removeButton = shaderRow->Add(new Choice(ImageID("I_TRASHCAN"), new LinearLayoutParams(0.0f))); removeButton->OnClick.Add([=](EventParams &e) -> UI::EventReturn { - g_Config.vPostShaderNames.erase(g_Config.vPostShaderNames.begin() + i); - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); - RecreateViews(); + // Protect against possible race conditions. + if (i < g_Config.vPostShaderNames.size()) { + g_Config.vPostShaderNames.erase(g_Config.vPostShaderNames.begin() + i); + FixPostShaderOrder(&g_Config.vPostShaderNames); + NotifyPostChanges(); + RecreateViews(); + } return UI::EVENT_DONE; }); auto moreButton = shaderRow->Add(new Choice(ImageID("I_THREE_DOTS"), new LinearLayoutParams(0.0f))); moreButton->OnClick.Add([=](EventParams &e) -> UI::EventReturn { + if (i >= g_Config.vPostShaderNames.size()) { + // Protect against possible race conditions. + return UI::EVENT_DONE; + } + PopupContextMenuScreen *contextMenu = new UI::PopupContextMenuScreen(postShaderContextMenu, ARRAY_SIZE(postShaderContextMenu), I18NCat::DIALOG, moreButton); screenManager()->push(contextMenu); const ShaderInfo *info = GetPostShaderInfo(g_Config.vPostShaderNames[i]); @@ -407,7 +419,7 @@ void DisplayLayoutScreen::CreateViews() { return UI::EVENT_DONE; } FixPostShaderOrder(&g_Config.vPostShaderNames); - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NotifyPostChanges(); RecreateViews(); return UI::EVENT_DONE; }); diff --git a/UI/DisplayLayoutScreen.h b/UI/DisplayLayoutScreen.h index d256b94f6d..9f89462bba 100644 --- a/UI/DisplayLayoutScreen.h +++ b/UI/DisplayLayoutScreen.h @@ -50,7 +50,7 @@ private: UI::ChoiceStrip *mode_ = nullptr; UI::Choice *postProcChoice_ = nullptr; std::string shaderNames_[256]; - std::deque settingsVisible_; // vector is an insane bitpacked specialization! + std::deque settingsVisible_; // vector is an insane bitpacked specialization! Not to be used with checkboxes! }; class PostProcScreen : public UI::ListPopupScreen {