X11 devicePixelRatio screen mapping fix

Fix screen detection and window geometry when screens have
different displayPixelRatios.

We must use the native coordinate system to figure out which
screen a window belongs to. Also, when a window moves to a
screen with a different devicePixelRatio, we must recalculate
the Qt geometry.

Task-number: QTBUG-43713
Change-Id: I93063e37354ff88f3c8a13320b76dfb272e43a9c
Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com>
bb10
Paul Olav Tvete 2015-01-07 15:44:12 +01:00
parent 3ba1b989a6
commit 075ae987c4
4 changed files with 35 additions and 3 deletions

View File

@ -77,8 +77,10 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr,
// virtual size is known (probably back-calculated from DPI and resolution)
if (m_sizeMillimeters.isEmpty())
m_sizeMillimeters = m_virtualSizeMillimeters;
if (m_geometry.isEmpty())
if (m_geometry.isEmpty()) {
m_geometry = QRect(QPoint(), m_virtualSize/dpr);
m_nativeGeometry = QRect(QPoint(), m_virtualSize);
}
if (m_availableGeometry.isEmpty())
m_availableGeometry = m_geometry;
@ -461,6 +463,7 @@ void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)
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_nativeGeometry = QRect(xGeometry.topLeft(), xGeometry.size());
m_availableGeometry = QRect(xAvailableGeometry.topLeft()/dpr, xAvailableGeometry.size()/dpr);
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry);

View File

@ -62,6 +62,7 @@ public:
QWindow *topLevelAt(const QPoint &point) const;
QRect geometry() const { return m_geometry; }
QRect nativeGeometry() const { return m_nativeGeometry; }
QRect availableGeometry() const {return m_availableGeometry;}
int depth() const { return m_screen->root_depth; }
QImage::Format format() const;
@ -114,6 +115,7 @@ private:
QSizeF m_outputSizeMillimeters;
QSizeF m_sizeMillimeters;
QRect m_geometry;
QRect m_nativeGeometry;
QRect m_availableGeometry;
QSize m_virtualSize;
QSizeF m_virtualSizeMillimeters;

View File

@ -1831,6 +1831,23 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
}
}
// Temporary workaround for bug in QPlatformScreen::screenForNativeGeometry
// we need the native geometries to detect our screen, but that's not
// available in cross-platform code. Will be fixed properly when highDPI
// support is refactored to expose the native coordinate system.
QPlatformScreen *QXcbWindow::screenForNativeGeometry(const QRect &newGeometry) const
{
QXcbScreen *currentScreen = static_cast<QXcbScreen*>(screen());
if (!parent() && !currentScreen->nativeGeometry().intersects(newGeometry)) {
Q_FOREACH (QPlatformScreen* screen, currentScreen->virtualSiblings()) {
if (static_cast<QXcbScreen*>(screen)->nativeGeometry().intersects(newGeometry))
return screen;
}
}
return currentScreen;
}
void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *event)
{
bool fromSendEvent = (event->response_type & 0x80);
@ -1847,15 +1864,23 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
}
}
QRect rect = mapFromNative(QRect(pos, QSize(event->width, event->height)), int(devicePixelRatio()));
const int dpr = devicePixelRatio();
const QRect nativeRect = QRect(pos, QSize(event->width, event->height));
const QRect rect = mapFromNative(nativeRect, dpr);
QPlatformWindow::setGeometry(rect);
QWindowSystemInterface::handleGeometryChange(window(), rect);
QPlatformScreen *newScreen = screenForGeometry(rect);
QPlatformScreen *newScreen = screenForNativeGeometry(nativeRect);
if (newScreen != m_screen) {
m_screen = static_cast<QXcbScreen*>(newScreen);
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
int newDpr = devicePixelRatio();
if (newDpr != dpr) {
QRect newRect = mapFromNative(nativeRect, newDpr);
QPlatformWindow::setGeometry(newRect);
QWindowSystemInterface::handleGeometryChange(window(), newRect);
}
}
m_configureNotifyPending = false;

View File

@ -154,6 +154,8 @@ public:
qreal devicePixelRatio() const;
QPlatformScreen *screenForNativeGeometry(const QRect &newGeometry) const;
public Q_SLOTS:
void updateSyncRequestCounter();