From 254c4e5f50615b6ee607ec2964d2d7d9cc41d475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 20 Sep 2022 19:40:32 +0800 Subject: [PATCH] WMTheme: support macOS --- README.md | 2 +- src/modules/wmtheme.c | 83 +++++++++++++++++++++++++++++++++++++++++++ src/util/FFstrbuf.c | 8 +++++ src/util/FFstrbuf.h | 1 + 4 files changed, 93 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 71f71e98e..a6fb617ed 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ The following libraries are used if present at runtime: * [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font. * [`libsqlite3`](https://www.sqlite.org/index.html): Needed for pkg & rpm package count. * [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE. -* [`libplist`](https://github.com/libimobiledevice/libplist): Binary `plist` file parser. Needed for iTerm2 Terminal font. +* [`libplist`](https://github.com/libimobiledevice/libplist): Binary `plist` file parser ( macOS ). Needed for iTerm2 Terminal font and WM Theme. ## Support status All categories not listed here should work without needing a specific implementation. diff --git a/src/modules/wmtheme.c b/src/modules/wmtheme.c index fbaf22512..8e422e672 100644 --- a/src/modules/wmtheme.c +++ b/src/modules/wmtheme.c @@ -229,6 +229,87 @@ static void printOpenbox(FFinstance* instance, const FFstrbuf* dePrettyName) ffStrbufDestroy(&absolutePath); } +#ifdef FF_HAVE_LIBPLIST +#include "common/library.h" +#include "common/io.h" +#include + +static const char* quartzCompositorParsePlist(FFinstance* instance, const FFstrbuf* content, FFstrbuf* theme) { + FF_LIBRARY_LOAD(libplist, &instance->config.libplist, "dlopen libplist failed", "libplist-2.0"FF_LIBRARY_EXTENSION, 2); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_is_binary); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_from_bin); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_from_xml); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_dict_get_item); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_get_string_ptr); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_get_uint_val); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_free); + + plist_t root_node = NULL; + if (ffplist_is_binary(content->chars, content->length)) + ffplist_from_bin(content->chars, content->length, &root_node); + else + ffplist_from_xml(content->chars, content->length, &root_node); + + if(root_node == NULL) + return "parsing Quartz Compositor preference file failed"; + + plist_t pWmThemeColor = ffplist_dict_get_item(root_node, "AppleAccentColor"); + uint64_t wmThemeColor = 100; + if (pWmThemeColor != NULL) + ffplist_get_uint_val(pWmThemeColor, &wmThemeColor); + switch (wmThemeColor) + { + case (uint64_t)-1: ffStrbufAppendS(theme, " (Graphite)"); + case 0: ffStrbufAppendS(theme, "Red"); break; + case 1: ffStrbufAppendS(theme, "Orange"); break; + case 2: ffStrbufAppendS(theme, "Yellow"); break; + case 3: ffStrbufAppendS(theme, "Green"); break; + case 5: ffStrbufAppendS(theme, "Purple"); break; + case 6: ffStrbufAppendS(theme, "Pink"); break; + default: ffStrbufAppendS(theme, "Blue"); break; + } + + plist_t pWmTheme = ffplist_dict_get_item(root_node, "AppleInterfaceStyle"); + ffStrbufAppendF(theme, " (%s)", pWmTheme != NULL ? ffplist_get_string_ptr(pWmTheme, NULL) : "Light"); + + ffplist_free(root_node); + return NULL; +} + +static void printQuartzCompositor(FFinstance* instance) { + FFstrbuf fileName; + ffStrbufInitS(&fileName, instance->state.passwd->pw_dir); + ffStrbufAppendS(&fileName, "/Library/Preferences/.GlobalPreferences.plist"); + + FFstrbuf content; + ffStrbufInit(&content); + ffAppendFileBuffer(fileName.chars, &content); + ffStrbufDestroy(&fileName); + if(content.length == 0) + { + ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "reading Quartz Compositor preference file failed"); + ffStrbufDestroy(&content); + return; + } + + FFstrbuf theme; + ffStrbufInit(&theme); + const char* error = quartzCompositorParsePlist(instance, &content, &theme); + ffStrbufDestroy(&content); + + if(error != NULL) + ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "%s", error); + else + printWMTheme(instance, theme.chars); +} +#else +static void printQuartzCompositor(FFinstance* instance) +{ + FF_UNUSED(instance); + ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "Fastfetch was compiled without libplist support"); +} +#endif + void ffPrintWMTheme(FFinstance* instance) { #ifdef __ANDROID__ @@ -261,6 +342,8 @@ void ffPrintWMTheme(FFinstance* instance) printWMThemeFromSettings(instance, "/org/mate/Marco/general/theme", "org.mate.Marco.general", NULL, "theme"); else if(ffStrbufIgnCaseCompS(&result->wmPrettyName, "Openbox") == 0) printOpenbox(instance, &result->dePrettyName); + else if(ffStrbufIgnCaseCompS(&result->wmPrettyName, "Quartz Compositor") == 0) + printQuartzCompositor(instance); else ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "Unknown WM: %s", result->wmPrettyName.chars); } diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index 430fca127..4748b0c3a 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -29,6 +29,14 @@ void ffStrbufInitCopy(FFstrbuf* strbuf, const FFstrbuf* src) ffStrbufAppend(strbuf, src); } +void ffStrbufInitS(FFstrbuf* strbuf, const char* str) +{ + uint32_t bufSize = (uint32_t)strlen(str) + 1; + ffStrbufInitA(strbuf, FASTFETCH_STRBUF_DEFAULT_ALLOC > bufSize ? FASTFETCH_STRBUF_DEFAULT_ALLOC : bufSize); + memcpy(strbuf->chars, str, bufSize); + strbuf->length = bufSize - 1; +} + uint32_t ffStrbufGetFree(const FFstrbuf* strbuf) { if(strbuf->allocated == 0) diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 0c0b9020b..2242d4ec8 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -24,6 +24,7 @@ typedef struct FFstrbuf void ffStrbufInit(FFstrbuf* strbuf); void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate); void ffStrbufInitCopy(FFstrbuf* strbuf, const FFstrbuf* src); +void ffStrbufInitS(FFstrbuf* strbuf, const char* str); void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free);