Mercurial > minori
diff src/sys/osx/dark_theme.cc @ 194:8548dc425697
sys/osx: remove all objective-c++ stuff
mmmm :)
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Thu, 07 Dec 2023 03:17:05 -0500 |
parents | |
children | 975a3f0965e2 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sys/osx/dark_theme.cc Thu Dec 07 03:17:05 2023 -0500 @@ -0,0 +1,133 @@ +#include "sys/osx/dark_theme.h" + +#include <objc/runtime.h> +#include <objc/message.h> + +#include <CoreFoundation/CoreFoundation.h> +#include <AvailabilityMacros.h> + +#include <QOperatingSystemVersion> + +namespace osx { + +typedef id (*object_message_send)(id, SEL, ...); +typedef id (*class_message_send)(Class, SEL, ...); + +static const object_message_send obj_send = reinterpret_cast<object_message_send>(objc_msgSend); +static const class_message_send cls_send = reinterpret_cast<class_message_send>(objc_msgSend); + +static CFStringRef NSAppearanceNameAqua = nullptr; +static CFStringRef NSAppearanceNameDarkAqua = nullptr; + +static const CFStringRef kLaunchServicesBundleID = CFSTR("com.apple.AppKit"); + +bool RetrieveAppearanceNames() { + CFBundleRef appkit_bundle = CFBundleGetBundleWithIdentifier(kLaunchServicesBundleID); + if (!appkit_bundle) + return false; + + NSAppearanceNameAqua = *reinterpret_cast<CFStringRef*>(CFBundleGetDataPointerForName(appkit_bundle, CFSTR("NSAppearanceNameAqua"))); + if (!NSAppearanceNameAqua) + return false; + + NSAppearanceNameDarkAqua = *reinterpret_cast<CFStringRef*>(CFBundleGetDataPointerForName(appkit_bundle, CFSTR("NSAppearanceNameDarkAqua"))); + if (!NSAppearanceNameDarkAqua) + return false; + + return true; +} + +bool DarkThemeAvailable() { + return (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave); +} + +bool IsInDarkTheme() { + if (!DarkThemeAvailable()) + return false; + + if (!NSAppearanceNameAqua || !NSAppearanceNameDarkAqua) + if (!RetrieveAppearanceNames()) + return false; + + CFArrayRef array = []() -> CFArrayRef { + CFStringRef refs[] = {NSAppearanceNameAqua, NSAppearanceNameDarkAqua}; + return CFArrayCreate(NULL, reinterpret_cast<const void**>(refs), 2, &kCFTypeArrayCallBacks); + }(); + + // NSApplication* app = [NSApplication sharedApplication]; + const id app = cls_send(objc_getClass("NSApplication"), sel_getUid("sharedApplication")); + + // NSAppearance* effectiveAppearance = [app effectiveAppearance]; + const id effectiveAppearance = obj_send(app, sel_getUid("effectiveAppearance")); + if (!effectiveAppearance) { + CFRelease(array); + return false; + } + + // NSAppearance* appearance = [effectiveAppearance bestMatchFromAppearancesWithNames: array]; + const id appearance = obj_send(effectiveAppearance, sel_getUid("bestMatchFromAppearancesWithNames:"), array); + + CFRelease(array); + + if (!appearance) + return false; + + return CFEqual(appearance, NSAppearanceNameDarkAqua); +} + +bool SetToDarkTheme() { + // https://stackoverflow.com/questions/55925862/how-can-i-set-my-os-x-application-theme-in-code + if (!DarkThemeAvailable()) + return false; + + if (!NSAppearanceNameAqua || !NSAppearanceNameDarkAqua) + if (!RetrieveAppearanceNames()) + return false; + + // NSApplication* app = [NSApplication sharedApplication]; + const id app = cls_send(objc_getClass("NSApplication"), sel_getUid("sharedApplication")); + + // NSAppearance* appearance = [NSAppearance appearanceNamed: NSAppearanceNameDarkAqua]; + const id appearance = cls_send(objc_getClass("NSAppearance"), sel_getUid("appearanceNamed:"), NSAppearanceNameDarkAqua); + if (!appearance) + return false; + + // [app setAppearance: appearance]; + obj_send(app, sel_getUid("setAppearance:"), appearance); + return true; +} + +bool SetToLightTheme() { + // https://stackoverflow.com/questions/55925862/how-can-i-set-my-os-x-application-theme-in-code + if (!DarkThemeAvailable()) + return false; + + if (!NSAppearanceNameAqua || !NSAppearanceNameDarkAqua) + if (!RetrieveAppearanceNames()) + return false; + + // NSApplication* app = [NSApplication sharedApplication]; + const id app = cls_send(objc_getClass("NSApplication"), sel_getUid("sharedApplication")); + + // NSAppearance* appearance = [NSAppearance appearanceNamed: NSAppearanceNameDarkAqua]; + const id appearance = cls_send(objc_getClass("NSAppearance"), sel_getUid("appearanceNamed:"), NSAppearanceNameAqua); + if (!appearance) + return false; + + // [app setAppearance: appearance]; + obj_send(app, sel_getUid("setAppearance:"), appearance); + return true; +} + +void SetToAutoTheme() { + if (!DarkThemeAvailable()) + return; + + // NSApplication* app = [NSApplication sharedApplication]; + const id app = cls_send(objc_getClass("NSApplication"), sel_getUid("sharedApplication")); + + // [app setAppearance: null]; + obj_send(app, sel_getUid("setAppearance:"), nullptr); +} + +} // namespace osx