/* This file is part of KDDockWidgets. SPDX-FileCopyrightText: 2019 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Sérgio Martins SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only Contact KDAB at for commercial licensing options. */ #include "TitleBar.h" #include "core/TitleBar.h" #include "core/FloatingWindow.h" #include "core/Window_p.h" #include "core/Utils_p.h" #include "core/View_p.h" #include "core/Logging_p.h" #include "core/TitleBar_p.h" #include "core/DockRegistry_p.h" #include "qtwidgets/ViewFactory.h" #include #include #include #include #include #include #include using namespace KDDockWidgets; using namespace KDDockWidgets::QtWidgets; Button::~Button() { } void Button::paintEvent(QPaintEvent *) { QPainter p(this); QStyleOptionToolButton opt; opt.initFrom(this); if (isEnabled() && underMouse()) { if (isDown()) { opt.state |= QStyle::State_Sunken; } else { opt.state |= QStyle::State_Raised; } style()->drawPrimitive(QStyle::PE_PanelButtonTool, &opt, &p, this); } opt.subControls = QStyle::SC_None; opt.features = QStyleOptionToolButton::None; opt.icon = icon(); opt.iconSize = iconSize(); // The first icon size is for scaling 1x, and is what QStyle expects. QStyle will pick ones // with higher resolution automatically when needed. const QList iconSizes = opt.icon.availableSizes(); if (!iconSizes.isEmpty()) { opt.iconSize = iconSizes.constFirst(); const qreal logicalFactor = logicalDpiX() / 96.0; // On Linux there's dozens of window managers and ways of setting the scaling. // Some window managers will just change the font dpi (which affects logical dpi), while // others will only change the device pixel ratio. Take care of both cases. // macOS is easier, as it never changes logical DPI. // On Windows, with AA_EnableHighDpiScaling, logical DPI is always 96 and physical is // manipulated instead. #if defined(Q_OS_LINUX) const qreal dpr = devicePixelRatioF(); const qreal combinedFactor = logicalFactor * dpr; if (scalingFactorIsSupported(combinedFactor)) // Older Qt has rendering bugs with fractional // factors opt.iconSize = opt.iconSize * combinedFactor; #elif defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // Probably Windows could use the same code path as Linux, but I'm seeing too thick icons on // Windows... if (!QGuiApplication::testAttribute(Qt::AA_EnableHighDpiScaling) && scalingFactorIsSupported(logicalFactor)) // Older Qt has rendering bugs with // fractional factors opt.iconSize = opt.iconSize * logicalFactor; #else Q_UNUSED(logicalFactor); #endif } style()->drawComplexControl(QStyle::CC_ToolButton, &opt, &p, this); } QSize Button::sizeHint() const { const int h = 24; return QSize(h, h); } bool Button::event(QEvent *ev) { switch (ev->type()) { case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::KeyPress: case QEvent::KeyRelease: { // A Button can trigger the deletion of its parent, in which case we use deleteLater m_inEventHandler = true; QPointer guard = this; const bool result = QToolButton::event(ev); if (guard) // Button press can trigger deletion of Button m_inEventHandler = false; return result; } default: break; } return QToolButton::event(ev); } class KDDockWidgets::QtWidgets::TitleBar::Private { public: KDBindings::ScopedConnection titleChangedConnection; KDBindings::ScopedConnection iconChangedConnection; KDBindings::ScopedConnection screenChangedConnection; KDBindings::ScopedConnection focusChangedConnection; KDBindings::ScopedConnection closeButtonEnabledConnection; KDBindings::ScopedConnection floatButtonToolTipConnection; KDBindings::ScopedConnection floatButtonVisibleConnection; KDBindings::ScopedConnection autoHideButtonConnection; KDBindings::ScopedConnection minimizeButtonConnection; KDBindings::ScopedConnection maximizeButtonConnection; }; TitleBar::TitleBar(Core::TitleBar *controller, Core::View *parent) : View(controller, Core::ViewType::TitleBar, View_qt::asQWidget(parent)) , Core::TitleBarViewInterface(controller) , m_layout(new QHBoxLayout(this)) , d(new Private()) { setAttribute(Qt::WA_StyledBackground, true); setObjectName(QStringLiteral("KDDWTitleBar")); } TitleBar::TitleBar(QWidget *parent) : View(new Core::TitleBar(this), Core::ViewType::TitleBar, parent) , Core::TitleBarViewInterface(static_cast(controller())) , m_layout(new QHBoxLayout(this)) , d(new Private()) { setAttribute(Qt::WA_StyledBackground, true); setObjectName(QStringLiteral("KDDWTitleBar")); m_titleBar->init(); } TitleBar::~TitleBar() { delete d; /// The window deletion might have been triggered by pressing a button, so use deleteLater() for (auto button : { m_closeButton, m_floatButton, m_maximizeButton, m_minimizeButton, m_autoHideButton }) { if (!button) continue; if (auto kddwButton = qobject_cast