diff --git a/CMakeLists.txt b/CMakeLists.txt index 9af54af..48b0d9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,37 +36,21 @@ endif() find_package(QT NAMES Qt6 Qt5 COMPONENTS Gui REQUIRED) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Gui REQUIRED) -find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets) -find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets) find_package(QT NAMES Qt6 Qt5 COMPONENTS Quick) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Quick) set(SOURCES - qtacrylichelper.qrc framelesshelper_global.h framelesswindowsmanager.h framelesswindowsmanager.cpp utilities.h utilities.cpp - qtacryliceffecthelper.h - qtacryliceffecthelper.cpp ) -if(TARGET Qt${QT_VERSION_MAJOR}::Widgets) - list(APPEND SOURCES - qtacrylicwidget.h - qtacrylicwidget.cpp - qtacrylicmainwindow.h - qtacrylicmainwindow.cpp - ) -endif() - if(TARGET Qt${QT_VERSION_MAJOR}::Quick) list(APPEND SOURCES framelessquickhelper.h framelessquickhelper.cpp - qtacrylicitem.h - qtacrylicitem.cpp ) endif() @@ -75,8 +59,6 @@ if(WIN32) utilities_win32.cpp framelesshelper_win32.h framelesshelper_win32.cpp - qtacryliceffecthelper_win32.h - qtacryliceffecthelper_win32.cpp ) else() list(APPEND SOURCES @@ -137,12 +119,6 @@ target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::GuiPrivate ) -if(TARGET Qt${QT_VERSION_MAJOR}::Widgets) - target_link_libraries(${PROJECT_NAME} PRIVATE - Qt${QT_VERSION_MAJOR}::Widgets - ) -endif() - if(TARGET Qt${QT_VERSION_MAJOR}::Quick) target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Quick diff --git a/README.md b/README.md index 3c3dd0d..fd054e8 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,6 @@ If you are using part of or all the code from this repository in your own projec - Support tiled and stack windows by DWM (Win32 only). - Won't cover the task bar when maximized (Win32 only). - Won't block the auto-hide task bar when maximized (Win32 only). -- Support cross-platform blur effect inspired by [Microsoft's Acrylic blur](https://docs.microsoft.com/en-us/windows/uwp/design/style/acrylic). ## Usage diff --git a/README_unix.md b/README_unix.md index 8a8b97e..0071d76 100644 --- a/README_unix.md +++ b/README_unix.md @@ -10,7 +10,6 @@ TODO - Draggable. - Resizable. - Cross-platform: Windows, X11, Wayland, macOS (however, it doesn't look good on Windows, so you may want to try [`FramelessHelperWin`](/framelesshelper_win32.h) instead). -- Support blur effect inspired by [Microsoft's Acrylic blur](https://docs.microsoft.com/en-us/windows/uwp/design/style/acrylic). As for the frame shadow and other window features, they mainly depend on your window manager. diff --git a/README_win32.md b/README_win32.md index 388e62a..05291ad 100644 --- a/README_win32.md +++ b/README_win32.md @@ -14,7 +14,6 @@ - Support tiled and stack windows by DWM. - Won't cover the task bar when maximized. - Won't block the auto-hide task bar when maximized. -- Support blur effect inspired by [Microsoft's Acrylic blur](https://docs.microsoft.com/en-us/windows/uwp/design/style/acrylic). ## Usage diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 72f5e57..d3404dc 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,7 +1,7 @@ -if(TARGET Qt${QT_VERSION_MAJOR}::Widgets) +#if(TARGET Qt${QT_VERSION_MAJOR}::Widgets) add_subdirectory(widget) add_subdirectory(mainwindow) -endif() +#endif() if(TARGET Qt${QT_VERSION_MAJOR}::Quick) add_subdirectory(quick) endif() diff --git a/examples/mainwindow/main.cpp b/examples/mainwindow/main.cpp index e88e838..bb5055a 100644 --- a/examples/mainwindow/main.cpp +++ b/examples/mainwindow/main.cpp @@ -23,12 +23,12 @@ */ #include "../../framelesswindowsmanager.h" -#include "../../qtacrylicmainwindow.h" #include "ui_MainWindow.h" #include "ui_TitleBar.h" #include #include #include +#include #include int main(int argc, char *argv[]) @@ -56,13 +56,12 @@ int main(int argc, char *argv[]) QApplication application(argc, argv); - QtAcrylicMainWindow *mainWindow = new QtAcrylicMainWindow; - mainWindow->setAcrylicEnabled(true); + const auto mainWindow = new QMainWindow; Ui::MainWindow appMainWindow; appMainWindow.setupUi(mainWindow); - QWidget *widget = new QWidget; + const auto widget = new QWidget; Ui::TitleBar titleBarWidget; titleBarWidget.setupUi(widget); @@ -82,11 +81,13 @@ int main(int argc, char *argv[]) mainWindow->showMaximized(); } }); - QObject::connect(mainWindow, &QtAcrylicMainWindow::windowStateChanged, [mainWindow, titleBarWidget](){ +#if 0 + QObject::connect(mainWindow, &QMainWindow::windowStateChanged, [mainWindow, titleBarWidget](){ titleBarWidget.maximizeButton->setChecked(mainWindow->isMaximized()); titleBarWidget.maximizeButton->setToolTip(mainWindow->isMaximized() ? QObject::tr("Restore") : QObject::tr("Maximize")); }); - QObject::connect(titleBarWidget.iconButton, &QPushButton::clicked, mainWindow, &QtAcrylicMainWindow::displaySystemMenu); + QObject::connect(titleBarWidget.iconButton, &QPushButton::clicked, mainWindow, &QMainWindow::displaySystemMenu); +#endif QStyleOption option; option.initFrom(mainWindow); @@ -105,7 +106,6 @@ int main(int argc, char *argv[]) FramelessWindowsManager::addIgnoreObject(win, appMainWindow.menubar); mainWindow->resize(800, 600); - Q_EMIT mainWindow->windowStateChanged(); mainWindow->show(); diff --git a/examples/quick/main.cpp b/examples/quick/main.cpp index 11c2939..feae057 100644 --- a/examples/quick/main.cpp +++ b/examples/quick/main.cpp @@ -23,7 +23,6 @@ */ #include "../../framelessquickhelper.h" -#include "../../qtacrylicitem.h" #include #include #include @@ -65,7 +64,6 @@ int main(int argc, char *argv[]) #endif qmlRegisterType("wangwenx190.Utils", 1, 0, "FramelessHelper"); - qmlRegisterType("wangwenx190.Utils", 1, 0, "AcrylicItem"); const QUrl mainQmlUrl(QStringLiteral("qrc:///qml/main.qml")); const QMetaObject::Connection connection = QObject::connect( diff --git a/examples/quick/qml/main.qml b/examples/quick/qml/main.qml index a55c2ea..84d20a6 100644 --- a/examples/quick/qml/main.qml +++ b/examples/quick/qml/main.qml @@ -33,7 +33,7 @@ Window { width: 800 height: 600 title: qsTr("Hello, World!") - color: "transparent" + color: "#f0f0f0" property int _flh_margin: ((window.visibility === Window.Maximized) || (window.visibility === Window.FullScreen)) ? 0 : (1 / Screen.devicePixelRatio) @@ -49,13 +49,6 @@ Window { onTriggered: label.text = Qt.formatTime(new Date(), "hh:mm:ss") } - AcrylicItem { - id: acrylicItem - anchors.fill: parent - acrylicEnabled: true - frameVisible: true - } - Rectangle { id: titleBar height: framelessHelper.titleBarHeight @@ -119,8 +112,15 @@ Window { } } - Component.onCompleted: { - framelessHelper.removeWindowFrame() - framelessHelper.setBlurEffectEnabled(true) + Rectangle { + id: windowFrame + anchors.fill: parent + color: "transparent" + border { + color: framelessHelper.nativeFrameColor + width: window._flh_margin + } } + + Component.onCompleted: framelessHelper.removeWindowFrame() } diff --git a/examples/widget/main.cpp b/examples/widget/main.cpp index 7ad28b9..929ed11 100644 --- a/examples/widget/main.cpp +++ b/examples/widget/main.cpp @@ -52,7 +52,6 @@ int main(int argc, char *argv[]) Widget widget; widget.resize(800, 600); - widget.moveToDesktopCenter(); widget.show(); return QApplication::exec(); diff --git a/examples/widget/widget.cpp b/examples/widget/widget.cpp index 021bf2c..c4ae775 100644 --- a/examples/widget/widget.cpp +++ b/examples/widget/widget.cpp @@ -28,30 +28,22 @@ #include #include #include +#include #include "../../utilities.h" #include "../../framelesswindowsmanager.h" -Widget::Widget(QWidget *parent) : QtAcrylicWidget(parent) +Widget::Widget(QWidget *parent) : QWidget(parent) { createWinId(); - setAcrylicEnabled(true); setupUi(); startTimer(500); } Widget::~Widget() = default; -void Widget::moveToDesktopCenter() -{ - const QSize ss = Utilities::getScreenGeometry(nullptr).size(); - const int newX = (ss.width() - width()) / 2; - const int newY = (ss.height() - height()) / 2; - move(newX, newY); -} - void Widget::showEvent(QShowEvent *event) { - QtAcrylicWidget::showEvent(event); + QWidget::showEvent(event); static bool inited = false; if (!inited) { FramelessWindowsManager::addWindow(windowHandle()); @@ -61,13 +53,14 @@ void Widget::showEvent(QShowEvent *event) void Widget::timerEvent(QTimerEvent *event) { - QtAcrylicWidget::timerEvent(event); + QWidget::timerEvent(event); m_label->setText(QTime::currentTime().toString(QStringLiteral("hh:mm:ss"))); } void Widget::changeEvent(QEvent *event) { - QtAcrylicWidget::changeEvent(event); + QWidget::changeEvent(event); + bool shouldUpdate = false; if (event->type() == QEvent::WindowStateChange) { if (isMaximized() || isFullScreen()) { layout()->setContentsMargins(0, 0, 0, 0); @@ -76,6 +69,37 @@ void Widget::changeEvent(QEvent *event) layout()->setContentsMargins(1, 1, 1, 1); m_maximizeButton->setIcon(QIcon{QStringLiteral(":/images/button_maximize_black.svg")}); } + shouldUpdate = true; + } else if (event->type() == QEvent::ActivationChange) { + shouldUpdate = true; + } + if (shouldUpdate) { + update(); + } +} + +void Widget::paintEvent(QPaintEvent *event) +{ + QWidget::paintEvent(event); + if (windowState() == Qt::WindowNoState) { + QPainter painter(this); + const int w = width(); + const int h = height(); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + using BorderLines = QList; +#else + using BorderLines = QVector; +#endif + const BorderLines lines = { + {0, 0, w, 0}, + {w - 1, 0, w - 1, h}, + {w, h - 1, 0, h - 1}, + {0, h, 0, 0} + }; + painter.save(); + painter.setPen({Utilities::getNativeWindowFrameColor(), 1}); + painter.drawLines(lines); + painter.restore(); } } diff --git a/examples/widget/widget.h b/examples/widget/widget.h index c0f98d8..9c66849 100644 --- a/examples/widget/widget.h +++ b/examples/widget/widget.h @@ -24,14 +24,14 @@ #pragma once -#include "../../qtacrylicwidget.h" +#include QT_BEGIN_NAMESPACE QT_FORWARD_DECLARE_CLASS(QLabel) QT_FORWARD_DECLARE_CLASS(QPushButton) QT_END_NAMESPACE -class Widget : public QtAcrylicWidget +class Widget : public QWidget { Q_OBJECT Q_DISABLE_COPY_MOVE(Widget) @@ -40,12 +40,11 @@ public: explicit Widget(QWidget *parent = nullptr); ~Widget() override; - Q_INVOKABLE void moveToDesktopCenter(); - protected: void showEvent(QShowEvent *event) override; void timerEvent(QTimerEvent *event) override; void changeEvent(QEvent *event) override; + void paintEvent(QPaintEvent *event) override; private: void setupUi(); diff --git a/framelesshelper_global.h b/framelesshelper_global.h index 9608bb8..74d0dd8 100644 --- a/framelesshelper_global.h +++ b/framelesshelper_global.h @@ -65,13 +65,6 @@ namespace _flh_global { [[maybe_unused]] const char _flh_borderHeight_flag[] = "_FRAMELESSHELPER_WINDOW_BORDER_HEIGHT"; [[maybe_unused]] const char _flh_titleBarHeight_flag[] = "_FRAMELESSHELPER_WINDOW_TITLE_BAR_HEIGHT"; [[maybe_unused]] const char _flh_ignoredObjects_flag[] = "_FRAMELESSHELPER_WINDOW_TITLE_BAR_IGNORED_OBJECTS"; -[[maybe_unused]] const char _flh_acrylic_blurEnabled_flag[] = "_FRAMELESSHELPER_BLUR_ENABLED"; -[[maybe_unused]] const char _flh_acrylic_blurMode_flag[] = "_FRAMELESSHELPER_BLUR_MODE"; -[[maybe_unused]] const char _flh_acrylic_gradientColor_flag[] = "_FRAMELESSHELPER_BLUR_GRADIENT_COLOR"; -[[maybe_unused]] const char _flh_acrylic_disableExtraProcess[] = "_FRAMELESSHELPER_DISABLE_EXTRA_PROCESS_FOR_BLUR"; -[[maybe_unused]] const char _flh_acrylic_forceEnableOfficialMSWin10AcrylicBlur_flag[] = "_FRAMELESSHELPER_FORCE_ENABLE_MSWIN10_OFFICIAL_ACRYLIC_BLUR"; -[[maybe_unused]] const char _flh_acrylic_forceEnableTraditionalBlur_flag[] = "_FRAMELESSHELPER_FORCE_ENABLE_TRADITIONAL_BLUR"; -[[maybe_unused]] const char _flh_acrylic_forceDisableWallpaperBlur_flag[] = "_FRAMELESSHELPER_FORCE_DISABLE_WALLPAPER_BLUR"; [[maybe_unused]] const char _flh_useNativeTitleBar_flag[] = "_FRAMELESSHELPER_USE_NATIVE_TITLE_BAR"; [[maybe_unused]] const char _flh_preserveNativeFrame_flag[] = "_FRAMELESSHELPER_PRESERVE_NATIVE_WINDOW_FRAME"; [[maybe_unused]] const char _flh_forcePreserveNativeFrame_flag[] = "_FRAMELESSHELPER_FORCE_PRESERVE_NATIVE_WINDOW_FRAME"; diff --git a/framelesshelper_win32.cpp b/framelesshelper_win32.cpp index 5bf5c0b..e51896c 100644 --- a/framelesshelper_win32.cpp +++ b/framelesshelper_win32.cpp @@ -412,6 +412,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me } } } +#if 0 // Fix the flickering issue while resizing. // "clientRect->right += 1;" also works. // The only draw back of this small trick is it will affect @@ -419,6 +420,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me // larger than it should be. Be careful if you need to paint // something manually either through QPainter or Qt Quick. clientRect->bottom += 1; +#endif // If the window bounds change, we're going to relayout and repaint // anyway. Returning WVR_REDRAW avoids an extra paint before that of // the old client pixels in the (now wrong) location, and thus makes @@ -661,38 +663,6 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me default: break; } -#if 0 - // TODO: what if the user want to use the wallpaper blur all the time? - // Add an option to let the user choose what he wants. - if (Utilities::isWin10OrGreater()) { - if (window->property(_flh_global::_flh_acrylic_blurEnabled_flag).toBool()) { - bool shouldSwitchBlurMode = false; - if (msg->message == WM_ENTERSIZEMOVE) { - shouldSwitchBlurMode = true; - // Switch to the wallpaper blur temporarily due to the following issue: - // the window will become **VERY** laggy when it's being moved or resized. - // It's known as a bug of the API itself, currently no one knows how to fix it. - qunsetenv(_flh_global::_flh_acrylic_forceDisableWallpaperBlur_flag); - qunsetenv(_flh_global::_flh_acrylic_forceEnableTraditionalBlur_flag); - qunsetenv(_flh_global::_flh_acrylic_forceEnableOfficialMSWin10AcrylicBlur_flag); - } - if (msg->message == WM_EXITSIZEMOVE) { - shouldSwitchBlurMode = true; - // Switch back to the official Acrylic blur. That undocumented API won't cause any issues - // if we don't move or resize the window. - qputenv(_flh_global::_flh_acrylic_forceEnableTraditionalBlur_flag, "True"); - qputenv(_flh_global::_flh_acrylic_forceDisableWallpaperBlur_flag, "True"); - qputenv(_flh_global::_flh_acrylic_forceEnableOfficialMSWin10AcrylicBlur_flag, "True"); - } - if (shouldSwitchBlurMode) { - const auto gradientColor = qvariant_cast(window->property(_flh_global::_flh_acrylic_gradientColor_flag)); - if (!Utilities::setBlurEffectEnabled(window, true, gradientColor)) { - qWarning() << "Failed to enable the blur effect."; - } - } - } - } -#endif return false; } diff --git a/framelessquickhelper.cpp b/framelessquickhelper.cpp index 62566ca..1ed8e25 100644 --- a/framelessquickhelper.cpp +++ b/framelessquickhelper.cpp @@ -29,7 +29,14 @@ FramelessQuickHelper::FramelessQuickHelper(QQuickItem *parent) : QQuickItem(parent) { - startTimer(500); + connect(this, &FramelessQuickHelper::windowChanged, this, [this](QQuickWindow *win){ + if (m_frameColorConnection) { + disconnect(m_frameColorConnection); + } + if (win) { + m_frameColorConnection = connect(win, &QQuickWindow::activeChanged, this, &FramelessQuickHelper::nativeFrameColorChanged); + } + }); } int FramelessQuickHelper::borderWidth() const @@ -40,7 +47,7 @@ int FramelessQuickHelper::borderWidth() const void FramelessQuickHelper::setBorderWidth(const int val) { FramelessWindowsManager::setBorderWidth(window(), val); - Q_EMIT borderWidthChanged(val); + Q_EMIT borderWidthChanged(); } int FramelessQuickHelper::borderHeight() const @@ -51,7 +58,7 @@ int FramelessQuickHelper::borderHeight() const void FramelessQuickHelper::setBorderHeight(const int val) { FramelessWindowsManager::setBorderHeight(window(), val); - Q_EMIT borderHeightChanged(val); + Q_EMIT borderHeightChanged(); } int FramelessQuickHelper::titleBarHeight() const @@ -62,7 +69,7 @@ int FramelessQuickHelper::titleBarHeight() const void FramelessQuickHelper::setTitleBarHeight(const int val) { FramelessWindowsManager::setTitleBarHeight(window(), val); - Q_EMIT titleBarHeightChanged(val); + Q_EMIT titleBarHeightChanged(); } bool FramelessQuickHelper::resizable() const @@ -73,46 +80,18 @@ bool FramelessQuickHelper::resizable() const void FramelessQuickHelper::setResizable(const bool val) { FramelessWindowsManager::setResizable(window(), val); - Q_EMIT resizableChanged(val); + Q_EMIT resizableChanged(); } -bool FramelessQuickHelper::lightThemeEnabled() const +QColor FramelessQuickHelper::nativeFrameColor() const { - return Utilities::isLightThemeEnabled(); + const auto win = window(); + if (!win) { + return Qt::black; + } + return Utilities::getNativeWindowFrameColor(win->isActive()); } -bool FramelessQuickHelper::darkThemeEnabled() const -{ - return Utilities::isDarkThemeEnabled(); -} - -#ifdef Q_OS_WINDOWS -bool FramelessQuickHelper::colorizationEnabled() const -{ - return Utilities::isColorizationEnabled(); -} - -QColor FramelessQuickHelper::colorizationColor() const -{ - return Utilities::getColorizationColor(); -} - -bool FramelessQuickHelper::highContrastModeEnabled() const -{ - return Utilities::isHighContrastModeEnabled(); -} - -bool FramelessQuickHelper::darkFrameEnabled() const -{ - return Utilities::isDarkFrameEnabled(window()); -} - -bool FramelessQuickHelper::transparencyEffectEnabled() const -{ - return Utilities::isTransparencyEffectEnabled(); -} -#endif - void FramelessQuickHelper::removeWindowFrame() { FramelessWindowsManager::addWindow(window()); @@ -126,22 +105,3 @@ void FramelessQuickHelper::addIgnoreObject(QQuickItem *val) } FramelessWindowsManager::addIgnoreObject(window(), val); } - -void FramelessQuickHelper::timerEvent(QTimerEvent *event) -{ - QQuickItem::timerEvent(event); - Q_EMIT lightThemeEnabledChanged(lightThemeEnabled()); - Q_EMIT darkThemeEnabledChanged(darkThemeEnabled()); -#ifdef Q_OS_WINDOWS - Q_EMIT colorizationEnabledChanged(colorizationEnabled()); - Q_EMIT colorizationColorChanged(colorizationColor()); - Q_EMIT highContrastModeEnabledChanged(highContrastModeEnabled()); - Q_EMIT darkFrameEnabledChanged(darkFrameEnabled()); - Q_EMIT transparencyEffectEnabledChanged(transparencyEffectEnabled()); -#endif -} - -void FramelessQuickHelper::setBlurEffectEnabled(const bool enabled, const QColor &gradientColor) -{ - Utilities::setBlurEffectEnabled(window(), enabled, gradientColor); -} diff --git a/framelessquickhelper.h b/framelessquickhelper.h index 60254bf..13c7029 100644 --- a/framelessquickhelper.h +++ b/framelessquickhelper.h @@ -32,21 +32,13 @@ class FRAMELESSHELPER_EXPORT FramelessQuickHelper : public QQuickItem Q_OBJECT Q_DISABLE_COPY_MOVE(FramelessQuickHelper) #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) - QML_ELEMENT + QML_NAMED_ELEMENT(FramelessHelper) #endif Q_PROPERTY(int borderWidth READ borderWidth WRITE setBorderWidth NOTIFY borderWidthChanged) Q_PROPERTY(int borderHeight READ borderHeight WRITE setBorderHeight NOTIFY borderHeightChanged) Q_PROPERTY(int titleBarHeight READ titleBarHeight WRITE setTitleBarHeight NOTIFY titleBarHeightChanged) Q_PROPERTY(bool resizable READ resizable WRITE setResizable NOTIFY resizableChanged) - Q_PROPERTY(bool lightThemeEnabled READ lightThemeEnabled NOTIFY lightThemeEnabledChanged) - Q_PROPERTY(bool darkThemeEnabled READ darkThemeEnabled NOTIFY darkThemeEnabledChanged) -#ifdef Q_OS_WINDOWS - Q_PROPERTY(bool colorizationEnabled READ colorizationEnabled NOTIFY colorizationEnabledChanged) - Q_PROPERTY(QColor colorizationColor READ colorizationColor NOTIFY colorizationColorChanged) - Q_PROPERTY(bool highContrastModeEnabled READ highContrastModeEnabled NOTIFY highContrastModeEnabledChanged) - Q_PROPERTY(bool darkFrameEnabled READ darkFrameEnabled NOTIFY darkFrameEnabledChanged) - Q_PROPERTY(bool transparencyEffectEnabled READ transparencyEffectEnabled NOTIFY transparencyEffectEnabledChanged) -#endif + Q_PROPERTY(QColor nativeFrameColor READ nativeFrameColor NOTIFY nativeFrameColorChanged) public: explicit FramelessQuickHelper(QQuickItem *parent = nullptr); @@ -64,37 +56,19 @@ public: bool resizable() const; void setResizable(const bool val); - bool lightThemeEnabled() const; - bool darkThemeEnabled() const; - -#ifdef Q_OS_WINDOWS - bool colorizationEnabled() const; - QColor colorizationColor() const; - bool highContrastModeEnabled() const; - bool darkFrameEnabled() const; - bool transparencyEffectEnabled() const; -#endif + QColor nativeFrameColor() const; public Q_SLOTS: void removeWindowFrame(); void addIgnoreObject(QQuickItem *val); - void setBlurEffectEnabled(const bool enabled = true, const QColor &gradientColor = {}); - -protected: - void timerEvent(QTimerEvent *event) override; Q_SIGNALS: - void borderWidthChanged(int); - void borderHeightChanged(int); - void titleBarHeightChanged(int); - void resizableChanged(bool); - void lightThemeEnabledChanged(bool); - void darkThemeEnabledChanged(bool); -#ifdef Q_OS_WINDOWS - void colorizationEnabledChanged(bool); - void colorizationColorChanged(const QColor &); - void highContrastModeEnabledChanged(bool); - void darkFrameEnabledChanged(bool); - void transparencyEffectEnabledChanged(bool); -#endif + void borderWidthChanged(); + void borderHeightChanged(); + void titleBarHeightChanged(); + void resizableChanged(); + void nativeFrameColorChanged(); + +private: + QMetaObject::Connection m_frameColorConnection = {}; }; diff --git a/lib.pro b/lib.pro index c0bd4b5..ee2c15e 100644 --- a/lib.pro +++ b/lib.pro @@ -15,45 +15,26 @@ HEADERS += \ framelesshelper_global.h \ framelesshelper.h \ framelesswindowsmanager.h \ - utilities.h \ - qtacryliceffecthelper.h + utilities.h SOURCES += \ framelesshelper.cpp \ framelesswindowsmanager.cpp \ - utilities.cpp \ - qtacryliceffecthelper.cpp -qtHaveModule(widgets) { - QT += widgets - HEADERS += \ - qtacrylicwidget.h \ - qtacrylicmainwindow.h - SOURCES += \ - qtacrylicwidget.cpp \ - qtacrylicmainwindow.cpp -} + utilities.cpp qtHaveModule(quick) { QT += quick - HEADERS += \ - framelessquickhelper.h \ - qtacrylicitem.h - SOURCES += \ - framelessquickhelper.cpp \ - qtacrylicitem.cpp + HEADERS += framelessquickhelper.h + SOURCES += framelessquickhelper.cpp } -RESOURCES += qtacrylichelper.qrc win32 { DEFINES += \ WIN32_LEAN_AND_MEAN \ _CRT_SECURE_NO_WARNINGS \ UNICODE \ _UNICODE - HEADERS += \ - framelesshelper_win32.h \ - qtacryliceffecthelper_win32.h + HEADERS += framelesshelper_win32.h SOURCES += \ utilities_win32.cpp \ - framelesshelper_win32.cpp \ - qtacryliceffecthelper_win32.cpp - LIBS += -luser32 -lshell32 -lgdi32 -ldwmapi -lole32 + framelesshelper_win32.cpp + LIBS += -luser32 -lshell32 -lgdi32 -ldwmapi RC_FILE = framelesshelper.rc } diff --git a/qtacryliceffecthelper.cpp b/qtacryliceffecthelper.cpp deleted file mode 100644 index 40b52c2..0000000 --- a/qtacryliceffecthelper.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/* - * MIT License - * - * Copyright (C) 2021 by wangwenx190 (Yuhang Zhao) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "qtacryliceffecthelper.h" -#include "utilities.h" -#include -#include -#include -#include - -QtAcrylicEffectHelper::QtAcrylicEffectHelper(QObject *parent) : QObject(parent) -{ - Q_INIT_RESOURCE(qtacrylichelper); - QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); -#ifdef Q_OS_MACOS - if (Utilities::shouldUseTraditionalBlur()) { - m_tintOpacity = 0.6; - } -#endif -#ifdef Q_OS_WINDOWS - m_frameColor = Utilities::getNativeWindowFrameColor(true); -#else - m_frameColor = Qt::black; -#endif -} - -QtAcrylicEffectHelper::~QtAcrylicEffectHelper() = default; - -void QtAcrylicEffectHelper::install(const QWindow *window) -{ - Q_ASSERT(window); - if (!window) { - return; - } - if (m_window != window) { - m_window = const_cast(window); - connect(m_window, &QWindow::xChanged, this, &QtAcrylicEffectHelper::needsRepaint); - connect(m_window, &QWindow::yChanged, this, &QtAcrylicEffectHelper::needsRepaint); - connect(m_window, &QWindow::activeChanged, this, &QtAcrylicEffectHelper::needsRepaint); - // What's the difference between "visibility" and "window state"? - //connect(m_window, &QWindow::visibilityChanged, this, &QtAcrylicEffectHelper::needsRepaint); - connect(m_window, &QWindow::windowStateChanged, this, &QtAcrylicEffectHelper::needsRepaint); -#ifdef Q_OS_WINDOWS - //QtAcrylicWinEventFilter::setup(); -#endif - } -} - -void QtAcrylicEffectHelper::uninstall() -{ - if (m_window) { -#ifdef Q_OS_WINDOWS - //QtAcrylicWinEventFilter::unsetup(); -#endif - disconnect(m_window, &QWindow::xChanged, this, &QtAcrylicEffectHelper::needsRepaint); - disconnect(m_window, &QWindow::yChanged, this, &QtAcrylicEffectHelper::needsRepaint); - disconnect(m_window, &QWindow::activeChanged, this, &QtAcrylicEffectHelper::needsRepaint); - //disconnect(m_window, &QWindow::visibilityChanged, this, &QtAcrylicEffectHelper::needsRepaint); - disconnect(m_window, &QWindow::windowStateChanged, this, &QtAcrylicEffectHelper::needsRepaint); - m_window = nullptr; - } -} - -void QtAcrylicEffectHelper::clearWallpaper() -{ - if (!m_bluredWallpaper.isNull()) { - m_bluredWallpaper = {}; - } -} - -void QtAcrylicEffectHelper::showWarning() const -{ - qDebug() << "The Acrylic blur effect has been enabled. Rendering acrylic material surfaces is highly GPU-intensive, which can slow down the application, increase the power consumption on the devices on which the application is running."; -} - -QBrush QtAcrylicEffectHelper::getAcrylicBrush() const -{ - return m_acrylicBrush; -} - -QColor QtAcrylicEffectHelper::getTintColor() const -{ - return m_tintColor; -} - -qreal QtAcrylicEffectHelper::getTintOpacity() const -{ - return m_tintOpacity; -} - -qreal QtAcrylicEffectHelper::getNoiseOpacity() const -{ - return m_noiseOpacity; -} - -QPixmap QtAcrylicEffectHelper::getBluredWallpaper() const -{ - return m_bluredWallpaper; -} - -QColor QtAcrylicEffectHelper::getFrameColor() const -{ - return m_frameColor; -} - -qreal QtAcrylicEffectHelper::getFrameThickness() const -{ - return m_frameThickness; -} - -void QtAcrylicEffectHelper::setTintColor(const QColor &value) -{ - if (!value.isValid()) { - qWarning() << value << "is not a valid color."; - return; - } - if (m_tintColor != value) { - m_tintColor = value; - } -} - -void QtAcrylicEffectHelper::setTintOpacity(const qreal value) -{ - if (m_tintOpacity != value) { - m_tintOpacity = value; - } -} - -void QtAcrylicEffectHelper::setNoiseOpacity(const qreal value) -{ - if (m_noiseOpacity != value) { - m_noiseOpacity = value; - } -} - -void QtAcrylicEffectHelper::setFrameColor(const QColor &value) -{ - if (!value.isValid()) { - qWarning() << value << "is not a valid color."; - return; - } - if (m_frameColor != value) { - m_frameColor = value; - } -} - -void QtAcrylicEffectHelper::setFrameThickness(const qreal value) -{ - if (m_frameThickness != value) { - m_frameThickness = value; - } -} - -void QtAcrylicEffectHelper::paintWindowBackground(QPainter *painter, const QRegion &clip) -{ - Q_ASSERT(painter); - Q_ASSERT(!clip.isEmpty()); - if (!painter || clip.isEmpty()) { - return; - } - if (!checkWindow()) { - return; - } - painter->save(); - painter->setClipRegion(clip); - paintBackground(painter, clip.boundingRect()); - painter->restore(); -} - -void QtAcrylicEffectHelper::paintWindowBackground(QPainter *painter, const QRect &rect) -{ - Q_ASSERT(painter); - Q_ASSERT(rect.isValid()); - if (!painter || !rect.isValid()) { - return; - } - if (!checkWindow()) { - return; - } - painter->save(); - painter->setClipRegion({rect}); - paintBackground(painter, rect); - painter->restore(); -} - -void QtAcrylicEffectHelper::paintBackground(QPainter *painter, const QRect &rect) -{ - Q_ASSERT(painter); - Q_ASSERT(rect.isValid()); - if (!painter || !rect.isValid()) { - return; - } - if (!checkWindow()) { - return; - } - // TODO: should we limit it to Win32 only? Or should we do something about the - // acrylic brush instead? - if (Utilities::disableExtraProcessingForBlur()) { - return; - } - if (Utilities::shouldUseTraditionalBlur()) { - const QPainter::CompositionMode mode = painter->compositionMode(); - painter->setCompositionMode(QPainter::CompositionMode_Clear); - painter->fillRect(rect, Qt::white); - painter->setCompositionMode(mode); - } else { - // Emulate blur behind window by blurring the desktop wallpaper. - updateBehindWindowBackground(); - painter->drawPixmap(QPoint{0, 0}, m_bluredWallpaper, QRect{m_window->mapToGlobal(QPoint{0, 0}), rect.size()}); - } - painter->setCompositionMode(QPainter::CompositionMode_SourceOver); - painter->setOpacity(1); - painter->fillRect(rect, m_acrylicBrush); -} - -void QtAcrylicEffectHelper::paintWindowFrame(QPainter *painter, const QRect &rect) -{ - Q_ASSERT(painter); - if (!painter) { - return; - } - if (!checkWindow()) { - return; - } - if (m_window->windowState() != Qt::WindowNoState) { - // We shouldn't draw the window frame when it's minimized/maximized/fullscreen. - return; - } - const int width = rect.isValid() ? rect.width() : m_window->width(); - const int height = rect.isValid() ? rect.height() : m_window->height(); -#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) - using BorderLines = QList; -#else - using BorderLines = QVector; -#endif -#ifdef Q_OS_WINDOWS - const int internalFix = 1; -#else - const int internalFix = 0; -#endif - const BorderLines lines = { - {0, 0, static_cast(width), 0}, - {width - m_frameThickness, 0, width - m_frameThickness, static_cast(height)}, - {static_cast(width), height - m_frameThickness - internalFix, 0, height - m_frameThickness - internalFix}, - {0, static_cast(height), 0, 0} - }; - const bool active = m_window->isActive(); - const QColor color = (active && m_frameColor.isValid() && (m_frameColor != Qt::transparent)) ? m_frameColor : Utilities::getNativeWindowFrameColor(active); - painter->save(); - painter->setPen({color, 1}); - painter->drawLines(lines); - painter->restore(); -} - -void QtAcrylicEffectHelper::updateAcrylicBrush(const QColor &alternativeTintColor) -{ - const auto getAppropriateTintColor = [&alternativeTintColor, this]() -> QColor { - if (alternativeTintColor.isValid() && (alternativeTintColor != Qt::transparent)) { - return alternativeTintColor; - } - if (m_tintColor.isValid() && (m_tintColor != Qt::transparent)) { - return m_tintColor; - } - return Qt::white; - }; - static const QImage noiseTexture(QStringLiteral(":/QtAcrylicHelper/Noise.png")); - QImage acrylicTexture({64, 64}, QImage::Format_ARGB32_Premultiplied); - QColor fillColor = Qt::transparent; -#ifdef Q_OS_WINDOWS - if (!Utilities::isOfficialMSWin10AcrylicBlurAvailable()) { - // Add a soft light layer for the background. - fillColor = Qt::white; - fillColor.setAlpha(150); - } -#endif - acrylicTexture.fill(fillColor); - QPainter painter(&acrylicTexture); - painter.setOpacity(m_tintOpacity); - painter.fillRect(QRect{0, 0, acrylicTexture.width(), acrylicTexture.height()}, getAppropriateTintColor()); - painter.setOpacity(m_noiseOpacity); - painter.fillRect(QRect{0, 0, acrylicTexture.width(), acrylicTexture.height()}, noiseTexture); - m_acrylicBrush = acrylicTexture; -} - -void QtAcrylicEffectHelper::updateBehindWindowBackground() -{ - if (!checkWindow()) { - return; - } - if (!m_bluredWallpaper.isNull()) { - return; - } - const QSize size = Utilities::getScreenGeometry(m_window).size(); - m_bluredWallpaper = QPixmap(size); - m_bluredWallpaper.fill(Qt::transparent); - QImage image = Utilities::getDesktopWallpaperImage(); - // On some platforms we may not be able to get the desktop wallpaper, such as Linux and WebAssembly. - if (image.isNull()) { - return; - } - const Utilities::DesktopWallpaperAspectStyle aspectStyle = Utilities::getDesktopWallpaperAspectStyle(); - QImage buffer(size, QImage::Format_ARGB32_Premultiplied); -#ifdef Q_OS_WINDOWS - if ((aspectStyle == Utilities::DesktopWallpaperAspectStyle::Central) || - (aspectStyle == Utilities::DesktopWallpaperAspectStyle::KeepRatioFit)) { - buffer.fill(Utilities::getDesktopBackgroundColor()); - } -#endif - if (aspectStyle == Utilities::DesktopWallpaperAspectStyle::IgnoreRatioFit || - aspectStyle == Utilities::DesktopWallpaperAspectStyle::KeepRatioFit || - aspectStyle == Utilities::DesktopWallpaperAspectStyle::KeepRatioByExpanding) { - Qt::AspectRatioMode mode; - if (aspectStyle == Utilities::DesktopWallpaperAspectStyle::IgnoreRatioFit) { - mode = Qt::IgnoreAspectRatio; - } else if (aspectStyle == Utilities::DesktopWallpaperAspectStyle::KeepRatioFit) { - mode = Qt::KeepAspectRatio; - } else { - mode = Qt::KeepAspectRatioByExpanding; - } - QSize newSize = image.size(); - newSize.scale(size, mode); - image = image.scaled(newSize, Qt::IgnoreAspectRatio, Qt::FastTransformation); - } - if (aspectStyle == Utilities::DesktopWallpaperAspectStyle::Tiled) { - QPainter painterBuffer(&buffer); - painterBuffer.fillRect(QRect{{0, 0}, size}, image); - } else { - QPainter painterBuffer(&buffer); - const QRect rect = Utilities::alignedRect(Qt::LeftToRight, Qt::AlignCenter, image.size(), {{0, 0}, size}); - painterBuffer.drawImage(rect.topLeft(), image); - } - QPainter painter(&m_bluredWallpaper); -#if 1 - Utilities::blurImage(&painter, buffer, 128, false, false); -#else - painter.drawImage(QPoint{0, 0}, buffer); -#endif -} - -bool QtAcrylicEffectHelper::checkWindow() const -{ - if (m_window) { - return true; - } - qWarning() << "m_window is null, forgot to call \"QtAcrylicEffectHelper::install()\"?"; - return false; -} diff --git a/qtacryliceffecthelper.h b/qtacryliceffecthelper.h deleted file mode 100644 index b64bd1c..0000000 --- a/qtacryliceffecthelper.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * MIT License - * - * Copyright (C) 2021 by wangwenx190 (Yuhang Zhao) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#pragma once - -#include "framelesshelper_global.h" -#include - -class FRAMELESSHELPER_EXPORT QtAcrylicEffectHelper : public QObject -{ - Q_OBJECT - Q_DISABLE_COPY_MOVE(QtAcrylicEffectHelper) - -public: - explicit QtAcrylicEffectHelper(QObject *parent = nullptr); - ~QtAcrylicEffectHelper() override; - - QBrush getAcrylicBrush() const; - QColor getTintColor() const; - qreal getTintOpacity() const; - qreal getNoiseOpacity() const; - QPixmap getBluredWallpaper() const; - QColor getFrameColor() const; - qreal getFrameThickness() const; - -public Q_SLOTS: - void install(const QWindow *window); - void uninstall(); - - void clearWallpaper(); - - void showWarning() const; - - void setTintColor(const QColor &value); - void setTintOpacity(const qreal value); - void setNoiseOpacity(const qreal value); - void setFrameColor(const QColor &value); - void setFrameThickness(const qreal value); - - void paintWindowBackground(QPainter *painter, const QRegion &clip); - void paintWindowBackground(QPainter *painter, const QRect &rect); - void paintWindowFrame(QPainter *painter, const QRect &rect = {}); - void updateAcrylicBrush(const QColor &alternativeTintColor = {}); - -private: - void paintBackground(QPainter *painter, const QRect &rect); - void updateBehindWindowBackground(); - bool checkWindow() const; - -Q_SIGNALS: - void needsRepaint(); - -private: - QWindow *m_window = nullptr; - QBrush m_acrylicBrush = {}; - QColor m_tintColor = {}; - qreal m_tintOpacity = 0.7; - qreal m_noiseOpacity = 0.04; - QPixmap m_bluredWallpaper = {}; - QColor m_frameColor = {}; - qreal m_frameThickness = 1.0; -}; diff --git a/qtacryliceffecthelper_win32.cpp b/qtacryliceffecthelper_win32.cpp deleted file mode 100644 index 8e093c4..0000000 --- a/qtacryliceffecthelper_win32.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * MIT License - * - * Copyright (C) 2021 by wangwenx190 (Yuhang Zhao) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "qtacryliceffecthelper_win32.h" -#include "utilities.h" -#include -#include - -#ifndef WM_DWMCOMPOSITIONCHANGED -// Only available since Windows Vista -#define WM_DWMCOMPOSITIONCHANGED 0x031E -#endif - -#ifndef WM_DWMCOLORIZATIONCOLORCHANGED -// Only available since Windows Vista -#define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320 -#endif - -#ifndef WM_DPICHANGED -// Only available since Windows 8.1 -#define WM_DPICHANGED 0x02E0 -#endif - -const int QtAcrylicWinUpdateEvent::QtAcrylicEffectChangeEventId = QEvent::registerEventType(); - -QtAcrylicWinUpdateEvent::QtAcrylicWinUpdateEvent(const bool clearWallpaper) : QEvent(static_cast(QtAcrylicEffectChangeEventId)) -{ - m_shouldClearPreviousWallpaper = clearWallpaper; -} - -QtAcrylicWinUpdateEvent::~QtAcrylicWinUpdateEvent() = default; - -static QScopedPointer g_instance; - -QtAcrylicWinEventFilter::QtAcrylicWinEventFilter() = default; - -QtAcrylicWinEventFilter::~QtAcrylicWinEventFilter() -{ - // FIXME - //unsetup(); -} - -void QtAcrylicWinEventFilter::setup() -{ - if (g_instance.isNull()) { - g_instance.reset(new QtAcrylicWinEventFilter); - qApp->installNativeEventFilter(g_instance.data()); - } -} - -void QtAcrylicWinEventFilter::unsetup() -{ - if (!g_instance.isNull()) { - qApp->removeNativeEventFilter(g_instance.data()); - g_instance.reset(); - } -} - -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) -bool QtAcrylicWinEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) -#else -bool QtAcrylicWinEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result) -#endif -{ - Q_ASSERT(eventType == "windows_generic_MSG"); - Q_ASSERT(message); - Q_UNUSED(result); // We don't need this parameter. - if ((eventType != "windows_generic_MSG") || !message) { - return false; - } -#if (QT_VERSION == QT_VERSION_CHECK(5, 11, 1)) - const auto msg = *reinterpret_cast(message); -#else - const auto msg = static_cast(message); -#endif - bool shouldUpdate = false; - bool shouldClearWallpaper = false; - switch (msg->message) { - case WM_SETTINGCHANGE: { - if (msg->wParam == SPI_SETDESKWALLPAPER) { - shouldClearWallpaper = true; - shouldUpdate = true; - } - if ((msg->wParam == 0) && (QString::fromWCharArray(reinterpret_cast(msg->lParam)) == QStringLiteral("ImmersiveColorSet"))) { - shouldUpdate = true; - } - } break; - case WM_DPICHANGED: { - shouldClearWallpaper = true; - shouldUpdate = true; - } break; - case WM_THEMECHANGED: - case WM_DWMCOMPOSITIONCHANGED: - case WM_DWMCOLORIZATIONCOLORCHANGED: - shouldUpdate = true; - break; - default : - break; - } - if (shouldUpdate) { - const QWindow *window = Utilities::findWindow(reinterpret_cast(msg->hwnd)); - if (window) { - QtAcrylicWinUpdateEvent event(shouldClearWallpaper); - QCoreApplication::sendEvent(const_cast(window), &event); - } - } - return false; -} diff --git a/qtacryliceffecthelper_win32.h b/qtacryliceffecthelper_win32.h deleted file mode 100644 index c24d44b..0000000 --- a/qtacryliceffecthelper_win32.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * MIT License - * - * Copyright (C) 2021 by wangwenx190 (Yuhang Zhao) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#pragma once - -#include "framelesshelper_global.h" -#include -#include - -class FRAMELESSHELPER_EXPORT QtAcrylicWinUpdateEvent : public QEvent -{ -public: - static const int QtAcrylicEffectChangeEventId; - - explicit QtAcrylicWinUpdateEvent(const bool clearWallpaper = false); - ~QtAcrylicWinUpdateEvent() override; - - inline bool shouldClearPreviousWallpaper() const - { - return m_shouldClearPreviousWallpaper; - } - -private: - bool m_shouldClearPreviousWallpaper = false; -}; - -class FRAMELESSHELPER_EXPORT QtAcrylicWinEventFilter : public QAbstractNativeEventFilter -{ -public: - explicit QtAcrylicWinEventFilter(); - ~QtAcrylicWinEventFilter() override; - - static void setup(); - static void unsetup(); - -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override; -#else - bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override; -#endif -}; diff --git a/qtacrylichelper.qrc b/qtacrylichelper.qrc deleted file mode 100644 index 7f21c5c..0000000 --- a/qtacrylichelper.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - resources/noise.png - - diff --git a/qtacrylicitem.cpp b/qtacrylicitem.cpp deleted file mode 100644 index e1783f6..0000000 --- a/qtacrylicitem.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - * MIT License - * - * Copyright (C) 2021 by wangwenx190 (Yuhang Zhao) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "qtacrylicitem.h" -#include -#include "utilities.h" -#include -#include - -QtAcrylicItem::QtAcrylicItem(QQuickItem *parent) : QQuickPaintedItem(parent) -{ - connect(this, &QtAcrylicItem::windowChanged, this, [this](QQuickWindow *win){ - if (m_repaintConnection) { - disconnect(m_repaintConnection); - } - m_acrylicHelper.uninstall(); - if (win) { - m_acrylicHelper.install(win); - m_acrylicHelper.updateAcrylicBrush(); - m_repaintConnection = connect(&m_acrylicHelper, &QtAcrylicEffectHelper::needsRepaint, this, [this](){ - update(); - }); - } - }); -} - -QtAcrylicItem::~QtAcrylicItem() = default; - -void QtAcrylicItem::paint(QPainter *painter) -{ - const QRect rect = {0, 0, qRound(width()), qRound(height())}; - if (acrylicEnabled()) { - m_acrylicHelper.paintWindowBackground(painter, rect); - } - if (frameVisible()) { - m_acrylicHelper.paintWindowFrame(painter, rect); - } -} - -QColor QtAcrylicItem::tintColor() const -{ - const QColor color = m_acrylicHelper.getTintColor(); - if (color.isValid() && (color != Qt::transparent)) { - return color; - } else { - return /*palette().color(backgroundRole())*/Qt::white; - } -} - -void QtAcrylicItem::setTintColor(const QColor &value) -{ - if (!value.isValid()) { - qWarning() << "Tint color not valid."; - return; - } - if (m_acrylicHelper.getTintColor() != value) { - m_acrylicHelper.setTintColor(value); -#if 0 - QPalette pal = palette(); - pal.setColor(backgroundRole(), m_acrylicHelper.getTintColor()); - setPalette(pal); -#endif - m_acrylicHelper.updateAcrylicBrush(tintColor()); - update(); - Q_EMIT tintColorChanged(); - } -} - -qreal QtAcrylicItem::tintOpacity() const -{ - return m_acrylicHelper.getTintOpacity(); -} - -void QtAcrylicItem::setTintOpacity(const qreal value) -{ - if (m_acrylicHelper.getTintOpacity() != value) { - m_acrylicHelper.setTintOpacity(value); - m_acrylicHelper.updateAcrylicBrush(tintColor()); - update(); - Q_EMIT tintOpacityChanged(); - } -} - -qreal QtAcrylicItem::noiseOpacity() const -{ - return m_acrylicHelper.getNoiseOpacity(); -} - -void QtAcrylicItem::setNoiseOpacity(const qreal value) -{ - if (m_acrylicHelper.getNoiseOpacity() != value) { - m_acrylicHelper.setNoiseOpacity(value); - m_acrylicHelper.updateAcrylicBrush(tintColor()); - update(); - Q_EMIT noiseOpacityChanged(); - } -} - -bool QtAcrylicItem::frameVisible() const -{ - return m_frameVisible; -} - -void QtAcrylicItem::setFrameVisible(const bool value) -{ - if (m_frameVisible != value) { - m_frameVisible = value; - update(); - Q_EMIT frameVisibleChanged(); - } -} - -QColor QtAcrylicItem::frameColor() const -{ - return m_acrylicHelper.getFrameColor(); -} - -void QtAcrylicItem::setFrameColor(const QColor &value) -{ - if (m_acrylicHelper.getFrameColor() != value) { - m_acrylicHelper.setFrameColor(value); - update(); - Q_EMIT frameColorChanged(); - } -} - -qreal QtAcrylicItem::frameThickness() const -{ - return m_acrylicHelper.getFrameThickness(); -} - -void QtAcrylicItem::setFrameThickness(const qreal value) -{ - if (m_acrylicHelper.getFrameThickness() != value) { - m_acrylicHelper.setFrameThickness(value); - update(); - Q_EMIT frameThicknessChanged(); - } -} - -bool QtAcrylicItem::acrylicEnabled() const -{ - return m_acrylicEnabled; -} - -void QtAcrylicItem::setAcrylicEnabled(const bool value) -{ - if (m_acrylicEnabled != value) { - m_acrylicEnabled = value; - update(); - Q_EMIT acrylicEnabledChanged(); - if (m_acrylicEnabled) { - m_acrylicHelper.showWarning(); - } - } -} diff --git a/qtacrylicitem.h b/qtacrylicitem.h deleted file mode 100644 index e5e99b9..0000000 --- a/qtacrylicitem.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * MIT License - * - * Copyright (C) 2021 by wangwenx190 (Yuhang Zhao) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#pragma once - -#include "framelesshelper_global.h" -#include -#include "qtacryliceffecthelper.h" - -class FRAMELESSHELPER_EXPORT QtAcrylicItem : public QQuickPaintedItem -{ - Q_OBJECT -#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) - QML_NAMED_ELEMENT(AcrylicItem) -#endif - Q_DISABLE_COPY_MOVE(QtAcrylicItem) - Q_PROPERTY(QColor tintColor READ tintColor WRITE setTintColor NOTIFY tintColorChanged) - Q_PROPERTY(qreal tintOpacity READ tintOpacity WRITE setTintOpacity NOTIFY tintOpacityChanged) - Q_PROPERTY(qreal noiseOpacity READ noiseOpacity WRITE setNoiseOpacity NOTIFY noiseOpacityChanged) - Q_PROPERTY(bool frameVisible READ frameVisible WRITE setFrameVisible NOTIFY frameVisibleChanged) - Q_PROPERTY(QColor frameColor READ frameColor WRITE setFrameColor NOTIFY frameColorChanged) - Q_PROPERTY(qreal frameThickness READ frameThickness WRITE setFrameThickness NOTIFY frameThicknessChanged) - Q_PROPERTY(bool acrylicEnabled READ acrylicEnabled WRITE setAcrylicEnabled NOTIFY acrylicEnabledChanged) - -public: - explicit QtAcrylicItem(QQuickItem *parent = nullptr); - ~QtAcrylicItem() override; - - void paint(QPainter *painter) override; - - QColor tintColor() const; - void setTintColor(const QColor &value); - - qreal tintOpacity() const; - void setTintOpacity(const qreal value); - - qreal noiseOpacity() const; - void setNoiseOpacity(const qreal value); - - bool frameVisible() const; - void setFrameVisible(const bool value); - - QColor frameColor() const; - void setFrameColor(const QColor &value); - - qreal frameThickness() const; - void setFrameThickness(const qreal value); - - bool acrylicEnabled() const; - void setAcrylicEnabled(const bool value); - -Q_SIGNALS: - void tintColorChanged(); - void tintOpacityChanged(); - void noiseOpacityChanged(); - void frameVisibleChanged(); - void frameColorChanged(); - void frameThicknessChanged(); - void acrylicEnabledChanged(); - -private: - QtAcrylicEffectHelper m_acrylicHelper; - bool m_frameVisible = true; - QMetaObject::Connection m_repaintConnection = {}; - bool m_acrylicEnabled = false; -}; diff --git a/qtacrylicmainwindow.cpp b/qtacrylicmainwindow.cpp deleted file mode 100644 index c08a3ec..0000000 --- a/qtacrylicmainwindow.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - * MIT License - * - * Copyright (C) 2021 by wangwenx190 (Yuhang Zhao) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "qtacrylicmainwindow.h" -#include "utilities.h" -#include -#include -#include - -QtAcrylicMainWindow::QtAcrylicMainWindow(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags) -{ -} - -QtAcrylicMainWindow::~QtAcrylicMainWindow() = default; - -QColor QtAcrylicMainWindow::tintColor() const -{ - const QColor color = m_acrylicHelper.getTintColor(); - if (color.isValid() && (color != Qt::transparent)) { - return color; - } else { - return palette().color(backgroundRole()); - } -} - -void QtAcrylicMainWindow::setTintColor(const QColor &value) -{ - if (!value.isValid()) { - qWarning() << "Tint color not valid."; - return; - } - if (m_acrylicHelper.getTintColor() != value) { - m_acrylicHelper.setTintColor(value); - QPalette pal = palette(); - pal.setColor(backgroundRole(), m_acrylicHelper.getTintColor()); - setPalette(pal); - //m_acrylicHelper.updateAcrylicBrush(tintColor()); - update(); - Q_EMIT tintColorChanged(); - } -} - -qreal QtAcrylicMainWindow::tintOpacity() const -{ - return m_acrylicHelper.getTintOpacity(); -} - -void QtAcrylicMainWindow::setTintOpacity(const qreal value) -{ - if (m_acrylicHelper.getTintOpacity() != value) { - m_acrylicHelper.setTintOpacity(value); - m_acrylicHelper.updateAcrylicBrush(tintColor()); - update(); - Q_EMIT tintOpacityChanged(); - } -} - -qreal QtAcrylicMainWindow::noiseOpacity() const -{ - return m_acrylicHelper.getNoiseOpacity(); -} - -void QtAcrylicMainWindow::setNoiseOpacity(const qreal value) -{ - if (m_acrylicHelper.getNoiseOpacity() != value) { - m_acrylicHelper.setNoiseOpacity(value); - m_acrylicHelper.updateAcrylicBrush(tintColor()); - update(); - Q_EMIT noiseOpacityChanged(); - } -} - -bool QtAcrylicMainWindow::frameVisible() const -{ - return m_frameVisible; -} - -void QtAcrylicMainWindow::setFrameVisible(const bool value) -{ - if (m_frameVisible != value) { - m_frameVisible = value; - update(); - Q_EMIT frameVisibleChanged(); - } -} - -QColor QtAcrylicMainWindow::frameColor() const -{ - return m_acrylicHelper.getFrameColor(); -} - -void QtAcrylicMainWindow::setFrameColor(const QColor &value) -{ - if (m_acrylicHelper.getFrameColor() != value) { - m_acrylicHelper.setFrameColor(value); - update(); - Q_EMIT frameColorChanged(); - } -} - -qreal QtAcrylicMainWindow::frameThickness() const -{ - return m_acrylicHelper.getFrameThickness(); -} - -void QtAcrylicMainWindow::setFrameThickness(const qreal value) -{ - if (m_acrylicHelper.getFrameThickness() != value) { - m_acrylicHelper.setFrameThickness(value); - update(); - Q_EMIT frameThicknessChanged(); - } -} - -bool QtAcrylicMainWindow::acrylicEnabled() const -{ - return m_acrylicEnabled; -} - -void QtAcrylicMainWindow::setAcrylicEnabled(const bool value) -{ - if (m_acrylicEnabled != value) { - m_acrylicEnabled = value; - if (m_inited) { - Utilities::setBlurEffectEnabled(windowHandle(), m_acrylicEnabled); - } - setAutoFillBackground(!m_acrylicEnabled); - setAttribute(Qt::WA_NoSystemBackground, m_acrylicEnabled); - setAttribute(Qt::WA_OpaquePaintEvent, m_acrylicEnabled); - setBackgroundRole(m_acrylicEnabled ? QPalette::Base : QPalette::Window); - update(); - Q_EMIT acrylicEnabledChanged(); - if (m_acrylicEnabled) { - m_acrylicHelper.showWarning(); - } - } -} - -void QtAcrylicMainWindow::showEvent(QShowEvent *event) -{ - QMainWindow::showEvent(event); - updateContentMargin(); - if (!m_inited) { - m_acrylicHelper.install(windowHandle()); - m_acrylicHelper.updateAcrylicBrush(tintColor()); - connect(&m_acrylicHelper, &QtAcrylicEffectHelper::needsRepaint, this, qOverload<>(&QtAcrylicMainWindow::update)); - Utilities::setBlurEffectEnabled(windowHandle(), m_acrylicEnabled); - m_inited = true; - } -} - -void QtAcrylicMainWindow::updateContentMargin() -{ - const qreal margin = (isMaximized() || isFullScreen()) ? 0.0 : (1.0 / devicePixelRatioF()); - const int m = qRound(margin); - setContentsMargins(m, m, m, m); -} - -void QtAcrylicMainWindow::paintEvent(QPaintEvent *event) -{ - QPainter painter(this); - const QRect rect = {0, 0, width(), height()}; - if (acrylicEnabled()) { - m_acrylicHelper.paintWindowBackground(&painter, rect); - } - if (frameVisible()) { - m_acrylicHelper.paintWindowFrame(&painter, rect); - } - QMainWindow::paintEvent(event); -} - -void QtAcrylicMainWindow::changeEvent(QEvent *event) -{ - QMainWindow::changeEvent(event); - if (event->type() == QEvent::WindowStateChange) { - updateContentMargin(); - Q_EMIT windowStateChanged(); - } -} - -void QtAcrylicMainWindow::displaySystemMenu() -{ -#ifdef Q_OS_WINDOWS - Utilities::displaySystemMenu(windowHandle()); -#endif -} diff --git a/qtacrylicmainwindow.h b/qtacrylicmainwindow.h deleted file mode 100644 index 90ad401..0000000 --- a/qtacrylicmainwindow.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * MIT License - * - * Copyright (C) 2021 by wangwenx190 (Yuhang Zhao) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#pragma once - -#include "framelesshelper_global.h" -#include -#include "qtacryliceffecthelper.h" - -class FRAMELESSHELPER_EXPORT QtAcrylicMainWindow : public QMainWindow -{ - Q_OBJECT - Q_DISABLE_COPY_MOVE(QtAcrylicMainWindow) - Q_PROPERTY(QColor tintColor READ tintColor WRITE setTintColor NOTIFY tintColorChanged) - Q_PROPERTY(qreal tintOpacity READ tintOpacity WRITE setTintOpacity NOTIFY tintOpacityChanged) - Q_PROPERTY(qreal noiseOpacity READ noiseOpacity WRITE setNoiseOpacity NOTIFY noiseOpacityChanged) - Q_PROPERTY(bool frameVisible READ frameVisible WRITE setFrameVisible NOTIFY frameVisibleChanged) - Q_PROPERTY(QColor frameColor READ frameColor WRITE setFrameColor NOTIFY frameColorChanged) - Q_PROPERTY(qreal frameThickness READ frameThickness WRITE setFrameThickness NOTIFY frameThicknessChanged) - Q_PROPERTY(bool acrylicEnabled READ acrylicEnabled WRITE setAcrylicEnabled NOTIFY acrylicEnabledChanged) - -public: - explicit QtAcrylicMainWindow(QWidget *parent = nullptr, Qt::WindowFlags flags = {}); - ~QtAcrylicMainWindow() override; - - QColor tintColor() const; - void setTintColor(const QColor &value); - - qreal tintOpacity() const; - void setTintOpacity(const qreal value); - - qreal noiseOpacity() const; - void setNoiseOpacity(const qreal value); - - bool frameVisible() const; - void setFrameVisible(const bool value); - - QColor frameColor() const; - void setFrameColor(const QColor &value); - - qreal frameThickness() const; - void setFrameThickness(const qreal value); - - bool acrylicEnabled() const; - void setAcrylicEnabled(const bool value); - -public Q_SLOTS: - void displaySystemMenu(); - -Q_SIGNALS: - void tintColorChanged(); - void tintOpacityChanged(); - void noiseOpacityChanged(); - void frameVisibleChanged(); - void frameColorChanged(); - void frameThicknessChanged(); - void acrylicEnabledChanged(); - void windowStateChanged(); - -protected: - void showEvent(QShowEvent *event) override; - void paintEvent(QPaintEvent *event) override; - void changeEvent(QEvent *event) override; - -private: - void updateContentMargin(); - -private: - QtAcrylicEffectHelper m_acrylicHelper; - bool m_frameVisible = true; - bool m_acrylicEnabled = false; - bool m_inited = false; -}; diff --git a/qtacrylicwidget.cpp b/qtacrylicwidget.cpp deleted file mode 100644 index b896ee3..0000000 --- a/qtacrylicwidget.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - * MIT License - * - * Copyright (C) 2021 by wangwenx190 (Yuhang Zhao) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "qtacrylicwidget.h" -#include "utilities.h" -#include -#include -#include - -QtAcrylicWidget::QtAcrylicWidget(QWidget *parent) : QWidget(parent) -{ -} - -QtAcrylicWidget::~QtAcrylicWidget() = default; - -QColor QtAcrylicWidget::tintColor() const -{ - const QColor color = m_acrylicHelper.getTintColor(); - if (color.isValid() && (color != Qt::transparent)) { - return color; - } else { - return palette().color(backgroundRole()); - } -} - -void QtAcrylicWidget::setTintColor(const QColor &value) -{ - if (!value.isValid()) { - qWarning() << "Tint color not valid."; - return; - } - if (m_acrylicHelper.getTintColor() != value) { - m_acrylicHelper.setTintColor(value); - QPalette pal = palette(); - pal.setColor(backgroundRole(), m_acrylicHelper.getTintColor()); - setPalette(pal); - //m_acrylicHelper.updateAcrylicBrush(tintColor()); - update(); - Q_EMIT tintColorChanged(); - } -} - -qreal QtAcrylicWidget::tintOpacity() const -{ - return m_acrylicHelper.getTintOpacity(); -} - -void QtAcrylicWidget::setTintOpacity(const qreal value) -{ - if (m_acrylicHelper.getTintOpacity() != value) { - m_acrylicHelper.setTintOpacity(value); - m_acrylicHelper.updateAcrylicBrush(tintColor()); - update(); - Q_EMIT tintOpacityChanged(); - } -} - -qreal QtAcrylicWidget::noiseOpacity() const -{ - return m_acrylicHelper.getNoiseOpacity(); -} - -void QtAcrylicWidget::setNoiseOpacity(const qreal value) -{ - if (m_acrylicHelper.getNoiseOpacity() != value) { - m_acrylicHelper.setNoiseOpacity(value); - m_acrylicHelper.updateAcrylicBrush(tintColor()); - update(); - Q_EMIT noiseOpacityChanged(); - } -} - -bool QtAcrylicWidget::frameVisible() const -{ - return m_frameVisible; -} - -void QtAcrylicWidget::setFrameVisible(const bool value) -{ - if (m_frameVisible != value) { - m_frameVisible = value; - update(); - Q_EMIT frameVisibleChanged(); - } -} - -QColor QtAcrylicWidget::frameColor() const -{ - return m_acrylicHelper.getFrameColor(); -} - -void QtAcrylicWidget::setFrameColor(const QColor &value) -{ - if (m_acrylicHelper.getFrameColor() != value) { - m_acrylicHelper.setFrameColor(value); - update(); - Q_EMIT frameColorChanged(); - } -} - -qreal QtAcrylicWidget::frameThickness() const -{ - return m_acrylicHelper.getFrameThickness(); -} - -void QtAcrylicWidget::setFrameThickness(const qreal value) -{ - if (m_acrylicHelper.getFrameThickness() != value) { - m_acrylicHelper.setFrameThickness(value); - update(); - Q_EMIT frameThicknessChanged(); - } -} - -bool QtAcrylicWidget::acrylicEnabled() const -{ - return m_acrylicEnabled; -} - -void QtAcrylicWidget::setAcrylicEnabled(const bool value) -{ - if (m_acrylicEnabled != value) { - m_acrylicEnabled = value; - if (m_inited) { - Utilities::setBlurEffectEnabled(windowHandle(), m_acrylicEnabled); - } - setAutoFillBackground(!m_acrylicEnabled); - setAttribute(Qt::WA_NoSystemBackground, m_acrylicEnabled); - setAttribute(Qt::WA_OpaquePaintEvent, m_acrylicEnabled); - setBackgroundRole(m_acrylicEnabled ? QPalette::Base : QPalette::Window); - update(); - Q_EMIT acrylicEnabledChanged(); - if (m_acrylicEnabled) { - m_acrylicHelper.showWarning(); - } - } -} - -void QtAcrylicWidget::showEvent(QShowEvent *event) -{ - QWidget::showEvent(event); - if (!m_inited) { - m_acrylicHelper.install(windowHandle()); - m_acrylicHelper.updateAcrylicBrush(tintColor()); - connect(&m_acrylicHelper, &QtAcrylicEffectHelper::needsRepaint, this, qOverload<>(&QtAcrylicWidget::update)); - Utilities::setBlurEffectEnabled(windowHandle(), m_acrylicEnabled); - m_inited = true; - } -} - -void QtAcrylicWidget::paintEvent(QPaintEvent *event) -{ - QPainter painter(this); - const QRect rect = {0, 0, width(), height()}; - if (acrylicEnabled()) { - m_acrylicHelper.paintWindowBackground(&painter, rect); - } - if (frameVisible()) { - m_acrylicHelper.paintWindowFrame(&painter, rect); - } - QWidget::paintEvent(event); -} diff --git a/qtacrylicwidget.h b/qtacrylicwidget.h deleted file mode 100644 index 9849f59..0000000 --- a/qtacrylicwidget.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * MIT License - * - * Copyright (C) 2021 by wangwenx190 (Yuhang Zhao) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#pragma once - -#include "framelesshelper_global.h" -#include -#include "qtacryliceffecthelper.h" - -class FRAMELESSHELPER_EXPORT QtAcrylicWidget : public QWidget -{ - Q_OBJECT - Q_DISABLE_COPY_MOVE(QtAcrylicWidget) - Q_PROPERTY(QColor tintColor READ tintColor WRITE setTintColor NOTIFY tintColorChanged) - Q_PROPERTY(qreal tintOpacity READ tintOpacity WRITE setTintOpacity NOTIFY tintOpacityChanged) - Q_PROPERTY(qreal noiseOpacity READ noiseOpacity WRITE setNoiseOpacity NOTIFY noiseOpacityChanged) - Q_PROPERTY(bool frameVisible READ frameVisible WRITE setFrameVisible NOTIFY frameVisibleChanged) - Q_PROPERTY(QColor frameColor READ frameColor WRITE setFrameColor NOTIFY frameColorChanged) - Q_PROPERTY(qreal frameThickness READ frameThickness WRITE setFrameThickness NOTIFY frameThicknessChanged) - Q_PROPERTY(bool acrylicEnabled READ acrylicEnabled WRITE setAcrylicEnabled NOTIFY acrylicEnabledChanged) - -public: - explicit QtAcrylicWidget(QWidget *parent = nullptr); - ~QtAcrylicWidget() override; - - QColor tintColor() const; - void setTintColor(const QColor &value); - - qreal tintOpacity() const; - void setTintOpacity(const qreal value); - - qreal noiseOpacity() const; - void setNoiseOpacity(const qreal value); - - bool frameVisible() const; - void setFrameVisible(const bool value); - - QColor frameColor() const; - void setFrameColor(const QColor &value); - - qreal frameThickness() const; - void setFrameThickness(const qreal value); - - bool acrylicEnabled() const; - void setAcrylicEnabled(const bool value); - -Q_SIGNALS: - void tintColorChanged(); - void tintOpacityChanged(); - void noiseOpacityChanged(); - void frameVisibleChanged(); - void frameColorChanged(); - void frameThicknessChanged(); - void acrylicEnabledChanged(); - -protected: - void showEvent(QShowEvent *event) override; - void paintEvent(QPaintEvent *event) override; - -private: - QtAcrylicEffectHelper m_acrylicHelper; - bool m_frameVisible = true; - bool m_acrylicEnabled = false; - bool m_inited = false; -}; diff --git a/resources/noise.png b/resources/noise.png deleted file mode 100644 index a78e829..0000000 Binary files a/resources/noise.png and /dev/null differ diff --git a/utilities.cpp b/utilities.cpp index ee2d7cc..1659deb 100644 --- a/utilities.cpp +++ b/utilities.cpp @@ -23,345 +23,8 @@ */ #include "utilities.h" -#include -#include -#include -#include #include - -/* - * Copied from https://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/effects/qpixmapfilter.cpp - * With minor modifications, most of them are format changes. - * They are exported functions of Qt, we can make use of them directly, but they are in the QtWidgets - * module, I don't want our library have such a dependency. - */ - -#ifndef AVG -#define AVG(a,b) ( ((((a)^(b)) & 0xfefefefeUL) >> 1) + ((a)&(b)) ) -#endif - -#ifndef AVG16 -#define AVG16(a,b) ( ((((a)^(b)) & 0xf7deUL) >> 1) + ((a)&(b)) ) -#endif - -template -static inline int qt_static_shift(const int value) -{ - if (shift == 0) { - return value; - } else if (shift > 0) { - return value << (uint(shift) & 0x1f); - } else { - return value >> (uint(-shift) & 0x1f); - } -} - -template -static inline void qt_blurinner(uchar *bptr, int &zR, int &zG, int &zB, int &zA, const int alpha) -{ - QRgb *pixel = reinterpret_cast(bptr); -#define Z_MASK (0xff << zprec) - const int A_zprec = qt_static_shift(*pixel) & Z_MASK; - const int R_zprec = qt_static_shift(*pixel) & Z_MASK; - const int G_zprec = qt_static_shift(*pixel) & Z_MASK; - const int B_zprec = qt_static_shift(*pixel) & Z_MASK; -#undef Z_MASK - const int zR_zprec = zR >> aprec; - const int zG_zprec = zG >> aprec; - const int zB_zprec = zB >> aprec; - const int zA_zprec = zA >> aprec; - zR += alpha * (R_zprec - zR_zprec); - zG += alpha * (G_zprec - zG_zprec); - zB += alpha * (B_zprec - zB_zprec); - zA += alpha * (A_zprec - zA_zprec); -#define ZA_MASK (0xff << (zprec + aprec)) - *pixel = - qt_static_shift<24 - zprec - aprec>(zA & ZA_MASK) - | qt_static_shift<16 - zprec - aprec>(zR & ZA_MASK) - | qt_static_shift<8 - zprec - aprec>(zG & ZA_MASK) - | qt_static_shift<-zprec - aprec>(zB & ZA_MASK); -#undef ZA_MASK -} - -static const int alphaIndex = ((QSysInfo::ByteOrder == QSysInfo::BigEndian) ? 0 : 3); - -template -static inline void qt_blurinner_alphaOnly(uchar *bptr, int &z, const int alpha) -{ - const int A_zprec = int(*(bptr)) << zprec; - const int z_zprec = z >> aprec; - z += alpha * (A_zprec - z_zprec); - *(bptr) = z >> (zprec + aprec); -} - -template -static inline void qt_blurrow(QImage &im, const int line, const int alpha) -{ - uchar *bptr = im.scanLine(line); - int zR = 0, zG = 0, zB = 0, zA = 0; - if (alphaOnly && (im.format() != QImage::Format_Indexed8)) { - bptr += alphaIndex; - } - const int stride = im.depth() >> 3; - const int im_width = im.width(); - for (int index = 0; index < im_width; ++index) { - if (alphaOnly) { - qt_blurinner_alphaOnly(bptr, zA, alpha); - } else { - qt_blurinner(bptr, zR, zG, zB, zA, alpha); - } - bptr += stride; - } - bptr -= stride; - for (int index = im_width - 2; index >= 0; --index) { - bptr -= stride; - if (alphaOnly) { - qt_blurinner_alphaOnly(bptr, zA, alpha); - } else { - qt_blurinner(bptr, zR, zG, zB, zA, alpha); - } - } -} - -/* - * expblur(QImage &img, const qreal radius) - * - * Based on exponential blur algorithm by Jani Huhtanen - * - * In-place blur of image 'img' with kernel - * of approximate radius 'radius'. - * - * Blurs with two sided exponential impulse - * response. - * - * aprec = precision of alpha parameter - * in fixed-point format 0.aprec - * - * zprec = precision of state parameters - * zR,zG,zB and zA in fp format 8.zprec - */ -template -static inline void expblur(QImage &img, const qreal radius, const bool improvedQuality = false, const int transposed = 0) -{ - qreal _radius = radius; - // halve the radius if we're using two passes - if (improvedQuality) { - _radius *= 0.5; - } - Q_ASSERT((img.format() == QImage::Format_ARGB32_Premultiplied) - || (img.format() == QImage::Format_RGB32) - || (img.format() == QImage::Format_Indexed8) - || (img.format() == QImage::Format_Grayscale8)); - // choose the alpha such that pixels at radius distance from a fully - // saturated pixel will have an alpha component of no greater than - // the cutOffIntensity - const qreal cutOffIntensity = 2; - const int alpha = _radius <= qreal(1e-5) - ? ((1 << aprec)-1) - : qRound((1<(img, row, alpha); - } - } - // TODO: QImage(int width, int height, QImage::Format format) - // Why the argument order is inverted here? The application will crash if change it back. - QImage temp(img.height(), img.width(), img.format()); - temp.setDevicePixelRatio(img.devicePixelRatio()); - if (transposed >= 0) { - if (img.depth() == 8) { - qt_memrotate270(reinterpret_cast(img.bits()), - img.width(), img.height(), img.bytesPerLine(), - reinterpret_cast(temp.bits()), - temp.bytesPerLine()); - } else { - qt_memrotate270(reinterpret_cast(img.bits()), - img.width(), img.height(), img.bytesPerLine(), - reinterpret_cast(temp.bits()), - temp.bytesPerLine()); - } - } else { - if (img.depth() == 8) { - qt_memrotate90(reinterpret_cast(img.bits()), - img.width(), img.height(), img.bytesPerLine(), - reinterpret_cast(temp.bits()), - temp.bytesPerLine()); - } else { - qt_memrotate90(reinterpret_cast(img.bits()), - img.width(), img.height(), img.bytesPerLine(), - reinterpret_cast(temp.bits()), - temp.bytesPerLine()); - } - } - img_height = temp.height(); - for (int row = 0; row < img_height; ++row) { - for (int i = 0; i <= int(improvedQuality); ++i) { - qt_blurrow(temp, row, alpha); - } - } - if (transposed == 0) { - if (img.depth() == 8) { - qt_memrotate90(reinterpret_cast(temp.bits()), - temp.width(), temp.height(), temp.bytesPerLine(), - reinterpret_cast(img.bits()), - img.bytesPerLine()); - } else { - qt_memrotate90(reinterpret_cast(temp.bits()), - temp.width(), temp.height(), temp.bytesPerLine(), - reinterpret_cast(img.bits()), - img.bytesPerLine()); - } - } else { - img = temp; - } -} - -static inline QImage qt_halfScaled(const QImage &source) -{ - if (source.width() < 2 || source.height() < 2) { - return {}; - } - QImage srcImage = source; - if (source.format() == QImage::Format_Indexed8 || source.format() == QImage::Format_Grayscale8) { - // assumes grayscale - QImage dest(source.width() / 2, source.height() / 2, srcImage.format()); - dest.setDevicePixelRatio(source.devicePixelRatio()); - const uchar *src = reinterpret_cast(const_cast(srcImage).bits()); - qsizetype sx = srcImage.bytesPerLine(); - qsizetype sx2 = sx << 1; - uchar *dst = reinterpret_cast(dest.bits()); - qsizetype dx = dest.bytesPerLine(); - int ww = dest.width(); - int hh = dest.height(); - for (int y = hh; y; --y, dst += dx, src += sx2) { - const uchar *p1 = src; - const uchar *p2 = src + sx; - uchar *q = dst; - for (int x = ww; x; --x, ++q, p1 += 2, p2 += 2) { - *q = ((int(p1[0]) + int(p1[1]) + int(p2[0]) + int(p2[1])) + 2) >> 2; - } - } - return dest; - } else if (source.format() == QImage::Format_ARGB8565_Premultiplied) { - QImage dest(source.width() / 2, source.height() / 2, srcImage.format()); - dest.setDevicePixelRatio(source.devicePixelRatio()); - const uchar *src = reinterpret_cast(const_cast(srcImage).bits()); - qsizetype sx = srcImage.bytesPerLine(); - qsizetype sx2 = sx << 1; - uchar *dst = reinterpret_cast(dest.bits()); - qsizetype dx = dest.bytesPerLine(); - int ww = dest.width(); - int hh = dest.height(); - for (int y = hh; y; --y, dst += dx, src += sx2) { - const uchar *p1 = src; - const uchar *p2 = src + sx; - uchar *q = dst; - for (int x = ww; x; --x, q += 3, p1 += 6, p2 += 6) { - // alpha - q[0] = AVG(AVG(p1[0], p1[3]), AVG(p2[0], p2[3])); - // rgb - const quint16 p16_1 = (p1[2] << 8) | p1[1]; - const quint16 p16_2 = (p1[5] << 8) | p1[4]; - const quint16 p16_3 = (p2[2] << 8) | p2[1]; - const quint16 p16_4 = (p2[5] << 8) | p2[4]; - const quint16 result = AVG16(AVG16(p16_1, p16_2), AVG16(p16_3, p16_4)); - q[1] = result & 0xff; - q[2] = result >> 8; - } - } - return dest; - } else if ((source.format() != QImage::Format_ARGB32_Premultiplied) && (source.format() != QImage::Format_RGB32)) { - srcImage = source.convertToFormat(QImage::Format_ARGB32_Premultiplied); - } - QImage dest(source.width() / 2, source.height() / 2, srcImage.format()); - dest.setDevicePixelRatio(source.devicePixelRatio()); - const quint32 *src = reinterpret_cast(const_cast(srcImage).bits()); - qsizetype sx = srcImage.bytesPerLine() >> 2; - qsizetype sx2 = sx << 1; - quint32 *dst = reinterpret_cast(dest.bits()); - qsizetype dx = dest.bytesPerLine() >> 2; - int ww = dest.width(); - int hh = dest.height(); - for (int y = hh; y; --y, dst += dx, src += sx2) { - const quint32 *p1 = src; - const quint32 *p2 = src + sx; - quint32 *q = dst; - for (int x = ww; x; --x, q++, p1 += 2, p2 += 2) { - *q = AVG(AVG(p1[0], p1[1]), AVG(p2[0], p2[1])); - } - } - return dest; -} - -void Utilities::blurImage(QPainter *painter, QImage &blurImage, const qreal radius, const bool quality, const bool alphaOnly, const int transposed) -{ - if ((blurImage.format() != QImage::Format_ARGB32_Premultiplied) && (blurImage.format() != QImage::Format_RGB32)) { - blurImage = blurImage.convertToFormat(QImage::Format_ARGB32_Premultiplied); - } - qreal _radius = radius; - qreal scale = 1; - if ((_radius >= 4) && (blurImage.width() >= 2) && (blurImage.height() >= 2)) { - blurImage = qt_halfScaled(blurImage); - scale = 2; - _radius *= 0.5; - } - if (alphaOnly) { - expblur<12, 10, true>(blurImage, _radius, quality, transposed); - } else { - expblur<12, 10, false>(blurImage, _radius, quality, transposed); - } - if (painter) { - painter->scale(scale, scale); - painter->setRenderHint(QPainter::SmoothPixmapTransform); - painter->drawImage(QRect{QPoint{0, 0}, blurImage.size() / blurImage.devicePixelRatio()}, blurImage); - } -} - -void Utilities::blurImage(QImage &blurImage, const qreal radius, const bool quality, const int transposed) -{ - if ((blurImage.format() == QImage::Format_Indexed8) || (blurImage.format() == QImage::Format_Grayscale8)) { - expblur<12, 10, true>(blurImage, radius, quality, transposed); - } else { - expblur<12, 10, false>(blurImage, radius, quality, transposed); - } -} - -/////////////////////////////////////////////////// - -/* - * Copied from https://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/styles/qstyle.cpp - * With minor modifications, most of them are format changes. - * They are exported functions of Qt, we can make use of them directly, but they are in the QtWidgets - * module, I don't want our library have such a dependency. - */ - -static inline Qt::Alignment visualAlignment(const Qt::LayoutDirection direction, const Qt::Alignment alignment) -{ - return QGuiApplicationPrivate::visualAlignment(direction, alignment); -} - -QRect Utilities::alignedRect(const Qt::LayoutDirection direction, const Qt::Alignment alignment, const QSize &size, const QRect &rectangle) -{ - const Qt::Alignment align = visualAlignment(direction, alignment); - int x = rectangle.x(); - int y = rectangle.y(); - const int w = size.width(); - const int h = size.height(); - if ((align & Qt::AlignVCenter) == Qt::AlignVCenter) { - y += rectangle.size().height() / 2 - h / 2; - } else if ((align & Qt::AlignBottom) == Qt::AlignBottom) { - y += rectangle.size().height() - h; - } - if ((align & Qt::AlignRight) == Qt::AlignRight) { - x += rectangle.size().width() - w; - } else if ((align & Qt::AlignHCenter) == Qt::AlignHCenter) { - x += rectangle.size().width() / 2 - w / 2; - } - return {x, y, w, h}; -} - -/////////////////////////////////////////////////// +#include QWindow *Utilities::findWindow(const WId winId) { @@ -380,37 +43,6 @@ QWindow *Utilities::findWindow(const WId winId) return nullptr; } -QRect Utilities::getScreenAvailableGeometry(const QWindow *window) -{ - if (window) { - const QScreen *screen = window->screen(); - if (screen) { - return screen->availableGeometry(); - } - } - return QGuiApplication::primaryScreen()->availableGeometry(); -} - -bool Utilities::shouldUseWallpaperBlur() -{ - return !shouldUseTraditionalBlur(); -} - -bool Utilities::disableExtraProcessingForBlur() -{ - return qEnvironmentVariableIsSet(_flh_global::_flh_acrylic_disableExtraProcess); -} - -bool Utilities::forceEnableTraditionalBlur() -{ - return qEnvironmentVariableIsSet(_flh_global::_flh_acrylic_forceEnableTraditionalBlur_flag); -} - -bool Utilities::forceDisableWallpaperBlur() -{ - return qEnvironmentVariableIsSet(_flh_global::_flh_acrylic_forceDisableWallpaperBlur_flag); -} - bool Utilities::shouldUseNativeTitleBar() { return qEnvironmentVariableIsSet(_flh_global::_flh_useNativeTitleBar_flag); @@ -482,36 +114,3 @@ bool Utilities::isMouseInSpecificObjects(const QPointF &mousePos, const QObjectL } return false; } - -QRect Utilities::getScreenAvailableGeometry(const QPoint &pos) -{ - if (!pos.isNull()) { - const QScreen *screen = QGuiApplication::screenAt(pos); - if (screen) { - return screen->availableGeometry(); - } - } - return QGuiApplication::primaryScreen()->availableGeometry(); -} - -QRect Utilities::getScreenGeometry(const QWindow *window) -{ - if (window) { - const QScreen *screen = window->screen(); - if (screen) { - return screen->geometry(); - } - } - return QGuiApplication::primaryScreen()->geometry(); -} - -QRect Utilities::getScreenGeometry(const QPoint &pos) -{ - if (!pos.isNull()) { - const QScreen *screen = QGuiApplication::screenAt(pos); - if (screen) { - return screen->geometry(); - } - } - return QGuiApplication::primaryScreen()->geometry(); -} diff --git a/utilities.h b/utilities.h index d28a8b9..08df5e2 100644 --- a/utilities.h +++ b/utilities.h @@ -37,21 +37,7 @@ enum class SystemMetric TitleBarHeight }; -enum class DesktopWallpaperAspectStyle -{ - Central, - Tiled, - IgnoreRatioFit, // Stretch - KeepRatioFit, // Fit - KeepRatioByExpanding, // Fill - Span -}; - // Common -FRAMELESSHELPER_EXPORT bool shouldUseWallpaperBlur(); -FRAMELESSHELPER_EXPORT bool shouldUseTraditionalBlur(); -FRAMELESSHELPER_EXPORT bool setBlurEffectEnabled(const QWindow *window, const bool enabled, const QColor &gradientColor = {}); - FRAMELESSHELPER_EXPORT int getSystemMetric(const QWindow *window, const SystemMetric metric, const bool dpiAware, const bool forceSystemValue = false); FRAMELESSHELPER_EXPORT bool isLightThemeEnabled(); @@ -59,30 +45,14 @@ FRAMELESSHELPER_EXPORT bool isDarkThemeEnabled(); FRAMELESSHELPER_EXPORT QWindow *findWindow(const WId winId); -FRAMELESSHELPER_EXPORT QImage getDesktopWallpaperImage(const int screen = -1); -FRAMELESSHELPER_EXPORT QColor getDesktopBackgroundColor(const int screen = -1); -FRAMELESSHELPER_EXPORT DesktopWallpaperAspectStyle getDesktopWallpaperAspectStyle(const int screen = -1); - -FRAMELESSHELPER_EXPORT QRect getScreenAvailableGeometry(const QWindow *window); -FRAMELESSHELPER_EXPORT QRect getScreenAvailableGeometry(const QPoint &pos); - -FRAMELESSHELPER_EXPORT QRect getScreenGeometry(const QWindow *window); -FRAMELESSHELPER_EXPORT QRect getScreenGeometry(const QPoint &pos); - -FRAMELESSHELPER_EXPORT QRect alignedRect(const Qt::LayoutDirection direction, const Qt::Alignment alignment, const QSize &size, const QRect &rectangle); - -FRAMELESSHELPER_EXPORT void blurImage(QImage &blurImage, const qreal radius, const bool quality, const int transposed = 0); -FRAMELESSHELPER_EXPORT void blurImage(QPainter *painter, QImage &blurImage, const qreal radius, const bool quality, const bool alphaOnly, const int transposed = 0); - -FRAMELESSHELPER_EXPORT bool disableExtraProcessingForBlur(); -FRAMELESSHELPER_EXPORT bool forceEnableTraditionalBlur(); -FRAMELESSHELPER_EXPORT bool forceDisableWallpaperBlur(); FRAMELESSHELPER_EXPORT bool shouldUseNativeTitleBar(); FRAMELESSHELPER_EXPORT bool isWindowFixedSize(const QWindow *window); FRAMELESSHELPER_EXPORT bool isMouseInSpecificObjects(const QPointF &mousePos, const QObjectList &objects, const qreal dpr = 1.0); +FRAMELESSHELPER_EXPORT QColor getNativeWindowFrameColor(const bool isActive = true); + #ifdef Q_OS_WINDOWS // Windows specific FRAMELESSHELPER_EXPORT bool isWin7OrGreater(); @@ -92,22 +62,16 @@ FRAMELESSHELPER_EXPORT bool isWin10OrGreater(); FRAMELESSHELPER_EXPORT bool isWin10OrGreater(const int subVer); FRAMELESSHELPER_EXPORT bool isDwmBlurAvailable(); -FRAMELESSHELPER_EXPORT bool isOfficialMSWin10AcrylicBlurAvailable(); FRAMELESSHELPER_EXPORT bool isColorizationEnabled(); FRAMELESSHELPER_EXPORT QColor getColorizationColor(); -FRAMELESSHELPER_EXPORT bool isHighContrastModeEnabled(); -FRAMELESSHELPER_EXPORT bool isDarkFrameEnabled(const QWindow *window); -FRAMELESSHELPER_EXPORT bool isTransparencyEffectEnabled(); - FRAMELESSHELPER_EXPORT void triggerFrameChange(const QWindow *window); FRAMELESSHELPER_EXPORT void updateFrameMargins(const QWindow *window, const bool reset); FRAMELESSHELPER_EXPORT void updateQtFrameMargins(QWindow *window, const bool enable); FRAMELESSHELPER_EXPORT quint32 getWindowDpi(const QWindow *window); FRAMELESSHELPER_EXPORT QMargins getWindowNativeFrameMargins(const QWindow *window); -FRAMELESSHELPER_EXPORT QColor getNativeWindowFrameColor(const bool isActive = true); FRAMELESSHELPER_EXPORT void displaySystemMenu(const QWindow *window, const QPoint &pos = {}); #endif diff --git a/utilities_win32.cpp b/utilities_win32.cpp index 7aa0535..495e289 100644 --- a/utilities_win32.cpp +++ b/utilities_win32.cpp @@ -36,11 +36,7 @@ #include #include #include -#include #include -#include -#include -#include #include #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) #include @@ -52,9 +48,6 @@ #else #include #endif -#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) -#include -#endif Q_DECLARE_METATYPE(QMargins) @@ -68,61 +61,8 @@ Q_DECLARE_METATYPE(QMargins) #define SM_CXPADDEDBORDER 92 #endif -enum : WORD -{ - DwmwaUseImmersiveDarkMode = 20, - DwmwaUseImmersiveDarkModeBefore20h1 = 19 -}; - -using WINDOWCOMPOSITIONATTRIB = enum _WINDOWCOMPOSITIONATTRIB -{ - WCA_ACCENT_POLICY = 19 -}; - -using WINDOWCOMPOSITIONATTRIBDATA = struct _WINDOWCOMPOSITIONATTRIBDATA -{ - WINDOWCOMPOSITIONATTRIB Attrib; - PVOID pvData; - SIZE_T cbData; -}; - -using ACCENT_STATE = enum _ACCENT_STATE -{ - ACCENT_DISABLED = 0, - ACCENT_ENABLE_GRADIENT = 1, - ACCENT_ENABLE_TRANSPARENTGRADIENT = 2, - ACCENT_ENABLE_BLURBEHIND = 3, - ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, // RS4 1803 - ACCENT_ENABLE_HOSTBACKDROP = 5, // RS5 1809 - ACCENT_INVALID_STATE = 6 -}; - -using ACCENT_POLICY = struct _ACCENT_POLICY -{ - ACCENT_STATE AccentState; - DWORD AccentFlags; - COLORREF GradientColor; - DWORD AnimationId; -}; - -using IMMERSIVE_HC_CACHE_MODE = enum _IMMERSIVE_HC_CACHE_MODE -{ - IHCM_USE_CACHED_VALUE, - IHCM_REFRESH -}; - -using PREFERRED_APP_MODE = enum _PREFERRED_APP_MODE -{ - Default, - AllowDark, - ForceDark, - ForceLight, - Max -}; - static const QString g_dwmRegistryKey = QStringLiteral(R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM)"); static const QString g_personalizeRegistryKey = QStringLiteral(R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)"); -static const QString g_desktopRegistryKey = QStringLiteral(R"(HKEY_CURRENT_USER\Control Panel\Desktop)"); // The standard values of border width, border height and title bar height when DPI is 96. static const int g_defaultBorderWidth = 8, g_defaultBorderHeight = 8, g_defaultTitleBarHeight = 31; @@ -139,16 +79,8 @@ using PROCESS_DPI_AWARENESS = enum _PROCESS_DPI_AWARENESS PROCESS_PER_MONITOR_DPI_AWARE = 2 }; -using SetWindowCompositionAttributePtr = BOOL(WINAPI *)(HWND, WINDOWCOMPOSITIONATTRIBDATA *); using ShouldAppsUseDarkModePtr = BOOL(WINAPI *)(); -using AllowDarkModeForWindowPtr = BOOL(WINAPI *)(HWND, BOOL); -using AllowDarkModeForAppPtr = BOOL(WINAPI *)(BOOL); -using IsDarkModeAllowedForWindowPtr = BOOL(WINAPI *)(HWND); -using GetIsImmersiveColorUsingHighContrastPtr = BOOL(WINAPI *)(IMMERSIVE_HC_CACHE_MODE); -using RefreshImmersiveColorPolicyStatePtr = VOID(WINAPI *)(); using ShouldSystemUseDarkModePtr = BOOL(WINAPI *)(); -using SetPreferredAppModePtr = PREFERRED_APP_MODE(WINAPI *)(PREFERRED_APP_MODE); -using IsDarkModeAllowedForAppPtr = BOOL(WINAPI *)(); using GetDpiForMonitorPtr = HRESULT(WINAPI *)(HMONITOR, MONITOR_DPI_TYPE, UINT *, UINT *); using GetProcessDpiAwarenessPtr = HRESULT(WINAPI *)(HANDLE, PROCESS_DPI_AWARENESS *); @@ -160,18 +92,8 @@ using AdjustWindowRectExForDpiPtr = BOOL(WINAPI *)(LPRECT, DWORD, BOOL, DWORD, U using Win32Data = struct _FLH_UTILITIES_WIN32_DATA { - _FLH_UTILITIES_WIN32_DATA() { load(); } - - SetWindowCompositionAttributePtr SetWindowCompositionAttributePFN = nullptr; ShouldAppsUseDarkModePtr ShouldAppsUseDarkModePFN = nullptr; - AllowDarkModeForWindowPtr AllowDarkModeForWindowPFN = nullptr; - AllowDarkModeForAppPtr AllowDarkModeForAppPFN = nullptr; - IsDarkModeAllowedForWindowPtr IsDarkModeAllowedForWindowPFN = nullptr; - GetIsImmersiveColorUsingHighContrastPtr GetIsImmersiveColorUsingHighContrastPFN = nullptr; - RefreshImmersiveColorPolicyStatePtr RefreshImmersiveColorPolicyStatePFN = nullptr; ShouldSystemUseDarkModePtr ShouldSystemUseDarkModePFN = nullptr; - SetPreferredAppModePtr SetPreferredAppModePFN = nullptr; - IsDarkModeAllowedForAppPtr IsDarkModeAllowedForAppPFN = nullptr; GetDpiForMonitorPtr GetDpiForMonitorPFN = nullptr; GetProcessDpiAwarenessPtr GetProcessDpiAwarenessPFN = nullptr; @@ -181,10 +103,14 @@ using Win32Data = struct _FLH_UTILITIES_WIN32_DATA GetSystemMetricsForDpiPtr GetSystemMetricsForDpiPFN = nullptr; AdjustWindowRectExForDpiPtr AdjustWindowRectExForDpiPFN = nullptr; + _FLH_UTILITIES_WIN32_DATA() + { + load(); + } + void load() { QLibrary User32Dll(QStringLiteral("User32")); - SetWindowCompositionAttributePFN = reinterpret_cast(User32Dll.resolve("SetWindowCompositionAttribute")); GetDpiForWindowPFN = reinterpret_cast(User32Dll.resolve("GetDpiForWindow")); GetDpiForSystemPFN = reinterpret_cast(User32Dll.resolve("GetDpiForSystem")); GetSystemMetricsForDpiPFN = reinterpret_cast(User32Dll.resolve("GetSystemMetricsForDpi")); @@ -193,14 +119,7 @@ using Win32Data = struct _FLH_UTILITIES_WIN32_DATA QLibrary UxThemeDll(QStringLiteral("UxTheme")); ShouldAppsUseDarkModePFN = reinterpret_cast(UxThemeDll.resolve(MAKEINTRESOURCEA(132))); - AllowDarkModeForWindowPFN = reinterpret_cast(UxThemeDll.resolve(MAKEINTRESOURCEA(133))); - AllowDarkModeForAppPFN = reinterpret_cast(UxThemeDll.resolve(MAKEINTRESOURCEA(135))); - RefreshImmersiveColorPolicyStatePFN = reinterpret_cast(UxThemeDll.resolve(MAKEINTRESOURCEA(104))); - IsDarkModeAllowedForWindowPFN = reinterpret_cast(UxThemeDll.resolve(MAKEINTRESOURCEA(137))); - GetIsImmersiveColorUsingHighContrastPFN = reinterpret_cast(UxThemeDll.resolve(MAKEINTRESOURCEA(106))); ShouldSystemUseDarkModePFN = reinterpret_cast(UxThemeDll.resolve(MAKEINTRESOURCEA(138))); - SetPreferredAppModePFN = reinterpret_cast(UxThemeDll.resolve(MAKEINTRESOURCEA(135))); - IsDarkModeAllowedForAppPFN = reinterpret_cast(UxThemeDll.resolve(MAKEINTRESOURCEA(139))); QLibrary SHCoreDll(QStringLiteral("SHCore")); GetDpiForMonitorPFN = reinterpret_cast(SHCoreDll.resolve("GetDpiForMonitor")); @@ -294,72 +213,6 @@ int Utilities::getSystemMetric(const QWindow *window, const SystemMetric metric, return ret; } -bool Utilities::setBlurEffectEnabled(const QWindow *window, const bool enabled, const QColor &gradientColor) -{ - Q_ASSERT(window); - if (!window) { - return false; - } - const auto hwnd = reinterpret_cast(window->winId()); - Q_ASSERT(hwnd); - if (!hwnd) { - return false; - } - bool result = false; - // We prefer DwmEnableBlurBehindWindow on Windows 7. - if (isWin8OrGreater() && win32Data()->SetWindowCompositionAttributePFN) { - ACCENT_POLICY accentPolicy; - SecureZeroMemory(&accentPolicy, sizeof(accentPolicy)); - WINDOWCOMPOSITIONATTRIBDATA wcaData; - SecureZeroMemory(&wcaData, sizeof(wcaData)); - wcaData.Attrib = WCA_ACCENT_POLICY; - wcaData.pvData = &accentPolicy; - wcaData.cbData = sizeof(accentPolicy); - if (enabled) { - // The gradient color must be set otherwise it'll look like a classic blur. - // Use semi-transparent gradient color to get better appearance. - if (gradientColor.isValid()) { - accentPolicy.GradientColor = qRgba(gradientColor.blue(), gradientColor.green(), gradientColor.red(), gradientColor.alpha()); - } else { - const QColor colorizationColor = getColorizationColor(); - accentPolicy.GradientColor = - RGB(qRound(colorizationColor.red() * (colorizationColor.alpha() / 255.0) + 255 - colorizationColor.alpha()), - qRound(colorizationColor.green() * (colorizationColor.alpha() / 255.0) + 255 - colorizationColor.alpha()), - qRound(colorizationColor.blue() * (colorizationColor.alpha() / 255.0) + 255 - colorizationColor.alpha())); - } - if (isOfficialMSWin10AcrylicBlurAvailable()) { - accentPolicy.AccentState = ACCENT_ENABLE_ACRYLICBLURBEHIND; - if (!gradientColor.isValid()) { - accentPolicy.GradientColor = 0x01FFFFFF; - } - } else { - accentPolicy.AccentState = ACCENT_ENABLE_BLURBEHIND; - } - } else { - accentPolicy.AccentState = ACCENT_DISABLED; - } - result = (win32Data()->SetWindowCompositionAttributePFN(hwnd, &wcaData) != FALSE); - if (!result) { - qWarning() << "SetWindowCompositionAttribute failed."; - } - } else { - DWM_BLURBEHIND dwmBB; - SecureZeroMemory(&dwmBB, sizeof(dwmBB)); - dwmBB.dwFlags = DWM_BB_ENABLE; - dwmBB.fEnable = enabled ? TRUE : FALSE; - result = SUCCEEDED(DwmEnableBlurBehindWindow(hwnd, &dwmBB)); - if (!result) { - qWarning() << "DwmEnableBlurBehindWindow failed."; - } - } - if (result) { - const auto win = const_cast(window); - win->setProperty(_flh_global::_flh_acrylic_blurEnabled_flag, enabled); - win->setProperty(_flh_global::_flh_acrylic_gradientColor_flag, gradientColor); - } - return result; -} - bool Utilities::isColorizationEnabled() { if (!isWin10OrGreater()) { @@ -411,50 +264,6 @@ bool Utilities::isDarkThemeEnabled() return (ok && !lightThemeEnabled); } -bool Utilities::isHighContrastModeEnabled() -{ - HIGHCONTRASTW hc; - SecureZeroMemory(&hc, sizeof(hc)); - hc.cbSize = sizeof(hc); - if (SystemParametersInfoW(SPI_GETHIGHCONTRAST, 0, &hc, 0) == FALSE) { - qWarning() << "SystemParametersInfoW failed."; - return false; - } - return hc.dwFlags & HCF_HIGHCONTRASTON; -} - -bool Utilities::isDarkFrameEnabled(const QWindow *window) -{ - Q_ASSERT(window); - if (!window) { - return false; - } - if (!isWin10OrGreater(17763)) { - return false; - } - const auto hwnd = reinterpret_cast(window->winId()); - Q_ASSERT(hwnd); - if (!hwnd) { - return false; - } - BOOL result = FALSE; - const bool ok = SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkMode, &result, sizeof(result))) - || SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkModeBefore20h1, &result, sizeof(result))); - return (ok && result); -} - -bool Utilities::isTransparencyEffectEnabled() -{ - if (!isWin10OrGreater()) { - return false; - } - // TODO: Is there an official Win32 API to do this? - bool ok = false; - const QSettings registry(g_personalizeRegistryKey, QSettings::NativeFormat); - const bool transparencyEnabled = registry.value(QStringLiteral("EnableTransparency"), 0).toULongLong(&ok) != 0; - return (ok && transparencyEnabled); -} - void Utilities::triggerFrameChange(const QWindow *window) { Q_ASSERT(window); @@ -488,243 +297,6 @@ void Utilities::updateFrameMargins(const QWindow *window, const bool reset) } } -QImage Utilities::getDesktopWallpaperImage(const int screen) -{ - if (isWin8OrGreater()) { - if (SUCCEEDED(CoInitialize(nullptr))) { - IDesktopWallpaper* pDesktopWallpaper = nullptr; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) - const auto cleanup = qScopeGuard([pDesktopWallpaper](){ - if (pDesktopWallpaper) { - pDesktopWallpaper->Release(); - } - CoUninitialize(); - }); -#endif - // TODO: Why CLSCTX_INPROC_SERVER failed? - if (SUCCEEDED(CoCreateInstance(CLSID_DesktopWallpaper, nullptr, CLSCTX_LOCAL_SERVER, IID_IDesktopWallpaper, reinterpret_cast(&pDesktopWallpaper))) && pDesktopWallpaper) { - UINT monitorCount = 0; - if (SUCCEEDED(pDesktopWallpaper->GetMonitorDevicePathCount(&monitorCount))) { - if (screen > int(monitorCount - 1)) { - qWarning() << "Screen number above total screen count."; - return {}; - } - const UINT monitorIndex = qMax(screen, 0); - LPWSTR monitorId = nullptr; - if (SUCCEEDED(pDesktopWallpaper->GetMonitorDevicePathAt(monitorIndex, &monitorId)) && monitorId) { - LPWSTR wallpaperPath = nullptr; - if (SUCCEEDED(pDesktopWallpaper->GetWallpaper(monitorId, &wallpaperPath)) && wallpaperPath) { - CoTaskMemFree(monitorId); - const QString _path = QString::fromWCharArray(wallpaperPath); - CoTaskMemFree(wallpaperPath); - return QImage(_path); - } else { - CoTaskMemFree(monitorId); - qWarning() << "IDesktopWallpaper::GetWallpaper() failed."; - } - } else { - qWarning() << "IDesktopWallpaper::GetMonitorDevicePathAt() failed"; - } - } else { - qWarning() << "IDesktopWallpaper::GetMonitorDevicePathCount() failed"; - } - } else { - qWarning() << "Failed to create COM instance - DesktopWallpaper."; - } - } else { - qWarning() << "Failed to initialize COM."; - } - qDebug() << "The IDesktopWallpaper interface failed. Trying the IActiveDesktop interface instead."; - } - if (SUCCEEDED(CoInitialize(nullptr))) { - IActiveDesktop *pActiveDesktop = nullptr; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) - const auto cleanup = qScopeGuard([pActiveDesktop](){ - if (pActiveDesktop) { - pActiveDesktop->Release(); - } - CoUninitialize(); - }); -#endif - if (SUCCEEDED(CoCreateInstance(CLSID_ActiveDesktop, nullptr, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, reinterpret_cast(&pActiveDesktop))) && pActiveDesktop) { - const auto wallpaperPath = new WCHAR[MAX_PATH]; - // TODO: AD_GETWP_BMP, AD_GETWP_IMAGE, AD_GETWP_LAST_APPLIED. What's the difference? - if (SUCCEEDED(pActiveDesktop->GetWallpaper(wallpaperPath, MAX_PATH, AD_GETWP_LAST_APPLIED))) { - const QString _path = QString::fromWCharArray(wallpaperPath); - delete [] wallpaperPath; - return QImage(_path); - } else { - qWarning() << "IActiveDesktop::GetWallpaper() failed."; - } - } else { - qWarning() << "Failed to create COM instance - ActiveDesktop."; - } - } else { - qWarning() << "Failed to initialize COM."; - } - qDebug() << "Shell API failed. Using SystemParametersInfoW instead."; - const auto wallpaperPath = new WCHAR[MAX_PATH]; - if (SystemParametersInfoW(SPI_GETDESKWALLPAPER, MAX_PATH, wallpaperPath, 0) != FALSE) { - const QString _path = QString::fromWCharArray(wallpaperPath); - delete [] wallpaperPath; - return QImage(_path); - } - qWarning() << "SystemParametersInfoW failed. Reading from the registry instead."; - const QSettings settings(g_desktopRegistryKey, QSettings::NativeFormat); - const QString path = settings.value(QStringLiteral("WallPaper")).toString(); - if (QFileInfo::exists(path)) { - return QImage(path); - } - qWarning() << "Failed to read the registry."; - return {}; -} - -QColor Utilities::getDesktopBackgroundColor(const int screen) -{ - Q_UNUSED(screen); - if (isWin8OrGreater()) { - if (SUCCEEDED(CoInitialize(nullptr))) { - IDesktopWallpaper *pDesktopWallpaper = nullptr; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) - const auto cleanup = qScopeGuard([pDesktopWallpaper]() { - if (pDesktopWallpaper) { - pDesktopWallpaper->Release(); - } - CoUninitialize(); - }); -#endif - // TODO: Why CLSCTX_INPROC_SERVER failed? - if (SUCCEEDED(CoCreateInstance(CLSID_DesktopWallpaper, nullptr, CLSCTX_LOCAL_SERVER, IID_IDesktopWallpaper, reinterpret_cast(&pDesktopWallpaper))) && pDesktopWallpaper) { - COLORREF color = 0; - if (SUCCEEDED(pDesktopWallpaper->GetBackgroundColor(&color))) { - return QColor::fromRgba(color); - } else { - qWarning() << "IDesktopWallpaper::GetBackgroundColor() failed."; - } - } else { - qWarning() << "Failed to create COM instance - DesktopWallpaper."; - } - } else { - qWarning() << "Failed to initialize COM."; - } - qDebug() << "The IDesktopWallpaper interface failed."; - } - // TODO: Is there any other way to get the background color? Traditional Win32 API? Registry? - // Is there a Shell API for Win7? - return Qt::black; -} - -Utilities::DesktopWallpaperAspectStyle Utilities::getDesktopWallpaperAspectStyle(const int screen) -{ - Q_UNUSED(screen); - if (isWin8OrGreater()) { - if (SUCCEEDED(CoInitialize(nullptr))) { - IDesktopWallpaper *pDesktopWallpaper = nullptr; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) - const auto cleanup = qScopeGuard([pDesktopWallpaper](){ - if (pDesktopWallpaper) { - pDesktopWallpaper->Release(); - } - CoUninitialize(); - }); -#endif - // TODO: Why CLSCTX_INPROC_SERVER failed? - if (SUCCEEDED(CoCreateInstance(CLSID_DesktopWallpaper, nullptr, CLSCTX_LOCAL_SERVER, IID_IDesktopWallpaper, reinterpret_cast(&pDesktopWallpaper))) && pDesktopWallpaper) { - DESKTOP_WALLPAPER_POSITION position = DWPOS_FILL; - if (SUCCEEDED(pDesktopWallpaper->GetPosition(&position))) { - switch (position) { - case DWPOS_CENTER: - return DesktopWallpaperAspectStyle::Central; - case DWPOS_TILE: - return DesktopWallpaperAspectStyle::Tiled; - case DWPOS_STRETCH: - return DesktopWallpaperAspectStyle::IgnoreRatioFit; - case DWPOS_FIT: - return DesktopWallpaperAspectStyle::KeepRatioFit; - case DWPOS_FILL: - return DesktopWallpaperAspectStyle::KeepRatioByExpanding; - case DWPOS_SPAN: - return DesktopWallpaperAspectStyle::Span; - } - } else { - qWarning() << "IDesktopWallpaper::GetPosition() failed."; - } - } else { - qWarning() << "Failed to create COM instance - DesktopWallpaper."; - } - } else { - qWarning() << "Failed to initialize COM."; - } - qDebug() << "The IDesktopWallpaper interface failed. Trying the IActiveDesktop interface instead."; - } - if (SUCCEEDED(CoInitialize(nullptr))) { - IActiveDesktop *pActiveDesktop = nullptr; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) - const auto cleanup = qScopeGuard([pActiveDesktop](){ - if (pActiveDesktop) { - pActiveDesktop->Release(); - } - CoUninitialize(); - }); -#endif - if (SUCCEEDED(CoCreateInstance(CLSID_ActiveDesktop, nullptr, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, reinterpret_cast(&pActiveDesktop))) && pActiveDesktop) { - WALLPAPEROPT opt; - SecureZeroMemory(&opt, sizeof(opt)); - opt.dwSize = sizeof(opt); - if (SUCCEEDED(pActiveDesktop->GetWallpaperOptions(&opt, 0))) { - switch (opt.dwStyle) { - case WPSTYLE_CENTER: - return DesktopWallpaperAspectStyle::Central; - case WPSTYLE_TILE: - return DesktopWallpaperAspectStyle::Tiled; - case WPSTYLE_STRETCH: - return DesktopWallpaperAspectStyle::IgnoreRatioFit; - case WPSTYLE_KEEPASPECT: - return DesktopWallpaperAspectStyle::KeepRatioFit; - case WPSTYLE_CROPTOFIT: - return DesktopWallpaperAspectStyle::KeepRatioByExpanding; - case WPSTYLE_SPAN: - return DesktopWallpaperAspectStyle::Span; - } - } else { - qWarning() << "IActiveDesktop::GetWallpaperOptions() failed."; - } - } else { - qWarning() << "Failed to create COM instance - ActiveDesktop."; - } - } else { - qWarning() << "Failed to initialize COM."; - } - qDebug() << "Shell API failed. Reading from the registry instead."; - const QSettings settings(g_desktopRegistryKey, QSettings::NativeFormat); - bool ok = false; - const DWORD style = settings.value(QStringLiteral("WallpaperStyle"), 0).toULongLong(&ok); - if (!ok) { - qWarning() << "Failed to read the registry."; - return DesktopWallpaperAspectStyle::KeepRatioByExpanding; // Fill - } - switch (style) { - case 0: { - bool ok = false; - if ((settings.value(QStringLiteral("TileWallpaper"), 0).toULongLong(&ok) != 0) && ok) { - return DesktopWallpaperAspectStyle::Tiled; - } else { - return DesktopWallpaperAspectStyle::Central; - } - } - case 2: - return DesktopWallpaperAspectStyle::IgnoreRatioFit; - case 6: - return DesktopWallpaperAspectStyle::KeepRatioFit; - case 10: - return DesktopWallpaperAspectStyle::KeepRatioByExpanding; - case 22: - return DesktopWallpaperAspectStyle::Span; - default: - return DesktopWallpaperAspectStyle::KeepRatioByExpanding; // Fill - } -} - quint32 Utilities::getWindowDpi(const QWindow *window) { Q_ASSERT(window); @@ -882,58 +454,6 @@ bool Utilities::isWin10OrGreater(const int subVer) #endif } -static inline bool forceEnableOfficialMSWin10AcrylicBlur() -{ - return qEnvironmentVariableIsSet(_flh_global::_flh_acrylic_forceEnableOfficialMSWin10AcrylicBlur_flag); -} - -static inline bool shouldUseOfficialMSWin10AcrylicBlur() -{ -#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) - const QOperatingSystemVersion currentVersion = QOperatingSystemVersion::current(); - if (currentVersion > QOperatingSystemVersion::Windows10) { - return true; - } - return ((currentVersion.microVersion() >= 16190) && (currentVersion.microVersion() < 18362)); -#else - // TODO - return false; -#endif -} - -bool Utilities::isOfficialMSWin10AcrylicBlurAvailable() -{ - if (!isWin10OrGreater()) { - return false; - } - if (!forceEnableTraditionalBlur() && !forceDisableWallpaperBlur() && !disableExtraProcessingForBlur()) { - // We can't enable the official Acrylic blur in wallpaper blur mode. - return false; - } - if (forceEnableOfficialMSWin10AcrylicBlur()) { - return true; - } - return shouldUseOfficialMSWin10AcrylicBlur(); -} - -static inline bool shouldUseOriginalDwmBlur() -{ -#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) - return Utilities::isWin10OrGreater() || (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite); -#else - // TODO - return false; -#endif -} - -bool Utilities::shouldUseTraditionalBlur() -{ - if ((forceEnableTraditionalBlur() || forceDisableWallpaperBlur() || disableExtraProcessingForBlur()) && shouldUseOriginalDwmBlur()) { - return true; - } - return false; -} - void Utilities::displaySystemMenu(const QWindow *window, const QPoint &pos) { Q_ASSERT(window);