fix hidpi position calculation

Task-number: #210

Signed-off-by: Yuhang Zhao <zhaoyuhang@rankyee.com>
This commit is contained in:
Yuhang Zhao 2023-03-30 11:39:05 +08:00
parent 2a6b8e6ebe
commit 5ade3cfb74
7 changed files with 95 additions and 17 deletions

View File

@ -76,6 +76,10 @@ FRAMELESSHELPER_CORE_API void registerThemeChangeNotification();
[[nodiscard]] FRAMELESSHELPER_CORE_API QPoint fromNativePixels(const QWindow *window, const QPoint &point);
[[nodiscard]] FRAMELESSHELPER_CORE_API QSize fromNativePixels(const QWindow *window, const QSize &size);
[[nodiscard]] FRAMELESSHELPER_CORE_API QRect fromNativePixels(const QWindow *window, const QRect &rect);
[[nodiscard]] FRAMELESSHELPER_CORE_API QPoint toNativeLocalPosition(const QWindow *window, const QPoint &point);
[[nodiscard]] FRAMELESSHELPER_CORE_API QPoint toNativeGlobalPosition(const QWindow *window, const QPoint &point);
[[nodiscard]] FRAMELESSHELPER_CORE_API QPoint fromNativeLocalPosition(const QWindow *window, const QPoint &point);
[[nodiscard]] FRAMELESSHELPER_CORE_API QPoint fromNativeGlobalPosition(const QWindow *window, const QPoint &point);
[[nodiscard]] FRAMELESSHELPER_CORE_API int horizontalAdvance(const QFontMetrics &fm, const QString &str);
#ifdef Q_OS_WINDOWS

View File

@ -202,8 +202,8 @@ Q_GLOBAL_STATIC(Win32Helper, g_win32Helper)
WARNING << Utils::getSystemErrorMessage(kScreenToClient);
break;
}
const QPoint qtScenePos = Utils::fromNativePixels(data.params.getWindowHandle(),
QPoint(nativeLocalPos.x, nativeLocalPos.y));
const QPoint qtScenePos = Utils::fromNativeLocalPosition(
data.params.getWindowHandle(), QPoint(nativeLocalPos.x, nativeLocalPos.y));
SystemButtonType buttonType = SystemButtonType::Unknown;
if (data.params.isInsideSystemButtons(qtScenePos, &buttonType)) {
switch (buttonType) {
@ -1001,8 +1001,8 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
WARNING << Utils::getSystemErrorMessage(kScreenToClient);
break;
}
const QPoint qtScenePos = Utils::fromNativePixels(data.params.getWindowHandle(),
QPoint(nativeLocalPos.x, nativeLocalPos.y));
const QPoint qtScenePos = Utils::fromNativeLocalPosition(
data.params.getWindowHandle(), QPoint(nativeLocalPos.x, nativeLocalPos.y));
const bool max = IsMaximized(hWnd);
const bool full = Utils::isFullScreen(windowId);
const int frameSizeY = Utils::getResizeBorderThickness(windowId, false, true);

View File

@ -78,6 +78,24 @@ static const QHash<int, FONT_ICON> g_fontIconsTable = {
};
#endif // FRAMELESSHELPER_CORE_NO_BUNDLE_RESOURCE
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
[[nodiscard]] static inline QPoint getScaleOrigin(const QWindow *window)
{
Q_ASSERT(window);
if (!window) {
return {};
}
QScreen *screen = window->screen();
if (!screen) {
screen = QGuiApplication::primaryScreen();
}
if (!screen) {
return {};
}
return screen->virtualGeometry().topLeft();
}
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
Qt::CursorShape Utils::calculateCursorShape(const QWindow *window, const QPoint &pos)
{
#ifdef Q_OS_MACOS
@ -304,7 +322,7 @@ bool Utils::shouldAppsUseDarkMode()
qreal Utils::roundScaleFactor(const qreal factor)
{
// Qt can't handle scale factors less than 1.0 (according to the comments in qhighdpiscaling.cpp).
Q_ASSERT(factor >= 1);
Q_ASSERT((factor > 1) || qFuzzyCompare(factor, qreal(1)));
if (factor < 1) {
return 1;
}
@ -315,11 +333,15 @@ qreal Utils::roundScaleFactor(const qreal factor)
case Qt::HighDpiScaleFactorRoundingPolicy::Round:
return std::round(factor);
case Qt::HighDpiScaleFactorRoundingPolicy::Ceil:
return qCeil(factor);
return std::ceil(factor);
case Qt::HighDpiScaleFactorRoundingPolicy::Floor:
return qFloor(factor);
return std::floor(factor);
case Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor:
return (((factor - qreal(int(factor))) >= qreal(0.75)) ? std::round(factor) : qFloor(factor));
{
static constexpr const auto flag = qreal(0.75);
const qreal gap = (factor - qreal(int(factor)));
return (((gap > flag) || qFuzzyCompare(gap, flag)) ? std::round(factor) : std::floor(factor));
}
case Qt::HighDpiScaleFactorRoundingPolicy::PassThrough:
case Qt::HighDpiScaleFactorRoundingPolicy::Unset: // According to Qt source code, this enum value is the same with PassThrough.
return factor;
@ -353,7 +375,8 @@ QPoint Utils::toNativePixels(const QWindow *window, const QPoint &point)
return {};
}
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
return QPointF(QPointF(point) * window->devicePixelRatio()).toPoint();
const QPoint origin = getScaleOrigin(window);
return QPointF(QPointF(point - origin) * window->devicePixelRatio()).toPoint() + origin;
#else // !FRAMELESSHELPER_CORE_NO_PRIVATE
return QHighDpi::toNativePixels(point, window);
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
@ -405,7 +428,8 @@ QPoint Utils::fromNativePixels(const QWindow *window, const QPoint &point)
return {};
}
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
return QPointF(QPointF(point) / window->devicePixelRatio()).toPoint();
const QPoint origin = getScaleOrigin(window);
return QPointF(QPointF(point - origin) / window->devicePixelRatio()).toPoint() + origin;
#else // !FRAMELESSHELPER_CORE_NO_PRIVATE
return QHighDpi::fromNativePixels(point, window);
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
@ -437,6 +461,58 @@ QRect Utils::fromNativePixels(const QWindow *window, const QRect &rect)
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
}
QPoint Utils::toNativeLocalPosition(const QWindow *window, const QPoint &point)
{
Q_ASSERT(window);
if (!window) {
return {};
}
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
return QPointF(QPointF(point) * window->devicePixelRatio()).toPoint();
#else // !FRAMELESSHELPER_CORE_NO_PRIVATE
return QHighDpi::toNativeLocalPosition(point, window);
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
}
QPoint Utils::toNativeGlobalPosition(const QWindow *window, const QPoint &point)
{
Q_ASSERT(window);
if (!window) {
return {};
}
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
return toNativePixels(window, point);
#else // !FRAMELESSHELPER_CORE_NO_PRIVATE
return QHighDpi::toNativeGlobalPosition(point, window);
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
}
QPoint Utils::fromNativeLocalPosition(const QWindow *window, const QPoint &point)
{
Q_ASSERT(window);
if (!window) {
return {};
}
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
return QPointF(QPointF(point) / window->devicePixelRatio()).toPoint();
#else // !FRAMELESSHELPER_CORE_NO_PRIVATE
return QHighDpi::fromNativeLocalPosition(point, window);
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
}
QPoint Utils::fromNativeGlobalPosition(const QWindow *window, const QPoint &point)
{
Q_ASSERT(window);
if (!window) {
return {};
}
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
return fromNativePixels(window, point);
#else // !FRAMELESSHELPER_CORE_NO_PRIVATE
return QHighDpi::fromNativeGlobalPosition(point, window);
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
}
int Utils::horizontalAdvance(const QFontMetrics &fm, const QString &str)
{
#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))

View File

@ -360,7 +360,7 @@ void Utils::startSystemMove(QWindow *window, const QPoint &globalPos)
Q_UNUSED(globalPos);
window->startSystemMove();
#else // (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
const QPoint nativeGlobalPos = Utils::toNativePixels(window, globalPos);
const QPoint nativeGlobalPos = Utils::toNativeGlobalPosition(window, globalPos);
sendMoveResizeMessage(window->winId(), _NET_WM_MOVERESIZE_MOVE, nativeGlobalPos);
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
}
@ -378,7 +378,7 @@ void Utils::startSystemResize(QWindow *window, const Qt::Edges edges, const QPoi
Q_UNUSED(globalPos);
window->startSystemResize(edges);
#else // (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
const QPoint nativeGlobalPos = Utils::toNativePixels(window, globalPos);
const QPoint nativeGlobalPos = Utils::toNativeGlobalPosition(window, globalPos);
const int netWmOperation = qtEdgesToWmMoveOrResizeOperation(edges);
sendMoveResizeMessage(window->winId(), netWmOperation, nativeGlobalPos);
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))

