[Bf-blender-cvs] [6de85a0cc08] master: Ghost: Support queries for special user directories (desktop, documents, etc.)

Julian Eisel noreply at git.blender.org
Fri Dec 11 16:21:11 CET 2020


Commit: 6de85a0cc08da26f63ae0512f19fa5360556c2bd
Author: Julian Eisel
Date:   Fri Dec 11 15:36:29 2020 +0100
Branches: master
https://developer.blender.org/rB6de85a0cc08da26f63ae0512f19fa5360556c2bd

Ghost: Support queries for special user directories (desktop, documents, etc.)

When we had to get special user directories, we'd usually do it in varying,
rather ad-hoc ways. It would be done with a bunch of `#ifdef`s for the
different operating systems. Also, some of the used Win32 functions were legacy
ones and the API docs recommend using newer ones.
Further, seems `BKE_appdir_folder_default()` used `XDG_DOCUMENTS_DIR` wrong.
It's not supposed to be an environment variable but a value inside a config
file.

This adds the platform dependent logic to Ghost, so we can abstract it away
nicely using the `GHOST_ISystemPaths` interface. Getting the desktop directory
for example can now easily be done with:
`GHOST_getUserSpecialDir(GHOST_kUserSpecialDirDesktop).`

For now I added the logic for desktop, documents, downloads, videos, images and
music directories, even though we only use the Documents one. We can extend/
change this as needed, it's easy to do now.
On Windows and macOS, it uses pretty much the same way to access the
directories as elsewhere already. On Linux, it uses the `xdg-user-dir` command
that seems to be available by default on most Linux systems.

No functional changes. The new queries are not actually used yet.

Differential Revision: https://developer.blender.org/D9800

Reviewed by: Brecht Van Lommel

===================================================================

M	intern/ghost/GHOST_ISystemPaths.h
M	intern/ghost/GHOST_Path-api.h
M	intern/ghost/GHOST_Types.h
M	intern/ghost/intern/GHOST_Path-api.cpp
M	intern/ghost/intern/GHOST_SystemPathsCocoa.h
M	intern/ghost/intern/GHOST_SystemPathsCocoa.mm
M	intern/ghost/intern/GHOST_SystemPathsUnix.cpp
M	intern/ghost/intern/GHOST_SystemPathsUnix.h
M	intern/ghost/intern/GHOST_SystemPathsWin32.cpp
M	intern/ghost/intern/GHOST_SystemPathsWin32.h

===================================================================

diff --git a/intern/ghost/GHOST_ISystemPaths.h b/intern/ghost/GHOST_ISystemPaths.h
index b47d14984d8..e7ac752d322 100644
--- a/intern/ghost/GHOST_ISystemPaths.h
+++ b/intern/ghost/GHOST_ISystemPaths.h
@@ -77,6 +77,12 @@ class GHOST_ISystemPaths {
    */
   virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const = 0;
 
+  /**
+   * Determine a special ("well known") and easy to reach user directory.
+   * \return Unsigned char string pointing to user dir (eg `~/Documents/`).
+   */
+  virtual const GHOST_TUns8 *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const = 0;
+
   /**
    * Determine the directory of the current binary
    * \return Unsigned char string pointing to the binary dir
diff --git a/intern/ghost/GHOST_Path-api.h b/intern/ghost/GHOST_Path-api.h
index 4cc232be6b6..36ea70838ca 100644
--- a/intern/ghost/GHOST_Path-api.h
+++ b/intern/ghost/GHOST_Path-api.h
@@ -56,6 +56,12 @@ extern const GHOST_TUns8 *GHOST_getSystemDir(int version, const char *versionstr
  */
 extern const GHOST_TUns8 *GHOST_getUserDir(int version, const char *versionstr);
 
+/**
+ * Determine a special ("well known") and easy to reach user directory.
+ * \return Unsigned char string pointing to user dir (eg `~/Documents/`).
+ */
+extern const GHOST_TUns8 *GHOST_getUserSpecialDir(GHOST_TUserSpecialDirTypes type);
+
 /**
  * Determine the dir in which the binary file is found.
  * \return Unsigned char string pointing to binary dir (eg ~/usr/local/bin/).
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index a03b59d14b0..8bce064ce63 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -565,6 +565,16 @@ typedef struct {
   char is_repeat;
 } GHOST_TEventKeyData;
 
+typedef enum {
+  GHOST_kUserSpecialDirDesktop,
+  GHOST_kUserSpecialDirDocuments,
+  GHOST_kUserSpecialDirDownloads,
+  GHOST_kUserSpecialDirMusic,
+  GHOST_kUserSpecialDirPictures,
+  GHOST_kUserSpecialDirVideos,
+  /* Can be extended as needed. */
+} GHOST_TUserSpecialDirTypes;
+
 typedef struct {
   /** Number of pixels on a line. */
   GHOST_TUns32 xPixels;
diff --git a/intern/ghost/intern/GHOST_Path-api.cpp b/intern/ghost/intern/GHOST_Path-api.cpp
index df3592fb5e5..c82e9819f3c 100644
--- a/intern/ghost/intern/GHOST_Path-api.cpp
+++ b/intern/ghost/intern/GHOST_Path-api.cpp
@@ -50,6 +50,12 @@ const GHOST_TUns8 *GHOST_getUserDir(int version, const char *versionstr)
   return systemPaths ? systemPaths->getUserDir(version, versionstr) : NULL; /* shouldn't be NULL */
 }
 
