macOS: widgets: preserve the native title bar elements
Quick part to be done.
This commit is contained in:
parent
9e975e02e0
commit
819ffb79fb
|
@ -52,7 +52,9 @@ void Dialog::setupUi()
|
||||||
|
|
||||||
titleBar = new StandardTitleBar(this);
|
titleBar = new StandardTitleBar(this);
|
||||||
titleBar->setWindowIconVisible(true);
|
titleBar->setWindowIconVisible(true);
|
||||||
|
#ifndef Q_OS_MACOS
|
||||||
titleBar->maximizeButton()->hide();
|
titleBar->maximizeButton()->hide();
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
|
|
||||||
label = new QLabel(tr("Find &what:"));
|
label = new QLabel(tr("Find &what:"));
|
||||||
lineEdit = new QLineEdit;
|
lineEdit = new QLineEdit;
|
||||||
|
@ -124,9 +126,11 @@ void Dialog::setupUi()
|
||||||
|
|
||||||
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
|
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
|
||||||
helper->setTitleBarWidget(titleBar);
|
helper->setTitleBarWidget(titleBar);
|
||||||
|
#ifndef Q_OS_MACOS
|
||||||
helper->setSystemButton(titleBar->minimizeButton(), SystemButtonType::Minimize);
|
helper->setSystemButton(titleBar->minimizeButton(), SystemButtonType::Minimize);
|
||||||
helper->setSystemButton(titleBar->maximizeButton(), SystemButtonType::Maximize);
|
helper->setSystemButton(titleBar->maximizeButton(), SystemButtonType::Maximize);
|
||||||
helper->setSystemButton(titleBar->closeButton(), SystemButtonType::Close);
|
helper->setSystemButton(titleBar->closeButton(), SystemButtonType::Close);
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
// Special hack to disable the overriding of the mouse cursor, it's totally different
|
// Special hack to disable the overriding of the mouse cursor, it's totally different
|
||||||
// with making the window un-resizable: we still want the window be able to resize
|
// with making the window un-resizable: we still want the window be able to resize
|
||||||
// programatically, but we also want the user not able to resize the window manually.
|
// programatically, but we also want the user not able to resize the window manually.
|
||||||
|
|
|
@ -101,9 +101,11 @@ QMenuBar::item:pressed {
|
||||||
|
|
||||||
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
|
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
|
||||||
helper->setTitleBarWidget(m_titleBar);
|
helper->setTitleBarWidget(m_titleBar);
|
||||||
|
#ifndef Q_OS_MACOS
|
||||||
helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize);
|
helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize);
|
||||||
helper->setSystemButton(m_titleBar->maximizeButton(), SystemButtonType::Maximize);
|
helper->setSystemButton(m_titleBar->maximizeButton(), SystemButtonType::Maximize);
|
||||||
helper->setSystemButton(m_titleBar->closeButton(), SystemButtonType::Close);
|
helper->setSystemButton(m_titleBar->closeButton(), SystemButtonType::Close);
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
helper->setHitTestVisible(mb); // IMPORTANT!
|
helper->setHitTestVisible(mb); // IMPORTANT!
|
||||||
connect(helper, &FramelessWidgetsHelper::ready, this, [this, helper](){
|
connect(helper, &FramelessWidgetsHelper::ready, this, [this, helper](){
|
||||||
const auto savedGeometry = Settings::get<QRect>({}, kGeometry);
|
const auto savedGeometry = Settings::get<QRect>({}, kGeometry);
|
||||||
|
|
|
@ -77,9 +77,11 @@ void MainWindow::initialize()
|
||||||
|
|
||||||
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
|
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
|
||||||
helper->setTitleBarWidget(m_titleBar);
|
helper->setTitleBarWidget(m_titleBar);
|
||||||
|
#ifndef Q_OS_MACOS
|
||||||
helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize);
|
helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize);
|
||||||
helper->setSystemButton(m_titleBar->maximizeButton(), SystemButtonType::Maximize);
|
helper->setSystemButton(m_titleBar->maximizeButton(), SystemButtonType::Maximize);
|
||||||
helper->setSystemButton(m_titleBar->closeButton(), SystemButtonType::Close);
|
helper->setSystemButton(m_titleBar->closeButton(), SystemButtonType::Close);
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
connect(helper, &FramelessWidgetsHelper::ready, this, [this, helper](){
|
connect(helper, &FramelessWidgetsHelper::ready, this, [this, helper](){
|
||||||
const auto savedGeometry = Settings::get<QRect>({}, kGeometry);
|
const auto savedGeometry = Settings::get<QRect>({}, kGeometry);
|
||||||
if (savedGeometry.isValid() && !parent()) {
|
if (savedGeometry.isValid() && !parent()) {
|
||||||
|
|
|
@ -128,9 +128,11 @@ void Widget::initialize()
|
||||||
|
|
||||||
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
|
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
|
||||||
helper->setTitleBarWidget(m_titleBar);
|
helper->setTitleBarWidget(m_titleBar);
|
||||||
|
#ifndef Q_OS_MACOS
|
||||||
helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize);
|
helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize);
|
||||||
helper->setSystemButton(m_titleBar->maximizeButton(), SystemButtonType::Maximize);
|
helper->setSystemButton(m_titleBar->maximizeButton(), SystemButtonType::Maximize);
|
||||||
helper->setSystemButton(m_titleBar->closeButton(), SystemButtonType::Close);
|
helper->setSystemButton(m_titleBar->closeButton(), SystemButtonType::Close);
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
connect(helper, &FramelessWidgetsHelper::ready, this, [this, helper](){
|
connect(helper, &FramelessWidgetsHelper::ready, this, [this, helper](){
|
||||||
const QString objName = objectName();
|
const QString objName = objectName();
|
||||||
const auto savedGeometry = Settings::get<QRect>(objName, kGeometry);
|
const auto savedGeometry = Settings::get<QRect>(objName, kGeometry);
|
||||||
|
|
|
@ -206,6 +206,7 @@ Q_NAMESPACE_EXPORT(FRAMELESSHELPER_CORE_API)
|
||||||
[[maybe_unused]] inline constexpr const int kDefaultWindowFrameBorderThickness = 1;
|
[[maybe_unused]] inline constexpr const int kDefaultWindowFrameBorderThickness = 1;
|
||||||
[[maybe_unused]] inline constexpr const int kDefaultTitleBarFontPointSize = 11;
|
[[maybe_unused]] inline constexpr const int kDefaultTitleBarFontPointSize = 11;
|
||||||
[[maybe_unused]] inline constexpr const int kDefaultTitleBarContentsMargin = 10;
|
[[maybe_unused]] inline constexpr const int kDefaultTitleBarContentsMargin = 10;
|
||||||
|
[[maybe_unused]] inline constexpr const int kMacOSChromeButtonAreaWidth = 60;
|
||||||
[[maybe_unused]] inline constexpr const QSize kDefaultWindowIconSize = {16, 16};
|
[[maybe_unused]] inline constexpr const QSize kDefaultWindowIconSize = {16, 16};
|
||||||
// We have to use "qRound()" here because "std::round()" is not constexpr, yet.
|
// We have to use "qRound()" here because "std::round()" is not constexpr, yet.
|
||||||
[[maybe_unused]] inline constexpr const QSize kDefaultSystemButtonSize = {qRound(qreal(kDefaultTitleBarHeight) * 1.5), kDefaultTitleBarHeight};
|
[[maybe_unused]] inline constexpr const QSize kDefaultSystemButtonSize = {qRound(qreal(kDefaultTitleBarHeight) * 1.5), kDefaultTitleBarHeight};
|
||||||
|
|
|
@ -25,9 +25,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "framelesshelperwidgets_global.h"
|
#include "framelesshelperwidgets_global.h"
|
||||||
|
#include <QtGui/qfont.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QPaintEvent;
|
class QPaintEvent;
|
||||||
|
class QMouseEvent;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
@ -43,6 +45,13 @@ class FRAMELESSHELPER_WIDGETS_API StandardTitleBarPrivate : public QObject
|
||||||
Q_DISABLE_COPY_MOVE(StandardTitleBarPrivate)
|
Q_DISABLE_COPY_MOVE(StandardTitleBarPrivate)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
struct FontMetrics
|
||||||
|
{
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
int baseline = 0;
|
||||||
|
};
|
||||||
|
|
||||||
explicit StandardTitleBarPrivate(StandardTitleBar *q);
|
explicit StandardTitleBarPrivate(StandardTitleBar *q);
|
||||||
~StandardTitleBarPrivate() override;
|
~StandardTitleBarPrivate() override;
|
||||||
|
|
||||||
|
@ -80,6 +89,9 @@ public:
|
||||||
Q_NODISCARD bool windowIconVisible_real() const;
|
Q_NODISCARD bool windowIconVisible_real() const;
|
||||||
Q_NODISCARD bool isInTitleBarIconArea(const QPoint &pos) const;
|
Q_NODISCARD bool isInTitleBarIconArea(const QPoint &pos) const;
|
||||||
|
|
||||||
|
Q_NODISCARD QFont defaultFont() const;
|
||||||
|
Q_NODISCARD FontMetrics titleLabelSize() const;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void updateMaximizeButton();
|
void updateMaximizeButton();
|
||||||
void updateTitleBarColor();
|
void updateTitleBarColor();
|
||||||
|
@ -94,9 +106,11 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StandardTitleBar *q_ptr = nullptr;
|
StandardTitleBar *q_ptr = nullptr;
|
||||||
|
#ifndef Q_OS_MACOS
|
||||||
StandardSystemButton *m_minimizeButton = nullptr;
|
StandardSystemButton *m_minimizeButton = nullptr;
|
||||||
StandardSystemButton *m_maximizeButton = nullptr;
|
StandardSystemButton *m_maximizeButton = nullptr;
|
||||||
StandardSystemButton *m_closeButton = nullptr;
|
StandardSystemButton *m_closeButton = nullptr;
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
QPointer<QWidget> m_window = nullptr;
|
QPointer<QWidget> m_window = nullptr;
|
||||||
bool m_extended = false;
|
bool m_extended = false;
|
||||||
Qt::Alignment m_labelAlignment = {};
|
Qt::Alignment m_labelAlignment = {};
|
||||||
|
|
|
@ -41,9 +41,11 @@ class FRAMELESSHELPER_WIDGETS_API StandardTitleBar : public QWidget
|
||||||
Q_DECLARE_PRIVATE(StandardTitleBar)
|
Q_DECLARE_PRIVATE(StandardTitleBar)
|
||||||
Q_DISABLE_COPY_MOVE(StandardTitleBar)
|
Q_DISABLE_COPY_MOVE(StandardTitleBar)
|
||||||
Q_PROPERTY(Qt::Alignment titleLabelAlignment READ titleLabelAlignment WRITE setTitleLabelAlignment NOTIFY titleLabelAlignmentChanged FINAL)
|
Q_PROPERTY(Qt::Alignment titleLabelAlignment READ titleLabelAlignment WRITE setTitleLabelAlignment NOTIFY titleLabelAlignmentChanged FINAL)
|
||||||
|
#ifndef Q_OS_MACOS
|
||||||
Q_PROPERTY(StandardSystemButton* minimizeButton READ minimizeButton CONSTANT FINAL)
|
Q_PROPERTY(StandardSystemButton* minimizeButton READ minimizeButton CONSTANT FINAL)
|
||||||
Q_PROPERTY(StandardSystemButton* maximizeButton READ maximizeButton CONSTANT FINAL)
|
Q_PROPERTY(StandardSystemButton* maximizeButton READ maximizeButton CONSTANT FINAL)
|
||||||
Q_PROPERTY(StandardSystemButton* closeButton READ closeButton CONSTANT FINAL)
|
Q_PROPERTY(StandardSystemButton* closeButton READ closeButton CONSTANT FINAL)
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
Q_PROPERTY(bool extended READ isExtended WRITE setExtended NOTIFY extendedChanged FINAL)
|
Q_PROPERTY(bool extended READ isExtended WRITE setExtended NOTIFY extendedChanged FINAL)
|
||||||
Q_PROPERTY(bool hideWhenClose READ isHideWhenClose WRITE setHideWhenClose NOTIFY hideWhenCloseChanged FINAL)
|
Q_PROPERTY(bool hideWhenClose READ isHideWhenClose WRITE setHideWhenClose NOTIFY hideWhenCloseChanged FINAL)
|
||||||
Q_PROPERTY(ChromePalette* chromePalette READ chromePalette CONSTANT FINAL)
|
Q_PROPERTY(ChromePalette* chromePalette READ chromePalette CONSTANT FINAL)
|
||||||
|
@ -59,9 +61,11 @@ public:
|
||||||
Q_NODISCARD Qt::Alignment titleLabelAlignment() const;
|
Q_NODISCARD Qt::Alignment titleLabelAlignment() const;
|
||||||
void setTitleLabelAlignment(const Qt::Alignment value);
|
void setTitleLabelAlignment(const Qt::Alignment value);
|
||||||
|
|
||||||
|
#ifndef Q_OS_MACOS
|
||||||
Q_NODISCARD StandardSystemButton *minimizeButton() const;
|
Q_NODISCARD StandardSystemButton *minimizeButton() const;
|
||||||
Q_NODISCARD StandardSystemButton *maximizeButton() const;
|
Q_NODISCARD StandardSystemButton *maximizeButton() const;
|
||||||
Q_NODISCARD StandardSystemButton *closeButton() const;
|
Q_NODISCARD StandardSystemButton *closeButton() const;
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
|
|
||||||
Q_NODISCARD bool isExtended() const;
|
Q_NODISCARD bool isExtended() const;
|
||||||
void setExtended(const bool value);
|
void setExtended(const bool value);
|
||||||
|
|
|
@ -88,15 +88,12 @@ void FramelessHelperQt::addWindow(const SystemParameters ¶ms)
|
||||||
data.eventFilter = new FramelessHelperQt(window);
|
data.eventFilter = new FramelessHelperQt(window);
|
||||||
g_qtHelper()->data.insert(windowId, data);
|
g_qtHelper()->data.insert(windowId, data);
|
||||||
g_qtHelper()->mutex.unlock();
|
g_qtHelper()->mutex.unlock();
|
||||||
const auto shouldApplyFramelessFlag = [¶ms]() -> bool {
|
const auto shouldApplyFramelessFlag = []() -> bool {
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
const auto widget = params.getWidgetHandle();
|
return false;
|
||||||
return (widget && widget->isWidgetType());
|
|
||||||
#elif defined(Q_OS_LINUX)
|
#elif defined(Q_OS_LINUX)
|
||||||
Q_UNUSED(params);
|
|
||||||
return !Utils::isCustomDecorationSupported();
|
return !Utils::isCustomDecorationSupported();
|
||||||
#else // Windows
|
#else // Windows
|
||||||
Q_UNUSED(params);
|
|
||||||
return true;
|
return true;
|
||||||
#endif // Q_OS_MACOS
|
#endif // Q_OS_MACOS
|
||||||
}();
|
}();
|
||||||
|
|
|
@ -197,10 +197,6 @@ void initialize()
|
||||||
Utils::fixupDialogsDpiScaling();
|
Utils::fixupDialogsDpiScaling();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This attribute is known to be __NOT__ compatible with QGLWidget.
|
|
||||||
// Please consider migrating to the recommended QOpenGLWidget instead.
|
|
||||||
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
|
||||||
|
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
// Enable high DPI scaling by default, but only for Qt5 applications,
|
// Enable high DPI scaling by default, but only for Qt5 applications,
|
||||||
// because this has become the default setting since Qt6 and it can't
|
// because this has become the default setting since Qt6 and it can't
|
||||||
|
|
|
@ -292,6 +292,7 @@ public Q_SLOTS:
|
||||||
oldSetTitlebarAppearsTransparent = reinterpret_cast<setTitlebarAppearsTransparentPtr>(method_setImplementation(method, reinterpret_cast<IMP>(setTitlebarAppearsTransparent)));
|
oldSetTitlebarAppearsTransparent = reinterpret_cast<setTitlebarAppearsTransparentPtr>(method_setImplementation(method, reinterpret_cast<IMP>(setTitlebarAppearsTransparent)));
|
||||||
Q_ASSERT(oldSetTitlebarAppearsTransparent);
|
Q_ASSERT(oldSetTitlebarAppearsTransparent);
|
||||||
|
|
||||||
|
#if 0
|
||||||
method = class_getInstanceMethod(windowClass, @selector(canBecomeKeyWindow));
|
method = class_getInstanceMethod(windowClass, @selector(canBecomeKeyWindow));
|
||||||
Q_ASSERT(method);
|
Q_ASSERT(method);
|
||||||
oldCanBecomeKeyWindow = reinterpret_cast<canBecomeKeyWindowPtr>(method_setImplementation(method, reinterpret_cast<IMP>(canBecomeKeyWindow)));
|
oldCanBecomeKeyWindow = reinterpret_cast<canBecomeKeyWindowPtr>(method_setImplementation(method, reinterpret_cast<IMP>(canBecomeKeyWindow)));
|
||||||
|
@ -301,6 +302,7 @@ public Q_SLOTS:
|
||||||
Q_ASSERT(method);
|
Q_ASSERT(method);
|
||||||
oldCanBecomeMainWindow = reinterpret_cast<canBecomeMainWindowPtr>(method_setImplementation(method, reinterpret_cast<IMP>(canBecomeMainWindow)));
|
oldCanBecomeMainWindow = reinterpret_cast<canBecomeMainWindowPtr>(method_setImplementation(method, reinterpret_cast<IMP>(canBecomeMainWindow)));
|
||||||
Q_ASSERT(oldCanBecomeMainWindow);
|
Q_ASSERT(oldCanBecomeMainWindow);
|
||||||
|
#endif
|
||||||
|
|
||||||
method = class_getInstanceMethod(windowClass, @selector(sendEvent:));
|
method = class_getInstanceMethod(windowClass, @selector(sendEvent:));
|
||||||
Q_ASSERT(method);
|
Q_ASSERT(method);
|
||||||
|
@ -320,6 +322,7 @@ public Q_SLOTS:
|
||||||
method_setImplementation(method, reinterpret_cast<IMP>(oldSetTitlebarAppearsTransparent));
|
method_setImplementation(method, reinterpret_cast<IMP>(oldSetTitlebarAppearsTransparent));
|
||||||
oldSetTitlebarAppearsTransparent = nil;
|
oldSetTitlebarAppearsTransparent = nil;
|
||||||
|
|
||||||
|
#if 0
|
||||||
method = class_getInstanceMethod(windowClass, @selector(canBecomeKeyWindow));
|
method = class_getInstanceMethod(windowClass, @selector(canBecomeKeyWindow));
|
||||||
Q_ASSERT(method);
|
Q_ASSERT(method);
|
||||||
method_setImplementation(method, reinterpret_cast<IMP>(oldCanBecomeKeyWindow));
|
method_setImplementation(method, reinterpret_cast<IMP>(oldCanBecomeKeyWindow));
|
||||||
|
@ -329,6 +332,7 @@ public Q_SLOTS:
|
||||||
Q_ASSERT(method);
|
Q_ASSERT(method);
|
||||||
method_setImplementation(method, reinterpret_cast<IMP>(oldCanBecomeMainWindow));
|
method_setImplementation(method, reinterpret_cast<IMP>(oldCanBecomeMainWindow));
|
||||||
oldCanBecomeMainWindow = nil;
|
oldCanBecomeMainWindow = nil;
|
||||||
|
#endif
|
||||||
|
|
||||||
method = class_getInstanceMethod(windowClass, @selector(sendEvent:));
|
method = class_getInstanceMethod(windowClass, @selector(sendEvent:));
|
||||||
Q_ASSERT(method);
|
Q_ASSERT(method);
|
||||||
|
@ -487,6 +491,7 @@ private:
|
||||||
oldSendEvent(obj, sel, event);
|
oldSendEvent(obj, sel, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
const auto nswindow = reinterpret_cast<NSWindow *>(obj);
|
const auto nswindow = reinterpret_cast<NSWindow *>(obj);
|
||||||
if (!instances.contains(nswindow)) {
|
if (!instances.contains(nswindow)) {
|
||||||
return;
|
return;
|
||||||
|
@ -498,12 +503,13 @@ private:
|
||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
proxy->lastMouseDownEvent = nil;
|
proxy->lastMouseDownEvent = nil;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWindow *qwindow = nil;
|
QWindow *qwindow = nil;
|
||||||
NSWindow *nswindow = nil;
|
NSWindow *nswindow = nil;
|
||||||
NSEvent *lastMouseDownEvent = nil;
|
//NSEvent *lastMouseDownEvent = nil;
|
||||||
NSView *blurEffect = nil;
|
NSView *blurEffect = nil;
|
||||||
|
|
||||||
NSWindowStyleMask oldStyleMask = 0;
|
NSWindowStyleMask oldStyleMask = 0;
|
||||||
|
|
|
@ -79,12 +79,6 @@ const FramelessDialogPrivate *FramelessDialogPrivate::get(const FramelessDialog
|
||||||
void FramelessDialogPrivate::initialize()
|
void FramelessDialogPrivate::initialize()
|
||||||
{
|
{
|
||||||
Q_Q(FramelessDialog);
|
Q_Q(FramelessDialog);
|
||||||
// Without this flag, Qt will always create an invisible native parent window
|
|
||||||
// for any native widgets which will intercept some win32 messages and confuse
|
|
||||||
// our own native event filter, so to prevent some weired bugs from happening,
|
|
||||||
// just disable this feature.
|
|
||||||
q->setAttribute(Qt::WA_DontCreateNativeAncestors);
|
|
||||||
q->setAttribute(Qt::WA_NativeWindow);
|
|
||||||
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
|
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
|
||||||
m_sharedHelper = new WidgetsSharedHelper(this);
|
m_sharedHelper = new WidgetsSharedHelper(this);
|
||||||
m_sharedHelper->setup(q);
|
m_sharedHelper->setup(q);
|
||||||
|
|
|
@ -79,12 +79,6 @@ const FramelessMainWindowPrivate *FramelessMainWindowPrivate::get(const Frameles
|
||||||
void FramelessMainWindowPrivate::initialize()
|
void FramelessMainWindowPrivate::initialize()
|
||||||
{
|
{
|
||||||
Q_Q(FramelessMainWindow);
|
Q_Q(FramelessMainWindow);
|
||||||
// Without this flag, Qt will always create an invisible native parent window
|
|
||||||
// for any native widgets which will intercept some win32 messages and confuse
|
|
||||||
// our own native event filter, so to prevent some weired bugs from happening,
|
|
||||||
// just disable this feature.
|
|
||||||
q->setAttribute(Qt::WA_DontCreateNativeAncestors);
|
|
||||||
q->setAttribute(Qt::WA_NativeWindow);
|
|
||||||
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
|
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
|
||||||
m_sharedHelper = new WidgetsSharedHelper(this);
|
m_sharedHelper = new WidgetsSharedHelper(this);
|
||||||
m_sharedHelper->setup(q);
|
m_sharedHelper->setup(q);
|
||||||
|
|
|
@ -79,12 +79,6 @@ const FramelessWidgetPrivate *FramelessWidgetPrivate::get(const FramelessWidget
|
||||||
void FramelessWidgetPrivate::initialize()
|
void FramelessWidgetPrivate::initialize()
|
||||||
{
|
{
|
||||||
Q_Q(FramelessWidget);
|
Q_Q(FramelessWidget);
|
||||||
// Without this flag, Qt will always create an invisible native parent window
|
|
||||||
// for any native widgets which will intercept some win32 messages and confuse
|
|
||||||
// our own native event filter, so to prevent some weired bugs from happening,
|
|
||||||
// just disable this feature.
|
|
||||||
q->setAttribute(Qt::WA_DontCreateNativeAncestors);
|
|
||||||
q->setAttribute(Qt::WA_NativeWindow);
|
|
||||||
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
|
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
|
||||||
m_sharedHelper = new WidgetsSharedHelper(this);
|
m_sharedHelper = new WidgetsSharedHelper(this);
|
||||||
m_sharedHelper->setup(q);
|
m_sharedHelper->setup(q);
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <QtCore/qtimer.h>
|
#include <QtCore/qtimer.h>
|
||||||
#include <QtGui/qpainter.h>
|
#include <QtGui/qpainter.h>
|
||||||
#include <QtGui/qevent.h>
|
#include <QtGui/qevent.h>
|
||||||
|
#include <QtGui/qfontmetrics.h>
|
||||||
#include <QtWidgets/qboxlayout.h>
|
#include <QtWidgets/qboxlayout.h>
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
@ -132,6 +133,32 @@ ChromePalette *StandardTitleBarPrivate::chromePalette() const
|
||||||
return m_chromePalette;
|
return m_chromePalette;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QFont StandardTitleBarPrivate::defaultFont() const
|
||||||
|
{
|
||||||
|
Q_Q(const StandardTitleBar);
|
||||||
|
QFont font = q->font();
|
||||||
|
font.setPointSize(kDefaultTitleBarFontPointSize);
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardTitleBarPrivate::FontMetrics StandardTitleBarPrivate::titleLabelSize() const
|
||||||
|
{
|
||||||
|
if (!m_window) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const QString text = m_window->windowTitle();
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const QFont font = m_titleFont.value_or(defaultFont());
|
||||||
|
const QFontMetrics fontMetrics(font);
|
||||||
|
return {
|
||||||
|
fontMetrics.horizontalAdvance(text),
|
||||||
|
fontMetrics.height(),
|
||||||
|
fontMetrics.ascent()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void StandardTitleBarPrivate::paintTitleBar(QPaintEvent *event)
|
void StandardTitleBarPrivate::paintTitleBar(QPaintEvent *event)
|
||||||
{
|
{
|
||||||
Q_ASSERT(event);
|
Q_ASSERT(event);
|
||||||
|
@ -154,41 +181,35 @@ void StandardTitleBarPrivate::paintTitleBar(QPaintEvent *event)
|
||||||
painter.setRenderHints(QPainter::Antialiasing |
|
painter.setRenderHints(QPainter::Antialiasing |
|
||||||
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
||||||
painter.fillRect(QRect(QPoint(0, 0), q->size()), backgroundColor);
|
painter.fillRect(QRect(QPoint(0, 0), q->size()), backgroundColor);
|
||||||
int titleLabelLeftOffset = 0;
|
|
||||||
if (m_windowIconVisible) {
|
if (m_windowIconVisible) {
|
||||||
const QIcon icon = m_window->windowIcon();
|
const QIcon icon = m_window->windowIcon();
|
||||||
if (!icon.isNull()) {
|
if (!icon.isNull()) {
|
||||||
const QRect rect = windowIconRect();
|
icon.paint(&painter, windowIconRect());
|
||||||
titleLabelLeftOffset = (rect.left() + rect.width());
|
|
||||||
icon.paint(&painter, rect);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_titleLabelVisible) {
|
if (m_titleLabelVisible) {
|
||||||
const QString text = m_window->windowTitle();
|
const QString text = m_window->windowTitle();
|
||||||
if (!text.isEmpty()) {
|
if (!text.isEmpty()) {
|
||||||
painter.setPen(foregroundColor);
|
painter.setPen(foregroundColor);
|
||||||
painter.setFont(m_titleFont.value_or([q]() -> QFont {
|
painter.setFont(m_titleFont.value_or(defaultFont()));
|
||||||
QFont f = q->font();
|
const auto pos = [this, q]() -> QPoint {
|
||||||
f.setPointSize(kDefaultTitleBarFontPointSize);
|
const FontMetrics labelSize = titleLabelSize();
|
||||||
return f;
|
const int titleBarWidth = q->width();
|
||||||
}()));
|
int x = 0;
|
||||||
const auto rect = [this, q, titleLabelLeftOffset]() -> QRect {
|
|
||||||
const int w = q->width();
|
|
||||||
int leftMargin = 0;
|
|
||||||
int rightMargin = 0;
|
|
||||||
if (m_labelAlignment & Qt::AlignLeft) {
|
if (m_labelAlignment & Qt::AlignLeft) {
|
||||||
leftMargin = (kDefaultTitleBarContentsMargin + titleLabelLeftOffset);
|
x = (windowIconRect().right() + kDefaultTitleBarContentsMargin);
|
||||||
|
} else if (m_labelAlignment & Qt::AlignRight) {
|
||||||
|
x = (titleBarWidth - kDefaultTitleBarContentsMargin - labelSize.width);
|
||||||
|
#ifndef Q_OS_MACOS
|
||||||
|
x -= m_minimizeButton->x();
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
|
} else {
|
||||||
|
x = std::round(qreal(titleBarWidth - labelSize.width) / qreal(2));
|
||||||
}
|
}
|
||||||
if (m_labelAlignment & Qt::AlignRight) {
|
const int y = std::round((qreal(q->height() - labelSize.height) / qreal(2)) + qreal(labelSize.baseline));
|
||||||
rightMargin = (w - m_minimizeButton->x() + kDefaultTitleBarContentsMargin);
|
return {x, y};
|
||||||
}
|
|
||||||
const int x = leftMargin;
|
|
||||||
const int y = 0;
|
|
||||||
const int width = (w - leftMargin - rightMargin);
|
|
||||||
const int height = q->height();
|
|
||||||
return {QPoint(x, y), QSize(width, height)};
|
|
||||||
}();
|
}();
|
||||||
painter.drawText(rect, int(m_labelAlignment), text);
|
painter.drawText(pos, text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
painter.restore();
|
painter.restore();
|
||||||
|
@ -242,6 +263,10 @@ void StandardTitleBarPrivate::setWindowIconVisible(const bool value)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_windowIconVisible = value;
|
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
|
// 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
|
// 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
|
// to the top level widget yet, and thus it will trigger an assert error (the assert
|
||||||
|
@ -250,9 +275,7 @@ void StandardTitleBarPrivate::setWindowIconVisible(const bool value)
|
||||||
// NOTE: In your own code, you should always use FramelessWidgetsHelper::get(this)
|
// NOTE: In your own code, you should always use FramelessWidgetsHelper::get(this)
|
||||||
// if possible.
|
// if possible.
|
||||||
FramelessWidgetsHelper::get(m_window)->setHitTestVisible(windowIconRect(), windowIconVisible_real());
|
FramelessWidgetsHelper::get(m_window)->setHitTestVisible(windowIconRect(), windowIconVisible_real());
|
||||||
Q_Q(StandardTitleBar);
|
#endif // Q_OS_MACOS
|
||||||
q->update();
|
|
||||||
Q_EMIT q->windowIconVisibleChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QFont StandardTitleBarPrivate::titleFont() const
|
QFont StandardTitleBarPrivate::titleFont() const
|
||||||
|
@ -273,17 +296,21 @@ void StandardTitleBarPrivate::setTitleFont(const QFont &value)
|
||||||
|
|
||||||
bool StandardTitleBarPrivate::mouseEventHandler(QMouseEvent *event)
|
bool StandardTitleBarPrivate::mouseEventHandler(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
Q_UNUSED(event);
|
||||||
|
return false;
|
||||||
|
#else // !Q_OS_MACOS
|
||||||
Q_ASSERT(event);
|
Q_ASSERT(event);
|
||||||
if (!event) {
|
if (!event) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Q_Q(const StandardTitleBar);
|
Q_Q(const StandardTitleBar);
|
||||||
const Qt::MouseButton button = event->button();
|
const Qt::MouseButton button = event->button();
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
const QPoint scenePos = event->scenePosition().toPoint();
|
const QPoint scenePos = event->scenePosition().toPoint();
|
||||||
#else
|
# else // (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
const QPoint scenePos = event->windowPos().toPoint();
|
const QPoint scenePos = event->windowPos().toPoint();
|
||||||
#endif
|
# endif // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
const bool interestArea = isInTitleBarIconArea(scenePos);
|
const bool interestArea = isInTitleBarIconArea(scenePos);
|
||||||
switch (event->type()) {
|
switch (event->type()) {
|
||||||
case QEvent::MouseButtonRelease:
|
case QEvent::MouseButtonRelease:
|
||||||
|
@ -336,14 +363,31 @@ bool StandardTitleBarPrivate::mouseEventHandler(QMouseEvent *event)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect StandardTitleBarPrivate::windowIconRect() const
|
QRect StandardTitleBarPrivate::windowIconRect() const
|
||||||
{
|
{
|
||||||
Q_Q(const StandardTitleBar);
|
Q_Q(const StandardTitleBar);
|
||||||
const QSize size = windowIconSize();
|
const QSize size = windowIconSize();
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
const auto x = [this, q, &size]() -> int {
|
||||||
|
if (m_labelAlignment & Qt::AlignLeft) {
|
||||||
|
return (kMacOSChromeButtonAreaWidth + kDefaultTitleBarContentsMargin);
|
||||||
|
}
|
||||||
|
const int titleBarWidth = q->width();
|
||||||
|
const int labelWidth = titleLabelSize().width;
|
||||||
|
if (m_labelAlignment & Qt::AlignRight) {
|
||||||
|
return (titleBarWidth - labelWidth - kDefaultTitleBarContentsMargin - size.width());
|
||||||
|
}
|
||||||
|
const int centeredX = std::round(qreal(titleBarWidth - labelWidth) / qreal(2));
|
||||||
|
return (centeredX - kDefaultTitleBarContentsMargin - size.width());
|
||||||
|
}();
|
||||||
|
#else // !Q_OS_MACOS
|
||||||
|
const int x = kDefaultTitleBarContentsMargin;
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
const int y = std::round(qreal(q->height() - size.height()) / qreal(2));
|
const int y = std::round(qreal(q->height() - size.height()) / qreal(2));
|
||||||
return {QPoint(kDefaultTitleBarContentsMargin, y), size};
|
return {QPoint(x, y), size};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StandardTitleBarPrivate::windowIconVisible_real() const
|
bool StandardTitleBarPrivate::windowIconVisible_real() const
|
||||||
|
@ -361,9 +405,11 @@ bool StandardTitleBarPrivate::isInTitleBarIconArea(const QPoint &pos) const
|
||||||
|
|
||||||
void StandardTitleBarPrivate::updateMaximizeButton()
|
void StandardTitleBarPrivate::updateMaximizeButton()
|
||||||
{
|
{
|
||||||
|
#ifndef Q_OS_MACOS
|
||||||
const bool max = m_window->isMaximized();
|
const bool max = m_window->isMaximized();
|
||||||
m_maximizeButton->setButtonType(max ? SystemButtonType::Restore : SystemButtonType::Maximize);
|
m_maximizeButton->setButtonType(max ? SystemButtonType::Restore : SystemButtonType::Maximize);
|
||||||
m_maximizeButton->setToolTip(max ? tr("Restore") : tr("Maximize"));
|
m_maximizeButton->setToolTip(max ? tr("Restore") : tr("Maximize"));
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
}
|
}
|
||||||
|
|
||||||
void StandardTitleBarPrivate::updateTitleBarColor()
|
void StandardTitleBarPrivate::updateTitleBarColor()
|
||||||
|
@ -374,6 +420,7 @@ void StandardTitleBarPrivate::updateTitleBarColor()
|
||||||
|
|
||||||
void StandardTitleBarPrivate::updateChromeButtonColor()
|
void StandardTitleBarPrivate::updateChromeButtonColor()
|
||||||
{
|
{
|
||||||
|
#ifndef Q_OS_MACOS
|
||||||
const bool active = m_window->isActiveWindow();
|
const bool active = m_window->isActiveWindow();
|
||||||
const QColor activeForeground = m_chromePalette->titleBarActiveForegroundColor();
|
const QColor activeForeground = m_chromePalette->titleBarActiveForegroundColor();
|
||||||
const QColor inactiveForeground = m_chromePalette->titleBarInactiveForegroundColor();
|
const QColor inactiveForeground = m_chromePalette->titleBarInactiveForegroundColor();
|
||||||
|
@ -398,13 +445,16 @@ void StandardTitleBarPrivate::updateChromeButtonColor()
|
||||||
m_closeButton->setHoverColor(m_chromePalette->closeButtonHoverColor());
|
m_closeButton->setHoverColor(m_chromePalette->closeButtonHoverColor());
|
||||||
m_closeButton->setPressColor(m_chromePalette->closeButtonPressColor());
|
m_closeButton->setPressColor(m_chromePalette->closeButtonPressColor());
|
||||||
m_closeButton->setActive(active);
|
m_closeButton->setActive(active);
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
}
|
}
|
||||||
|
|
||||||
void StandardTitleBarPrivate::retranslateUi()
|
void StandardTitleBarPrivate::retranslateUi()
|
||||||
{
|
{
|
||||||
|
#ifndef Q_OS_MACOS
|
||||||
m_minimizeButton->setToolTip(tr("Minimize"));
|
m_minimizeButton->setToolTip(tr("Minimize"));
|
||||||
m_maximizeButton->setToolTip(m_window->isMaximized() ? tr("Restore") : tr("Maximize"));
|
m_maximizeButton->setToolTip(m_window->isMaximized() ? tr("Restore") : tr("Maximize"));
|
||||||
m_closeButton->setToolTip(tr("Close"));
|
m_closeButton->setToolTip(tr("Close"));
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StandardTitleBarPrivate::eventFilter(QObject *object, QEvent *event)
|
bool StandardTitleBarPrivate::eventFilter(QObject *object, QEvent *event)
|
||||||
|
@ -457,6 +507,13 @@ void StandardTitleBarPrivate::initialize()
|
||||||
Q_UNUSED(title);
|
Q_UNUSED(title);
|
||||||
q->update();
|
q->update();
|
||||||
});
|
});
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
const auto titleBarLayout = new QHBoxLayout(q);
|
||||||
|
titleBarLayout->setSpacing(0);
|
||||||
|
titleBarLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
q->setLayout(titleBarLayout);
|
||||||
|
setTitleLabelAlignment(Qt::AlignCenter);
|
||||||
|
#else // !Q_OS_MACOS
|
||||||
m_minimizeButton = new StandardSystemButton(SystemButtonType::Minimize, q);
|
m_minimizeButton = new StandardSystemButton(SystemButtonType::Minimize, q);
|
||||||
connect(m_minimizeButton, &StandardSystemButton::clicked, m_window, &QWidget::showMinimized);
|
connect(m_minimizeButton, &StandardSystemButton::clicked, m_window, &QWidget::showMinimized);
|
||||||
m_maximizeButton = new StandardSystemButton(SystemButtonType::Maximize, q);
|
m_maximizeButton = new StandardSystemButton(SystemButtonType::Maximize, q);
|
||||||
|
@ -497,6 +554,7 @@ void StandardTitleBarPrivate::initialize()
|
||||||
titleBarLayout->addLayout(systemButtonsOuterLayout);
|
titleBarLayout->addLayout(systemButtonsOuterLayout);
|
||||||
q->setLayout(titleBarLayout);
|
q->setLayout(titleBarLayout);
|
||||||
setTitleLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
setTitleLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
retranslateUi();
|
retranslateUi();
|
||||||
updateTitleBarColor();
|
updateTitleBarColor();
|
||||||
updateChromeButtonColor();
|
updateChromeButtonColor();
|
||||||
|
@ -522,6 +580,7 @@ void StandardTitleBar::setTitleLabelAlignment(const Qt::Alignment value)
|
||||||
d->setTitleLabelAlignment(value);
|
d->setTitleLabelAlignment(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef Q_OS_MACOS
|
||||||
StandardSystemButton *StandardTitleBar::minimizeButton() const
|
StandardSystemButton *StandardTitleBar::minimizeButton() const
|
||||||
{
|
{
|
||||||
Q_D(const StandardTitleBar);
|
Q_D(const StandardTitleBar);
|
||||||
|
@ -539,6 +598,7 @@ StandardSystemButton *StandardTitleBar::closeButton() const
|
||||||
Q_D(const StandardTitleBar);
|
Q_D(const StandardTitleBar);
|
||||||
return d->m_closeButton;
|
return d->m_closeButton;
|
||||||
}
|
}
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
|
|
||||||
bool StandardTitleBar::isExtended() const
|
bool StandardTitleBar::isExtended() const
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue