forked from github_mirror/framelesshelper
some wip code
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
b5d2ae5888
commit
e19dad5b82
|
@ -3,6 +3,7 @@
|
|||
## Highlights compared to 1.x
|
||||
|
||||
- Windows: Gained the ability to only remove the title bar but preserve the window frame at the same time.
|
||||
- Windows: Support the maximize button docking feature introduced in Windows 11.
|
||||
- Windows: The flicker and jitter during window resizing is completely gone.
|
||||
- Windows: The system menu will be opened if you right-click on your custom title bar.
|
||||
- Windows: Replaced Qt's original system menu with FramelessHelper's homemade one, which looks a lot better than the original one.
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
|
||||
static void addWindow(const Global::UserSettings &settings, const Global::SystemParameters ¶ms);
|
||||
|
||||
Q_NODISCARD bool nativeEventFilter(const QByteArray &eventType, void *message, NATIVE_EVENT_RESULT_TYPE *result) override;
|
||||
Q_NODISCARD bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
|
||||
};
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <uxtheme.h>
|
||||
#include <shellapi.h>
|
||||
#include <dwmapi.h>
|
||||
|
||||
|
@ -188,10 +189,12 @@ GetDpiForMonitor(
|
|||
|
||||
[[maybe_unused]] static constexpr const int kAutoHideTaskBarThickness = 2; // The thickness of an auto-hide taskbar in pixels.
|
||||
|
||||
[[maybe_unused]] static constexpr const char kDwmRegistryKey[] = R"(Software\Microsoft\Windows\DWM)";
|
||||
[[maybe_unused]] static constexpr const char kPersonalizeRegistryKey[] = R"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)";
|
||||
[[maybe_unused]] static constexpr const char kThemeSettingChangeEventName[] = "ImmersiveColorSet";
|
||||
[[maybe_unused]] static constexpr const char kDwmColorKeyName[] = "ColorPrevalence";
|
||||
[[maybe_unused]] static constexpr const wchar_t kDwmRegistryKey[] = LR"(Software\Microsoft\Windows\DWM)";
|
||||
[[maybe_unused]] static constexpr const wchar_t kPersonalizeRegistryKey[] = LR"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)";
|
||||
[[maybe_unused]] static constexpr const wchar_t kThemeSettingChangeEventName[] = L"ImmersiveColorSet";
|
||||
[[maybe_unused]] static constexpr const wchar_t kDwmColorKeyName[] = L"ColorPrevalence";
|
||||
[[maybe_unused]] static constexpr const wchar_t kSystemDarkThemeResourceName[] = L"DarkMode_Explorer";
|
||||
[[maybe_unused]] static constexpr const wchar_t kSystemLightThemeResourceName[] = L"Explorer";
|
||||
|
||||
[[maybe_unused]] static constexpr const DWORD _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19;
|
||||
[[maybe_unused]] static constexpr const DWORD _DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <QtCore/qpointer.h>
|
||||
#include <QtGui/qcolor.h>
|
||||
#include <QtGui/qwindowdefs.h>
|
||||
#include <functional>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QScreen;
|
||||
|
@ -80,10 +81,12 @@ QT_END_NAMESPACE
|
|||
# define Q_NODISCARD
|
||||
#endif
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
using NATIVE_EVENT_RESULT_TYPE = qintptr;
|
||||
#else
|
||||
using NATIVE_EVENT_RESULT_TYPE = long;
|
||||
#ifndef QT_NATIVE_EVENT_RESULT_TYPE
|
||||
# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
# define QT_NATIVE_EVENT_RESULT_TYPE qintptr
|
||||
# else
|
||||
# define QT_NATIVE_EVENT_RESULT_TYPE long
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef QUtf8String
|
||||
|
@ -158,16 +161,15 @@ Q_NAMESPACE_EXPORT(FRAMELESSHELPER_CORE_API)
|
|||
|
||||
[[maybe_unused]] static constexpr const QColor kDefaultBlackColor = {0, 0, 0}; // #000000
|
||||
[[maybe_unused]] static constexpr const QColor kDefaultWhiteColor = {255, 255, 255}; // #FFFFFF
|
||||
[[maybe_unused]] static constexpr const QColor kDefaultTransparentColor = {0, 0, 0, 0};
|
||||
[[maybe_unused]] static constexpr const QColor kDefaultDarkGrayColor = {169, 169, 169}; // #A9A9A9
|
||||
[[maybe_unused]] static constexpr const QColor kDefaultSystemLightColor = {240, 240, 240}; // #F0F0F0
|
||||
[[maybe_unused]] static constexpr const QColor kDefaultSystemDarkColor = {32, 32, 32}; // #202020
|
||||
[[maybe_unused]] static constexpr const QColor kDefaultFrameBorderActiveColor = {77, 77, 77}; // #4D4D4D
|
||||
[[maybe_unused]] static constexpr const QColor kDefaultFrameBorderInactiveColorDark = {87, 89, 89}; // #575959
|
||||
[[maybe_unused]] static constexpr const QColor kDefaultFrameBorderInactiveColorLight = {166, 166, 166}; // #A6A6A6
|
||||
[[maybe_unused]] static constexpr const QColor kDefaultSystemButtonHoverColor = {204, 204, 204}; // #CCCCCC
|
||||
[[maybe_unused]] static constexpr const QColor kDefaultSystemButtonPressColor = {179, 179, 179}; // #B3B3B3
|
||||
[[maybe_unused]] static constexpr const QColor kDefaultSystemCloseButtonHoverColor = {232, 17, 35}; // #E81123
|
||||
[[maybe_unused]] static constexpr const QColor kDefaultSystemCloseButtonPressColor = {241, 112, 122}; // #F1707A
|
||||
[[maybe_unused]] static constexpr const QColor kDefaultSystemButtonBackgroundColor = {204, 204, 204}; // #CCCCCC
|
||||
[[maybe_unused]] static constexpr const QColor kDefaultSystemCloseButtonBackgroundColor = {232, 17, 35}; // #E81123
|
||||
|
||||
[[maybe_unused]] static constexpr const QSize kDefaultSystemButtonSize = {int(qRound(qreal(kDefaultTitleBarHeight) * 1.5)), kDefaultTitleBarHeight};
|
||||
[[maybe_unused]] static constexpr const QSize kDefaultSystemButtonIconSize = {16, 16};
|
||||
|
@ -191,7 +193,7 @@ enum class Option : int
|
|||
DontDrawTopWindowFrameBorder = 0x00000004, // Windows only, don't draw the top window frame border even if the window frame border is visible.
|
||||
EnableRoundedWindowCorners = 0x00000008, // Not implemented yet.
|
||||
TransparentWindowBackground = 0x00000010, // Not implemented yet.
|
||||
MaximizeButtonDocking = 0x00000020, // Windows only, enable the window docking feature introduced in Windows 11.
|
||||
MaximizeButtonDocking = 0x00000020, // Not implemented yet.
|
||||
CreateStandardWindowLayout = 0x00000040, // Using this option will cause FramelessHelper create a homemade titlebar and a window layout to contain it. If your window has a layout already, the newly created layout will mess up your own layout.
|
||||
BeCompatibleWithQtFramelessWindowHint = 0x00000080, // Windows only, make the code compatible with Qt::FramelessWindowHint. Don't use this option unless you really need that flag.
|
||||
DontTouchQtInternals = 0x00000100, // Windows only, don't modify Qt's internal data.
|
||||
|
@ -207,7 +209,8 @@ enum class Option : int
|
|||
DontTouchHighDpiScalingPolicy = 0x00040000, // Don't change Qt's default high DPI scaling policy. Qt5 default: disabled, Qt6 default: enabled.
|
||||
DontTouchScaleFactorRoundingPolicy = 0x00080000, // Don't change Qt's default scale factor rounding policy. Qt5 default: round, Qt6 default: pass through.
|
||||
DontTouchProcessDpiAwarenessLevel = 0x00100000, // Windows only, don't change the current process's DPI awareness level.
|
||||
DontEnsureNonNativeWidgetSiblings = 0x00200000 // Don't ensure that siblings of native widgets stay non-native.
|
||||
DontEnsureNonNativeWidgetSiblings = 0x00200000, // Don't ensure that siblings of native widgets stay non-native.
|
||||
SyncNativeControlsThemeWithSystem = 0x00400000 // Windows only, sync the native Win32 controls' theme with system theme.
|
||||
};
|
||||
Q_ENUM_NS(Option)
|
||||
Q_DECLARE_FLAGS(Options, Option)
|
||||
|
@ -264,6 +267,15 @@ enum class Anchor : int
|
|||
};
|
||||
Q_ENUM_NS(Anchor)
|
||||
|
||||
enum class ButtonState : int
|
||||
{
|
||||
Unspecified = -1,
|
||||
Hovered = 0,
|
||||
Pressed = 1,
|
||||
Released = 2
|
||||
};
|
||||
Q_ENUM_NS(ButtonState)
|
||||
|
||||
using GetWindowFlagsCallback = std::function<Qt::WindowFlags()>;
|
||||
using SetWindowFlagsCallback = std::function<void(const Qt::WindowFlags)>;
|
||||
|
||||
|
@ -298,6 +310,8 @@ struct UserSettings
|
|||
Qt::WindowState startupState = Qt::WindowNoState;
|
||||
Options options = {};
|
||||
QPoint systemMenuOffset = {};
|
||||
QPointer<QObject> windowIconButton = nullptr;
|
||||
QPointer<QObject> contextHelpButton = nullptr;
|
||||
QPointer<QObject> minimizeButton = nullptr;
|
||||
QPointer<QObject> maximizeButton = nullptr;
|
||||
QPointer<QObject> closeButton = nullptr;
|
||||
|
|
|
@ -52,12 +52,16 @@ FRAMELESSHELPER_CORE_API void moveWindowToDesktopCenter(
|
|||
[[nodiscard]] FRAMELESSHELPER_CORE_API Global::SystemTheme getSystemTheme();
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API Qt::WindowState windowStatesToWindowState(
|
||||
const Qt::WindowStates states);
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isThemeChangeEvent(const QEvent * const event);
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor calculateSystemButtonBackgroundColor(
|
||||
const Global::SystemButtonType button, const Global::ButtonState state);
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWin8OrGreater();
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWin8Point1OrGreater();
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWin10OrGreater();
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWin101607OrGreater();
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWin101809OrGreater();
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWin11OrGreater();
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isDwmCompositionEnabled();
|
||||
FRAMELESSHELPER_CORE_API void triggerFrameChange(const WId windowId);
|
||||
|
@ -106,6 +110,7 @@ FRAMELESSHELPER_CORE_API void tryToBeCompatibleWithQtFramelessWindowHint(
|
|||
const bool enable);
|
||||
FRAMELESSHELPER_CORE_API void setAeroSnappingEnabled(const WId windowId, const bool enable);
|
||||
FRAMELESSHELPER_CORE_API void tryToEnableHighestDpiAwarenessLevel();
|
||||
FRAMELESSHELPER_CORE_API void updateGlobalWin32ControlsTheme(const WId windowId, const bool dark);
|
||||
#endif // Q_OS_WINDOWS
|
||||
|
||||
} // namespace Utils
|
||||
|
|
|
@ -54,10 +54,8 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickUtils : public QObject
|
|||
Q_PROPERTY(QColor defaultSystemDarkColor READ defaultSystemDarkColor CONSTANT FINAL)
|
||||
Q_PROPERTY(QSizeF defaultSystemButtonSize READ defaultSystemButtonSize CONSTANT FINAL)
|
||||
Q_PROPERTY(QSizeF defaultSystemButtonIconSize READ defaultSystemButtonIconSize CONSTANT FINAL)
|
||||
Q_PROPERTY(QColor defaultSystemButtonHoverColor READ defaultSystemButtonHoverColor CONSTANT FINAL)
|
||||
Q_PROPERTY(QColor defaultSystemButtonPressColor READ defaultSystemButtonPressColor CONSTANT FINAL)
|
||||
Q_PROPERTY(QColor defaultSystemCloseButtonHoverColor READ defaultSystemCloseButtonHoverColor CONSTANT FINAL)
|
||||
Q_PROPERTY(QColor defaultSystemCloseButtonPressColor READ defaultSystemCloseButtonPressColor CONSTANT FINAL)
|
||||
Q_PROPERTY(QColor defaultSystemButtonBackgroundColor READ defaultSystemButtonBackgroundColor CONSTANT FINAL)
|
||||
Q_PROPERTY(QColor defaultSystemCloseButtonBackgroundColor READ defaultSystemCloseButtonBackgroundColor CONSTANT FINAL)
|
||||
|
||||
public:
|
||||
explicit FramelessQuickUtils(QObject *parent = nullptr);
|
||||
|
@ -73,10 +71,11 @@ public:
|
|||
Q_NODISCARD static QColor defaultSystemDarkColor();
|
||||
Q_NODISCARD static QSizeF defaultSystemButtonSize();
|
||||
Q_NODISCARD static QSizeF defaultSystemButtonIconSize();
|
||||
Q_NODISCARD static QColor defaultSystemButtonHoverColor();
|
||||
Q_NODISCARD static QColor defaultSystemButtonPressColor();
|
||||
Q_NODISCARD static QColor defaultSystemCloseButtonHoverColor();
|
||||
Q_NODISCARD static QColor defaultSystemCloseButtonPressColor();
|
||||
Q_NODISCARD static QColor defaultSystemButtonBackgroundColor();
|
||||
Q_NODISCARD static QColor defaultSystemCloseButtonBackgroundColor();
|
||||
|
||||
Q_NODISCARD Q_INVOKABLE static QColor getSystemButtonBackgroundColor(
|
||||
const Global::SystemButtonType button, const Global::ButtonState state);
|
||||
|
||||
Q_SIGNALS:
|
||||
void darkModeEnabledChanged();
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#include <standardsystembutton.h>
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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
|
|
@ -26,6 +26,7 @@
|
|||
#include <QtCore/qmutex.h>
|
||||
#include <QtGui/qevent.h>
|
||||
#include <QtGui/qwindow.h>
|
||||
#include "framelesswindowsmanager.h"
|
||||
#include "utils.h"
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
@ -81,6 +82,12 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
|||
if (!object || !event) {
|
||||
return false;
|
||||
}
|
||||
// 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)) {
|
||||
Q_EMIT FramelessWindowsManager::instance()->systemThemeChanged();
|
||||
return false;
|
||||
}
|
||||
// Only monitor window events.
|
||||
if (!object->isWindowType()) {
|
||||
return false;
|
||||
|
|
|
@ -41,6 +41,7 @@ struct Win32HelperData
|
|||
{
|
||||
UserSettings settings = {};
|
||||
SystemParameters params = {};
|
||||
UINT lastMessage = 0;
|
||||
};
|
||||
|
||||
struct Win32Helper
|
||||
|
@ -53,7 +54,7 @@ struct Win32Helper
|
|||
Q_GLOBAL_STATIC(Win32Helper, g_win32Helper)
|
||||
|
||||
FRAMELESSHELPER_BYTEARRAY_CONSTANT2(Win32MessageTypeName, "windows_generic_MSG")
|
||||
static const QString qThemeSettingChangeEventName = QUtf8String(kThemeSettingChangeEventName);
|
||||
static const QString qThemeSettingChangeEventName = QString::fromWCharArray(kThemeSettingChangeEventName);
|
||||
FRAMELESSHELPER_STRING_CONSTANT(MonitorFromWindow)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(GetMonitorInfoW)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(ScreenToClient)
|
||||
|
@ -96,13 +97,20 @@ void FramelessHelperWin::addWindow(const UserSettings &settings, const SystemPar
|
|||
}
|
||||
Utils::updateInternalWindowFrameMargins(params.getWindowHandle(), true);
|
||||
Utils::updateWindowFrameMargins(params.windowId, false);
|
||||
if (!(settings.options & Option::DontTouchWindowFrameBorderColor)) {
|
||||
if (Utils::isWin101607OrGreater()) {
|
||||
const bool dark = Utils::shouldAppsUseDarkMode();
|
||||
Utils::updateWindowFrameBorderColor(params.windowId, dark);
|
||||
if (!(settings.options & Option::DontTouchWindowFrameBorderColor)) {
|
||||
Utils::updateWindowFrameBorderColor(params.windowId, dark);
|
||||
}
|
||||
if (Utils::isWin101809OrGreater()) {
|
||||
if (settings.options & Option::SyncNativeControlsThemeWithSystem) {
|
||||
Utils::updateGlobalWin32ControlsTheme(params.windowId, dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *message, NATIVE_EVENT_RESULT_TYPE *result)
|
||||
bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result)
|
||||
{
|
||||
if ((eventType != kWin32MessageTypeName) || !message || !result) {
|
||||
return false;
|
||||
|
@ -126,6 +134,8 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
|||
return false;
|
||||
}
|
||||
const Win32HelperData data = g_win32Helper()->data.value(windowId);
|
||||
const UINT uMsg = msg->message;
|
||||
g_win32Helper()->data[windowId].lastMessage = uMsg;
|
||||
g_win32Helper()->mutex.unlock();
|
||||
const bool frameBorderVisible = [&data]() -> bool {
|
||||
if (data.settings.options & Option::ForceShowWindowFrameBorder) {
|
||||
|
@ -136,9 +146,133 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
|||
}
|
||||
return Utils::isWindowFrameBorderVisible();
|
||||
}();
|
||||
const UINT uMsg = msg->message;
|
||||
const WPARAM wParam = msg->wParam;
|
||||
const LPARAM lParam = msg->lParam;
|
||||
#if 0
|
||||
const bool isNonClientMouseEvent = (((uMsg >= WM_NCMOUSEMOVE) && (uMsg <= WM_NCMBUTTONDBLCLK))
|
||||
|| (uMsg == WM_NCHITTEST));
|
||||
const bool isClientMouseEvent = (((uMsg >= WM_MOUSEFIRST) && (uMsg <= WM_MOUSELAST))
|
||||
|| ((uMsg >= WM_XBUTTONDOWN) && (uMsg <= WM_XBUTTONDBLCLK)));
|
||||
const bool isMouseEvent = (isNonClientMouseEvent || isClientMouseEvent);
|
||||
if ((data.settings.options & Option::MaximizeButtonDocking) && isMouseEvent) {
|
||||
POINT nativeScreenPos = {};
|
||||
POINT nativeClientPos = {};
|
||||
if (isNonClientMouseEvent) {
|
||||
nativeScreenPos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
|
||||
nativeClientPos = nativeScreenPos;
|
||||
ScreenToClient(hWnd, &nativeClientPos);
|
||||
}
|
||||
if (isClientMouseEvent) {
|
||||
nativeClientPos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
|
||||
nativeScreenPos = nativeClientPos;
|
||||
ClientToScreen(hWnd, &nativeScreenPos);
|
||||
}
|
||||
const LPARAM screenPosLParam = MAKELPARAM(nativeScreenPos.x, nativeScreenPos.y);
|
||||
const LPARAM clientPosLParam = MAKELPARAM(nativeClientPos.x, nativeClientPos.y);
|
||||
const qreal devicePixelRatio = data.params.getWindowDevicePixelRatio();
|
||||
const QPoint qtScenePos = QPointF(QPointF(qreal(nativeClientPos.x),
|
||||
qreal(nativeClientPos.y)) / devicePixelRatio).toPoint();
|
||||
SystemButtonType systemButton = SystemButtonType::Unknown;
|
||||
if (data.params.isInsideSystemButtons(qtScenePos, &systemButton)) {
|
||||
const int hitTestResult = [systemButton]() -> int {
|
||||
switch (systemButton) {
|
||||
case SystemButtonType::WindowIcon:
|
||||
return HTSYSMENU;
|
||||
case SystemButtonType::Help:
|
||||
return HTHELP;
|
||||
case SystemButtonType::Minimize:
|
||||
return HTREDUCE;
|
||||
case SystemButtonType::Maximize:
|
||||
case SystemButtonType::Restore:
|
||||
return HTZOOM;
|
||||
case SystemButtonType::Close:
|
||||
return HTCLOSE;
|
||||
case SystemButtonType::Unknown:
|
||||
return HTCAPTION;
|
||||
}
|
||||
return 0;
|
||||
}();
|
||||
Q_ASSERT(hitTestResult);
|
||||
if ((uMsg == WM_NCHITTEST) && (hitTestResult != 0)) {
|
||||
*result = hitTestResult;
|
||||
return true;
|
||||
}
|
||||
if ((uMsg == WM_MOUSEMOVE) || (uMsg == WM_NCMOUSEMOVE)) {
|
||||
bool translated = false;
|
||||
switch (data.lastMessage) {
|
||||
case WM_NCLBUTTONDOWN: {
|
||||
PostMessageW(hWnd, WM_NCLBUTTONUP, hitTestResult, screenPosLParam);
|
||||
translated = true;
|
||||
} break;
|
||||
case WM_NCMBUTTONDOWN: {
|
||||
PostMessageW(hWnd, WM_NCMBUTTONUP, hitTestResult, screenPosLParam);
|
||||
translated = true;
|
||||
} break;
|
||||
case WM_NCRBUTTONDOWN: {
|
||||
PostMessageW(hWnd, WM_NCRBUTTONUP, hitTestResult, screenPosLParam);
|
||||
translated = true;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (translated) {
|
||||
*result = 0;
|
||||
return true;
|
||||
}
|
||||
if (uMsg == WM_NCMOUSEMOVE) {
|
||||
PostMessageW(hWnd, WM_MOUSEMOVE, 0, clientPosLParam);
|
||||
*result = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bool translated = false;
|
||||
switch (uMsg) {
|
||||
case WM_NCLBUTTONDOWN: {
|
||||
PostMessageW(hWnd, WM_LBUTTONDOWN, 0, clientPosLParam);
|
||||
translated = true;
|
||||
} break;
|
||||
case WM_NCLBUTTONUP: {
|
||||
PostMessageW(hWnd, WM_LBUTTONUP, 0, clientPosLParam);
|
||||
translated = true;
|
||||
} break;
|
||||
case WM_NCLBUTTONDBLCLK: {
|
||||
PostMessageW(hWnd, WM_LBUTTONDBLCLK, 0, clientPosLParam);
|
||||
translated = true;
|
||||
} break;
|
||||
case WM_NCMBUTTONDOWN: {
|
||||
PostMessageW(hWnd, WM_MBUTTONDOWN, 0, clientPosLParam);
|
||||
translated = true;
|
||||
} break;
|
||||
case WM_NCMBUTTONUP: {
|
||||
PostMessageW(hWnd, WM_MBUTTONUP, 0, clientPosLParam);
|
||||
translated = true;
|
||||
} break;
|
||||
case WM_NCMBUTTONDBLCLK: {
|
||||
PostMessageW(hWnd, WM_MBUTTONDBLCLK, 0, clientPosLParam);
|
||||
translated = true;
|
||||
} break;
|
||||
case WM_NCRBUTTONDOWN: {
|
||||
PostMessageW(hWnd, WM_RBUTTONDOWN, 0, clientPosLParam);
|
||||
translated = true;
|
||||
} break;
|
||||
case WM_NCRBUTTONUP: {
|
||||
PostMessageW(hWnd, WM_RBUTTONUP, 0, clientPosLParam);
|
||||
translated = true;
|
||||
} break;
|
||||
case WM_NCRBUTTONDBLCLK: {
|
||||
PostMessageW(hWnd, WM_RBUTTONDBLCLK, 0, clientPosLParam);
|
||||
translated = true;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (translated) {
|
||||
*result = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
switch (uMsg) {
|
||||
case WM_NCCALCSIZE: {
|
||||
// Windows是根据这个消息的返回值来设置窗口的客户区(窗口中真正显示的内容)
|
||||
|
@ -362,21 +496,6 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
|||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
// Fix the flickering issue while resizing.
|
||||
// "clientRect->right += 1;" also works.
|
||||
// This small technique is known to have two draw backs:
|
||||
// (1) Qt's coordinate system will be confused because the canvas size
|
||||
// doesn't match the client area size so you will get some warnings
|
||||
// from Qt and you should also be careful when you try to draw something
|
||||
// manually through QPainter or in Qt Quick, be aware of the coordinate
|
||||
// mismatch issue when you calculate position yourself.
|
||||
// (2) Qt's window system will take some wrong actions when the window
|
||||
// is being resized. For example, the window size will become 1px smaller
|
||||
// or bigger everytime when resize() is called because the client area size
|
||||
// is not correct. It confuses QPA's internal logic.
|
||||
clientRect->bottom += 1;
|
||||
#endif
|
||||
Utils::syncWmPaintWithDwm(); // This should be executed at the very last.
|
||||
// By returning WVR_REDRAW we can make the window resizing look less broken.
|
||||
// But we must return 0 if wParam is FALSE, according to Microsoft Docs.
|
||||
|
@ -466,32 +585,6 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
|||
qWarning() << Utils::getSystemErrorMessage(kScreenToClient);
|
||||
break;
|
||||
}
|
||||
if (data.settings.options & Option::MaximizeButtonDocking) {
|
||||
const QPoint scenePos = QPointF(QPointF(qreal(localPos.x), qreal(localPos.y))
|
||||
/ data.params.getWindowDevicePixelRatio()).toPoint();
|
||||
SystemButtonType systemButton = SystemButtonType::Unknown;
|
||||
if (data.params.isInsideSystemButtons(scenePos, &systemButton)) {
|
||||
switch (systemButton) {
|
||||
case SystemButtonType::Help:
|
||||
*result = HTHELP;
|
||||
break;
|
||||
case SystemButtonType::Minimize:
|
||||
*result = HTREDUCE;
|
||||
break;
|
||||
case SystemButtonType::Maximize:
|
||||
case SystemButtonType::Restore:
|
||||
*result = HTZOOM;
|
||||
break;
|
||||
case SystemButtonType::Close:
|
||||
*result = HTCLOSE;
|
||||
break;
|
||||
default:
|
||||
*result = HTCAPTION;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const bool max = IsMaximized(hWnd);
|
||||
const bool full = Utils::isFullScreen(windowId);
|
||||
const int frameSizeY = Utils::getResizeBorderThickness(windowId, false, true);
|
||||
|
@ -685,25 +778,26 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
|||
break;
|
||||
}
|
||||
}
|
||||
const bool themeSettingChanged = [uMsg, wParam, lParam]() -> bool {
|
||||
if (Utils::isWin101607OrGreater()) {
|
||||
if (uMsg == WM_SETTINGCHANGE) {
|
||||
if ((wParam == 0) && (QString::fromWCharArray(reinterpret_cast<LPCWSTR>(lParam))
|
||||
.compare(qThemeSettingChangeEventName, Qt::CaseInsensitive) == 0)) {
|
||||
return true;
|
||||
bool systemThemeChanged = ((uMsg == WM_THEMECHANGED) || (uMsg == WM_SYSCOLORCHANGE)
|
||||
|| (uMsg == WM_DWMCOLORIZATIONCOLORCHANGED));
|
||||
if (Utils::isWin101607OrGreater()) {
|
||||
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();
|
||||
if (!(data.settings.options & Option::DontTouchWindowFrameBorderColor)) {
|
||||
Utils::updateWindowFrameBorderColor(windowId, dark);
|
||||
}
|
||||
if (Utils::isWin101809OrGreater()) {
|
||||
if (data.settings.options & Option::SyncNativeControlsThemeWithSystem) {
|
||||
Utils::updateGlobalWin32ControlsTheme(windowId, dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}();
|
||||
if (themeSettingChanged) {
|
||||
if (!(data.settings.options & Option::DontTouchWindowFrameBorderColor)) {
|
||||
const bool dark = Utils::shouldAppsUseDarkMode();
|
||||
Utils::updateWindowFrameBorderColor(windowId, dark);
|
||||
}
|
||||
}
|
||||
if (themeSettingChanged || (uMsg == WM_THEMECHANGED)
|
||||
|| (uMsg == WM_SYSCOLORCHANGE) || (uMsg == WM_DWMCOLORIZATIONCOLORCHANGED)) {
|
||||
if (systemThemeChanged) {
|
||||
Q_EMIT FramelessWindowsManager::instance()->systemThemeChanged();
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -182,14 +182,17 @@ void FramelessHelper::Core::initialize(const Options options)
|
|||
qRegisterMetaType<ResourceType>();
|
||||
qRegisterMetaType<DwmColorizationArea>();
|
||||
qRegisterMetaType<Anchor>();
|
||||
qRegisterMetaType<ButtonState>();
|
||||
qRegisterMetaType<UserSettings>();
|
||||
qRegisterMetaType<SystemParameters>();
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
// Only needed by Qt5 Quick applications, it's hard to say whether it's a
|
||||
// bug or a lack of features. The QML engine is having a hard time to find
|
||||
// the correct type if the type has a long namespace with a deep hierarchy.
|
||||
qRegisterMetaType<SystemButtonType>("Global::SystemButtonType");
|
||||
qRegisterMetaType<Anchor>("Global::Anchor");
|
||||
qRegisterMetaType<ButtonState>("Global::ButtonState");
|
||||
#endif
|
||||
qRegisterMetaType<UserSettings>();
|
||||
qRegisterMetaType<SystemParameters>();
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -218,4 +218,33 @@ Qt::WindowState Utils::windowStatesToWindowState(const Qt::WindowStates states)
|
|||
return Qt::WindowNoState;
|
||||
}
|
||||
|
||||
bool Utils::isThemeChangeEvent(const QEvent * const event)
|
||||
{
|
||||
Q_ASSERT(event);
|
||||
if (!event) {
|
||||
return false;
|
||||
}
|
||||
const QEvent::Type type = event->type();
|
||||
return ((type == QEvent::ThemeChange) || (type == QEvent::ApplicationPaletteChange));
|
||||
}
|
||||
|
||||
QColor Utils::calculateSystemButtonBackgroundColor(const SystemButtonType button, const ButtonState state)
|
||||
{
|
||||
if ((state == ButtonState::Unspecified) || (state == ButtonState::Released)) {
|
||||
return kDefaultTransparentColor;
|
||||
}
|
||||
const QColor result = [button]() -> QColor {
|
||||
if (button == SystemButtonType::Close) {
|
||||
return kDefaultSystemCloseButtonBackgroundColor;
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (isTitleBarColorized()) {
|
||||
return getDwmColorizationColor();
|
||||
}
|
||||
#endif
|
||||
return kDefaultSystemButtonBackgroundColor;
|
||||
}();
|
||||
return ((state == ButtonState::Hovered) ? result.lighter(110) : result.lighter(105));
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -68,9 +68,9 @@ struct Win32UtilsHelper
|
|||
|
||||
Q_GLOBAL_STATIC(Win32UtilsHelper, g_utilsHelper)
|
||||
|
||||
static const QString qDwmRegistryKey = QUtf8String(kDwmRegistryKey);
|
||||
static const QString qPersonalizeRegistryKey = QUtf8String(kPersonalizeRegistryKey);
|
||||
static const QString qDwmColorKeyName = QUtf8String(kDwmColorKeyName);
|
||||
static const QString qDwmRegistryKey = QString::fromWCharArray(kDwmRegistryKey);
|
||||
static const QString qPersonalizeRegistryKey = QString::fromWCharArray(kPersonalizeRegistryKey);
|
||||
static const QString qDwmColorKeyName = QString::fromWCharArray(kDwmColorKeyName);
|
||||
FRAMELESSHELPER_STRING_CONSTANT2(SuccessMessageText, "The operation completed successfully.")
|
||||
FRAMELESSHELPER_STRING_CONSTANT2(FormatMessageEmptyResult, "\"FormatMessageW()\" returned empty string.")
|
||||
FRAMELESSHELPER_STRING_CONSTANT2(ErrorMessageTemplate, "Function \"%1()\" failed with error code %2: %3.")
|
||||
|
@ -83,6 +83,7 @@ FRAMELESSHELPER_STRING_CONSTANT(dwmapi)
|
|||
FRAMELESSHELPER_STRING_CONSTANT(winmm)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(shcore)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(d2d1)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(uxtheme)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(GetWindowRect)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(DwmIsCompositionEnabled)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(SetWindowPos)
|
||||
|
@ -727,6 +728,18 @@ bool Utils::isWin101607OrGreater()
|
|||
return result;
|
||||
}
|
||||
|
||||
bool Utils::isWin101809OrGreater()
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 3, 0))
|
||||
static const bool result = (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10_1809);
|
||||
#elif (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
||||
static const bool result = (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 17763));
|
||||
#else
|
||||
static const bool result = isWindowsVersionOrGreater(10, 0, 17763);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Utils::isHighContrastModeEnabled()
|
||||
{
|
||||
HIGHCONTRASTW hc;
|
||||
|
@ -935,6 +948,7 @@ void Utils::fixupQtInternals(const WId windowId)
|
|||
return;
|
||||
}
|
||||
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||
#if 0
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
const auto oldClassStyle = static_cast<DWORD>(GetClassLongPtrW(hwnd, GCL_STYLE));
|
||||
if (oldClassStyle == 0) {
|
||||
|
@ -947,12 +961,22 @@ void Utils::fixupQtInternals(const WId windowId)
|
|||
qWarning() << getSystemErrorMessage(kSetClassLongPtrW);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
const auto oldWindowStyle = static_cast<DWORD>(GetWindowLongPtrW(hwnd, GWL_STYLE));
|
||||
if (oldWindowStyle == 0) {
|
||||
qWarning() << getSystemErrorMessage(kGetWindowLongPtrW);
|
||||
return;
|
||||
}
|
||||
// Qt by default adds the "WS_POPUP" flag to all Win32 windows it created and maintained,
|
||||
// which is not a good thing (although it won't cause any obvious issues in most cases
|
||||
// either), because popup windows have some different behavior with normal overlapped
|
||||
// windows, for example, it will affect DWM's default policy. And Qt will also not add
|
||||
// the "WS_OVERLAPPED" flag to the windows in some cases, which also causes some trouble
|
||||
// for us. To avoid some weird bugs, we do the correction here: remove the WS_POPUP flag
|
||||
// and add the WS_OVERLAPPED flag, unconditionally. If your window really don't need this
|
||||
// correction, it also means you should not use this framework, because without this
|
||||
// correction, our core frameless functionality will be broken in some degree.
|
||||
const DWORD newWindowStyle = ((oldWindowStyle & ~WS_POPUP) | WS_OVERLAPPED);
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
if (SetWindowLongPtrW(hwnd, GWL_STYLE, static_cast<LONG_PTR>(newWindowStyle)) == 0) {
|
||||
|
@ -1195,6 +1219,8 @@ void Utils::tryToEnableHighestDpiAwarenessLevel()
|
|||
reinterpret_cast<decltype(&SetProcessDpiAwareness)>(
|
||||
QSystemLibrary::resolve(kshcore, "SetProcessDpiAwareness"));
|
||||
if (pSetProcessDpiAwareness) {
|
||||
// This enum value is our own extension, so don't check for "E_ACCESSDENIED"
|
||||
// because it won't appear in anywhere outside of our own code.
|
||||
if (SUCCEEDED(pSetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE_V2))) {
|
||||
return;
|
||||
}
|
||||
|
@ -1224,4 +1250,25 @@ SystemTheme Utils::getSystemTheme()
|
|||
return SystemTheme::Light;
|
||||
}
|
||||
|
||||
void Utils::updateGlobalWin32ControlsTheme(const WId windowId, const bool dark)
|
||||
{
|
||||
Q_ASSERT(windowId);
|
||||
if (!windowId) {
|
||||
return;
|
||||
}
|
||||
// There's no global dark theme for common Win32 controls before Win10 1809.
|
||||
if (!isWin101809OrGreater()) {
|
||||
return;
|
||||
}
|
||||
static const auto pSetWindowTheme =
|
||||
reinterpret_cast<decltype(&SetWindowTheme)>(
|
||||
QSystemLibrary::resolve(kuxtheme, "SetWindowTheme"));
|
||||
if (!pSetWindowTheme) {
|
||||
return;
|
||||
}
|
||||
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||
// The result depends on the runtime system version, no need to check.
|
||||
pSetWindowTheme(hwnd, (dark ? kSystemDarkThemeResourceName : kSystemLightThemeResourceName), nullptr);
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<RCC>
|
||||
<qresource prefix="/org.wangwenx190.FramelessHelper">
|
||||
<file>qml/CloseButton.qml</file>
|
||||
<file>qml/MaximizeButton.qml</file>
|
||||
<file>qml/MinimizeButton.qml</file>
|
||||
<file>qml/StandardCloseButton.qml</file>
|
||||
<file>qml/StandardMaximizeButton.qml</file>
|
||||
<file>qml/StandardMinimizeButton.qml</file>
|
||||
<file>qml/StandardTitleBar.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -93,9 +93,9 @@ void FramelessHelper::Quick::registerTypes(QQmlEngine *engine)
|
|||
qmlRegisterAnonymousType2(QQuickWindow, QUICK_URI_SHORT);
|
||||
qmlRegisterType<FramelessQuickWindow>(QUICK_URI_EXPAND("FramelessWindow"));
|
||||
initResource();
|
||||
qmlRegisterFile("MinimizeButton");
|
||||
qmlRegisterFile("MaximizeButton");
|
||||
qmlRegisterFile("CloseButton");
|
||||
qmlRegisterFile("StandardMinimizeButton");
|
||||
qmlRegisterFile("StandardMaximizeButton");
|
||||
qmlRegisterFile("StandardCloseButton");
|
||||
qmlRegisterFile("StandardTitleBar");
|
||||
}
|
||||
|
||||
|
|
|
@ -118,24 +118,19 @@ QSizeF FramelessQuickUtils::defaultSystemButtonIconSize()
|
|||
return kDefaultSystemButtonIconSize;
|
||||
}
|
||||
|
||||
QColor FramelessQuickUtils::defaultSystemButtonHoverColor()
|
||||
QColor FramelessQuickUtils::defaultSystemButtonBackgroundColor()
|
||||
{
|
||||
return kDefaultSystemButtonHoverColor;
|
||||
return kDefaultSystemButtonBackgroundColor;
|
||||
}
|
||||
|
||||
QColor FramelessQuickUtils::defaultSystemButtonPressColor()
|
||||
QColor FramelessQuickUtils::defaultSystemCloseButtonBackgroundColor()
|
||||
{
|
||||
return kDefaultSystemButtonPressColor;
|
||||
return kDefaultSystemCloseButtonBackgroundColor;
|
||||
}
|
||||
|
||||
QColor FramelessQuickUtils::defaultSystemCloseButtonHoverColor()
|
||||
QColor FramelessQuickUtils::getSystemButtonBackgroundColor(const SystemButtonType button, const ButtonState state)
|
||||
{
|
||||
return kDefaultSystemCloseButtonHoverColor;
|
||||
}
|
||||
|
||||
QColor FramelessQuickUtils::defaultSystemCloseButtonPressColor()
|
||||
{
|
||||
return kDefaultSystemCloseButtonPressColor;
|
||||
return Utils::calculateSystemButtonBackgroundColor(button, state);
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.wangwenx190.FramelessHelper 1.0
|
|||
|
||||
Button {
|
||||
id: button
|
||||
objectName: "CloseButtonObject"
|
||||
implicitWidth: FramelessUtils.defaultSystemButtonSize.width
|
||||
implicitHeight: FramelessUtils.defaultSystemButtonSize.height
|
||||
contentItem: Item {
|
||||
|
@ -42,15 +43,7 @@ Button {
|
|||
}
|
||||
background: Rectangle {
|
||||
visible: button.hovered || button.pressed
|
||||
color: {
|
||||
if (button.pressed) {
|
||||
return FramelessUtils.defaultSystemCloseButtonPressColor;
|
||||
}
|
||||
if (button.hovered) {
|
||||
return FramelessUtils.defaultSystemCloseButtonHoverColor;
|
||||
}
|
||||
return "transparent";
|
||||
}
|
||||
color: FramelessUtils.getSystemButtonBackgroundColor(FramelessHelper.Close, (button.pressed ? FramelessHelper.Pressed : FramelessHelper.Hovered))
|
||||
}
|
||||
|
||||
ToolTip {
|
|
@ -30,6 +30,7 @@ Button {
|
|||
property bool maximized: false
|
||||
|
||||
id: button
|
||||
objectName: "MaximizeButtonObject"
|
||||
implicitWidth: FramelessUtils.defaultSystemButtonSize.width
|
||||
implicitHeight: FramelessUtils.defaultSystemButtonSize.height
|
||||
contentItem: Item {
|
||||
|
@ -47,15 +48,7 @@ Button {
|
|||
}
|
||||
background: Rectangle {
|
||||
visible: button.hovered || button.pressed
|
||||
color: {
|
||||
if (button.pressed) {
|
||||
return FramelessUtils.defaultSystemButtonPressColor;
|
||||
}
|
||||
if (button.hovered) {
|
||||
return FramelessUtils.defaultSystemButtonHoverColor;
|
||||
}
|
||||
return "transparent";
|
||||
}
|
||||
color: FramelessUtils.getSystemButtonBackgroundColor(FramelessHelper.Maximize, (button.pressed ? FramelessHelper.Pressed : FramelessHelper.Hovered))
|
||||
}
|
||||
|
||||
ToolTip {
|
|
@ -28,6 +28,7 @@ import org.wangwenx190.FramelessHelper 1.0
|
|||
|
||||
Button {
|
||||
id: button
|
||||
objectName: "MinimizeButtonObject"
|
||||
implicitWidth: FramelessUtils.defaultSystemButtonSize.width
|
||||
implicitHeight: FramelessUtils.defaultSystemButtonSize.height
|
||||
contentItem: Item {
|
||||
|
@ -42,15 +43,7 @@ Button {
|
|||
}
|
||||
background: Rectangle {
|
||||
visible: button.hovered || button.pressed
|
||||
color: {
|
||||
if (button.pressed) {
|
||||
return FramelessUtils.defaultSystemButtonPressColor;
|
||||
}
|
||||
if (button.hovered) {
|
||||
return FramelessUtils.defaultSystemButtonHoverColor;
|
||||
}
|
||||
return "transparent";
|
||||
}
|
||||
color: FramelessUtils.getSystemButtonBackgroundColor(FramelessHelper.Minimize, (button.pressed ? FramelessHelper.Pressed : FramelessHelper.Hovered))
|
||||
}
|
||||
|
||||
ToolTip {
|
|
@ -58,16 +58,16 @@ Rectangle {
|
|||
right: parent.right
|
||||
}
|
||||
|
||||
MinimizeButton {
|
||||
StandardMinimizeButton {
|
||||
id: minimizeButton
|
||||
}
|
||||
|
||||
MaximizeButton {
|
||||
StandardMaximizeButton {
|
||||
id: maximizeButton
|
||||
maximized: titleBar.maximized
|
||||
}
|
||||
|
||||
CloseButton {
|
||||
StandardCloseButton {
|
||||
id: closeButton
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,9 +31,11 @@ set(SOURCES
|
|||
${INCLUDE_PREFIX}/framelesswidgetshelper.h
|
||||
${INCLUDE_PREFIX}/framelesswidget.h
|
||||
${INCLUDE_PREFIX}/framelessmainwindow.h
|
||||
${INCLUDE_PREFIX}/standardsystembutton.h
|
||||
framelessmainwindow.cpp
|
||||
framelesswidgetshelper.cpp
|
||||
framelesswidget.cpp
|
||||
standardsystembutton.cpp
|
||||
)
|
||||
|
||||
if(WIN32 AND NOT FRAMELESSHELPER_BUILD_STATIC)
|
||||
|
|
|
@ -515,27 +515,40 @@ bool FramelessWidgetsHelper::isInSystemButtons(const QPoint &pos, SystemButtonTy
|
|||
return false;
|
||||
}
|
||||
*button = SystemButtonType::Unknown;
|
||||
if (!m_settings.minimizeButton || !m_settings.maximizeButton || !m_settings.closeButton) {
|
||||
return false;
|
||||
if (m_settings.windowIconButton && m_settings.windowIconButton->isWidgetType()) {
|
||||
const auto iconBtn = qobject_cast<QWidget *>(m_settings.windowIconButton);
|
||||
if (iconBtn->geometry().contains(pos)) {
|
||||
*button = SystemButtonType::WindowIcon;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!m_settings.minimizeButton->isWidgetType() || !m_settings.maximizeButton->isWidgetType()
|
||||
|| !m_settings.closeButton->isWidgetType()) {
|
||||
return false;
|
||||
if (m_settings.contextHelpButton && m_settings.contextHelpButton->isWidgetType()) {
|
||||
const auto helpBtn = qobject_cast<QWidget *>(m_settings.contextHelpButton);
|
||||
if (helpBtn->geometry().contains(pos)) {
|
||||
*button = SystemButtonType::Help;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const auto minBtn = qobject_cast<QWidget *>(m_settings.minimizeButton);
|
||||
if (minBtn->geometry().contains(pos)) {
|
||||
*button = SystemButtonType::Minimize;
|
||||
return true;
|
||||
if (m_settings.minimizeButton && m_settings.minimizeButton->isWidgetType()) {
|
||||
const auto minBtn = qobject_cast<QWidget *>(m_settings.minimizeButton);
|
||||
if (minBtn->geometry().contains(pos)) {
|
||||
*button = SystemButtonType::Minimize;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const auto maxBtn = qobject_cast<QWidget *>(m_settings.maximizeButton);
|
||||
if (maxBtn->geometry().contains(pos)) {
|
||||
*button = SystemButtonType::Maximize;
|
||||
return true;
|
||||
if (m_settings.maximizeButton && m_settings.maximizeButton->isWidgetType()) {
|
||||
const auto maxBtn = qobject_cast<QWidget *>(m_settings.maximizeButton);
|
||||
if (maxBtn->geometry().contains(pos)) {
|
||||
*button = SystemButtonType::Maximize;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const auto closeBtn = qobject_cast<QWidget *>(m_settings.closeButton);
|
||||
if (closeBtn->geometry().contains(pos)) {
|
||||
*button = SystemButtonType::Close;
|
||||
return true;
|
||||
if (m_settings.closeButton && m_settings.closeButton->isWidgetType()) {
|
||||
const auto closeBtn = qobject_cast<QWidget *>(m_settings.closeButton);
|
||||
if (closeBtn->geometry().contains(pos)) {
|
||||
*button = SystemButtonType::Close;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 "standardsystembutton.h"
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 "../../include/FramelessHelper/Widgets/standardsystembutton.h"
|
Loading…
Reference in New Issue