centralize how we handle global options

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-05-08 16:09:00 +08:00
parent 286811c9df
commit 053d6b104e
33 changed files with 438 additions and 166 deletions

View File

@ -1,5 +1,9 @@
# FramelessHelper 2.x
## Join with us :triangular_flag_on_post:
You can join our <a href="https://discord.gg/Rc6r9J3uZw">Discord Channel</a> to communicate with us. You can share your findings, thoughts and ideas on improving / implementing FramelessHelper functionalities on more platforms and apps!
## Highlights compared to 2.1 (TODO list)
- Common: Added cross-platform customizable system menu for both Qt Widgets and Qt Quick. Also supports both light and dark theme.

View File

@ -26,7 +26,7 @@
#include <QtCore/qdatetime.h>
#include <QtWidgets/qlabel.h>
#include <QtWidgets/qboxlayout.h>
#include <FramelessWindowsManager>
#include <FramelessManager>
#include <Utils>
#include <FramelessWidgetsHelper>
#include <StandardTitleBar>
@ -40,7 +40,7 @@ Widget::Widget(QWidget *parent) : FramelessWidget(parent)
{
initialize();
startTimer(500);
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, &Widget::updateStyleSheet);
connect(FramelessManager::instance(), &FramelessManager::systemThemeChanged, this, &Widget::updateStyleSheet);
}
Widget::~Widget() = default;

View File

@ -0,0 +1 @@
#include <framelessmanager.h>

View File

@ -1 +0,0 @@
#include <framelesswindowsmanager.h>

View File

@ -183,14 +183,15 @@ Q_NAMESPACE_EXPORT(FRAMELESSHELPER_CORE_API)
[[maybe_unused]] static Q_CONSTEXPR2 const QColor kDefaultSystemButtonBackgroundColor = {204, 204, 204}; // #CCCCCC
[[maybe_unused]] static Q_CONSTEXPR2 const QColor kDefaultSystemCloseButtonBackgroundColor = {232, 17, 35}; // #E81123
[[maybe_unused]] static constexpr const char kUsePureQtImplFlag[] = "FRAMELESSHELPER_PURE_QT_IMPLEMENTATION";
[[maybe_unused]] static constexpr const char kForceHideFrameBorderFlag[] = "FRAMELESSHELPER_FORCE_HIDE_FRAME_BORDER";
[[maybe_unused]] static constexpr const char kForceShowFrameBorderFlag[] = "FRAMELESSHELPER_FORCE_SHOW_FRAME_BORDER";
FRAMELESSHELPER_STRING_CONSTANT2(ConfigFileName, ".framelesshelper.ini")
FRAMELESSHELPER_STRING_CONSTANT2(UsePureQtImplKeyPath, "Options/UsePureQtImplementation")
FRAMELESSHELPER_STRING_CONSTANT2(ForceHideFrameBorderKeyPath, "Options/ForceHideFrameBorder")
FRAMELESSHELPER_STRING_CONSTANT2(ForceShowFrameBorderKeyPath, "Options/ForceShowFrameBorder")
enum class Option
{
UseCrossPlatformQtImplementation = 0,
ForceHideWindowFrameBorder = 1,
ForceShowWindowFrameBorder = 2,
DisableWindowsSnapLayouts = 3,
WindowUseRoundCorners = 4
};
Q_ENUM_NS(Option)
enum class SystemTheme
{
@ -477,7 +478,7 @@ struct SystemParameters
{10, 0, 19044}, // Windows 10 Version 21H2 (November 2021 Update) (21H2)
{10, 0, 22000}, // Windows 11 Version 21H2 (21H2)
};
static_assert((sizeof(WindowsVersions) / sizeof(WindowsVersions[0])) == (static_cast<int>(WindowsVersion::_11_21H2) + 1));
static_assert(std::size(WindowsVersions) == (static_cast<int>(WindowsVersion::_11_21H2) + 1));
} // namespace Global

View File

