free all resources during destruction
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
fb13ff1c1b
commit
7dda58deaf
|
@ -42,7 +42,7 @@ int main(int argc, char *argv[])
|
||||||
// Must be called after QGuiApplication has been constructed, we are using
|
// Must be called after QGuiApplication has been constructed, we are using
|
||||||
// some private functions from QPA which won't be available until there's
|
// some private functions from QPA which won't be available until there's
|
||||||
// a QGuiApplication instance.
|
// a QGuiApplication instance.
|
||||||
FramelessHelper::Core::setApplicationOSThemeAware(true, false);
|
FramelessHelper::Core::setApplicationOSThemeAware(false);
|
||||||
|
|
||||||
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
||||||
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
||||||
|
|
|
@ -42,7 +42,7 @@ int main(int argc, char *argv[])
|
||||||
// Must be called after QGuiApplication has been constructed, we are using
|
// Must be called after QGuiApplication has been constructed, we are using
|
||||||
// some private functions from QPA which won't be available until there's
|
// some private functions from QPA which won't be available until there's
|
||||||
// a QGuiApplication instance.
|
// a QGuiApplication instance.
|
||||||
FramelessHelper::Core::setApplicationOSThemeAware(true, false);
|
FramelessHelper::Core::setApplicationOSThemeAware(false);
|
||||||
|
|
||||||
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
||||||
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
||||||
|
|
|
@ -79,7 +79,7 @@ int main(int argc, char *argv[])
|
||||||
// Must be called after QGuiApplication has been constructed, we are using
|
// Must be called after QGuiApplication has been constructed, we are using
|
||||||
// some private functions from QPA which won't be available until there's
|
// some private functions from QPA which won't be available until there's
|
||||||
// a QGuiApplication instance.
|
// a QGuiApplication instance.
|
||||||
FramelessHelper::Core::setApplicationOSThemeAware(true, false);
|
FramelessHelper::Core::setApplicationOSThemeAware(false);
|
||||||
|
|
||||||
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
||||||
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
||||||
|
|
|
@ -54,7 +54,7 @@ int main(int argc, char *argv[])
|
||||||
// Must be called after QGuiApplication has been constructed, we are using
|
// Must be called after QGuiApplication has been constructed, we are using
|
||||||
// some private functions from QPA which won't be available until there's
|
// some private functions from QPA which won't be available until there's
|
||||||
// a QGuiApplication instance.
|
// a QGuiApplication instance.
|
||||||
FramelessHelper::Core::setApplicationOSThemeAware(true, true);
|
FramelessHelper::Core::setApplicationOSThemeAware(true);
|
||||||
|
|
||||||
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
||||||
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
||||||
|
|
|
@ -42,7 +42,7 @@ int main(int argc, char *argv[])
|
||||||
// Must be called after QGuiApplication has been constructed, we are using
|
// Must be called after QGuiApplication has been constructed, we are using
|
||||||
// some private functions from QPA which won't be available until there's
|
// some private functions from QPA which won't be available until there's
|
||||||
// a QGuiApplication instance.
|
// a QGuiApplication instance.
|
||||||
FramelessHelper::Core::setApplicationOSThemeAware(true, false);
|
FramelessHelper::Core::setApplicationOSThemeAware(false);
|
||||||
|
|
||||||
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
||||||
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
||||||
|
|
|
@ -579,7 +579,7 @@ FRAMELESSHELPER_CORE_API void uninitialize();
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API Global::VersionInfo version();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API Global::VersionInfo version();
|
||||||
FRAMELESSHELPER_CORE_API void registerInitializeHook(const Global::InitializeHookCallback &cb);
|
FRAMELESSHELPER_CORE_API void registerInitializeHook(const Global::InitializeHookCallback &cb);
|
||||||
FRAMELESSHELPER_CORE_API void registerUninitializeHook(const Global::UninitializeHookCallback &cb);
|
FRAMELESSHELPER_CORE_API void registerUninitializeHook(const Global::UninitializeHookCallback &cb);
|
||||||
FRAMELESSHELPER_CORE_API void setApplicationOSThemeAware(const bool enable, const bool pureQuick);
|
FRAMELESSHELPER_CORE_API void setApplicationOSThemeAware(const bool pureQuick);
|
||||||
} // namespace FramelessHelper::Core
|
} // namespace FramelessHelper::Core
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -101,7 +101,7 @@ void FramelessHelperQt::addWindow(const SystemParameters ¶ms)
|
||||||
Utils::setSystemTitleBarVisible(windowId, false);
|
Utils::setSystemTitleBarVisible(windowId, false);
|
||||||
#endif
|
#endif
|
||||||
static const bool isQtQuickApplication = (params.getCurrentApplicationType() == ApplicationType::Quick);
|
static const bool isQtQuickApplication = (params.getCurrentApplicationType() == ApplicationType::Quick);
|
||||||
FramelessHelper::Core::setApplicationOSThemeAware(true, isQtQuickApplication);
|
FramelessHelper::Core::setApplicationOSThemeAware(isQtQuickApplication);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
#include <QtCore/qmutex.h>
|
#include <QtCore/qmutex.h>
|
||||||
#include <QtCore/qvariant.h>
|
#include <QtCore/qvariant.h>
|
||||||
#include <QtCore/qcoreapplication.h>
|
#include <QtCore/qcoreapplication.h>
|
||||||
#include <QtCore/qtimer.h>
|
|
||||||
#include <QtGui/qwindow.h>
|
#include <QtGui/qwindow.h>
|
||||||
#include "framelessmanager.h"
|
#include "framelessmanager.h"
|
||||||
#include "framelessmanager_p.h"
|
#include "framelessmanager_p.h"
|
||||||
|
@ -74,6 +73,7 @@ FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent)
|
||||||
FRAMELESSHELPER_STRING_CONSTANT(FindWindowW)
|
FRAMELESSHELPER_STRING_CONSTANT(FindWindowW)
|
||||||
FRAMELESSHELPER_STRING_CONSTANT(UnregisterClassW)
|
FRAMELESSHELPER_STRING_CONSTANT(UnregisterClassW)
|
||||||
FRAMELESSHELPER_BYTEARRAY_CONSTANT2(DontOverrideCursor, "FRAMELESSHELPER_DONT_OVERRIDE_CURSOR")
|
FRAMELESSHELPER_BYTEARRAY_CONSTANT2(DontOverrideCursor, "FRAMELESSHELPER_DONT_OVERRIDE_CURSOR")
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT(DestroyWindow)
|
||||||
|
|
||||||
struct Win32HelperData
|
struct Win32HelperData
|
||||||
{
|
{
|
||||||
|
@ -92,21 +92,6 @@ struct Win32Helper
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(Win32Helper, g_win32Helper)
|
Q_GLOBAL_STATIC(Win32Helper, g_win32Helper)
|
||||||
|
|
||||||
[[nodiscard]] static inline bool unregisterFallbackTitleBarWindowClass()
|
|
||||||
{
|
|
||||||
const HINSTANCE instance = GetModuleHandleW(nullptr);
|
|
||||||
if (instance) {
|
|
||||||
if (UnregisterClassW(kFallbackTitleBarWindowClassName, instance) == FALSE) {
|
|
||||||
WARNING << Utils::getSystemErrorMessage(kUnregisterClassW);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
WARNING << Utils::getSystemErrorMessage(kGetModuleHandleW);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] static inline LRESULT CALLBACK FallbackTitleBarWindowProc
|
[[nodiscard]] static inline LRESULT CALLBACK FallbackTitleBarWindowProc
|
||||||
(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam)
|
(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam)
|
||||||
{
|
{
|
||||||
|
@ -347,25 +332,6 @@ Q_GLOBAL_STATIC(Win32Helper, g_win32Helper)
|
||||||
case WM_NCRBUTTONDBLCLK:
|
case WM_NCRBUTTONDBLCLK:
|
||||||
case WM_NCRBUTTONUP:
|
case WM_NCRBUTTONUP:
|
||||||
return SendMessageW(parentWindowHandle, uMsg, wParam, lParam);
|
return SendMessageW(parentWindowHandle, uMsg, wParam, lParam);
|
||||||
case WM_DESTROY: {
|
|
||||||
const QMutexLocker locker(&g_win32Helper()->mutex);
|
|
||||||
g_win32Helper()->fallbackTitleBarToParentWindowMapping.remove(windowId);
|
|
||||||
if (g_win32Helper()->fallbackTitleBarToParentWindowMapping.count() < 1) {
|
|
||||||
// According to Microsoft Docs, window classes registered by DLLs will
|
|
||||||
// not be unregistered automatically on application termination, so we
|
|
||||||
// have to unregister them manually.
|
|
||||||
// And also from the docs, we are told that when the window received
|
|
||||||
// the "WM_DESTROY" message, the window may still exist, and we can't
|
|
||||||
// unregister the window class if it's corresponding windows are not
|
|
||||||
// all destroyed. So we have to wait a little bit to make sure the
|
|
||||||
// last window has been destroyed.
|
|
||||||
QTimer::singleShot(0, qApp, [](){
|
|
||||||
if (!unregisterFallbackTitleBarWindowClass()) {
|
|
||||||
WARNING << "Failed to unregister the window class of the fallback title bar window.";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -448,6 +414,30 @@ Q_GLOBAL_STATIC(Win32Helper, g_win32Helper)
|
||||||
wcex.lpfnWndProc = FallbackTitleBarWindowProc;
|
wcex.lpfnWndProc = FallbackTitleBarWindowProc;
|
||||||
wcex.hInstance = instance;
|
wcex.hInstance = instance;
|
||||||
if (RegisterClassExW(&wcex) != INVALID_ATOM) {
|
if (RegisterClassExW(&wcex) != INVALID_ATOM) {
|
||||||
|
FramelessHelper::Core::registerUninitializeHook([](){
|
||||||
|
g_win32Helper()->mutex.lock();
|
||||||
|
if (!g_win32Helper()->fallbackTitleBarToParentWindowMapping.isEmpty()) {
|
||||||
|
auto it = g_win32Helper()->fallbackTitleBarToParentWindowMapping.constBegin();
|
||||||
|
while (it != g_win32Helper()->fallbackTitleBarToParentWindowMapping.constEnd()) {
|
||||||
|
const auto hwnd = reinterpret_cast<HWND>(it.key());
|
||||||
|
Q_ASSERT(hwnd);
|
||||||
|
if (hwnd && (DestroyWindow(hwnd) == FALSE)) {
|
||||||
|
WARNING << Utils::getSystemErrorMessage(kDestroyWindow);
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
g_win32Helper()->fallbackTitleBarToParentWindowMapping.clear();
|
||||||
|
}
|
||||||
|
g_win32Helper()->mutex.unlock();
|
||||||
|
const HINSTANCE instance = GetModuleHandleW(nullptr);
|
||||||
|
if (!instance) {
|
||||||
|
WARNING << Utils::getSystemErrorMessage(kGetModuleHandleW);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (UnregisterClassW(kFallbackTitleBarWindowClassName, instance) == FALSE) {
|
||||||
|
WARNING << Utils::getSystemErrorMessage(kUnregisterClassW);
|
||||||
|
}
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
WARNING << Utils::getSystemErrorMessage(kRegisterClassExW);
|
WARNING << Utils::getSystemErrorMessage(kRegisterClassExW);
|
||||||
|
@ -523,7 +513,7 @@ void FramelessHelperWin::addWindow(const SystemParameters ¶ms)
|
||||||
const bool dark = Utils::shouldAppsUseDarkMode();
|
const bool dark = Utils::shouldAppsUseDarkMode();
|
||||||
static const bool isQtQuickApplication = (params.getCurrentApplicationType() == ApplicationType::Quick);
|
static const bool isQtQuickApplication = (params.getCurrentApplicationType() == ApplicationType::Quick);
|
||||||
// Tell DWM we may need dark theme non-client area (title bar & frame border).
|
// Tell DWM we may need dark theme non-client area (title bar & frame border).
|
||||||
FramelessHelper::Core::setApplicationOSThemeAware(true, isQtQuickApplication);
|
FramelessHelper::Core::setApplicationOSThemeAware(isQtQuickApplication);
|
||||||
Utils::updateWindowFrameBorderColor(windowId, dark);
|
Utils::updateWindowFrameBorderColor(windowId, dark);
|
||||||
static const bool isWin10RS5OrGreater = Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1809);
|
static const bool isWin10RS5OrGreater = Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1809);
|
||||||
if (isWin10RS5OrGreater) {
|
if (isWin10RS5OrGreater) {
|
||||||
|
|
|
@ -271,7 +271,7 @@ void registerUninitializeHook(const UninitializeHookCallback &cb)
|
||||||
coreData()->uninitHooks.append(cb);
|
coreData()->uninitHooks.append(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setApplicationOSThemeAware(const bool enable, const bool pureQuick)
|
void setApplicationOSThemeAware(const bool pureQuick)
|
||||||
{
|
{
|
||||||
static bool set = false;
|
static bool set = false;
|
||||||
if (set) {
|
if (set) {
|
||||||
|
@ -280,9 +280,8 @@ void setApplicationOSThemeAware(const bool enable, const bool pureQuick)
|
||||||
set = true;
|
set = true;
|
||||||
|
|
||||||
#if (defined(Q_OS_WINDOWS) && (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)))
|
#if (defined(Q_OS_WINDOWS) && (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)))
|
||||||
Utils::setQtDarkModeAwareEnabled(enable, pureQuick);
|
Utils::setQtDarkModeAwareEnabled(true, pureQuick);
|
||||||
#else
|
#else
|
||||||
Q_UNUSED(enable);
|
|
||||||
Q_UNUSED(pureQuick);
|
Q_UNUSED(pureQuick);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -567,6 +567,24 @@ Q_GLOBAL_STATIC(MacUtilsData, g_macUtilsData);
|
||||||
const auto proxy = new NSWindowProxy(qwindow, nswindow);
|
const auto proxy = new NSWindowProxy(qwindow, nswindow);
|
||||||
g_macUtilsData()->hash.insert(windowId, proxy);
|
g_macUtilsData()->hash.insert(windowId, proxy);
|
||||||
}
|
}
|
||||||
|
static const int hook = []() -> int {
|
||||||
|
FramelessHelper::Core::registerUninitializeHook([](){
|
||||||
|
const QMutexLocker locker(&g_macUtilsData()->mutex);
|
||||||
|
if (g_macUtilsData()->hash.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (auto &&proxy : qAsConst(g_macUtilsData()->hash)) {
|
||||||
|
Q_ASSERT(proxy);
|
||||||
|
if (!proxy) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
delete proxy;
|
||||||
|
}
|
||||||
|
g_macUtilsData()->hash.clear();
|
||||||
|
});
|
||||||
|
return 0;
|
||||||
|
}();
|
||||||
|
Q_UNUSED(hook);
|
||||||
return g_macUtilsData()->hash.value(windowId);
|
return g_macUtilsData()->hash.value(windowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -240,41 +240,6 @@ private:
|
||||||
T *p = nullptr;
|
T *p = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WindowClassCleaner
|
|
||||||
{
|
|
||||||
explicit WindowClassCleaner(const HWND hWnd, const std::wstring &Class) : _hWnd(hWnd), _Class(Class)
|
|
||||||
{
|
|
||||||
Q_ASSERT(_hWnd);
|
|
||||||
Q_ASSERT(!_Class.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
~WindowClassCleaner()
|
|
||||||
{
|
|
||||||
if (!_hWnd || _Class.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (DestroyWindow(_hWnd) == FALSE) {
|
|
||||||
WARNING << Utils::getSystemErrorMessage(kDestroyWindow);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const HINSTANCE instance = GetModuleHandleW(nullptr);
|
|
||||||
if (!instance) {
|
|
||||||
WARNING << Utils::getSystemErrorMessage(kGetModuleHandleW);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (UnregisterClassW(_Class.c_str(), instance) == FALSE) {
|
|
||||||
WARNING << Utils::getSystemErrorMessage(kUnregisterClassW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Q_DISABLE_COPY_MOVE(WindowClassCleaner)
|
|
||||||
|
|
||||||
private:
|
|
||||||
const HWND _hWnd = nullptr;
|
|
||||||
const std::wstring _Class = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
[[nodiscard]] static inline QString dwmRegistryKey()
|
[[nodiscard]] static inline QString dwmRegistryKey()
|
||||||
{
|
{
|
||||||
static const QString key = QString::fromWCharArray(kDwmRegistryKey);
|
static const QString key = QString::fromWCharArray(kDwmRegistryKey);
|
||||||
|
@ -319,7 +284,20 @@ private:
|
||||||
WARNING << Utils::getSystemErrorMessage(kCreateWindowExW);
|
WARNING << Utils::getSystemErrorMessage(kCreateWindowExW);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
static const auto cleaner = WindowClassCleaner(window, kDummyWindowClassName);
|
FramelessHelper::Core::registerUninitializeHook([window](){
|
||||||
|
if (window && (DestroyWindow(window) == FALSE)) {
|
||||||
|
WARNING << Utils::getSystemErrorMessage(kDestroyWindow);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const HINSTANCE instance = GetModuleHandleW(nullptr);
|
||||||
|
if (!instance) {
|
||||||
|
WARNING << Utils::getSystemErrorMessage(kGetModuleHandleW);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (UnregisterClassW(kDummyWindowClassName, instance) == FALSE) {
|
||||||
|
WARNING << Utils::getSystemErrorMessage(kUnregisterClassW);
|
||||||
|
}
|
||||||
|
});
|
||||||
return window;
|
return window;
|
||||||
}();
|
}();
|
||||||
return hwnd;
|
return hwnd;
|
||||||
|
|
Loading…
Reference in New Issue