devicePixelRatio support for XCB

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 <allan.jensen@digia.com>
Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
This commit is contained in:
Paul Olav Tvete 2014-07-29 13:12:01 +02:00
parent 98cd256d24
commit ae5f2a6672
8 changed files with 174 additions and 73 deletions

View File

@ -280,13 +280,14 @@ void QXcbBackingStore::beginPaint(const QRegion &region)
{
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<QRect> rects = region.rects();
const QVector<QRect> rects = xRegion.rects();
const QColor blank = Qt::transparent;
for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) {
p.fillRect(*it, blank);
@ -323,9 +324,13 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
return;
}
const int dpr = int(window->devicePixelRatio());
QVector<QRect> 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 &region, 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<QXcbScreen *>(window()->screen()->handle());
@ -369,7 +376,8 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &)
QXcbWindow* win = static_cast<QXcbWindow *>(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<QRect> 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<QRect> xRects = xArea.rects();
for (int i = 0; i < xRects.size(); ++i)
qt_scrollRectInImage(*m_image->image(), xRects.at(i), delta);
return true;
}

View File

@ -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());

View File

@ -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());
}

View File

@ -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();
}

View File

@ -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
{
if (m_forcedDpi > 0)
return QDpi(m_forcedDpi, m_forcedDpi);
int dpr = int(devicePixelRatio());
return QDpi(Q_MM_PER_INCH * m_virtualSize.width() / m_virtualSizeMillimeters.width(),
Q_MM_PER_INCH * m_virtualSize.height() / m_virtualSizeMillimeters.height());
if (m_forcedDpi > 0)
return QDpi(m_forcedDpi/dpr, m_forcedDpi/dpr);
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);
}

View File

@ -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;

View File

@ -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 &region)
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<xcb_rectangle_t> 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

View File

@ -160,6 +160,8 @@ public:
void postSyncWindowRequest();
void clearSyncWindowRequest() { m_pendingSyncRequest = 0; }
qreal devicePixelRatio() const;
public Q_SLOTS:
void updateSyncRequestCounter();