mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-08-17 07:49:21 +00:00
Respect XDG_STATE_HOME & LocalAppData specification
https://specifications.freedesktop.org/basedir-spec/0.8/#variables https://learn.microsoft.com/en-us/windows/apps/design/app-settings/store-and-retrieve-app-data#local-app-data
This commit is contained in:
parent
53b54406bd
commit
752cd4d449
5 changed files with 77 additions and 26 deletions
|
@ -108,6 +108,9 @@
|
||||||
#define FREELOOK_CONFIG "FreeLook.ini"
|
#define FREELOOK_CONFIG "FreeLook.ini"
|
||||||
#define RETROACHIEVEMENTS_CONFIG "RetroAchievements.ini"
|
#define RETROACHIEVEMENTS_CONFIG "RetroAchievements.ini"
|
||||||
|
|
||||||
|
// Files in the directory returned by GetUserPath(D_APPLICATIONSTATE_IDX)
|
||||||
|
#define QSETTINGS_CONFIG "Qt.ini"
|
||||||
|
|
||||||
// Files in the directory returned by GetUserPath(D_LOGS_IDX)
|
// Files in the directory returned by GetUserPath(D_LOGS_IDX)
|
||||||
#define MAIN_LOG "dolphin.log"
|
#define MAIN_LOG "dolphin.log"
|
||||||
|
|
||||||
|
|
|
@ -847,6 +847,7 @@ static void RebuildUserDirectories(unsigned int dir_index)
|
||||||
s_user_paths[D_CONFIG_IDX] = s_user_paths[D_USER_IDX] + CONFIG_DIR DIR_SEP;
|
s_user_paths[D_CONFIG_IDX] = s_user_paths[D_USER_IDX] + CONFIG_DIR DIR_SEP;
|
||||||
s_user_paths[D_GAMESETTINGS_IDX] = s_user_paths[D_USER_IDX] + GAMESETTINGS_DIR DIR_SEP;
|
s_user_paths[D_GAMESETTINGS_IDX] = s_user_paths[D_USER_IDX] + GAMESETTINGS_DIR DIR_SEP;
|
||||||
s_user_paths[D_MAPS_IDX] = s_user_paths[D_USER_IDX] + MAPS_DIR DIR_SEP;
|
s_user_paths[D_MAPS_IDX] = s_user_paths[D_USER_IDX] + MAPS_DIR DIR_SEP;
|
||||||
|
s_user_paths[D_APPLICATIONSTATE_IDX] = s_user_paths[D_USER_IDX] + DIR_SEP;
|
||||||
s_user_paths[D_CACHE_IDX] = s_user_paths[D_USER_IDX] + CACHE_DIR DIR_SEP;
|
s_user_paths[D_CACHE_IDX] = s_user_paths[D_USER_IDX] + CACHE_DIR DIR_SEP;
|
||||||
s_user_paths[D_COVERCACHE_IDX] = s_user_paths[D_CACHE_IDX] + COVERCACHE_DIR DIR_SEP;
|
s_user_paths[D_COVERCACHE_IDX] = s_user_paths[D_CACHE_IDX] + COVERCACHE_DIR DIR_SEP;
|
||||||
s_user_paths[D_REDUMPCACHE_IDX] = s_user_paths[D_CACHE_IDX] + REDUMPCACHE_DIR DIR_SEP;
|
s_user_paths[D_REDUMPCACHE_IDX] = s_user_paths[D_CACHE_IDX] + REDUMPCACHE_DIR DIR_SEP;
|
||||||
|
@ -888,6 +889,7 @@ static void RebuildUserDirectories(unsigned int dir_index)
|
||||||
s_user_paths[F_GCKEYBOARDCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + GCKEYBOARD_CONFIG;
|
s_user_paths[F_GCKEYBOARDCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + GCKEYBOARD_CONFIG;
|
||||||
s_user_paths[F_GFXCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + GFX_CONFIG;
|
s_user_paths[F_GFXCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + GFX_CONFIG;
|
||||||
s_user_paths[F_LOGGERCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + LOGGER_CONFIG;
|
s_user_paths[F_LOGGERCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + LOGGER_CONFIG;
|
||||||
|
s_user_paths[F_QSETTINGSCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + QSETTINGS_CONFIG;
|
||||||
s_user_paths[F_DUALSHOCKUDPCLIENTCONFIG_IDX] =
|
s_user_paths[F_DUALSHOCKUDPCLIENTCONFIG_IDX] =
|
||||||
s_user_paths[D_CONFIG_IDX] + DUALSHOCKUDPCLIENT_CONFIG;
|
s_user_paths[D_CONFIG_IDX] + DUALSHOCKUDPCLIENT_CONFIG;
|
||||||
s_user_paths[F_FREELOOKCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + FREELOOK_CONFIG;
|
s_user_paths[F_FREELOOKCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + FREELOOK_CONFIG;
|
||||||
|
@ -932,12 +934,29 @@ static void RebuildUserDirectories(unsigned int dir_index)
|
||||||
s_user_paths[D_CONFIG_IDX] + RETROACHIEVEMENTS_CONFIG;
|
s_user_paths[D_CONFIG_IDX] + RETROACHIEVEMENTS_CONFIG;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case D_APPLICATIONSTATE_IDX:
|
||||||
|
// Use legacy locations if they already exist.
|
||||||
|
if (!Exists(s_user_paths[F_QSETTINGSCONFIG_IDX]))
|
||||||
|
s_user_paths[F_QSETTINGSCONFIG_IDX] = s_user_paths[D_APPLICATIONSTATE_IDX] + QSETTINGS_CONFIG;
|
||||||
|
if (!Exists(s_user_paths[D_LOGS_IDX]))
|
||||||
|
{
|
||||||
|
s_user_paths[D_LOGS_IDX] = s_user_paths[D_APPLICATIONSTATE_IDX] + LOGS_DIR DIR_SEP;
|
||||||
|
s_user_paths[F_MAINLOG_IDX] = s_user_paths[D_LOGS_IDX] + MAIN_LOG;
|
||||||
|
s_user_paths[D_MAILLOGS_IDX] = s_user_paths[D_LOGS_IDX] + MAIL_LOGS_DIR DIR_SEP;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case D_CACHE_IDX:
|
case D_CACHE_IDX:
|
||||||
s_user_paths[D_COVERCACHE_IDX] = s_user_paths[D_CACHE_IDX] + COVERCACHE_DIR DIR_SEP;
|
// Use legacy locations if they already exist.
|
||||||
s_user_paths[D_REDUMPCACHE_IDX] = s_user_paths[D_CACHE_IDX] + REDUMPCACHE_DIR DIR_SEP;
|
if (!Exists(s_user_paths[D_COVERCACHE_IDX]))
|
||||||
s_user_paths[D_SHADERCACHE_IDX] = s_user_paths[D_CACHE_IDX] + SHADERCACHE_DIR DIR_SEP;
|
s_user_paths[D_COVERCACHE_IDX] = s_user_paths[D_CACHE_IDX] + COVERCACHE_DIR DIR_SEP;
|
||||||
s_user_paths[D_RETROACHIEVEMENTSCACHE_IDX] =
|
if (!Exists(s_user_paths[D_REDUMPCACHE_IDX]))
|
||||||
s_user_paths[D_CACHE_IDX] + RETROACHIEVEMENTSCACHE_DIR DIR_SEP;
|
s_user_paths[D_REDUMPCACHE_IDX] = s_user_paths[D_CACHE_IDX] + REDUMPCACHE_DIR DIR_SEP;
|
||||||
|
if (!Exists(s_user_paths[D_SHADERCACHE_IDX]))
|
||||||
|
s_user_paths[D_SHADERCACHE_IDX] = s_user_paths[D_CACHE_IDX] + SHADERCACHE_DIR DIR_SEP;
|
||||||
|
if (!Exists(s_user_paths[D_RETROACHIEVEMENTSCACHE_IDX]))
|
||||||
|
s_user_paths[D_RETROACHIEVEMENTSCACHE_IDX] =
|
||||||
|
s_user_paths[D_CACHE_IDX] + RETROACHIEVEMENTSCACHE_DIR DIR_SEP;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_GCUSER_IDX:
|
case D_GCUSER_IDX:
|
||||||
|
|
|
@ -28,11 +28,12 @@ enum
|
||||||
{
|
{
|
||||||
D_USER_IDX,
|
D_USER_IDX,
|
||||||
D_GCUSER_IDX,
|
D_GCUSER_IDX,
|
||||||
D_WIIROOT_IDX, // always points to User/Wii or global user-configured directory
|
D_WIIROOT_IDX, // always points to User/Wii or global user-configured directory
|
||||||
D_SESSION_WIIROOT_IDX, // may point to minimal temporary directory for determinism
|
D_SESSION_WIIROOT_IDX, // may point to minimal temporary directory for determinism
|
||||||
D_CONFIG_IDX, // global settings
|
D_CONFIG_IDX, // global settings
|
||||||
D_GAMESETTINGS_IDX, // user-specified settings which override both the global and the default
|
D_APPLICATIONSTATE_IDX, // data that is not portable (window positions, open recent, etc.)
|
||||||
// settings (per game)
|
D_GAMESETTINGS_IDX, // user-specified settings which override both the global and the default
|
||||||
|
// settings (per game)
|
||||||
D_SKYLANDERS_IDX,
|
D_SKYLANDERS_IDX,
|
||||||
|
|
||||||
D_MAPS_IDX,
|
D_MAPS_IDX,
|
||||||
|
@ -96,6 +97,7 @@ enum
|
||||||
F_FREELOOKCONFIG_IDX,
|
F_FREELOOKCONFIG_IDX,
|
||||||
F_GBABIOS_IDX,
|
F_GBABIOS_IDX,
|
||||||
F_RETROACHIEVEMENTSCONFIG_IDX,
|
F_RETROACHIEVEMENTSCONFIG_IDX,
|
||||||
|
F_QSETTINGSCONFIG_IDX,
|
||||||
NUM_PATH_INDICES
|
NUM_PATH_INDICES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -112,9 +112,8 @@ Settings& Settings::Instance()
|
||||||
|
|
||||||
QSettings& Settings::GetQSettings()
|
QSettings& Settings::GetQSettings()
|
||||||
{
|
{
|
||||||
static QSettings settings(
|
const QString filename = QString::fromStdString(File::GetUserPath(F_QSETTINGSCONFIG_IDX));
|
||||||
QStringLiteral("%1/Qt.ini").arg(QString::fromStdString(File::GetUserPath(D_CONFIG_IDX))),
|
static QSettings settings(filename, QSettings::IniFormat);
|
||||||
QSettings::IniFormat);
|
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -298,6 +298,9 @@ void SetUserDirectory(std::string custom_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string user_path;
|
std::string user_path;
|
||||||
|
std::optional<std::string> application_state_path;
|
||||||
|
std::optional<std::string> config_path;
|
||||||
|
std::optional<std::string> cache_path;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Detect where the User directory is. There are five different cases
|
// Detect where the User directory is. There are five different cases
|
||||||
// (on top of the command line flag, which overrides all this):
|
// (on top of the command line flag, which overrides all this):
|
||||||
|
@ -305,19 +308,25 @@ void SetUserDirectory(std::string custom_path)
|
||||||
// -> Use GetExeDirectory()\User
|
// -> Use GetExeDirectory()\User
|
||||||
// 2. HKCU\Software\Dolphin Emulator\LocalUserConfig exists and is true
|
// 2. HKCU\Software\Dolphin Emulator\LocalUserConfig exists and is true
|
||||||
// -> Use GetExeDirectory()\User
|
// -> Use GetExeDirectory()\User
|
||||||
// 3. HKCU\Software\Dolphin Emulator\UserConfigPath exists
|
// 3. HKCU\Software\Dolphin Emulator\UserConfigPath exists and isn't the same as
|
||||||
|
// AppData\Roaming
|
||||||
// -> Use this as the user directory path
|
// -> Use this as the user directory path
|
||||||
// 4. My Documents\Dolphin Emulator exists (default user folder before PR 10708)
|
// 4. My Documents\Dolphin Emulator exists (default user folder before PR 10708)
|
||||||
// -> Use this as the user directory path
|
// -> Use this as the user directory path
|
||||||
// 5. AppData\Roaming exists
|
// 5. AppData\Roaming exists
|
||||||
// -> Use AppData\Roaming\Dolphin Emulator as the User directory path
|
// -> Use AppData\Roaming\Dolphin Emulator as the User directory path
|
||||||
|
// 5.1 AppData\Local exists,
|
||||||
|
// -> Use AppData\Local\Dolphin Emulator as the Application State and Cache directory paths
|
||||||
// 6. Default
|
// 6. Default
|
||||||
// -> Use GetExeDirectory()\User
|
// -> Use GetExeDirectory()\User
|
||||||
|
|
||||||
// Get AppData path in case we need it.
|
// Get AppData path in case we need it.
|
||||||
|
std::string appdata_path;
|
||||||
wil::unique_cotaskmem_string appdata;
|
wil::unique_cotaskmem_string appdata;
|
||||||
bool appdata_found = SUCCEEDED(
|
bool appdata_found = SUCCEEDED(
|
||||||
SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_DEFAULT, nullptr, appdata.put()));
|
SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_DEFAULT, nullptr, appdata.put()));
|
||||||
|
if (appdata_found)
|
||||||
|
appdata_path = TStrToUTF8(appdata.get()) + DIR_SEP NORMAL_USER_DIR DIR_SEP;
|
||||||
|
|
||||||
// Check our registry keys
|
// Check our registry keys
|
||||||
wil::unique_hkey hkey;
|
wil::unique_hkey hkey;
|
||||||
|
@ -360,7 +369,7 @@ void SetUserDirectory(std::string custom_path)
|
||||||
{
|
{
|
||||||
user_path = File::GetExeDirectory() + DIR_SEP PORTABLE_USER_DIR DIR_SEP;
|
user_path = File::GetExeDirectory() + DIR_SEP PORTABLE_USER_DIR DIR_SEP;
|
||||||
}
|
}
|
||||||
else if (configPath) // Case 3
|
else if (configPath && appdata_path != TStrToUTF8(configPath.get())) // Case 3
|
||||||
{
|
{
|
||||||
user_path = TStrToUTF8(configPath.get());
|
user_path = TStrToUTF8(configPath.get());
|
||||||
}
|
}
|
||||||
|
@ -370,7 +379,20 @@ void SetUserDirectory(std::string custom_path)
|
||||||
}
|
}
|
||||||
else if (appdata_found) // Case 5
|
else if (appdata_found) // Case 5
|
||||||
{
|
{
|
||||||
user_path = TStrToUTF8(appdata.get()) + DIR_SEP NORMAL_USER_DIR DIR_SEP;
|
user_path = appdata_path;
|
||||||
|
|
||||||
|
wil::unique_cotaskmem_string localappdata;
|
||||||
|
bool localappdata_found = SUCCEEDED(
|
||||||
|
SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_DEFAULT, nullptr, localappdata.put()));
|
||||||
|
|
||||||
|
if (localappdata_found) // Case 5.1
|
||||||
|
{
|
||||||
|
const std::string localappdata_path =
|
||||||
|
TStrToUTF8(localappdata.get()) + DIR_SEP NORMAL_USER_DIR DIR_SEP;
|
||||||
|
|
||||||
|
application_state_path = localappdata_path;
|
||||||
|
cache_path = localappdata_path + CACHE_DIR DIR_SEP;
|
||||||
|
}
|
||||||
|
|
||||||
// Set the UserConfigPath value in the registry for backwards compatibility with older Dolphin
|
// Set the UserConfigPath value in the registry for backwards compatibility with older Dolphin
|
||||||
// builds, which will look for the default User directory in Documents. If we set this key,
|
// builds, which will look for the default User directory in Documents. If we set this key,
|
||||||
|
@ -441,32 +463,38 @@ void SetUserDirectory(std::string custom_path)
|
||||||
if (File::Exists("/.flatpak-info") || !File::Exists(user_path))
|
if (File::Exists("/.flatpak-info") || !File::Exists(user_path))
|
||||||
{
|
{
|
||||||
const char* data_home = getenv("XDG_DATA_HOME");
|
const char* data_home = getenv("XDG_DATA_HOME");
|
||||||
std::string data_path =
|
user_path =
|
||||||
std::string(data_home && data_home[0] == '/' ? data_home :
|
std::string(data_home && data_home[0] == '/' ? data_home :
|
||||||
(home_path + ".local" DIR_SEP "share")) +
|
(home_path + ".local" DIR_SEP "share")) +
|
||||||
DIR_SEP NORMAL_USER_DIR DIR_SEP;
|
DIR_SEP NORMAL_USER_DIR DIR_SEP;
|
||||||
|
|
||||||
const char* config_home = getenv("XDG_CONFIG_HOME");
|
const char* config_home = getenv("XDG_CONFIG_HOME");
|
||||||
std::string config_path =
|
config_path = std::string(config_home && config_home[0] == '/' ? config_home :
|
||||||
std::string(config_home && config_home[0] == '/' ? config_home :
|
(home_path + ".config")) +
|
||||||
(home_path + ".config")) +
|
DIR_SEP NORMAL_USER_DIR DIR_SEP;
|
||||||
DIR_SEP NORMAL_USER_DIR DIR_SEP;
|
|
||||||
|
|
||||||
const char* cache_home = getenv("XDG_CACHE_HOME");
|
const char* cache_home = getenv("XDG_CACHE_HOME");
|
||||||
std::string cache_path =
|
cache_path =
|
||||||
std::string(cache_home && cache_home[0] == '/' ? cache_home : (home_path + ".cache")) +
|
std::string(cache_home && cache_home[0] == '/' ? cache_home : (home_path + ".cache")) +
|
||||||
DIR_SEP NORMAL_USER_DIR DIR_SEP;
|
DIR_SEP NORMAL_USER_DIR DIR_SEP;
|
||||||
|
|
||||||
File::SetUserPath(D_USER_IDX, data_path);
|
const char* state_home = getenv("XDG_STATE_HOME");
|
||||||
File::SetUserPath(D_CONFIG_IDX, config_path);
|
application_state_path = std::string(state_home && state_home[0] == '/' ?
|
||||||
File::SetUserPath(D_CACHE_IDX, cache_path);
|
state_home :
|
||||||
return;
|
(home_path + ".local" DIR_SEP "state")) +
|
||||||
|
DIR_SEP NORMAL_USER_DIR DIR_SEP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
File::SetUserPath(D_USER_IDX, std::move(user_path));
|
File::SetUserPath(D_USER_IDX, std::move(user_path));
|
||||||
|
if (config_path)
|
||||||
|
File::SetUserPath(D_CONFIG_IDX, std::move(*config_path));
|
||||||
|
if (cache_path)
|
||||||
|
File::SetUserPath(D_CACHE_IDX, std::move(*cache_path));
|
||||||
|
if (application_state_path)
|
||||||
|
File::SetUserPath(D_APPLICATIONSTATE_IDX, std::move(*application_state_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TriggerSTMPowerEvent()
|
bool TriggerSTMPowerEvent()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue