From 6a5bc9f9927301598d03c1d2d3efc63ee3c17632 Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 20 Aug 2024 23:12:02 +0200 Subject: [PATCH 1/3] Save and rename input bindings file To reduce the chance of corrupting the file. --- apps/openmw/mwinput/bindingsmanager.cpp | 17 ++++++++++++++--- extern/oics/ICSInputControlSystem.cpp | 9 ++------- extern/oics/ICSInputControlSystem.h | 2 +- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwinput/bindingsmanager.cpp b/apps/openmw/mwinput/bindingsmanager.cpp index a6bab19673..bad6744c0f 100644 --- a/apps/openmw/mwinput/bindingsmanager.cpp +++ b/apps/openmw/mwinput/bindingsmanager.cpp @@ -1,5 +1,7 @@ #include "bindingsmanager.hpp" +#include + #include #include @@ -209,13 +211,22 @@ namespace MWInput BindingsManager::~BindingsManager() { + const std::string newFileName = Files::pathToUnicodeString(mUserFile) + ".new"; try { - mInputBinder->save(Files::pathToUnicodeString(mUserFile)); + if (mInputBinder->save(newFileName)) + { + std::filesystem::rename(Files::pathFromUnicodeString(newFileName), mUserFile); + Log(Debug::Info) << "Saved input bindings: " << mUserFile; + } + else + { + Log(Debug::Error) << "Failed to save input bindings to " << newFileName; + } } - catch (std::exception& e) + catch (const std::exception& e) { - Log(Debug::Error) << "Failed to save input bindings: " << e.what(); + Log(Debug::Error) << "Failed to save input bindings to " << newFileName << ": " << e.what(); } } diff --git a/extern/oics/ICSInputControlSystem.cpp b/extern/oics/ICSInputControlSystem.cpp index 7d92d9ee07..e64fef0fc6 100644 --- a/extern/oics/ICSInputControlSystem.cpp +++ b/extern/oics/ICSInputControlSystem.cpp @@ -357,14 +357,9 @@ namespace ICS return file.substr(0, file.find_last_of(".")); } - bool InputControlSystem::save(std::string fileName) + bool InputControlSystem::save(const std::string& fileName) { - if(fileName != "") - { - mFileName = fileName; - } - - TiXmlDocument doc( mFileName.c_str() ); + TiXmlDocument doc(fileName.c_str()); TiXmlDeclaration dec; dec.Parse( "", 0, TIXML_ENCODING_UNKNOWN ); diff --git a/extern/oics/ICSInputControlSystem.h b/extern/oics/ICSInputControlSystem.h index 97ab8d2edf..aa37c4a124 100644 --- a/extern/oics/ICSInputControlSystem.h +++ b/extern/oics/ICSInputControlSystem.h @@ -144,7 +144,7 @@ namespace ICS void cancelDetectingBindingState(); bool detectingBindingState(); - bool save(std::string fileName = ""); + bool save(const std::string& fileName); void adjustMouseRegion (Uint16 width, Uint16 height); From ca2bacd47a79b5d0532c8cf0497e8e2d2a88786d Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 21 Aug 2024 00:13:27 +0200 Subject: [PATCH 2/3] Revert "Ability to unbind controls in settings menu" This reverts commit 0836680e36ede07d733eb02f8c9c2027d6555e01. To prevent crashes on empty input bindings config. --- apps/openmw/mwinput/bindingsmanager.cpp | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwinput/bindingsmanager.cpp b/apps/openmw/mwinput/bindingsmanager.cpp index bad6744c0f..339ebf4276 100644 --- a/apps/openmw/mwinput/bindingsmanager.cpp +++ b/apps/openmw/mwinput/bindingsmanager.cpp @@ -79,12 +79,7 @@ namespace MWInput // Disallow binding escape key if (key == SDL_SCANCODE_ESCAPE) { - // Unbind if esc pressed - if (mDetectingKeyboard) - clearAllKeyBindings(mInputBinder, control); - else - clearAllControllerBindings(mInputBinder, control); - control->setInitialValue(0.0f); + // Stop binding if esc pressed mInputBinder->cancelDetectingBindingState(); MWBase::Environment::get().getWindowManager()->notifyInputActionBound(); return; @@ -161,14 +156,7 @@ namespace MWInput return; clearAllControllerBindings(mInputBinder, control); control->setInitialValue(0.0f); - if (button == SDL_CONTROLLER_BUTTON_START) - { - // Disallow rebinding SDL_CONTROLLER_BUTTON_START - it is used to open main and without it is not - // even possible to exit the game (or change the binding back). - mInputBinder->cancelDetectingBindingState(); - } - else - ICS::DetectingBindingListener::joystickButtonBindingDetected(ICS, deviceID, control, button, direction); + ICS::DetectingBindingListener::joystickButtonBindingDetected(ICS, deviceID, control, button, direction); MWBase::Environment::get().getWindowManager()->notifyInputActionBound(); } @@ -192,11 +180,8 @@ namespace MWInput mListener = std::make_unique(mInputBinder.get(), this); mInputBinder->setDetectingBindingListener(mListener.get()); - if (!userFileExists) - { - loadKeyDefaults(); - loadControllerDefaults(); - } + loadKeyDefaults(); + loadControllerDefaults(); for (int i = 0; i < A_Last; ++i) { From 58b72e383664a9d17e0c16a4ed7fa27d3e52df0b Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 20 Aug 2024 23:55:00 +0200 Subject: [PATCH 3/3] Access channels and controls via at function To avoid UB on out of range access. --- extern/oics/ICSInputControlSystem.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extern/oics/ICSInputControlSystem.h b/extern/oics/ICSInputControlSystem.h index aa37c4a124..f0736409c9 100644 --- a/extern/oics/ICSInputControlSystem.h +++ b/extern/oics/ICSInputControlSystem.h @@ -84,11 +84,11 @@ namespace ICS // in seconds void update(float timeSinceLastFrame); - inline Channel* getChannel(int i){ return mChannels[i]; }; + Channel* getChannel(int i){ return mChannels.at(i); }; float getChannelValue(int i); inline int getChannelCount(){ return (int)mChannels.size(); }; - inline Control* getControl(int i){ return mControls[i]; }; + Control* getControl(int i){ return mControls.at(i); }; float getControlValue(int i); inline int getControlCount(){ return (int)mControls.size(); }; inline void addControl(Control* control){ mControls.push_back(control); };