Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-03-23 10:48:22 +08:00
parent d3157699ef
commit d94f8221d3
11 changed files with 169 additions and 33 deletions

View File

@ -23,10 +23,17 @@
*/
#include <QtWidgets/qapplication.h>
#include <Utils>
#include "mainwindow.h"
FRAMELESSHELPER_USE_NAMESPACE
int main(int argc, char *argv[])
{
#ifdef Q_OS_WINDOWS
Utils::tryToEnableHighestDpiAwarenessLevel();
#endif
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);

View File

@ -27,11 +27,16 @@
#include <QtQuick/qquickwindow.h>
#include <QtQuickControls2/qquickstyle.h>
#include <FramelessHelper_Quick>
#include <Utils>
FRAMELESSHELPER_USE_NAMESPACE
int main(int argc, char *argv[])
{
#ifdef Q_OS_WINDOWS
Utils::tryToEnableHighestDpiAwarenessLevel();
#endif
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);

View File

@ -23,10 +23,17 @@
*/
#include <QtWidgets/qapplication.h>
#include <Utils>
#include "widget.h"
FRAMELESSHELPER_USE_NAMESPACE
int main(int argc, char *argv[])
{
#ifdef Q_OS_WINDOWS
Utils::tryToEnableHighestDpiAwarenessLevel();
#endif
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);

View File

