From ae5f2a66720a4bb22c120bd7d1564652cac00367 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Tue, 29 Jul 2014 13:12:01 +0200 Subject: devicePixelRatio support for XCB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds support for the environment variable QT_DEVICE_PIXEL_RATIO for the xcb platform plugin. Task-number: QTBUG-38858 Change-Id: I7faca2f2e7dc5c601a82b3cc08456870b3e5602d Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Jørgen Lind --- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 34 +++--- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 10 +- src/plugins/platforms/xcb/qxcbcursor.cpp | 6 +- src/plugins/platforms/xcb/qxcbdrag.cpp | 15 ++- src/plugins/platforms/xcb/qxcbscreen.cpp | 49 ++++++--- src/plugins/platforms/xcb/qxcbscreen.h | 2 + src/plugins/platforms/xcb/qxcbwindow.cpp | 127 ++++++++++++++++------- src/plugins/platforms/xcb/qxcbwindow.h | 2 + 8 files changed, 173 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 6258b29fc7..2daadb8649 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -280,13 +280,14 @@ void QXcbBackingStore::beginPaint(const QRegion ®ion) { if (!m_image) return; - - m_image->preparePaint(region); + const int dpr = int(m_image->image()->devicePixelRatio()); + QRegion xRegion = dpr == 1 ? region : QTransform::fromScale(dpr,dpr).map(region); + m_image->preparePaint(xRegion); if (m_image->image()->hasAlphaChannel()) { QPainter p(m_image->image()); p.setCompositionMode(QPainter::CompositionMode_Source); - const QVector rects = region.rects(); + const QVector rects = xRegion.rects(); const QColor blank = Qt::transparent; for (QVector::const_iterator it = rects.begin(); it != rects.end(); ++it) { p.fillRect(*it, blank); @@ -323,9 +324,13 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoin return; } + const int dpr = int(window->devicePixelRatio()); + QVector rects = clipped.rects(); - for (int i = 0; i < rects.size(); ++i) - m_image->put(platformWindow->xcb_window(), rects.at(i).topLeft(), rects.at(i).translated(offset)); + for (int i = 0; i < rects.size(); ++i) { + QRect rect = QRect(rects.at(i).topLeft() * dpr, rects.at(i).size() * dpr); + m_image->put(platformWindow->xcb_window(), rect.topLeft(), rect.translated(offset * dpr)); + } Q_XCB_NOOP(connection()); @@ -355,9 +360,11 @@ void QXcbBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, c void QXcbBackingStore::resize(const QSize &size, const QRegion &) { - if (m_image && size == m_image->size()) - return; + const int dpr = int(window()->devicePixelRatio()); + const QSize xSize = size * dpr; + if (m_image && xSize == m_image->size()) + return; Q_XCB_NOOP(connection()); QXcbScreen *screen = static_cast(window()->screen()->handle()); @@ -369,7 +376,8 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &) QXcbWindow* win = static_cast(pw); delete m_image; - m_image = new QXcbShmImage(screen, size, win->depth(), win->imageFormat()); + m_image = new QXcbShmImage(screen, xSize, win->depth(), win->imageFormat()); + m_image->image()->setDevicePixelRatio(dpr); Q_XCB_NOOP(connection()); } @@ -380,12 +388,14 @@ bool QXcbBackingStore::scroll(const QRegion &area, int dx, int dy) if (!m_image || m_image->image()->isNull()) return false; + const int dpr = int(m_image->image()->devicePixelRatio()); + QRegion xArea = dpr == 1 ? area : QTransform::fromScale(dpr,dpr).map(area); m_image->preparePaint(area); - const QVector rects = area.rects(); - for (int i = 0; i < rects.size(); ++i) - qt_scrollRectInImage(*m_image->image(), rects.at(i), QPoint(dx, dy)); - + QPoint delta(dx * dpr, dy * dpr); + const QVector xRects = xArea.rects(); + for (int i = 0; i < xRects.size(); ++i) + qt_scrollRectInImage(*m_image->image(), xRects.at(i), delta); return true; } diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index e3194d8177..7c5db7c6e5 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -648,8 +648,9 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin } } if (!angleDelta.isNull()) { - QPoint local(fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y)); - QPoint global(fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y)); + const int dpr = int(platformWindow->devicePixelRatio()); + QPoint local(fixed1616ToReal(xiDeviceEvent->event_x)/dpr, fixed1616ToReal(xiDeviceEvent->event_y)/dpr); + QPoint global(fixed1616ToReal(xiDeviceEvent->root_x)/dpr, fixed1616ToReal(xiDeviceEvent->root_y)/dpr); Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(xiDeviceEvent->mods.effective_mods); if (modifiers & Qt::AltModifier) { std::swap(angleDelta.rx(), angleDelta.ry()); @@ -675,8 +676,9 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin angleDelta.setX(-120); } if (!angleDelta.isNull()) { - QPoint local(fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y)); - QPoint global(fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y)); + const int dpr = int(platformWindow->devicePixelRatio()); + QPoint local(fixed1616ToReal(xiDeviceEvent->event_x)/dpr, fixed1616ToReal(xiDeviceEvent->event_y)/dpr); + QPoint global(fixed1616ToReal(xiDeviceEvent->root_x)/dpr, fixed1616ToReal(xiDeviceEvent->root_y)/dpr); Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(xiDeviceEvent->mods.effective_mods); if (modifiers & Qt::AltModifier) std::swap(angleDelta.rx(), angleDelta.ry()); diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index 6dbac90e0c..c9adf00673 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -629,16 +629,18 @@ void QXcbCursor::queryPointer(QXcbConnection *c, xcb_window_t *rootWin, QPoint * QPoint QXcbCursor::pos() const { + const int dpr = int(m_screen->devicePixelRatio()); QPoint p; queryPointer(connection(), 0, &p); - return p; + return p / dpr; } void QXcbCursor::setPos(const QPoint &pos) { + const int dpr = int(m_screen->devicePixelRatio()); xcb_window_t root = 0; queryPointer(connection(), &root, 0); - xcb_warp_pointer(xcb_connection(), XCB_NONE, root, 0, 0, 0, 0, pos.x(), pos.y()); + xcb_warp_pointer(xcb_connection(), XCB_NONE, root, 0, 0, 0, 0, pos.x()*dpr, pos.y()*dpr); xcb_flush(xcb_connection()); } diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index bd28548cba..fa5ccf58ef 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -300,6 +300,11 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md void QXcbDrag::move(const QMouseEvent *me) { + // The mouse event is in the coordinate system of the window that started the drag. + // We do not know which window that was at this point, so we just use the device pixel ratio + // of the QGuiApplication. This will break once we support screens with different DPR. Fixing + // this properly requires some redesign of the drag and drop architecture. + static const int dpr = int(qApp->devicePixelRatio()); QBasicDrag::move(me); QPoint globalPos = me->globalPos(); @@ -336,7 +341,7 @@ void QXcbDrag::move(const QMouseEvent *me) // qt_xdnd_current_screen = screen; xcb_window_t rootwin = current_screen->root(); xcb_translate_coordinates_reply_t *translate = - ::translateCoordinates(connection(), rootwin, rootwin, globalPos.x(), globalPos.y()); + ::translateCoordinates(connection(), rootwin, rootwin, globalPos.x() * dpr, globalPos.y() * dpr); if (!translate) return; @@ -459,7 +464,7 @@ void QXcbDrag::move(const QMouseEvent *me) move.type = atom(QXcbAtom::XdndPosition); move.data.data32[0] = connection()->clipboard()->owner(); move.data.data32[1] = 0; // flags - move.data.data32[2] = (globalPos.x() << 16) + globalPos.y(); + move.data.data32[2] = (globalPos.x() * dpr << 16) + globalPos.y() * dpr; move.data.data32[3] = connection()->time(); move.data.data32[4] = toXdndAction(defaultAction(currentDrag()->supportedActions(), QGuiApplication::keyboardModifiers())); DEBUG() << "sending Xdnd position source=" << move.data.data32[0] << "target=" << move.window; @@ -705,7 +710,9 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t QPoint p((e->data.data32[2] & 0xffff0000) >> 16, e->data.data32[2] & 0x0000ffff); Q_ASSERT(w); QRect geometry = w->geometry(); + const int dpr = int(w->handle()->devicePixelRatio()); + p /= dpr; p -= geometry.topLeft(); if (!w || (w->type() == Qt::Desktop)) @@ -824,10 +831,12 @@ void QXcbDrag::handle_xdnd_status(const xcb_client_message_event_t *event) updateCursor(Qt::IgnoreAction); } + static const int dpr = int(qApp->devicePixelRatio()); + if ((event->data.data32[1] & 2) == 0) { QPoint p((event->data.data32[2] & 0xffff0000) >> 16, event->data.data32[2] & 0x0000ffff); QSize s((event->data.data32[3] & 0xffff0000) >> 16, event->data.data32[3] & 0x0000ffff); - source_sameanswer = QRect(p, s); + source_sameanswer = QRect(p / dpr, s / dpr); } else { source_sameanswer = QRect(); } diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 952f32d806..83ffb02362 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -68,6 +68,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, , m_number(number) , m_refreshRate(60) , m_forcedDpi(-1) + , m_devicePixelRatio(1) , m_hintStyle(QFontEngine::HintStyle(-1)) , m_subpixelType(QFontEngine::SubpixelAntialiasingType(-1)) , m_antialiasingEnabled(-1) @@ -78,19 +79,18 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, updateGeometry(output ? output->timestamp : 0); updateRefreshRate(); - + const int dpr = int(devicePixelRatio()); // On VNC, it can be that physical size is unknown while // virtual size is known (probably back-calculated from DPI and resolution) if (m_sizeMillimeters.isEmpty()) m_sizeMillimeters = m_virtualSizeMillimeters; if (m_geometry.isEmpty()) - m_geometry = QRect(QPoint(), m_virtualSize); + m_geometry = QRect(QPoint(), m_virtualSize/dpr); if (m_availableGeometry.isEmpty()) - m_availableGeometry = QRect(QPoint(), m_virtualSize); + m_availableGeometry = m_geometry; readXResources(); - #ifdef Q_XCB_DEBUG qDebug(); qDebug("Screen output %s of xcb screen %d:", m_outputName.toUtf8().constData(), m_number); @@ -101,6 +101,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, qDebug(" virtual height.: %lf", m_virtualSizeMillimeters.height()); qDebug(" virtual geom...: %d x %d", m_virtualSize.width(), m_virtualSize.height()); qDebug(" avail virt geom: %d x %d +%d +%d", m_availableGeometry.width(), m_availableGeometry.height(), m_availableGeometry.x(), m_availableGeometry.y()); + qDebug(" pixel ratio....: %d", m_devicePixelRatio); qDebug(" depth..........: %d", screen()->root_depth); qDebug(" white pixel....: %x", screen()->white_pixel); qDebug(" black pixel....: %x", screen()->black_pixel); @@ -222,8 +223,9 @@ QWindow *QXcbScreen::topLevelAt(const QPoint &p) const { xcb_window_t root = m_screen->root; - int x = p.x(); - int y = p.y(); + int dpr = int(devicePixelRatio()); + int x = p.x() / dpr; + int y = p.y() / dpr; xcb_window_t parent = root; xcb_window_t child = root; @@ -314,11 +316,25 @@ QImage::Format QXcbScreen::format() const QDpi QXcbScreen::logicalDpi() const { + int dpr = int(devicePixelRatio()); + if (m_forcedDpi > 0) - return QDpi(m_forcedDpi, m_forcedDpi); + return QDpi(m_forcedDpi/dpr, m_forcedDpi/dpr); - return QDpi(Q_MM_PER_INCH * m_virtualSize.width() / m_virtualSizeMillimeters.width(), - Q_MM_PER_INCH * m_virtualSize.height() / m_virtualSizeMillimeters.height()); + return QDpi(Q_MM_PER_INCH * m_virtualSize.width() / m_virtualSizeMillimeters.width() / dpr, + Q_MM_PER_INCH * m_virtualSize.height() / m_virtualSizeMillimeters.height() / dpr); +} + + +qreal QXcbScreen::devicePixelRatio() const +{ + static int override_dpr = qgetenv("QT_DEVICE_PIXEL_RATIO").toInt(); + static bool auto_dpr = qgetenv("QT_DEVICE_PIXEL_RATIO").toLower() == "auto"; + if (override_dpr > 0) + return override_dpr; + if (auto_dpr) + return m_devicePixelRatio; + return 1.0; } QPlatformCursor *QXcbScreen::cursor() const @@ -396,12 +412,15 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp) { + QRect xGeometry; + QRect xAvailableGeometry; + if (connection()->hasXRandr()) { xcb_randr_get_crtc_info_reply_t *crtc = xcb_randr_get_crtc_info_reply(xcb_connection(), xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, timestamp), NULL); if (crtc) { - m_geometry = QRect(crtc->x, crtc->y, crtc->width, crtc->height); - m_availableGeometry = m_geometry; + xGeometry = QRect(crtc->x, crtc->y, crtc->width, crtc->height); + xAvailableGeometry = xGeometry; free(crtc); } } @@ -422,10 +441,16 @@ void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp) QRect virtualAvailableGeometry(geom[0], geom[1], geom[2], geom[3]); // Take the intersection of the desktop's available geometry with this screen's geometry // to get the part of the available geometry which belongs to this screen. - m_availableGeometry = m_geometry & virtualAvailableGeometry; + xAvailableGeometry = xGeometry & virtualAvailableGeometry; } free(workArea); + qreal dpi = xGeometry.width() / physicalSize().width() * qreal(25.4); + m_devicePixelRatio = qRound(dpi/96); + const int dpr = int(devicePixelRatio()); // we may override m_devicePixelRatio + m_geometry = QRect(xGeometry.topLeft()/dpr, xGeometry.size()/dpr); + m_availableGeometry = QRect(xAvailableGeometry.topLeft()/dpr, xAvailableGeometry.size()/dpr); + QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), m_availableGeometry); } diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index db72d94698..06dc2a32a2 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -75,6 +75,7 @@ public: QImage::Format format() const; QSizeF physicalSize() const { return m_sizeMillimeters; } QDpi logicalDpi() const; + qreal devicePixelRatio() const; QPlatformCursor *cursor() const; qreal refreshRate() const { return m_refreshRate; } Qt::ScreenOrientation orientation() const { return m_orientation; } @@ -134,6 +135,7 @@ private: QXcbCursor *m_cursor; int m_refreshRate; int m_forcedDpi; + int m_devicePixelRatio; QFontEngine::HintStyle m_hintStyle; QFontEngine::SubpixelAntialiasingType m_subpixelType; int m_antialiasingEnabled; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index cb647e946d..e4feda2c81 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -154,6 +154,30 @@ enum QX11EmbedMessageType { const quint32 XEMBED_VERSION = 0; +static inline QRect mapToNative(const QRect &qtRect, int dpr) +{ + return QRect(qtRect.x() * dpr, qtRect.y() * dpr, qtRect.width() * dpr, qtRect.height() * dpr); +} + +// When converting native rects to Qt rects: round top/left towards the origin and +// bottom/right away from the origin, making sure that we cover the whole widget + +static inline QPoint dpr_floor(const QPoint &p, int dpr) +{ + return QPoint(p.x()/dpr, p.y()/dpr); +} + +static inline QPoint dpr_ceil(const QPoint &p, int dpr) +{ + return QPoint((p.x() + dpr - 1) / dpr, (p.y() + dpr - 1) / dpr); +} + +static inline QRect mapFromNative(const QRect &xRect, int dpr) +{ + return QRect(dpr_floor(xRect.topLeft(), dpr), dpr_ceil(xRect.bottomRight(), dpr)); +} + + // Returns \c true if we should set WM_TRANSIENT_FOR on \a w static inline bool isTransient(const QWindow *w) { @@ -288,11 +312,12 @@ void QXcbWindow::create() // currently no way to implement it for frame-exclusive geometries. QRect rect = window()->geometry(); QPlatformWindow::setGeometry(rect); + const int dpr = int(devicePixelRatio()); QSize minimumSize = window()->minimumSize(); if (rect.width() > 0 || rect.height() > 0) { - rect.setWidth(qBound(1, rect.width(), XCOORD_MAX)); - rect.setHeight(qBound(1, rect.height(), XCOORD_MAX)); + rect.setWidth(qBound(1, rect.width(), XCOORD_MAX/dpr)); + rect.setHeight(qBound(1, rect.height(), XCOORD_MAX/dpr)); } else if (minimumSize.width() > 0 || minimumSize.height() > 0) { rect.setSize(minimumSize); } else { @@ -350,7 +375,9 @@ void QXcbWindow::create() m_visualId = visualInfo->visualid; - m_window = XCreateWindow(DISPLAY_FROM_XCB(this), xcb_parent_id, rect.x(), rect.y(), rect.width(), rect.height(), + const QRect xRect = mapToNative(rect, dpr); + + m_window = XCreateWindow(DISPLAY_FROM_XCB(this), xcb_parent_id, xRect.x(), xRect.y(), xRect.width(), xRect.height(), 0, visualInfo->depth, InputOutput, visualInfo->visual, CWBackPixel|CWBorderPixel|CWColormap, &a); @@ -561,7 +588,9 @@ void QXcbWindow::setGeometry(const QRect &rect) QPlatformWindow::setGeometry(rect); propagateSizeHints(); - const QRect wmGeometry = windowToWmGeometry(rect); + + const QRect xRect = mapToNative(rect, int(devicePixelRatio())); + const QRect wmGeometry = windowToWmGeometry(xRect); if (qt_window_private(window())->positionAutomatic) { const quint32 mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; @@ -1444,23 +1473,26 @@ void QXcbWindow::propagateSizeHints() xcb_size_hints_t hints; memset(&hints, 0, sizeof(hints)); - const QRect rect = windowToWmGeometry(geometry()); + const int dpr = int(devicePixelRatio()); + const QRect xRect = mapToNative(windowToWmGeometry(geometry()), dpr); QWindow *win = window(); if (!qt_window_private(win)->positionAutomatic) - xcb_size_hints_set_position(&hints, true, rect.x(), rect.y()); - if (rect.width() < QWINDOWSIZE_MAX || rect.height() < QWINDOWSIZE_MAX) - xcb_size_hints_set_size(&hints, true, rect.width(), rect.height()); + xcb_size_hints_set_position(&hints, true, xRect.x(), xRect.y()); + if (xRect.width() < QWINDOWSIZE_MAX || xRect.height() < QWINDOWSIZE_MAX) + xcb_size_hints_set_size(&hints, true, xRect.width(), xRect.height()); xcb_size_hints_set_win_gravity(&hints, m_gravity); - QSize minimumSize = win->minimumSize(); - QSize maximumSize = win->maximumSize(); - QSize baseSize = win->baseSize(); - QSize sizeIncrement = win->sizeIncrement(); + QSize minimumSize = win->minimumSize() * dpr; + QSize maximumSize = win->maximumSize() * dpr; + QSize baseSize = win->baseSize() * dpr; + QSize sizeIncrement = win->sizeIncrement() * dpr; if (minimumSize.width() > 0 || minimumSize.height() > 0) - xcb_size_hints_set_min_size(&hints, minimumSize.width(), minimumSize.height()); + xcb_size_hints_set_min_size(&hints, + qMin(XCOORD_MAX,minimumSize.width()), + qMin(XCOORD_MAX,minimumSize.height())); if (maximumSize.width() < QWINDOWSIZE_MAX || maximumSize.height() < QWINDOWSIZE_MAX) xcb_size_hints_set_max_size(&hints, @@ -1664,9 +1696,10 @@ void QXcbWindow::setWmWindowType(QXcbWindowFunctions::WmWindowTypes types) class ExposeCompressor { public: - ExposeCompressor(xcb_window_t window, QRegion *region) + ExposeCompressor(xcb_window_t window, QRegion *region, int devicePixelRatio) : m_window(window) , m_region(region) + , m_dpr(devicePixelRatio) , m_pending(true) { } @@ -1682,7 +1715,7 @@ public: return false; if (expose->count == 0) m_pending = false; - *m_region |= QRect(expose->x, expose->y, expose->width, expose->height); + *m_region |= mapFromNative(QRect(expose->x, expose->y, expose->width, expose->height), m_dpr); return true; } @@ -1694,6 +1727,7 @@ public: private: xcb_window_t m_window; QRegion *m_region; + int m_dpr; bool m_pending; }; @@ -1707,14 +1741,16 @@ bool QXcbWindow::handleGenericEvent(xcb_generic_event_t *event, long *result) void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event) { - QRect rect(event->x, event->y, event->width, event->height); + const int dpr = int(devicePixelRatio()); + QRect x_rect(event->x, event->y, event->width, event->height); + QRect rect = mapFromNative(x_rect, dpr); if (m_exposeRegion.isEmpty()) m_exposeRegion = rect; else m_exposeRegion |= rect; - ExposeCompressor compressor(m_window, &m_exposeRegion); + ExposeCompressor compressor(m_window, &m_exposeRegion, dpr); xcb_generic_event_t *filter = 0; do { filter = connection()->checkEvent(compressor); @@ -1808,7 +1844,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * } } - QRect rect(pos, QSize(event->width, event->height)); + QRect rect = mapFromNative(QRect(pos, QSize(event->width, event->height)), int(devicePixelRatio())); QPlatformWindow::setGeometry(rect); QWindowSystemInterface::handleGeometryChange(window(), rect); @@ -1850,15 +1886,16 @@ QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const if (!m_embedded) return pos; + const int dpr = int(devicePixelRatio()); QPoint ret; xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(), m_screen->root(), - pos.x(), pos.y()); + pos.x() * dpr, pos.y() * dpr); xcb_translate_coordinates_reply_t *reply = xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); if (reply) { - ret.setX(reply->dst_x); - ret.setY(reply->dst_y); + ret.setX(reply->dst_x / dpr); + ret.setY(reply->dst_y / dpr); free(reply); } @@ -1869,15 +1906,17 @@ QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const { if (!m_embedded) return pos; + + const int dpr = int(devicePixelRatio()); QPoint ret; xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), m_screen->root(), xcb_window(), - pos.x(), pos.y()); + pos.x() *dpr, pos.y() * dpr); xcb_translate_coordinates_reply_t *reply = xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); if (reply) { - ret.setX(reply->dst_x); - ret.setY(reply->dst_y); + ret.setX(reply->dst_x / dpr); + ret.setY(reply->dst_y / dpr); free(reply); } @@ -1893,7 +1932,7 @@ void QXcbWindow::handleMapNotifyEvent(const xcb_map_notify_event_t *event) if (m_configureNotifyPending) m_deferredExpose = true; else - QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); + QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size() * int(devicePixelRatio()))); } } @@ -1924,9 +1963,9 @@ void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) sendXEmbedMessage(container->xcb_window(), XEMBED_REQUEST_FOCUS); } } - - QPoint local(event->event_x, event->event_y); - QPoint global(event->root_x, event->root_y); + const int dpr = int(devicePixelRatio()); + QPoint local(event->event_x/dpr, event->event_y/dpr); + QPoint global(event->root_x/dpr, event->root_y/dpr); Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); @@ -1949,8 +1988,9 @@ void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *event) { - QPoint local(event->event_x, event->event_y); - QPoint global(event->root_x, event->root_y); + const int dpr = int(devicePixelRatio()); + QPoint local(event->event_x/dpr, event->event_y/dpr); + QPoint global(event->root_x/dpr, event->root_y/dpr); Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); if (event->detail >= 4 && event->detail <= 7) { @@ -1963,8 +2003,9 @@ void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *even void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event) { - QPoint local(event->event_x, event->event_y); - QPoint global(event->root_x, event->root_y); + const int dpr = int(devicePixelRatio()); + QPoint local(event->event_x/dpr, event->event_y/dpr); + QPoint global(event->root_x/dpr, event->root_y/dpr); Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); handleMouseEvent(event->time, local, global, modifiers); @@ -2014,9 +2055,9 @@ void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event) { return; } - - const QPoint local(event->event_x, event->event_y); - const QPoint global(event->root_x, event->root_y); + const int dpr = int(devicePixelRatio()); + const QPoint local(event->event_x/dpr, event->event_y/dpr); + const QPoint global(event->root_x/dpr, event->root_y/dpr); QWindowSystemInterface::handleEnterEvent(window(), local, global); } @@ -2036,8 +2077,9 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event) QXcbWindow *enterWindow = enter ? connection()->platformWindowFromId(enter->event) : 0; if (enterWindow) { - QPoint local(enter->event_x, enter->event_y); - QPoint global(enter->root_x, enter->root_y); + const int dpr = int(devicePixelRatio()); + QPoint local(enter->event_x/dpr, enter->event_y/dpr); + QPoint global(enter->root_x/dpr, enter->root_y/dpr); QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global); } else { @@ -2190,6 +2232,7 @@ void QXcbWindow::windowEvent(QEvent *event) bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) { + const int dpr = int(devicePixelRatio()); const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE); if (!connection()->wmSupport()->isSupportedByWM(moveResize)) return false; @@ -2198,7 +2241,7 @@ bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) xev.type = moveResize; xev.window = xcb_window(); xev.format = 32; - const QPoint globalPos = window()->mapToGlobal(pos); + const QPoint globalPos = window()->mapToGlobal(pos) * dpr; xev.data.data32[0] = globalPos.x(); xev.data.data32[1] = globalPos.y(); const bool bottom = corner == Qt::BottomRightCorner || corner == Qt::BottomLeftCorner; @@ -2316,9 +2359,10 @@ void QXcbWindow::setMask(const QRegion ®ion) xcb_shape_mask(connection()->xcb_connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, xcb_window(), 0, 0, XCB_NONE); } else { + const int dpr = devicePixelRatio(); QVector rects; foreach (const QRect &r, region.rects()) - rects.push_back(qRectToXCBRectangle(r)); + rects.push_back(qRectToXCBRectangle(mapToNative(r, dpr))); xcb_shape_rectangles(connection()->xcb_connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, xcb_window(), 0, 0, rects.size(), &rects[0]); @@ -2352,4 +2396,9 @@ void QXcbWindow::postSyncWindowRequest() } } +qreal QXcbWindow::devicePixelRatio() const +{ + return m_screen ? m_screen->devicePixelRatio() : 1.0; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index af9b06a791..4a81fff5b8 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -160,6 +160,8 @@ public: void postSyncWindowRequest(); void clearSyncWindowRequest() { m_pendingSyncRequest = 0; } + qreal devicePixelRatio() const; + public Q_SLOTS: void updateSyncRequestCounter(); -- cgit v1.2.3