Skip to content
This repository has been archived by the owner on Dec 19, 2023. It is now read-only.

Commit

Permalink
win: reshuffle code a bit
Browse files Browse the repository at this point in the history
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
  • Loading branch information
wangwenx190 committed Nov 9, 2022
1 parent 8c35eb9 commit c86a3fe
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 31 deletions.
2 changes: 2 additions & 0 deletions include/FramelessHelper/Core/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ FRAMELESSHELPER_CORE_API void refreshWin32ThemeResources(const WId windowId, con
FRAMELESSHELPER_CORE_API void enableNonClientAreaDpiScalingForWindow(const WId windowId);
[[nodiscard]] FRAMELESSHELPER_CORE_API
Global::DpiAwareness getDpiAwarenessForCurrentProcess(bool *highest = nullptr);
FRAMELESSHELPER_CORE_API void fixupChildWindowsDpiMessage(const WId windowId);
FRAMELESSHELPER_CORE_API void fixupDialogsDpiScaling();
#endif // Q_OS_WINDOWS

#ifdef Q_OS_LINUX
Expand Down
23 changes: 7 additions & 16 deletions src/core/framelesshelper_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@
#include "winverhelper_p.h"
#include "framelesshelper_windows.h"

EXTERN_C BOOL WINAPI EnableChildWindowDpiMessage2(const HWND hWnd, const BOOL fEnable);

FRAMELESSHELPER_BEGIN_NAMESPACE

Q_LOGGING_CATEGORY(lcFramelessHelperWin, "wangwenx190.framelesshelper.core.impl.win")
Expand Down Expand Up @@ -75,7 +73,6 @@ FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent)
FRAMELESSHELPER_STRING_CONSTANT(FindWindowW)
FRAMELESSHELPER_STRING_CONSTANT(UnregisterClassW)
FRAMELESSHELPER_STRING_CONSTANT(DestroyWindow)
FRAMELESSHELPER_STRING_CONSTANT(EnableChildWindowDpiMessage)
[[maybe_unused]] static constexpr const char kFallbackTitleBarErrorMessage[] =
"FramelessHelper is unable to create the fallback title bar window, and thus the snap layout feature will be disabled"
" unconditionally. You can ignore this error and continue running your application, nothing else will be affected, "
Expand All @@ -102,12 +99,14 @@ Q_GLOBAL_STATIC(Win32Helper, g_win32Helper)

[[nodiscard]] static inline QString hwnd2str(const WId windowId)
{
// NULL handle is allowed here.
return FRAMELESSHELPER_STRING_LITERAL("0x")
+ QString::number(windowId, 16).toUpper();
}

[[nodiscard]] static inline QString hwnd2str(const HWND hwnd)
{
// NULL handle is allowed here.
return hwnd2str(reinterpret_cast<WId>(hwnd));
}

