Keep screen geometries from overlapping

The simple mapping of dividing each position by the
devicePixelRatio does not work when screens have different
DPR. If the low-DPR screen above or to the left of the high-DPR
screen, the geometries will overlap in the Qt coordinate system.

This change introduces a new mapping where the origin of each screen
does not move. This mapping is not perfect: it will have gaps between
contiguous screens. However, it will keep non-overlapping screens
non-overlapping in the Qt coordinate system.

Since there is no longer a simple linear coordinate transform, we
have to add screen-dependent mapping functions, and distinguish between
local and non-local coordinates. A side benefit is that the code is
now easier to read, since we remove most manual coordinate transformation.

We also have to cache the screen of each window: since we send resize events
before screen change events, we cannot rely on QPlatformWindow::screen()
(which is set from the screen change event).

Task-number: QTBUG-45076
Change-Id: Ie95a0b71ae274e02903caa102a98af2050a44129
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
This commit is contained in:
Paul Olav Tvete 2015-03-20 17:30:26 +01:00
parent a02c04a51b
commit 4e1b09fa8f
5 changed files with 138 additions and 56 deletions

View File

@ -633,18 +633,17 @@ void QXcbCursor::queryPointer(QXcbConnection *c, xcb_window_t *rootWin, QPoint *
QPoint QXcbCursor::pos() const QPoint QXcbCursor::pos() const
{ {
const int dpr = int(m_screen->devicePixelRatio());
QPoint p; QPoint p;
queryPointer(connection(), 0, &p); queryPointer(connection(), 0, &p);
return p / dpr; return m_screen->mapFromNative(p);
} }
void QXcbCursor::setPos(const QPoint &pos) void QXcbCursor::setPos(const QPoint &pos)
{ {
const int dpr = int(m_screen->devicePixelRatio()); const QPoint xPos = m_screen->mapToNative(pos);
xcb_window_t root = 0; xcb_window_t root = 0;
queryPointer(connection(), &root, 0); queryPointer(connection(), &root, 0);
xcb_warp_pointer(xcb_connection(), XCB_NONE, root, 0, 0, 0, 0, pos.x()*dpr, pos.y()*dpr); xcb_warp_pointer(xcb_connection(), XCB_NONE, root, 0, 0, 0, 0, xPos.x(), xPos.y());
xcb_flush(xcb_connection()); xcb_flush(xcb_connection());
} }

View File

@ -273,6 +273,31 @@ QWindow *QXcbScreen::topLevelAt(const QPoint &p) const
return 0; return 0;
} }
QPoint QXcbScreen::mapToNative(const QPoint &pos) const
{
const int dpr = int(devicePixelRatio());
return (pos - m_geometry.topLeft()) * dpr + m_nativeGeometry.topLeft();
}
QPoint QXcbScreen::mapFromNative(const QPoint &pos) const
{
const int dpr = int(devicePixelRatio());
return (pos - m_nativeGeometry.topLeft()) / dpr + m_geometry.topLeft();
}
QRect QXcbScreen::mapToNative(const QRect &rect) const
{
const int dpr = int(devicePixelRatio());
return QRect(mapToNative(rect.topLeft()), rect.size() * dpr);
}
QRect QXcbScreen::mapFromNative(const QRect &rect) const
{
const int dpr = int(devicePixelRatio());
return QRect(mapFromNative(rect.topLeft()), rect.size() / dpr);
}
void QXcbScreen::windowShown(QXcbWindow *window) void QXcbScreen::windowShown(QXcbWindow *window)
{ {
// Freedesktop.org Startup Notification // Freedesktop.org Startup Notification
@ -499,9 +524,9 @@ void QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation)
qreal dpi = xGeometry.width() / physicalSize().width() * qreal(25.4); qreal dpi = xGeometry.width() / physicalSize().width() * qreal(25.4);
m_devicePixelRatio = qRound(dpi/96); m_devicePixelRatio = qRound(dpi/96);
const int dpr = int(devicePixelRatio()); // we may override m_devicePixelRatio const int dpr = int(devicePixelRatio()); // we may override m_devicePixelRatio
m_geometry = QRect(xGeometry.topLeft()/dpr, xGeometry.size()/dpr); m_geometry = QRect(xGeometry.topLeft(), xGeometry.size()/dpr);
m_nativeGeometry = QRect(xGeometry.topLeft(), xGeometry.size()); m_nativeGeometry = QRect(xGeometry.topLeft(), xGeometry.size());
m_availableGeometry = QRect(xAvailableGeometry.topLeft()/dpr, xAvailableGeometry.size()/dpr); m_availableGeometry = QRect(mapFromNative(xAvailableGeometry.topLeft()), xAvailableGeometry.size()/dpr);
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry); QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry);
} }

