Unix: enable use of XDG paths for storing Blender configuration on Linux/BSD/..,

starting from version 2.64. Unless you have a special system setup, this means the
will be in ~/.config/blender rather than ~/.blender.

When the version number is changed to 2.64, the "Copy Previous Settings" operator
in the splash will copy the settings to the new location.

XDG base directory specification:
http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
This commit is contained in:
Brecht Van Lommel 2012-05-25 12:08:29 +00:00
parent 81935ee677
commit 942fcf4415
16 changed files with 108 additions and 120 deletions

@ -161,8 +161,6 @@ if(UNIX AND NOT APPLE)
option(WITH_X11_XINPUT "Enable X11 Xinput (tablet support and unicode input)" ON)
option(WITH_X11_XF86VMODE "Enable X11 video mode switching" ON)
option(WITH_BUILTIN_GLEW "Use GLEW OpenGL wrapper library bundled with blender" ON)
option(WITH_XDG_USER_DIRS "Build with XDG Base Directory Specification (only config and documents for now)" OFF)
mark_as_advanced(WITH_XDG_USER_DIRS)
# freebsd doesn't seems to support XDND
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")

@ -108,10 +108,6 @@ if(WITH_INPUT_NDOF)
)
endif()
if(WITH_XDG_USER_DIRS)
add_definitions(-DWITH_XDG_USER_DIRS)
endif()
if(WITH_HEADLESS OR WITH_GHOST_SDL)
if(WITH_HEADLESS)
list(APPEND SRC

@ -72,17 +72,17 @@ protected:
public:
/**
* Determine the base dir in which shared resources are located. It will first try to use
* "unpack and run" path, then look for properly installed path, not including versioning.
* "unpack and run" path, then look for properly installed path, including versioning.
* @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
*/
virtual const GHOST_TUns8 *getSystemDir() const = 0;
virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const = 0;
/**
* Determine the base dir in which user configuration is stored, not including versioning.
* Determine the base dir in which user configuration is stored, including versioning.
* If needed, it will create the base directory.
* @return Unsigned char string pointing to user dir (eg ~/.blender/).
*/
virtual const GHOST_TUns8 *getUserDir() const = 0;
virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const = 0;
/**
* Determine the directory of the current binary

@ -55,16 +55,16 @@ extern GHOST_TSuccess GHOST_DisposeSystemPaths(void);
/**
* Determine the base dir in which shared resources are located. It will first try to use
* "unpack and run" path, then look for properly installed path, not including versioning.
* "unpack and run" path, then look for properly installed path, including versioning.
* @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
*/
extern const GHOST_TUns8 *GHOST_getSystemDir(void);
extern const GHOST_TUns8 *GHOST_getSystemDir(int version, const char *versionstr);
/**
* Determine the base dir in which user configuration is stored, not including versioning.
* Determine the base dir in which user configuration is stored, including versioning.
* @return Unsigned char string pointing to user dir (eg ~).
*/
extern const GHOST_TUns8 *GHOST_getUserDir(void);
extern const GHOST_TUns8 *GHOST_getUserDir(int version, const char *versionstr);
/**

@ -45,16 +45,16 @@ GHOST_TSuccess GHOST_DisposeSystemPaths(void)
return GHOST_ISystemPaths::dispose();
}
const GHOST_TUns8 *GHOST_getSystemDir()
const GHOST_TUns8 *GHOST_getSystemDir(int version, const char *versionstr)
{
GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
return systemPaths ? systemPaths->getSystemDir() : 0;
return systemPaths ? systemPaths->getSystemDir(version, versionstr) : 0;
}
const GHOST_TUns8 *GHOST_getUserDir()
const GHOST_TUns8 *GHOST_getUserDir(int version, const char *versionstr)
{
GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
return systemPaths ? systemPaths->getUserDir() : 0; /* shouldn't be NULL */
return systemPaths ? systemPaths->getUserDir(version, versionstr) : 0; /* shouldn't be NULL */
}
const GHOST_TUns8 *GHOST_getBinaryDir()