Expand Down Expand Up @@ -536,18 +535,10 @@ void FramelessHelperWin::addWindow(const SystemParameters &params)
Utils::updateWindowFrameMargins(windowId, false);
// Tell DWM we don't use the window icon/caption/sysmenu, don't draw them.
Utils::hideOriginalTitleBarElements(windowId);
// We don't need this hack on Win10 1607 and newer, the PMv2 DPI awareness
// mode will take care of it for us by default.
if (WindowsVersionHelper::isWin10OrGreater()
&& !WindowsVersionHelper::isWin10RS1OrGreater()) {
// Without this hack, child windows can't get DPI change messages,
// which means only top level windows can scale to the correct size.
if (EnableChildWindowDpiMessage2(reinterpret_cast<HWND>(windowId), TRUE) == FALSE) {
if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) {
WARNING << Utils::getSystemErrorMessage(kEnableChildWindowDpiMessage);
}
}
}
// Without this hack, the child windows can't get DPI change messages from
// Windows, which means only the top level windows can be scaled to the correct
// size, we of course don't want such thing from happening.
Utils::fixupChildWindowsDpiMessage(windowId);
if (WindowsVersionHelper::isWin10RS1OrGreater()) {
// Tell DWM we may need dark theme non-client area (title bar & frame border).
FramelessHelper::Core::setApplicationOSThemeAware();
Expand Down Expand Up @@ -649,7 +640,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
// Enable automatic DPI scaling for the non-client area of the window,
// such as the caption bar, the scrollbars, and the menu bar. We need
// to do this explicitly and manually here (only inside WM_NCCREATE).
// If we are using the PMv2 DPI awareness level, the non-client area
// If we are using the PMv2 DPI awareness mode, the non-client area
// of the window will be scaled by the OS automatically, so there will
// be no need to do this in that case.
Utils::enableNonClientAreaDpiScalingForWindow(windowId);
Expand Down
7 changes: 6 additions & 1 deletion src/core/framelesshelpercore_global.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,17 @@ void initialize()
#ifdef Q_OS_WINDOWS
// This is equivalent to set the "dpiAware" and "dpiAwareness" field in
// your manifest file. It works through out Windows Vista to Windows 11.
// It's highly recommended to enable the highest DPI awareness level
// It's highly recommended to enable the highest DPI awareness mode
// (currently it's PerMonitor Version 2, or PMv2 for short) for any GUI
// applications, to allow your user interface scale to an appropriate
// size and still stay sharp, though you will have to do the calculation
// and resize by yourself.
Utils::tryToEnableHighestDpiAwarenessLevel();
// This function need to be called before any dialogs are created, so
// to be safe we call it here.
// Without this hack, our native dialogs won't be able to respond to
// DPI change messages correctly, especially the non-client area.
Utils::fixupDialogsDpiScaling();
#endif

// This attribute is known to be __NOT__ compatible with QGLWidget.
Expand Down
60 changes: 46 additions & 14 deletions src/core/utils_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1850,18 +1850,6 @@ void Utils::setAeroSnappingEnabled(const WId windowId, const bool enable)

void Utils::tryToEnableHighestDpiAwarenessLevel()
{
// We don't need this hack when running on Win10 1607 and newer, the PMv2
// DPI awareness mode will take care of it for us by default.
if (WindowsVersionHelper::isWin10OrGreater()
&& !WindowsVersionHelper::isWin10RS1OrGreater()) {
// This function need to be called before any dialogs are created, so
// to be safe we call it here.
if (EnablePerMonitorDialogScaling2() == FALSE) {
if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) {
WARNING << getSystemErrorMessage(kEnablePerMonitorDialogScaling);
}
}
}
bool isHighestAlready = false;
const DpiAwareness currentAwareness = getDpiAwarenessForCurrentProcess(&isHighestAlready);
DEBUG << "Current DPI awareness mode:" << currentAwareness;
Expand Down Expand Up @@ -2490,8 +2478,7 @@ void Utils::enableNonClientAreaDpiScalingForWindow(const WId windowId)
if (!API_USER_AVAILABLE(EnableNonClientDpiScaling)) {
return;
}
// There's no need to enable automatic non-client area DPI scaling for PMv2,
// PMv2 will enable it for us by default.
// The PMv2 DPI awareness mode will take care of it for us.
if (getDpiAwarenessForCurrentProcess() == DpiAwareness::PerMonitorVersion2) {
return;
}
Expand Down Expand Up @@ -2607,4 +2594,49 @@ DpiAwareness Utils::getDpiAwarenessForCurrentProcess(bool *highest)
return DpiAwareness::Unknown;
}

void Utils::fixupChildWindowsDpiMessage(const WId windowId)
{
Q_ASSERT(windowId);
if (!windowId) {
return;
}
// This hack is only available on Windows 10 and newer, and starting from
// Win10 1607 it become useless due to the PMv2 DPI awareness mode already
// takes care of it for us.
if (!WindowsVersionHelper::isWin10OrGreater()
|| (WindowsVersionHelper::isWin10RS1OrGreater()
&& (getDpiAwarenessForCurrentProcess() == DpiAwareness::PerMonitorVersion2))) {
return;
}
const auto hwnd = reinterpret_cast<HWND>(windowId);
if (EnableChildWindowDpiMessage2(hwnd, TRUE) != FALSE) {
return;
}
// This API is not available on current platform, it's fine.
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
return;
}
WARNING << getSystemErrorMessage(kEnableChildWindowDpiMessage);
}

void Utils::fixupDialogsDpiScaling()
{
// This hack is only available on Windows 10 and newer, and starting from
// Win10 1607 it become useless due to the PMv2 DPI awareness mode already
// takes care of it for us.
if (!WindowsVersionHelper::isWin10OrGreater()
|| (WindowsVersionHelper::isWin10RS1OrGreater()
&& (getDpiAwarenessForCurrentProcess() == DpiAwareness::PerMonitorVersion2))) {
return;
}
if (EnablePerMonitorDialogScaling2() != FALSE) {
return;
}
// This API is not available on current platform, it's fine.
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
return;
}
WARNING << getSystemErrorMessage(kEnablePerMonitorDialogScaling);
}

FRAMELESSHELPER_END_NAMESPACE

0 comments on commit c86a3fe

Please sign in to comment.