Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-03-14 15:26:49 +08:00
parent efb56c712c
commit bb8d174c56
18 changed files with 228 additions and 54 deletions

View File

@ -5,6 +5,14 @@ project(FramelessHelper LANGUAGES CXX)
option(FRAMELESSHELPER_BUILD_STATIC "Build FramelessHelper as a static library." OFF)
option(FRAMELESSHELPER_BUILD_EXAMPLES "Build FramelessHelper demo applications." ON)
if(NOT DEFINED CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug") AND NOT DEFINED CMAKE_INTERPROCEDURAL_OPTIMIZATION)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
endif()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

View File

@ -1,3 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.11641 7.99992L2.55835 12.558L3.44223 13.4419L8.00029 8.88381L12.5583 13.4419L13.4422 12.558L8.88417 7.99992L13.4422 3.44187L12.5583 2.55798L8.00029 7.11604L3.44223 2.55798L2.55835 3.44187L7.11641 7.99992Z" fill="#424242"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.11641 7.99992L2.55835 12.558L3.44223 13.4419L8.00029 8.88381L12.5583 13.4419L13.4422 12.558L8.88417 7.99992L13.4422 3.44187L12.5583 2.55798L8.00029 7.11604L3.44223 2.55798L2.55835 3.44187L7.11641 7.99992Z" fill="#000"/>
</svg>

Before

Width:  |  Height:  |  Size: 378 B

After

Width:  |  Height:  |  Size: 375 B

View File

@ -1,3 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.00024 3V13H13.0002V3H3.00024ZM12.0002 12H4.00024V4H12.0002V12Z" fill="#424242"/>
<path d="M3.00024 3V13H13.0002V3H3.00024ZM12.0002 12H4.00024V4H12.0002V12Z" fill="#000"/>
</svg>

Before

Width:  |  Height:  |  Size: 196 B

After

Width:  |  Height:  |  Size: 193 B

View File

@ -1,3 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.0002 7.99994V8.99994H3.00024V7.99994H14.0002Z" fill="#424242"/>
<path d="M14.0002 7.99994V8.99994H3.00024V7.99994H14.0002Z" fill="#000"/>
</svg>

Before

Width:  |  Height:  |  Size: 180 B

After

Width:  |  Height:  |  Size: 177 B

View File

@ -1,4 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.00024 5V14H12.0002V5H3.00024ZM11.0002 13H4.00024V6H11.0002V13Z" fill="#424242"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.00024 5H6.00024V4H13.0002V11H12.0002V12H14.0002V5V3H12.0002H5.00024V5Z" fill="#424242"/>
<path d="M3.00024 5V14H12.0002V5H3.00024ZM11.0002 13H4.00024V6H11.0002V13Z" fill="#000"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.00024 5H6.00024V4H13.0002V11H12.0002V12H14.0002V5V3H12.0002H5.00024V5Z" fill="#000"/>
</svg>

Before

Width:  |  Height:  |  Size: 337 B

After

Width:  |  Height:  |  Size: 331 B

View File

@ -1,3 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.1161 7.99992L2.55804 12.558L3.44193 13.4419L7.99999 8.88381L12.558 13.4419L13.4419 12.558L8.88387 7.99992L13.4419 3.44187L12.558 2.55798L7.99999 7.11604L3.44193 2.55798L2.55804 3.44187L7.1161 7.99992Z" fill="#C5C5C5"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.1161 7.99992L2.55804 12.558L3.44193 13.4419L7.99999 8.88381L12.558 13.4419L13.4419 12.558L8.88387 7.99992L13.4419 3.44187L12.558 2.55798L7.99999 7.11604L3.44193 2.55798L2.55804 3.44187L7.1161 7.99992Z" fill="#fff"/>
</svg>

Before

Width:  |  Height:  |  Size: 374 B

After

Width:  |  Height:  |  Size: 371 B

View File

@ -1,3 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 3V13H13V3H3ZM12 12H4V4H12V12Z" fill="#C5C5C5"/>
<path d="M3 3V13H13V3H3ZM12 12H4V4H12V12Z" fill="#fff"/>
</svg>

Before

Width:  |  Height:  |  Size: 163 B

After

Width:  |  Height:  |  Size: 160 B

View File

@ -1,3 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 7.99994V8.99994H3V7.99994H14Z" fill="#C5C5C5"/>
<path d="M14 7.99994V8.99994H3V7.99994H14Z" fill="#fff"/>
</svg>

Before

Width:  |  Height:  |  Size: 164 B

After

Width:  |  Height:  |  Size: 161 B

View File

@ -1,4 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 5V14H12V5H3ZM11 13H4V6H11V13Z" fill="#C5C5C5"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 5H6V4H13V11H12V12H14V5V3H12H5V5Z" fill="#C5C5C5"/>
<path d="M3 5V14H12V5H3ZM11 13H4V6H11V13Z" fill="#fff"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 5H6V4H13V11H12V12H14V5V3H12H5V5Z" fill="#fff"/>
</svg>

Before

Width:  |  Height:  |  Size: 266 B

After

Width:  |  Height:  |  Size: 260 B

View File

@ -92,8 +92,7 @@ void MainWindow::resetContentsMargins()
{
#ifdef Q_OS_WINDOWS
if (Utilities::isWin10OrGreater()) {
const int frameBorderThickness = 1;
setContentsMargins(0, frameBorderThickness, 0, 0);
setContentsMargins(0, 1, 0, 0);
}
#endif
}
@ -107,10 +106,9 @@ void MainWindow::paintEvent(QPaintEvent *event)
painter.save();
QPen pen = {};
pen.setColor(Utilities::getFrameBorderColor(isActiveWindow()));
const int frameBorderThickness = 1;
pen.setWidth(frameBorderThickness);
pen.setWidth(1);
painter.setPen(pen);
painter.drawLine(0, frameBorderThickness, width(), frameBorderThickness);
painter.drawLine(0, 0, width(), 0);
painter.restore();
}
#endif

