diff --git a/examples/dialog/dialog.cpp b/examples/dialog/dialog.cpp index 6c600ca..e72966e 100644 --- a/examples/dialog/dialog.cpp +++ b/examples/dialog/dialog.cpp @@ -39,16 +39,23 @@ Dialog::~Dialog() = default; void Dialog::closeEvent(QCloseEvent *event) { if (!parent()) { - Settings::set({}, kGeometry, geometry()); - Settings::set({}, kDevicePixelRatio, devicePixelRatioF()); + const QString id = objectName(); + Settings::set(id, kGeometry, geometry()); + Settings::set(id, kDevicePixelRatio, devicePixelRatioF()); } FramelessDialog::closeEvent(event); } void Dialog::setupUi() { - setWindowTitle(tr("Qt Dialog demo")); + setWindowTitle(tr("FramelessHelper demo application - QDialog")); setWindowIcon(QFileIconProvider().icon(QFileIconProvider::Computer)); + connect(this, &Dialog::objectNameChanged, this, [this](const QString &name){ + if (name.isEmpty()) { + return; + } + setWindowTitle(windowTitle() + FRAMELESSHELPER_STRING_LITERAL(" [%1]").arg(name)); + }); titleBar = new StandardTitleBar(this); titleBar->setWindowIconVisible(true); @@ -142,9 +149,10 @@ void Dialog::waitReady() { FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this); helper->waitForReady(); - const auto savedGeometry = Settings::get({}, kGeometry); + const QString id = objectName(); + const auto savedGeometry = Settings::get(id, kGeometry); if (savedGeometry.isValid() && !parent()) { - const auto savedDpr = Settings::get({}, kDevicePixelRatio); + const auto savedDpr = Settings::get(id, kDevicePixelRatio); // Qt doesn't support dpr < 1. const qreal oldDpr = std::max(savedDpr, qreal(1)); const qreal scale = (devicePixelRatioF() / oldDpr); diff --git a/examples/dialog/main.cpp b/examples/dialog/main.cpp index df2c996..d81af6a 100644 --- a/examples/dialog/main.cpp +++ b/examples/dialog/main.cpp @@ -29,6 +29,12 @@ FRAMELESSHELPER_USE_NAMESPACE +#define CREATE_WINDOW(Name) \ + const auto Name = std::make_unique(); \ + Name->setObjectName(FRAMELESSHELPER_STRING_LITERAL(#Name)); \ + Name->waitReady(); \ + Name->show(); + int main(int argc, char *argv[]) { Log::setup(FRAMELESSHELPER_STRING_LITERAL("dialog")); @@ -51,11 +57,11 @@ int main(int argc, char *argv[]) FramelessHelper::Core::setApplicationOSThemeAware(); FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow); - FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial); + //FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial); - const auto dialog = std::make_unique(); - dialog->waitReady(); - dialog->show(); + CREATE_WINDOW(dialog1) + CREATE_WINDOW(dialog2) + CREATE_WINDOW(dialog3) return QCoreApplication::exec(); } diff --git a/examples/mainwindow/main.cpp b/examples/mainwindow/main.cpp index a427d1f..efc3291 100644 --- a/examples/mainwindow/main.cpp +++ b/examples/mainwindow/main.cpp @@ -29,6 +29,12 @@ FRAMELESSHELPER_USE_NAMESPACE +#define CREATE_WINDOW(Name) \ + const auto Name = std::make_unique(); \ + Name->setObjectName(FRAMELESSHELPER_STRING_LITERAL(#Name)); \ + Name->waitReady(); \ + Name->show(); + int main(int argc, char *argv[]) { Log::setup(FRAMELESSHELPER_STRING_LITERAL("mainwindow")); @@ -51,11 +57,11 @@ int main(int argc, char *argv[]) FramelessHelper::Core::setApplicationOSThemeAware(); FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow); - FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial); + //FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial); - const auto mainWindow = std::make_unique(); - mainWindow->waitReady(); - mainWindow->show(); + CREATE_WINDOW(mainWindow1) + CREATE_WINDOW(mainWindow2) + CREATE_WINDOW(mainWindow3) return QCoreApplication::exec(); } diff --git a/examples/mainwindow/mainwindow.cpp b/examples/mainwindow/mainwindow.cpp index 5a5e490..c4aad19 100644 --- a/examples/mainwindow/mainwindow.cpp +++ b/examples/mainwindow/mainwindow.cpp @@ -60,9 +60,10 @@ MainWindow::~MainWindow() = default; void MainWindow::closeEvent(QCloseEvent *event) { if (!parent()) { - Settings::set({}, kGeometry, geometry()); - Settings::set({}, kState, saveState()); - Settings::set({}, kDevicePixelRatio, devicePixelRatioF()); + const QString id = objectName(); + Settings::set(id, kGeometry, geometry()); + Settings::set(id, kState, saveState()); + Settings::set(id, kDevicePixelRatio, devicePixelRatioF()); } FramelessMainWindow::closeEvent(event); } @@ -108,8 +109,14 @@ QMenuBar::item:pressed { #endif // Q_OS_MACOS helper->setHitTestVisible(mb); // IMPORTANT! - setWindowTitle(tr("FramelessHelper demo application - Qt MainWindow")); + setWindowTitle(tr("FramelessHelper demo application - QMainWindow")); setWindowIcon(QFileIconProvider().icon(QFileIconProvider::Computer)); + connect(this, &MainWindow::objectNameChanged, this, [this](const QString &name){ + if (name.isEmpty()) { + return; + } + setWindowTitle(windowTitle() + FRAMELESSHELPER_STRING_LITERAL(" [%1]").arg(name)); + }); connect(m_mainWindow->pushButton, &QPushButton::clicked, this, [this]{ const auto dialog = new Dialog(this); dialog->waitReady(); @@ -128,9 +135,10 @@ void MainWindow::waitReady() { FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this); helper->waitForReady(); - const auto savedGeometry = Settings::get({}, kGeometry); + const QString id = objectName(); + const auto savedGeometry = Settings::get(id, kGeometry); if (savedGeometry.isValid() && !parent()) { - const auto savedDpr = Settings::get({}, kDevicePixelRatio); + const auto savedDpr = Settings::get(id, kDevicePixelRatio); // Qt doesn't support dpr < 1. const qreal oldDpr = std::max(savedDpr, qreal(1)); const qreal scale = (devicePixelRatioF() / oldDpr); @@ -138,7 +146,7 @@ void MainWindow::waitReady() } else { helper->moveWindowToDesktopCenter(); } - const QByteArray savedState = Settings::get({}, kState); + const QByteArray savedState = Settings::get(id, kState); if (!savedState.isEmpty() && !parent()) { restoreState(savedState); } diff --git a/examples/widget/main.cpp b/examples/widget/main.cpp index 01ae825..38cf27e 100644 --- a/examples/widget/main.cpp +++ b/examples/widget/main.cpp @@ -59,10 +59,9 @@ int main(int argc, char *argv[]) FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow); //FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial); - CREATE_WINDOW(window1) - CREATE_WINDOW(window2) - CREATE_WINDOW(window3) - CREATE_WINDOW(window4) + CREATE_WINDOW(widget1) + CREATE_WINDOW(widget2) + CREATE_WINDOW(widget3) return QCoreApplication::exec(); } diff --git a/examples/widget/widget.cpp b/examples/widget/widget.cpp index 52d2d43..07f1d87 100644 --- a/examples/widget/widget.cpp +++ b/examples/widget/widget.cpp @@ -80,7 +80,7 @@ void Widget::closeEvent(QCloseEvent *event) void Widget::initialize() { - setWindowTitle(tr("FramelessHelper demo application - Qt Widgets")); + setWindowTitle(tr("FramelessHelper demo application - QWidget")); setWindowIcon(QFileIconProvider().icon(QFileIconProvider::Computer)); resize(800, 600); m_titleBar = new StandardTitleBar(this); diff --git a/include/FramelessHelper/Core/private/micamaterial_p.h b/include/FramelessHelper/Core/private/micamaterial_p.h index f8853e1..25f1c4d 100644 --- a/include/FramelessHelper/Core/private/micamaterial_p.h +++ b/include/FramelessHelper/Core/private/micamaterial_p.h @@ -65,8 +65,8 @@ private: QBrush micaBrush = {}; bool initialized = false; struct { - qreal x = 0; - qreal y = 0; + qreal horizontal = 0; + qreal vertical = 0; } transform = {}; }; diff --git a/src/core/micamaterial.cpp b/src/core/micamaterial.cpp index 3627d76..4508d22 100644 --- a/src/core/micamaterial.cpp +++ b/src/core/micamaterial.cpp @@ -29,6 +29,7 @@ #include "framelessconfig_p.h" #include #include +#include #include #include #include @@ -77,6 +78,7 @@ struct MicaMaterialData { QPixmap blurredWallpaper = {}; bool graphicsResourcesReady = false; + QMutex mutex; }; Q_GLOBAL_STATIC(MicaMaterialData, g_micaMaterialData) @@ -529,15 +531,25 @@ const MicaMaterialPrivate *MicaMaterialPrivate::get(const MicaMaterial *q) void MicaMaterialPrivate::maybeGenerateBlurredWallpaper(const bool force) { + g_micaMaterialData()->mutex.lock(); if (!g_micaMaterialData()->blurredWallpaper.isNull() && !force) { + g_micaMaterialData()->mutex.unlock(); return; } + g_micaMaterialData()->mutex.unlock(); + // ### FIXME: Ideally, we should not use virtual desktop size here. QSize monitorSize = QGuiApplication::primaryScreen()->virtualSize(); if (monitorSize.isEmpty()) { WARNING << "Failed to retrieve the monitor size. Using default size (1920x1080) instead ..."; monitorSize = kMaximumPictureSize; } const QSize imageSize = (monitorSize > kMaximumPictureSize ? kMaximumPictureSize : monitorSize); + if (imageSize == monitorSize) { + transform = {}; + } else { + transform.horizontal = (qreal(imageSize.width()) / qreal(monitorSize.width())); + transform.vertical = (qreal(imageSize.height()) / qreal(monitorSize.height())); + } const QString wallpaperFilePath = Utils::getWallpaperFilePath(); if (wallpaperFilePath.isEmpty()) { WARNING << "Failed to retrieve the wallpaper file path."; @@ -554,23 +566,17 @@ void MicaMaterialPrivate::maybeGenerateBlurredWallpaper(const bool force) return; } const QSize correctedSize = (actualSize > kMaximumPictureSize ? kMaximumPictureSize : actualSize); - if (actualSize == correctedSize) { - transform = {}; - } else { + if (correctedSize != actualSize) { DEBUG << "The wallpaper picture size is greater than 1920x1080, it will be shrinked to reduce memory consumption."; reader.setScaledSize(correctedSize); - transform.x = qreal(correctedSize.width()) / qreal(actualSize.width()); - transform.y = qreal(correctedSize.height()) / qreal(actualSize.height()); } QImage image(correctedSize, kDefaultImageFormat); if (!reader.read(&image)) { WARNING << "Failed to read the wallpaper image:" << reader.errorString(); - transform = {}; return; } if (image.isNull()) { WARNING << "The obtained image data is null."; - transform = {}; return; } WallpaperAspectStyle aspectStyle = Utils::getWallpaperAspectStyle(); @@ -607,6 +613,7 @@ void MicaMaterialPrivate::maybeGenerateBlurredWallpaper(const bool force) const QRect rect = alignedRect(Qt::LeftToRight, Qt::AlignCenter, image.size(), desktopRect); bufferPainter.drawImage(rect.topLeft(), image); } + g_micaMaterialData()->mutex.lock(); g_micaMaterialData()->blurredWallpaper = QPixmap(imageSize); g_micaMaterialData()->blurredWallpaper.fill(kDefaultTransparentColor); QPainter painter(&g_micaMaterialData()->blurredWallpaper); @@ -617,6 +624,7 @@ void MicaMaterialPrivate::maybeGenerateBlurredWallpaper(const bool force) #else // !FRAMELESSHELPER_CORE_NO_PRIVATE qt_blurImage(&painter, buffer, kDefaultBlurRadius, true, false); #endif // FRAMELESSHELPER_CORE_NO_PRIVATE + g_micaMaterialData()->mutex.unlock(); if (initialized) { Q_Q(MicaMaterial); Q_EMIT q->shouldRedraw(); @@ -661,18 +669,19 @@ void MicaMaterialPrivate::paint(QPainter *painter, const QSize &size, const QPoi static constexpr const QPointF originPoint = {0, 0}; QPointF correctedPos = pos; QSizeF correctedSize = size; - if (!qFuzzyIsNull(transform.x) && (transform.x > qreal(0)) && !qFuzzyCompare(transform.x, qreal(1))) { - correctedPos.setX(correctedPos.x() * transform.x); - correctedSize.setWidth(correctedSize.width() * transform.x); + if (!qFuzzyIsNull(transform.horizontal) && (transform.horizontal > qreal(0)) && !qFuzzyCompare(transform.horizontal, qreal(1))) { + correctedPos.setX(correctedPos.x() * transform.horizontal); + correctedSize.setWidth(correctedSize.width() * transform.horizontal); } - if (!qFuzzyIsNull(transform.y) && (transform.y > qreal(0)) && !qFuzzyCompare(transform.y, qreal(1))) { - correctedPos.setY(correctedPos.y() * transform.y); - correctedSize.setHeight(correctedSize.height() * transform.y); + if (!qFuzzyIsNull(transform.vertical) && (transform.vertical > qreal(0)) && !qFuzzyCompare(transform.vertical, qreal(1))) { + correctedPos.setY(correctedPos.y() * transform.vertical); + correctedSize.setHeight(correctedSize.height() * transform.vertical); } painter->save(); painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); if (active) { + const QMutexLocker locker(&g_micaMaterialData()->mutex); painter->drawPixmap(originPoint, g_micaMaterialData()->blurredWallpaper, QRectF{correctedPos, correctedSize}); } painter->setCompositionMode(QPainter::CompositionMode_SourceOver); @@ -715,10 +724,13 @@ void MicaMaterialPrivate::initialize() void MicaMaterialPrivate::prepareGraphicsResources() { + g_micaMaterialData()->mutex.lock(); if (g_micaMaterialData()->graphicsResourcesReady) { + g_micaMaterialData()->mutex.unlock(); return; } g_micaMaterialData()->graphicsResourcesReady = true; + g_micaMaterialData()->mutex.unlock(); maybeGenerateBlurredWallpaper(); }