Compare commits

..

5 Commits

Author SHA1 Message Date
Yuhang Zhao ae674a2507 wip 2023-09-15 17:51:08 +08:00
Zhao Yuhang 5ffb2ef733 wip 2023-09-15 14:24:00 +08:00
Yuhang Zhao 146384f9b0 wip 2023-09-15 14:24:00 +08:00
Zhao Yuhang 26b9996ec6 fix qmake build and version 2023-09-14 19:27:07 +08:00
Zhao Yuhang 322c448bc1 minor tweaks 2023-09-13 21:10:57 +08:00
18 changed files with 413 additions and 321 deletions

View File

@ -120,28 +120,28 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
endif()
set(FRAMELESSHELPER_LICENSE_HEADER "/*
* MIT License
*
* Copyright (C) 2021-2023 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.
*/")
* MIT License
*
* Copyright (C) 2021-2023 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.
*/")
set(__extra_flags "")
if(NOT FRAMELESSHELPER_BUILD_STATIC)

37
build/msvc.bat Normal file
View File

@ -0,0 +1,37 @@
@echo off
title Building FramelessHelper ...
setlocal
cls
set __vs_bat=%ProgramFiles%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat
if not exist "%__vs_bat%" set __vs_bat=%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat
if not exist "%__vs_bat%" set __vs_bat=%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat
if not exist "%__vs_bat%" set __vs_bat=%ProgramFiles(x86)%\Microsoft Visual Studio\2015\Community\VC\Auxiliary\Build\vcvars64.bat
if not exist "%__vs_bat%" (
echo Cannot find a valid Visual Studio toolchain!
echo Please install at least Visual Studio 2015 to the default location!
goto fin
)
call "%__vs_bat%"
cmake --version
echo ninja build
ninja --version
cd /d "%~dp0"
if exist "%~dp0build.user.bat" call "%~dp0build.user.bat"
if not defined QTDIR set QTDIR=C:\Qt\6.6.0\msvc2019_64
echo QTDIR=%QTDIR%
if exist cmake rd /s /q cmake
md cmake
cd cmake
md build
cd build
cmake -DCMAKE_PREFIX_PATH="%QTDIR%" -DCMAKE_INSTALL_PREFIX="%~dp0cmake\install" -DCMAKE_CONFIGURATION_TYPES=Release;Debug -G"Ninja Multi-Config" -DFRAMELESSHELPER_ENABLE_VCLTL=ON -DFRAMELESSHELPER_ENABLE_YYTHUNKS=ON -DFRAMELESSHELPER_ENABLE_SPECTRE=ON -DFRAMELESSHELPER_ENABLE_EHCONTGUARD=ON -DFRAMELESSHELPER_ENABLE_INTELCET=ON -DFRAMELESSHELPER_ENABLE_INTELJCC=ON -DFRAMELESSHELPER_ENABLE_CFGUARD=ON -DFRAMELESSHELPER_FORCE_LTO=ON "%~dp0.."
cmake --build . --target all --config Release --parallel
cmake --build . --target all --config Debug --parallel
cmake --install . --config Release --strip
cmake --install . --config Debug
goto fin
:fin
endlocal
cd /d "%~dp0"
pause
exit /b 0

View File

@ -1,20 +0,0 @@
@echo off
title Building FramelessHelper ...
setlocal
cls
call "%ProgramFiles%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat"
cd /d "%~dp0"
if exist cmake rd /s /q cmake
md cmake
cd cmake
md build
cd build
cmake -DCMAKE_PREFIX_PATH="C:\Qt\6.6.0\msvc2019_64" -DCMAKE_INSTALL_PREFIX="%~dp0cmake\install" -DCMAKE_CONFIGURATION_TYPES=Release;Debug -G"Ninja Multi-Config" -DFRAMELESSHELPER_ENABLE_VCLTL=ON -DFRAMELESSHELPER_ENABLE_YYTHUNKS=ON -DFRAMELESSHELPER_ENABLE_SPECTRE=ON -DFRAMELESSHELPER_ENABLE_EHCONTGUARD=ON -DFRAMELESSHELPER_ENABLE_INTELCET=ON -DFRAMELESSHELPER_ENABLE_INTELJCC=ON -DFRAMELESSHELPER_ENABLE_CFGUARD=ON -DFRAMELESSHELPER_FORCE_LTO=ON "%~dp0.."
cmake --build . --target all --config Release --parallel
cmake --build . --target all --config Debug --parallel
cmake --install . --config Release --strip
cmake --install . --config Debug
endlocal
cd /d "%~dp0"
pause
exit /b 0

View File

@ -265,6 +265,10 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
#include "framelesshelper.version"
#ifndef __FRAMELESSHELPER__
# define __FRAMELESSHELPER__ __FRAMELESSHELPER_VERSION__
#endif // __FRAMELESSHELPER__
namespace Global
{

View File

@ -104,26 +104,32 @@ private:
};
using FramelessCallbacksPtr = FramelessCallbacks::PtrType;
struct FramelessExtraData
{
using PtrType = std::shared_ptr<FramelessExtraData>;
//[[nodiscard]] static PtrType create();
private:
Q_DISABLE_COPY_MOVE(FramelessExtraData)
};
using FramelessExtraDataPtr = FramelessExtraData::PtrType;
using FramelessExtraDataPtrs = QList<FramelessExtraDataPtr>;
using FramelessExtraDataHash = QHash<quint8, FramelessExtraDataPtr>;
struct FramelessData
{
bool frameless = false;
FramelessCallbacksPtr callbacks = nullptr;
struct {
void *ptr = nullptr;
using DeleterFunctionPrototype = void(*)(void*);
DeleterFunctionPrototype deleter = nullptr;
} extraData = {};
FramelessExtraDataHash extraData = {};
using PtrType = std::shared_ptr<FramelessData>;
[[nodiscard]] static PtrType create();
~FramelessData();
private:
Q_DISABLE_COPY_MOVE(FramelessData)
};
using FramelessDataPtr = FramelessData::PtrType;
using FramelessDataPtrs = QList<FramelessDataPtr>;
using FramelessDataHash = QHash<const QWindow *, FramelessDataPtr>;
template<typename T>

View File

@ -25,9 +25,6 @@
#pragma once
#include <FramelessHelper/Core/framelesshelpercore_global.h>
#if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
# include <FramelessHelper/Core/framelesshelper_linux.h>
#endif // Q_OS_LINUX
#if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
QT_BEGIN_NAMESPACE
@ -37,8 +34,6 @@ QT_END_NAMESPACE
FRAMELESSHELPER_BEGIN_NAMESPACE
struct SystemParameters;
namespace Utils
{

View File

@ -40,7 +40,6 @@ class QuickMicaMaterial;
class QuickWindowBorder;
#endif
class FramelessQuickHelper;
struct FramelessQuickHelperData;
class FRAMELESSHELPER_QUICK_API FramelessQuickHelperPrivate : public QObject
{
@ -83,8 +82,6 @@ public:
Q_NODISCARD bool isInTitleBarDraggableArea(const QPoint &pos) const;
Q_NODISCARD bool shouldIgnoreMouseEvents(const QPoint &pos) const;
void setSystemButtonState(const QuickGlobal::SystemButtonType button, const QuickGlobal::ButtonState state);
Q_NODISCARD const FramelessQuickHelperData *getWindowData() const;
Q_NODISCARD FramelessQuickHelperData *getWindowDataMutable() const;
void rebindWindow();
FramelessQuickHelper *q_ptr = nullptr;

View File

@ -7,9 +7,6 @@ CORE_PRIV_INC_DIR = $$CORE_PUB_INC_DIR/private
CORE_EXTRA_INC_DIR = $$PWD/inc/core
CORE_SRC_DIR = $$PWD/../src/core
DEFINES += \
FRAMELESSHELPER_CORE_STATIC
INCLUDEPATH += \
$$BASE_INC_DIR \
$$COMMON_INC_DIR \

View File

@ -22,16 +22,14 @@
* SOFTWARE.
*/
// Generated automatically by CMake.
// WARNING! DO NOT EDIT THIS FILE MANUALLY!
// ALL CHANGES WILL BE LOST AFTER RE-CONFIGURING!
// Also please do not include this file directly,
// it's designed to be included by FramelessHelper's own headers.
// Caution: This file is generated by CMake automatically during configure.
// WARNING!!! DO NOT EDIT THIS FILE MANUALLY!!!
// ALL YOUR MODIFICATIONS HERE WILL GET LOST AFTER RE-CONFIGURING!!!
#pragma once
#ifndef _FRAMELESSHELPER_CONFIG_DEFINED_
#define _FRAMELESSHELPER_CONFIG_DEFINED_
#ifndef _FRAMELESSHELPER_CONFIG_INCLUDE_GUARD_
#define _FRAMELESSHELPER_CONFIG_INCLUDE_GUARD_
#define FRAMELESSHELPER_FEATURE_static_build 1
#define FRAMELESSHELPER_FEATURE_widgets 1
@ -46,4 +44,4 @@
#define FRAMELESSHELPER_FEATURE_border_painter 1
#define FRAMELESSHELPER_FEATURE_system_button 1
#endif // _FRAMELESSHELPER_CONFIG_DEFINED_
#endif // _FRAMELESSHELPER_CONFIG_INCLUDE_GUARD_

View File

@ -22,30 +22,38 @@
* SOFTWARE.
*/
// Generated automatically by QMake.
// WARNING! DO NOT EDIT THIS FILE MANUALLY!
// ALL CHANGES WILL BE LOST AFTER RE-CONFIGURING!
// Also please do not include this file directly,
// it's designed to be included by FramelessHelper's own headers.
// Caution: This file is generated by CMake automatically during configure.
// WARNING!!! DO NOT EDIT THIS FILE MANUALLY!!!
// ALL YOUR MODIFICATIONS HERE WILL GET LOST AFTER RE-CONFIGURING!!!
#pragma once
#ifndef _FRAMELESSHELPER_VERSION_DEFINED_
#define _FRAMELESSHELPER_VERSION_DEFINED_
[[maybe_unused]] inline constexpr const int FRAMELESSHELPER_VERSION_MAJOR = 2;
[[maybe_unused]] inline constexpr const int FRAMELESSHELPER_VERSION_MINOR = 5;
[[maybe_unused]] inline constexpr const int FRAMELESSHELPER_VERSION_PATCH = 0;
//[[maybe_unused]] inline constexpr const int FRAMELESSHELPER_VERSION_TWEAK = 0;
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_VERSION_STR[] = "2.5.0";
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_COMMIT_STR[] = "UNKNOWN";
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_COMPILE_DATETIME_STR[] = "UNKNOWN";
#ifndef _FRAMELESSHELPER_VERSION_INCLUDE_GUARD_
#define _FRAMELESSHELPER_VERSION_INCLUDE_GUARD_
#define __FRAMELESSHELPER_VERSION_MAJOR__ 2
#define __FRAMELESSHELPER_VERSION_MINOR__ 5
#define __FRAMELESSHELPER_VERSION_PATCH__ 0
//#define __FRAMELESSHELPER_VERSION_TWEAK__ 0
#define __FRAMELESSHELPER_VERSION_TWEAK__ 0
#define __FRAMELESSHELPER_VERSION__ 0x02050000
#define __FRAMELESSHELPER__ 0x02050000
#endif // _FRAMELESSHELPER_VERSION_DEFINED_
[[maybe_unused]] inline constexpr const unsigned long FRAMELESSHELPER_VERSION_MAJOR = 2;
[[maybe_unused]] inline constexpr const unsigned long FRAMELESSHELPER_VERSION_MINOR = 5;
[[maybe_unused]] inline constexpr const unsigned long FRAMELESSHELPER_VERSION_PATCH = 0;
[[maybe_unused]] inline constexpr const unsigned long FRAMELESSHELPER_VERSION_TWEAK = 0;
[[maybe_unused]] inline constexpr const unsigned long FRAMELESSHELPER_VERSION = 0x02050000;
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_VERSION_STR[] = "2.5.0";
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_COMMIT_HASH_STR[] = "UNKNOWN";
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_COMMIT_SUBJECT_STR[] = "UNKNOWN";
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_COMMIT_AUTHOR_STR[] = "UNKNOWN";
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_COMMIT_DATETIME_STR[] = "UNKNOWN";
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_COMMIT_BRANCH_STR[] = "UNKNOWN";
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_COMPILER_NAME_STR[] = "UNKNOWN";
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_COMPILER_VERSION_STR[] = "UNKNOWN";
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_COMPILER_VENDOR_STR[] = "UNKNOWN";
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_BUILD_DATETIME_STR[] = "UNKNOWN";
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_ARCHITECTURE_STR[] = "UNKNOWN";
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_CMAKE_VERSION_STR[] = "UNKNOWN";
[[maybe_unused]] inline constexpr const char FRAMELESSHELPER_CMAKE_GENERATOR_STR[] = "UNKNOWN";
#endif // _FRAMELESSHELPER_VERSION_INCLUDE_GUARD_

View File

@ -9,9 +9,6 @@ QUICK_PUB_INC_DIR = $$COMMON_INC_DIR/Quick
QUICK_PRIV_INC_DIR = $$QUICK_PUB_INC_DIR/private
QUICK_SRC_DIR = $$PWD/../src/quick
DEFINES += \
FRAMELESSHELPER_QUICK_STATIC
INCLUDEPATH += \
$$BASE_INC_DIR \
$$COMMON_INC_DIR \

View File

@ -6,9 +6,6 @@ WIDGETS_PUB_INC_DIR = $$COMMON_INC_DIR/Widgets
WIDGETS_PRIV_INC_DIR = $$WIDGETS_PUB_INC_DIR/private
WIDGETS_SRC_DIR = $$PWD/../src/widgets
DEFINES += \
FRAMELESSHELPER_WIDGETS_STATIC
INCLUDEPATH += \
$$BASE_INC_DIR \
$$COMMON_INC_DIR \

View File

@ -56,7 +56,7 @@ struct FramelessConfigEntry
static constexpr const std::array<FramelessConfigEntry, static_cast<int>(Option::Last) + 1> FramelessOptionsTable =
{
FramelessConfigEntry{ "FRAMELESSHELPER_USE_CROSS_PLATFORM_QT_IMPLEMENTATION", "Options/UseCrossPlatformQtImplementation" },
//FramelessConfigEntry{ "FRAMELESSHELPER_USE_CROSS_PLATFORM_QT_IMPLEMENTATION", "Options/UseCrossPlatformQtImplementation" },
FramelessConfigEntry{ "FRAMELESSHELPER_FORCE_HIDE_WINDOW_FRAME_BORDER", "Options/ForceHideWindowFrameBorder" },
FramelessConfigEntry{ "FRAMELESSHELPER_FORCE_SHOW_WINDOW_FRAME_BORDER", "Options/ForceShowWindowFrameBorder" },
FramelessConfigEntry{ "FRAMELESSHELPER_DISABLE_WINDOWS_SNAP_LAYOUT", "Options/DisableWindowsSnapLayout" },
@ -85,14 +85,14 @@ Q_GLOBAL_STATIC(FramelessConfigData, g_framelessConfigData)
static inline void warnInappropriateOptions()
{
const FramelessConfig * const cfg = FramelessConfig::instance();
if (cfg->isSet(Option::UseCrossPlatformQtImplementation)) {
WARNING << "Option::UseCrossPlatformQtImplementation is deprecated and has no effect now. It will be removed in a future version.";
}
#ifdef Q_OS_WINDOWS
if (cfg->isSet(Option::DisableWindowsSnapLayout)) {
WARNING << "Option::DisableWindowsSnapLayout is deprecated and will removed in a future version. It has not effect now.";
WARNING << "Option::DisableWindowsSnapLayout is deprecated and has no effect now. It will be removed in a future version.";
}
#else
if (cfg->isSet(Option::UseCrossPlatformQtImplementation)) {
WARNING << "Option::UseCrossPlatformQtImplementation is default on non-Windows platforms.";
}
if (cfg->isSet(Option::ForceHideWindowFrameBorder)) {
WARNING << "Option::ForceHideWindowFrameBorder is only available on Windows.";
}

View File

@ -114,8 +114,21 @@ struct FramelessDataWin : public FramelessData
QRect restoreGeometry = {};
#endif // (QT_VERSION < QT_VERSION_CHECK(6, 5, 1))
};
using FramelessDataWinPtr = std::shared_ptr<FramelessDataWin>;
#define GetFramelessDataWin(Window) std::dynamic_pointer_cast<FramelessDataWin>(FramelessManagerPrivate::getData(Window))
[[nodiscard]] static inline FramelessDataWinPtr tryGetData(const QWindow *window)
{
Q_ASSERT(window);
if (!window) {
return nullptr;
}
const FramelessDataPtr data = FramelessManagerPrivate::getData(window);
Q_ASSERT(data);
if (!data) {
return nullptr;
}
return std::dynamic_pointer_cast<FramelessDataWin>(data);
}
[[nodiscard]] FramelessDataPtr FramelessData::create()
{
@ -199,7 +212,7 @@ void FramelessHelperWin::addWindow(const QWindow *window)
if (!window) {
return;
}
const auto data = GetFramelessDataWin(window);
const FramelessDataWinPtr data = tryGetData(window);
Q_ASSERT(data);
if (!data || data->frameless) {
return;
@ -292,7 +305,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
return false;
}
const auto data = GetFramelessDataWin(window);
const FramelessDataWinPtr data = tryGetData(window);
Q_ASSERT(data);
if (!data || !data->frameless) {
return false;

View File

@ -119,15 +119,20 @@ FramelessCallbacksPtr FramelessCallbacks::create()
return std::make_shared<FramelessCallbacks>();
}
FramelessData::~FramelessData()
FramelessExtraDataPtr FramelessExtraData::create()
{
if (extraData.ptr) {
Q_ASSERT(extraData.deleter);
if (extraData.deleter) {
extraData.deleter(extraData.ptr);
extraData.deleter = nullptr;
return std::make_shared<FramelessExtraData>();
}
FramelessExtraData::~FramelessExtraData()
{
if (ptr) {
Q_ASSERT(deleter);
if (deleter) {
deleter(ptr);
deleter = nullptr;
}
extraData.ptr = nullptr;
ptr = nullptr;
}
}

View File

@ -194,19 +194,48 @@ FRAMELESSHELPER_STRING_CONSTANT(ScreenToClient)
FRAMELESSHELPER_STRING_CONSTANT(DwmFlush)
FRAMELESSHELPER_STRING_CONSTANT(GetCursorPos)
struct FramelessDataExtra
static constexpr const auto UTILS_WIN_EXTRA_DATA_ID = quint8(1);
struct UtilsWinExtraData : public FramelessExtraData
{
WNDPROC qtWindowProc = nullptr;
bool windowProcHooked = false;
bool mica = false;
};
static inline void FramelessDataExtraDeleter(void *data)
[[nodiscard]] static FramelessExtraDataPtr create();
};
using UtilsWinExtraDataPtr = std::shared_ptr<UtilsWinExtraData>;
FramelessExtraDataPtr UtilsWinExtraData::create()
{
Q_ASSERT(data);
if (data) {
delete static_cast<FramelessDataExtra *>(data);
return std::make_shared<UtilsWinExtraData>();
}
template<typename T>
[[nodiscard]] static inline UtilsWinExtraDataPtr tryGetExtraData(const T t, const bool create)
{
FramelessDataPtr data = nullptr;
using T2 = std::remove_cvref_t<T>;
if constexpr (std::is_same_v<T2, QWindow *>) {
data = FramelessManagerPrivate::getData(t);
} else if constexpr (std::is_same_v<T2, FramelessDataPtr>) {
data = t;
} else {
Q_UNREACHABLE_RETURN(nullptr);
}
Q_ASSERT(data);
if (!data) {
return nullptr;
}
auto it = data->extraData.find(UTILS_WIN_EXTRA_DATA_ID);
if (it == data->extraData.end()) {
if (create) {
it = data->extraData.insert(UTILS_WIN_EXTRA_DATA_ID, UtilsWinExtraData::create());
} else {
return nullptr;
}
}
return std::dynamic_pointer_cast<UtilsWinExtraData>(it.value());
}
struct Win32Message
@ -889,7 +918,7 @@ static constexpr const std::array<Win32Message, 333> g_win32MessageMap =
if (!data) {
return ::DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
const auto extraData = static_cast<FramelessDataExtra *>(data->extraData.ptr);
const UtilsWinExtraDataPtr extraData = tryGetExtraData(data, false);
Q_ASSERT(extraData);
if (!extraData) {
return ::DefWindowProcW(hWnd, uMsg, wParam, lParam);
@ -1101,12 +1130,7 @@ bool Utils::updateWindowFrameMargins(const QWindow *window, const bool reset)
if (!isDwmCompositionEnabled()) {
return false;
}
const FramelessDataPtr data = FramelessManagerPrivate::getData(window);
Q_ASSERT(data);
if (!data) {
return false;
}
const auto extraData = static_cast<FramelessDataExtra *>(data->extraData.ptr);
const UtilsWinExtraDataPtr extraData = tryGetExtraData(window, false);
Q_ASSERT(extraData);
if (!extraData) {
return false;
@ -1932,18 +1956,7 @@ bool Utils::installWindowProcHook(const QWindow *window)
if (!window) {
return false;
}
const FramelessDataPtr data = FramelessManagerPrivate::getData(window);
Q_ASSERT(data);
if (!data) {
return false;
}
if (!data->extraData.ptr) {
data->extraData.ptr = new FramelessDataExtra();
}
if (!data->extraData.deleter) {
data->extraData.deleter = FramelessDataExtraDeleter;
}
const auto extraData = static_cast<FramelessDataExtra *>(data->extraData.ptr);
const UtilsWinExtraDataPtr extraData = tryGetExtraData(window, true);
const auto hwnd = qWindowId<HWND>(window);
if (!extraData->qtWindowProc) {
::SetLastError(ERROR_SUCCESS);
@ -1972,12 +1985,7 @@ bool Utils::uninstallWindowProcHook(const QWindow *window)
if (!window) {
return false;
}
const FramelessDataPtr data = FramelessManagerPrivate::getData(window);
Q_ASSERT(data);
if (!data) {
return false;
}
const auto extraData = static_cast<FramelessDataExtra *>(data->extraData.ptr);
const UtilsWinExtraDataPtr extraData = tryGetExtraData(window, false);
if (!extraData || !extraData->windowProcHooked) {
return false;
}
@ -2249,12 +2257,7 @@ bool Utils::setBlurBehindWindowEnabled(const QWindow *window, const BlurMode mod
if (!window) {
return false;
}
const FramelessDataPtr data = FramelessManagerPrivate::getData(window);
Q_ASSERT(data);
if (!data) {
return false;
}
const auto extraData = static_cast<FramelessDataExtra *>(data->extraData.ptr);
const UtilsWinExtraDataPtr extraData = tryGetExtraData(window, false);
Q_ASSERT(extraData);
if (!extraData) {
return false;
@ -3013,12 +3016,8 @@ bool Utils::removeMicaWindow(const QWindow *window)
if (!window) {
return false;
}
const FramelessDataPtr data = FramelessManagerPrivate::getData(window);
Q_ASSERT(data);
if (!data) {
return false;
}
const auto extraData = static_cast<FramelessDataExtra *>(data->extraData.ptr);
const UtilsWinExtraDataPtr extraData = tryGetExtraData(window, false);
Q_ASSERT(extraData);
if (!extraData || !extraData->mica) {
return false;
}

View File

@ -32,6 +32,7 @@
#endif
#include <FramelessHelper/Core/framelessmanager.h>
#include <FramelessHelper/Core/utils.h>
#include <FramelessHelper/Core/private/framelessmanager_p.h>
#include <FramelessHelper/Core/private/framelessconfig_p.h>
#include <FramelessHelper/Core/private/framelesshelpercore_global_p.h>
#ifdef Q_OS_WINDOWS
@ -72,10 +73,10 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
using namespace Global;
struct FramelessQuickHelperData
static constexpr const auto FRAMELESS_QUICK_HELPER_EXTRA_DATA_ID = quint8(3);
struct FramelessQuickHelperExtraData : public FramelessExtraData
{
bool ready = false;
SystemParameters params = {};
QPointer<QQuickItem> titleBarItem = nullptr;
QList<QPointer<QQuickItem>> hitTestVisibleItems = {};
QPointer<QQuickItem> windowIconButton = nullptr;
@ -84,11 +85,42 @@ struct FramelessQuickHelperData
QPointer<QQuickItem> maximizeButton = nullptr;
QPointer<QQuickItem> closeButton = nullptr;
QList<QRect> hitTestVisibleRects = {};
[[nodiscard]] static FramelessExtraDataPtr create();
};
using FramelessQuickHelperExtraDataPtr = std::shared_ptr<FramelessQuickHelperExtraData>;
using FramelessQuickHelperInternal = QHash<WId, FramelessQuickHelperData>;
FramelessExtraDataPtr FramelessQuickHelperExtraData::create()
{
return std::make_shared<FramelessQuickHelperExtraData>();
}
Q_GLOBAL_STATIC(FramelessQuickHelperInternal, g_framelessQuickHelperData)
template<typename T>
[[nodiscard]] static inline FramelessQuickHelperExtraDataPtr tryGetExtraData(const T t, const bool create)
{
FramelessDataPtr data = nullptr;
using T2 = std::remove_cvref_t<T>;
if constexpr (std::is_same_v<T2, QQuickWindow *>) {
data = FramelessManagerPrivate::getData(t);
} else if constexpr (std::is_same_v<T2, FramelessDataPtr>) {
data = t;
} else {
Q_UNREACHABLE_RETURN(nullptr);
}
Q_ASSERT(data);
if (!data) {
return nullptr;
}
auto it = data->extraData.find(FRAMELESS_QUICK_HELPER_EXTRA_DATA_ID);
if (it == data->extraData.end()) {
if (create) {
it = data->extraData.insert(FRAMELESS_QUICK_HELPER_EXTRA_DATA_ID, FramelessQuickHelperExtraData::create());
} else {
return nullptr;
}
}
return std::dynamic_pointer_cast<FramelessQuickHelperExtraData>(it.value());
}
FramelessQuickHelperPrivate::FramelessQuickHelperPrivate(FramelessQuickHelper *q) : QObject(q)
{
@ -130,53 +162,54 @@ void FramelessQuickHelperPrivate::attach()
return;
}
FramelessQuickHelperData * const data = getWindowDataMutable();
if (!data || data->ready) {
const FramelessDataPtr data = FramelessManagerPrivate::getData(window);
Q_ASSERT(data);
if (!data) {
return;
}
SystemParameters params = {};
params.getWindowId = [window]() -> WId { return window->winId(); };
params.getWindowFlags = [window]() -> Qt::WindowFlags { return window->flags(); };
params.setWindowFlags = [window](const Qt::WindowFlags flags) -> void { window->setFlags(flags); };
params.getWindowSize = [window]() -> QSize { return window->size(); };
params.setWindowSize = [window](const QSize &size) -> void { window->resize(size); };
params.getWindowPosition = [window]() -> QPoint { return window->position(); };
params.setWindowPosition = [window](const QPoint &pos) -> void { window->setX(pos.x()); window->setY(pos.y()); };
params.getWindowScreen = [window]() -> QScreen * { return window->screen(); };
params.isWindowFixedSize = [q]() -> bool { return q->isWindowFixedSize(); };
params.setWindowFixedSize = [q](const bool value) -> void { q->setWindowFixedSize(value); };
params.getWindowState = [window]() -> Qt::WindowState { return window->windowState(); };
params.setWindowState = [window](const Qt::WindowState state) -> void { window->setWindowState(state); };
params.getWindowHandle = [window]() -> QWindow * { return window; };
params.windowToScreen = [window](const QPoint &pos) -> QPoint { return window->mapToGlobal(pos); };
params.screenToWindow = [window](const QPoint &pos) -> QPoint { return window->mapFromGlobal(pos); };
params.isInsideSystemButtons = [this](const QPoint &pos, SystemButtonType *button) -> bool {
QuickGlobal::SystemButtonType button2 = QuickGlobal::SystemButtonType::Unknown;
const bool result = isInSystemButtons(pos, &button2);
*button = FRAMELESSHELPER_ENUM_QUICK_TO_CORE(SystemButtonType, button2);
return result;
};
params.isInsideTitleBarDraggableArea = [this](const QPoint &pos) -> bool { return isInTitleBarDraggableArea(pos); };
params.getWindowDevicePixelRatio = [window]() -> qreal { return window->effectiveDevicePixelRatio(); };
params.setSystemButtonState = [this](const SystemButtonType button, const ButtonState state) -> void {
setSystemButtonState(FRAMELESSHELPER_ENUM_CORE_TO_QUICK(SystemButtonType, button),
FRAMELESSHELPER_ENUM_CORE_TO_QUICK(ButtonState, state));
};
params.shouldIgnoreMouseEvents = [this](const QPoint &pos) -> bool { return shouldIgnoreMouseEvents(pos); };
params.showSystemMenu = [q](const QPoint &pos) -> void { q->showSystemMenu(pos); };
params.setProperty = [this](const char *name, const QVariant &value) -> void { setProperty(name, value); };
params.getProperty = [this](const char *name, const QVariant &defaultValue) -> QVariant { return getProperty(name, defaultValue); };
params.setCursor = [window](const QCursor &cursor) -> void { window->setCursor(cursor); };
params.unsetCursor = [window]() -> void { window->unsetCursor(); };
params.getWidgetHandle = []() -> QObject * { return nullptr; };
params.forceChildrenRepaint = [this](const int delay) -> void { repaintAllChildren(delay); };
params.resetQtGrabbedControl = []() -> bool { return false; };
if (!data->callbacks) {
data->callbacks = FramelessCallbacks::create();
data->callbacks->getWindowId = [window]() -> WId { return window->winId(); };
data->callbacks->getWindowFlags = [window]() -> Qt::WindowFlags { return window->flags(); };
data->callbacks->setWindowFlags = [window](const Qt::WindowFlags flags) -> void { window->setFlags(flags); };
data->callbacks->getWindowSize = [window]() -> QSize { return window->size(); };
data->callbacks->setWindowSize = [window](const QSize &size) -> void { window->resize(size); };
data->callbacks->getWindowPosition = [window]() -> QPoint { return window->position(); };
data->callbacks->setWindowPosition = [window](const QPoint &pos) -> void { window->setX(pos.x()); window->setY(pos.y()); };
data->callbacks->getWindowScreen = [window]() -> QScreen * { return window->screen(); };
data->callbacks->isWindowFixedSize = [q]() -> bool { return q->isWindowFixedSize(); };
data->callbacks->setWindowFixedSize = [q](const bool value) -> void { q->setWindowFixedSize(value); };
data->callbacks->getWindowState = [window]() -> Qt::WindowState { return window->windowState(); };
data->callbacks->setWindowState = [window](const Qt::WindowState state) -> void { window->setWindowState(state); };
data->callbacks->getWindowHandle = [window]() -> QWindow * { return window; };
data->callbacks->windowToScreen = [window](const QPoint &pos) -> QPoint { return window->mapToGlobal(pos); };
data->callbacks->screenToWindow = [window](const QPoint &pos) -> QPoint { return window->mapFromGlobal(pos); };
data->callbacks->isInsideSystemButtons = [this](const QPoint &pos, SystemButtonType *button) -> bool {
QuickGlobal::SystemButtonType button2 = QuickGlobal::SystemButtonType::Unknown;
const bool result = isInSystemButtons(pos, &button2);
*button = FRAMELESSHELPER_ENUM_QUICK_TO_CORE(SystemButtonType, button2);
return result;
};
data->callbacks->isInsideTitleBarDraggableArea = [this](const QPoint &pos) -> bool { return isInTitleBarDraggableArea(pos); };
data->callbacks->getWindowDevicePixelRatio = [window]() -> qreal { return window->effectiveDevicePixelRatio(); };
data->callbacks->setSystemButtonState = [this](const SystemButtonType button, const ButtonState state) -> void {
setSystemButtonState(FRAMELESSHELPER_ENUM_CORE_TO_QUICK(SystemButtonType, button), FRAMELESSHELPER_ENUM_CORE_TO_QUICK(ButtonState, state));
};
data->callbacks->shouldIgnoreMouseEvents = [this](const QPoint &pos) -> bool { return shouldIgnoreMouseEvents(pos); };
data->callbacks->showSystemMenu = [q](const QPoint &pos) -> void { q->showSystemMenu(pos); };
data->callbacks->setProperty = [this](const char *name, const QVariant &value) -> void { setProperty(name, value); };
data->callbacks->getProperty = [this](const char *name, const QVariant &defaultValue) -> QVariant { return getProperty(name, defaultValue); };
data->callbacks->setCursor = [window](const QCursor &cursor) -> void { window->setCursor(cursor); };
data->callbacks->unsetCursor = [window]() -> void { window->unsetCursor(); };
data->callbacks->getWidgetHandle = []() -> QObject * { return nullptr; };
data->callbacks->forceChildrenRepaint = [this](const int delay) -> void { repaintAllChildren(delay); };
data->callbacks->resetQtGrabbedControl = []() -> bool { return false; };
}
FramelessManager::instance()->addWindow(&params);
std::ignore = tryGetExtraData(data, true);
data->params = params;
data->ready = true;
std::ignore = FramelessManager::instance()->addWindow(window);
// We have to wait for a little time before moving the top level window
// , because the platform window may not finish initializing by the time
@ -198,17 +231,11 @@ void FramelessQuickHelperPrivate::attach()
void FramelessQuickHelperPrivate::detach()
{
Q_Q(FramelessQuickHelper);
QQuickWindow * const w = q->window();
if (!w) {
const QQuickWindow * const window = q->window();
if (!window) {
return;
}
const WId windowId = w->winId();
const auto it = g_framelessQuickHelperData()->constFind(windowId);
if (it == g_framelessQuickHelperData()->constEnd()) {
return;
}
g_framelessQuickHelperData()->erase(it);
FramelessManager::instance()->removeWindow(windowId);
std::ignore = FramelessManager::instance()->removeWindow(window);
}
void FramelessQuickHelperPrivate::emitSignalForAllInstances(const char *signal)
@ -433,37 +460,43 @@ bool FramelessQuickHelperPrivate::isInSystemButtons(const QPoint &pos, QuickGlob
if (!button) {
return false;
}
const FramelessQuickHelperData *data = getWindowData();
if (!data) {
Q_Q(const FramelessQuickHelper);
const QQuickWindow * const window = q->window();
if (!window) {
return false;
}
const FramelessQuickHelperExtraDataPtr extraData = tryGetExtraData(window, false);
Q_ASSERT(extraData);
if (!extraData) {
return false;
}
*button = QuickGlobal::SystemButtonType::Unknown;
if (data->windowIconButton && data->windowIconButton->isVisible() && data->windowIconButton->isEnabled()) {
if (mapItemGeometryToScene(data->windowIconButton).contains(pos)) {
if (extraData->windowIconButton && extraData->windowIconButton->isVisible() && extraData->windowIconButton->isEnabled()) {
if (mapItemGeometryToScene(extraData->windowIconButton).contains(pos)) {
*button = QuickGlobal::SystemButtonType::WindowIcon;
return true;
}
}
if (data->contextHelpButton && data->contextHelpButton->isVisible() && data->contextHelpButton->isEnabled()) {
if (mapItemGeometryToScene(data->contextHelpButton).contains(pos)) {
if (extraData->contextHelpButton && extraData->contextHelpButton->isVisible() && extraData->contextHelpButton->isEnabled()) {
if (mapItemGeometryToScene(extraData->contextHelpButton).contains(pos)) {
*button = QuickGlobal::SystemButtonType::Help;
return true;
}
}
if (data->minimizeButton && data->minimizeButton->isVisible() && data->minimizeButton->isEnabled()) {
if (mapItemGeometryToScene(data->minimizeButton).contains(pos)) {
if (extraData->minimizeButton && extraData->minimizeButton->isVisible() && extraData->minimizeButton->isEnabled()) {
if (mapItemGeometryToScene(extraData->minimizeButton).contains(pos)) {
*button = QuickGlobal::SystemButtonType::Minimize;
return true;
}
}
if (data->maximizeButton && data->maximizeButton->isVisible() && data->maximizeButton->isEnabled()) {
if (mapItemGeometryToScene(data->maximizeButton).contains(pos)) {
if (extraData->maximizeButton && extraData->maximizeButton->isVisible() && extraData->maximizeButton->isEnabled()) {
if (mapItemGeometryToScene(extraData->maximizeButton).contains(pos)) {
*button = QuickGlobal::SystemButtonType::Maximize;
return true;
}
}
if (data->closeButton && data->closeButton->isVisible() && data->closeButton->isEnabled()) {
if (mapItemGeometryToScene(data->closeButton).contains(pos)) {
if (extraData->closeButton && extraData->closeButton->isVisible() && extraData->closeButton->isEnabled()) {
if (mapItemGeometryToScene(extraData->closeButton).contains(pos)) {
*button = QuickGlobal::SystemButtonType::Close;
return true;
}
@ -473,18 +506,6 @@ bool FramelessQuickHelperPrivate::isInSystemButtons(const QPoint &pos, QuickGlob
bool FramelessQuickHelperPrivate::isInTitleBarDraggableArea(const QPoint &pos) const
{
const FramelessQuickHelperData *data = getWindowData();
if (!data) {
return false;
}
if (!data->titleBarItem) {
// There's no title bar at all, the mouse will always be in the client area.
return false;
}
if (!data->titleBarItem->isVisible() || !data->titleBarItem->isEnabled()) {
// The title bar is hidden or disabled for some reason, treat it as there's no title bar.
return false;
}
Q_Q(const FramelessQuickHelper);
const QQuickWindow * const window = q->window();
if (!window) {
@ -492,8 +513,21 @@ bool FramelessQuickHelperPrivate::isInTitleBarDraggableArea(const QPoint &pos) c
// so we assume there's no title bar.
return false;
}
const FramelessQuickHelperExtraDataPtr extraData = tryGetExtraData(window, false);
Q_ASSERT(extraData);
if (!extraData) {
return false;
}
if (!extraData->titleBarItem) {
// There's no title bar at all, the mouse will always be in the client area.
return false;
}
if (!extraData->titleBarItem->isVisible() || !extraData->titleBarItem->isEnabled()) {
// The title bar is hidden or disabled for some reason, treat it as there's no title bar.
return false;
}
const QRect windowRect = {QPoint(0, 0), window->size()};
const QRect titleBarRect = mapItemGeometryToScene(data->titleBarItem);
const QRect titleBarRect = mapItemGeometryToScene(extraData->titleBarItem);
if (!titleBarRect.intersects(windowRect)) {
// The title bar is totally outside of the window for some reason,
// also treat it as there's no title bar.
@ -501,24 +535,24 @@ bool FramelessQuickHelperPrivate::isInTitleBarDraggableArea(const QPoint &pos) c
}
QRegion region = titleBarRect;
const auto systemButtons = {
data->windowIconButton, data->contextHelpButton,
data->minimizeButton, data->maximizeButton,
data->closeButton
extraData->windowIconButton, extraData->contextHelpButton,
extraData->minimizeButton, extraData->maximizeButton,
extraData->closeButton
};
for (auto &&button : std::as_const(systemButtons)) {
if (button && button->isVisible() && button->isEnabled()) {
region -= mapItemGeometryToScene(button);
}
}
if (!data->hitTestVisibleItems.isEmpty()) {
for (auto &&item : std::as_const(data->hitTestVisibleItems)) {
if (!extraData->hitTestVisibleItems.isEmpty()) {
for (auto &&item : std::as_const(extraData->hitTestVisibleItems)) {
if (item && item->isVisible() && item->isEnabled()) {
region -= mapItemGeometryToScene(item);
}
}
}
if (!data->hitTestVisibleRects.isEmpty()) {
for (auto &&rect : std::as_const(data->hitTestVisibleRects)) {
if (!extraData->hitTestVisibleRects.isEmpty()) {
for (auto &&rect : std::as_const(extraData->hitTestVisibleRects)) {
if (rect.isValid()) {
region -= rect;
}
@ -556,38 +590,6 @@ void FramelessQuickHelperPrivate::setSystemButtonState(const QuickGlobal::System
Q_UNUSED(state);
}
const FramelessQuickHelperData *FramelessQuickHelperPrivate::getWindowData() const
{
Q_Q(const FramelessQuickHelper);
const QQuickWindow * const window = q->window();
//Q_ASSERT(window);
if (!window) {
return nullptr;
}
const WId windowId = window->winId();
auto it = g_framelessQuickHelperData()->find(windowId);
if (it == g_framelessQuickHelperData()->end()) {
it = g_framelessQuickHelperData()->insert(windowId, {});
}
return &it.value();
}
FramelessQuickHelperData *FramelessQuickHelperPrivate::getWindowDataMutable() const
{
Q_Q(const FramelessQuickHelper);
const QQuickWindow * const window = q->window();
//Q_ASSERT(window);
if (!window) {
return nullptr;
}
const WId windowId = window->winId();
auto it = g_framelessQuickHelperData()->find(windowId);
if (it == g_framelessQuickHelperData()->end()) {
it = g_framelessQuickHelperData()->insert(windowId, {});
}
return &it.value();
}
void FramelessQuickHelperPrivate::rebindWindow()
{
Q_Q(FramelessQuickHelper);
@ -668,33 +670,41 @@ void FramelessQuickHelper::setHitTestVisible_item(QQuickItem *item, const bool v
if (!item) {
return;
}
Q_D(FramelessQuickHelper);
FramelessQuickHelperData *data = d->getWindowDataMutable();
if (!data) {
const QQuickWindow * const w = window();
if (!w) {
return;
}
const FramelessQuickHelperExtraDataPtr extraData = tryGetExtraData(w, false);
Q_ASSERT(extraData);
if (!extraData) {
return;
}
if (visible) {
data->hitTestVisibleItems.append(item);
extraData->hitTestVisibleItems.append(item);
} else {
data->hitTestVisibleItems.removeAll(item);
extraData->hitTestVisibleItems.removeAll(item);
}
}
void FramelessQuickHelper::setHitTestVisible_rect(const QRect &rect, const bool visible)
{
Q_ASSERT(rect.isValid());
if (!rect.isValid()) {
Q_ASSERT(Utils::isValidGeometry(rect));
if (!Utils::isValidGeometry(rect)) {
return;
}
Q_D(FramelessQuickHelper);
FramelessQuickHelperData *data = d->getWindowDataMutable();
if (!data) {
const QQuickWindow * const w = window();
if (!w) {
return;
}
const FramelessQuickHelperExtraDataPtr extraData = tryGetExtraData(w, false);
Q_ASSERT(extraData);
if (!extraData) {
return;
}
if (visible) {
data->hitTestVisibleRects.append(rect);
extraData->hitTestVisibleRects.append(rect);
} else {
data->hitTestVisibleRects.removeAll(rect);
extraData->hitTestVisibleRects.removeAll(rect);
}
}
@ -714,9 +724,13 @@ void FramelessQuickHelper::setHitTestVisible_object(QObject *object, const bool
bool FramelessQuickHelper::isContentExtendedIntoTitleBar() const
{
Q_D(const FramelessQuickHelper);
const FramelessQuickHelperData *data = d->getWindowData();
return (data ? data->ready : false);
const QQuickWindow * const w = window();
if (!w) {
return false;
}
const FramelessDataPtr data = FramelessManagerPrivate::getData(w);
Q_ASSERT(data);
return (data && data->frameless);
}
void FramelessQuickHelper::extendsContentIntoTitleBar(const bool value)
@ -736,9 +750,16 @@ void FramelessQuickHelper::extendsContentIntoTitleBar(const bool value)
QQuickItem *FramelessQuickHelper::titleBarItem() const
{
Q_D(const FramelessQuickHelper);
const FramelessQuickHelperData *data = d->getWindowData();
return (data ? data->titleBarItem : nullptr);
const QQuickWindow * const w = window();
if (!w) {
return nullptr;
}
const FramelessQuickHelperExtraDataPtr extraData = tryGetExtraData(w, false);
Q_ASSERT(extraData);
if (!extraData) {
return nullptr;
}
return extraData->titleBarItem;
}
void FramelessQuickHelper::setTitleBarItem(QQuickItem *value)
@ -747,12 +768,17 @@ void FramelessQuickHelper::setTitleBarItem(QQuickItem *value)
if (!value) {
return;
}
Q_D(FramelessQuickHelper);
FramelessQuickHelperData *data = d->getWindowDataMutable();
if (!data || (data->titleBarItem == value)) {
const QQuickWindow * const w = window();
if (!w) {
return;
}
data->titleBarItem = value;
const FramelessQuickHelperExtraDataPtr extraData = tryGetExtraData(w, false);
Q_ASSERT(extraData);
if (!extraData || (extraData->titleBarItem == value)) {
return;
}
extraData->titleBarItem = value;
Q_D(FramelessQuickHelper);
d->emitSignalForAllInstances("titleBarItemChanged");
}
@ -763,27 +789,31 @@ void FramelessQuickHelper::setSystemButton(QQuickItem *item, const QuickGlobal::
if (!item || (buttonType == QuickGlobal::SystemButtonType::Unknown)) {
return;
}
Q_D(FramelessQuickHelper);
FramelessQuickHelperData *data = d->getWindowDataMutable();
if (!data) {
const QQuickWindow * const w = window();
if (!w) {
return;
}
const FramelessQuickHelperExtraDataPtr extraData = tryGetExtraData(w, false);
Q_ASSERT(extraData);
if (!extraData) {
return;
}
switch (buttonType) {
case QuickGlobal::SystemButtonType::WindowIcon:
data->windowIconButton = item;
extraData->windowIconButton = item;
break;
case QuickGlobal::SystemButtonType::Help:
data->contextHelpButton = item;
extraData->contextHelpButton = item;
break;
case QuickGlobal::SystemButtonType::Minimize:
data->minimizeButton = item;
extraData->minimizeButton = item;
break;
case QuickGlobal::SystemButtonType::Maximize:
case QuickGlobal::SystemButtonType::Restore:
data->maximizeButton = item;
extraData->maximizeButton = item;
break;
case QuickGlobal::SystemButtonType::Close:
data->closeButton = item;
extraData->closeButton = item;
break;
case QuickGlobal::SystemButtonType::Unknown:
Q_UNREACHABLE();
@ -796,15 +826,12 @@ void FramelessQuickHelper::showSystemMenu(const QPoint &pos)
if (!w) {
return;
}
const WId windowId = w->winId();
const QPoint nativePos = Utils::toNativeGlobalPosition(w, pos);
#ifdef Q_OS_WINDOWS
Q_D(FramelessQuickHelper);
std::ignore = Utils::showSystemMenu(windowId, nativePos, false, &d->getWindowData()->params);
std::ignore = Utils::showSystemMenu(w, nativePos, false);
#elif (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
Utils::openSystemMenu(windowId, nativePos);
Utils::openSystemMenu(w, nativePos);
#else
Q_UNUSED(windowId);
Q_UNUSED(nativePos);
#endif
}
@ -832,11 +859,11 @@ void FramelessQuickHelper::windowStartSystemResize2(const Qt::Edges edges, const
void FramelessQuickHelper::moveWindowToDesktopCenter()
{
if (!window()) {
const QQuickWindow * const w = window();
if (!w) {
return;
}
Q_D(FramelessQuickHelper);
Utils::moveWindowToDesktopCenter(&d->getWindowData()->params, true);
std::ignore = Utils::moveWindowToDesktopCenter(w, true);
}
void FramelessQuickHelper::bringWindowToFront()
@ -846,7 +873,7 @@ void FramelessQuickHelper::bringWindowToFront()
return;
}
#ifdef Q_OS_WINDOWS
std::ignore = Utils::bringWindowToFront(w->winId());
std::ignore = Utils::bringWindowToFront(w);
#else
if (w->visibility() == QQuickWindow::Hidden) {
w->show();
@ -898,7 +925,7 @@ void FramelessQuickHelper::setWindowFixedSize(const bool value)
w->setMaximumSize(QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX));
}
#ifdef Q_OS_WINDOWS
std::ignore = Utils::setAeroSnappingEnabled(w->winId(), !value);
std::ignore = Utils::setAeroSnappingEnabled(w, !value);
#endif
Q_D(FramelessQuickHelper);
d->emitSignalForAllInstances("windowFixedSizeChanged");
@ -935,7 +962,7 @@ void FramelessQuickHelper::setBlurBehindWindowEnabled(const bool value)
}
mode = QuickGlobal::BlurMode::Disable;
}
if (Utils::setBlurBehindWindowEnabled(w->winId(), FRAMELESSHELPER_ENUM_QUICK_TO_CORE(BlurMode, mode), {})) {
if (Utils::setBlurBehindWindowEnabled(w, FRAMELESSHELPER_ENUM_QUICK_TO_CORE(BlurMode, mode), {})) {
d->blurBehindWindowEnabled = value;
d->emitSignalForAllInstances("blurBehindWindowEnabledChanged");
} else {

View File

@ -35,6 +35,7 @@
#include "widgetssharedhelper_p.h"
#include <FramelessHelper/Core/framelessmanager.h>
#include <FramelessHelper/Core/utils.h>
#include <FramelessHelper/Core/private/framelessmanager_p.h>
#include <FramelessHelper/Core/private/framelessconfig_p.h>
#include <FramelessHelper/Core/private/framelesshelpercore_global_p.h>
#include <QtCore/qhash.h>
@ -71,10 +72,10 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
using namespace Global;
struct FramelessWidgetsHelperData
static constexpr const auto FRAMELESS_WIDGETS_HELPER_EXTRA_DATA_ID = quint8(2);
struct FramelessWidgetsHelperExtraData : public FramelessExtraData
{
bool ready = false;
SystemParameters params = {};
QPointer<QWidget> titleBarWidget = nullptr;
QList<QPointer<QWidget>> hitTestVisibleWidgets = {};
QPointer<QWidget> windowIconButton = nullptr;
@ -83,11 +84,42 @@ struct FramelessWidgetsHelperData
QPointer<QWidget> maximizeButton = nullptr;
QPointer<QWidget> closeButton = nullptr;
QList<QRect> hitTestVisibleRects = {};
[[nodiscard]] static FramelessExtraDataPtr create();
};
using FramelessWidgetsHelperExtraDataPtr = std::shared_ptr<FramelessWidgetsHelperExtraData>;
using FramelessWidgetsHelperInternal = QHash<WId, FramelessWidgetsHelperData>;
FramelessExtraDataPtr FramelessWidgetsHelperExtraData::create()
{
return std::make_shared<FramelessWidgetsHelperExtraData>();
}
Q_GLOBAL_STATIC(FramelessWidgetsHelperInternal, g_framelessWidgetsHelperData)
template<typename T>
[[nodiscard]] static inline FramelessWidgetsHelperExtraDataPtr tryGetExtraData(const T t, const bool create)
{
FramelessDataPtr data = nullptr;
using T2 = std::remove_cvref_t<T>;
if constexpr (std::is_same_v<T2, QWindow *>) {
data = FramelessManagerPrivate::getData(t);
} else if constexpr (std::is_same_v<T2, FramelessDataPtr>) {
data = t;
} else {
Q_UNREACHABLE_RETURN(nullptr);
}
Q_ASSERT(data);
if (!data) {
return nullptr;
}
auto it = data->extraData.find(FRAMELESS_WIDGETS_HELPER_EXTRA_DATA_ID);
if (it == data->extraData.end()) {
if (create) {
it = data->extraData.insert(FRAMELESS_WIDGETS_HELPER_EXTRA_DATA_ID, FramelessWidgetsHelperExtraData::create());
} else {
return nullptr;
}
}
return std::dynamic_pointer_cast<FramelessWidgetsHelperExtraData>(it.value());
}
[[nodiscard]] static inline bool isWidgetFixedSize(const QWidget * const widget)
{
@ -421,7 +453,7 @@ void FramelessWidgetsHelperPrivate::attach()
params.resetQtGrabbedControl = []() -> bool {
if (qt_button_down) {
static constexpr const auto invalidPos = QPoint{ -99999, -99999 };
const auto event = std::make_unique<QMouseEvent>(
const auto event = new QMouseEvent(
QEvent::MouseButtonRelease,
invalidPos,
invalidPos,
@ -429,7 +461,7 @@ void FramelessWidgetsHelperPrivate::attach()
Qt::LeftButton,
QGuiApplication::mouseButtons() ^ Qt::LeftButton,
QGuiApplication::keyboardModifiers());
QApplication::sendEvent(qt_button_down, event.get());
QApplication::postEvent(qt_button_down, event);
qt_button_down = nullptr;
return true;
}