From 6329385f5a178169db0e8dead6d886765980b504 Mon Sep 17 00:00:00 2001 From: RigoLigo Date: Fri, 18 Oct 2024 11:08:59 +0800 Subject: [PATCH] fix: use native resolution in X11 layershell emu Log: --- frame/layershell/x11dlayershellemulation.cpp | 61 +++++++++++++++----- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/frame/layershell/x11dlayershellemulation.cpp b/frame/layershell/x11dlayershellemulation.cpp index bb950b8cb..02f98a78f 100644 --- a/frame/layershell/x11dlayershellemulation.cpp +++ b/frame/layershell/x11dlayershellemulation.cpp @@ -11,6 +11,9 @@ #include #include +#include +#include +#include #include #include @@ -104,42 +107,72 @@ void LayerShellEmulation::onLayerChanged() void LayerShellEmulation::onPositionChanged() { + // Work around QPA abstraction so we can use physical pixels, not logical pixels after Qt DPI transformation + auto platformScreen = m_window->screen()->handle(); + qreal factor = QHighDpiScaling::factor(platformScreen); + + // These geometries are in physical pixels + auto windowGeometry = m_window->handle()->geometry(); + auto screenGeom = platformScreen->geometry(); + auto anchors = m_dlayerShellWindow->anchors(); - auto screen = m_window->screen(); - auto screenRect = screen->geometry(); - auto x = screenRect.left() + (screenRect.width() - m_window->width()) / 2; - auto y = screenRect.top() + (screenRect.height() - m_window->height()) / 2; + auto x = screenGeom.left() + (screenGeom.width() - windowGeometry.width()) / 2; + auto y = screenGeom.top() + (screenGeom.height() - windowGeometry.height()) / 2; + + // Set if (anchors & DLayerShellWindow::AnchorRight) { // https://doc.qt.io/qt-6/qrect.html#right - x = (screen->geometry().right() + 1 - m_window->width() - m_dlayerShellWindow->rightMargin()); + x = (screenGeom.right() + 1 - windowGeometry.width() - qRound(m_dlayerShellWindow->rightMargin() * factor)); } if (anchors & DLayerShellWindow::AnchorBottom) { // https://doc.qt.io/qt-6/qrect.html#bottom - y = (screen->geometry().bottom() + 1 - m_window->height() - m_dlayerShellWindow->bottomMargin()); + y = (screenGeom.bottom() + 1 - windowGeometry.height() - qRound(m_dlayerShellWindow->bottomMargin() * factor)); } if (anchors & DLayerShellWindow::AnchorLeft) { - x = (screen->geometry().left() + m_dlayerShellWindow->leftMargin()); + x = (screenGeom.left() + qRound(m_dlayerShellWindow->leftMargin() * factor)); } if (anchors & DLayerShellWindow::AnchorTop) { - y = (screen->geometry().top() + m_dlayerShellWindow->topMargin()); + y = (screenGeom.top() + qRound(m_dlayerShellWindow->topMargin() * factor)); } - QRect rect(x, y, m_window->width(), m_window->height()); + QRect rect(x, y, windowGeometry.width(), windowGeometry.height()); const bool horizontallyConstrained = anchors.testFlags({DLayerShellWindow::AnchorLeft, DLayerShellWindow::AnchorRight}); const bool verticallyConstrained = anchors.testFlags({DLayerShellWindow::AnchorTop, DLayerShellWindow::AnchorBottom}); if (horizontallyConstrained) { - rect.setX(screen->geometry().left() + m_dlayerShellWindow->leftMargin()); - rect.setWidth(screen->geometry().width() - m_dlayerShellWindow->leftMargin() - m_dlayerShellWindow->rightMargin()); + rect.setX(screenGeom.left() + qRound(m_dlayerShellWindow->leftMargin() * factor)); + rect.setWidth(screenGeom.width() - qRound((m_dlayerShellWindow->leftMargin() + m_dlayerShellWindow->rightMargin()) * factor)); } if (verticallyConstrained) { - rect.setY(screen->geometry().top() + m_dlayerShellWindow->topMargin()); - rect.setHeight(screen->geometry().height() - m_dlayerShellWindow->topMargin() - m_dlayerShellWindow->bottomMargin()); + rect.setY(screenGeom.top() + qRound(m_dlayerShellWindow->topMargin() * factor)); + rect.setHeight(screenGeom.height() - qRound((m_dlayerShellWindow->topMargin() + m_dlayerShellWindow->bottomMargin()) * factor)); } - m_window->setGeometry(rect); + // Configure window geometry via XCB interface + auto x11App = qGuiApp->nativeInterface(); + auto xcbConnection = x11App->connection(); + auto xcbWindow = m_window->winId(); + uint16_t mask = 0; + struct { + int32_t x; + int32_t y; + uint32_t width; + uint32_t height; + } targetWindowRect; + + targetWindowRect.x = rect.x(); + targetWindowRect.y = rect.y(); + targetWindowRect.width = rect.width(); + targetWindowRect.height = rect.height(); + mask |= XCB_CONFIG_WINDOW_X; + mask |= XCB_CONFIG_WINDOW_Y; + mask |= XCB_CONFIG_WINDOW_WIDTH; + mask |= XCB_CONFIG_WINDOW_HEIGHT; + + xcb_configure_window(xcbConnection, xcbWindow, mask, &targetWindowRect); + xcb_flush(xcbConnection); } /**