feat(macos/tray): allow tray icon paths to be set at runtime from .app bundle (#4711)
This commit is contained in:
@@ -23,7 +23,9 @@
|
||||
#define TRAY_ICON_PLAYING WEB_DIR "images/sunshine-playing-16.png"
|
||||
#define TRAY_ICON_PAUSING WEB_DIR "images/sunshine-pausing-16.png"
|
||||
#define TRAY_ICON_LOCKED WEB_DIR "images/sunshine-locked-16.png"
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <dispatch/dispatch.h>
|
||||
#include <unordered_map>
|
||||
#endif
|
||||
|
||||
// standard includes
|
||||
@@ -127,6 +129,58 @@ namespace system_tray {
|
||||
.allIconPaths = {TRAY_ICON, TRAY_ICON_LOCKED, TRAY_ICON_PLAYING, TRAY_ICON_PAUSING},
|
||||
};
|
||||
|
||||
const char *GetResourcePath(const char *relativePath) {
|
||||
#ifdef __APPLE__
|
||||
if (!relativePath || !*relativePath) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Simple cache ensures our string pointers live forever
|
||||
static std::unordered_map<std::string, std::string> g_cache;
|
||||
auto search = g_cache.find(relativePath);
|
||||
if (search != g_cache.end()) {
|
||||
return search->second.c_str();
|
||||
}
|
||||
|
||||
// If we're running from an .app bundle, get the internal Resources dir
|
||||
CFBundleRef bundle = CFBundleGetMainBundle();
|
||||
if (!bundle) {
|
||||
return relativePath;
|
||||
}
|
||||
|
||||
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
|
||||
if (!resourcesURL) {
|
||||
return relativePath;
|
||||
}
|
||||
|
||||
char resourcesPath[PATH_MAX];
|
||||
bool ok = CFURLGetFileSystemRepresentation(
|
||||
resourcesURL,
|
||||
true,
|
||||
reinterpret_cast<UInt8 *>(resourcesPath),
|
||||
sizeof(resourcesPath)
|
||||
);
|
||||
CFRelease(resourcesURL);
|
||||
if (!ok) {
|
||||
return relativePath;
|
||||
}
|
||||
|
||||
std::string full;
|
||||
if (relativePath && relativePath[0] == '/') {
|
||||
full = relativePath;
|
||||
} else {
|
||||
full = std::string(resourcesPath) + "/" + relativePath;
|
||||
}
|
||||
|
||||
BOOST_LOG(debug) << "System Tray: using " << full << " for icon path";
|
||||
|
||||
auto [it, inserted] = g_cache.emplace(relativePath, std::move(full));
|
||||
return it->second.c_str();
|
||||
#else
|
||||
return relativePath;
|
||||
#endif
|
||||
}
|
||||
|
||||
int init_tray() {
|
||||
#ifdef _WIN32
|
||||
// If we're running as SYSTEM, Explorer.exe will not have permission to open our thread handle
|
||||
@@ -190,6 +244,16 @@ namespace system_tray {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
// if these icon paths are relative, resolve to internal .app Resources path
|
||||
tray.allIconPaths[0] = GetResourcePath(TRAY_ICON);
|
||||
tray.allIconPaths[1] = GetResourcePath(TRAY_ICON_LOCKED);
|
||||
tray.allIconPaths[2] = GetResourcePath(TRAY_ICON_PLAYING);
|
||||
tray.allIconPaths[3] = GetResourcePath(TRAY_ICON_PAUSING);
|
||||
|
||||
tray.icon = tray.allIconPaths[0];
|
||||
#endif
|
||||
|
||||
if (tray_init(&tray) < 0) {
|
||||
BOOST_LOG(warning) << "Failed to create system tray"sv;
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user