+const GHOST_TUns8 *GHOST_getUserSpecialDir(GHOST_TUserSpecialDirTypes type)
+{
+  GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
+  return systemPaths ? systemPaths->getUserSpecialDir(type) : NULL; /* shouldn't be NULL */
+}
+
 const GHOST_TUns8 *GHOST_getBinaryDir()
 {
   GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.h b/intern/ghost/intern/GHOST_SystemPathsCocoa.h
index 188f6f02286..14633d46f03 100644
--- a/intern/ghost/intern/GHOST_SystemPathsCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.h
@@ -55,6 +55,12 @@ class GHOST_SystemPathsCocoa : public GHOST_SystemPaths {
    */
   const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
 
+  /**
+   * Determine a special ("well known") and easy to reach user directory.
+   * \return Unsigned char string pointing to user dir (eg `~/Documents/`).
+   */
+  const GHOST_TUns8 *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const;
+
   /**
    * Determine the directory of the current binary
    * \return Unsigned char string pointing to the binary dir
diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.mm b/intern/ghost/intern/GHOST_SystemPathsCocoa.mm
index 830d58ba42c..7c6184837bf 100644
--- a/intern/ghost/intern/GHOST_SystemPathsCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.mm
@@ -21,6 +21,7 @@
 
 #import <Foundation/Foundation.h>
 
+#include "GHOST_Debug.h"
 #include "GHOST_SystemPathsCocoa.h"
 
 #pragma mark initialization/finalization
@@ -89,6 +90,57 @@ const GHOST_TUns8 *GHOST_SystemPathsCocoa::getUserDir(int, const char *versionst
   return (GHOST_TUns8 *)tempPath;
 }
 
+const GHOST_TUns8 *GHOST_SystemPathsCocoa::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const
+{
+  static char tempPath[512] = "";
+  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+  NSString *basePath;
+  NSArray *paths;
+  NSSearchPathDirectory ns_directory;
+
+  switch (type) {
+    case GHOST_kUserSpecialDirDesktop:
+      ns_directory = NSDesktopDirectory;
+      break;
+    case GHOST_kUserSpecialDirDocuments:
+      ns_directory = NSDocumentDirectory;
+      break;
+    case GHOST_kUserSpecialDirDownloads:
+      ns_directory = NSDownloadsDirectory;
+      break;
+    case GHOST_kUserSpecialDirMusic:
+      ns_directory = NSMusicDirectory;
+      break;
+    case GHOST_kUserSpecialDirPictures:
+      ns_directory = NSPicturesDirectory;
+      break;
+    case GHOST_kUserSpecialDirVideos:
+      ns_directory = NSMoviesDirectory;
+      break;
+    default:
+      GHOST_ASSERT(
+          false,
+          "GHOST_SystemPathsCocoa::getUserSpecialDir(): Invalid enum value for type parameter");
+      [pool drain];
+      return NULL;
+  }
+
+  paths = NSSearchPathForDirectoriesInDomains(ns_directory, NSUserDomainMask, YES);
+
+  if ([paths count] > 0)
+    basePath = [paths objectAtIndex:0];
+  else {
+    [pool drain];
+    return NULL;
+  }
+
+  strncpy(
+      (char *)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding], sizeof(tempPath));
+
+  [pool drain];
+  return (GHOST_TUns8 *)tempPath;
+}
+
 const GHOST_TUns8 *GHOST_SystemPathsCocoa::getBinaryDir() const
 {
   static GHOST_TUns8 tempPath[512] = "";
diff --git a/intern/ghost/intern/GHOST_SystemPathsUnix.cpp b/intern/ghost/intern/GHOST_SystemPathsUnix.cpp
index ad3d490eb91..16b092a9e5e 100644
--- a/intern/ghost/intern/GHOST_SystemPathsUnix.cpp
+++ b/intern/ghost/intern/GHOST_SystemPathsUnix.cpp
@@ -21,6 +21,9 @@
  * \ingroup GHOST
  */
 
+#include <cstdio>
+#include <sstream>
+
 #include "GHOST_SystemPathsUnix.h"
 
 #include "GHOST_Debug.h"
@@ -108,6 +111,61 @@ const GHOST_TUns8 *GHOST_SystemPathsUnix::getUserDir(int version, const char *ve
   }
 }
 
+const GHOST_TUns8 *GHOST_SystemPathsUnix::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const
+{
+  const char *type_str;
+
+  switch (type) {
+    case GHOST_kUserSpecialDirDesktop:
+      type_str = "DESKTOP";
+      break;
+    case GHOST_kUserSpecialDirDocuments:
+      type_str = "DOCUMENTS";
+      break;
+    case GHOST_kUserSpecialDirDownloads:
+      type_str = "DOWNLOAD";
+      break;
+    case GHOST_kUserSpecialDirMusic:
+      type_str = "MUSIC";
+      break;
+    case GHOST_kUserSpecialDirPictures:
+      type_str = "PICTURES";
+      break;
+    case GHOST_kUserSpecialDirVideos:
+      type_str = "VIDEOS";
+      break;
+    default:
+      GHOST_ASSERT(
+          false,
+          "GHOST_SystemPathsUnix::getUserSpecialDir(): Invalid enum value for type parameter");
+      return NULL;
+  }
+
+  static string path = "";
+  string command = string("xdg-user-dir ") + type_str;
+
+  FILE *fstream = popen(command.c_str(), "r");
+  if (fstream == NULL) {
+    return NULL;
+  }
+  std::stringstream path_stream;
+  while (!feof(fstream)) {
+    char c = fgetc(fstream);
+    /* xdg-user-dir ends the path with '\n'. */
+    if (c == '\n') {
+        break;
+    }
+    path_stream << c;
+  }
+  if (pclose(fstream) == -1) {
+    perror("GHOST_SystemPathsUnix::getUserSpecialDir failed at pclose()");
+    return NULL;
+  }
+
+  path = path_stream.str();
+  return (const GHOST_TUns8 *)path.c_str();
+}
+
 const GHOST_TUns8 *GHOST_SystemPathsUnix::getBinaryDir() const
 {
   return NULL;
diff --git a/intern/ghost/intern/GHOST_SystemPathsUnix.h b/intern/ghost/intern/GHOST_SystemPathsUnix.h
index 8d2f26a28aa..bc9272ecd8f 100644
--- a/intern/ghost/intern/GHOST_SystemPathsUnix.h
+++ b/intern/ghost/intern/GHOST_SystemPathsUnix.h
@@ -53,6 +53,12 @@ class GHOST_SystemPathsUnix : public GHOST_SystemPaths {
    */
   const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
 
+  /**
+   * Determine a special ("well known") and easy to reach user directory.
+   * \return Unsigned char string pointing to user dir (eg `~/Documents/`).
+   */
+  const GHOST_TUns8 *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const;
+
   /**
    * Determine the directory of the current binary
    * \return Unsigned char string pointing to the binary dir
diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp
index 673cbcad97e..193633b5c3e 100644
--- a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp
@@ -22,6 +22,7 @@
  */
 
 #include "GHOST_SystemPathsWin32.h"
+#include "GHOST_Debug.h"
 
 #ifndef _WIN32_IE
 #  define _WIN32_IE 0x0501
@@ -76,6 +77,50 @@ const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserDir(int, const char *versionst
   return NULL;
 }
 
+const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const
+{
+  GUID folderid;
+
+  switch (type) {
+    case GHOST_kUserSpecialDirDesktop:
+      folderid = FOLDERID_Desktop;
+      break;
+    case GHOST_kUserSpecialDirDocuments:
+      folderid = FOLDERID_Documents;
+      break;
+    case GHOST_kUserSpecialDirDownloads:
+      folderid = FOLDERID_Downloads;
+      break;
+    case GHOST_kUserSpecialDirMusic:
+      folderid = FOLDERID_Music;
+      break;
+    case GHOST_kUserSpecialDirPictures:
+      folderid = FOLDERID_Pictures;
+      break;
+    case GHOST_kUserSpecialDirVideos:
+      folderid = FOLDERID_Videos;
+      break;
+    default:
+      GHOST_ASSERT(
+          false,
+          "GHOST_SystemPathsWin32::getUserSpecialDir(): Invalid enum value for type parameter");
+      return NULL;
+  }
+
+  static char knownpath[MAX_PATH * 3] = {0};
+  PWSTR knownpath_16 = NULL;
+  HRESULT hResult = SHGetKnownFolderPath(folderid, KF_FLAG_DEFAULT, NULL, &knownpath_16);
+
+  if (hResult == S_OK) {
+    conv_utf_16_to_8(knownpath_16, knownpath, MAX_PATH * 3);
+    CoTaskMemFree(knownpath_

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list