@ -29,24 +29,22 @@
FRAMELESSHELPER_BEGIN_NAMESPACE
class FramelessWindowsManagerPrivate;
class FramelessManagerPrivate;
class FRAMELESSHELPER_CORE_API FramelessWindowsManager : public QObject
class FRAMELESSHELPER_CORE_API FramelessManager : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(FramelessWindowsManager)
Q_DISABLE_COPY_MOVE(FramelessWindowsManager)
Q_PROPERTY(bool usePureQtImplementation READ usePureQtImplementation CONSTANT FINAL)
Q_DECLARE_PRIVATE(FramelessManager)
Q_DISABLE_COPY_MOVE(FramelessManager)
Q_PROPERTY(Global::SystemTheme systemTheme READ systemTheme NOTIFY systemThemeChanged FINAL)
Q_PROPERTY(QColor systemAccentColor READ systemAccentColor NOTIFY systemThemeChanged FINAL)
public:
explicit FramelessWindowsManager(QObject *parent = nullptr);
~FramelessWindowsManager() override;
explicit FramelessManager(QObject *parent = nullptr);
~FramelessManager() override;
Q_NODISCARD static FramelessWindowsManager *instance();
Q_NODISCARD static FramelessManager *instance();
Q_NODISCARD bool usePureQtImplementation() const;
Q_NODISCARD Global::SystemTheme systemTheme() const;
Q_NODISCARD QColor systemAccentColor() const;
@ -57,7 +55,7 @@ Q_SIGNALS:
void systemThemeChanged();
private:
QScopedPointer<FramelessWindowsManagerPrivate> d_ptr;
QScopedPointer<FramelessManagerPrivate> d_ptr;
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -0,0 +1,49 @@
/*
* MIT License
*
* Copyright (C) 2022 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include "framelesshelpercore_global.h"
#include <QtCore/qobject.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
class FRAMELESSHELPER_CORE_API FramelessConfig : public QObject
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(FramelessConfig)
public:
explicit FramelessConfig(QObject *parent = nullptr);
~FramelessConfig() override;
Q_NODISCARD static FramelessConfig *instance();
void reload(const bool force = false);
void set(const Global::Option option, const bool on = true);
Q_NODISCARD bool isSet(const Global::Option option) const;
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -29,22 +29,21 @@
FRAMELESSHELPER_BEGIN_NAMESPACE
class FramelessWindowsManager;
class FramelessManager;
class FRAMELESSHELPER_CORE_API FramelessWindowsManagerPrivate : public QObject
class FRAMELESSHELPER_CORE_API FramelessManagerPrivate : public QObject
{
Q_OBJECT
Q_DECLARE_PUBLIC(FramelessWindowsManager)
Q_DISABLE_COPY_MOVE(FramelessWindowsManagerPrivate)
Q_DECLARE_PUBLIC(FramelessManager)
Q_DISABLE_COPY_MOVE(FramelessManagerPrivate)
public:
explicit FramelessWindowsManagerPrivate(FramelessWindowsManager *q);
~FramelessWindowsManagerPrivate() override;
explicit FramelessManagerPrivate(FramelessManager *q);
~FramelessManagerPrivate() override;
Q_NODISCARD static FramelessWindowsManagerPrivate *get(FramelessWindowsManager *pub);
Q_NODISCARD static const FramelessWindowsManagerPrivate *get(const FramelessWindowsManager *pub);
Q_NODISCARD static FramelessManagerPrivate *get(FramelessManager *pub);
Q_NODISCARD static const FramelessManagerPrivate *get(const FramelessManager *pub);
Q_NODISCARD static bool usePureQtImplementation();
Q_NODISCARD Global::SystemTheme systemTheme() const;
Q_NODISCARD QColor systemAccentColor() const;
@ -55,7 +54,7 @@ private:
void initialize();
private:
FramelessWindowsManager *q_ptr = nullptr;
FramelessManager *q_ptr = nullptr;
Global::SystemTheme m_systemTheme = Global::SystemTheme::Unknown;
QColor m_accentColor = {};
#ifdef Q_OS_WINDOWS

View File

@ -50,6 +50,7 @@ class FRAMELESSHELPER_QUICK_API QuickStandardTitleBar : public QQuickRectangle
Q_PROPERTY(QuickStandardMinimizeButton* minimizeButton READ minimizeButton CONSTANT FINAL)
Q_PROPERTY(QuickStandardMaximizeButton* maximizeButton READ maximizeButton CONSTANT FINAL)
Q_PROPERTY(QuickStandardCloseButton* closeButton READ closeButton CONSTANT FINAL)
Q_PROPERTY(bool extended READ isExtended WRITE setExtended NOTIFY extendedChanged FINAL)
public:
explicit QuickStandardTitleBar(QQuickItem *parent = nullptr);
@ -62,6 +63,9 @@ public:
Q_NODISCARD QuickStandardMaximizeButton *maximizeButton() const;
Q_NODISCARD QuickStandardCloseButton *closeButton() const;
Q_NODISCARD bool isExtended() const;
void setExtended(const bool value);
protected:
void itemChange(const ItemChange change, const ItemChangeData &value) override;
@ -75,6 +79,7 @@ private Q_SLOTS:
Q_SIGNALS:
void titleLabelAlignmentChanged();
void extendedChanged();
private:
void initialize();
@ -90,6 +95,7 @@ private:
QMetaObject::Connection m_windowStateChangeConnection = {};
QMetaObject::Connection m_windowActiveChangeConnection = {};
QMetaObject::Connection m_windowTitleChangeConnection = {};
bool m_extended = false;
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -50,6 +50,9 @@ public:
Q_NODISCARD static StandardTitleBarPrivate *get(StandardTitleBar *pub);
Q_NODISCARD static const StandardTitleBarPrivate *get(const StandardTitleBar *pub);
Q_NODISCARD bool isExtended() const;
void setExtended(const bool value);
public Q_SLOTS:
void updateMaximizeButton();
void updateTitleBarStyleSheet();
@ -67,6 +70,7 @@ private:
QScopedPointer<StandardSystemButton> m_maximizeButton;
QScopedPointer<StandardSystemButton> m_closeButton;
QPointer<QWidget> m_window = nullptr;
bool m_extended = false;
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -40,6 +40,7 @@ class FRAMELESSHELPER_WIDGETS_API StandardTitleBar : public QWidget
Q_PROPERTY(StandardSystemButton* minimizeButton READ minimizeButton CONSTANT FINAL)
Q_PROPERTY(StandardSystemButton* maximizeButton READ maximizeButton CONSTANT FINAL)
Q_PROPERTY(StandardSystemButton* closeButton READ closeButton CONSTANT FINAL)
Q_PROPERTY(bool extended READ isExtended WRITE setExtended NOTIFY extendedChanged FINAL)
public:
explicit StandardTitleBar(QWidget *parent = nullptr);
@ -49,9 +50,15 @@ public:
Q_NODISCARD StandardSystemButton *maximizeButton() const;
Q_NODISCARD StandardSystemButton *closeButton() const;
Q_NODISCARD bool isExtended() const;
void setExtended(const bool value);
protected:
void paintEvent(QPaintEvent *event) override;
Q_SIGNALS:
void extendedChanged();
private:
QScopedPointer<StandardTitleBarPrivate> d_ptr;
};

View File

@ -35,13 +35,15 @@ set(INCLUDE_PREFIX ../../include/FramelessHelper/Core)
set(SOURCES
${INCLUDE_PREFIX}/framelesshelpercore_global.h
${INCLUDE_PREFIX}/framelesshelper_qt.h
${INCLUDE_PREFIX}/framelesswindowsmanager.h
${INCLUDE_PREFIX}/framelessmanager.h
${INCLUDE_PREFIX}/utils.h
${INCLUDE_PREFIX}/private/framelesswindowsmanager_p.h
${INCLUDE_PREFIX}/private/framelessmanager_p.h
${INCLUDE_PREFIX}/private/framelessconfig_p.h
framelesshelpercore.qrc
utils.cpp
framelesshelper_qt.cpp
framelesswindowsmanager.cpp
framelessmanager.cpp
framelessconfig.cpp
)
if(WIN32)

View File

@ -0,0 +1,102 @@
/*
* MIT License
*
* Copyright (C) 2022 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "framelessconfig_p.h"
#include <QtCore/qmutex.h>
#include <QtCore/qdir.h>
#include <QtCore/qsettings.h>
#include <QtCore/qcoreapplication.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
using namespace Global;
FRAMELESSHELPER_STRING_CONSTANT2(ConfigFileName, ".framelesshelper.ini")
static constexpr const struct
{
const char *env = nullptr;
const char *ini = nullptr;
} OptionsTable[] = {
{"FRAMELESSHELPER_USE_CROSS_PLATFORM_QT_IMPLEMENTATION", "Options/UseCrossPlatformQtImplementation"},
{"FRAMELESSHELPER_FORCE_HIDE_WINDOW_FRAME_BORDER", "Options/ForceHideWindowFrameBorder"},
{"FRAMELESSHELPER_FORCE_SHOW_WINDOW_FRAME_BORDER", "Options/ForceShowWindowFrameBorder"},
{"FRAMELESSHELPER_DISABLE_WINDOWS_SNAP_LAYOUTS", "Options/DisableWindowsSnapLayouts"},
{"FRAMELESSHELPER_WINDOW_USE_ROUND_CORNERS", "Options/WindowUseRoundCorners"}
};
static constexpr const auto OptionCount = std::size(OptionsTable);
struct ConfigData
{
QMutex mutex;
bool loaded = false;
bool options[OptionCount] = {};
};
Q_GLOBAL_STATIC(ConfigData, g_data)
Q_GLOBAL_STATIC(FramelessConfig, g_config)
FramelessConfig::FramelessConfig(QObject *parent) : QObject(parent)
{
reload();
}
FramelessConfig::~FramelessConfig() = default;
FramelessConfig *FramelessConfig::instance()
{
return g_config();
}
void FramelessConfig::reload(const bool force)
{
QMutexLocker locker(&g_data()->mutex);
if (g_data()->loaded && !force) {
return;
}
const QDir appDir(QCoreApplication::applicationDirPath());
const QSettings configFile(appDir.filePath(kConfigFileName), QSettings::IniFormat);
for (int i = 0; i != OptionCount; ++i) {
const bool on = (qEnvironmentVariableIsSet(OptionsTable[i].env) && (qEnvironmentVariableIntValue(OptionsTable[i].env) > 0))
|| (configFile.value(QUtf8String(OptionsTable[i].ini), false).toBool());
g_data()->options[i] = on;
}
g_data()->loaded = true;
}
void FramelessConfig::set(const Option option, const bool on)
{
QMutexLocker locker(&g_data()->mutex);
g_data()->options[static_cast<int>(option)] = on;
}
bool FramelessConfig::isSet(const Option option) const
{
QMutexLocker locker(&g_data()->mutex);
return g_data()->options[static_cast<int>(option)];
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -0,0 +1 @@
#include "../../include/FramelessHelper/Core/private/framelessconfig_p.h"

View File

@ -26,8 +26,8 @@
#include <QtCore/qmutex.h>
#include <QtGui/qevent.h>
#include <QtGui/qwindow.h>
#include "framelesswindowsmanager.h"
#include "framelesswindowsmanager_p.h"
#include "framelessmanager.h"
#include "framelessmanager_p.h"
#include "utils.h"
FRAMELESSHELPER_BEGIN_NAMESPACE
@ -90,8 +90,8 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
// First detect whether we got a theme change event or not, if so,
// inform the user the system theme has changed.
if (Utils::isThemeChangeEvent(event)) {
FramelessWindowsManager *manager = FramelessWindowsManager::instance();
FramelessWindowsManagerPrivate *managerPriv = FramelessWindowsManagerPrivate::get(manager);
FramelessManager *manager = FramelessManager::instance();
FramelessManagerPrivate *managerPriv = FramelessManagerPrivate::get(manager);
managerPriv->notifySystemThemeHasChangedOrNot();
return false;
}

View File

@ -30,8 +30,9 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/quuid.h>
#include <QtGui/qwindow.h>
#include "framelesswindowsmanager.h"
#include "framelesswindowsmanager_p.h"
#include "framelessmanager.h"
#include "framelessmanager_p.h"
#include "framelessconfig_p.h"
#include "utils.h"
#include "framelesshelper_windows.h"
@ -353,7 +354,10 @@ FRAMELESSHELPER_STRING_CONSTANT(FindWindowW)
if (!parentWindowId) {
return false;
}
if (!Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1507)) {
static const bool isWin10OrGreater = []() -> bool {
return Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1507);
}();
if (!isWin10OrGreater) {
qWarning() << "The drag bar window is only supported on Windows 10 and onwards.";
return false;
}
@ -437,17 +441,32 @@ void FramelessHelperWin::addWindow(const SystemParameters &params)
Utils::fixupQtInternals(windowId);
Utils::updateInternalWindowFrameMargins(params.getWindowHandle(), true);
Utils::updateWindowFrameMargins(windowId, false);
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1507)) {
if (!createDragBarWindow(windowId)) {
qWarning() << "Failed to create the drag bar window.";
static const bool isWin10OrGreater = []() -> bool {
return Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1507);
}();
if (isWin10OrGreater) {
const FramelessConfig * const config = FramelessConfig::instance();
if (!config->isSet(Option::DisableWindowsSnapLayouts)) {
if (!createDragBarWindow(windowId)) {
qWarning() << "Failed to create the drag bar window.";
}
}
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1607)) {
static const bool isWin10RS1OrGreater = []() -> bool {
return Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1607);
}();
if (isWin10RS1OrGreater) {
const bool dark = Utils::shouldAppsUseDarkMode();
Utils::updateWindowFrameBorderColor(windowId, dark);
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1809)) {
static const bool isWin10RS5OrGreater = []() -> bool {
return Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1809);
}();
if (isWin10RS5OrGreater) {
//Utils::updateGlobalWin32ControlsTheme(windowId, dark); // Causes some QtWidgets paint incorrectly.
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2)) {
Utils::forceSquareCornersForWindow(windowId, true);
static const bool isWin11OrGreater = []() -> bool {
return Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2);
}();
if (isWin11OrGreater) {
Utils::forceSquareCornersForWindow(windowId, !config->isSet(Option::WindowUseRoundCorners));
}
}
}
@ -623,10 +642,13 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
// First, check if we have an auto-hide taskbar at all:
if (taskbarState & ABS_AUTOHIDE) {
bool top = false, bottom = false, left = false, right = false;
// Due to ABM_GETAUTOHIDEBAREX only exists from Win8.1,
// we have to use another way to judge this if we are
// running on Windows 7 or Windows 8.
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_8_1)) {
// Due to ABM_GETAUTOHIDEBAREX was introduced in Windows 8.1,
// we have to use another way to judge this if we are running
// on Windows 7 or Windows 8.
static const bool isWin8Point1OrGreater = []() -> bool {
return Utils::isWindowsVersionOrGreater(WindowsVersion::_8_1);
}();
if (isWin8Point1OrGreater) {
MONITORINFO monitorInfo;
SecureZeroMemory(&monitorInfo, sizeof(monitorInfo));
monitorInfo.cbSize = sizeof(monitorInfo);
@ -1008,7 +1030,10 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
break;
}
}
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_8) && data.dragBarWindowId) {
static const bool isWin10OrGreater = []() -> bool {
return Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1507);
}();
if (isWin10OrGreater && data.dragBarWindowId) {
switch (uMsg) {
case WM_SIZE:
case WM_DISPLAYCHANGE: {
@ -1022,22 +1047,28 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
}
bool systemThemeChanged = ((uMsg == WM_THEMECHANGED) || (uMsg == WM_SYSCOLORCHANGE)
|| (uMsg == WM_DWMCOLORIZATIONCOLORCHANGED));
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1607)) {
static const bool isWin10RS1OrGreater = []() -> bool {
return Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1607);
}();
if (isWin10RS1OrGreater) {
if (uMsg == WM_SETTINGCHANGE) {
if ((wParam == 0) && (QString::fromWCharArray(reinterpret_cast<LPCWSTR>(lParam))
.compare(qThemeSettingChangeEventName, Qt::CaseInsensitive) == 0)) {
systemThemeChanged = true;
const bool dark = Utils::shouldAppsUseDarkMode();
Utils::updateWindowFrameBorderColor(windowId, dark);
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1809)) {
static const bool isWin10RS5OrGreater = []() -> bool {
return Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1809);
}();
if (isWin10RS5OrGreater) {
//Utils::updateGlobalWin32ControlsTheme(windowId, dark); // Causes some QtWidgets paint incorrectly.
}
}
}
}
if (systemThemeChanged) {
FramelessWindowsManager *manager = FramelessWindowsManager::instance();
FramelessWindowsManagerPrivate *managerPriv = FramelessWindowsManagerPrivate::get(manager);
FramelessManager *manager = FramelessManager::instance();
FramelessManagerPrivate *managerPriv = FramelessManagerPrivate::get(manager);
managerPriv->notifySystemThemeHasChangedOrNot();
}
return false;

View File

@ -22,15 +22,14 @@
* SOFTWARE.
*/
#include "framelesswindowsmanager.h"
#include "framelesswindowsmanager_p.h"
#include <QtCore/qvariant.h>
#include "framelessmanager.h"
#include "framelessmanager_p.h"
#include <QtCore/qmutex.h>
#include <QtCore/qsettings.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qscreen.h>
#include <QtGui/qwindow.h>
#include "framelesshelper_qt.h"
#include "framelessconfig_p.h"
#include "utils.h"
#ifdef Q_OS_WINDOWS
# include "framelesshelper_win.h"
@ -40,15 +39,15 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
using namespace Global;
struct FramelessWindowsManagerHelper
struct FramelessManagerHelper
{
QMutex mutex;
QList<WId> windowIds = {};
};
Q_GLOBAL_STATIC(FramelessWindowsManagerHelper, g_helper)
Q_GLOBAL_STATIC(FramelessManagerHelper, g_helper)
Q_GLOBAL_STATIC(FramelessWindowsManager, g_manager)
Q_GLOBAL_STATIC(FramelessManager, g_manager)
#ifdef Q_OS_LINUX
static constexpr const char QT_QPA_ENV_VAR[] = "QT_QPA_PLATFORM";
@ -60,7 +59,7 @@ static constexpr const char MAC_LAYER_ENV_VAR[] = "QT_MAC_WANTS_LAYER";
FRAMELESSHELPER_BYTEARRAY_CONSTANT2(ValueOne, "1")
#endif
FramelessWindowsManagerPrivate::FramelessWindowsManagerPrivate(FramelessWindowsManager *q) : QObject(q)
FramelessManagerPrivate::FramelessManagerPrivate(FramelessManager *q) : QObject(q)
{
Q_ASSERT(q);
if (!q) {
@ -70,9 +69,9 @@ FramelessWindowsManagerPrivate::FramelessWindowsManagerPrivate(FramelessWindowsM
initialize();
}
FramelessWindowsManagerPrivate::~FramelessWindowsManagerPrivate() = default;
FramelessManagerPrivate::~FramelessManagerPrivate() = default;
FramelessWindowsManagerPrivate *FramelessWindowsManagerPrivate::get(FramelessWindowsManager *pub)
FramelessManagerPrivate *FramelessManagerPrivate::get(FramelessManager *pub)
{
Q_ASSERT(pub);
if (!pub) {
@ -81,7 +80,7 @@ FramelessWindowsManagerPrivate *FramelessWindowsManagerPrivate::get(FramelessWin
return pub->d_func();
}
const FramelessWindowsManagerPrivate *FramelessWindowsManagerPrivate::get(const FramelessWindowsManager *pub)
const FramelessManagerPrivate *FramelessManagerPrivate::get(const FramelessManager *pub)
{
Q_ASSERT(pub);
if (!pub) {
@ -90,34 +89,17 @@ const FramelessWindowsManagerPrivate *FramelessWindowsManagerPrivate::get(const
return pub->d_func();
}
bool FramelessWindowsManagerPrivate::usePureQtImplementation()
{
#ifdef Q_OS_WINDOWS
static const bool result = []() -> bool {
if (qEnvironmentVariableIntValue(kUsePureQtImplFlag) != 0) {
return true;
}
const QString iniFilePath = QCoreApplication::applicationDirPath() + QChar(u'/') + kConfigFileName;
QSettings settings(iniFilePath, QSettings::IniFormat);
return settings.value(kUsePureQtImplKeyPath, false).toBool();
}();
#else
static constexpr const bool result = true;
#endif
return result;
}
SystemTheme FramelessWindowsManagerPrivate::systemTheme() const
SystemTheme FramelessManagerPrivate::systemTheme() const
{
return m_systemTheme;
}
QColor FramelessWindowsManagerPrivate::systemAccentColor() const
QColor FramelessManagerPrivate::systemAccentColor() const
{
return m_accentColor;
}
void FramelessWindowsManagerPrivate::addWindow(const SystemParameters &params)
void FramelessManagerPrivate::addWindow(const SystemParameters &params)
{
Q_ASSERT(params.isValid());
if (!params.isValid()) {
@ -131,7 +113,13 @@ void FramelessWindowsManagerPrivate::addWindow(const SystemParameters &params)
}
g_helper()->windowIds.append(windowId);
g_helper()->mutex.unlock();
static const bool pureQt = usePureQtImplementation();
static const bool pureQt = []() -> bool {
#ifdef Q_OS_WINDOWS
return FramelessConfig::instance()->isSet(Option::UseCrossPlatformQtImplementation);
#else
return true;
#endif
}();
#ifdef Q_OS_WINDOWS
if (!pureQt) {
// Work-around Win32 multi-monitor artifacts.
@ -162,9 +150,9 @@ void FramelessWindowsManagerPrivate::addWindow(const SystemParameters &params)
#endif
}
void FramelessWindowsManagerPrivate::notifySystemThemeHasChangedOrNot()
void FramelessManagerPrivate::notifySystemThemeHasChangedOrNot()
{
Q_Q(FramelessWindowsManager);
Q_Q(FramelessManager);
const SystemTheme currentSystemTheme = Utils::getSystemTheme();
#ifdef Q_OS_WINDOWS
const DwmColorizationArea currentColorizationArea = Utils::getDwmColorizationArea();
@ -196,7 +184,7 @@ void FramelessWindowsManagerPrivate::notifySystemThemeHasChangedOrNot()
}
}
void FramelessWindowsManagerPrivate::initialize()
void FramelessManagerPrivate::initialize()
{
m_systemTheme = Utils::getSystemTheme();
#ifdef Q_OS_WINDOWS
@ -211,38 +199,32 @@ void FramelessWindowsManagerPrivate::initialize()
#endif
}
FramelessWindowsManager::FramelessWindowsManager(QObject *parent) : QObject(parent), d_ptr(new FramelessWindowsManagerPrivate(this))
FramelessManager::FramelessManager(QObject *parent) : QObject(parent), d_ptr(new FramelessManagerPrivate(this))
{
}
FramelessWindowsManager::~FramelessWindowsManager() = default;
FramelessManager::~FramelessManager() = default;
FramelessWindowsManager *FramelessWindowsManager::instance()
FramelessManager *FramelessManager::instance()
{
return g_manager();
}
bool FramelessWindowsManager::usePureQtImplementation() const
SystemTheme FramelessManager::systemTheme() const
{
Q_D(const FramelessWindowsManager);
return d->usePureQtImplementation();
}
SystemTheme FramelessWindowsManager::systemTheme() const
{
Q_D(const FramelessWindowsManager);
Q_D(const FramelessManager);
return d->systemTheme();
}
QColor FramelessWindowsManager::systemAccentColor() const
QColor FramelessManager::systemAccentColor() const
{
Q_D(const FramelessWindowsManager);
Q_D(const FramelessManager);
return d->systemAccentColor();
}
void FramelessWindowsManager::addWindow(const SystemParameters &params)
void FramelessManager::addWindow(const SystemParameters &params)
{
Q_D(FramelessWindowsManager);
Q_D(FramelessManager);
d->addWindow(params);
}
@ -294,6 +276,7 @@ void FramelessHelper::Core::initialize()
// flicker and jitter during window resizing.
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round);
#endif
qRegisterMetaType<Option>();
qRegisterMetaType<SystemTheme>();
qRegisterMetaType<SystemButtonType>();
qRegisterMetaType<ResourceType>();

View File

@ -0,0 +1 @@
#include "../../include/FramelessHelper/Core/framelessmanager.h"

View File

@ -0,0 +1 @@
#include "../../include/FramelessHelper/Core/private/framelessmanager_p.h"

View File

@ -1 +0,0 @@
#include "../../include/FramelessHelper/Core/framelesswindowsmanager.h"

View File

@ -1 +0,0 @@
#include "../../include/FramelessHelper/Core/private/framelesswindowsmanager_p.h"

View File

@ -35,8 +35,9 @@
#else
# include <QtGui/qpa/qplatformwindow_p.h>
#endif
#include "framelesswindowsmanager.h"
#include "framelessmanager.h"
#include "framelesshelper_windows.h"
#include "framelessconfig_p.h"
#include <atlbase.h>
#include <d2d1.h>
@ -258,7 +259,10 @@ FRAMELESSHELPER_STRING_CONSTANT2(HKEY_CURRENT_USER, "HKEY_CURRENT_USER")
return titleBarHeight;
}
const int frameSizeY = Utils::getResizeBorderThickness(windowId, false, true);
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2)) {
static const bool isWin11OrGreater = []() -> bool {
return Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2);
}();
if (isWin11OrGreater) {
if (maxOrFull) {
return (titleBarHeight + frameSizeY);
}
@ -343,7 +347,10 @@ bool Utils::isWindowsVersionOrGreater(const WindowsVersion version)
bool Utils::isDwmCompositionEnabled()
{
// DWM composition is always enabled and can't be disabled since Windows 8.
if (isWindowsVersionOrGreater(WindowsVersion::_8)) {
static const bool isWin8OrGreater = []() -> bool {
return isWindowsVersionOrGreater(WindowsVersion::_8);
}();
if (isWin8OrGreater) {
return true;
}
const auto resultFromRegistry = []() -> bool {
@ -493,7 +500,10 @@ QColor Utils::getDwmColorizationColor()
DwmColorizationArea Utils::getDwmColorizationArea()
{
// It's a Win10 only feature. (TO BE VERIFIED)
if (!isWindowsVersionOrGreater(WindowsVersion::_10_1507)) {
static const bool isWin10OrGreater = []() -> bool {
return isWindowsVersionOrGreater(WindowsVersion::_10_1507);
}();
if (!isWin10OrGreater) {
return DwmColorizationArea::None_;
}
const QSettings themeRegistry(kHKEY_CURRENT_USER + u'\\' + qPersonalizeRegistryKey, QSettings::NativeFormat);
@ -852,7 +862,10 @@ quint32 Utils::getFrameBorderThickness(const WId windowId, const bool scaled)
return 0;
}
// There's no window frame border before Windows 10.
if (!isWindowsVersionOrGreater(WindowsVersion::_10_1507)) {
static const bool isWin10OrGreater = []() -> bool {
return isWindowsVersionOrGreater(WindowsVersion::_10_1507);
}();
if (!isWin10OrGreater) {
return 0;
}
static const auto pDwmGetWindowAttribute =
@ -878,7 +891,10 @@ QColor Utils::getFrameBorderColor(const bool active)
{
// There's no window frame border before Windows 10.
// So we just return a default value which is based on most window managers.
if (!isWindowsVersionOrGreater(WindowsVersion::_10_1507)) {
static const bool isWin10OrGreater = []() -> bool {
return isWindowsVersionOrGreater(WindowsVersion::_10_1507);
}();
if (!isWin10OrGreater) {
return (active ? kDefaultBlackColor : kDefaultDarkGrayColor);
}
const bool dark = shouldAppsUseDarkMode();
@ -900,7 +916,10 @@ void Utils::updateWindowFrameBorderColor(const WId windowId, const bool dark)
return;
}
// There's no global dark theme before Win10 1607.
if (!isWindowsVersionOrGreater(WindowsVersion::_10_1607)) {
static const bool isWin10RS1OrGreater = []() -> bool {
return isWindowsVersionOrGreater(WindowsVersion::_10_1607);
}();
if (!isWin10RS1OrGreater) {
return;
}
static const auto pDwmSetWindowAttribute =
@ -910,7 +929,10 @@ void Utils::updateWindowFrameBorderColor(const WId windowId, const bool dark)
return;
}
const auto hwnd = reinterpret_cast<HWND>(windowId);
const DWORD mode = (isWindowsVersionOrGreater(WindowsVersion::_10_2004) ? _DWMWA_USE_IMMERSIVE_DARK_MODE : _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1);
static const bool isWin1020H1OrGreater = []() -> bool {
return isWindowsVersionOrGreater(WindowsVersion::_10_2004);
}();
const DWORD mode = (isWin1020H1OrGreater ? _DWMWA_USE_IMMERSIVE_DARK_MODE : _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1);
const BOOL value = (dark ? TRUE : FALSE);
const HRESULT hr = pDwmSetWindowAttribute(hwnd, mode, &value, sizeof(value));
if (FAILED(hr)) {
@ -1012,28 +1034,17 @@ void Utils::startSystemResize(QWindow *window, const Qt::Edges edges, const QPoi
bool Utils::isWindowFrameBorderVisible()
{
static const bool result = []() -> bool {
if (FramelessWindowsManager::instance()->usePureQtImplementation()) {
return false;
}
// If we preserve the window frame border on systems prior to Windows 10,
// the window will look rather ugly and I guess no one would like to see
// such weired windows. But for the ones who really want to see what the
// window look like, I still provide a way to enter such scenarios.
if (qEnvironmentVariableIntValue(kForceShowFrameBorderFlag) != 0) {
const FramelessConfig * const config = FramelessConfig::instance();
if (config->isSet(Option::ForceShowWindowFrameBorder)) {
return true;
}
if (qEnvironmentVariableIntValue(kForceHideFrameBorderFlag) != 0) {
if (config->isSet(Option::ForceHideWindowFrameBorder)) {
return false;
}
const QString iniFilePath = QCoreApplication::applicationDirPath() + QChar(u'/') + kConfigFileName;
QSettings settings(iniFilePath, QSettings::IniFormat);
if (settings.value(kForceShowFrameBorderKeyPath, false).toBool()) {
return true;
}
if (settings.value(kForceHideFrameBorderKeyPath, false).toBool()) {
return false;
}
return isWindowsVersionOrGreater(WindowsVersion::_10_1507);
static const bool isWin10OrGreater = []() -> bool {
return isWindowsVersionOrGreater(WindowsVersion::_10_1507);
}();
return isWin10OrGreater;
}();
return result;
}
@ -1041,7 +1052,10 @@ bool Utils::isWindowFrameBorderVisible()
bool Utils::isTitleBarColorized()
{
// CHECK: is it supported on win7?
if (!isWindowsVersionOrGreater(WindowsVersion::_10_1507)) {
static const bool isWin10OrGreater = []() -> bool {
return isWindowsVersionOrGreater(WindowsVersion::_10_1507);
}();
if (!isWin10OrGreater) {
return false;
}
const DwmColorizationArea area = getDwmColorizationArea();
@ -1254,7 +1268,10 @@ SystemTheme Utils::getSystemTheme()
if (isHighContrastModeEnabled()) {
return SystemTheme::HighContrast;
}
if (isWindowsVersionOrGreater(WindowsVersion::_10_1607) && shouldAppsUseDarkMode()) {
static const bool isWin10RS1OrGreater = []() -> bool {
return isWindowsVersionOrGreater(WindowsVersion::_10_1607);
}();
if (isWin10RS1OrGreater && shouldAppsUseDarkMode()) {
return SystemTheme::Dark;
}
return SystemTheme::Light;
@ -1267,7 +1284,10 @@ void Utils::updateGlobalWin32ControlsTheme(const WId windowId, const bool dark)
return;
}
// There's no global dark theme for common Win32 controls before Win10 1809.
if (!isWindowsVersionOrGreater(WindowsVersion::_10_1809)) {
static const bool isWin10RS5OrGreater = []() -> bool {
return isWindowsVersionOrGreater(WindowsVersion::_10_1809);
}();
if (!isWin10RS5OrGreater) {
return;
}
static const auto pSetWindowTheme =
@ -1286,7 +1306,10 @@ void Utils::updateGlobalWin32ControlsTheme(const WId windowId, const bool dark)
bool Utils::shouldAppsUseDarkMode_windows()
{
// The global dark mode was first introduced in Windows 10 1607.
if (!isWindowsVersionOrGreater(WindowsVersion::_10_1607)) {
static const bool isWin10RS1OrGreater = []() -> bool {
return isWindowsVersionOrGreater(WindowsVersion::_10_1607);
}();
if (!isWin10RS1OrGreater) {
return false;
}
const auto resultFromRegistry = []() -> bool {
@ -1298,7 +1321,10 @@ bool Utils::shouldAppsUseDarkMode_windows()
static const auto pShouldAppsUseDarkMode =
reinterpret_cast<BOOL(WINAPI *)(VOID)>(
QSystemLibrary::resolve(kuxtheme, MAKEINTRESOURCEA(132)));
if (pShouldAppsUseDarkMode && !isWindowsVersionOrGreater(WindowsVersion::_10_1903)) {
static const bool isWin1019H1OrGreater = []() -> bool {
return isWindowsVersionOrGreater(WindowsVersion::_10_1903);
}();
if (pShouldAppsUseDarkMode && !isWin1019H1OrGreater) {
return (pShouldAppsUseDarkMode() != FALSE);
}
// Starting from Windows 10 1903, "ShouldAppsUseDarkMode()" always return "TRUE"
@ -1319,7 +1345,10 @@ void Utils::forceSquareCornersForWindow(const WId windowId, const bool force)
return;
}
// We cannot change the window corner style until Windows 11.
if (!isWindowsVersionOrGreater(WindowsVersion::_11_21H2)) {
static const bool isWin11OrGreater = []() -> bool {
return isWindowsVersionOrGreater(WindowsVersion::_11_21H2);
}();
if (!isWin11OrGreater) {
return;
}
static const auto pDwmSetWindowAttribute =

View File

@ -32,7 +32,7 @@
#endif
#include <QtQuick/qquickwindow.h>
#include <QtQuickTemplates2/private/qquickabstractbutton_p.h>
#include <framelesswindowsmanager.h>
#include <framelessmanager.h>
#include <utils.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
@ -208,7 +208,7 @@ void FramelessQuickHelperPrivate::attachToWindow()
data->attached = true;
g_quickHelper()->mutex.unlock();
FramelessWindowsManager::instance()->addWindow(params);
FramelessManager::instance()->addWindow(params);
}
void FramelessQuickHelperPrivate::setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType)

View File

@ -23,7 +23,7 @@
*/
#include "framelessquickutils.h"
#include <framelesswindowsmanager.h>
#include <framelessmanager.h>
#include <utils.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
@ -32,7 +32,7 @@ using namespace Global;
FramelessQuickUtils::FramelessQuickUtils(QObject *parent) : QObject(parent)
{
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, [this](){
connect(FramelessManager::instance(), &FramelessManager::systemThemeChanged, this, [this](){
Q_EMIT systemThemeChanged();
Q_EMIT systemAccentColorChanged();
Q_EMIT titleBarColorizedChanged();
@ -49,7 +49,10 @@ qreal FramelessQuickUtils::titleBarHeight() const
bool FramelessQuickUtils::frameBorderVisible() const
{
#ifdef Q_OS_WINDOWS
return (Utils::isWindowFrameBorderVisible() && !Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2));
static const bool isWin11OrGreater = []() -> bool {
return Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2);
}();
return (Utils::isWindowFrameBorderVisible() && !isWin11OrGreater);
#else
return false;
#endif

View File

@ -29,7 +29,7 @@
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
#include <QtQuick/private/qquickanchors_p.h>
#include <framelesswindowsmanager.h>
#include <framelessmanager.h>
#include <utils.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
@ -180,13 +180,16 @@ void FramelessQuickWindowPrivate::initialize()
Q_EMIT q->fullScreenChanged();
});
connect(q, &FramelessQuickWindow::activeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor);
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor);
connect(FramelessManager::instance(), &FramelessManager::systemThemeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor);
}
bool FramelessQuickWindowPrivate::shouldDrawFrameBorder() const
{
#ifdef Q_OS_WINDOWS
return (Utils::isWindowFrameBorderVisible() && !Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2));
static const bool isWin11OrGreater = []() -> bool {
return Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2);
}();
return (Utils::isWindowFrameBorderVisible() && !isWin11OrGreater);
#else
return false;
#endif

View File

@ -24,7 +24,7 @@
#include "quickstandardclosebutton_p.h"
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
#include <framelesswindowsmanager.h>
#include <framelessmanager.h>
#include <utils.h>
#include <QtQuick/private/qquickimage_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
@ -84,7 +84,7 @@ void QuickStandardCloseButton::initialize()
imageAnchors->setCenterIn(m_contentItem.data());
connect(this, &QuickStandardCloseButton::hoveredChanged, this, &QuickStandardCloseButton::updateForeground);
connect(this, &QuickStandardCloseButton::pressedChanged, this, &QuickStandardCloseButton::updateForeground);
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, &QuickStandardCloseButton::updateForeground);
connect(FramelessManager::instance(), &FramelessManager::systemThemeChanged, this, &QuickStandardCloseButton::updateForeground);
m_backgroundItem.reset(new QQuickRectangle(this));
QQuickPen * const border = m_backgroundItem->border();

View File

@ -24,7 +24,7 @@
#include "quickstandardmaximizebutton_p.h"
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
#include <framelesswindowsmanager.h>
#include <framelessmanager.h>
#include <utils.h>
#include <QtQuick/private/qquickimage_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
@ -99,7 +99,7 @@ void QuickStandardMaximizeButton::initialize()
m_image.reset(new QQuickImage(m_contentItem.data()));
const auto imageAnchors = new QQuickAnchors(m_image.data(), m_image.data());
imageAnchors->setCenterIn(m_contentItem.data());
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, &QuickStandardMaximizeButton::updateForeground);
connect(FramelessManager::instance(), &FramelessManager::systemThemeChanged, this, &QuickStandardMaximizeButton::updateForeground);
connect(this, &QuickStandardMaximizeButton::maximizedChanged, this, &QuickStandardMaximizeButton::updateForeground);
m_backgroundItem.reset(new QQuickRectangle(this));

View File

@ -24,7 +24,7 @@
#include "quickstandardminimizebutton_p.h"
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
#include <framelesswindowsmanager.h>
#include <framelessmanager.h>
#include <utils.h>
#include <QtQuick/private/qquickimage_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
@ -82,7 +82,7 @@ void QuickStandardMinimizeButton::initialize()
m_image.reset(new QQuickImage(m_contentItem.data()));
const auto imageAnchors = new QQuickAnchors(m_image.data(), m_image.data());
imageAnchors->setCenterIn(m_contentItem.data());
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, &QuickStandardMinimizeButton::updateForeground);
connect(FramelessManager::instance(), &FramelessManager::systemThemeChanged, this, &QuickStandardMinimizeButton::updateForeground);
m_backgroundItem.reset(new QQuickRectangle(this));
QQuickPen * const border = m_backgroundItem->border();

View File

@ -27,7 +27,7 @@
#include "quickstandardminimizebutton_p.h"
#include "quickstandardmaximizebutton_p.h"
#include "quickstandardclosebutton_p.h"
#include <framelesswindowsmanager.h>
#include <framelessmanager.h>
#include <utils.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickanchors_p.h>
@ -103,6 +103,21 @@ QuickStandardCloseButton *QuickStandardTitleBar::closeButton() const
return m_closeBtn.data();
}
bool QuickStandardTitleBar::isExtended() const
{
return m_extended;
}
void QuickStandardTitleBar::setExtended(const bool value)
{
if (m_extended == value) {
return;
}
m_extended = value;
setHeight(m_extended ? kDefaultExtendedTitleBarHeight : kDefaultTitleBarHeight);
Q_EMIT extendedChanged();
}
void QuickStandardTitleBar::updateMaximizeButton()
{
const QQuickWindow * const w = window();
@ -217,7 +232,7 @@ void QuickStandardTitleBar::initialize()
m_closeBtn.reset(new QuickStandardCloseButton(m_row.data()));
connect(m_closeBtn.data(), &QuickStandardCloseButton::clicked, this, &QuickStandardTitleBar::clickCloseButton);
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, &QuickStandardTitleBar::updateTitleBarColor);
connect(FramelessManager::instance(), &FramelessManager::systemThemeChanged, this, &QuickStandardTitleBar::updateTitleBarColor);
setTitleLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter);

View File

@ -27,8 +27,9 @@
#include <QtCore/qmutex.h>
#include <QtCore/qhash.h>
#include <QtCore/qpointer.h>
#include <QtGui/qwindow.h>
#include <QtWidgets/qwidget.h>
#include <framelesswindowsmanager.h>
#include <framelessmanager.h>
#include <utils.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
@ -236,7 +237,7 @@ void FramelessWidgetsHelperPrivate::attachToWindow()
data->attached = true;
g_widgetsHelper()->mutex.unlock();
FramelessWindowsManager::instance()->addWindow(params);
FramelessManager::instance()->addWindow(params);
}
QWidget *FramelessWidgetsHelperPrivate::getWindow() const

View File

@ -26,7 +26,7 @@
#include "standardsystembutton_p.h"
#include <QtCore/qvariant.h>
#include <QtGui/qpainter.h>
#include <framelesswindowsmanager.h>
#include <framelessmanager.h>
#include <utils.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
@ -307,7 +307,7 @@ void StandardSystemButtonPrivate::initialize()
q->setIconSize(kDefaultSystemButtonIconSize);
connect(q, &StandardSystemButton::pressed, this, [this](){ setPressed(true); });
connect(q, &StandardSystemButton::released, this, [this](){ setPressed(false); });
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged,
connect(FramelessManager::instance(), &FramelessManager::systemThemeChanged,
this, [this](){ refreshButtonTheme(false); });
}

View File

@ -31,7 +31,7 @@
#include <QtWidgets/qboxlayout.h>
#include <QtWidgets/qstyle.h>
#include <QtWidgets/qstyleoption.h>
#include <framelesswindowsmanager.h>
#include <framelessmanager.h>
#include <utils.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
@ -71,6 +71,22 @@ const StandardTitleBarPrivate *StandardTitleBarPrivate::get(const StandardTitleB
return pub->d_func();
}
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();
}
void StandardTitleBarPrivate::updateMaximizeButton()
{
const bool zoomed = (m_window->isMaximized() || m_window->isFullScreen());
@ -172,6 +188,9 @@ void StandardTitleBarPrivate::initialize()
m_closeButton.reset(new StandardSystemButton(SystemButtonType::Close, q));
m_closeButton->setToolTip(tr("Close"));
connect(m_closeButton.data(), &StandardSystemButton::clicked, m_window, &QWidget::close);
// According to the title bar design guidance, the system buttons should always be
// placed on the top-right corner of the window, so we need the following additional
// layouts to ensure this.
const auto systemButtonsInnerLayout = new QHBoxLayout;
systemButtonsInnerLayout->setSpacing(0);
systemButtonsInnerLayout->setContentsMargins(0, 0, 0, 0);
@ -192,8 +211,8 @@ void StandardTitleBarPrivate::initialize()
titleBarLayout->addLayout(systemButtonsOuterLayout);
q->setLayout(titleBarLayout);
updateTitleBarStyleSheet();
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged,
this, &StandardTitleBarPrivate::updateTitleBarStyleSheet);
connect(FramelessManager::instance(), &FramelessManager::systemThemeChanged,
this, &StandardTitleBarPrivate::updateTitleBarStyleSheet);
m_window->installEventFilter(this);
}
@ -222,6 +241,18 @@ StandardSystemButton *StandardTitleBar::closeButton() const
return d->m_closeButton.data();
}
bool StandardTitleBar::isExtended() const
{
Q_D(const StandardTitleBar);
return d->isExtended();
}
void StandardTitleBar::setExtended(const bool value)
{
Q_D(StandardTitleBar);
d->setExtended(value);
}
void StandardTitleBar::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);

View File

@ -127,7 +127,10 @@ void WidgetsSharedHelper::paintEventHandler(QPaintEvent *event)
bool WidgetsSharedHelper::shouldDrawFrameBorder() const
{
#ifdef Q_OS_WINDOWS
return (Utils::isWindowFrameBorderVisible() && !Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2)
static const bool isWin11OrGreater = []() -> bool {
return Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2);
}();
return (Utils::isWindowFrameBorderVisible() && !isWin11OrGreater
&& (Utils::windowStatesToWindowState(m_targetWidget->windowState()) == Qt::WindowNoState));
#else
return false;