View File

@ -140,6 +140,11 @@ public:
QXcbXSettings *xSettings() const; QXcbXSettings *xSettings() const;
QPoint mapToNative(const QPoint &pos) const;
QPoint mapFromNative(const QPoint &pos) const;
QRect mapToNative(const QRect &rect) const;
QRect mapFromNative(const QRect &rect) const;
private: private:
static bool xResource(const QByteArray &identifier, static bool xResource(const QByteArray &identifier,
const QByteArray &expectedIdentifier, const QByteArray &expectedIdentifier,

View File

@ -138,7 +138,7 @@ enum QX11EmbedMessageType {
const quint32 XEMBED_VERSION = 0; const quint32 XEMBED_VERSION = 0;
static inline QRect mapToNative(const QRect &qtRect, int dpr) static inline QRect mapLocalGeometryToNative(const QRect &qtRect, int dpr)
{ {
return QRect(qtRect.x() * dpr, qtRect.y() * dpr, qtRect.width() * dpr, qtRect.height() * dpr); return QRect(qtRect.x() * dpr, qtRect.y() * dpr, qtRect.width() * dpr, qtRect.height() * dpr);
} }
@ -166,11 +166,45 @@ static inline QRect mapExposeFromNative(const QRect &xRect, int dpr)
return QRect(dpr_floor(xRect.topLeft(), dpr), dpr_ceil(xRect.bottomRight(), dpr)); return QRect(dpr_floor(xRect.topLeft(), dpr), dpr_ceil(xRect.bottomRight(), dpr));
} }
static inline QRect mapGeometryFromNative(const QRect &xRect, int dpr) static inline QRect mapLocalGeometryFromNative(const QRect &xRect, int dpr)
{ {
return QRect(xRect.topLeft() / dpr, dpr_ceil(xRect.size(), dpr)); return QRect(xRect.topLeft() / dpr, dpr_ceil(xRect.size(), dpr));
} }
QXcbScreen *QXcbWindow::parentScreen()
{
return parent() ? static_cast<QXcbWindow*>(parent())->parentScreen() : m_xcbScreen;
}
QPoint QXcbWindow::mapToNative(const QPoint &pos, const QXcbScreen *screen) const
{
if (parent())
return pos * int(screen->devicePixelRatio());
else
return screen->mapToNative(pos);
}
QPoint QXcbWindow::mapFromNative(const QPoint &pos, const QXcbScreen *screen) const
{
if (parent())
return pos / int(screen->devicePixelRatio());
else
return screen->mapFromNative(pos);
}
QRect QXcbWindow::mapToNative(const QRect &rect, const QXcbScreen *screen) const
{
if (parent())
return mapLocalGeometryToNative(rect, int(screen->devicePixelRatio()));
else
return screen->mapToNative(rect);
}
QRect QXcbWindow::mapFromNative(const QRect &rect, const QXcbScreen *screen) const
{
if (parent())
return mapLocalGeometryFromNative(rect, int(screen->devicePixelRatio()));
else
return screen->mapFromNative(rect);
}
// Returns \c true if we should set WM_TRANSIENT_FOR on \a w // Returns \c true if we should set WM_TRANSIENT_FOR on \a w
static inline bool isTransient(const QWindow *w) static inline bool isTransient(const QWindow *w)
{ {
@ -291,6 +325,7 @@ static const char *wm_window_type_property_id = "_q_xcb_wm_window_type";
QXcbWindow::QXcbWindow(QWindow *window) QXcbWindow::QXcbWindow(QWindow *window)
: QPlatformWindow(window) : QPlatformWindow(window)
, m_window(0) , m_window(0)
, m_xcbScreen(0)
, m_syncCounter(0) , m_syncCounter(0)
, m_gravity(XCB_GRAVITY_STATIC) , m_gravity(XCB_GRAVITY_STATIC)
, m_mapped(false) , m_mapped(false)
@ -344,8 +379,11 @@ void QXcbWindow::create()
Qt::WindowType type = window()->type(); Qt::WindowType type = window()->type();
QXcbScreen *platformScreen = xcbScreen(); QXcbScreen *currentScreen = xcbScreen();
QRect rect = window()->geometry();
QXcbScreen *platformScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
m_xcbScreen = platformScreen;
if (type == Qt::Desktop) { if (type == Qt::Desktop) {
m_window = platformScreen->root(); m_window = platformScreen->root();
m_depth = platformScreen->screen()->root_depth; m_depth = platformScreen->screen()->root_depth;
@ -371,13 +409,10 @@ void QXcbWindow::create()
// Parameters to XCreateWindow() are frame corner + inner size. // Parameters to XCreateWindow() are frame corner + inner size.
// This fits in case position policy is frame inclusive. There is // This fits in case position policy is frame inclusive. There is
// currently no way to implement it for frame-exclusive geometries. // currently no way to implement it for frame-exclusive geometries.
QRect rect = window()->geometry();
QPlatformWindow::setGeometry(rect); QPlatformWindow::setGeometry(rect);
QXcbScreen *currentScreen = xcbScreen();
QPlatformScreen *newScreen = screenForGeometry(rect);
if (newScreen != currentScreen) if (platformScreen != currentScreen)
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); QWindowSystemInterface::handleWindowScreenChanged(window(), platformScreen->QPlatformScreen::screen());
const int dpr = int(devicePixelRatio()); const int dpr = int(devicePixelRatio());
@ -428,7 +463,7 @@ void QXcbWindow::create()
m_visualId = visualInfo->visualid; m_visualId = visualInfo->visualid;
const QRect xRect = mapToNative(rect, dpr); const QRect xRect = mapToNative(rect, platformScreen);
m_window = XCreateWindow(DISPLAY_FROM_XCB(this), xcb_parent_id, xRect.x(), xRect.y(), xRect.width(), xRect.height(), m_window = XCreateWindow(DISPLAY_FROM_XCB(this), xcb_parent_id, xRect.x(), xRect.y(), xRect.width(), xRect.height(),
0, visualInfo->depth, InputOutput, visualInfo->visual, 0, visualInfo->depth, InputOutput, visualInfo->visual,
@ -472,15 +507,16 @@ void QXcbWindow::create()
const xcb_visualtype_t *visual = platformScreen->visualForId(m_visualId); const xcb_visualtype_t *visual = platformScreen->visualForId(m_visualId);
m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap); m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap);
const QRect xRect = mapToNative(rect, platformScreen);
Q_XCB_CALL(xcb_create_window(xcb_connection(), Q_XCB_CALL(xcb_create_window(xcb_connection(),
m_depth, m_depth,
m_window, // window id m_window, // window id
xcb_parent_id, // parent window id xcb_parent_id, // parent window id
rect.x(), xRect.x(),
rect.y(), xRect.y(),
rect.width(), xRect.width(),
rect.height(), xRect.height(),
0, // border width 0, // border width
XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
m_visualId, // visual m_visualId, // visual
@ -631,7 +667,7 @@ void QXcbWindow::destroy()
void QXcbWindow::maybeSetScreen(QXcbScreen *screen) void QXcbWindow::maybeSetScreen(QXcbScreen *screen)
{ {
if (!window()->screen() && screen->geometry().contains(geometry().topLeft() * int(devicePixelRatio()))) { if (!window()->screen() && screen->geometry().contains(geometry().topLeft())) {
QWindowSystemInterface::handleWindowScreenChanged(window(), static_cast<QPlatformScreen *>(screen)->screen()); QWindowSystemInterface::handleWindowScreenChanged(window(), static_cast<QPlatformScreen *>(screen)->screen());
QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(0, 0), window()->size()))); QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(0, 0), window()->size())));
} }
@ -644,16 +680,17 @@ void QXcbWindow::setGeometry(const QRect &rect)
propagateSizeHints(); propagateSizeHints();
QXcbScreen *currentScreen = xcbScreen(); QXcbScreen *currentScreen = xcbScreen();
QPlatformScreen *newScreen = screenForGeometry(rect); QXcbScreen *newScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
if (!newScreen) if (!newScreen)
newScreen = currentScreen; newScreen = currentScreen;
const QRect xRect = mapToNative(rect, int(newScreen->devicePixelRatio())); m_xcbScreen = newScreen;
const QRect xRect = mapToNative(rect, newScreen);
const QRect wmGeometry = windowToWmGeometry(xRect); const QRect wmGeometry = windowToWmGeometry(xRect);
if (newScreen != currentScreen) if (newScreen != currentScreen)
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
if (qt_window_private(window())->positionAutomatic) { if (qt_window_private(window())->positionAutomatic) {
const quint32 mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; const quint32 mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
@ -1160,6 +1197,8 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
event.data.data32[3] = 0; event.data.data32[3] = 0;
event.data.data32[4] = 0; event.data.data32[4] = 0;
if (!xcbScreen())
return;
Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
} }
@ -1554,7 +1593,7 @@ void QXcbWindow::propagateSizeHints()
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
const int dpr = int(devicePixelRatio()); const int dpr = int(devicePixelRatio());
const QRect xRect = mapToNative(windowToWmGeometry(geometry()), dpr); const QRect xRect = windowToWmGeometry(mapToNative(geometry(), xcbScreen()));
QWindow *win = window(); QWindow *win = window();
@ -1892,20 +1931,21 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
} }
} }
// Temporary workaround for bug in QPlatformScreen::screenForNativeGeometry // Temporary workaround for bug in QPlatformScreen::screenForGeometry
// we need the native geometries to detect our screen, but that's not // we need the native geometries to detect our screen, but that's not
// available in cross-platform code. Will be fixed properly when highDPI // available in cross-platform code. Will be fixed properly when highDPI
// support is refactored to expose the native coordinate system. // support is refactored to expose the native coordinate system.
QPlatformScreen *QXcbWindow::screenForNativeGeometry(const QRect &newGeometry) const QXcbScreen *QXcbWindow::screenForNativeGeometry(const QRect &newGeometry) const
{ {
QXcbScreen *currentScreen = static_cast<QXcbScreen*>(screen()); QXcbScreen *currentScreen = xcbScreen();
if (!currentScreen && QGuiApplication::primaryScreen()) if (!currentScreen && QGuiApplication::primaryScreen())
currentScreen = static_cast<QXcbScreen*>(QGuiApplication::primaryScreen()->handle()); currentScreen = static_cast<QXcbScreen*>(QGuiApplication::primaryScreen()->handle());
if (currentScreen && !parent() && !currentScreen->nativeGeometry().intersects(newGeometry)) { if (currentScreen && !parent() && !currentScreen->nativeGeometry().intersects(newGeometry)) {
Q_FOREACH (QPlatformScreen* screen, currentScreen->virtualSiblings()) { Q_FOREACH (QPlatformScreen* screen, currentScreen->virtualSiblings()) {
if (static_cast<QXcbScreen*>(screen)->nativeGeometry().intersects(newGeometry)) QXcbScreen *xcbScreen = static_cast<QXcbScreen*>(screen);
return screen; if (xcbScreen->nativeGeometry().intersects(newGeometry))
return xcbScreen;
} }
} }
return currentScreen; return currentScreen;
@ -1927,23 +1967,18 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
} }
} }
const int dpr = devicePixelRatio();
const QRect nativeRect = QRect(pos, QSize(event->width, event->height)); const QRect nativeRect = QRect(pos, QSize(event->width, event->height));
const QRect rect = mapGeometryFromNative(nativeRect, dpr); QXcbScreen *newScreen = parent() ? parentScreen() : screenForNativeGeometry(nativeRect);
m_xcbScreen = newScreen;
if (!newScreen)
return;
const QRect rect = mapFromNative(nativeRect, newScreen);
QPlatformWindow::setGeometry(rect); QPlatformWindow::setGeometry(rect);
QWindowSystemInterface::handleGeometryChange(window(), rect); QWindowSystemInterface::handleGeometryChange(window(), rect);
QPlatformScreen *newScreen = screenForNativeGeometry(nativeRect); if (newScreen != screen())
if (newScreen != screen()) { QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
if (newScreen)
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
int newDpr = newScreen->devicePixelRatio();
if (newDpr != dpr) {
QRect newRect = mapGeometryFromNative(nativeRect, newDpr);
QPlatformWindow::setGeometry(newRect);
QWindowSystemInterface::handleGeometryChange(window(), newRect);
}
}
m_configureNotifyPending = false; m_configureNotifyPending = false;
@ -1984,12 +2019,12 @@ QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const
xcb_translate_coordinates_reply_t *reply = xcb_translate_coordinates_reply_t *reply =
xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL);
if (reply) { if (reply) {
ret.setX(reply->dst_x / dpr); ret.setX(reply->dst_x);
ret.setY(reply->dst_y / dpr); ret.setY(reply->dst_y);
free(reply); free(reply);
} }
return ret; return mapFromNative(ret, xcbScreen());
} }
QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const
@ -1999,9 +2034,10 @@ QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const
const int dpr = int(devicePixelRatio()); const int dpr = int(devicePixelRatio());
QPoint ret; QPoint ret;
QPoint xPos = mapToNative(pos, xcbScreen());
xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates_cookie_t cookie =
xcb_translate_coordinates(xcb_connection(), xcbScreen()->root(), xcb_window(), xcb_translate_coordinates(xcb_connection(), xcbScreen()->root(), xcb_window(),
pos.x() *dpr, pos.y() * dpr); xPos.x(), xPos.y());
xcb_translate_coordinates_reply_t *reply = xcb_translate_coordinates_reply_t *reply =
xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL);
if (reply) { if (reply) {
@ -2055,7 +2091,7 @@ void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event)
} }
const int dpr = int(devicePixelRatio()); const int dpr = int(devicePixelRatio());
QPoint local(event->event_x/dpr, event->event_y/dpr); QPoint local(event->event_x/dpr, event->event_y/dpr);
QPoint global(event->root_x/dpr, event->root_y/dpr); QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
@ -2080,7 +2116,7 @@ void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *even
{ {
const int dpr = int(devicePixelRatio()); const int dpr = int(devicePixelRatio());
QPoint local(event->event_x/dpr, event->event_y/dpr); QPoint local(event->event_x/dpr, event->event_y/dpr);
QPoint global(event->root_x/dpr, event->root_y/dpr); QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
if (event->detail >= 4 && event->detail <= 7) { if (event->detail >= 4 && event->detail <= 7) {
@ -2095,7 +2131,9 @@ void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event)
{ {
const int dpr = int(devicePixelRatio()); const int dpr = int(devicePixelRatio());
QPoint local(event->event_x/dpr, event->event_y/dpr); QPoint local(event->event_x/dpr, event->event_y/dpr);
QPoint global(event->root_x/dpr, event->root_y/dpr); if (!xcbScreen())
return;
QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
handleMouseEvent(event->time, local, global, modifiers); handleMouseEvent(event->time, local, global, modifiers);
@ -2152,7 +2190,9 @@ void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
const int dpr = int(devicePixelRatio()); const int dpr = int(devicePixelRatio());
const QPoint local(event->event_x/dpr, event->event_y/dpr); const QPoint local(event->event_x/dpr, event->event_y/dpr);
const QPoint global(event->root_x/dpr, event->root_y/dpr); if (!xcbScreen())
return;
QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
QWindowSystemInterface::handleEnterEvent(window(), local, global); QWindowSystemInterface::handleEnterEvent(window(), local, global);
} }
@ -2170,7 +2210,9 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
if (enterWindow) { if (enterWindow) {
const int dpr = int(devicePixelRatio()); const int dpr = int(devicePixelRatio());
QPoint local(enter->event_x/dpr, enter->event_y/dpr); QPoint local(enter->event_x/dpr, enter->event_y/dpr);
QPoint global(enter->root_x/dpr, enter->root_y/dpr); if (!xcbScreen())
return;
QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global); QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global);
} else { } else {
@ -2185,6 +2227,8 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
connection()->setTime(event->time); connection()->setTime(event->time);
const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE; const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE;
if (!xcbScreen())
return;
if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) { if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) {
if (propertyDeleted) if (propertyDeleted)
@ -2333,7 +2377,6 @@ void QXcbWindow::windowEvent(QEvent *event)
bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) 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); const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
if (!connection()->wmSupport()->isSupportedByWM(moveResize)) if (!connection()->wmSupport()->isSupportedByWM(moveResize))
return false; return false;
@ -2342,7 +2385,7 @@ bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
xev.type = moveResize; xev.type = moveResize;
xev.window = xcb_window(); xev.window = xcb_window();
xev.format = 32; xev.format = 32;
const QPoint globalPos = window()->mapToGlobal(pos) * dpr; const QPoint globalPos = mapToNative(window()->mapToGlobal(pos), xcbScreen());
xev.data.data32[0] = globalPos.x(); xev.data.data32[0] = globalPos.x();
xev.data.data32[1] = globalPos.y(); xev.data.data32[1] = globalPos.y();
const bool bottom = corner == Qt::BottomRightCorner || corner == Qt::BottomLeftCorner; const bool bottom = corner == Qt::BottomRightCorner || corner == Qt::BottomLeftCorner;
@ -2471,7 +2514,7 @@ void QXcbWindow::setMask(const QRegion &region)
const int dpr = devicePixelRatio(); const int dpr = devicePixelRatio();
QVector<xcb_rectangle_t> rects; QVector<xcb_rectangle_t> rects;
foreach (const QRect &r, region.rects()) foreach (const QRect &r, region.rects())
rects.push_back(qRectToXCBRectangle(mapToNative(r, dpr))); rects.push_back(qRectToXCBRectangle(mapLocalGeometryToNative(r, dpr)));
xcb_shape_rectangles(connection()->xcb_connection(), XCB_SHAPE_SO_SET, xcb_shape_rectangles(connection()->xcb_connection(), XCB_SHAPE_SO_SET,
XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
xcb_window(), 0, 0, rects.size(), &rects[0]); xcb_window(), 0, 0, rects.size(), &rects[0]);
@ -2495,6 +2538,8 @@ bool QXcbWindow::needsSync() const
void QXcbWindow::postSyncWindowRequest() void QXcbWindow::postSyncWindowRequest()
{ {
if (!xcbScreen())
return;
if (!m_pendingSyncRequest) { if (!m_pendingSyncRequest) {
QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this); QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this);
m_pendingSyncRequest = e; m_pendingSyncRequest = e;

View File

@ -155,7 +155,7 @@ public:
virtual void create(); virtual void create();
virtual void destroy(); virtual void destroy();
void maybeSetScreen(QXcbScreen *screen); void maybeSetScreen(QXcbScreen *screen);
QPlatformScreen *screenForNativeGeometry(const QRect &newGeometry) const; QXcbScreen *screenForNativeGeometry(const QRect &newGeometry) const;
public Q_SLOTS: public Q_SLOTS:
void updateSyncRequestCounter(); void updateSyncRequestCounter();
@ -165,6 +165,12 @@ protected:
virtual void *createVisual() { return Q_NULLPTR; } virtual void *createVisual() { return Q_NULLPTR; }
virtual bool supportsSyncProtocol() { return !window()->supportsOpenGL(); } virtual bool supportsSyncProtocol() { return !window()->supportsOpenGL(); }
QPoint mapToNative(const QPoint &pos, const QXcbScreen *screen) const;
QPoint mapFromNative(const QPoint &pos, const QXcbScreen *screen) const;
QRect mapToNative(const QRect &rect, const QXcbScreen *screen) const;
QRect mapFromNative(const QRect &rect, const QXcbScreen *screen) const;
QXcbScreen *parentScreen();
void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0); void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0);
NetWmStates netWmStates(); NetWmStates netWmStates();
void setNetWmStates(NetWmStates); void setNetWmStates(NetWmStates);
@ -192,6 +198,8 @@ protected:
xcb_window_t m_window; xcb_window_t m_window;
QXcbScreen *m_xcbScreen;
uint m_depth; uint m_depth;
QImage::Format m_imageFormat; QImage::Format m_imageFormat;
bool m_imageRgbSwap; bool m_imageRgbSwap;