widgets: PIMPL refactor

This commit is contained in:
Yuhang Zhao 2023-08-25 17:50:22 +08:00
parent e6a4849f81
commit f7368d0a08
18 changed files with 759 additions and 1300 deletions

View File

@ -97,12 +97,11 @@ void Dialog::setupUi()
connect(moreButton, &QPushButton::toggled, extension, &QWidget::setVisible);
QVBoxLayout *extensionLayout = new QVBoxLayout;
QVBoxLayout *extensionLayout = new QVBoxLayout(extension);
extensionLayout->setContentsMargins(0, 0, 0, 0);
extensionLayout->addWidget(wholeWordsCheckBox);
extensionLayout->addWidget(backwardCheckBox);
extensionLayout->addWidget(searchSelectionCheckBox);
extension->setLayout(extensionLayout);
QHBoxLayout *topLeftLayout = new QHBoxLayout;
topLeftLayout->addWidget(label);
@ -120,14 +119,12 @@ void Dialog::setupUi()
controlsLayout->addWidget(extension, 1, 0, 1, 2);
controlsLayout->setRowStretch(2, 1);
QVBoxLayout *mainLayout = new QVBoxLayout;
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
mainLayout->addWidget(titleBar);
mainLayout->addLayout(controlsLayout);
setLayout(mainLayout);
extension->hide();
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);

View File

@ -73,7 +73,6 @@ void MainWindow::initialize()
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->addWidget(m_titleBar);
mainLayout->addWidget(m_glWidget);
setLayout(mainLayout);
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
helper->setTitleBarWidget(m_titleBar);

View File

@ -102,7 +102,6 @@ void Widget::initialize()
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->addWidget(m_titleBar);
mainLayout->addLayout(contentLayout);
setLayout(mainLayout);
updateStyleSheet();
m_cancelShortcut = new QShortcut(this);

View File

@ -44,14 +44,8 @@ public:
Q_NODISCARD static FramelessDialogPrivate *get(FramelessDialog *pub);
Q_NODISCARD static const FramelessDialogPrivate *get(const FramelessDialog *pub);
Q_NODISCARD WidgetsSharedHelper *widgetsSharedHelper() const;
private:
void initialize();
private:
FramelessDialog *q_ptr = nullptr;
WidgetsSharedHelper *m_sharedHelper = nullptr;
WidgetsSharedHelper *sharedHelper = nullptr;
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -44,21 +44,9 @@ public:
Q_NODISCARD static FramelessMainWindowPrivate *get(FramelessMainWindow *pub);
Q_NODISCARD static const FramelessMainWindowPrivate *get(const FramelessMainWindow *pub);
Q_NODISCARD bool isNormal() const;
Q_NODISCARD bool isZoomed() const;
void toggleMaximized();
void toggleFullScreen();
Q_NODISCARD WidgetsSharedHelper *widgetsSharedHelper() const;
private:
void initialize();
private:
FramelessMainWindow *q_ptr = nullptr;
Qt::WindowState m_savedWindowState = Qt::WindowNoState;
WidgetsSharedHelper *m_sharedHelper = nullptr;
Qt::WindowState savedWindowState = Qt::WindowNoState;
WidgetsSharedHelper *sharedHelper = nullptr;
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -44,21 +44,9 @@ public:
Q_NODISCARD static FramelessWidgetPrivate *get(FramelessWidget *pub);
Q_NODISCARD static const FramelessWidgetPrivate *get(const FramelessWidget *pub);
Q_NODISCARD bool isNormal() const;
Q_NODISCARD bool isZoomed() const;
void toggleMaximized();
void toggleFullScreen();
Q_NODISCARD WidgetsSharedHelper *widgetsSharedHelper() const;
private:
void initialize();
private:
FramelessWidget *q_ptr = nullptr;
Qt::WindowState m_savedWindowState = Qt::WindowNoState;
WidgetsSharedHelper *m_sharedHelper = nullptr;
Qt::WindowState savedWindowState = Qt::WindowNoState;
WidgetsSharedHelper *sharedHelper = nullptr;
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -49,53 +49,25 @@ public:
Q_NODISCARD static FramelessWidgetsHelperPrivate *get(FramelessWidgetsHelper *pub);
Q_NODISCARD static const FramelessWidgetsHelperPrivate *get(const FramelessWidgetsHelper *pub);
Q_NODISCARD bool isContentExtendedIntoTitleBar() const;
void extendsContentIntoTitleBar(const bool value);
Q_NODISCARD QWidget *getTitleBarWidget() const;
void setTitleBarWidget(QWidget *widget);
void attach();
void detach();
void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType);
void setHitTestVisible(QWidget *widget, const bool visible = true);
void setHitTestVisible(const QRect &rect, const bool visible = true);
void setHitTestVisible(QObject *object, const bool visible = true);
void showSystemMenu(const QPoint &pos);
void windowStartSystemMove2(const QPoint &pos);
void windowStartSystemResize2(const Qt::Edges edges, const QPoint &pos);
void moveWindowToDesktopCenter();
void bringWindowToFront();
Q_NODISCARD bool isWindowFixedSize() const;
void setWindowFixedSize(const bool value);
void emitSignalForAllInstances(const char *signal);
Q_NODISCARD bool isBlurBehindWindowEnabled() const;
void setBlurBehindWindowEnabled(const bool enable, const QColor &color);
void setProperty(const char *name, const QVariant &value);
Q_NODISCARD QVariant getProperty(const char *name, const QVariant &defaultValue = {});
Q_NODISCARD QWidget *window() const;
Q_NODISCARD MicaMaterial *getMicaMaterialIfAny() const;
Q_NODISCARD WindowBorderPainter *getWindowBorderIfAny() const;
Q_NODISCARD static WidgetsSharedHelper *findOrCreateSharedHelper(QWidget *window);
Q_NODISCARD static FramelessWidgetsHelper *findOrCreateFramelessHelper(QObject *object);
Q_NODISCARD bool isReady() const;
void waitForReady();
void repaintAllChildren(const quint32 delay = 0) const;
Q_NODISCARD quint32 readyWaitTime() const;
void setReadyWaitTime(const quint32 time);
private:
Q_NODISCARD QRect mapWidgetGeometryToScene(const QWidget * const widget) const;
Q_NODISCARD bool isInSystemButtons(const QPoint &pos, Global::SystemButtonType *button) const;
Q_NODISCARD bool isInTitleBarDraggableArea(const QPoint &pos) const;
@ -105,15 +77,13 @@ private:
Q_NODISCARD const FramelessWidgetsHelperData *getWindowData() const;
Q_NODISCARD FramelessWidgetsHelperData *getWindowDataMutable() const;
private:
FramelessWidgetsHelper *q_ptr = nullptr;
QColor m_savedWindowBackgroundColor = {};
bool m_blurBehindWindowEnabled = false;
QPointer<QWidget> m_window = nullptr;
bool m_destroying = false;
bool m_qpaReady = false;
QSizePolicy m_savedSizePolicy = {};
quint32 m_qpaWaitTime = 0;
QColor savedWindowBackgroundColor = {};
bool blurBehindWindowEnabled = false;
QPointer<QWidget> window = nullptr;
bool qpaReady = false;
QSizePolicy savedSizePolicy = {};
quint32 qpaWaitTime = 0;
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -27,11 +27,6 @@
#include <FramelessHelper/Widgets/framelesshelperwidgets_global.h>
#include <optional>
QT_BEGIN_NAMESPACE
class QEnterEvent;
class QPaintEvent;
QT_END_NAMESPACE
FRAMELESSHELPER_BEGIN_NAMESPACE
class StandardSystemButton;
@ -49,46 +44,18 @@ public:
Q_NODISCARD static StandardSystemButtonPrivate *get(StandardSystemButton *pub);
Q_NODISCARD static const StandardSystemButtonPrivate *get(const StandardSystemButton *pub);
Q_NODISCARD QString getGlyph() const;
void setGlyph(const QString &value);
Q_NODISCARD static QSize getRecommendedButtonSize();
Q_NODISCARD Global::SystemButtonType getButtonType() const;
void setButtonType(const Global::SystemButtonType type);
Q_NODISCARD QSize getRecommendedButtonSize() const;
Q_NODISCARD QColor getHoverColor() const;
Q_NODISCARD QColor getPressColor() const;
Q_NODISCARD QColor getNormalColor() const;
Q_NODISCARD QColor getActiveForegroundColor() const;
Q_NODISCARD QColor getInactiveForegroundColor() const;
Q_NODISCARD bool isActive() const;
Q_NODISCARD int glyphSize() const;
void setHoverColor(const QColor &value);
void setPressColor(const QColor &value);
void setNormalColor(const QColor &value);
void setActiveForegroundColor(const QColor &value);
void setInactiveForegroundColor(const QColor &value);
void setActive(const bool value);
void setGlyphSize(const int value);
void paintEventHandler(QPaintEvent *event);
private:
void initialize();
private:
StandardSystemButton *q_ptr = nullptr;
Global::SystemButtonType m_buttonType = Global::SystemButtonType::Unknown;
QString m_glyph = {};
QColor m_hoverColor = {};
QColor m_pressColor = {};
QColor m_normalColor = {};
QColor m_activeForegroundColor = {};
QColor m_inactiveForegroundColor = {};
bool m_active = false;
std::optional<int> m_glyphSize = std::nullopt;
Global::SystemButtonType buttonType = Global::SystemButtonType::Unknown;
QString glyph = {};
QColor hoverColor = {};
QColor pressColor = {};
QColor normalColor = {};
QColor activeForegroundColor = {};
QColor inactiveForegroundColor = {};
bool active = false;
std::optional<int> glyphSize = std::nullopt;
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -29,7 +29,6 @@
#include <optional>
QT_BEGIN_NAMESPACE
class QPaintEvent;
class QMouseEvent;
QT_END_NAMESPACE
@ -59,33 +58,6 @@ public:
Q_NODISCARD static StandardTitleBarPrivate *get(StandardTitleBar *pub);
Q_NODISCARD static const StandardTitleBarPrivate *get(const StandardTitleBar *pub);
Q_NODISCARD Qt::Alignment titleLabelAlignment() const;
void setTitleLabelAlignment(const Qt::Alignment value);
Q_NODISCARD bool isExtended() const;
void setExtended(const bool value);
Q_NODISCARD bool isHideWhenClose() const;
void setHideWhenClose(const bool value);
Q_NODISCARD ChromePalette *chromePalette() const;
void paintTitleBar(QPaintEvent *event);
Q_NODISCARD bool titleLabelVisible() const;
void setTitleLabelVisible(const bool value);
Q_NODISCARD QSize windowIconSize() const;
void setWindowIconSize(const QSize &value);
Q_NODISCARD bool windowIconVisible() const;
void setWindowIconVisible(const bool value);
Q_NODISCARD QFont titleFont() const;
void setTitleFont(const QFont &value);
Q_NODISCARD bool mouseEventHandler(QMouseEvent *event);
Q_NODISCARD QRect windowIconRect() const;
Q_NODISCARD bool windowIconVisible_real() const;
Q_NODISCARD bool isInTitleBarIconArea(const QPoint &pos) const;
@ -93,35 +65,34 @@ public:
Q_NODISCARD QFont defaultFont() const;
Q_NODISCARD FontMetrics titleLabelSize() const;
public Q_SLOTS:
void updateMaximizeButton();
void updateTitleBarColor();
void updateChromeButtonColor();
void retranslateUi();
Q_SLOT void updateMaximizeButton();
Q_SLOT void updateTitleBarColor();
Q_SLOT void updateChromeButtonColor();
Q_SLOT void retranslateUi();
protected:
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
Q_NODISCARD bool mouseEventHandler(QMouseEvent *event);
private:
void initialize();
private:
StandardTitleBar *q_ptr = nullptr;
#ifndef Q_OS_MACOS
StandardSystemButton *m_minimizeButton = nullptr;
StandardSystemButton *m_maximizeButton = nullptr;
StandardSystemButton *m_closeButton = nullptr;
StandardSystemButton *minimizeButton = nullptr;
StandardSystemButton *maximizeButton = nullptr;
StandardSystemButton *closeButton = nullptr;
#endif // Q_OS_MACOS
QPointer<QWidget> m_window = nullptr;
bool m_extended = false;
Qt::Alignment m_labelAlignment = {};
bool m_hideWhenClose = false;
ChromePalette *m_chromePalette = nullptr;
bool m_titleLabelVisible = true;
std::optional<QSize> m_windowIconSize = std::nullopt;
bool m_windowIconVisible = false;
std::optional<QFont> m_titleFont = std::nullopt;
bool m_closeTriggered = false;
QPointer<QWidget> window = nullptr;
bool extended = false;
Qt::Alignment labelAlignment = {};
bool hideWhenClose = false;
ChromePalette *chromePalette = nullptr;
bool titleLabelVisible = true;
std::optional<QSize> windowIconSize = std::nullopt;
bool windowIconVisible = false;
std::optional<QFont> titleFont = std::nullopt;
bool closeTriggered = false;
protected:
bool eventFilter(QObject *object, QEvent *event) override;
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -52,7 +52,7 @@ public:
~StandardSystemButton() override;
Q_NODISCARD QSize sizeHint() const override;
Q_NODISCARD Global::SystemButtonType buttonType();
Q_NODISCARD Global::SystemButtonType buttonType() const;
Q_NODISCARD QString glyph() const;
Q_NODISCARD QColor hoverColor() const;
Q_NODISCARD QColor pressColor() const;

