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
|
||||
// some private functions from QPA which won't be available until there's
|
||||
// a QGuiApplication instance.
|
||||
FramelessHelper::Core::setApplicationOSThemeAware(true, false);
|
||||
FramelessHelper::Core::setApplicationOSThemeAware(false);
|
||||
|
||||
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
||||
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
|
||||
// some private functions from QPA which won't be available until there's
|
||||
// a QGuiApplication instance.
|
||||
FramelessHelper::Core::setApplicationOSThemeAware(true, false);
|
||||
FramelessHelper::Core::setApplicationOSThemeAware(false);
|
||||
|
||||
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
||||
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
|
||||
// some private functions from QPA which won't be available until there's
|
||||
// a QGuiApplication instance.
|
||||
FramelessHelper::Core::setApplicationOSThemeAware(true, false);
|
||||
FramelessHelper::Core::setApplicationOSThemeAware(false);
|
||||
|
||||
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
||||
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
|
||||
// some private functions from QPA which won't be available until there's
|
||||
// a QGuiApplication instance.
|
||||
FramelessHelper::Core::setApplicationOSThemeAware(true, true);
|
||||
FramelessHelper::Core::setApplicationOSThemeAware(true);
|
||||
|
||||
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
||||
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
|
||||
// some private functions from QPA which won't be available until there's
|
||||
// a QGuiApplication instance.
|
||||
FramelessHelper::Core::setApplicationOSThemeAware(true, false);
|
||||
FramelessHelper::Core::setApplicationOSThemeAware(false);
|
||||
|
||||
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
||||
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
||||
|
|
|
@ -579,7 +579,7 @@ FRAMELESSHELPER_CORE_API void uninitialize();
|
|||
[[nodiscard]] FRAMELESSHELPER_CORE_API Global::VersionInfo version();
|
||||
FRAMELESSHELPER_CORE_API void registerInitializeHook(const Global::InitializeHookCallback &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
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -101,7 +101,7 @@ void FramelessHelperQt::addWindow(const SystemParameters ¶ms)
|
|||
Utils::setSystemTitleBarVisible(windowId, false);
|
||||
#endif
|
||||
static const bool isQtQuickApplication = (params.getCurrentApplicationType() == ApplicationType::Quick);
|
||||
FramelessHelper::Core::setApplicationOSThemeAware(true, isQtQuickApplication);
|
||||
FramelessHelper::Core::setApplicationOSThemeAware(isQtQuickApplication);
|
||||
}
|
||||
|
||||
bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
#include <QtCore/qcoreapplication.h>
|
||||
#include <QtCore/qtimer.h>
|
||||
#include <QtGui/qwindow.h>
|
||||
#include "framelessmanager.h"
|
||||
#include "framelessmanager_p.h"
|
||||
|
@ -74,6 +73,7 @@ FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent)
|
|||
FRAMELESSHELPER_STRING_CONSTANT(FindWindowW)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(UnregisterClassW)
|
||||
FRAMELESSHELPER_BYTEARRAY_CONSTANT2(DontOverrideCursor, "FRAMELESSHELPER_DONT_OVERRIDE_CURSOR")
|
||||
FRAMELESSHELPER_STRING_CONSTANT(DestroyWindow)
|
||||
|
||||
struct Win32HelperData
|
||||
{
|
||||
|
@ -92,21 +92,6 @@ struct 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
|
||||
(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_NCRBUTTONUP:
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
@ -448,6 +414,30 @@ Q_GLOBAL_STATIC(Win32Helper, g_win32Helper)
|
|||
wcex.lpfnWndProc = FallbackTitleBarWindowProc;
|
||||
wcex.hInstance = instance;
|
||||
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;
|
||||
}
|
||||
WARNING << Utils::getSystemErrorMessage(kRegisterClassExW);
|
||||
|
@ -523,7 +513,7 @@ void FramelessHelperWin::addWindow(const SystemParameters ¶ms)
|
|||
const bool dark = Utils::shouldAppsUseDarkMode();
|
||||
static const bool isQtQuickApplication = (params.getCurrentApplicationType() == ApplicationType::Quick);
|
||||
// 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);
|
||||
static const bool isWin10RS5OrGreater = Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1809);
|
||||
if (isWin10RS5OrGreater) {
|
||||
|
|
|
@ -271,7 +271,7 @@ void registerUninitializeHook(const UninitializeHookCallback &cb)
|
|||
coreData()->uninitHooks.append(cb);
|
||||
}
|
||||
|
||||
void setApplicationOSThemeAware(const bool enable, const bool pureQuick)
|
||||
void setApplicationOSThemeAware(const bool pureQuick)
|
||||
{
|
||||
static bool set = false;
|
||||
if (set) {
|
||||
|
@ -280,9 +280,8 @@ void setApplicationOSThemeAware(const bool enable, const bool pureQuick)
|
|||
set = true;
|
||||
|
||||
#if (defined(Q_OS_WINDOWS) && (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)))
|
||||
Utils::setQtDarkModeAwareEnabled(enable, pureQuick);
|
||||
Utils::setQtDarkModeAwareEnabled(true, pureQuick);
|
||||
#else
|
||||
Q_UNUSED(enable);
|
||||
Q_UNUSED(pureQuick);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -567,6 +567,24 @@ Q_GLOBAL_STATIC(MacUtilsData, g_macUtilsData);
|
|||
const auto proxy = new NSWindowProxy(qwindow, nswindow);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -240,41 +240,6 @@ private:
|
|||
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()
|
||||
{
|
||||
static const QString key = QString::fromWCharArray(kDwmRegistryKey);
|
||||
|
@ -319,7 +284,20 @@ private:
|
|||
WARNING << Utils::getSystemErrorMessage(kCreateWindowExW);
|
||||
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 hwnd;
|
||||
|
|
Loading…
Reference in New Issue