win: use qt own functions more

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-08-19 10:53:46 +08:00
parent a49756ee45
commit 1bce57445b
4 changed files with 56 additions and 8 deletions

View File

@ -116,12 +116,12 @@ There are also two classes called `FramelessWidget` and `FramelessMainWindow`, t
#### Code Snippet #### Code Snippet
First of all, call `void FramelessHelper::Core::initialize()` in your `main` function in a very early stage: First of all, call `void FramelessHelper::Widgets::initialize()` in your `main` function in a very early stage:
```cpp ```cpp
int main(int, char **) int main(int, char **)
{ {
FramelessHelper::Core::initialize(); FramelessHelper::Widgets::initialize();
// ... // ...
} }
``` ```
@ -167,12 +167,12 @@ void MyWidget::myFunction2()
#### Code Snippet #### Code Snippet
First of all, you should call `void FramelessHelper::Core::initialize()` in your `main` function in a very early stage: First of all, you should call `void FramelessHelper::Quick::initialize()` in your `main` function in a very early stage:
```cpp ```cpp
int main(int, char **) int main(int, char **)
{ {
FramelessHelper::Core::initialize(); FramelessHelper::Quick::initialize();
// ... // ...
} }
``` ```
@ -325,7 +325,7 @@ Please refer to the demo projects to see more detailed usages: [examples](./exam
### `When running on Wayland, dragging the title bar causes crash?` ### `When running on Wayland, dragging the title bar causes crash?`
You need to force Qt to use the **XCB** QPA when running on Wayland. Try setting the environment variable `QT_QPA_PLATFORM` to `xcb` before instantiating any `Q(Gui)Application` instances. Or just call `void FramelessHelper::Core::initialize()` in your `main` function, this function will take care of it for you. You need to force Qt to use the **XCB** QPA when running on Wayland. Try setting the environment variable `QT_QPA_PLATFORM` to `xcb` before instantiating any `Q(Gui)Application` instances. Or just call `void FramelessHelper::Widgets/Quick::initialize()` in your `main` function, this function will take care of it for you.
### `I can see the black background during window resizing?` ### `I can see the black background during window resizing?`

View File

@ -120,6 +120,7 @@ FRAMELESSHELPER_CORE_API void forceSquareCornersForWindow(const WId windowId, co
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor getDwmAccentColor(); [[nodiscard]] FRAMELESSHELPER_CORE_API QColor getDwmAccentColor();
FRAMELESSHELPER_CORE_API void disableOriginalTitleBarFunctionalities FRAMELESSHELPER_CORE_API void disableOriginalTitleBarFunctionalities
(const WId windowId, const bool disable = true); (const WId windowId, const bool disable = true);
FRAMELESSHELPER_CORE_API void setQtDarkModeAwareEnabled(const bool enable, const bool pureQuick);
#endif // Q_OS_WINDOWS #endif // Q_OS_WINDOWS
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX

View File

@ -464,8 +464,8 @@ Q_GLOBAL_STATIC(Win32Helper, g_win32Helper)
WARNING << Utils::getSystemErrorMessage(kCreateWindowExW); WARNING << Utils::getSystemErrorMessage(kCreateWindowExW);
return false; return false;
} }
// Layered window won't become visible unless you call SetLayeredWindowAttributes() // Layered windows won't become visible unless we call the SetLayeredWindowAttributes()
// or UpdateLayeredWindow(). // or UpdateLayeredWindow() function at least once.
if (SetLayeredWindowAttributes(fallbackTitleBarWindowHandle, 0, 255, LWA_ALPHA) == FALSE) { if (SetLayeredWindowAttributes(fallbackTitleBarWindowHandle, 0, 255, LWA_ALPHA) == FALSE) {
WARNING << Utils::getSystemErrorMessage(kSetLayeredWindowAttributes); WARNING << Utils::getSystemErrorMessage(kSetLayeredWindowAttributes);
return false; return false;
@ -519,11 +519,18 @@ void FramelessHelperWin::addWindow(const SystemParameters &params)
static const bool isWin10RS1OrGreater = Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1607); static const bool isWin10RS1OrGreater = Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1607);
if (isWin10RS1OrGreater) { if (isWin10RS1OrGreater) {
const bool dark = Utils::shouldAppsUseDarkMode(); 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). // Tell DWM we may need dark theme non-client area (title bar & frame border).
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
static bool darkModeAwareSet = false;
if (!darkModeAwareSet) {
darkModeAwareSet = true;
Utils::setQtDarkModeAwareEnabled(true, isQtQuickApplication);
}
#endif
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) {
static const bool isQtQuickApplication = (params.getCurrentApplicationType() == ApplicationType::Quick);
if (isQtQuickApplication) { if (isQtQuickApplication) {
// Tell UXTheme we may need dark theme controls. // Tell UXTheme we may need dark theme controls.
// Causes some QtWidgets paint incorrectly, so only apply to Qt Quick applications. // Causes some QtWidgets paint incorrectly, so only apply to Qt Quick applications.
@ -1126,7 +1133,9 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
&& (std::wcscmp(reinterpret_cast<LPCWSTR>(lParam), kThemeSettingChangeEventName) == 0)) { && (std::wcscmp(reinterpret_cast<LPCWSTR>(lParam), kThemeSettingChangeEventName) == 0)) {
systemThemeChanged = true; systemThemeChanged = true;
const bool dark = Utils::shouldAppsUseDarkMode(); const bool dark = Utils::shouldAppsUseDarkMode();
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
Utils::updateWindowFrameBorderColor(windowId, dark); Utils::updateWindowFrameBorderColor(windowId, dark);
#endif
static const bool isWin10RS5OrGreater = Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1809); static const bool isWin10RS5OrGreater = Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1809);
if (isWin10RS5OrGreater) { if (isWin10RS5OrGreater) {
static const bool isQtQuickApplication = (data.params.getCurrentApplicationType() == ApplicationType::Quick); static const bool isQtQuickApplication = (data.params.getCurrentApplicationType() == ApplicationType::Quick);

View File

@ -1904,4 +1904,42 @@ void Utils::disableOriginalTitleBarFunctionalities(const WId windowId, const boo
} }
} }
void Utils::setQtDarkModeAwareEnabled(const bool enable, const bool pureQuick)
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
using App = QNativeInterface::Private::QWindowsApplication;
if (const auto app = qApp->nativeInterface<App>()) {
app->setDarkModeHandling([enable, pureQuick]() -> App::DarkModeHandling {
if (!enable) {
return {};
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
Q_UNUSED(pureQuick);
// Enabling the DarkModeWindowFrames flag will save us the call of the
// DwmSetWindowAttribute function. Qt will adjust the non-client area
// (title bar & frame border) automatically.
// Enabling the DarkModeStyle flag will make Qt Widgets apply dark theme
// automatically when the system is in dark mode, but before Qt6.5 it's
// own dark theme is really broken, so don't use it before 6.5.
// There's no global dark theme for Qt Quick applications, so setting this
// flag has no effect for pure Qt Quick applications.
return {App::DarkModeWindowFrames | App::DarkModeStyle};
#else
if (pureQuick) {
// Pure Qt Quick application, it's OK to enable the DarkModeStyle flag.
return {App::DarkModeWindowFrames | App::DarkModeStyle};
}
// Don't try to use the broken dark theme for Qt Widgets applications.
return {App::DarkModeWindowFrames};
#endif
}());
} else {
WARNING << "QWindowsApplication is not available.";
}
#else
Q_UNUSED(enable);
Q_UNUSED(pureQuick);
#endif
}
FRAMELESSHELPER_END_NAMESPACE FRAMELESSHELPER_END_NAMESPACE