View File

@ -988,6 +988,9 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
#endif
case WM_NCMOUSEHOVER:
case WM_NCMOUSELEAVE: {
// For future code readers:
// The following code is not workaround anything, it's just try to emulate the original
// behavior of a native Win32 window.
const WindowPart previousWindowPart = getHittedWindowPart(data.hitTestResult.first.value_or(HTNOWHERE));
const bool isXButtonMessage = ((uMsg >= WM_NCXBUTTONDOWN) && (uMsg <= WM_NCXBUTTONDBLCLK));
const WindowPart nowWindowPart = getHittedWindowPart(isXButtonMessage ? GET_NCHITTEST_WPARAM(wParam) : wParam);

View File

@ -237,7 +237,8 @@ void FramelessQuickHelperPrivate::setProperty(const char *name, const QVariant &
Q_ASSERT(name);
Q_ASSERT(*name != '\0');
Q_ASSERT(value.isValid());
if (!name || (*name == '\0') || !value.isValid()) {
Q_ASSERT(!value.isNull());
if (!name || (*name == '\0') || !value.isValid() || value.isNull()) {
return;
}
Q_Q(FramelessQuickHelper);
@ -261,7 +262,7 @@ QVariant FramelessQuickHelperPrivate::getProperty(const char *name, const QVaria
return {};
}
const QVariant value = window->property(name);
return (value.isValid() ? value : defaultValue);
return ((value.isValid() && !value.isNull()) ? value : defaultValue);
}
QuickMicaMaterial *FramelessQuickHelperPrivate::findOrCreateMicaMaterial() const

View File

@ -26,7 +26,6 @@
#include "framelessdialog_p.h"
#include "framelesswidgetshelper.h"
#include "widgetssharedhelper_p.h"
#include <FramelessHelper/Core/utils.h>
#include <QtCore/qloggingcategory.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
@ -54,7 +53,6 @@ FramelessDialogPrivate::FramelessDialogPrivate(FramelessDialog *q) : QObject(q)
return;
}
q_ptr = q;
initialize();
}
FramelessDialogPrivate::~FramelessDialogPrivate() = default;
@ -77,22 +75,13 @@ const FramelessDialogPrivate *FramelessDialogPrivate::get(const FramelessDialog
return pub->d_func();
}
void FramelessDialogPrivate::initialize()
{
Q_Q(FramelessDialog);
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
m_sharedHelper = new WidgetsSharedHelper(this);
m_sharedHelper->setup(q);
}
WidgetsSharedHelper *FramelessDialogPrivate::widgetsSharedHelper() const
{
return m_sharedHelper;
}
FramelessDialog::FramelessDialog(QWidget *parent)
: QDialog(parent), d_ptr(new FramelessDialogPrivate(this))
{
FramelessWidgetsHelper::get(this)->extendsContentIntoTitleBar();
Q_D(FramelessDialog);
d->sharedHelper = new WidgetsSharedHelper(d);
d->sharedHelper->setup(this);
}
FramelessDialog::~FramelessDialog() = default;

View File

