Automatically add missing hotkeys to the global input config (#4003)
Some checks are pending
Build and Release / reuse (push) Waiting to run
Build and Release / clang-format (push) Waiting to run
Build and Release / get-info (push) Waiting to run
Build and Release / windows-sdl (push) Blocked by required conditions
Build and Release / macos-sdl (push) Blocked by required conditions
Build and Release / linux-sdl (push) Blocked by required conditions
Build and Release / linux-sdl-gcc (push) Blocked by required conditions
Build and Release / pre-release (push) Blocked by required conditions

This commit is contained in:
kalaposfos13 2026-02-07 21:39:08 +01:00 committed by GitHub
parent 88cdfb4b1f
commit 2e789649ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 52 additions and 22 deletions

View File

@ -1,7 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
// SPDX-FileCopyrightText: Copyright 2025-2026 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <fstream>
#include <map>
#include <optional>
#include <string>
#include <fmt/core.h>
@ -14,6 +15,8 @@
#include "common/path_util.h"
#include "common/scm_rev.h"
#include "input/input_handler.h"
using std::nullopt;
using std::optional;
using std::string;
@ -1289,19 +1292,6 @@ void setDefaultValues(bool is_game_specific) {
constexpr std::string_view GetDefaultGlobalConfig() {
return R"(# Anything put here will be loaded for all games,
# alongside the game's config or default.ini depending on your preference.
hotkey_renderdoc_capture = f12
hotkey_fullscreen = f11
hotkey_show_fps = f10
hotkey_pause = f9
hotkey_reload_inputs = f8
hotkey_toggle_mouse_to_joystick = f7
hotkey_toggle_mouse_to_gyro = f6
hotkey_toggle_mouse_to_touchpad = delete
hotkey_quit = lctrl, lshift, end
hotkey_volume_up = kpplus
hotkey_volume_down = kpminus
)";
}
@ -1379,7 +1369,7 @@ analog_deadzone = rightjoystick, 2, 127
override_controller_color = false, 0, 0, 255
)";
}
std::filesystem::path GetFoolproofInputConfigFile(const string& game_id) {
std::filesystem::path GetInputConfigFile(const string& game_id) {
// Read configuration file of the game, and if it doesn't exist, generate it from default
// If that doesn't exist either, generate that from getDefaultConfig() and try again
// If even the folder is missing, we start with that.
@ -1418,6 +1408,39 @@ std::filesystem::path GetFoolproofInputConfigFile(const string& game_id) {
}
}
}
if (game_id == "global") {
std::map<string, string> default_bindings_to_add = {
{"hotkey_renderdoc_capture", "f12"},
{"hotkey_fullscreen", "f11"},
{"hotkey_show_fps", "f10"},
{"hotkey_pause", "f9"},
{"hotkey_reload_inputs", "f8"},
{"hotkey_toggle_mouse_to_joystick", "f7"},
{"hotkey_toggle_mouse_to_gyro", "f6"},
{"hotkey_toggle_mouse_to_touchpad", "delete"},
{"hotkey_quit", "lctrl, lshift, end"},
{"hotkey_volume_up", "kpplus"},
{"hotkey_volume_down", "kpminus"},
};
std::ifstream global_in(config_file);
string line;
while (std::getline(global_in, line)) {
line.erase(std::remove_if(line.begin(), line.end(),
[](unsigned char c) { return std::isspace(c); }),
line.end());
std::size_t equal_pos = line.find('=');
if (equal_pos == std::string::npos) {
continue;
}
std::string output_string = line.substr(0, equal_pos);
default_bindings_to_add.erase(output_string);
}
global_in.close();
std::ofstream global_out(config_file, std::ios::app);
for (auto const& b : default_bindings_to_add) {
global_out << b.first << " = " << b.second << "\n";
}
}
// If game-specific config doesn't exist, create it from the default config
if (!std::filesystem::exists(config_file)) {

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
// SPDX-FileCopyrightText: Copyright 2025-2026 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@ -183,6 +183,6 @@ std::filesystem::path getAddonInstallDir();
void setDefaultValues(bool is_game_specific = false);
constexpr std::string_view GetDefaultGlobalConfig();
std::filesystem::path GetFoolproofInputConfigFile(const std::string& game_id = "");
std::filesystem::path GetInputConfigFile(const std::string& game_id = "");
}; // namespace Config

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "input_handler.h"
@ -200,6 +200,8 @@ InputBinding GetBindingFromString(std::string& line) {
input = InputID(InputType::Axis, string_to_axis_map.at(t).axis);
} else if (string_to_cbutton_map.find(t) != string_to_cbutton_map.end()) {
input = InputID(InputType::Controller, string_to_cbutton_map.at(t));
} else if (string_to_hotkey_map.find(t) != string_to_hotkey_map.end()) {
input = InputID(InputType::Controller, string_to_hotkey_map.at(t));
} else {
// Invalid token found; return default binding
LOG_DEBUG(Input, "Invalid token found: {}", t);
@ -220,8 +222,8 @@ InputBinding GetBindingFromString(std::string& line) {
void ParseInputConfig(const std::string game_id = "") {
std::string game_id_or_default = Config::GetUseUnifiedInputConfig() ? "default" : game_id;
const auto config_file = Config::GetFoolproofInputConfigFile(game_id_or_default);
const auto global_config_file = Config::GetFoolproofInputConfigFile("global");
const auto config_file = Config::GetInputConfigFile(game_id_or_default);
const auto global_config_file = Config::GetInputConfigFile("global");
// we reset these here so in case the user fucks up or doesn't include some of these,
// we can fall back to default
@ -396,13 +398,16 @@ void ParseInputConfig(const std::string game_id = "") {
InputBinding binding = GetBindingFromString(input_string);
BindingConnection connection(InputID(), nullptr);
auto button_it = string_to_cbutton_map.find(output_string);
if (button_it == string_to_cbutton_map.end()) {
button_it = string_to_hotkey_map.find(output_string);
}
auto axis_it = string_to_axis_map.find(output_string);
if (binding.IsEmpty()) {
LOG_WARNING(Input, "Invalid format at line: {}, data: \"{}\", skipping line.",
lineCount, line);
return;
}
if (button_it != string_to_cbutton_map.end()) {
if (button_it != string_to_hotkey_map.end()) {
connection = BindingConnection(
binding, &*std::ranges::find(output_array, ControllerOutput(button_it->second)));
connections.insert(connections.end(), connection);

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@ -138,6 +138,8 @@ const std::map<std::string, u32> string_to_cbutton_map = {
{"rpaddle_high", SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1},
{"rpaddle_low", SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2},
{"mouse_gyro_roll_mode", MOUSE_GYRO_ROLL_MODE},
};
const std::map<std::string, u32> string_to_hotkey_map = {
{"hotkey_pause", HOTKEY_PAUSE},
{"hotkey_fullscreen", HOTKEY_FULLSCREEN},
{"hotkey_show_fps", HOTKEY_SIMPLE_FPS},