SineStriker
2023-12-28 5bfd136473edc506b860177bf88626e35a5a1ba4
Add mac blur view
4个文件已修改
160 ■■■■■ 已修改文件
examples/mainwindow/mainwindow.cpp 58 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/contexts/cocoawindowcontext.mm 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/windowagentbase.cpp 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/widgets/widgetwindowagent_mac.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/mainwindow/mainwindow.cpp
@@ -140,7 +140,7 @@
#ifdef Q_OS_WIN
        auto dwmBlurAction = new QAction(tr("Enable DWM blur"), menuBar);
        dwmBlurAction->setCheckable(true);
        connect(dwmBlurAction, &QAction::triggered, this, [this](bool checked) {
        connect(dwmBlurAction, &QAction::toggled, this, [this](bool checked) {
            if (!windowAgent->setWindowAttribute(QStringLiteral("dwm-blur"), checked)) {
                return;
            }
@@ -150,7 +150,7 @@
        auto acrylicAction = new QAction(tr("Enable acrylic material"), menuBar);
        acrylicAction->setCheckable(true);
        connect(acrylicAction, &QAction::triggered, this, [this](bool checked) {
        connect(acrylicAction, &QAction::toggled, this, [this](bool checked) {
            if (!windowAgent->setWindowAttribute(QStringLiteral("acrylic-material"), true)) {
                return;
            }
@@ -160,7 +160,7 @@
        auto micaAction = new QAction(tr("Enable mica"), menuBar);
        micaAction->setCheckable(true);
        connect(micaAction, &QAction::triggered, this, [this](bool checked) {
        connect(micaAction, &QAction::toggled, this, [this](bool checked) {
            if (!windowAgent->setWindowAttribute(QStringLiteral("mica"), checked)) {
                return;
            }
@@ -170,30 +170,70 @@
        auto micaAltAction = new QAction(tr("Enable mica alt"), menuBar);
        micaAltAction->setCheckable(true);
        connect(micaAltAction, &QAction::triggered, this, [this](bool checked) {
        connect(micaAltAction, &QAction::toggled, this, [this](bool checked) {
            if (!windowAgent->setWindowAttribute(QStringLiteral("mica-alt"), checked)) {
                return;
            }
            setProperty("custom-style", checked);
            style()->polish(this);
        });
#elif defined(Q_OS_MAC)
        auto darkBlurAction = new QAction(tr("Dark blur"), menuBar);
        darkBlurAction->setCheckable(true);
        connect(darkBlurAction, &QAction::toggled, this, [this](bool checked) {
            if (!windowAgent->setWindowAttribute(QStringLiteral("blur-effect"), "dark")) {
                return;
            }
            if (checked) {
                setProperty("custom-style", true);
                style()->polish(this);
            }
        });
        auto winStyleGroup = new QActionGroup(menuBar);
        winStyleGroup->addAction(dwmBlurAction);
        winStyleGroup->addAction(acrylicAction);
        winStyleGroup->addAction(micaAction);
        winStyleGroup->addAction(micaAltAction);
        auto lightBlurAction = new QAction(tr("Light blur"), menuBar);
        lightBlurAction->setCheckable(true);
        connect(lightBlurAction, &QAction::toggled, this, [this](bool checked) {
            if (!windowAgent->setWindowAttribute(QStringLiteral("blur-effect"), "light")) {
                return;
            }
            if (checked) {
                setProperty("custom-style", true);
                style()->polish(this);
            }
        });
        auto noBlurAction = new QAction(tr("No blur"), menuBar);
        noBlurAction->setCheckable(true);
        connect(noBlurAction, &QAction::toggled, this, [this](bool checked) {
            if (!windowAgent->setWindowAttribute(QStringLiteral("blur-effect"), "none")) {
                return;
            }
            if (checked) {
                setProperty("custom-style", false);
                style()->polish(this);
            }
        });
        auto macStyleGroup = new QActionGroup(menuBar);
        macStyleGroup->addAction(darkBlurAction);
        macStyleGroup->addAction(lightBlurAction);
        macStyleGroup->addAction(noBlurAction);
#endif
        // Real menu
        auto settings = new QMenu(tr("Settings(&S)"), menuBar);
        settings->addAction(darkAction);
#ifdef Q_OS_WIN
        settings->addSeparator();
        settings->addAction(dwmBlurAction);
        settings->addAction(acrylicAction);
        settings->addAction(micaAction);
        settings->addAction(micaAltAction);
#elif defined(Q_OS_MAC)
        settings->addAction(darkBlurAction);
        settings->addAction(lightBlurAction);
        settings->addAction(noBlurAction);
#endif
        menuBar->addMenu(file);
src/core/contexts/cocoawindowcontext.mm
@@ -118,12 +118,21 @@
namespace QWK {
    struct NSWindowProxy : public QWK_NSWindowDelegate {
        enum class BlurMode {
            Dark,
            Light,
            None,
        };
        NSWindowProxy(NSWindow *macWindow) {
            nswindow = macWindow;
            g_proxyIndexes->insert(nswindow, this);
        }
        ~NSWindowProxy() override {
            if (blurEffect) {
                setBlurEffect(BlurMode::None);
            }
            g_proxyIndexes->remove(nswindow);
        }
@@ -155,6 +164,10 @@
        }
        void windowDidResize() override {
            if (blurEffect) {
                updateBlurEffectSize();
            }
            if (systemButtonRect.isEmpty() || !systemButtonVisible) {
                return;
            }
@@ -223,6 +236,47 @@
            NSButton *minimizeBtn = [nswindow standardWindowButton:NSWindowMiniaturizeButton];
            NSButton *zoomBtn = [nswindow standardWindowButton:NSWindowZoomButton];
            return {closeBtn, minimizeBtn, zoomBtn};
        }
        void setBlurEffect(BlurMode option) {
            if (option == BlurMode::None) {
                if (!blurEffect) {
                    return;
                }
                [blurEffect removeFromSuperview];
                [blurEffect release];
                blurEffect = nil;
            } else {
                if (!blurEffect) {
                    NSView *const view = [nswindow contentView];
                    NSVisualEffectView *const blurView =
                        [[visualEffectViewClass alloc] initWithFrame:view.bounds];
                    blurView.material = NSVisualEffectMaterialUnderWindowBackground;
                    blurView.blendingMode = NSVisualEffectBlendingModeBehindWindow;
                    blurView.state = NSVisualEffectStateFollowsWindowActiveState;
#if 1
                    const NSView *const parent = [view superview];
                    [parent addSubview:blurView positioned:NSWindowBelow relativeTo:view];
#endif
                    blurEffect = blurView;
                    updateBlurEffectSize();
                }
                auto view = static_cast<const NSVisualEffectView *>(blurEffect);
                if (option == BlurMode::Dark) {
                    view.appearance = [NSAppearance appearanceNamed:@"NSAppearanceNameVibrantDark"];
                } else {
                    view.appearance =
                        [NSAppearance appearanceNamed:@"NSAppearanceNameVibrantLight"];
                }
            }
        }
        void updateBlurEffectSize() {
            const NSView *const view = [nswindow contentView];
            blurEffect.frame = view.frame;
        }
        void setSystemTitleBarVisible(const bool visible) {
@@ -311,6 +365,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))) {
@@ -377,12 +435,11 @@
#endif
        }
        static inline const Class windowClass = [NSWindow class];
    private:
        Q_DISABLE_COPY(NSWindowProxy)
        NSWindow *nswindow = nil;
        NSView *blurEffect = nil;
        bool systemButtonVisible = true;
        QRect systemButtonRect;
@@ -622,6 +679,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;
    }
src/core/windowagentbase.cpp
@@ -99,7 +99,11 @@
                   internal state.
        On macOS,
            \li \c no-system-buttons: Specify a boolean value to set the system buttons' visibility.
            \li \c no-system-buttons: Specify a boolean value to set the system buttons'
                   visibility.
            \li \c blur-effect: You can specify a string value, "dark" to set dark mode, "light"
                   to set light mode, "none" to disable. You can also specify a boolean value,
                   \c true to enable and set the current theme, \c false to disable.
    */
    bool WindowAgentBase::setWindowAttribute(const QString &key, const QVariant &attribute) {
        Q_D(WindowAgentBase);
src/widgets/widgetwindowagent_mac.cpp
@@ -5,7 +5,7 @@
namespace QWK {
    static inline QRect getWidgetSceneRect(QWidget *widget) {
        return {widget->mapTo(widget->window(), {}), widget->size()};
        return {widget->mapTo(widget->window(), QPoint()), widget->size()};
    }
    class SystemButtonAreaWidgetEventFilter : public QObject {