@ -54,7 +54,6 @@ FramelessMainWindowPrivate::FramelessMainWindowPrivate(FramelessMainWindow *q) :
return;
}
q_ptr = q;
initialize();
}
FramelessMainWindowPrivate::~FramelessMainWindowPrivate() = default;
@ -77,81 +76,45 @@ const FramelessMainWindowPrivate *FramelessMainWindowPrivate::get(const Frameles
return pub->d_func();
}
void FramelessMainWindowPrivate::initialize()
{
Q_Q(FramelessMainWindow);
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
m_sharedHelper = new WidgetsSharedHelper(this);
m_sharedHelper->setup(q);
}
bool FramelessMainWindowPrivate::isNormal() const
{
Q_Q(const FramelessMainWindow);
return (Utils::windowStatesToWindowState(q->windowState()) == Qt::WindowNoState);
}
bool FramelessMainWindowPrivate::isZoomed() const
{
Q_Q(const FramelessMainWindow);
return (q->isMaximized() || q->isFullScreen());
}
void FramelessMainWindowPrivate::toggleMaximized()
{
Q_Q(FramelessMainWindow);
if (q->isMaximized()) {
q->showNormal();
} else {
q->showMaximized();
}
}
void FramelessMainWindowPrivate::toggleFullScreen()
{
Q_Q(FramelessMainWindow);
if (q->isFullScreen()) {
q->setWindowState(m_savedWindowState);
} else {
m_savedWindowState = Utils::windowStatesToWindowState(q->windowState());
q->showFullScreen();
}
}
WidgetsSharedHelper *FramelessMainWindowPrivate::widgetsSharedHelper() const
{
return m_sharedHelper;
}
FramelessMainWindow::FramelessMainWindow(QWidget *parent, const Qt::WindowFlags flags)
: QMainWindow(parent, flags), d_ptr(new FramelessMainWindowPrivate(this))
{
FramelessWidgetsHelper::get(this)->extendsContentIntoTitleBar();
Q_D(FramelessMainWindow);
d->sharedHelper = new WidgetsSharedHelper(d);
d->sharedHelper->setup(this);
}
FramelessMainWindow::~FramelessMainWindow() = default;
bool FramelessMainWindow::isNormal() const
{
Q_D(const FramelessMainWindow);
return d->isNormal();
return (Utils::windowStatesToWindowState(windowState()) == Qt::WindowNoState);
}
bool FramelessMainWindow::isZoomed() const
{
Q_D(const FramelessMainWindow);
return d->isZoomed();
return (isMaximized() || isFullScreen());
}
void FramelessMainWindow::toggleMaximized()
{
Q_D(FramelessMainWindow);
d->toggleMaximized();
if (isMaximized()) {
showNormal();
} else {
showMaximized();
}
}
void FramelessMainWindow::toggleFullScreen()
{
Q_D(FramelessMainWindow);
d->toggleFullScreen();
if (isFullScreen()) {
setWindowState(d->savedWindowState);
} else {
d->savedWindowState = Utils::windowStatesToWindowState(windowState());
showFullScreen();
}
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -54,7 +54,6 @@ FramelessWidgetPrivate::FramelessWidgetPrivate(FramelessWidget *q) : QObject(q)
return;
}
q_ptr = q;
initialize();
}
FramelessWidgetPrivate::~FramelessWidgetPrivate() = default;
@ -77,81 +76,45 @@ const FramelessWidgetPrivate *FramelessWidgetPrivate::get(const FramelessWidget
return pub->d_func();
}
void FramelessWidgetPrivate::initialize()
{
Q_Q(FramelessWidget);
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
m_sharedHelper = new WidgetsSharedHelper(this);
m_sharedHelper->setup(q);
}
bool FramelessWidgetPrivate::isNormal() const
{
Q_Q(const FramelessWidget);
return (Utils::windowStatesToWindowState(q->windowState()) == Qt::WindowNoState);
}
bool FramelessWidgetPrivate::isZoomed() const
{
Q_Q(const FramelessWidget);
return (q->isMaximized() || q->isFullScreen());
}
void FramelessWidgetPrivate::toggleMaximized()
{
Q_Q(FramelessWidget);
if (q->isMaximized()) {
q->showNormal();
} else {
q->showMaximized();
}
}
void FramelessWidgetPrivate::toggleFullScreen()
{
Q_Q(FramelessWidget);
if (q->isFullScreen()) {
q->setWindowState(m_savedWindowState);
} else {
m_savedWindowState = Utils::windowStatesToWindowState(q->windowState());
q->showFullScreen();
}
}
WidgetsSharedHelper *FramelessWidgetPrivate::widgetsSharedHelper() const
{
return m_sharedHelper;
}
FramelessWidget::FramelessWidget(QWidget *parent)
: QWidget(parent, Qt::Window), d_ptr(new FramelessWidgetPrivate(this))
{
FramelessWidgetsHelper::get(this)->extendsContentIntoTitleBar();
Q_D(FramelessWidget);
d->sharedHelper = new WidgetsSharedHelper(d);
d->sharedHelper->setup(this);
}
FramelessWidget::~FramelessWidget() = default;
bool FramelessWidget::isNormal() const
{
Q_D(const FramelessWidget);
return d->isNormal();
return (Utils::windowStatesToWindowState(windowState()) == Qt::WindowNoState);
}
bool FramelessWidget::isZoomed() const
{
Q_D(const FramelessWidget);
return d->isZoomed();
return (isMaximized() || isFullScreen());
}
void FramelessWidget::toggleMaximized()
{
Q_D(FramelessWidget);
d->toggleMaximized();
if (isMaximized()) {
showNormal();
} else {
showMaximized();
}
}
void FramelessWidget::toggleFullScreen()
{
Q_D(FramelessWidget);
d->toggleFullScreen();
if (isFullScreen()) {
setWindowState(d->savedWindowState);
} else {
d->savedWindowState = Utils::windowStatesToWindowState(windowState());
showFullScreen();
}
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -169,11 +169,7 @@ FramelessWidgetsHelperPrivate::FramelessWidgetsHelperPrivate(FramelessWidgetsHel
q_ptr = q;
}
FramelessWidgetsHelperPrivate::~FramelessWidgetsHelperPrivate()
{
m_destroying = true;
extendsContentIntoTitleBar(false);
}
FramelessWidgetsHelperPrivate::~FramelessWidgetsHelperPrivate() = default;
FramelessWidgetsHelperPrivate *FramelessWidgetsHelperPrivate::get(FramelessWidgetsHelper *pub)
{
@ -193,37 +189,6 @@ const FramelessWidgetsHelperPrivate *FramelessWidgetsHelperPrivate::get(const Fr
return pub->d_func();
}
bool FramelessWidgetsHelperPrivate::isWindowFixedSize() const
{
if (!m_window) {
return false;
}
return isWidgetFixedSize(m_window);
}
void FramelessWidgetsHelperPrivate::setWindowFixedSize(const bool value)
{
if (!m_window) {
return;
}
if (isWindowFixedSize() == value) {
return;
}
if (value) {
m_savedSizePolicy = m_window->sizePolicy();
m_window->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
m_window->setFixedSize(m_window->size());
} else {
m_window->setSizePolicy(m_savedSizePolicy);
m_window->setMinimumSize(kDefaultWindowSize);
m_window->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
}
#ifdef Q_OS_WINDOWS
std::ignore = Utils::setAeroSnappingEnabled(m_window->winId(), !value);
#endif
emitSignalForAllInstances("windowFixedSizeChanged");
}
void FramelessWidgetsHelperPrivate::emitSignalForAllInstances(const char *signal)
{
Q_ASSERT(signal);
@ -231,10 +196,10 @@ void FramelessWidgetsHelperPrivate::emitSignalForAllInstances(const char *signal
if (!signal || (*signal == '\0')) {
return;
}
if (!m_window) {
if (!window) {
return;
}
const auto instances = m_window->findChildren<FramelessWidgetsHelper *>();
const auto instances = window->findChildren<FramelessWidgetsHelper *>();
if (instances.isEmpty()) {
return;
}
@ -243,57 +208,20 @@ void FramelessWidgetsHelperPrivate::emitSignalForAllInstances(const char *signal
}
}
bool FramelessWidgetsHelperPrivate::isBlurBehindWindowEnabled() const
{
return m_blurBehindWindowEnabled;
}
void FramelessWidgetsHelperPrivate::setBlurBehindWindowEnabled(const bool enable, const QColor &color)
{
if (!m_window) {
return;
}
if (m_blurBehindWindowEnabled == enable) {
return;
}
if (Utils::isBlurBehindWindowSupported()) {
QPalette palette = m_window->palette();
if (enable) {
m_savedWindowBackgroundColor = palette.color(QPalette::Window);
}
palette.setColor(QPalette::Window, (enable ? kDefaultTransparentColor : m_savedWindowBackgroundColor));
m_window->setPalette(palette);
if (Utils::setBlurBehindWindowEnabled(m_window->winId(),
(enable ? BlurMode::Default : BlurMode::Disable), color)) {
m_blurBehindWindowEnabled = enable;
emitSignalForAllInstances("blurBehindWindowEnabledChanged");
} else {
WARNING << "Failed to enable/disable blur behind window.";
}
} else {
if (WidgetsSharedHelper * const helper = findOrCreateSharedHelper(m_window)) {
m_blurBehindWindowEnabled = enable;
helper->setMicaEnabled(m_blurBehindWindowEnabled);
emitSignalForAllInstances("blurBehindWindowEnabledChanged");
} else {
DEBUG << "Blur behind window is not supported on current platform.";
}
}
}
void FramelessWidgetsHelperPrivate::setProperty(const char *name, const QVariant &value)
{
Q_ASSERT(name);
Q_ASSERT(*name != '\0');
Q_ASSERT(value.isValid());
if (!name || (*name == '\0') || !value.isValid()) {
Q_ASSERT(!value.isNull());
if (!name || (*name == '\0') || !value.isValid() || value.isNull()) {
return;
}
Q_ASSERT(m_window);
if (!m_window) {
Q_ASSERT(window);
if (!window) {
return;
}
m_window->setProperty(name, value);
window->setProperty(name, value);
}
QVariant FramelessWidgetsHelperPrivate::getProperty(const char *name, const QVariant &defaultValue)
@ -303,25 +231,20 @@ QVariant FramelessWidgetsHelperPrivate::getProperty(const char *name, const QVar
if (!name || (*name == '\0')) {
return {};
}
Q_ASSERT(m_window);
if (!m_window) {
Q_ASSERT(window);
if (!window) {
return {};
}
const QVariant value = m_window->property(name);
return (value.isValid() ? value : defaultValue);
}
QWidget *FramelessWidgetsHelperPrivate::window() const
{
return m_window;
const QVariant value = window->property(name);
return ((value.isValid() && !value.isNull()) ? value : defaultValue);
}
MicaMaterial *FramelessWidgetsHelperPrivate::getMicaMaterialIfAny() const
{
if (!m_window) {
if (!window) {
return nullptr;
}
if (const WidgetsSharedHelper * const helper = findOrCreateSharedHelper(m_window)) {
if (const WidgetsSharedHelper * const helper = findOrCreateSharedHelper(window)) {
return helper->rawMicaMaterial();
}
return nullptr;
@ -329,10 +252,10 @@ MicaMaterial *FramelessWidgetsHelperPrivate::getMicaMaterialIfAny() const
WindowBorderPainter *FramelessWidgetsHelperPrivate::getWindowBorderIfAny() const
{
if (!m_window) {
if (!window) {
return nullptr;
}
if (const WidgetsSharedHelper * const helper = findOrCreateSharedHelper(m_window)) {
if (const WidgetsSharedHelper * const helper = findOrCreateSharedHelper(window)) {
return helper->rawWindowBorder();
}
return nullptr;
@ -346,17 +269,17 @@ WidgetsSharedHelper *FramelessWidgetsHelperPrivate::findOrCreateSharedHelper(QWi
}
if (const auto widget = qobject_cast<FramelessWidget *>(window)) {
if (const auto widgetPriv = FramelessWidgetPrivate::get(widget)) {
return widgetPriv->widgetsSharedHelper();
return widgetPriv->sharedHelper;
}
}
if (const auto mainWindow = qobject_cast<FramelessMainWindow *>(window)) {
if (const auto mainWindowPriv = FramelessMainWindowPrivate::get(mainWindow)) {
return mainWindowPriv->widgetsSharedHelper();
return mainWindowPriv->sharedHelper;
}
}
if (const auto dialog = qobject_cast<FramelessDialog *>(window)) {
if (const auto dialogPriv = FramelessDialogPrivate::get(dialog)) {
return dialogPriv->widgetsSharedHelper();
return dialogPriv->sharedHelper;
}
}
QWidget * const topLevelWindow = window->window();
@ -391,38 +314,14 @@ FramelessWidgetsHelper *FramelessWidgetsHelperPrivate::findOrCreateFramelessHelp
return instance;
}
bool FramelessWidgetsHelperPrivate::isReady() const
{
return m_qpaReady;
}
void FramelessWidgetsHelperPrivate::waitForReady()
{
if (m_qpaReady) {
return;
}
#if 1
QEventLoop loop;
Q_Q(FramelessWidgetsHelper);
const QMetaObject::Connection connection = connect(
q, &FramelessWidgetsHelper::ready, &loop, &QEventLoop::quit);
loop.exec();
disconnect(connection);
#else
while (!m_qpaReady) {
QCoreApplication::processEvents();
}
#endif
}
void FramelessWidgetsHelperPrivate::repaintAllChildren(const quint32 delay) const
{
if (!m_window) {
if (!window) {
return;
}
const auto update = [this]() -> void {
forceWidgetRepaint(m_window);
const QList<QWidget *> widgets = m_window->findChildren<QWidget *>();
forceWidgetRepaint(window);
const QList<QWidget *> widgets = window->findChildren<QWidget *>();
if (widgets.isEmpty()) {
return;
}
@ -439,102 +338,28 @@ void FramelessWidgetsHelperPrivate::repaintAllChildren(const quint32 delay) cons
quint32 FramelessWidgetsHelperPrivate::readyWaitTime() const
{
return m_qpaWaitTime;
return qpaWaitTime;
}
void FramelessWidgetsHelperPrivate::setReadyWaitTime(const quint32 time)
{
if (m_qpaWaitTime == time) {
if (qpaWaitTime == time) {
return;
}
m_qpaWaitTime = time;
}
bool FramelessWidgetsHelperPrivate::isContentExtendedIntoTitleBar() const
{
const FramelessWidgetsHelperData *data = getWindowData();
return (data ? data->ready : false);
}
void FramelessWidgetsHelperPrivate::setTitleBarWidget(QWidget *widget)
{
Q_ASSERT(widget);
if (!widget) {
return;
}
FramelessWidgetsHelperData *data = getWindowDataMutable();
if (!data || (data->titleBarWidget == widget)) {
return;
}
data->titleBarWidget = widget;
emitSignalForAllInstances("titleBarWidgetChanged");
}
QWidget *FramelessWidgetsHelperPrivate::getTitleBarWidget() const
{
const FramelessWidgetsHelperData *data = getWindowData();
return (data ? data->titleBarWidget : nullptr);
}
void FramelessWidgetsHelperPrivate::setHitTestVisible(QWidget *widget, const bool visible)
{
Q_ASSERT(widget);
if (!widget) {
return;
}
FramelessWidgetsHelperData *data = getWindowDataMutable();
if (!data) {
return;
}
if (visible) {
data->hitTestVisibleWidgets.append(widget);
} else {
data->hitTestVisibleWidgets.removeAll(widget);
}
}
void FramelessWidgetsHelperPrivate::setHitTestVisible(const QRect &rect, const bool visible)
{
Q_ASSERT(rect.isValid());
if (!rect.isValid()) {
return;
}
FramelessWidgetsHelperData *data = getWindowDataMutable();
if (!data) {
return;
}
if (visible) {
data->hitTestVisibleRects.append(rect);
} else {
data->hitTestVisibleRects.removeAll(rect);
}
}
void FramelessWidgetsHelperPrivate::setHitTestVisible(QObject *object, const bool visible)
{
Q_ASSERT(object);
if (!object) {
return;
}
const auto widget = qobject_cast<QWidget *>(object);
Q_ASSERT(widget);
if (!widget) {
return;
}
setHitTestVisible(widget, visible);
qpaWaitTime = time;
}
void FramelessWidgetsHelperPrivate::attach()
{
QWidget * const window = findTopLevelWindow();
Q_ASSERT(window);
if (!window) {
QWidget * const tlw = findTopLevelWindow();
Q_ASSERT(tlw);
if (!tlw) {
return;
}
if (m_window == window) {
if (window == tlw) {
return;
}
m_window = window;
window = tlw;
if (!window->testAttribute(Qt::WA_DontCreateNativeAncestors)) {
window->setAttribute(Qt::WA_DontCreateNativeAncestors);
@ -548,39 +373,41 @@ void FramelessWidgetsHelperPrivate::attach()
return;
}
Q_Q(FramelessWidgetsHelper);
SystemParameters params = {};
params.getWindowId = [window]() -> WId { return window->winId(); };
params.getWindowFlags = [window]() -> Qt::WindowFlags { return window->windowFlags(); };
params.setWindowFlags = [window](const Qt::WindowFlags flags) -> void { window->setWindowFlags(flags); };
params.getWindowSize = [window]() -> QSize { return window->size(); };
params.setWindowSize = [window](const QSize &size) -> void { window->resize(size); };
params.getWindowPosition = [window]() -> QPoint { return window->pos(); };
params.setWindowPosition = [window](const QPoint &pos) -> void { window->move(pos); };
params.getWindowScreen = [window]() -> QScreen * {
params.getWindowId = [this]() -> WId { return window->winId(); };
params.getWindowFlags = [this]() -> Qt::WindowFlags { return window->windowFlags(); };
params.setWindowFlags = [this](const Qt::WindowFlags flags) -> void { window->setWindowFlags(flags); };
params.getWindowSize = [this]() -> QSize { return window->size(); };
params.setWindowSize = [this](const QSize &size) -> void { window->resize(size); };
params.getWindowPosition = [this]() -> QPoint { return window->pos(); };
params.setWindowPosition = [this](const QPoint &pos) -> void { window->move(pos); };
params.getWindowScreen = [this]() -> QScreen * {
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
return window->screen();
#else
return window->windowHandle()->screen();
#endif
};
params.isWindowFixedSize = [this]() -> bool { return isWindowFixedSize(); };
params.setWindowFixedSize = [this](const bool value) -> void { setWindowFixedSize(value); };
params.getWindowState = [window]() -> Qt::WindowState { return Utils::windowStatesToWindowState(window->windowState()); };
params.setWindowState = [window](const Qt::WindowState state) -> void { window->setWindowState(state); };
params.getWindowHandle = [window]() -> QWindow * { return window->windowHandle(); };
params.windowToScreen = [window](const QPoint &pos) -> QPoint { return window->mapToGlobal(pos); };
params.screenToWindow = [window](const QPoint &pos) -> QPoint { return window->mapFromGlobal(pos); };
params.isWindowFixedSize = [q]() -> bool { return q->isWindowFixedSize(); };
params.setWindowFixedSize = [q](const bool value) -> void { q->setWindowFixedSize(value); };
params.getWindowState = [this]() -> Qt::WindowState { return Utils::windowStatesToWindowState(window->windowState()); };
params.setWindowState = [this](const Qt::WindowState state) -> void { window->setWindowState(state); };
params.getWindowHandle = [this]() -> QWindow * { return window->windowHandle(); };
params.windowToScreen = [this](const QPoint &pos) -> QPoint { return window->mapToGlobal(pos); };
params.screenToWindow = [this](const QPoint &pos) -> QPoint { return window->mapFromGlobal(pos); };
params.isInsideSystemButtons = [this](const QPoint &pos, SystemButtonType *button) -> bool { return isInSystemButtons(pos, button); };
params.isInsideTitleBarDraggableArea = [this](const QPoint &pos) -> bool { return isInTitleBarDraggableArea(pos); };
params.getWindowDevicePixelRatio = [window]() -> qreal { return window->devicePixelRatioF(); };
params.getWindowDevicePixelRatio = [this]() -> qreal { return window->devicePixelRatioF(); };
params.setSystemButtonState = [this](const SystemButtonType button, const ButtonState state) -> void { setSystemButtonState(button, state); };
params.shouldIgnoreMouseEvents = [this](const QPoint &pos) -> bool { return shouldIgnoreMouseEvents(pos); };
params.showSystemMenu = [this](const QPoint &pos) -> void { showSystemMenu(pos); };
params.showSystemMenu = [q](const QPoint &pos) -> void { q->showSystemMenu(pos); };
params.setProperty = [this](const char *name, const QVariant &value) -> void { setProperty(name, value); };
params.getProperty = [this](const char *name, const QVariant &defaultValue) -> QVariant { return getProperty(name, defaultValue); };
params.setCursor = [window](const QCursor &cursor) -> void { window->setCursor(cursor); };
params.unsetCursor = [window]() -> void { window->unsetCursor(); };
params.getWidgetHandle = [window]() -> QObject * { return window; };
params.setCursor = [this](const QCursor &cursor) -> void { window->setCursor(cursor); };
params.unsetCursor = [this]() -> void { window->unsetCursor(); };
params.getWidgetHandle = [this]() -> QObject * { return window; };
params.forceChildrenRepaint = [this](const int delay) -> void { repaintAllChildren(delay); };
params.resetQtGrabbedControl = []() -> void { qt_button_down = nullptr; };
@ -594,13 +421,13 @@ void FramelessWidgetsHelperPrivate::attach()
// we reach here, and all the modifications from the Qt side will be lost
// due to QPA will reset the position and size of the window during it's
// initialization process.
QTimer::singleShot(m_qpaWaitTime, this, [this](){
m_qpaReady = true;
QTimer::singleShot(qpaWaitTime, this, [this, q](){
qpaReady = true;
if (FramelessConfig::instance()->isSet(Option::CenterWindowBeforeShow)) {
moveWindowToDesktopCenter();
q->moveWindowToDesktopCenter();
}
if (FramelessConfig::instance()->isSet(Option::EnableBlurBehindWindow)) {
setBlurBehindWindowEnabled(true, {});
q->setBlurBehindWindowEnabled(true);
}
emitSignalForAllInstances("windowChanged");
emitSignalForAllInstances("ready");
@ -609,35 +436,20 @@ void FramelessWidgetsHelperPrivate::attach()
void FramelessWidgetsHelperPrivate::detach()
{
if (!m_window) {
if (!window) {
return;
}
const WId windowId = m_window->winId();
const WId windowId = window->winId();
const auto it = g_framelessWidgetsHelperData()->constFind(windowId);
if (it == g_framelessWidgetsHelperData()->constEnd()) {
return;
}
g_framelessWidgetsHelperData()->erase(it);
FramelessManager::instance()->removeWindow(windowId);
m_window = nullptr;
window = nullptr;
emitSignalForAllInstances("windowChanged");
}
void FramelessWidgetsHelperPrivate::extendsContentIntoTitleBar(const bool value)
{
if (isContentExtendedIntoTitleBar() == value) {
return;
}
if (value) {
attach();
} else {
detach();
}
if (!m_destroying) {
emitSignalForAllInstances("extendsContentIntoTitleBarChanged");
}
}
QWidget *FramelessWidgetsHelperPrivate::findTopLevelWindow() const
{
Q_Q(const FramelessWidgetsHelper);
@ -653,11 +465,11 @@ QWidget *FramelessWidgetsHelperPrivate::findTopLevelWindow() const
const FramelessWidgetsHelperData *FramelessWidgetsHelperPrivate::getWindowData() const
{
//Q_ASSERT(m_window);
if (!m_window) {
//Q_ASSERT(window);
if (!window) {
return nullptr;
}
const WId windowId = m_window->winId();
const WId windowId = window->winId();
auto it = g_framelessWidgetsHelperData()->find(windowId);
if (it == g_framelessWidgetsHelperData()->end()) {
it = g_framelessWidgetsHelperData()->insert(windowId, {});
@ -667,11 +479,11 @@ const FramelessWidgetsHelperData *FramelessWidgetsHelperPrivate::getWindowData()
FramelessWidgetsHelperData *FramelessWidgetsHelperPrivate::getWindowDataMutable() const
{
//Q_ASSERT(m_window);
if (!m_window) {
//Q_ASSERT(window);
if (!window) {
return nullptr;
}
const WId windowId = m_window->winId();
const WId windowId = window->winId();
auto it = g_framelessWidgetsHelperData()->find(windowId);
if (it == g_framelessWidgetsHelperData()->end()) {
it = g_framelessWidgetsHelperData()->insert(windowId, {});
@ -685,10 +497,10 @@ QRect FramelessWidgetsHelperPrivate::mapWidgetGeometryToScene(const QWidget * co
if (!widget) {
return {};
}
if (!m_window) {
if (!window) {
return {};
}
const QPoint originPoint = widget->mapTo(m_window, QPoint(0, 0));
const QPoint originPoint = widget->mapTo(window, QPoint(0, 0));
const QSize size = widget->size();
return QRect(originPoint, size);
}
@ -751,12 +563,12 @@ bool FramelessWidgetsHelperPrivate::isInTitleBarDraggableArea(const QPoint &pos)
// The title bar is hidden or disabled for some reason, treat it as there's no title bar.
return false;
}
if (!m_window) {
if (!window) {
// The FramelessWidgetsHelper object has not been attached to a specific window yet,
// so we assume there's no title bar.
return false;
}
const QRect windowRect = {QPoint(0, 0), m_window->size()};
const QRect windowRect = {QPoint(0, 0), window->size()};
const QRect titleBarRect = mapWidgetGeometryToScene(data->titleBarWidget);
if (!titleBarRect.intersects(windowRect)) {
// The title bar is totally outside of the window for some reason,
@ -793,7 +605,7 @@ bool FramelessWidgetsHelperPrivate::isInTitleBarDraggableArea(const QPoint &pos)
bool FramelessWidgetsHelperPrivate::shouldIgnoreMouseEvents(const QPoint &pos) const
{
if (!m_window) {
if (!window) {
return false;
}
const auto withinFrameBorder = [this, &pos]() -> bool {
@ -806,9 +618,9 @@ bool FramelessWidgetsHelperPrivate::shouldIgnoreMouseEvents(const QPoint &pos) c
}
#endif
return ((pos.x() < kDefaultResizeBorderThickness)
|| (pos.x() >= (m_window->width() - kDefaultResizeBorderThickness)));
|| (pos.x() >= (window->width() - kDefaultResizeBorderThickness)));
}();
return ((Utils::windowStatesToWindowState(m_window->windowState()) == Qt::WindowNoState) && withinFrameBorder);
return ((Utils::windowStatesToWindowState(window->windowState()) == Qt::WindowNoState) && withinFrameBorder);
}
void FramelessWidgetsHelperPrivate::setSystemButtonState(const SystemButtonType button, const ButtonState state)
@ -817,42 +629,45 @@ void FramelessWidgetsHelperPrivate::setSystemButtonState(const SystemButtonType
Q_UNUSED(state);
}
void FramelessWidgetsHelperPrivate::moveWindowToDesktopCenter()
void FramelessWidgetsHelper::moveWindowToDesktopCenter()
{
if (!m_window) {
Q_D(FramelessWidgetsHelper);
if (!d->window) {
return;
}
Utils::moveWindowToDesktopCenter(&getWindowData()->params, true);
Utils::moveWindowToDesktopCenter(&d->getWindowData()->params, true);
}
void FramelessWidgetsHelperPrivate::bringWindowToFront()
void FramelessWidgetsHelper::bringWindowToFront()
{
if (!m_window) {
Q_D(FramelessWidgetsHelper);
if (!d->window) {
return;
}
#ifdef Q_OS_WINDOWS
std::ignore = Utils::bringWindowToFront(m_window->winId());
std::ignore = Utils::bringWindowToFront(d->window->winId());
#else
if (m_window->isHidden()) {
m_window->show();
if (d->window->isHidden()) {
d->window->show();
}
if (m_window->isMinimized()) {
m_window->setWindowState(m_window->windowState() & ~Qt::WindowMinimized);
if (d->window->isMinimized()) {
d->window->setWindowState(d->window->windowState() & ~Qt::WindowMinimized);
}
m_window->raise();
m_window->activateWindow();
d->window->raise();
d->window->activateWindow();
#endif
}
void FramelessWidgetsHelperPrivate::showSystemMenu(const QPoint &pos)
void FramelessWidgetsHelper::showSystemMenu(const QPoint &pos)
{
if (!m_window) {
Q_D(FramelessWidgetsHelper);
if (!d->window) {
return;
}
const WId windowId = m_window->winId();
const QPoint nativePos = Utils::toNativeGlobalPosition(m_window->windowHandle(), pos);
const WId windowId = d->window->winId();
const QPoint nativePos = Utils::toNativeGlobalPosition(d->window->windowHandle(), pos);
#ifdef Q_OS_WINDOWS
std::ignore = Utils::showSystemMenu(windowId, nativePos, false, &getWindowData()->params);
std::ignore = Utils::showSystemMenu(windowId, nativePos, false, &d->getWindowData()->params);
#elif defined(Q_OS_LINUX)
Utils::openSystemMenu(windowId, nativePos);
#else
@ -861,33 +676,36 @@ void FramelessWidgetsHelperPrivate::showSystemMenu(const QPoint &pos)
#endif
}
void FramelessWidgetsHelperPrivate::windowStartSystemMove2(const QPoint &pos)
void FramelessWidgetsHelper::windowStartSystemMove2(const QPoint &pos)
{
if (!m_window) {
Q_D(FramelessWidgetsHelper);
if (!d->window) {
return;
}
std::ignore = Utils::startSystemMove(m_window->windowHandle(), pos);
std::ignore = Utils::startSystemMove(d->window->windowHandle(), pos);
}
void FramelessWidgetsHelperPrivate::windowStartSystemResize2(const Qt::Edges edges, const QPoint &pos)
void FramelessWidgetsHelper::windowStartSystemResize2(const Qt::Edges edges, const QPoint &pos)
{
if (!m_window) {
Q_D(FramelessWidgetsHelper);
if (!d->window) {
return;
}
if (edges == Qt::Edges{}) {
return;
}
std::ignore = Utils::startSystemResize(m_window->windowHandle(), edges, pos);
std::ignore = Utils::startSystemResize(d->window->windowHandle(), edges, pos);
}
void FramelessWidgetsHelperPrivate::setSystemButton(QWidget *widget, const SystemButtonType buttonType)
void FramelessWidgetsHelper::setSystemButton(QWidget *widget, const SystemButtonType buttonType)
{
Q_ASSERT(widget);
Q_ASSERT(buttonType != SystemButtonType::Unknown);
if (!widget || (buttonType == SystemButtonType::Unknown)) {
return;
}
FramelessWidgetsHelperData *data = getWindowDataMutable();
Q_D(FramelessWidgetsHelper);
FramelessWidgetsHelperData *data = d->getWindowDataMutable();
if (!data) {
return;
}
@ -929,34 +747,10 @@ FramelessWidgetsHelper *FramelessWidgetsHelper::get(QObject *object)
return FramelessWidgetsHelperPrivate::findOrCreateFramelessHelper(object);
}
QWidget *FramelessWidgetsHelper::titleBarWidget() const
{
Q_D(const FramelessWidgetsHelper);
return d->getTitleBarWidget();
}
bool FramelessWidgetsHelper::isWindowFixedSize() const
{
Q_D(const FramelessWidgetsHelper);
return d->isWindowFixedSize();
}
bool FramelessWidgetsHelper::isBlurBehindWindowEnabled() const
{
Q_D(const FramelessWidgetsHelper);
return d->isBlurBehindWindowEnabled();
}
QWidget *FramelessWidgetsHelper::window() const
{
Q_D(const FramelessWidgetsHelper);
return d->window();
}
bool FramelessWidgetsHelper::isContentExtendedIntoTitleBar() const
{
Q_D(const FramelessWidgetsHelper);
return d->isContentExtendedIntoTitleBar();
return d->window;
}
MicaMaterial *FramelessWidgetsHelper::micaMaterial() const
@ -971,22 +765,107 @@ WindowBorderPainter *FramelessWidgetsHelper::windowBorder() const
return d->getWindowBorderIfAny();
}
bool FramelessWidgetsHelper::isWindowFixedSize() const
{
Q_D(const FramelessWidgetsHelper);
if (!d->window) {
return false;
}
return isWidgetFixedSize(d->window);
}
void FramelessWidgetsHelper::setWindowFixedSize(const bool value)
{
Q_D(FramelessWidgetsHelper);
if (!d->window) {
return;
}
if (isWindowFixedSize() == value) {
return;
}
if (value) {
d->savedSizePolicy = d->window->sizePolicy();
d->window->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
d->window->setFixedSize(d->window->size());
} else {
d->window->setSizePolicy(d->savedSizePolicy);
d->window->setMinimumSize(kDefaultWindowSize);
d->window->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
}
#ifdef Q_OS_WINDOWS
std::ignore = Utils::setAeroSnappingEnabled(d->window->winId(), !value);
#endif
d->emitSignalForAllInstances("windowFixedSizeChanged");
}
bool FramelessWidgetsHelper::isBlurBehindWindowEnabled() const
{
Q_D(const FramelessWidgetsHelper);
return d->blurBehindWindowEnabled;
}
void FramelessWidgetsHelper::setBlurBehindWindowEnabled(const bool enable)
{
Q_D(FramelessWidgetsHelper);
if (!d->window) {
return;
}
if (d->blurBehindWindowEnabled == enable) {
return;
}
if (Utils::isBlurBehindWindowSupported()) {
QPalette palette = d->window->palette();
if (enable) {
d->savedWindowBackgroundColor = palette.color(QPalette::Window);
}
palette.setColor(QPalette::Window, (enable ? kDefaultTransparentColor : d->savedWindowBackgroundColor));
d->window->setPalette(palette);
if (Utils::setBlurBehindWindowEnabled(d->window->winId(), (enable ? BlurMode::Default : BlurMode::Disable), {})) {
d->blurBehindWindowEnabled = enable;
d->emitSignalForAllInstances("blurBehindWindowEnabledChanged");
} else {
WARNING << "Failed to enable/disable blur behind window.";
}
} else {
if (WidgetsSharedHelper * const helper = d->findOrCreateSharedHelper(d->window)) {
d->blurBehindWindowEnabled = enable;
helper->setMicaEnabled(d->blurBehindWindowEnabled);
d->emitSignalForAllInstances("blurBehindWindowEnabledChanged");
} else {
DEBUG << "Blur behind window is not supported on current platform.";
}
}
}
bool FramelessWidgetsHelper::isReady() const
{
Q_D(const FramelessWidgetsHelper);
return d->isReady();
return d->qpaReady;
}
void FramelessWidgetsHelper::waitForReady()
{
Q_D(FramelessWidgetsHelper);
d->waitForReady();
if (d->qpaReady) {
return;
}
#if 1
QEventLoop loop{};
const QMetaObject::Connection connection = connect(this, &FramelessWidgetsHelper::ready, &loop, &QEventLoop::quit);
loop.exec();
disconnect(connection);
#else
while (!d->qpaReady) {
QCoreApplication::processEvents();
}
#endif
}
void FramelessWidgetsHelper::extendsContentIntoTitleBar(const bool value)
bool FramelessWidgetsHelper::isContentExtendedIntoTitleBar() const
{
Q_D(FramelessWidgetsHelper);
d->extendsContentIntoTitleBar(value);
Q_D(const FramelessWidgetsHelper);
const FramelessWidgetsHelperData *data = d->getWindowData();
return (data ? data->ready : false);
}
void FramelessWidgetsHelper::setTitleBarWidget(QWidget *widget)
@ -996,18 +875,19 @@ void FramelessWidgetsHelper::setTitleBarWidget(QWidget *widget)
return;
}
Q_D(FramelessWidgetsHelper);
d->setTitleBarWidget(widget);
}
void FramelessWidgetsHelper::setSystemButton(QWidget *widget, const SystemButtonType buttonType)
{
Q_ASSERT(widget);
Q_ASSERT(buttonType != SystemButtonType::Unknown);
if (!widget || (buttonType == SystemButtonType::Unknown)) {
FramelessWidgetsHelperData *data = d->getWindowDataMutable();
if (!data || (data->titleBarWidget == widget)) {
return;
}
Q_D(FramelessWidgetsHelper);
d->setSystemButton(widget, buttonType);
data->titleBarWidget = widget;
d->emitSignalForAllInstances("titleBarWidgetChanged");
}
QWidget *FramelessWidgetsHelper::titleBarWidget() const
{
Q_D(const FramelessWidgetsHelper);
const FramelessWidgetsHelperData *data = d->getWindowData();
return (data ? data->titleBarWidget : nullptr);
}
void FramelessWidgetsHelper::setHitTestVisible(QWidget *widget, const bool visible)
@ -1017,7 +897,15 @@ void FramelessWidgetsHelper::setHitTestVisible(QWidget *widget, const bool visib
return;
}
Q_D(FramelessWidgetsHelper);
d->setHitTestVisible(widget, visible);
FramelessWidgetsHelperData *data = d->getWindowDataMutable();
if (!data) {
return;
}
if (visible) {
data->hitTestVisibleWidgets.append(widget);
} else {
data->hitTestVisibleWidgets.removeAll(widget);
}
}
void FramelessWidgetsHelper::setHitTestVisible(const QRect &rect, const bool visible)
@ -1027,7 +915,15 @@ void FramelessWidgetsHelper::setHitTestVisible(const QRect &rect, const bool vis
return;
}
Q_D(FramelessWidgetsHelper);
d->setHitTestVisible(rect, visible);
FramelessWidgetsHelperData *data = d->getWindowDataMutable();
if (!data) {
return;
}
if (visible) {
data->hitTestVisibleRects.append(rect);
} else {
data->hitTestVisibleRects.removeAll(rect);
}
}
void FramelessWidgetsHelper::setHitTestVisible(QObject *object, const bool visible)
@ -1036,53 +932,26 @@ void FramelessWidgetsHelper::setHitTestVisible(QObject *object, const bool visib
if (!object) {
return;
}
Q_D(FramelessWidgetsHelper);
d->setHitTestVisible(object, visible);
const auto widget = qobject_cast<QWidget *>(object);
Q_ASSERT(widget);
if (!widget) {
return;
}
setHitTestVisible(widget, visible);
}
void FramelessWidgetsHelper::showSystemMenu(const QPoint &pos)
void FramelessWidgetsHelper::extendsContentIntoTitleBar(const bool value)
{
Q_D(FramelessWidgetsHelper);
d->showSystemMenu(pos);
}
void FramelessWidgetsHelper::windowStartSystemMove2(const QPoint &pos)
{
Q_D(FramelessWidgetsHelper);
d->windowStartSystemMove2(pos);
}
void FramelessWidgetsHelper::windowStartSystemResize2(const Qt::Edges edges, const QPoint &pos)
{
if (edges == Qt::Edges{}) {
if (isContentExtendedIntoTitleBar() == value) {
return;
}
Q_D(FramelessWidgetsHelper);
d->windowStartSystemResize2(edges, pos);
}
void FramelessWidgetsHelper::moveWindowToDesktopCenter()
{
Q_D(FramelessWidgetsHelper);
d->moveWindowToDesktopCenter();
}
void FramelessWidgetsHelper::bringWindowToFront()
{
Q_D(FramelessWidgetsHelper);
d->bringWindowToFront();
}
void FramelessWidgetsHelper::setWindowFixedSize(const bool value)
{
Q_D(FramelessWidgetsHelper);
d->setWindowFixedSize(value);
}
void FramelessWidgetsHelper::setBlurBehindWindowEnabled(const bool value)
{
Q_D(FramelessWidgetsHelper);
d->setBlurBehindWindowEnabled(value, {});
if (value) {
d->attach();
} else {
d->detach();
}
d->emitSignalForAllInstances("extendsContentIntoTitleBarChanged");
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -56,7 +56,6 @@ StandardSystemButtonPrivate::StandardSystemButtonPrivate(StandardSystemButton *q
return;
}
q_ptr = q;
initialize();
}
StandardSystemButtonPrivate::~StandardSystemButtonPrivate() = default;
@ -79,252 +78,20 @@ const StandardSystemButtonPrivate *StandardSystemButtonPrivate::get(const Standa
return pub->d_func();
}
QString StandardSystemButtonPrivate::getGlyph() const
{
return m_glyph;
}
void StandardSystemButtonPrivate::setGlyph(const QString &value)
{
Q_ASSERT(!value.isEmpty());
if (value.isEmpty()) {
return;
}
if (m_glyph == value) {
return;
}
m_glyph = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->glyphChanged();
}
SystemButtonType StandardSystemButtonPrivate::getButtonType() const
{
return m_buttonType;
}
void StandardSystemButtonPrivate::setButtonType(const SystemButtonType type)
{
Q_ASSERT(type != SystemButtonType::Unknown);
if (type == SystemButtonType::Unknown) {
return;
}
if (m_buttonType == type) {
return;
}
m_buttonType = type;
setGlyph(Utils::getSystemButtonGlyph(m_buttonType));
Q_Q(StandardSystemButton);
q->update();
}
QSize StandardSystemButtonPrivate::getRecommendedButtonSize() const
QSize StandardSystemButtonPrivate::getRecommendedButtonSize()
{
return kDefaultSystemButtonSize;
}
QColor StandardSystemButtonPrivate::getHoverColor() const
{
return m_hoverColor;
}
QColor StandardSystemButtonPrivate::getPressColor() const
{
return m_pressColor;
}
QColor StandardSystemButtonPrivate::getNormalColor() const
{
return m_normalColor;
}
QColor StandardSystemButtonPrivate::getActiveForegroundColor() const
{
return m_activeForegroundColor;
}
QColor StandardSystemButtonPrivate::getInactiveForegroundColor() const
{
return m_inactiveForegroundColor;
}
bool StandardSystemButtonPrivate::isActive() const
{
return m_active;
}
int StandardSystemButtonPrivate::glyphSize() const
{
return m_glyphSize.value_or(FramelessManagerPrivate::getIconFont().pointSize());
}
void StandardSystemButtonPrivate::setHoverColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
if (m_hoverColor == value) {
return;
}
m_hoverColor = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->hoverColorChanged();
}
void StandardSystemButtonPrivate::setPressColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
if (m_pressColor == value) {
return;
}
m_pressColor = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->pressColorChanged();
}
void StandardSystemButtonPrivate::setNormalColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
if (m_normalColor == value) {
return;
}
m_normalColor = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->normalColorChanged();
}
void StandardSystemButtonPrivate::setActiveForegroundColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
if (m_activeForegroundColor == value) {
return;
}
m_activeForegroundColor = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->activeForegroundColorChanged();
}
void StandardSystemButtonPrivate::setInactiveForegroundColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
if (m_inactiveForegroundColor == value) {
return;
}
m_inactiveForegroundColor = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->inactiveForegroundColorChanged();
}
void StandardSystemButtonPrivate::setActive(const bool value)
{
if (m_active == value) {
return;
}
m_active = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->activeChanged();
}
void StandardSystemButtonPrivate::setGlyphSize(const int value)
{
Q_ASSERT(value > 0);
if (value <= 0) {
return;
}
if (glyphSize() == value) {
return;
}
m_glyphSize = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->glyphSizeChanged();
}
void StandardSystemButtonPrivate::paintEventHandler(QPaintEvent *event)
{
Q_ASSERT(event);
if (!event) {
return;
}
Q_Q(StandardSystemButton);
QPainter painter(q);
painter.save();
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing
| QPainter::SmoothPixmapTransform);
const auto backgroundColor = [this, q]() -> QColor {
// The pressed state has higher priority than the hovered state.
if (q->isDown() && m_pressColor.isValid()) {
return m_pressColor;
}
if (q->underMouse() && m_hoverColor.isValid()) {
return m_hoverColor;
}
if (m_normalColor.isValid()) {
return m_normalColor;
}
return {};
}();
const QRect buttonRect = {QPoint(0, 0), q->size()};
if (backgroundColor.isValid()) {
painter.fillRect(buttonRect, backgroundColor);
}
if (!m_glyph.isEmpty()) {
painter.setPen([this, q]() -> QColor {
if (!q->underMouse() && !m_active && m_inactiveForegroundColor.isValid()) {
return m_inactiveForegroundColor;
}
if (m_activeForegroundColor.isValid()) {
return m_activeForegroundColor;
}
return kDefaultBlackColor;
}());
painter.setFont([this]() -> QFont {
QFont font = FramelessManagerPrivate::getIconFont();
if (m_glyphSize.has_value()) {
font.setPointSize(m_glyphSize.value());
}
return font;
}());
painter.drawText(buttonRect, Qt::AlignCenter, m_glyph);
}
painter.restore();
event->accept();
}
void StandardSystemButtonPrivate::initialize()
{
FramelessManagerPrivate::initializeIconFont();
Q_Q(StandardSystemButton);
q->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
q->setFixedSize(getRecommendedButtonSize());
q->setIconSize(kDefaultSystemButtonIconSize);
q->setMouseTracking(true);
q->setAttribute(Qt::WA_Hover);
}
StandardSystemButton::StandardSystemButton(QWidget *parent)
: QPushButton(parent), d_ptr(new StandardSystemButtonPrivate(this))
{
FramelessManagerPrivate::initializeIconFont();
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setFixedSize(StandardSystemButtonPrivate::getRecommendedButtonSize());
setIconSize(kDefaultSystemButtonIconSize);
setMouseTracking(true);
setAttribute(Qt::WA_Hover);
}
StandardSystemButton::StandardSystemButton(const SystemButtonType type, QWidget *parent)
@ -337,122 +104,243 @@ StandardSystemButton::~StandardSystemButton() = default;
QSize StandardSystemButton::sizeHint() const
{
Q_D(const StandardSystemButton);
return d->getRecommendedButtonSize();
}
SystemButtonType StandardSystemButton::buttonType()
{
Q_D(const StandardSystemButton);
return d->getButtonType();
return StandardSystemButtonPrivate::getRecommendedButtonSize();
}
QString StandardSystemButton::glyph() const
{
Q_D(const StandardSystemButton);
return d->getGlyph();
return d->glyph;
}
void StandardSystemButton::setButtonType(const SystemButtonType value)
void StandardSystemButton::setGlyph(const QString &value)
{
Q_ASSERT(!value.isEmpty());
if (value.isEmpty()) {
return;
}
Q_D(StandardSystemButton);
d->setButtonType(value);
if (d->glyph == value) {
return;
}
d->glyph = value;
update();
Q_EMIT glyphChanged();
}
void StandardSystemButton::setGlyph(const QString &glyph)
SystemButtonType StandardSystemButton::buttonType() const
{
Q_D(const StandardSystemButton);
return d->buttonType;
}
void StandardSystemButton::setButtonType(const SystemButtonType type)
{
Q_ASSERT(type != SystemButtonType::Unknown);
if (type == SystemButtonType::Unknown) {
return;
}
Q_D(StandardSystemButton);
d->setGlyph(glyph);
if (d->buttonType == type) {
return;
}
d->buttonType = type;
setGlyph(Utils::getSystemButtonGlyph(d->buttonType));
update();
}
QColor StandardSystemButton::hoverColor() const
{
Q_D(const StandardSystemButton);
return d->getHoverColor();
}
void StandardSystemButton::setHoverColor(const QColor &value)
{
Q_D(StandardSystemButton);
d->setHoverColor(value);
return d->hoverColor;
}
QColor StandardSystemButton::pressColor() const
{
Q_D(const StandardSystemButton);
return d->getPressColor();
return d->pressColor;
}
QColor StandardSystemButton::normalColor() const
{
Q_D(const StandardSystemButton);
return d->getNormalColor();
return d->normalColor;
}
QColor StandardSystemButton::activeForegroundColor() const
{
Q_D(const StandardSystemButton);
return d->getActiveForegroundColor();
return d->activeForegroundColor;
}
QColor StandardSystemButton::inactiveForegroundColor() const
{
Q_D(const StandardSystemButton);
return d->getInactiveForegroundColor();
return d->inactiveForegroundColor;
}
bool StandardSystemButton::isActive() const
{
Q_D(const StandardSystemButton);
return d->isActive();
return d->active;
}
int StandardSystemButton::glyphSize() const
{
Q_D(const StandardSystemButton);
return d->glyphSize();
return d->glyphSize.value_or(FramelessManagerPrivate::getIconFont().pointSize());
}
void StandardSystemButton::setHoverColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
Q_D(StandardSystemButton);
if (d->hoverColor == value) {
return;
}
d->hoverColor = value;
update();
Q_EMIT hoverColorChanged();
}
void StandardSystemButton::setPressColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
Q_D(StandardSystemButton);
d->setPressColor(value);
if (d->pressColor == value) {
return;
}
d->pressColor = value;
update();
Q_EMIT pressColorChanged();
}
void StandardSystemButton::setNormalColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
Q_D(StandardSystemButton);
d->setNormalColor(value);
if (d->normalColor == value) {
return;
}
d->normalColor = value;
update();
Q_EMIT normalColorChanged();
}
void StandardSystemButton::setActiveForegroundColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
Q_D(StandardSystemButton);
d->setActiveForegroundColor(value);
if (d->activeForegroundColor == value) {
return;
}
d->activeForegroundColor = value;
update();
Q_EMIT activeForegroundColorChanged();
}
void StandardSystemButton::setInactiveForegroundColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
Q_D(StandardSystemButton);
d->setInactiveForegroundColor(value);
if (d->inactiveForegroundColor == value) {
return;
}
d->inactiveForegroundColor = value;
update();
Q_EMIT inactiveForegroundColorChanged();
}
void StandardSystemButton::setActive(const bool value)
{
Q_D(StandardSystemButton);
d->setActive(value);
if (d->active == value) {
return;
}
d->active = value;
update();
Q_EMIT activeChanged();
}
void StandardSystemButton::setGlyphSize(const int value)
{
Q_ASSERT(value > 0);
if (value <= 0) {
return;
}
if (glyphSize() == value) {
return;
}
Q_D(StandardSystemButton);
d->setGlyphSize(value);
d->glyphSize = value;
update();
Q_EMIT glyphSizeChanged();
}
void StandardSystemButton::paintEvent(QPaintEvent *event)
{
Q_ASSERT(event);
if (!event) {
return;
}
Q_D(StandardSystemButton);
d->paintEventHandler(event);
QPainter painter(this);
painter.save();
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing
| QPainter::SmoothPixmapTransform);
const auto backgroundColor = [this, d]() -> QColor {
// The pressed state has higher priority than the hovered state.
if (isDown() && d->pressColor.isValid()) {
return d->pressColor;
}
if (underMouse() && d->hoverColor.isValid()) {
return d->hoverColor;
}
if (d->normalColor.isValid()) {
return d->normalColor;
}
return {};
}();
const QRect buttonRect = {QPoint(0, 0), size()};
if (backgroundColor.isValid()) {
painter.fillRect(buttonRect, backgroundColor);
}
if (!d->glyph.isEmpty()) {
painter.setPen([this, d]() -> QColor {
if (!underMouse() && !d->active && d->inactiveForegroundColor.isValid()) {
return d->inactiveForegroundColor;
}
if (d->activeForegroundColor.isValid()) {
return d->activeForegroundColor;
}
return kDefaultBlackColor;
}());
painter.setFont([d]() -> QFont {
QFont font = FramelessManagerPrivate::getIconFont();
if (d->glyphSize.has_value()) {
font.setPointSize(d->glyphSize.value());
}
return font;
}());
painter.drawText(buttonRect, Qt::AlignCenter, d->glyph);
}
painter.restore();
event->accept();
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -83,58 +83,6 @@ const StandardTitleBarPrivate *StandardTitleBarPrivate::get(const StandardTitleB
return pub->d_func();
}
Qt::Alignment StandardTitleBarPrivate::titleLabelAlignment() const
{
return m_labelAlignment;
}
void StandardTitleBarPrivate::setTitleLabelAlignment(const Qt::Alignment value)
{
if (m_labelAlignment == value) {
return;
}
m_labelAlignment = value;
Q_Q(StandardTitleBar);
q->update();
Q_EMIT q->titleLabelAlignmentChanged();
}
bool StandardTitleBarPrivate::isExtended() const
{
return m_extended;
}
void StandardTitleBarPrivate::setExtended(const bool value)
{
if (m_extended == value) {
return;
}
m_extended = value;
Q_Q(StandardTitleBar);
q->setFixedHeight(m_extended ? kDefaultExtendedTitleBarHeight : kDefaultTitleBarHeight);
Q_EMIT q->extendedChanged();
}
bool StandardTitleBarPrivate::isHideWhenClose() const
{
return m_hideWhenClose;
}
void StandardTitleBarPrivate::setHideWhenClose(const bool value)
{
if (m_hideWhenClose == value) {
return;
}
m_hideWhenClose = value;
Q_Q(StandardTitleBar);
Q_EMIT q->hideWhenCloseChanged();
}
ChromePalette *StandardTitleBarPrivate::chromePalette() const
{
return m_chromePalette;
}
QFont StandardTitleBarPrivate::defaultFont() const
{
Q_Q(const StandardTitleBar);
@ -145,14 +93,14 @@ QFont StandardTitleBarPrivate::defaultFont() const
StandardTitleBarPrivate::FontMetrics StandardTitleBarPrivate::titleLabelSize() const
{
if (!m_window) {
if (!window) {
return {};
}
const QString text = m_window->windowTitle();
const QString text = window->windowTitle();
if (text.isEmpty()) {
return {};
}
const QFont font = m_titleFont.value_or(defaultFont());
const QFont font = titleFont.value_or(defaultFont());
const QFontMetrics fontMetrics(font);
return {
/* .width */ Utils::horizontalAdvance(fontMetrics, text),
@ -161,143 +109,6 @@ StandardTitleBarPrivate::FontMetrics StandardTitleBarPrivate::titleLabelSize() c
};
}
void StandardTitleBarPrivate::paintTitleBar(QPaintEvent *event)
{
Q_ASSERT(event);
if (!event) {
return;
}
Q_Q(StandardTitleBar);
if (!m_window || !m_chromePalette) {
return;
}
const bool active = m_window->isActiveWindow();
const QColor backgroundColor = (active ?
m_chromePalette->titleBarActiveBackgroundColor() :
m_chromePalette->titleBarInactiveBackgroundColor());
const QColor foregroundColor = (active ?
m_chromePalette->titleBarActiveForegroundColor() :
m_chromePalette->titleBarInactiveForegroundColor());
QPainter painter(q);
painter.save();
painter.setRenderHints(QPainter::Antialiasing |
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
painter.fillRect(QRect(QPoint(0, 0), q->size()), backgroundColor);
if (m_titleLabelVisible) {
const QString text = m_window->windowTitle();
if (!text.isEmpty()) {
painter.setPen(foregroundColor);
painter.setFont(m_titleFont.value_or(defaultFont()));
const auto pos = [this, q]() -> QPoint {
const FontMetrics labelSize = titleLabelSize();
const int titleBarWidth = q->width();
int x = 0;
if (m_labelAlignment & Qt::AlignLeft) {
x = (windowIconRect().right() + kDefaultTitleBarContentsMargin);
} else if (m_labelAlignment & Qt::AlignRight) {
x = (titleBarWidth - kDefaultTitleBarContentsMargin - labelSize.width);
#ifndef Q_OS_MACOS
x -= (titleBarWidth - m_minimizeButton->x());
#endif // Q_OS_MACOS
} else if (m_labelAlignment & Qt::AlignHCenter) {
x = std::round(qreal(titleBarWidth - labelSize.width) / qreal(2));
} else {
WARNING << "The alignment for the title label is not set!";
}
const int y = std::round((qreal(q->height() - labelSize.height) / qreal(2)) + qreal(labelSize.ascent));
return {x, y};
}();
painter.drawText(pos, text);
}
}
if (m_windowIconVisible) {
const QIcon icon = m_window->windowIcon();
if (!icon.isNull()) {
icon.paint(&painter, windowIconRect());
}
}
painter.restore();
event->accept();
}
bool StandardTitleBarPrivate::titleLabelVisible() const
{
return m_titleLabelVisible;
}
void StandardTitleBarPrivate::setTitleLabelVisible(const bool value)
{
if (m_titleLabelVisible == value) {
return;
}
m_titleLabelVisible = value;
Q_Q(StandardTitleBar);
q->update();
Q_EMIT q->titleLabelVisibleChanged();
}
QSize StandardTitleBarPrivate::windowIconSize() const
{
return m_windowIconSize.value_or(kDefaultWindowIconSize);
}
void StandardTitleBarPrivate::setWindowIconSize(const QSize &value)
{
Q_ASSERT(!value.isEmpty());
if (value.isEmpty()) {
return;
}
if (windowIconSize() == value) {
return;
}
m_windowIconSize = value;
Q_Q(StandardTitleBar);
q->update();
Q_EMIT q->windowIconSizeChanged();
}
bool StandardTitleBarPrivate::windowIconVisible() const
{
return m_windowIconVisible;
}
void StandardTitleBarPrivate::setWindowIconVisible(const bool value)
{
if (m_windowIconVisible == value) {
return;
}
m_windowIconVisible = value;
Q_Q(StandardTitleBar);
q->update();
Q_EMIT q->windowIconVisibleChanged();
#ifndef Q_OS_MACOS
// Ideally we should use FramelessWidgetsHelper::get(this) everywhere, but sadly when
// we call it here, it may be too early that FramelessWidgetsHelper has not attached
// to the top level widget yet, and thus it will trigger an assert error (the assert
// should not be suppressed, because it usually indicates there's something really
// wrong). So here we have to use the top level widget directly, as a special case.
// NOTE: In your own code, you should always use FramelessWidgetsHelper::get(this)
// if possible.
FramelessWidgetsHelper::get(m_window)->setHitTestVisible(windowIconRect(), windowIconVisible_real());
#endif // Q_OS_MACOS
}
QFont StandardTitleBarPrivate::titleFont() const
{
return m_titleFont.value_or(QFont());
}
void StandardTitleBarPrivate::setTitleFont(const QFont &value)
{
if (titleFont() == value) {
return;
}
m_titleFont = value;
Q_Q(StandardTitleBar);
q->update();
Q_EMIT q->titleFontChanged();
}
bool StandardTitleBarPrivate::mouseEventHandler(QMouseEvent *event)
{
#ifdef Q_OS_MACOS
@ -319,7 +130,7 @@ bool StandardTitleBarPrivate::mouseEventHandler(QMouseEvent *event)
switch (event->type()) {
case QEvent::MouseButtonRelease:
// We need a valid top level widget here.
if (m_window && interestArea) {
if (window && interestArea) {
// Sadly the mouse release events are always triggered before the
// mouse double click events, and if we intercept the mouse release
// events here, we'll never get the double click events afterwards,
@ -339,16 +150,16 @@ bool StandardTitleBarPrivate::mouseEventHandler(QMouseEvent *event)
// The close event is already triggered, don't try to show the
// system menu anymore, otherwise it will prevent our window
// from closing.
if (m_closeTriggered) {
if (closeTriggered) {
return;
}
// Please refer to the comments in StandardTitleBarPrivate::setWindowIconVisible().
FramelessWidgetsHelper::get(m_window)->showSystemMenu([button, q, &scenePos, this]() -> QPoint {
FramelessWidgetsHelper::get(window)->showSystemMenu([button, q, &scenePos, this]() -> QPoint {
QPoint pos = scenePos;
if (button == Qt::LeftButton) {
pos = {0, q->height()};
}
return m_window->mapToGlobal(pos);
return window->mapToGlobal(pos);
}());
});
// Don't eat this event, we have not handled it yet.
@ -356,9 +167,9 @@ bool StandardTitleBarPrivate::mouseEventHandler(QMouseEvent *event)
break;
case QEvent::MouseButtonDblClick:
// We need a valid top level widget here.
if (m_window && (button == Qt::LeftButton) && interestArea) {
m_closeTriggered = true;
m_window->close();
if (window && (button == Qt::LeftButton) && interestArea) {
closeTriggered = true;
window->close();
// Eat this event, we have handled it here.
event->accept();
return true;
@ -377,21 +188,21 @@ QRect StandardTitleBarPrivate::windowIconRect() const
if (!windowIconVisible_real()) {
return {};
}
const QSize size = windowIconSize();
const QSize size = q->windowIconSize();
#ifdef Q_OS_MACOS
const auto x = [this, q, &size]() -> int {
if (m_labelAlignment & Qt::AlignLeft) {
if (labelAlignment & Qt::AlignLeft) {
return (kMacOSChromeButtonAreaWidth + kDefaultTitleBarContentsMargin);
}
const int titleBarWidth = q->width();
const int labelWidth = titleLabelSize().width;
if (m_labelAlignment & Qt::AlignRight) {
if (labelAlignment & Qt::AlignRight) {
// We need two spacer here, one is on the right edge of the title bar,
// the other one is between the window icon and the window label.
return (titleBarWidth - kDefaultTitleBarContentsMargin
- labelWidth - kDefaultTitleBarContentsMargin - size.width());
}
if (m_labelAlignment & Qt::AlignHCenter) {
if (labelAlignment & Qt::AlignHCenter) {
const int centeredX = std::round(qreal(titleBarWidth - labelWidth) / qreal(2));
return (centeredX - kDefaultTitleBarContentsMargin - size.width());
}
@ -407,7 +218,7 @@ QRect StandardTitleBarPrivate::windowIconRect() const
bool StandardTitleBarPrivate::windowIconVisible_real() const
{
return (m_windowIconVisible && !m_window->windowIcon().isNull());
return (windowIconVisible && !window->windowIcon().isNull());
}
bool StandardTitleBarPrivate::isInTitleBarIconArea(const QPoint &pos) const
@ -421,9 +232,9 @@ bool StandardTitleBarPrivate::isInTitleBarIconArea(const QPoint &pos) const
void StandardTitleBarPrivate::updateMaximizeButton()
{
#ifndef Q_OS_MACOS
const bool max = m_window->isMaximized();
m_maximizeButton->setButtonType(max ? SystemButtonType::Restore : SystemButtonType::Maximize);
m_maximizeButton->setToolTip(max ? tr("Restore") : tr("Maximize"));
const bool max = window->isMaximized();
maximizeButton->setButtonType(max ? SystemButtonType::Restore : SystemButtonType::Maximize);
maximizeButton->setToolTip(max ? tr("Restore") : tr("Maximize"));
#endif // Q_OS_MACOS
}
@ -436,39 +247,39 @@ void StandardTitleBarPrivate::updateTitleBarColor()
void StandardTitleBarPrivate::updateChromeButtonColor()
{
#ifndef Q_OS_MACOS
const bool active = m_window->isActiveWindow();
const QColor activeForeground = m_chromePalette->titleBarActiveForegroundColor();
const QColor inactiveForeground = m_chromePalette->titleBarInactiveForegroundColor();
const QColor normal = m_chromePalette->chromeButtonNormalColor();
const QColor hover = m_chromePalette->chromeButtonHoverColor();
const QColor press = m_chromePalette->chromeButtonPressColor();
m_minimizeButton->setActiveForegroundColor(activeForeground);
m_minimizeButton->setInactiveForegroundColor(inactiveForeground);
m_minimizeButton->setNormalColor(normal);
m_minimizeButton->setHoverColor(hover);
m_minimizeButton->setPressColor(press);
m_minimizeButton->setActive(active);
m_maximizeButton->setActiveForegroundColor(activeForeground);
m_maximizeButton->setInactiveForegroundColor(inactiveForeground);
m_maximizeButton->setNormalColor(normal);
m_maximizeButton->setHoverColor(hover);
m_maximizeButton->setPressColor(press);
m_maximizeButton->setActive(active);
m_closeButton->setActiveForegroundColor(activeForeground);
m_closeButton->setInactiveForegroundColor(inactiveForeground);
m_closeButton->setNormalColor(m_chromePalette->closeButtonNormalColor());
m_closeButton->setHoverColor(m_chromePalette->closeButtonHoverColor());
m_closeButton->setPressColor(m_chromePalette->closeButtonPressColor());
m_closeButton->setActive(active);
const bool active = window->isActiveWindow();
const QColor activeForeground = chromePalette->titleBarActiveForegroundColor();
const QColor inactiveForeground = chromePalette->titleBarInactiveForegroundColor();
const QColor normal = chromePalette->chromeButtonNormalColor();
const QColor hover = chromePalette->chromeButtonHoverColor();
const QColor press = chromePalette->chromeButtonPressColor();
minimizeButton->setActiveForegroundColor(activeForeground);
minimizeButton->setInactiveForegroundColor(inactiveForeground);
minimizeButton->setNormalColor(normal);
minimizeButton->setHoverColor(hover);
minimizeButton->setPressColor(press);
minimizeButton->setActive(active);
maximizeButton->setActiveForegroundColor(activeForeground);
maximizeButton->setInactiveForegroundColor(inactiveForeground);
maximizeButton->setNormalColor(normal);
maximizeButton->setHoverColor(hover);
maximizeButton->setPressColor(press);
maximizeButton->setActive(active);
closeButton->setActiveForegroundColor(activeForeground);
closeButton->setInactiveForegroundColor(inactiveForeground);
closeButton->setNormalColor(chromePalette->closeButtonNormalColor());
closeButton->setHoverColor(chromePalette->closeButtonHoverColor());
closeButton->setPressColor(chromePalette->closeButtonPressColor());
closeButton->setActive(active);
#endif // Q_OS_MACOS
}
void StandardTitleBarPrivate::retranslateUi()
{
#ifndef Q_OS_MACOS
m_minimizeButton->setToolTip(tr("Minimize"));
m_maximizeButton->setToolTip(m_window->isMaximized() ? tr("Restore") : tr("Maximize"));
m_closeButton->setToolTip(tr("Close"));
minimizeButton->setToolTip(tr("Minimize"));
maximizeButton->setToolTip(window->isMaximized() ? tr("Restore") : tr("Maximize"));
closeButton->setToolTip(tr("Close"));
#endif // Q_OS_MACOS
}
@ -483,17 +294,17 @@ bool StandardTitleBarPrivate::eventFilter(QObject *object, QEvent *event)
return QObject::eventFilter(object, event);
}
const auto widget = qobject_cast<QWidget *>(object);
if (!widget->isWindow() || (widget != m_window)) {
if (!widget->isWindow() || (widget != window)) {
return QObject::eventFilter(object, event);
}
switch (event->type()) {
case QEvent::WindowStateChange:
updateMaximizeButton();
break;
case QEvent::ActivationChange:
case QEvent::ActivationChange: {
updateTitleBarColor();
updateChromeButtonColor();
break;
} break;
case QEvent::LanguageChange:
retranslateUi();
break;
@ -506,19 +317,19 @@ bool StandardTitleBarPrivate::eventFilter(QObject *object, QEvent *event)
void StandardTitleBarPrivate::initialize()
{
Q_Q(StandardTitleBar);
m_window = q->window();
m_chromePalette = new ChromePalette(this);
connect(m_chromePalette, &ChromePalette::titleBarColorChanged,
window = q->window();
chromePalette = new ChromePalette(this);
connect(chromePalette, &ChromePalette::titleBarColorChanged,
this, &StandardTitleBarPrivate::updateTitleBarColor);
connect(m_chromePalette, &ChromePalette::chromeButtonColorChanged,
connect(chromePalette, &ChromePalette::chromeButtonColorChanged,
this, &StandardTitleBarPrivate::updateChromeButtonColor);
q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
q->setFixedHeight(kDefaultTitleBarHeight);
connect(m_window, &QWidget::windowIconChanged, this, [q](const QIcon &icon){
connect(window, &QWidget::windowIconChanged, this, [q](const QIcon &icon){
Q_UNUSED(icon);
q->update();
});
connect(m_window, &QWidget::windowTitleChanged, this, [q](const QString &title){
connect(window, &QWidget::windowTitleChanged, this, [q](const QString &title){
Q_UNUSED(title);
q->update();
});
@ -526,26 +337,25 @@ void StandardTitleBarPrivate::initialize()
const auto titleBarLayout = new QHBoxLayout(q);
titleBarLayout->setSpacing(0);
titleBarLayout->setContentsMargins(0, 0, 0, 0);
q->setLayout(titleBarLayout);
setTitleLabelAlignment(Qt::AlignCenter);
q->setTitleLabelAlignment(Qt::AlignCenter);
#else // !Q_OS_MACOS
m_minimizeButton = new StandardSystemButton(SystemButtonType::Minimize, q);
connect(m_minimizeButton, &StandardSystemButton::clicked, m_window, &QWidget::showMinimized);
m_maximizeButton = new StandardSystemButton(SystemButtonType::Maximize, q);
minimizeButton = new StandardSystemButton(SystemButtonType::Minimize, q);
connect(minimizeButton, &StandardSystemButton::clicked, window, &QWidget::showMinimized);
maximizeButton = new StandardSystemButton(SystemButtonType::Maximize, q);
updateMaximizeButton();
connect(m_maximizeButton, &StandardSystemButton::clicked, this, [this](){
if (m_window->isMaximized()) {
m_window->showNormal();
connect(maximizeButton, &StandardSystemButton::clicked, this, [this](){
if (window->isMaximized()) {
window->showNormal();
} else {
m_window->showMaximized();
window->showMaximized();
}
});
m_closeButton = new StandardSystemButton(SystemButtonType::Close, q);
connect(m_closeButton, &StandardSystemButton::clicked, this, [this](){
if (m_hideWhenClose) {
m_window->hide();
closeButton = new StandardSystemButton(SystemButtonType::Close, q);
connect(closeButton, &StandardSystemButton::clicked, this, [this](){
if (hideWhenClose) {
window->hide();
} else {
m_window->close();
window->close();
}
});
// According to the title bar design guidance, the system buttons should always be
@ -554,9 +364,9 @@ void StandardTitleBarPrivate::initialize()
const auto systemButtonsInnerLayout = new QHBoxLayout;
systemButtonsInnerLayout->setSpacing(0);
systemButtonsInnerLayout->setContentsMargins(0, 0, 0, 0);
systemButtonsInnerLayout->addWidget(m_minimizeButton);
systemButtonsInnerLayout->addWidget(m_maximizeButton);
systemButtonsInnerLayout->addWidget(m_closeButton);
systemButtonsInnerLayout->addWidget(minimizeButton);
systemButtonsInnerLayout->addWidget(maximizeButton);
systemButtonsInnerLayout->addWidget(closeButton);
const auto systemButtonsOuterLayout = new QVBoxLayout;
systemButtonsOuterLayout->setSpacing(0);
systemButtonsOuterLayout->setContentsMargins(0, 0, 0, 0);
@ -567,13 +377,12 @@ void StandardTitleBarPrivate::initialize()
titleBarLayout->setContentsMargins(0, 0, 0, 0);
titleBarLayout->addStretch();
titleBarLayout->addLayout(systemButtonsOuterLayout);
q->setLayout(titleBarLayout);
setTitleLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter);
q->setTitleLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter);
#endif // Q_OS_MACOS
retranslateUi();
updateTitleBarColor();
updateChromeButtonColor();
m_window->installEventFilter(this);
window->installEventFilter(this);
}
StandardTitleBar::StandardTitleBar(QWidget *parent)
@ -583,122 +392,26 @@ StandardTitleBar::StandardTitleBar(QWidget *parent)
StandardTitleBar::~StandardTitleBar() = default;
Qt::Alignment StandardTitleBar::titleLabelAlignment() const
{
Q_D(const StandardTitleBar);
return d->titleLabelAlignment();
}
void StandardTitleBar::setTitleLabelAlignment(const Qt::Alignment value)
{
Q_D(StandardTitleBar);
d->setTitleLabelAlignment(value);
}
#ifndef Q_OS_MACOS
StandardSystemButton *StandardTitleBar::minimizeButton() const
{
Q_D(const StandardTitleBar);
return d->m_minimizeButton;
return d->minimizeButton;
}
StandardSystemButton *StandardTitleBar::maximizeButton() const
{
Q_D(const StandardTitleBar);
return d->m_maximizeButton;
return d->maximizeButton;
}
StandardSystemButton *StandardTitleBar::closeButton() const
{
Q_D(const StandardTitleBar);
return d->m_closeButton;
return d->closeButton;
}
#endif // Q_OS_MACOS
bool StandardTitleBar::isExtended() const
{
Q_D(const StandardTitleBar);
return d->isExtended();
}
void StandardTitleBar::setExtended(const bool value)
{
Q_D(StandardTitleBar);
d->setExtended(value);
}
bool StandardTitleBar::isHideWhenClose() const
{
Q_D(const StandardTitleBar);
return d->isHideWhenClose();
}
void StandardTitleBar::setHideWhenClose(const bool value)
{
Q_D(StandardTitleBar);
d->setHideWhenClose(value);
}
ChromePalette *StandardTitleBar::chromePalette() const
{
Q_D(const StandardTitleBar);
return d->chromePalette();
}
bool StandardTitleBar::titleLabelVisible() const
{
Q_D(const StandardTitleBar);
return d->titleLabelVisible();
}
void StandardTitleBar::setTitleLabelVisible(const bool value)
{
Q_D(StandardTitleBar);
d->setTitleLabelVisible(value);
}
QSize StandardTitleBar::windowIconSize() const
{
Q_D(const StandardTitleBar);
return d->windowIconSize();
}
void StandardTitleBar::setWindowIconSize(const QSize &value)
{
Q_D(StandardTitleBar);
d->setWindowIconSize(value);
}
bool StandardTitleBar::windowIconVisible() const
{
Q_D(const StandardTitleBar);
return d->windowIconVisible();
}
void StandardTitleBar::setWindowIconVisible(const bool value)
{
Q_D(StandardTitleBar);
d->setWindowIconVisible(value);
}
QFont StandardTitleBar::titleFont() const
{
Q_D(const StandardTitleBar);
return d->titleFont();
}
void StandardTitleBar::setTitleFont(const QFont &value)
{
Q_D(StandardTitleBar);
d->setTitleFont(value);
}
void StandardTitleBar::paintEvent(QPaintEvent *event)
{
Q_D(StandardTitleBar);
d->paintTitleBar(event);
}
void StandardTitleBar::mouseReleaseEvent(QMouseEvent *event)
{
QWidget::mouseReleaseEvent(event);
@ -713,4 +426,201 @@ void StandardTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
std::ignore = d->mouseEventHandler(event);
}
Qt::Alignment StandardTitleBar::titleLabelAlignment() const
{
Q_D(const StandardTitleBar);
return d->labelAlignment;
}
void StandardTitleBar::setTitleLabelAlignment(const Qt::Alignment value)
{
Q_D(StandardTitleBar);
if (d->labelAlignment == value) {
return;
}
d->labelAlignment = value;
update();
Q_EMIT titleLabelAlignmentChanged();
}
bool StandardTitleBar::isExtended() const
{
Q_D(const StandardTitleBar);
return d->extended;
}
void StandardTitleBar::setExtended(const bool value)
{
Q_D(StandardTitleBar);
if (d->extended == value) {
return;
}
d->extended = value;
setFixedHeight(d->extended ? kDefaultExtendedTitleBarHeight : kDefaultTitleBarHeight);
Q_EMIT extendedChanged();
}
bool StandardTitleBar::isHideWhenClose() const
{
Q_D(const StandardTitleBar);
return d->hideWhenClose;
}
void StandardTitleBar::setHideWhenClose(const bool value)
{
Q_D(StandardTitleBar);
if (d->hideWhenClose == value) {
return;
}
d->hideWhenClose = value;
Q_EMIT hideWhenCloseChanged();
}
ChromePalette *StandardTitleBar::chromePalette() const
{
Q_D(const StandardTitleBar);
return d->chromePalette;
}
void StandardTitleBar::paintEvent(QPaintEvent *event)
{
Q_ASSERT(event);
if (!event) {
return;
}
Q_D(StandardTitleBar);
if (!d->window) {
return;
}
const bool active = d->window->isActiveWindow();
const QColor backgroundColor = (active ?
d->chromePalette->titleBarActiveBackgroundColor() :
d->chromePalette->titleBarInactiveBackgroundColor());
const QColor foregroundColor = (active ?
d->chromePalette->titleBarActiveForegroundColor() :
d->chromePalette->titleBarInactiveForegroundColor());
QPainter painter(this);
painter.save();
painter.setRenderHints(QPainter::Antialiasing |
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
painter.fillRect(QRect(QPoint(0, 0), size()), backgroundColor);
if (d->titleLabelVisible) {
const QString text = d->window->windowTitle();
if (!text.isEmpty()) {
painter.setPen(foregroundColor);
painter.setFont(d->titleFont.value_or(d->defaultFont()));
const auto pos = [this, d]() -> QPoint {
const StandardTitleBarPrivate::FontMetrics labelSize = d->titleLabelSize();
const int titleBarWidth = width();
int x = 0;
if (d->labelAlignment & Qt::AlignLeft) {
x = (d->windowIconRect().right() + kDefaultTitleBarContentsMargin);
} else if (d->labelAlignment & Qt::AlignRight) {
x = (titleBarWidth - kDefaultTitleBarContentsMargin - labelSize.width);
#ifndef Q_OS_MACOS
x -= (titleBarWidth - d->minimizeButton->x());
#endif // Q_OS_MACOS
} else if (d->labelAlignment & Qt::AlignHCenter) {
x = std::round(qreal(titleBarWidth - labelSize.width) / qreal(2));
} else {
WARNING << "The alignment for the title label is not set!";
}
const int y = std::round((qreal(height() - labelSize.height) / qreal(2)) + qreal(labelSize.ascent));
return {x, y};
}();
painter.drawText(pos, text);
}
}
if (d->windowIconVisible) {
const QIcon icon = d->window->windowIcon();
if (!icon.isNull()) {
icon.paint(&painter, d->windowIconRect());
}
}
painter.restore();
event->accept();
}
bool StandardTitleBar::titleLabelVisible() const
{
Q_D(const StandardTitleBar);
return d->titleLabelVisible;
}
void StandardTitleBar::setTitleLabelVisible(const bool value)
{
Q_D(StandardTitleBar);
if (d->titleLabelVisible == value) {
return;
}
d->titleLabelVisible = value;
update();
Q_EMIT titleLabelVisibleChanged();
}
QSize StandardTitleBar::windowIconSize() const
{
Q_D(const StandardTitleBar);
return d->windowIconSize.value_or(kDefaultWindowIconSize);
}
void StandardTitleBar::setWindowIconSize(const QSize &value)
{
Q_ASSERT(!value.isEmpty());
if (value.isEmpty()) {
return;
}
if (windowIconSize() == value) {
return;
}
Q_D(StandardTitleBar);
d->windowIconSize = value;
update();
Q_EMIT windowIconSizeChanged();
}
bool StandardTitleBar::windowIconVisible() const
{
Q_D(const StandardTitleBar);
return d->windowIconVisible;
}
void StandardTitleBar::setWindowIconVisible(const bool value)
{
Q_D(StandardTitleBar);
if (d->windowIconVisible == value) {
return;
}
d->windowIconVisible = value;
update();
Q_EMIT windowIconVisibleChanged();
#ifndef Q_OS_MACOS
// Ideally we should use FramelessWidgetsHelper::get(this) everywhere, but sadly when
// we call it here, it may be too early that FramelessWidgetsHelper has not attached
// to the top level widget yet, and thus it will trigger an assert error (the assert
// should not be suppressed, because it usually indicates there's something really
// wrong). So here we have to use the top level widget directly, as a special case.
// NOTE: In your own code, you should always use FramelessWidgetsHelper::get(this)
// if possible.
FramelessWidgetsHelper::get(d->window)->setHitTestVisible(d->windowIconRect(), d->windowIconVisible_real());
#endif // Q_OS_MACOS
}
QFont StandardTitleBar::titleFont() const
{
Q_D(const StandardTitleBar);
return d->titleFont.value_or(QFont());
}
void StandardTitleBar::setTitleFont(const QFont &value)
{
if (titleFont() == value) {
return;
}
Q_D(StandardTitleBar);
d->titleFont = value;
update();
Q_EMIT titleFontChanged();
}
FRAMELESSHELPER_END_NAMESPACE