@ -52,17 +52,17 @@ public:
/**
* Determine the base dir in which shared resources are located. It will first try to use
* "unpack and run" path, then look for properly installed path, not including versioning.
* "unpack and run" path, then look for properly installed path, including versioning.
* @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
*/
virtual const GHOST_TUns8 *getSystemDir() const = 0;
virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const = 0;
/**
* Determine the base dir in which user configuration is stored, not including versioning.
* If needed, it will create the base directory.
* @return Unsigned char string pointing to user dir (eg ~/.blender/).
*/
virtual const GHOST_TUns8 *getUserDir() const = 0;
/**
* Determine the base dir in which user configuration is stored, including versioning.
* If needed, it will create the base directory.
* @return Unsigned char string pointing to user dir (eg ~/.blender/).
*/
virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const = 0;
/**
* Determine the directory of the current binary

@ -44,21 +44,23 @@ GHOST_SystemPathsCarbon::~GHOST_SystemPathsCarbon()
{
}
const GHOST_TUns8 *GHOST_SystemPathsCarbon::getSystemDir() const
const GHOST_TUns8 *GHOST_SystemPathsCarbon::getSystemDir(int, const char *versionstr) const
{
return (GHOST_TUns8 *)"/Library/Application Support";
static char systemPath[1024];
snprintf(systemPath, sizeof(systemPath), "/Library/Application Support/Blender/%s", versionstr);
return (GHOST_TUns8*)systemPath;
}
const GHOST_TUns8 *GHOST_SystemPathsCarbon::getUserDir() const
const GHOST_TUns8 *GHOST_SystemPathsCarbon::getUserDir(int, const char *versionstr) const
{
static char usrPath[256] = "";
static char usrPath[1024];
char *env = getenv("HOME");
if (env) {
strncpy(usrPath, env, 245);
usrPath[245] = 0;
strcat(usrPath, "/Library/Application Support");
return (GHOST_TUns8 *) usrPath;
snprintf(usrPath, sizeof(usrPath), "%s/Library/Application Support/Blender/%s", env, versionstr);
return (GHOST_TUns8*)usrPath;
}
else
return NULL;

@ -60,17 +60,17 @@ public:
/**
* Determine the base dir in which shared resources are located. It will first try to use
* "unpack and run" path, then look for properly installed path, not including versioning.
* "unpack and run" path, then look for properly installed path, including versioning.
* @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
*/
virtual const GHOST_TUns8 *getSystemDir() const;
virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const;
/**
* Determine the base dir in which user configuration is stored, not including versioning.
* Determine the base dir in which user configuration is stored, including versioning.
* If needed, it will create the base directory.
* @return Unsigned char string pointing to user dir (eg ~/.blender/).
*/
virtual const GHOST_TUns8 *getUserDir() const;
virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
/**
* Determine the directory of the current binary

@ -54,17 +54,17 @@ public:
/**
* Determine the base dir in which shared resources are located. It will first try to use
* "unpack and run" path, then look for properly installed path, not including versioning.
* "unpack and run" path, then look for properly installed path, including versioning.
* @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
*/
virtual const GHOST_TUns8 *getSystemDir() const;
virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const;
/**
* Determine the base dir in which user configuration is stored, not including versioning.
* Determine the base dir in which user configuration is stored, including versioning.
* If needed, it will create the base directory.
* @return Unsigned char string pointing to user dir (eg ~/.blender/).
*/
virtual const GHOST_TUns8 *getUserDir() const;
virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
/**
* Determine the directory of the current binary

@ -50,9 +50,9 @@ GHOST_SystemPathsCocoa::~GHOST_SystemPathsCocoa()
#pragma mark Base directories retrieval
const GHOST_TUns8* GHOST_SystemPathsCocoa::getSystemDir() const
const GHOST_TUns8* GHOST_SystemPathsCocoa::getSystemDir(int, const char *versionstr) const
{
static GHOST_TUns8 tempPath[512] = "";
static char tempPath[512] = "";
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *basePath;
NSArray *paths;
@ -66,15 +66,15 @@ const GHOST_TUns8* GHOST_SystemPathsCocoa::getSystemDir() const
return NULL;
}
strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]);
snprintf(tempPath, sizeof(tempPath), "%s/Blender/%s", [basePath cStringUsingEncoding:NSASCIIStringEncoding], versionstr);
[pool drain];
return tempPath;
return (GHOST_TUns8*)tempPath;
}
const GHOST_TUns8* GHOST_SystemPathsCocoa::getUserDir() const
const GHOST_TUns8* GHOST_SystemPathsCocoa::getUserDir(int, const char *versionstr) const
{
static GHOST_TUns8 tempPath[512] = "";
static char tempPath[512] = "";
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *basePath;
NSArray *paths;
@ -88,10 +88,10 @@ const GHOST_TUns8* GHOST_SystemPathsCocoa::getUserDir() const
return NULL;
}
strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]);
snprintf(tempPath, sizeof(tempPath), "%s/Blender/%s", [basePath cStringUsingEncoding:NSASCIIStringEncoding], versionstr);
[pool drain];
return tempPath;
return (GHOST_TUns8*)tempPath;
}
const GHOST_TUns8* GHOST_SystemPathsCocoa::getBinaryDir() const

@ -69,9 +69,9 @@ GHOST_SystemPathsWin32::~GHOST_SystemPathsWin32()
{
}
const GHOST_TUns8 *GHOST_SystemPathsWin32::getSystemDir() const
const GHOST_TUns8 *GHOST_SystemPathsWin32::getSystemDir(int, const char *versionstr) const
{
static char knownpath[MAX_PATH * 3] = {0}; /* 1 utf-16 might translante into 3 utf-8. 2 utf-16 translates into 4 utf-8*/
static char knownpath[MAX_PATH * 3 + 128] = {0}; /* 1 utf-16 might translante into 3 utf-8. 2 utf-16 translates into 4 utf-8*/
wchar_t knownpath_16[MAX_PATH];
HRESULT hResult = SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath_16);
@ -79,15 +79,17 @@ const GHOST_TUns8 *GHOST_SystemPathsWin32::getSystemDir() const
if (hResult == S_OK)
{
conv_utf_16_to_8(knownpath_16, knownpath, MAX_PATH * 3);
return (GHOST_TUns8 *)knownpath;
strcat(knownpath, "\\Blender Foundation\\Blender\\");
strcat(knownpath, versionstr);
return (GHOST_TUns8*)knownpath;
}
return NULL;
}
const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserDir() const
const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserDir(int, const char *versionstr) const
{
static char knownpath[MAX_PATH * 3] = {0};
static char knownpath[MAX_PATH * 3 + 128] = {0};
wchar_t knownpath_16[MAX_PATH];
HRESULT hResult = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath_16);
@ -95,7 +97,9 @@ const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserDir() const
if (hResult == S_OK)
{
conv_utf_16_to_8(knownpath_16, knownpath, MAX_PATH * 3);
return (GHOST_TUns8 *)knownpath;
strcat(knownpath, "\\Blender Foundation\\Blender\\");
strcat(knownpath, versionstr);
return (GHOST_TUns8*)knownpath;
}
return NULL;