View File

@ -513,7 +513,7 @@ static inline void moveWindowToMonitor(const HWND hwnd, const MONITORINFOEXW &ac
switch (uMsg) {
case WM_RBUTTONUP: {
const QPoint nativeLocalPos = getNativePosFromMouse();
const QPoint qtScenePos = Utils::fromNativePixels(data.params.getWindowHandle(), nativeLocalPos);
const QPoint qtScenePos = Utils::fromNativeLocalPosition(data.params.getWindowHandle(), nativeLocalPos);
if (data.params.isInsideTitleBarDraggableArea(qtScenePos)) {
POINT pos = {nativeLocalPos.x(), nativeLocalPos.y()};
if (ClientToScreen(hWnd, &pos) == FALSE) {

View File

@ -361,8 +361,7 @@ void FramelessQuickHelperPrivate::showSystemMenu(const QPoint &pos)
return;
}
const WId windowId = window->winId();
const QPoint globalPos = window->mapToGlobal(pos);
const QPoint nativePos = Utils::toNativePixels(window, globalPos);
const QPoint nativePos = Utils::toNativeGlobalPosition(window, pos);
#ifdef Q_OS_WINDOWS
const SystemParameters params = getWindowData().params;
Utils::showSystemMenu(windowId, nativePos, false, &params);

View File

@ -818,8 +818,7 @@ void FramelessWidgetsHelperPrivate::showSystemMenu(const QPoint &pos)
return;
}
const WId windowId = m_window->winId();
const QPoint globalPos = m_window->mapToGlobal(pos);
const QPoint nativePos = Utils::toNativePixels(m_window->windowHandle(), globalPos);
const QPoint nativePos = Utils::toNativeGlobalPosition(m_window->windowHandle(), pos);
#ifdef Q_OS_WINDOWS
const SystemParameters params = getWindowData().params;
Utils::showSystemMenu(windowId, nativePos, false, &params);