From 1991199a9b9719a93bbf1d3bd4380ddb3fc5d167 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 26 Apr 2026 22:36:44 -0700
Subject: [PATCH] Enable XDG_DATA_HOME and XDG_DATA_DIRS for Linux
distributions
---
CMakeLists.txt | 6 ++++-
utils/files.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 63 insertions(+), 4 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 251f398f..d7ce918b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -248,7 +248,11 @@ else()
include(GNUInstallDirs)
set(GAME_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}")
- target_compile_definitions(${TARGET_NAME} PRIVATE MAELSTROM_DATA=\"${CMAKE_INSTALL_PREFIX}/${GAME_INSTALL_DATADIR}/Data/\")
+ target_compile_definitions(${TARGET_NAME} PRIVATE
+ MAELSTROM_USE_XDG_DIRS
+ MAELSTROM_DATA=\"${CMAKE_INSTALL_PREFIX}/${GAME_INSTALL_DATADIR}/Data/\"
+ MAELSTROM_MODS=\"${CMAKE_INSTALL_PREFIX}/${GAME_INSTALL_DATADIR}/mods/\"
+ )
endif()
install(TARGETS ${TARGET_NAME} SDL3-shared LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" NAMELINK_SKIP RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
diff --git a/utils/files.c b/utils/files.c
index d53dbbe0..6ab77b50 100644
--- a/utils/files.c
+++ b/utils/files.c
@@ -22,7 +22,7 @@
#include "files.h"
#ifndef PATH_MAX
-#define PATH_MAX 256
+#define PATH_MAX 256
#endif
static const char *storage_org;
@@ -31,7 +31,50 @@ static char datapath[PATH_MAX];
static char modpath[PATH_MAX];
static char modfile[PATH_MAX];
-bool InitDataPath(void)
+#ifdef MAELSTROM_USE_XDG_DIRS
+
+static bool GetXDGDataPath(const char *directory, char *path, size_t pathlen)
+{
+ SDL_PathInfo info;
+ const char *env = SDL_getenv("XDG_DATA_HOME");
+ if (env && *env) {
+ SDL_snprintf(path, pathlen, "%s/maelstrom/%s", env, directory);
+ if (SDL_GetPathInfo(path, &info) && info.type == SDL_PATHTYPE_DIRECTORY) {
+ return true;
+ }
+ } else {
+ const char *home = SDL_getenv("HOME");
+ if (home && *home) {
+ SDL_snprintf(path, pathlen, "%s/.local/share/maelstrom/%s", home, directory);
+ if (SDL_GetPathInfo(path, &info) && info.type == SDL_PATHTYPE_DIRECTORY) {
+ return true;
+ }
+ }
+ }
+
+ bool result = false;
+ env = SDL_getenv("XDG_DATA_DIRS");
+ if (!env || !*env) {
+ env = "/usr/local/share/:/usr/share/";
+ }
+ char *paths = SDL_strdup(env);
+ if (paths) {
+ char *saveptr;
+ for (char *candidate = SDL_strtok_r(paths, ":", &saveptr); candidate; candidate = SDL_strtok_r(NULL, ":", &saveptr)) {
+ SDL_snprintf(path, pathlen, "%s/maelstrom/%s", candidate, directory);
+ if (SDL_GetPathInfo(path, &info) && info.type == SDL_PATHTYPE_DIRECTORY) {
+ result = true;
+ break;
+ }
+ }
+ SDL_free(paths);
+ }
+ return result;
+}
+
+#endif // MAELSTROM_USE_XDG_DIRS
+
+static bool InitDataPath(void)
{
const char *env = SDL_getenv("MAELSTROM_DATA");
@@ -40,6 +83,12 @@ bool InitDataPath(void)
return true;
}
+#ifdef MAELSTROM_USE_XDG_DIRS
+ if (GetXDGDataPath("Data", datapath, sizeof(datapath))) {
+ return true;
+ }
+#endif
+
#ifdef MAELSTROM_DATA
SDL_strlcpy(datapath, MAELSTROM_DATA, sizeof(datapath));
return true;
@@ -69,7 +118,7 @@ bool InitDataPath(void)
#endif // MAELSTROM_DATA
}
-bool InitModPath(void)
+static bool InitModPath(void)
{
const char *env = SDL_getenv("MAELSTROM_MODS");
@@ -78,6 +127,12 @@ bool InitModPath(void)
return true;
}
+#ifdef MAELSTROM_USE_XDG_DIRS
+ if (GetXDGDataPath("mods", modpath, sizeof(modpath))) {
+ return true;
+ }
+#endif
+
#ifdef MAELSTROM_MODS
SDL_strlcpy(modpath, MAELSTROM_MODS, sizeof(modpath));
return true;