@ -141,6 +141,14 @@ using PTIMECAPS = TIMECAPS *;
using NPTIMECAPS = TIMECAPS NEAR *;
using LPTIMECAPS = TIMECAPS FAR *;
using PROCESS_DPI_AWARENESS = enum PROCESS_DPI_AWARENESS
{
PROCESS_DPI_UNAWARE = 0,
PROCESS_SYSTEM_DPI_AWARE = 1,
PROCESS_PER_MONITOR_DPI_AWARE = 2,
PROCESS_PER_MONITOR_DPI_AWARE_V2 = 3
};
using MONITOR_DPI_TYPE = enum MONITOR_DPI_TYPE
{
MDT_EFFECTIVE_DPI = 0,
@ -165,6 +173,11 @@ timeEndPeriod(
_In_ UINT uPeriod
);
EXTERN_C HRESULT WINAPI
SetProcessDpiAwareness(
_In_ PROCESS_DPI_AWARENESS value
);
EXTERN_C HRESULT WINAPI
GetDpiForMonitor(
_In_ HMONITOR hMonitor,
@ -173,14 +186,12 @@ GetDpiForMonitor(
_Out_ UINT *dpiY
);
#include <QtCore/qstring.h>
[[maybe_unused]] static constexpr const int kAutoHideTaskBarThickness = 2; // The thickness of an auto-hide taskbar in pixels.
[[maybe_unused]] static const QString kDwmRegistryKey = QStringLiteral(R"(Software\Microsoft\Windows\DWM)");
[[maybe_unused]] static const QString kPersonalizeRegistryKey = QStringLiteral(R"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)");
[[maybe_unused]] static const QString kThemeSettingChangeEventName = QStringLiteral("ImmersiveColorSet");
[[maybe_unused]] static const QString kDwmColorKeyName = QStringLiteral("ColorPrevalence");
[[maybe_unused]] static constexpr const char kDwmRegistryKey[] = R"(Software\Microsoft\Windows\DWM)";
[[maybe_unused]] static constexpr const char kPersonalizeRegistryKey[] = R"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)";
[[maybe_unused]] static constexpr const char kThemeSettingChangeEventName[] = "ImmersiveColorSet";
[[maybe_unused]] static constexpr const char kDwmColorKeyName[] = "ColorPrevalence";
[[maybe_unused]] static constexpr const DWORD _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19;
[[maybe_unused]] static constexpr const DWORD _DWMWA_USE_IMMERSIVE_DARK_MODE = 20;

View File

@ -73,6 +73,14 @@
# define Q_NODISCARD
#endif
#ifndef QUtf8String
# define QUtf8String(str) QString::fromUtf8(str)
#endif
#ifndef QU8Str
# define QU8Str(str) QUtf8String(str)
#endif
#ifndef FRAMELESSHELPER_NAMESPACE
# define FRAMELESSHELPER_NAMESPACE __flh_ns
#endif
@ -112,6 +120,7 @@ Q_NAMESPACE_EXPORT(FRAMELESSHELPER_CORE_API)
[[maybe_unused]] static constexpr const char kUsePureQtImplFlag[] = "FRAMELESSHELPER_PURE_QT_IMPLEMENTATION";
[[maybe_unused]] static constexpr const char kForceHideFrameBorderFlag[] = "FRAMELESSHELPER_FORCE_HIDE_FRAME_BORDER";
[[maybe_unused]] static constexpr const char kForceShowFrameBorderFlag[] = "FRAMELESSHELPER_FORCE_SHOW_FRAME_BORDER";
[[maybe_unused]] static constexpr const char kSystemMenuOffsetFlag[] = "FRAMELESSHELPER_SYSTEM_MENU_OFFSET";
[[maybe_unused]] static const QString kConfigFileName = QStringLiteral(".framelesshelper.ini");
[[maybe_unused]] static const QString kUsePureQtImplKeyPath = QStringLiteral("Options/UsePureQtImplementation");

View File

@ -28,6 +28,10 @@
#include <QtGui/qwindowdefs.h>
#include <functional>
QT_BEGIN_NAMESPACE
class QScreen;
QT_END_NAMESPACE
FRAMELESSHELPER_BEGIN_NAMESPACE
enum class SystemTheme : int
@ -69,7 +73,12 @@ Q_ENUM_NS(DwmColorizationArea)
#endif
using GetWindowFlagsCallback = std::function<Qt::WindowFlags()>;
using SetWindowFlagsCallback = std::function<void(Qt::WindowFlags)>;
using SetWindowFlagsCallback = std::function<void(const Qt::WindowFlags)>;
using GetWindowSizeCallback = std::function<QSize()>;
using MoveWindowCallback = std::function<void(const int, const int)>;
using GetWindowScreenCallback = std::function<QScreen *()>;
namespace Utils
{
@ -83,7 +92,8 @@ FRAMELESSHELPER_CORE_API void startSystemResize(QWindow *window, const Qt::Edges
(const SystemButtonType button, const SystemTheme theme, const ResourceType type);
FRAMELESSHELPER_CORE_API void sendMouseReleaseEvent();
[[nodiscard]] FRAMELESSHELPER_CORE_API QWindow *findWindow(const WId winId);
FRAMELESSHELPER_CORE_API void moveWindowToDesktopCenter(QWindow *window, const bool considerTaskBar);
FRAMELESSHELPER_CORE_API void moveWindowToDesktopCenter(const GetWindowScreenCallback &getWindowScreen,
const GetWindowSizeCallback &getWindowSize, const MoveWindowCallback &moveWindow, const bool considerTaskBar);
#ifdef Q_OS_WINDOWS
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWin8OrGreater();
@ -120,6 +130,8 @@ FRAMELESSHELPER_CORE_API void installSystemMenuHook(const QWindow *window);
FRAMELESSHELPER_CORE_API void uninstallSystemMenuHook(const WId winId);
FRAMELESSHELPER_CORE_API void tryToBeCompatibleWithQtFramelessWindowHint(const WId winId,
const GetWindowFlagsCallback &getWindowFlags, const SetWindowFlagsCallback &setWindowFlags, const bool enable);
FRAMELESSHELPER_CORE_API void disableAeroSnapping(const WId winId);
FRAMELESSHELPER_CORE_API void tryToEnableHighestDpiAwarenessLevel();
#endif // Q_OS_WINDOWS
} // namespace Utils

View File

@ -679,7 +679,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
if (Utils::isWin10OrGreater()) {
if (msg->message == WM_SETTINGCHANGE) {
if ((msg->wParam == 0) && (QString::fromWCharArray(reinterpret_cast<LPCWSTR>(msg->lParam))
.compare(kThemeSettingChangeEventName, Qt::CaseInsensitive) == 0)) {
.compare(QU8Str(kThemeSettingChangeEventName), Qt::CaseInsensitive) == 0)) {
return true;
}
}

View File

@ -209,9 +209,6 @@ void FramelessWindowsManager::addWindow(QWindow *window)
Utils::installSystemMenuHook(window);
}
#endif
if (!(options & Option::DontMoveWindowToDesktopCenter)) {
Utils::moveWindowToDesktopCenter(window, true);
}
}
void FramelessWindowsManager::removeWindow(QWindow *window)

View File

@ -25,8 +25,8 @@
#include "utils.h"
#include <QtCore/qvariant.h>
#include <QtGui/qwindow.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qscreen.h>
#include <QtGui/qguiapplication.h>
// The "Q_INIT_RESOURCE()" macro can't be used within a namespace,
// so we wrap it into a separate function outside of the namespace and
@ -172,20 +172,25 @@ QWindow *Utils::findWindow(const WId winId)
return nullptr;
}
void Utils::moveWindowToDesktopCenter(QWindow *window, const bool considerTaskBar)
void Utils::moveWindowToDesktopCenter(const GetWindowScreenCallback &getWindowScreen,
const GetWindowSizeCallback &getWindowSize,
const MoveWindowCallback &moveWindow,
const bool considerTaskBar)
{
Q_ASSERT(window);
if (!window) {
Q_ASSERT(getWindowScreen);
Q_ASSERT(getWindowSize);
Q_ASSERT(moveWindow);
if (!getWindowScreen || !getWindowSize || !moveWindow) {
return;
}
const QSize windowSize = window->size();
const QSize windowSize = getWindowSize();
if (windowSize.isEmpty() || (windowSize == kInvalidWindowSize)) {
return;
}
const QScreen * const screen = [window]() -> const QScreen * {
const QScreen * const s = window->screen();
return (s ? s : QGuiApplication::primaryScreen());
}();
const QScreen *screen = getWindowScreen();
if (!screen) {
screen = QGuiApplication::primaryScreen();
}
Q_ASSERT(screen);
if (!screen) {
return;
@ -194,8 +199,7 @@ void Utils::moveWindowToDesktopCenter(QWindow *window, const bool considerTaskBa
const QPoint offset = (considerTaskBar ? screen->availableGeometry().topLeft() : QPoint(0, 0));
const auto newX = static_cast<int>(qRound(qreal(screenSize.width() - windowSize.width()) / 2.0));
const auto newY = static_cast<int>(qRound(qreal(screenSize.height() - windowSize.height()) / 2.0));
window->setX(newX + offset.x());
window->setY(newY + offset.y());
moveWindow(newX + offset.x(), newY + offset.y());
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -313,7 +313,7 @@ bool Utils::isDwmCompositionEnabled()
return true;
}
const auto resultFromRegistry = []() -> bool {
const QWinRegistryKey registry(HKEY_CURRENT_USER, kDwmRegistryKey);
const QWinRegistryKey registry(HKEY_CURRENT_USER, QU8Str(kDwmRegistryKey));
const auto result = registry.dwordValue(QStringLiteral("Composition"));
return (result.second && (result.first != 0));
};
@ -434,7 +434,7 @@ QString Utils::getSystemErrorMessage(const QString &function)
QColor Utils::getDwmColorizationColor()
{
const auto resultFromRegistry = []() -> QColor {
const QWinRegistryKey registry(HKEY_CURRENT_USER, kDwmRegistryKey);
const QWinRegistryKey registry(HKEY_CURRENT_USER, QU8Str(kDwmRegistryKey));
const auto result = registry.dwordValue(QStringLiteral("ColorizationColor"));
return (result.second ? QColor::fromRgba(result.first) : Qt::darkGray);
};
@ -461,7 +461,7 @@ bool Utils::shouldAppsUseDarkMode()
return false;
}
const auto resultFromRegistry = []() -> bool {
const QWinRegistryKey registry(HKEY_CURRENT_USER, kPersonalizeRegistryKey);
const QWinRegistryKey registry(HKEY_CURRENT_USER, QU8Str(kPersonalizeRegistryKey));
const auto result = registry.dwordValue(QStringLiteral("AppsUseLightTheme"));
return (result.second && (result.first == 0));
};
@ -478,10 +478,10 @@ DwmColorizationArea Utils::getDwmColorizationArea()
if (!isWin10OrGreater()) {
return DwmColorizationArea::None;
}
const QWinRegistryKey themeRegistry(HKEY_CURRENT_USER, kPersonalizeRegistryKey);
const auto themeValue = themeRegistry.dwordValue(kDwmColorKeyName);
const QWinRegistryKey dwmRegistry(HKEY_CURRENT_USER, kDwmRegistryKey);
const auto dwmValue = dwmRegistry.dwordValue(kDwmColorKeyName);
const QWinRegistryKey themeRegistry(HKEY_CURRENT_USER, QU8Str(kPersonalizeRegistryKey));
const auto themeValue = themeRegistry.dwordValue(QU8Str(kDwmColorKeyName));
const QWinRegistryKey dwmRegistry(HKEY_CURRENT_USER, QU8Str(kDwmRegistryKey));
const auto dwmValue = dwmRegistry.dwordValue(QU8Str(kDwmColorKeyName));
const bool theme = themeValue.second && (themeValue.first != 0);
const bool dwm = dwmValue.second && (dwmValue.first != 0);
if (theme && dwm) {
@ -506,7 +506,6 @@ void Utils::showSystemMenu(const QWindow *window, const QPoint &pos)
qWarning() << getSystemErrorMessage(QStringLiteral("GetSystemMenu"));
return;
}
// Update the options based on window state.
MENUITEMINFOW mii;
SecureZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii);
@ -545,8 +544,11 @@ void Utils::showSystemMenu(const QWindow *window, const QPoint &pos)
qWarning() << getSystemErrorMessage(QStringLiteral("SetMenuDefaultItem"));
return;
}
const QPoint offset = (maxOrFull ? QPoint(0, 0) : window->property(kSystemMenuOffsetFlag).toPoint());
const int xPos = (pos.x() + offset.x());
const int yPos = (pos.y() + offset.y());
const int ret = TrackPopupMenu(menu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft()
? TPM_RIGHTALIGN : TPM_LEFTALIGN)), pos.x(), pos.y(), 0, hWnd, nullptr);
? TPM_RIGHTALIGN : TPM_LEFTALIGN)), xPos, yPos, 0, hWnd, nullptr);
if (ret != 0) {
if (PostMessageW(hWnd, WM_SYSCOMMAND, ret, 0) == FALSE) {
qWarning() << getSystemErrorMessage(QStringLiteral("PostMessageW"));
@ -1108,4 +1110,72 @@ void Utils::tryToBeCompatibleWithQtFramelessWindowHint(const WId winId,
triggerFrameChange(winId);
}
void Utils::disableAeroSnapping(const WId winId)
{
Q_ASSERT(winId);
if (!winId) {
return;
}
const auto hwnd = reinterpret_cast<HWND>(winId);
SetLastError(ERROR_SUCCESS);
const auto oldWindowStyle = static_cast<DWORD>(GetWindowLongPtrW(hwnd, GWL_STYLE));
if (oldWindowStyle == 0) {
qWarning() << getSystemErrorMessage(QStringLiteral("GetWindowLongPtrW"));
return;
}
const DWORD newWindowStyle = ((oldWindowStyle & ~WS_THICKFRAME) | WS_POPUP);
SetLastError(ERROR_SUCCESS);
if (SetWindowLongPtrW(hwnd, GWL_STYLE, static_cast<LONG_PTR>(newWindowStyle)) == 0) {
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
return;
}
triggerFrameChange(winId);
}
void Utils::tryToEnableHighestDpiAwarenessLevel()
{
static const auto pSetProcessDpiAwarenessContext =
reinterpret_cast<decltype(&SetProcessDpiAwarenessContext)>(
QSystemLibrary::resolve(QStringLiteral("user32"), "SetProcessDpiAwarenessContext"));
if (pSetProcessDpiAwarenessContext) {
if (pSetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) != FALSE) {
return;
}
const DWORD dwError = GetLastError();
// "ERROR_ACCESS_DENIED" means set externally (mostly due to manifest file).
if (dwError == ERROR_ACCESS_DENIED) {
return;
}
if (pSetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE) != FALSE) {
return;
}
if (pSetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE) != FALSE) {
return;
}
if (pSetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED) != FALSE) {
return;
}
}
static const auto pSetProcessDpiAwareness =
reinterpret_cast<decltype(&SetProcessDpiAwareness)>(
QSystemLibrary::resolve(QStringLiteral("shcore"), "SetProcessDpiAwareness"));
if (pSetProcessDpiAwareness) {
if (SUCCEEDED(pSetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE_V2))) {
return;
}
const HRESULT hr = pSetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
if (SUCCEEDED(hr)) {
return;
}
// "E_ACCESSDENIED" means set externally (mostly due to manifest file).
if (hr == E_ACCESSDENIED) {
return;
}
if (SUCCEEDED(pSetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE))) {
return;
}
}
SetProcessDPIAware();
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -311,7 +311,7 @@ void FramelessWidgetsHelper::initialize()
if (m_options & Option::BeCompatibleWithQtFramelessWindowHint) {
Utils::tryToBeCompatibleWithQtFramelessWindowHint(q->winId(),
[this]() -> Qt::WindowFlags { return q->windowFlags(); },
[this](Qt::WindowFlags flags) -> void { q->setWindowFlags(flags); },
[this](const Qt::WindowFlags flags) -> void { q->setWindowFlags(flags); },
true);
}
FramelessWindowsManager *manager = FramelessWindowsManager::instance();
@ -325,6 +325,20 @@ void FramelessWidgetsHelper::initialize()
QMetaObject::invokeMethod(q, "systemThemeChanged");
});
setupInitialUi();
if (!(m_options & Option::DontMoveWindowToDesktopCenter)) {
Utils::moveWindowToDesktopCenter(
[this, window]() -> QScreen * {
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
Q_UNUSED(window);
return q->screen();
#else
return window->screen();
#endif
},
[this]() -> QSize { return q->size(); },
[this](const int x, const int y) -> void { q->move(x, y); },
true);
}
}
void FramelessWidgetsHelper::createSystemTitleBar()