From 989de57f33c8f835b46ddaf15daf4df1a4c9fd9a Mon Sep 17 00:00:00 2001 From: Altair Wei Date: Tue, 21 Sep 2021 15:42:11 +0800 Subject: [PATCH] fix HiDPI position calculate error --- examples/minimal/main.cpp | 3 +- framelesshelper.cpp | 13 ++++++- utilities_linux.cpp | 77 ++++++++++++++++++++++----------------- 3 files changed, 56 insertions(+), 37 deletions(-) diff --git a/examples/minimal/main.cpp b/examples/minimal/main.cpp index d99e8ad..dc6d197 100644 --- a/examples/minimal/main.cpp +++ b/examples/minimal/main.cpp @@ -3,6 +3,7 @@ int main(int argc, char *argv[]) { +#if 1 QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); @@ -11,7 +12,7 @@ int main(int argc, char *argv[]) QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); #endif #endif - +#endif QApplication application(argc, argv); FLWindow win; diff --git a/framelesshelper.cpp b/framelesshelper.cpp index 03a1a50..6d04dbf 100644 --- a/framelesshelper.cpp +++ b/framelesshelper.cpp @@ -318,6 +318,9 @@ void FramelessHelper::updateHoverStates(const QPoint& pos) void FramelessHelper::startMove(const QPoint &globalPos) { #ifdef Q_OS_LINUX + // On HiDPI screen, X11 ButtonRelease is likely to trigger + // a QEvent::MouseMove, so we reset m_clickedFrameSection in advance. + m_clickedFrameSection = Qt::NoSection; Utilities::sendX11ButtonReleaseEvent(m_window, globalPos); Utilities::startX11Moving(m_window, globalPos); #endif @@ -326,6 +329,9 @@ void FramelessHelper::startMove(const QPoint &globalPos) void FramelessHelper::startResize(const QPoint &globalPos, Qt::WindowFrameSection frameSection) { #ifdef Q_OS_LINUX + // On HiDPI screen, X11 ButtonRelease is likely to trigger + // a QEvent::MouseMove, so we reset m_clickedFrameSection in advance. + m_clickedFrameSection = Qt::NoSection; Utilities::sendX11ButtonReleaseEvent(m_window, globalPos); Utilities::startX11Resizing(m_window, globalPos, frameSection); #endif @@ -375,17 +381,20 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) && isInTitlebarArea(ev->pos())) { // Start system move startMove(ev->globalPos()); + ev->accept(); filterOut = true; } else if (isClickResizeHandler() && isHoverResizeHandler()) { // Start system resize startResize(ev->globalPos(), m_hoveredFrameSection); + ev->accept(); filterOut = true; } // This case takes into account that the mouse moves outside the window boundary QRect windowRect(0, 0, windowSize().width(), windowSize().height()); - if (m_clickedFrameSection != Qt::NoSection && !windowRect.contains(ev->pos())) { + if (isClickResizeHandler() && !windowRect.contains(ev->pos())) { startResize(ev->globalPos(), m_clickedFrameSection); + ev->accept(); filterOut = true; } @@ -401,7 +410,7 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) { auto ev = static_cast(event); - if (ev->button() == Qt::LeftButton) + if (ev->button() == Qt::LeftButton) m_clickedFrameSection = m_hoveredFrameSection; break; diff --git a/utilities_linux.cpp b/utilities_linux.cpp index 3fa80b1..41216c0 100644 --- a/utilities_linux.cpp +++ b/utilities_linux.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -152,51 +153,59 @@ bool Utilities::showSystemMenu(const WId winId, const QPointF &pos) void Utilities::sendX11ButtonReleaseEvent(QWindow *w, const QPoint &globalPos) { const QPoint pos = w->mapFromGlobal(globalPos); - const auto display = QX11Info::display(); - const auto screen = QX11Info::appScreen(); + const auto display = QX11Info::display(); + const auto screen = QX11Info::appScreen(); - XEvent xevent; - memset(&xevent, 0, sizeof(XEvent)); + XEvent xevent; + memset(&xevent, 0, sizeof(XEvent)); - xevent.type = ButtonRelease; - xevent.xbutton.button = Button1; - xevent.xbutton.window = w->winId(); - xevent.xbutton.x = pos.x(); - xevent.xbutton.y = pos.y(); - xevent.xbutton.x_root = globalPos.x(); - xevent.xbutton.y_root = globalPos.y(); - xevent.xbutton.display = display; + xevent.type = ButtonRelease; + xevent.xbutton.time = CurrentTime; + xevent.xbutton.button = 0; + xevent.xbutton.same_screen = True; + xevent.xbutton.send_event = True; + xevent.xbutton.window = w->winId(); + xevent.xbutton.root = QX11Info::appRootWindow(screen); + xevent.xbutton.x = pos.x() * w->screen()->devicePixelRatio(); + xevent.xbutton.y = pos.y() * w->screen()->devicePixelRatio(); + xevent.xbutton.x_root = globalPos.x() * w->screen()->devicePixelRatio(); + xevent.xbutton.y_root = globalPos.y() * w->screen()->devicePixelRatio(); + xevent.xbutton.display = display; - if (XSendEvent(display, w->winId(), False, ButtonReleaseMask, &xevent) == 0) + if (XSendEvent(display, w->winId(), True, ButtonReleaseMask, &xevent) == 0) qWarning() << "Failed to send ButtonRelease event."; - XFlush(display); + XFlush(display); } void Utilities::sendX11MoveResizeEvent(QWindow *w, const QPoint &globalPos, int section) { - const auto display = QX11Info::display(); - const auto winId = w->winId(); - const auto screen = QX11Info::appScreen(); + const auto display = QX11Info::display(); + const auto winId = w->winId(); + const auto screen = QX11Info::appScreen(); - XEvent xev; - const Atom netMoveResize = XInternAtom(display, "_NET_WM_MOVERESIZE", false); - xev.xclient.type = ClientMessage; - xev.xclient.message_type = netMoveResize; - xev.xclient.display = display; - xev.xclient.window = winId; - xev.xclient.format = 32; + XUngrabPointer(display, CurrentTime); - xev.xclient.data.l[0] = globalPos.x(); - xev.xclient.data.l[1] = globalPos.y(); - xev.xclient.data.l[2] = section; - xev.xclient.data.l[3] = Button1; - xev.xclient.data.l[4] = 1; - XUngrabPointer(display, QX11Info::appTime()); + XEvent xev; + memset(&xev, 0x00, sizeof(xev)); + const Atom netMoveResize = XInternAtom(display, "_NET_WM_MOVERESIZE", False); + xev.xclient.type = ClientMessage; + xev.xclient.message_type = netMoveResize; + xev.xclient.serial = 0; + xev.xclient.display = display; + xev.xclient.send_event = True; + xev.xclient.window = winId; + xev.xclient.format = 32; - if(XSendEvent(display, QX11Info::appRootWindow(screen), - false, SubstructureRedirectMask | SubstructureNotifyMask, &xev) == 0) + xev.xclient.data.l[0] = globalPos.x() * w->screen()->devicePixelRatio(); + xev.xclient.data.l[1] = globalPos.y() * w->screen()->devicePixelRatio(); + xev.xclient.data.l[2] = section; + xev.xclient.data.l[3] = Button1; + xev.xclient.data.l[4] = 0; + + if(XSendEvent(display, QX11Info::appRootWindow(screen), + False, SubstructureRedirectMask | SubstructureNotifyMask, &xev) == 0) qWarning("Failed to send Move or Resize event."); - XFlush(display); + XFlush(display); } void Utilities::startX11Moving(QWindow *w, const QPoint &pos) @@ -315,4 +324,4 @@ unsigned int Utilities::getX11CursorForFrameSection(Qt::WindowFrameSection frame return (unsigned int)cursor; } -FRAMELESSHELPER_END_NAMESPACE \ No newline at end of file +FRAMELESSHELPER_END_NAMESPACE