mica material: minor fixes of previous implementation

This commit is contained in:
Yuhang Zhao 2023-07-02 11:44:54 +08:00
parent 7c0d8c4b11
commit 617a015b97
8 changed files with 79 additions and 40 deletions

View File

@ -39,16 +39,23 @@ Dialog::~Dialog() = default;
void Dialog::closeEvent(QCloseEvent *event) void Dialog::closeEvent(QCloseEvent *event)
{ {
if (!parent()) { if (!parent()) {
Settings::set({}, kGeometry, geometry()); const QString id = objectName();
Settings::set({}, kDevicePixelRatio, devicePixelRatioF()); Settings::set(id, kGeometry, geometry());
Settings::set(id, kDevicePixelRatio, devicePixelRatioF());
} }
FramelessDialog::closeEvent(event); FramelessDialog::closeEvent(event);
} }
void Dialog::setupUi() void Dialog::setupUi()
{ {
setWindowTitle(tr("Qt Dialog demo")); setWindowTitle(tr("FramelessHelper demo application - QDialog"));
setWindowIcon(QFileIconProvider().icon(QFileIconProvider::Computer)); 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 = new StandardTitleBar(this);
titleBar->setWindowIconVisible(true); titleBar->setWindowIconVisible(true);
@ -142,9 +149,10 @@ void Dialog::waitReady()
{ {
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this); FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
helper->waitForReady(); helper->waitForReady();
const auto savedGeometry = Settings::get<QRect>({}, kGeometry); const QString id = objectName();
const auto savedGeometry = Settings::get<QRect>(id, kGeometry);
if (savedGeometry.isValid() && !parent()) { if (savedGeometry.isValid() && !parent()) {
const auto savedDpr = Settings::get<qreal>({}, kDevicePixelRatio); const auto savedDpr = Settings::get<qreal>(id, kDevicePixelRatio);
// Qt doesn't support dpr < 1. // Qt doesn't support dpr < 1.
const qreal oldDpr = std::max(savedDpr, qreal(1)); const qreal oldDpr = std::max(savedDpr, qreal(1));
const qreal scale = (devicePixelRatioF() / oldDpr); const qreal scale = (devicePixelRatioF() / oldDpr);

View File

@ -29,6 +29,12 @@
FRAMELESSHELPER_USE_NAMESPACE FRAMELESSHELPER_USE_NAMESPACE
#define CREATE_WINDOW(Name) \
const auto Name = std::make_unique<Dialog>(); \
Name->setObjectName(FRAMELESSHELPER_STRING_LITERAL(#Name)); \
Name->waitReady(); \
Name->show();
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
Log::setup(FRAMELESSHELPER_STRING_LITERAL("dialog")); Log::setup(FRAMELESSHELPER_STRING_LITERAL("dialog"));
@ -51,11 +57,11 @@ int main(int argc, char *argv[])
FramelessHelper::Core::setApplicationOSThemeAware(); FramelessHelper::Core::setApplicationOSThemeAware();
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow); 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>(); CREATE_WINDOW(dialog1)
dialog->waitReady(); CREATE_WINDOW(dialog2)
dialog->show(); CREATE_WINDOW(dialog3)
return QCoreApplication::exec(); return QCoreApplication::exec();
} }

View File

@ -29,6 +29,12 @@
FRAMELESSHELPER_USE_NAMESPACE FRAMELESSHELPER_USE_NAMESPACE
#define CREATE_WINDOW(Name) \
const auto Name = std::make_unique<MainWindow>(); \
Name->setObjectName(FRAMELESSHELPER_STRING_LITERAL(#Name)); \
Name->waitReady(); \
Name->show();
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
Log::setup(FRAMELESSHELPER_STRING_LITERAL("mainwindow")); Log::setup(FRAMELESSHELPER_STRING_LITERAL("mainwindow"));
@ -51,11 +57,11 @@ int main(int argc, char *argv[])
FramelessHelper::Core::setApplicationOSThemeAware(); FramelessHelper::Core::setApplicationOSThemeAware();
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow); 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>(); CREATE_WINDOW(mainWindow1)
mainWindow->waitReady(); CREATE_WINDOW(mainWindow2)
mainWindow->show(); CREATE_WINDOW(mainWindow3)
return QCoreApplication::exec(); return QCoreApplication::exec();
} }

View File

@ -60,9 +60,10 @@ MainWindow::~MainWindow() = default;
void MainWindow::closeEvent(QCloseEvent *event) void MainWindow::closeEvent(QCloseEvent *event)
{ {
if (!parent()) { if (!parent()) {
Settings::set({}, kGeometry, geometry()); const QString id = objectName();
Settings::set({}, kState, saveState()); Settings::set(id, kGeometry, geometry());
Settings::set({}, kDevicePixelRatio, devicePixelRatioF()); Settings::set(id, kState, saveState());
Settings::set(id, kDevicePixelRatio, devicePixelRatioF());
} }
FramelessMainWindow::closeEvent(event); FramelessMainWindow::closeEvent(event);
} }
@ -108,8 +109,14 @@ QMenuBar::item:pressed {
#endif // Q_OS_MACOS #endif // Q_OS_MACOS
helper->setHitTestVisible(mb); // IMPORTANT! helper->setHitTestVisible(mb); // IMPORTANT!
setWindowTitle(tr("FramelessHelper demo application - Qt MainWindow")); setWindowTitle(tr("FramelessHelper demo application - QMainWindow"));
setWindowIcon(QFileIconProvider().icon(QFileIconProvider::Computer)); 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]{ connect(m_mainWindow->pushButton, &QPushButton::clicked, this, [this]{
const auto dialog = new Dialog(this); const auto dialog = new Dialog(this);
dialog->waitReady(); dialog->waitReady();
@ -128,9 +135,10 @@ void MainWindow::waitReady()
{ {
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this); FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
helper->waitForReady(); helper->waitForReady();
const auto savedGeometry = Settings::get<QRect>({}, kGeometry); const QString id = objectName();
const auto savedGeometry = Settings::get<QRect>(id, kGeometry);
if (savedGeometry.isValid() && !parent()) { if (savedGeometry.isValid() && !parent()) {
const auto savedDpr = Settings::get<qreal>({}, kDevicePixelRatio); const auto savedDpr = Settings::get<qreal>(id, kDevicePixelRatio);
// Qt doesn't support dpr < 1. // Qt doesn't support dpr < 1.
const qreal oldDpr = std::max(savedDpr, qreal(1)); const qreal oldDpr = std::max(savedDpr, qreal(1));
const qreal scale = (devicePixelRatioF() / oldDpr); const qreal scale = (devicePixelRatioF() / oldDpr);
@ -138,7 +146,7 @@ void MainWindow::waitReady()
} else { } else {
helper->moveWindowToDesktopCenter(); helper->moveWindowToDesktopCenter();
} }
const QByteArray savedState = Settings::get<QByteArray>({}, kState); const QByteArray savedState = Settings::get<QByteArray>(id, kState);
if (!savedState.isEmpty() && !parent()) { if (!savedState.isEmpty() && !parent()) {
restoreState(savedState); restoreState(savedState);
} }

View File

@ -59,10 +59,9 @@ int main(int argc, char *argv[])
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow); FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
//FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial); //FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
CREATE_WINDOW(window1) CREATE_WINDOW(widget1)
CREATE_WINDOW(window2) CREATE_WINDOW(widget2)
CREATE_WINDOW(window3) CREATE_WINDOW(widget3)
CREATE_WINDOW(window4)
return QCoreApplication::exec(); return QCoreApplication::exec();
} }

View File

@ -80,7 +80,7 @@ void Widget::closeEvent(QCloseEvent *event)
void Widget::initialize() void Widget::initialize()
{ {
setWindowTitle(tr("FramelessHelper demo application - Qt Widgets")); setWindowTitle(tr("FramelessHelper demo application - QWidget"));
setWindowIcon(QFileIconProvider().icon(QFileIconProvider::Computer)); setWindowIcon(QFileIconProvider().icon(QFileIconProvider::Computer));
resize(800, 600); resize(800, 600);
m_titleBar = new StandardTitleBar(this); m_titleBar = new StandardTitleBar(this);

View File

@ -65,8 +65,8 @@ private:
QBrush micaBrush = {}; QBrush micaBrush = {};
bool initialized = false; bool initialized = false;
struct { struct {
qreal x = 0; qreal horizontal = 0;
qreal y = 0; qreal vertical = 0;
} transform = {}; } transform = {};
}; };

View File

@ -29,6 +29,7 @@
#include "framelessconfig_p.h" #include "framelessconfig_p.h"
#include <QtCore/qsysinfo.h> #include <QtCore/qsysinfo.h>
#include <QtCore/qloggingcategory.h> #include <QtCore/qloggingcategory.h>
#include <QtCore/qmutex.h>
#include <QtGui/qpixmap.h> #include <QtGui/qpixmap.h>
#include <QtGui/qimage.h> #include <QtGui/qimage.h>
#include <QtGui/qimagereader.h> #include <QtGui/qimagereader.h>
@ -77,6 +78,7 @@ struct MicaMaterialData
{ {
QPixmap blurredWallpaper = {}; QPixmap blurredWallpaper = {};
bool graphicsResourcesReady = false; bool graphicsResourcesReady = false;
QMutex mutex;
}; };
Q_GLOBAL_STATIC(MicaMaterialData, g_micaMaterialData) Q_GLOBAL_STATIC(MicaMaterialData, g_micaMaterialData)
@ -529,15 +531,25 @@ const MicaMaterialPrivate *MicaMaterialPrivate::get(const MicaMaterial *q)
void MicaMaterialPrivate::maybeGenerateBlurredWallpaper(const bool force) void MicaMaterialPrivate::maybeGenerateBlurredWallpaper(const bool force)
{ {
g_micaMaterialData()->mutex.lock();
if (!g_micaMaterialData()->blurredWallpaper.isNull() && !force) { if (!g_micaMaterialData()->blurredWallpaper.isNull() && !force) {
g_micaMaterialData()->mutex.unlock();
return; return;
} }
g_micaMaterialData()->mutex.unlock();
// ### FIXME: Ideally, we should not use virtual desktop size here.
QSize monitorSize = QGuiApplication::primaryScreen()->virtualSize(); QSize monitorSize = QGuiApplication::primaryScreen()->virtualSize();
if (monitorSize.isEmpty()) { if (monitorSize.isEmpty()) {
WARNING << "Failed to retrieve the monitor size. Using default size (1920x1080) instead ..."; WARNING << "Failed to retrieve the monitor size. Using default size (1920x1080) instead ...";
monitorSize = kMaximumPictureSize; monitorSize = kMaximumPictureSize;
} }
const QSize imageSize = (monitorSize > kMaximumPictureSize ? kMaximumPictureSize : monitorSize); 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(); const QString wallpaperFilePath = Utils::getWallpaperFilePath();
if (wallpaperFilePath.isEmpty()) { if (wallpaperFilePath.isEmpty()) {
WARNING << "Failed to retrieve the wallpaper file path."; WARNING << "Failed to retrieve the wallpaper file path.";
@ -554,23 +566,17 @@ void MicaMaterialPrivate::maybeGenerateBlurredWallpaper(const bool force)
return; return;
} }
const QSize correctedSize = (actualSize > kMaximumPictureSize ? kMaximumPictureSize : actualSize); const QSize correctedSize = (actualSize > kMaximumPictureSize ? kMaximumPictureSize : actualSize);
if (actualSize == correctedSize) { if (correctedSize != actualSize) {
transform = {};
} else {
DEBUG << "The wallpaper picture size is greater than 1920x1080, it will be shrinked to reduce memory consumption."; DEBUG << "The wallpaper picture size is greater than 1920x1080, it will be shrinked to reduce memory consumption.";
reader.setScaledSize(correctedSize); reader.setScaledSize(correctedSize);
transform.x = qreal(correctedSize.width()) / qreal(actualSize.width());
transform.y = qreal(correctedSize.height()) / qreal(actualSize.height());
} }
QImage image(correctedSize, kDefaultImageFormat); QImage image(correctedSize, kDefaultImageFormat);
if (!reader.read(&image)) { if (!reader.read(&image)) {
WARNING << "Failed to read the wallpaper image:" << reader.errorString(); WARNING << "Failed to read the wallpaper image:" << reader.errorString();
transform = {};
return; return;
} }
if (image.isNull()) { if (image.isNull()) {
WARNING << "The obtained image data is null."; WARNING << "The obtained image data is null.";
transform = {};
return; return;
} }
WallpaperAspectStyle aspectStyle = Utils::getWallpaperAspectStyle(); 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); const QRect rect = alignedRect(Qt::LeftToRight, Qt::AlignCenter, image.size(), desktopRect);
bufferPainter.drawImage(rect.topLeft(), image); bufferPainter.drawImage(rect.topLeft(), image);
} }
g_micaMaterialData()->mutex.lock();
g_micaMaterialData()->blurredWallpaper = QPixmap(imageSize); g_micaMaterialData()->blurredWallpaper = QPixmap(imageSize);
g_micaMaterialData()->blurredWallpaper.fill(kDefaultTransparentColor); g_micaMaterialData()->blurredWallpaper.fill(kDefaultTransparentColor);
QPainter painter(&g_micaMaterialData()->blurredWallpaper); QPainter painter(&g_micaMaterialData()->blurredWallpaper);
@ -617,6 +624,7 @@ void MicaMaterialPrivate::maybeGenerateBlurredWallpaper(const bool force)
#else // !FRAMELESSHELPER_CORE_NO_PRIVATE #else // !FRAMELESSHELPER_CORE_NO_PRIVATE
qt_blurImage(&painter, buffer, kDefaultBlurRadius, true, false); qt_blurImage(&painter, buffer, kDefaultBlurRadius, true, false);
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE #endif // FRAMELESSHELPER_CORE_NO_PRIVATE
g_micaMaterialData()->mutex.unlock();
if (initialized) { if (initialized) {
Q_Q(MicaMaterial); Q_Q(MicaMaterial);
Q_EMIT q->shouldRedraw(); 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}; static constexpr const QPointF originPoint = {0, 0};
QPointF correctedPos = pos; QPointF correctedPos = pos;
QSizeF correctedSize = size; QSizeF correctedSize = size;
if (!qFuzzyIsNull(transform.x) && (transform.x > qreal(0)) && !qFuzzyCompare(transform.x, qreal(1))) { if (!qFuzzyIsNull(transform.horizontal) && (transform.horizontal > qreal(0)) && !qFuzzyCompare(transform.horizontal, qreal(1))) {
correctedPos.setX(correctedPos.x() * transform.x); correctedPos.setX(correctedPos.x() * transform.horizontal);
correctedSize.setWidth(correctedSize.width() * transform.x); correctedSize.setWidth(correctedSize.width() * transform.horizontal);
} }
if (!qFuzzyIsNull(transform.y) && (transform.y > qreal(0)) && !qFuzzyCompare(transform.y, qreal(1))) { if (!qFuzzyIsNull(transform.vertical) && (transform.vertical > qreal(0)) && !qFuzzyCompare(transform.vertical, qreal(1))) {
correctedPos.setY(correctedPos.y() * transform.y); correctedPos.setY(correctedPos.y() * transform.vertical);
correctedSize.setHeight(correctedSize.height() * transform.y); correctedSize.setHeight(correctedSize.height() * transform.vertical);
} }
painter->save(); painter->save();
painter->setRenderHints(QPainter::Antialiasing | painter->setRenderHints(QPainter::Antialiasing |
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
if (active) { if (active) {
const QMutexLocker locker(&g_micaMaterialData()->mutex);
painter->drawPixmap(originPoint, g_micaMaterialData()->blurredWallpaper, QRectF{correctedPos, correctedSize}); painter->drawPixmap(originPoint, g_micaMaterialData()->blurredWallpaper, QRectF{correctedPos, correctedSize});
} }
painter->setCompositionMode(QPainter::CompositionMode_SourceOver); painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
@ -715,10 +724,13 @@ void MicaMaterialPrivate::initialize()
void MicaMaterialPrivate::prepareGraphicsResources() void MicaMaterialPrivate::prepareGraphicsResources()
{ {
g_micaMaterialData()->mutex.lock();
if (g_micaMaterialData()->graphicsResourcesReady) { if (g_micaMaterialData()->graphicsResourcesReady) {
g_micaMaterialData()->mutex.unlock();
return; return;
} }
g_micaMaterialData()->graphicsResourcesReady = true; g_micaMaterialData()->graphicsResourcesReady = true;
g_micaMaterialData()->mutex.unlock();
maybeGenerateBlurredWallpaper(); maybeGenerateBlurredWallpaper();
} }