fix HiDPI position calculate error

This commit is contained in:
Altair Wei 2021-09-21 15:42:11 +08:00
parent 3a3e39c0c0
commit 989de57f33
3 changed files with 56 additions and 37 deletions

View File

@ -3,6 +3,7 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
#if 1
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
@ -11,7 +12,7 @@ int main(int argc, char *argv[])
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif #endif
#endif #endif
#endif
QApplication application(argc, argv); QApplication application(argc, argv);
FLWindow win; FLWindow win;

View File

@ -318,6 +318,9 @@ void FramelessHelper::updateHoverStates(const QPoint& pos)
void FramelessHelper::startMove(const QPoint &globalPos) void FramelessHelper::startMove(const QPoint &globalPos)
{ {
#ifdef Q_OS_LINUX #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::sendX11ButtonReleaseEvent(m_window, globalPos);
Utilities::startX11Moving(m_window, globalPos); Utilities::startX11Moving(m_window, globalPos);
#endif #endif
@ -326,6 +329,9 @@ void FramelessHelper::startMove(const QPoint &globalPos)
void FramelessHelper::startResize(const QPoint &globalPos, Qt::WindowFrameSection frameSection) void FramelessHelper::startResize(const QPoint &globalPos, Qt::WindowFrameSection frameSection)
{ {
#ifdef Q_OS_LINUX #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::sendX11ButtonReleaseEvent(m_window, globalPos);
Utilities::startX11Resizing(m_window, globalPos, frameSection); Utilities::startX11Resizing(m_window, globalPos, frameSection);
#endif #endif
@ -375,17 +381,20 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
&& isInTitlebarArea(ev->pos())) { && isInTitlebarArea(ev->pos())) {
// Start system move // Start system move
startMove(ev->globalPos()); startMove(ev->globalPos());
ev->accept();
filterOut = true; filterOut = true;
} else if (isClickResizeHandler() && isHoverResizeHandler()) { } else if (isClickResizeHandler() && isHoverResizeHandler()) {
// Start system resize // Start system resize
startResize(ev->globalPos(), m_hoveredFrameSection); startResize(ev->globalPos(), m_hoveredFrameSection);
ev->accept();
filterOut = true; filterOut = true;
} }
// This case takes into account that the mouse moves outside the window boundary // This case takes into account that the mouse moves outside the window boundary
QRect windowRect(0, 0, windowSize().width(), windowSize().height()); 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); startResize(ev->globalPos(), m_clickedFrameSection);
ev->accept();
filterOut = true; filterOut = true;
} }

View File

@ -26,6 +26,7 @@
#include <QtCore/qvariant.h> #include <QtCore/qvariant.h>
#include <QtCore/qdebug.h> #include <QtCore/qdebug.h>
#include <QtGui/qscreen.h>
#include <QtX11Extras/qx11info_x11.h> #include <QtX11Extras/qx11info_x11.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
@ -152,51 +153,59 @@ bool Utilities::showSystemMenu(const WId winId, const QPointF &pos)
void Utilities::sendX11ButtonReleaseEvent(QWindow *w, const QPoint &globalPos) void Utilities::sendX11ButtonReleaseEvent(QWindow *w, const QPoint &globalPos)
{ {
const QPoint pos = w->mapFromGlobal(globalPos); const QPoint pos = w->mapFromGlobal(globalPos);
const auto display = QX11Info::display(); const auto display = QX11Info::display();
const auto screen = QX11Info::appScreen(); const auto screen = QX11Info::appScreen();
XEvent xevent; XEvent xevent;
memset(&xevent, 0, sizeof(XEvent)); memset(&xevent, 0, sizeof(XEvent));
xevent.type = ButtonRelease; xevent.type = ButtonRelease;
xevent.xbutton.button = Button1; xevent.xbutton.time = CurrentTime;
xevent.xbutton.window = w->winId(); xevent.xbutton.button = 0;
xevent.xbutton.x = pos.x(); xevent.xbutton.same_screen = True;
xevent.xbutton.y = pos.y(); xevent.xbutton.send_event = True;
xevent.xbutton.x_root = globalPos.x(); xevent.xbutton.window = w->winId();
xevent.xbutton.y_root = globalPos.y(); xevent.xbutton.root = QX11Info::appRootWindow(screen);
xevent.xbutton.display = display; 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."; qWarning() << "Failed to send ButtonRelease event.";
XFlush(display); XFlush(display);
} }
void Utilities::sendX11MoveResizeEvent(QWindow *w, const QPoint &globalPos, int section) void Utilities::sendX11MoveResizeEvent(QWindow *w, const QPoint &globalPos, int section)
{ {
const auto display = QX11Info::display(); const auto display = QX11Info::display();
const auto winId = w->winId(); const auto winId = w->winId();
const auto screen = QX11Info::appScreen(); const auto screen = QX11Info::appScreen();
XEvent xev; XUngrabPointer(display, CurrentTime);
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;
xev.xclient.data.l[0] = globalPos.x(); XEvent xev;
xev.xclient.data.l[1] = globalPos.y(); memset(&xev, 0x00, sizeof(xev));
xev.xclient.data.l[2] = section; const Atom netMoveResize = XInternAtom(display, "_NET_WM_MOVERESIZE", False);
xev.xclient.data.l[3] = Button1; xev.xclient.type = ClientMessage;
xev.xclient.data.l[4] = 1; xev.xclient.message_type = netMoveResize;
XUngrabPointer(display, QX11Info::appTime()); 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), xev.xclient.data.l[0] = globalPos.x() * w->screen()->devicePixelRatio();
false, SubstructureRedirectMask | SubstructureNotifyMask, &xev) == 0) 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."); qWarning("Failed to send Move or Resize event.");
XFlush(display); XFlush(display);
} }
void Utilities::startX11Moving(QWindow *w, const QPoint &pos) void Utilities::startX11Moving(QWindow *w, const QPoint &pos)