From 96552dfcb531053f4a331c2c80ecf5d8cb2aaf36 Mon Sep 17 00:00:00 2001
From: 某莔 <seiuryuu@gmail.com>
Date: 周四, 28 12月 2023 22:55:40 +0800
Subject: [PATCH] fix: NSVisualEffectView

---
 src/core/contexts/cocoawindowcontext.mm |   77 +++++++++++++++++++++++++++++++++++++-
 1 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/src/core/contexts/cocoawindowcontext.mm b/src/core/contexts/cocoawindowcontext.mm
index faa75bb..a84e7dd 100644
--- a/src/core/contexts/cocoawindowcontext.mm
+++ b/src/core/contexts/cocoawindowcontext.mm
@@ -118,6 +118,12 @@
 namespace QWK {
 
     struct NSWindowProxy : public QWK_NSWindowDelegate {
+        enum class BlurMode {
+            Dark,
+            Light,
+            None,
+        };
+
         NSWindowProxy(NSWindow *macWindow) {
             nswindow = macWindow;
             g_proxyIndexes->insert(nswindow, this);
@@ -225,6 +231,38 @@
             return {closeBtn, minimizeBtn, zoomBtn};
         }
 
+        void setBlurEffect(BlurMode option) {
+            NSVisualEffectView *effectView = nil;
+            NSView *const view = [nswindow contentView];
+            for (NSView *subview in [[view superview] subviews]) {
+                if ([subview isKindOfClass:visualEffectViewClass]) {
+                    effectView = subview;
+                }
+            }
+            if (effectView == nil) { return; }
+
+            static const auto originalMaterial = effectView.material;
+            static const auto originalBlendingMode = effectView.blendingMode;
+            static const auto originalState = effectView.state;
+
+            if (option == BlurMode::None) {
+                effectView.material = originalMaterial;
+                effectView.blendingMode = originalBlendingMode;
+                effectView.state = originalState;
+            } else {
+                effectView.material = NSVisualEffectMaterialUnderWindowBackground;
+                effectView.blendingMode = NSVisualEffectBlendingModeBehindWindow;
+                effectView.state = NSVisualEffectStateFollowsWindowActiveState;
+
+                // if (option == BlurMode::Dark) {
+                //     view.appearance = [NSAppearance appearanceNamed:@"NSAppearanceNameVibrantDark"];
+                // } else {
+                //     view.appearance =
+                //         [NSAppearance appearanceNamed:@"NSAppearanceNameVibrantLight"];
+                // }
+            }
+        }
+
         void setSystemTitleBarVisible(const bool visible) {
             NSView *nsview = [nswindow contentView];
             if (!nsview) {
@@ -311,6 +349,10 @@
             windowObserver = nil;
         }
 
+        static inline const Class windowClass = [NSWindow class];
+
+        static inline const Class visualEffectViewClass = NSClassFromString(@"NSVisualEffectView");
+
     protected:
         static BOOL canBecomeKeyWindow(id obj, SEL sel) {
             if (g_proxyIndexes->contains(reinterpret_cast<NSWindow *>(obj))) {
@@ -376,8 +418,6 @@
             }
 #endif
         }
-
-        static inline const Class windowClass = [NSWindow class];
 
     private:
         Q_DISABLE_COPY(NSWindowProxy)
@@ -622,6 +662,39 @@
             ensureWindowProxy(windowId)->setSystemButtonVisible(!attribute.toBool());
             return true;
         }
+
+        if (key == QStringLiteral("blur-effect")) {
+            // Class not available
+            if (!NSWindowProxy::visualEffectViewClass) {
+                return false;
+            }
+
+            auto option = NSWindowProxy::BlurMode::None;
+            if (attribute.type() == QVariant::Bool) {
+                if (attribute.toBool()) {
+                    NSString *osxMode =
+                        [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
+                    option = [osxMode isEqualToString:@"Dark"] ? NSWindowProxy::BlurMode::Dark
+                                                               : NSWindowProxy::BlurMode::Light;
+                }
+            } else if (attribute.type() == QVariant::String) {
+                auto value = attribute.toString();
+                if (value == QStringLiteral("dark")) {
+                    option = NSWindowProxy::BlurMode::Dark;
+                } else if (value == QStringLiteral("light")) {
+                    option = NSWindowProxy::BlurMode::Light;
+                } else if (value == QStringLiteral("none")) {
+                    // ...
+                } else {
+                    return false;
+                }
+            } else {
+                return false;
+            }
+            ensureWindowProxy(windowId)->setBlurEffect(option);
+            return true;
+        }
+
         return false;
     }
 

--
Gitblit v1.9.1