@ -64,17 +64,17 @@ public:
/**
* Determine the base dir in which shared resources are located. It will first try to use
* "unpack and run" path, then look for properly installed path, not including versioning.
* "unpack and run" path, then look for properly installed path, including versioning.
* @return Unsigned char string pointing to system dir (eg /usr/share/).
*/
const GHOST_TUns8 *getSystemDir() const;
const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const;
/**
* Determine the base dir in which user configuration is stored, not including versioning.
* Determine the base dir in which user configuration is stored, including versioning.
* If needed, it will create the base directory.
* @return Unsigned char string pointing to user dir (eg ~/).
*/
const GHOST_TUns8 *getUserDir() const;
const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
/**
* Determine the directory of the current binary

@ -41,10 +41,8 @@
#include <stdio.h> // for fprintf only
#include <cstdlib> // for exit
#ifdef WITH_XDG_USER_DIRS
# include <pwd.h> // for get home without use getenv()
# include <limits.h> // for PATH_MAX
#endif
#include <pwd.h> // for get home without use getenv()
#include <limits.h> // for PATH_MAX
#ifdef PREFIX
static const char *static_path = PREFIX "/share";
@ -60,35 +58,51 @@ GHOST_SystemPathsX11::~GHOST_SystemPathsX11()
{
}
const GHOST_TUns8 *GHOST_SystemPathsX11::getSystemDir() const
const GHOST_TUns8 *GHOST_SystemPathsX11::getSystemDir(int, const char *versionstr) const
{
/* no prefix assumes a portable build which only uses bundled scripts */
return (const GHOST_TUns8 *)static_path;
if(static_path) {
static char system_path[PATH_MAX];
snprintf(system_path, sizeof(system_path), "%s/blender/%s", static_path, versionstr);
return (GHOST_TUns8*)system_path;
}
return NULL;
}
const GHOST_TUns8 *GHOST_SystemPathsX11::getUserDir() const
const GHOST_TUns8 *GHOST_SystemPathsX11::getUserDir(int version, const char *versionstr) const
{
#ifndef WITH_XDG_USER_DIRS
return (const GHOST_TUns8 *)getenv("HOME");
#else /* WITH_XDG_USER_DIRS */
const char *home = getenv("XDG_CONFIG_HOME");
static char user_path[PATH_MAX];
if (home) {
return (const GHOST_TUns8 *)home;
}
else {
static char user_path[PATH_MAX];
/* in blender 2.64, we migrate to XDG. to ensure the copy previous settings
* operator works we give a different path depending on the requested version */
if(version < 264) {
const char *home = getenv("HOME");
home = getenv("HOME");
if (home == NULL) {
home = getpwuid(getuid())->pw_dir;
if(home) {
snprintf(user_path, sizeof(user_path), "%s/.blender/%s", home, versionstr);
return (GHOST_TUns8*)user_path;
}
return NULL;
}
else {
const char *home= getenv("XDG_CONFIG_HOME");
if (home) {
snprintf(user_path, sizeof(user_path), "%s/blender/%s", home, versionstr);
}
else {
home= getenv("HOME");
if (home == NULL)
home= getpwuid(getuid())->pw_dir;
snprintf(user_path, sizeof(user_path), "%s/.config/blender/%s", home, versionstr);
}
snprintf(user_path, sizeof(user_path), "%s/.config", home);
return (const GHOST_TUns8 *)user_path;
}
#endif /* WITH_XDG_USER_DIRS */
}
const GHOST_TUns8 *GHOST_SystemPathsX11::getBinaryDir() const

@ -52,17 +52,17 @@ public:
/**
* Determine the base dir in which shared resources are located. It will first try to use
* "unpack and run" path, then look for properly installed path, not including versioning.
* "unpack and run" path, then look for properly installed path, including versioning.
* @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
*/
const GHOST_TUns8 *getSystemDir() const;
const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const;
/**
* Determine the base dir in which user configuration is stored, not including versioning.
* Determine the base dir in which user configuration is stored, including versioning.
* If needed, it will create the base directory.
* @return Unsigned char string pointing to user dir (eg ~/.blender/).
*/
const GHOST_TUns8 *getUserDir() const;
const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
/**
* Determine the directory of the current binary

@ -157,10 +157,6 @@ if(WITH_OPENMP)
add_definitions(-DPARALLEL=1)
endif()
if(WITH_XDG_USER_DIRS)
add_definitions(-DWITH_XDG_USER_DIRS)
endif()
if(WIN32)
list(APPEND INC
../../../intern/utfconv

@ -77,22 +77,6 @@
# endif
#endif /* WIN32 */
/* standard paths */
#ifdef WIN32
# define BLENDER_USER_FORMAT "%s\\Blender Foundation\\Blender\\%s"
# define BLENDER_SYSTEM_FORMAT "%s\\Blender Foundation\\Blender\\%s"
#elif defined(__APPLE__)
# define BLENDER_USER_FORMAT "%s/Blender/%s"
# define BLENDER_SYSTEM_FORMAT "%s/Blender/%s"
#else /* UNIX */
# ifndef WITH_XDG_USER_DIRS /* oldschool unix ~/.blender/ */
# define BLENDER_USER_FORMAT "%s/.blender/%s"
# else /* new XDG ~/blender/.config/ */
# define BLENDER_USER_FORMAT "%s/blender/%s"
# endif // WITH_XDG_USER_DIRS
# define BLENDER_SYSTEM_FORMAT "%s/blender/%s"
#endif
/* local */
#define UNIQUE_NAME_MAX 128
@ -822,16 +806,12 @@ void BLI_getlastdir(const char *dir, char *last, const size_t maxlen)
const char *BLI_getDefaultDocumentFolder(void)
{
#ifndef WIN32
const char *xdg_documents_dir= getenv("XDG_DOCUMENTS_DIR");
#ifdef WITH_XDG_USER_DIRS
const char *xdg_documents_dir = getenv("XDG_DOCUMENTS_DIR");
if (xdg_documents_dir) {
if (xdg_documents_dir)
return xdg_documents_dir;
}
#endif
return getenv("HOME");
#else /* Windows */
static char documentfolder[MAXPATHLEN];
HRESULT hResult;
@ -969,10 +949,9 @@ static int get_path_user(char *targetpath, const char *folder_name, const char *
}
}
user_base_path = (const char *)GHOST_getUserDir();
if (user_base_path) {
BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal(ver));
}
user_base_path = (const char *)GHOST_getUserDir(ver, blender_version_decimal(ver));
if (user_base_path)
BLI_strncpy(user_path, user_base_path, FILE_MAX);
if (!user_path[0])
return 0;
@ -1040,10 +1019,9 @@ static int get_path_system(char *targetpath, const char *folder_name, const char
}
}
system_base_path = (const char *)GHOST_getSystemDir();
if (system_base_path) {
BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal(ver));
}
system_base_path = (const char *)GHOST_getSystemDir(ver, blender_version_decimal(ver));
if (system_base_path)
BLI_strncpy(system_path, system_base_path, FILE_MAX);
if (!system_path[0])
return 0;