From cf713e32e14802511b21b90c4f3d9025d7ac6319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 4 Sep 2025 13:46:18 +0800 Subject: [PATCH] Wallpaper (Linux): improves XFCE wallpaper detection via property enumeration --- src/common/settings.c | 84 ++++++++++++++++++++++++++++++++++++++ src/common/settings.h | 2 + src/detection/gtk_qt/gtk.c | 13 +++--- 3 files changed, 94 insertions(+), 5 deletions(-) diff --git a/src/common/settings.c b/src/common/settings.c index 08f3002b5..26ec35016 100644 --- a/src/common/settings.c +++ b/src/common/settings.c @@ -250,12 +250,96 @@ FFvariant ffSettingsGetXFConf(const char* channelName, const char* propertyName, return FF_VARIANT_NULL; } + +#define FF_DBUS_ITER_CONTINUE(dbus, iterator) \ + { \ + if(!(dbus).lib->ffdbus_message_iter_next(iterator)) \ + break; \ + continue; \ + } + +FFvariant ffSettingsGetXFConfFirstMatch(const char* channelName, const char* propertyPrefix, FFvarianttype type, void* data, FFTestXfconfPropCallback* cb) +{ + FFDBusData dbus; + if (ffDBusLoadData(DBUS_BUS_SESSION, &dbus) != NULL) + return FF_VARIANT_NULL; + + DBusMessage* reply = ffDBusGetMethodReply(&dbus, "org.xfce.Xfconf", "/org/xfce/Xfconf", "org.xfce.Xfconf", "GetAllProperties", channelName, propertyPrefix); + if(!reply) + return FF_VARIANT_NULL; + + DBusMessageIter rootIterator; + if(!dbus.lib->ffdbus_message_iter_init(reply, &rootIterator)) + { + dbus.lib->ffdbus_message_unref(reply); + return FF_VARIANT_NULL; + } + + DBusMessageIter arrayIterator; + dbus.lib->ffdbus_message_iter_recurse(&rootIterator, &arrayIterator); + + while(true) + { + if(dbus.lib->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_DICT_ENTRY) + FF_DBUS_ITER_CONTINUE(dbus, &arrayIterator) + + DBusMessageIter dictIterator; + dbus.lib->ffdbus_message_iter_recurse(&arrayIterator, &dictIterator); + + const char* key; + dbus.lib->ffdbus_message_iter_get_basic(&dictIterator, &key); + + if (cb(data, key)) FF_DBUS_ITER_CONTINUE(dbus, &arrayIterator) + dbus.lib->ffdbus_message_iter_next(&dictIterator); + + if(type == FF_VARIANT_TYPE_INT) + { + int32_t value; + if (ffDBusGetInt(&dbus, &dictIterator, &value)) + { + dbus.lib->ffdbus_message_unref(reply); + return (FFvariant) { .intValue = value }; + } + return FF_VARIANT_NULL; + } + + if(type == FF_VARIANT_TYPE_STRING) + { + FFstrbuf value = ffStrbufCreate(); + if (ffDBusGetString(&dbus, &dictIterator, &value)) + { + dbus.lib->ffdbus_message_unref(reply); + return (FFvariant) { .strValue = value.chars }; // Leaks value.chars + } + return FF_VARIANT_NULL; + } + + if(type == FF_VARIANT_TYPE_BOOL) + { + bool value; + if (ffDBusGetBool(&dbus, &dictIterator, &value)) + { + dbus.lib->ffdbus_message_unref(reply); + return (FFvariant) { .boolValue = value, .boolValueSet = true }; + } + } + + return FF_VARIANT_NULL; + } + + return FF_VARIANT_NULL; +} #else //FF_HAVE_DBUS FFvariant ffSettingsGetXFConf(const char* channelName, const char* propertyName, FFvarianttype type) { FF_UNUSED(channelName, propertyName, type) return FF_VARIANT_NULL; } +FFvariant ffSettingsGetXFConfFirstMatch(const char* channelName, const char* propertyPrefix, FFvarianttype type, void* data, FFTestXfconfPropCallback* cb) +{ + FF_UNUSED(channelName, propertyPrefix, type, data, cb); + return FF_VARIANT_NULL; +} #endif //FF_HAVE_DBUS #ifdef FF_HAVE_SQLITE3 diff --git a/src/common/settings.h b/src/common/settings.h index cfe6d093e..937eeed6b 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -26,6 +26,8 @@ FFvariant ffSettingsGetDConf(const char* key, FFvarianttype type); FFvariant ffSettingsGetGSettings(const char* schemaName, const char* path, const char* key, FFvarianttype type); FFvariant ffSettingsGet(const char* dconfKey, const char* gsettingsSchemaName, const char* gsettingsPath, const char* gsettingsKey, FFvarianttype type); FFvariant ffSettingsGetXFConf(const char* channelName, const char* propertyName, FFvarianttype type); +typedef bool FFTestXfconfPropCallback(void* data, const char* propertyName); // Return false to break loop +FFvariant ffSettingsGetXFConfFirstMatch(const char* channelName, const char* propertyPrefix, FFvarianttype type, void* data, FFTestXfconfPropCallback* cb); int ffSettingsGetSQLite3Int(const char* dbPath, const char* query); bool ffSettingsGetSQLite3String(const char* dbPath, const char* query, FFstrbuf* result); diff --git a/src/detection/gtk_qt/gtk.c b/src/detection/gtk_qt/gtk.c index 9b6b8c6dc..da540bdc2 100644 --- a/src/detection/gtk_qt/gtk.c +++ b/src/detection/gtk_qt/gtk.c @@ -34,6 +34,13 @@ static inline void applyGTKSettings(FFGTKResult* result, const char* themeName, ffStrbufAppendS(&result->wallpaper, wallpaper); } +static bool testXfconfWallpaperPropKey(FF_MAYBE_UNUSED void* data, const char* key) +{ + int count = 0; + sscanf(key, "/backdrop/screen0/monitor%*[^/]/workspace0/last-image%n", &count); + return count == 0; +} + static void detectGTKFromSettings(FFGTKResult* result) { static const char* themeName = NULL; @@ -62,11 +69,7 @@ static void detectGTKFromSettings(FFGTKResult* result) fontName = ffSettingsGetXFConf("xsettings", "/Gtk/FontName", FF_VARIANT_TYPE_STRING).strValue; cursorTheme = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue; cursorSize = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue; - wallpaper = ffSettingsGetXFConf("xfce4-desktop", "/backdrop/screen0/monitor0/workspace0/last-image", FF_VARIANT_TYPE_STRING).strValue; - if (!wallpaper) // FIXME: find a way to enumerate possible properties - wallpaper = ffSettingsGetXFConf("xfce4-desktop", "/backdrop/screen0/monitoreDP-1/workspace0/last-image", FF_VARIANT_TYPE_STRING).strValue; - if (!wallpaper) - wallpaper = ffSettingsGetXFConf("xfce4-desktop", "/backdrop/screen0/monitorbuiltin/workspace0/last-image", FF_VARIANT_TYPE_STRING).strValue; + wallpaper = ffSettingsGetXFConfFirstMatch("xfce4-desktop", "/backdrop/screen0", FF_VARIANT_TYPE_STRING, NULL, testXfconfWallpaperPropKey).strValue; } else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_CINNAMON) == 0) {