View File

@ -24,6 +24,7 @@
#include <QtGui/qguiapplication.h>
#include <QtQml/qqmlapplicationengine.h>
#include <QtQuick/qquickwindow.h>
#include <QtQuickControls2/qquickstyle.h>
#include <framelessquickhelper.h>
@ -43,6 +44,14 @@ int main(int argc, char *argv[])
QGuiApplication application(argc, argv);
#ifdef Q_OS_WINDOWS
# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
QQuickWindow::setGraphicsApi(QSGRendererInterface::Direct3D11);
# elif (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Direct3D11Rhi);
# endif
#endif
QScopedPointer<FramelessQuickHelper> framelessHelper(new FramelessQuickHelper);
QScopedPointer<FramelessQuickUtils> framelessUtils(new FramelessQuickUtils);

View File

@ -44,7 +44,8 @@ Button {
Image {
anchors.centerIn: parent
source: FramelessUtils.darkModeEnabled ? "qrc:/images/light/chrome-close.svg" : "qrc:/images/dark/chrome-close.svg"
source: FramelessUtils.darkModeEnabled || FramelessUtils.titleBarColorVisible
? "qrc:/images/light/chrome-close.svg" : "qrc:/images/dark/chrome-close.svg"
}
}

View File

@ -46,9 +46,9 @@ Window {
Rectangle {
id: titleBar
height: 30
color: window.active ? (FramelessUtils.titleBarColorVisible ? FramelessUtils.systemAccentColor :
(FramelessUtils.darkModeEnabled ? "white" : "black")) :
(FramelessUtils.darkModeEnabled ? "#202020" : "white")
color: window.active ? (FramelessUtils.titleBarColorVisible ? FramelessUtils.systemAccentColor
: (FramelessUtils.darkModeEnabled ? "black" : "white"))
: (FramelessUtils.darkModeEnabled ? "#202020" : "white")
anchors {
top: parent.top
topMargin: windowTopBorder.height
@ -59,10 +59,11 @@ Window {
Text {
id: titleBarText
text: window.title
font.pointSize: 13
color: window.active ? (FramelessUtils.darkModeEnabled ? "white" : "black") : "darkGray"
font.pointSize: 11
color: window.active ? ((FramelessUtils.darkModeEnabled
|| FramelessUtils.titleBarColorVisible) ? "white" : "black") : "darkGray"
anchors.left: parent.left
anchors.leftMargin: 15
anchors.leftMargin: 10
anchors.verticalCenter: parent.verticalCenter
}

View File

@ -47,8 +47,10 @@ Button {
Image {
anchors.centerIn: parent
source: button.maximized ?
(FramelessUtils.darkModeEnabled ? "qrc:/images/light/chrome-restore.svg" : "qrc:/images/dark/chrome-restore.svg") :
(FramelessUtils.darkModeEnabled ? "qrc:/images/light/chrome-maximize.svg" : "qrc:/images/dark/chrome-maximize.svg")
(FramelessUtils.darkModeEnabled || FramelessUtils.titleBarColorVisible
? "qrc:/images/light/chrome-restore.svg" : "qrc:/images/dark/chrome-restore.svg") :
(FramelessUtils.darkModeEnabled || FramelessUtils.titleBarColorVisible
? "qrc:/images/light/chrome-maximize.svg" : "qrc:/images/dark/chrome-maximize.svg")
}
}

View File

@ -44,7 +44,8 @@ Button {
Image {
anchors.centerIn: parent
source: FramelessUtils.darkModeEnabled ? "qrc:/images/light/chrome-minimize.svg" : "qrc:/images/dark/chrome-minimize.svg"
source: FramelessUtils.darkModeEnabled || FramelessUtils.titleBarColorVisible
? "qrc:/images/light/chrome-minimize.svg" : "qrc:/images/dark/chrome-minimize.svg"
}
}

View File

@ -75,6 +75,12 @@ static const QString mainStyleSheet = QStringLiteral(R"(#MainWidget {
}
)");
[[nodiscard]] static inline bool isTitleBarColorized()
{
const DwmColorizationArea area = Utilities::getDwmColorizationArea();
return ((area == DwmColorizationArea::TitleBar_WindowBorder) || (area == DwmColorizationArea::All));
}
Widget::Widget(QWidget *parent) : QWidget(parent)
{
setAttribute(Qt::WA_DontCreateNativeAncestors);
@ -132,10 +138,9 @@ void Widget::paintEvent(QPaintEvent *event)
painter.save();
QPen pen = {};
pen.setColor(Utilities::getFrameBorderColor(isActiveWindow()));
const int frameBorderThickness = 1;
pen.setWidth(frameBorderThickness);
pen.setWidth(1);
painter.setPen(pen);
painter.drawLine(0, frameBorderThickness, width(), frameBorderThickness);
painter.drawLine(0, 0, width(), 0);
painter.restore();
}
#endif
@ -285,14 +290,11 @@ void Widget::updateStyleSheet()
{
const bool active = isActiveWindow();
const bool dark = Utilities::shouldAppsUseDarkMode();
const DwmColorizationArea area = Utilities::getDwmColorizationArea();
const bool colorizedTitleBar = ((area == DwmColorizationArea::TitleBar_WindowBorder) || (area == DwmColorizationArea::All));
const QColor colorizationColor = Utilities::getDwmColorizationColor();
const QColor mainWidgetBackgroundColor = (dark ? systemDarkColor : systemLightColor);
const QColor titleBarWidgetBackgroundColor = [active, colorizedTitleBar, &colorizationColor, dark]() -> QColor {
const bool colorizedTitleBar = isTitleBarColorized();
const QColor titleBarWidgetBackgroundColor = [active, colorizedTitleBar, dark]() -> QColor {
if (active) {
if (colorizedTitleBar) {
return colorizationColor;
return Utilities::getDwmColorizationColor();
} else {
if (dark) {
return QColor(Qt::black);
@ -308,8 +310,9 @@ void Widget::updateStyleSheet()
}
}
}();
const QColor windowTitleLabelTextColor = (active ? (dark ? Qt::white : Qt::black) : Qt::darkGray);
const QColor windowTitleLabelTextColor = (active ? ((dark || colorizedTitleBar) ? Qt::white : Qt::black) : Qt::darkGray);
const QColor clockLabelTextColor = (dark ? Qt::white : Qt::black);
const QColor mainWidgetBackgroundColor = (dark ? systemDarkColor : systemLightColor);
setStyleSheet(mainStyleSheet.arg(mainWidgetBackgroundColor.name(), titleBarWidgetBackgroundColor.name(),
windowTitleLabelTextColor.name(), clockLabelTextColor.name()));
update();
@ -317,7 +320,7 @@ void Widget::updateStyleSheet()
void Widget::updateSystemButtonIcons()
{
const QString prefix = (Utilities::shouldAppsUseDarkMode() ? QStringLiteral("light") : QStringLiteral("dark"));
const QString prefix = ((Utilities::shouldAppsUseDarkMode() || isTitleBarColorized()) ? QStringLiteral("light") : QStringLiteral("dark"));
m_minimizeButton->setIcon(QIcon(QStringLiteral(":/images/%1/chrome-minimize.svg").arg(prefix)));
if (isMaximized() || isFullScreen()) {
m_maximizeButton->setIcon(QIcon(QStringLiteral(":/images/%1/chrome-restore.svg").arg(prefix)));
@ -331,8 +334,7 @@ void Widget::resetContentsMargins()
{
#ifdef Q_OS_WINDOWS
if (Utilities::isWin10OrGreater()) {
const int frameBorderThickness = 1;
setContentsMargins(0, frameBorderThickness, 0, 0);
setContentsMargins(0, 1, 0, 0);
}
#endif
}

View File

@ -24,6 +24,7 @@
#include "framelesshelper_win32.h"
#include <QtCore/qdebug.h>
#include <QtCore/qhash.h>
#include <QtCore/qmutex.h>
#include <QtCore/qvariant.h>
#include <QtCore/qcoreapplication.h>
@ -39,6 +40,8 @@ struct FramelessHelperWinData
{
QMutex mutex = {};
QScopedPointer<FramelessHelperWin> instance;
QList<WId> acceptableWinIds = {};
QHash<HWND, WNDPROC> qtWindowProcs = {};
explicit FramelessHelperWinData() = default;
~FramelessHelperWinData() = default;
@ -49,6 +52,127 @@ private:
Q_GLOBAL_STATIC(FramelessHelperWinData, g_helper)
[[nodiscard]] static inline LRESULT CALLBACK HookWindowProc
(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam)
{
g_helper()->mutex.lock();
if (!g_helper()->qtWindowProcs.contains(hWnd)) {
g_helper()->mutex.unlock();
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
g_helper()->mutex.unlock();
const auto winId = reinterpret_cast<WId>(hWnd);
const auto getGlobalPosFromMouse = [lParam]() -> QPointF {
return {qreal(GET_X_LPARAM(lParam)), qreal(GET_Y_LPARAM(lParam))};
};
const auto getGlobalPosFromKeyboard = [hWnd, winId]() -> QPointF {
RECT rect = {};
if (GetWindowRect(hWnd, &rect) == FALSE) {
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("GetWindowRect"));
return {};
}
const bool maxOrFull = (IsMaximized(hWnd) || Utilities::isFullScreen(winId));
const int frameSizeX = Utilities::getResizeBorderThickness(winId, true, true);
const int frameSizeY = Utilities::getResizeBorderThickness(winId, false, true);
const int titleBarHeight = Utilities::getTitleBarHeight(winId, true);
const int horizontalOffset = (maxOrFull ? 0 : frameSizeX);
const int verticalOffset = (maxOrFull ? titleBarHeight : (titleBarHeight - frameSizeY));
return {qreal(rect.left + horizontalOffset), qreal(rect.top + verticalOffset)};
};
bool shouldShowSystemMenu = false;
QPointF globalPos = {};
if (uMsg == WM_NCRBUTTONUP) {
if (wParam == HTCAPTION) {
shouldShowSystemMenu = true;
globalPos = getGlobalPosFromMouse();
}
} else if (uMsg == WM_SYSCOMMAND) {
const WPARAM filteredWParam = (wParam & 0xFFF0);
if ((filteredWParam == SC_KEYMENU) && (lParam == VK_SPACE)) {
shouldShowSystemMenu = true;
globalPos = getGlobalPosFromKeyboard();
}
} else if ((uMsg == WM_KEYDOWN) || (uMsg == WM_SYSKEYDOWN)) {
const bool altPressed = ((wParam == VK_MENU) || (GetKeyState(VK_MENU) < 0));
const bool spacePressed = ((wParam == VK_SPACE) || (GetKeyState(VK_SPACE) < 0));
if (altPressed && spacePressed) {
shouldShowSystemMenu = true;
globalPos = getGlobalPosFromKeyboard();
}
}
if (shouldShowSystemMenu) {
Utilities::showSystemMenu(winId, globalPos);
// QPA's internal code will handle system menu events separately, and its
// behavior is not what we would want to see because it doesn't know our
// window doesn't have any window frame now, so return early here to avoid
// entering Qt's own handling logic.
return 0; // Return 0 means we have handled this event.
}
g_helper()->mutex.lock();
const WNDPROC originalWindowProc = g_helper()->qtWindowProcs.value(hWnd);
g_helper()->mutex.unlock();
Q_ASSERT(originalWindowProc);
if (originalWindowProc) {
// Hand over to Qt's original window proc function for events we are not
// interested in.
return CallWindowProcW(originalWindowProc, hWnd, uMsg, wParam, lParam);
} else {
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
}
[[nodiscard]] static inline bool installWindowHook(const WId winId)
{
Q_ASSERT(winId);
if (!winId) {
return false;
}
const auto hwnd = reinterpret_cast<HWND>(winId);
QMutexLocker locker(&g_helper()->mutex);
if (g_helper()->qtWindowProcs.contains(hwnd)) {
return false;
}
SetLastError(ERROR_SUCCESS);
const auto originalWindowProc = reinterpret_cast<WNDPROC>(GetWindowLongPtrW(hwnd, GWLP_WNDPROC));
Q_ASSERT(originalWindowProc);
if (!originalWindowProc) {
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("GetWindowLongPtrW"));
return false;
}
SetLastError(ERROR_SUCCESS);
if (SetWindowLongPtrW(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(HookWindowProc)) == 0) {
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
return false;
}
g_helper()->qtWindowProcs.insert(hwnd, originalWindowProc);
return true;
}
[[nodiscard]] static inline bool uninstallWindowHook(const WId winId)
{
Q_ASSERT(winId);
if (!winId) {
return false;
}
const auto hwnd = reinterpret_cast<HWND>(winId);
QMutexLocker locker(&g_helper()->mutex);
if (!g_helper()->qtWindowProcs.contains(hwnd)) {
return false;
}
const WNDPROC originalWindowProc = g_helper()->qtWindowProcs.value(hwnd);
Q_ASSERT(originalWindowProc);
if (!originalWindowProc) {
return false;
}
SetLastError(ERROR_SUCCESS);
if (SetWindowLongPtrW(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(originalWindowProc)) == 0) {
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
return false;
}
g_helper()->qtWindowProcs.remove(hwnd);
return true;
}
FramelessHelperWin::FramelessHelperWin() : QAbstractNativeEventFilter() {}
FramelessHelperWin::~FramelessHelperWin()
@ -62,17 +186,26 @@ void FramelessHelperWin::addWindow(QWindow *window)
if (!window) {
return;
}
QMutexLocker locker(&g_helper()->mutex);
const WId winId = window->winId();
g_helper()->mutex.lock();
if (g_helper()->acceptableWinIds.contains(winId)) {
g_helper()->mutex.unlock();
return;
}
g_helper()->acceptableWinIds.append(winId);
if (g_helper()->instance.isNull()) {
g_helper()->instance.reset(new FramelessHelperWin);
qApp->installNativeEventFilter(g_helper()->instance.data());
}
const WId winId = window->winId();
g_helper()->mutex.unlock();
Utilities::fixupQtInternals(winId);
Utilities::updateInternalWindowFrameMargins(window, true);
Utilities::updateWindowFrameMargins(winId, false);
const bool dark = Utilities::shouldAppsUseDarkMode();
Utilities::updateWindowFrameBorderColor(winId, dark);
if (!installWindowHook(winId)) {
qWarning() << "Failed to hook the window proc function.";
}
}
void FramelessHelperWin::removeWindow(QWindow *window)
@ -81,8 +214,18 @@ void FramelessHelperWin::removeWindow(QWindow *window)
if (!window) {
return;
}
const WId winId = window->winId();
g_helper()->mutex.lock();
if (!g_helper()->acceptableWinIds.contains(winId)) {
g_helper()->mutex.unlock();
return;
}
g_helper()->mutex.unlock();
if (!uninstallWindowHook(winId)) {
qWarning() << "Failed to un-hook the window proc function.";
}
Utilities::updateInternalWindowFrameMargins(window, false);
Utilities::updateWindowFrameMargins(window->winId(), true);
Utilities::updateWindowFrameMargins(winId, true);
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
@ -106,8 +249,15 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
return false;
}
const WId winId = reinterpret_cast<WId>(msg->hwnd);
g_helper()->mutex.lock();
if (!g_helper()->acceptableWinIds.contains(winId)) {
g_helper()->mutex.unlock();
return false;
}
g_helper()->mutex.unlock();
const FramelessManagerPrivate * const manager = FramelessManagerPrivate::instance();
const QUuid id = manager->findIdByWinId(winId);
Q_ASSERT(!id.isNull());
if (id.isNull()) {
return false;
}

View File

@ -24,6 +24,7 @@
#include "utilities.h"
#include <QtCore/qdebug.h>
#include <QtGui/qguiapplication.h>
#include <QtCore/private/qsystemlibrary_p.h>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
# include <QtCore/qoperatingsystemversion.h>
@ -32,7 +33,6 @@
#endif
#include <QtGui/qpa/qplatformwindow.h>
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
# include <QtGui/qguiapplication.h>
# include <QtGui/qpa/qplatformnativeinterface.h>
#else
# include <QtGui/qpa/qplatformwindow_p.h>
@ -396,39 +396,41 @@ void Utilities::showSystemMenu(const WId winId, const QPointF &pos)
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STATE;
mii.fType = MFT_STRING;
const auto setState = [&mii, menu](const UINT item, const bool enabled) -> bool {
mii.fState = (enabled ? MF_ENABLED : MF_DISABLED);
const auto setState = [&mii, menu](const UINT item, const bool enabled, const bool highlight) -> bool {
mii.fState = ((enabled ? MFS_ENABLED : MFS_DISABLED) | (highlight ? MFS_HILITE : 0));
if (SetMenuItemInfoW(menu, item, FALSE, &mii) == FALSE) {
Q_ASSERT(false);
qWarning() << getSystemErrorMessage(QStringLiteral("SetMenuItemInfoW"));
return false;
}
return true;
};
const bool max = IsMaximized(hWnd);
if (!setState(SC_RESTORE, max)) {
const bool maxOrFull = (IsMaximized(hWnd) || isFullScreen(reinterpret_cast<WId>(hWnd)));
if (!setState(SC_RESTORE, maxOrFull, true)) {
return;
}
if (!setState(SC_MOVE, !max)) {
if (!setState(SC_MOVE, !maxOrFull, false)) {
return;
}
if (!setState(SC_SIZE, !max)) {
if (!setState(SC_SIZE, !maxOrFull, false)) {
return;
}
if (!setState(SC_MINIMIZE, true)) {
if (!setState(SC_MINIMIZE, true, false)) {
return;
}
if (!setState(SC_MAXIMIZE, !max)) {
if (!setState(SC_MAXIMIZE, !maxOrFull, false)) {
return;
}
if (!setState(SC_CLOSE, true)) {
if (!setState(SC_CLOSE, true, false)) {
return;
}
if (SetMenuDefaultItem(menu, UINT_MAX, FALSE) == FALSE) {
if (SetMenuDefaultItem(menu, SC_CLOSE, FALSE) == FALSE) {
qWarning() << getSystemErrorMessage(QStringLiteral("SetMenuDefaultItem"));
return;
}
const QPoint roundedPos = pos.toPoint();
const auto ret = TrackPopupMenu(menu, TPM_RETURNCMD, roundedPos.x(), roundedPos.y(), 0, hWnd, nullptr);
const auto ret = TrackPopupMenu(menu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft()
? TPM_RIGHTALIGN : TPM_LEFTALIGN)), roundedPos.x(), roundedPos.y(), 0, hWnd, nullptr);
if (ret != 0) {
if (PostMessageW(hWnd, WM_SYSCOMMAND, ret, 0) == FALSE) {
qWarning() << getSystemErrorMessage(QStringLiteral("PostMessageW"));
@ -730,7 +732,7 @@ QColor Utilities::getFrameBorderColor(const bool active)
return (dark ? QColor(QStringLiteral("#4d4d4d")) : QColor(Qt::white));
}
} else {
return (dark ? QColor(QStringLiteral("#575959")) : QColor(QStringLiteral("#999999")));
return (dark ? QColor(QStringLiteral("#575959")) : QColor(QStringLiteral("#b3b3b3")));
}
}