minor tweaks

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-07-10 14:26:01 +08:00
parent 2f36d1f73e
commit 4f8106a009
6 changed files with 163 additions and 41 deletions

View File

@ -146,11 +146,11 @@
#ifndef _DPI_AWARENESS_CONTEXTS_
# define _DPI_AWARENESS_CONTEXTS_
DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
# define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1)
# define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT)-2)
# define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT)-3)
# define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4)
# define DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED ((DPI_AWARENESS_CONTEXT)-5)
# define DPI_AWARENESS_CONTEXT_UNAWARE (reinterpret_cast<DPI_AWARENESS_CONTEXT>(-1))
# define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE (reinterpret_cast<DPI_AWARENESS_CONTEXT>(-2))
# define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE (reinterpret_cast<DPI_AWARENESS_CONTEXT>(-3))
# define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (reinterpret_cast<DPI_AWARENESS_CONTEXT>(-4))
# define DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED (reinterpret_cast<DPI_AWARENESS_CONTEXT>(-5))
#endif
#ifndef STATUS_SUCCESS
@ -160,8 +160,6 @@
using NTSTATUS = LONG;
#ifndef WINMMAPI
# define WINMMAPI DECLSPEC_IMPORT
using MMRESULT = UINT;
using TIMECAPS = struct TIMECAPS
@ -190,6 +188,27 @@ using MONITOR_DPI_TYPE = enum MONITOR_DPI_TYPE
MDT_DEFAULT = MDT_EFFECTIVE_DPI
};
using DEVICE_SCALE_FACTOR = enum DEVICE_SCALE_FACTOR
{
DEVICE_SCALE_FACTOR_INVALID = 0,
SCALE_100_PERCENT = 100,
SCALE_120_PERCENT = 120,
SCALE_125_PERCENT = 125,
SCALE_140_PERCENT = 140,
SCALE_150_PERCENT = 150,
SCALE_160_PERCENT = 160,
SCALE_175_PERCENT = 175,
SCALE_180_PERCENT = 180,
SCALE_200_PERCENT = 200,
SCALE_225_PERCENT = 225,
SCALE_250_PERCENT = 250,
SCALE_300_PERCENT = 300,
SCALE_350_PERCENT = 350,
SCALE_400_PERCENT = 400,
SCALE_450_PERCENT = 450,
SCALE_500_PERCENT = 500
};
using _DWMWINDOWATTRIBUTE = enum _DWMWINDOWATTRIBUTE
{
_DWMWA_USE_HOSTBACKDROPBRUSH = 17, // [set] BOOL, Allows the use of host backdrop brushes for the window.
@ -290,18 +309,18 @@ using SetWindowCompositionAttributePtr = BOOL(WINAPI *)(HWND, PWINDOWCOMPOSITION
EXTERN_C_START
WINMMAPI MMRESULT WINAPI
DECLSPEC_IMPORT MMRESULT WINAPI
timeGetDevCaps(
_Out_writes_bytes_(cbtc) LPTIMECAPS ptc,
_In_ UINT cbtc
);
WINMMAPI MMRESULT WINAPI
DECLSPEC_IMPORT MMRESULT WINAPI
timeBeginPeriod(
_In_ UINT uPeriod
);
WINMMAPI MMRESULT WINAPI
DECLSPEC_IMPORT MMRESULT WINAPI
timeEndPeriod(
_In_ UINT uPeriod
);
@ -319,37 +338,43 @@ GetDpiForMonitor(
_Out_ UINT *dpiY
);
WINUSERAPI int WINAPI
DECLSPEC_IMPORT int WINAPI
GetSystemMetricsForDpi(
_In_ int nIndex,
_In_ UINT dpi
);
WINUSERAPI UINT WINAPI
DECLSPEC_IMPORT UINT WINAPI
GetDpiForWindow(
_In_ HWND hwnd
);
WINUSERAPI UINT WINAPI
DECLSPEC_IMPORT UINT WINAPI
GetDpiForSystem(
VOID
);
WINUSERAPI UINT WINAPI
DECLSPEC_IMPORT UINT WINAPI
GetSystemDpiForProcess(
_In_ HANDLE hProcess
);
WINUSERAPI BOOL WINAPI
DECLSPEC_IMPORT BOOL WINAPI
SetProcessDpiAwarenessContext(
_In_ DPI_AWARENESS_CONTEXT value
);
WINUSERAPI BOOL WINAPI
DECLSPEC_IMPORT BOOL WINAPI
SetProcessDPIAware(
VOID
);
DECLSPEC_IMPORT HRESULT WINAPI
GetScaleFactorForMonitor(
_In_ HMONITOR hMon,
_Out_ DEVICE_SCALE_FACTOR *pScale
);
EXTERN_C_END
[[maybe_unused]] static constexpr const int kAutoHideTaskBarThickness = 2; // The thickness of an auto-hide taskbar in pixels.

View File

@ -49,7 +49,7 @@ public:
static void setLoadFromEnvironmentVariablesDisabled(const bool on = true);
static void setLoadFromConfigurationFileDisabled(const bool on = true);
QVariant setInternal(const QString &key, const QVariant &value);
Q_NODISCARD QVariant setInternal(const QString &key, const QVariant &value);
Q_NODISCARD QVariant getInternal(const QString &key) const;
template<typename T>
Q_NODISCARD T getInternal(const QString &key) const

View File

@ -104,7 +104,7 @@ FRAMELESSHELPER_CORE_API void tryToEnableHighestDpiAwarenessLevel();
FRAMELESSHELPER_CORE_API void updateGlobalWin32ControlsTheme(const WId windowId, const bool dark);
[[nodiscard]] FRAMELESSHELPER_CORE_API bool shouldAppsUseDarkMode_windows();
FRAMELESSHELPER_CORE_API void forceSquareCornersForWindow(const WId windowId, const bool force);
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor getTitleBarAccentColor();
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor getDwmAccentColor();
#endif // Q_OS_WINDOWS
#ifdef Q_OS_LINUX

View File

@ -70,7 +70,7 @@ void ChromePalettePrivate::refresh()
titleBarActiveBackgroundColor_sys = [colorized, dark]() -> QColor {
if (colorized) {
#ifdef Q_OS_WINDOWS
return Utils::getTitleBarAccentColor();
return Utils::getDwmAccentColor();
#elif defined(Q_OS_LINUX)
return Utils::getWmThemeColor();
#elif defined(Q_OS_MACOS)

View File

@ -26,6 +26,7 @@
#include "framelessmanager.h"
#include <QtCore/qdebug.h>
#include <QtCore/qhash.h>
#include <QtCore/qmutex.h>
#include <QtCore/qcoreapplication.h>
#include <QtGui/qwindow.h>
#include <objc/runtime.h>
@ -365,8 +366,13 @@ private:
static inline sendEventPtr oldSendEvent = nil;
};
using NSWindowProxyHash = QHash<WId, NSWindowProxy *>;
Q_GLOBAL_STATIC(NSWindowProxyHash, g_nswindowOverrideHash);
struct MacUtilsData
{
QMutex mutex;
QHash<WId, NSWindowProxy *> hash = {};
};
Q_GLOBAL_STATIC(MacUtilsData, g_macUtilsData);
[[nodiscard]] static inline NSWindow *mac_getNSWindow(const WId windowId)
{
@ -388,7 +394,8 @@ Q_GLOBAL_STATIC(NSWindowProxyHash, g_nswindowOverrideHash);
if (!windowId) {
return nil;
}
if (!g_nswindowOverrideHash()->contains(windowId)) {
QMutexLocker locker(&g_macUtilsData()->mutex);
if (!g_macUtilsData()->hash.contains(windowId)) {
QWindow * const qwindow = Utils::findWindow(windowId);
Q_ASSERT(qwindow);
if (!qwindow) {
@ -400,9 +407,9 @@ Q_GLOBAL_STATIC(NSWindowProxyHash, g_nswindowOverrideHash);
return nil;
}
const auto proxy = new NSWindowProxy(qwindow, nswindow);
g_nswindowOverrideHash()->insert(windowId, proxy);
g_macUtilsData()->hash.insert(windowId, proxy);
}
return g_nswindowOverrideHash()->value(windowId);
return g_macUtilsData()->hash.value(windowId);
}
SystemTheme Utils::getSystemTheme()

View File

@ -139,6 +139,34 @@ FRAMELESSHELPER_STRING_CONSTANT(GetModuleHandleW)
FRAMELESSHELPER_STRING_CONSTANT(RegisterClassExW)
FRAMELESSHELPER_STRING_CONSTANT(CreateWindowExW)
FRAMELESSHELPER_STRING_CONSTANT(AccentColor)
FRAMELESSHELPER_STRING_CONSTANT(GetScaleFactorForMonitor)
struct SYSTEM_METRIC
{
int DPI_96 = 0; // 100%. The scale factor for the device is 1x.
int DPI_115 = 0; // 120%. The scale factor for the device is 1.2x.
int DPI_120 = 0; // 125%. The scale factor for the device is 1.25x.
int DPI_134 = 0; // 140%. The scale factor for the device is 1.4x.
int DPI_144 = 0; // 150%. The scale factor for the device is 1.5x.
int DPI_154 = 0; // 160%. The scale factor for the device is 1.6x.
int DPI_168 = 0; // 175%. The scale factor for the device is 1.75x.
int DPI_173 = 0; // 180%. The scale factor for the device is 1.8x.
int DPI_192 = 0; // 200%. The scale factor for the device is 2x.
int DPI_216 = 0; // 225%. The scale factor for the device is 2.25x.
int DPI_240 = 0; // 250%. The scale factor for the device is 2.5x.
int DPI_288 = 0; // 300%. The scale factor for the device is 3x.
int DPI_336 = 0; // 350%. The scale factor for the device is 3.5x.
int DPI_384 = 0; // 400%. The scale factor for the device is 4x.
int DPI_432 = 0; // 450%. The scale factor for the device is 4.5x.
int DPI_480 = 0; // 500%. The scale factor for the device is 5x.
};
static const QHash<int, SYSTEM_METRIC> g_systemMetricsTable = {
{SM_CYCAPTION, {23, 27, 29, 32, 34, 36, 40, 41, 45, 51, 56, 67, 78, 89, 100, 111}},
{SM_CXSIZEFRAME, { 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 8, 8}},
{SM_CYSIZEFRAME, { 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 8, 8}},
{SM_CXPADDEDBORDER, { 4, 5, 5, 6, 6, 6, 7, 7, 8, 9, 10, 12, 14, 16, 18, 20}}
};
template <typename T>
class HumbleComPtr
@ -325,15 +353,50 @@ private:
if (!windowId) {
return 0;
}
const UINT windowDpi = Utils::getWindowDpi(windowId, horizontal);
if (API_USER_AVAILABLE(GetSystemMetricsForDpi)) {
const UINT dpi = (scaled ? windowDpi : USER_DEFAULT_SCREEN_DPI);
return API_CALL_FUNCTION(GetSystemMetricsForDpi, index, dpi);
} else {
// The returned value is already scaled, we need to divide the dpr to get the unscaled value.
const qreal dpr = (scaled ? 1.0 : (qreal(windowDpi) / qreal(USER_DEFAULT_SCREEN_DPI)));
return qRound(qreal(GetSystemMetrics(index)) / dpr);
// NOTE: We deliberately don't use the "GetSystemMetrics(ForDpi)" function here,
// because in my testing process, I found in some abnormal cases it will always
// return the unscaled value (100% scale) regardless of what DPI we gave it. The
// exact reason is still unknown to me. To eliminate this uncertainty, I decided
// to return the hard-coded value directly.
// When DWM composition is disabled (only possible on Windows 7 in some rare cases),
// the thickness of the padded border will become 0.
if ((index == SM_CXPADDEDBORDER) && !Utils::isDwmCompositionEnabled()) {
return 0;
}
if (!g_systemMetricsTable.contains(index)) {
qWarning() << "FIXME: Add SYSTEM_METRIC value for index" << index;
return 0;
}
const SYSTEM_METRIC systemMetric = g_systemMetricsTable.value(index);
if (!scaled) {
return systemMetric.DPI_96;
}
const UINT dpi = Utils::getWindowDpi(windowId, horizontal);
#define DPI_CASE(x) case x: return systemMetric.DPI_##x;
switch (dpi) {
DPI_CASE(96)
DPI_CASE(115)
DPI_CASE(120)
DPI_CASE(134)
DPI_CASE(144)
DPI_CASE(154)
DPI_CASE(168)
DPI_CASE(173)
DPI_CASE(192)
DPI_CASE(216)
DPI_CASE(240)
DPI_CASE(288)
DPI_CASE(336)
DPI_CASE(384)
DPI_CASE(432)
DPI_CASE(480)
default:
qWarning() << "Unsupported DPI value:" << dpi;
return 0;
}
#undef DPI_CASE
}
[[maybe_unused]] [[nodiscard]] static inline
@ -842,7 +905,6 @@ bool Utils::isHighContrastModeEnabled()
quint32 Utils::getPrimaryScreenDpi(const bool horizontal)
{
if (API_SHCORE_AVAILABLE(GetDpiForMonitor)) {
const HMONITOR monitor = []() -> HMONITOR {
const HWND window = ensureDummyWindow();
if (window) {
@ -851,6 +913,7 @@ quint32 Utils::getPrimaryScreenDpi(const bool horizontal)
static constexpr const int kTaskBarSize = 100;
return MonitorFromPoint(POINT{kTaskBarSize, kTaskBarSize}, MONITOR_DEFAULTTOPRIMARY);
}();
if (API_SHCORE_AVAILABLE(GetDpiForMonitor)) {
if (monitor) {
UINT dpiX = 0, dpiY = 0;
const HRESULT hr = API_CALL_FUNCTION(GetDpiForMonitor, monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
@ -863,6 +926,19 @@ quint32 Utils::getPrimaryScreenDpi(const bool horizontal)
qWarning() << getSystemErrorMessage(kMonitorFromPoint);
}
}
if (API_SHCORE_AVAILABLE(GetScaleFactorForMonitor)) {
if (monitor) {
DEVICE_SCALE_FACTOR factor = DEVICE_SCALE_FACTOR_INVALID;
const HRESULT hr = API_CALL_FUNCTION(GetScaleFactorForMonitor, monitor, &factor);
if (SUCCEEDED(hr) && (factor != DEVICE_SCALE_FACTOR_INVALID)) {
return quint32(qRound(qreal(USER_DEFAULT_SCREEN_DPI) * qreal(factor) / qreal(100)));
} else {
qWarning() << __getSystemErrorMessage(kGetScaleFactorForMonitor, hr);
}
} else {
qWarning() << getSystemErrorMessage(kMonitorFromPoint);
}
}
if (API_D2D_AVAILABLE(D2D1CreateFactory)) {
using D2D1CreateFactoryPtr =
HRESULT(WINAPI *)(D2D1_FACTORY_TYPE, REFIID, CONST D2D1_FACTORY_OPTIONS *, void **);
@ -958,6 +1034,20 @@ quint32 Utils::getWindowDpi(const WId windowId, const bool horizontal)
qWarning() << getSystemErrorMessage(kMonitorFromWindow);
}
}
if (API_SHCORE_AVAILABLE(GetScaleFactorForMonitor)) {
const HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (monitor) {
DEVICE_SCALE_FACTOR factor = DEVICE_SCALE_FACTOR_INVALID;
const HRESULT hr = API_CALL_FUNCTION(GetScaleFactorForMonitor, monitor, &factor);
if (SUCCEEDED(hr) && (factor != DEVICE_SCALE_FACTOR_INVALID)) {
return quint32(qRound(qreal(USER_DEFAULT_SCREEN_DPI) * qreal(factor) / qreal(100)));
} else {
qWarning() << __getSystemErrorMessage(kGetScaleFactorForMonitor, hr);
}
} else {
qWarning() << getSystemErrorMessage(kMonitorFromWindow);
}
}
return getPrimaryScreenDpi(horizontal);
}
@ -1655,7 +1745,7 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode,
return false;
}
QColor Utils::getTitleBarAccentColor()
QColor Utils::getDwmAccentColor()
{
const QSettings registry(dwmRegistryKey(), QSettings::NativeFormat);
bool ok = false;