diff options
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbwindow.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 362 |
1 files changed, 271 insertions, 91 deletions
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 586068d8d9..e4feda2c81 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -101,7 +101,7 @@ #include <X11/Xutil.h> #endif -#if defined(XCB_USE_XINPUT2_MAEMO) || defined(XCB_USE_XINPUT2) +#if defined(XCB_USE_XINPUT2) #include <X11/extensions/XInput2.h> #endif @@ -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) { @@ -166,16 +190,36 @@ static inline bool isTransient(const QWindow *w) || w->type() == Qt::Popup; } -static inline QImage::Format imageFormatForDepth(int depth) +static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, quint32 blue_mask) { switch (depth) { - case 32: return QImage::Format_ARGB32_Premultiplied; - case 24: return QImage::Format_RGB32; - case 16: return QImage::Format_RGB16; - default: - qWarning("Unsupported screen depth: %d", depth); - return QImage::Format_Invalid; + case 32: + if (blue_mask == 0xff) + return QImage::Format_ARGB32_Premultiplied; + if (red_mask == 0x3ff) + return QImage::Format_A2BGR30_Premultiplied; + if (blue_mask == 0x3ff) + return QImage::Format_A2RGB30_Premultiplied; + break; + case 30: + if (red_mask == 0x3ff) + return QImage::Format_BGR30; + if (blue_mask == 0x3ff) + return QImage::Format_RGB30; + break; + case 24: + if (blue_mask == 0xff) + return QImage::Format_RGB32; + break; + case 16: + if (blue_mask == 0x1f) + return QImage::Format_RGB16; + break; + default: + break; } + qWarning("Unsupported screen format: depth: %d, red_mask: %x, blue_mask: %x", depth, red_mask, blue_mask); + return QImage::Format_Invalid; } static inline bool positionIncludesFrame(QWindow *w) @@ -183,6 +227,8 @@ static inline bool positionIncludesFrame(QWindow *w) return qt_window_private(w)->positionPolicy == QWindowPrivate::WindowFrameInclusive; } +static const char *wm_window_type_property_id = "_q_xcb_wm_window_type"; + QXcbWindow::QXcbWindow(QWindow *window) : QPlatformWindow(window) , m_window(0) @@ -201,6 +247,7 @@ QXcbWindow::QXcbWindow(QWindow *window) #endif , m_lastWindowStateEvent(-1) , m_syncState(NoSyncNeeded) + , m_pendingSyncRequest(0) { m_screen = static_cast<QXcbScreen *>(window->screen()->handle()); @@ -225,7 +272,9 @@ void QXcbWindow::create() if (type == Qt::Desktop) { m_window = m_screen->root(); m_depth = m_screen->screen()->root_depth; - m_imageFormat = imageFormatForDepth(m_depth); + m_visualId = m_screen->screen()->root_visual; + const xcb_visualtype_t *visual = m_screen->visualForId(m_visualId); + m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask); connection()->addWindowEventListener(m_window, this); return; } @@ -263,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 { @@ -315,7 +365,7 @@ void QXcbWindow::create() } if (visualInfo) { m_depth = visualInfo->depth; - m_imageFormat = imageFormatForDepth(m_depth); + m_imageFormat = imageFormatForVisual(visualInfo->depth, visualInfo->red_mask, visualInfo->blue_mask); Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), xcb_parent_id, visualInfo->visual, AllocNone); XSetWindowAttributes a; @@ -325,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); @@ -365,7 +417,8 @@ void QXcbWindow::create() } } - m_imageFormat = imageFormatForDepth(m_depth); + const xcb_visualtype_t *visual = m_screen->visualForId(m_visualId); + m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask); Q_XCB_CALL(xcb_create_window(xcb_connection(), m_depth, @@ -466,22 +519,7 @@ void QXcbWindow::create() 32, 2, (void *)data)); -#ifdef XCB_USE_XINPUT2_MAEMO - if (connection()->isUsingXInput2Maemo()) { - XIEventMask xieventmask; - uchar bitmask[2] = { 0, 0 }; - - xieventmask.deviceid = XIAllMasterDevices; - xieventmask.mask = bitmask; - xieventmask.mask_len = sizeof(bitmask); - - XISetMask(bitmask, XI_ButtonPress); - XISetMask(bitmask, XI_ButtonRelease); - XISetMask(bitmask, XI_Motion); - - XISelectEvents(DISPLAY_FROM_XCB(this), m_window, &xieventmask, 1); - } -#elif defined(XCB_USE_XINPUT2) +#if defined(XCB_USE_XINPUT2) connection()->xi2Select(m_window); #endif @@ -540,6 +578,9 @@ void QXcbWindow::destroy() delete m_eglSurface; m_eglSurface = 0; #endif + + if (m_pendingSyncRequest) + m_pendingSyncRequest->invalidate(); } void QXcbWindow::setGeometry(const QRect &rect) @@ -547,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; @@ -698,6 +741,11 @@ void QXcbWindow::show() updateNetWmStateBeforeMap(); } + if (window()->metaObject()->indexOfProperty(wm_window_type_property_id) >= 0) { + QXcbWindowFunctions::WmWindowTypes wmWindowTypes(window()->property(wm_window_type_property_id).value<int>()); + setWmWindowType(wmWindowTypes); + } + if (connection()->time() != XCB_TIME_CURRENT_TIME) updateNetWmUserTime(connection()->time()); @@ -1425,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, @@ -1497,23 +1548,6 @@ void QXcbWindow::requestActivateWindow() connection()->sync(); } -#if XCB_USE_MAEMO_WINDOW_PROPERTIES -void QXcbWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation) -{ - int angle = 0; - switch (orientation) { - case Qt::PortraitOrientation: angle = 270; break; - case Qt::LandscapeOrientation: angle = 0; break; - case Qt::InvertedPortraitOrientation: angle = 90; break; - case Qt::InvertedLandscapeOrientation: angle = 180; break; - case Qt::PrimaryOrientation: break; - } - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - atom(QXcbAtom::MeegoTouchOrientationAngle), XCB_ATOM_CARDINAL, 32, - 1, &angle)); -} -#endif - QSurfaceFormat QXcbWindow::format() const { // ### return actual format @@ -1535,12 +1569,137 @@ QXcbEGLSurface *QXcbWindow::eglSurface() const } #endif +void QXcbWindow::setWmWindowTypeStatic(QWindow *window, QXcbWindowFunctions::WmWindowTypes windowTypes) +{ + if (window->handle()) + static_cast<QXcbWindow *>(window->handle())->setWmWindowType(windowTypes); + else + window->setProperty(wm_window_type_property_id, QVariant::fromValue(static_cast<int>(windowTypes))); +} + +QXcbWindowFunctions::WmWindowTypes QXcbWindow::wmWindowTypes() const +{ + QXcbWindowFunctions::WmWindowTypes result(0); + + xcb_get_property_cookie_t get_cookie = + xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE), + XCB_ATOM_ATOM, 0, 1024); + + xcb_get_property_reply_t *reply = + xcb_get_property_reply(xcb_connection(), get_cookie, NULL); + + if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) { + const xcb_atom_t *types = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply)); + const xcb_atom_t *types_end = types + reply->length; + for (; types != types_end; types++) { + QXcbAtom::Atom type = connection()->qatom(*types); + switch (type) { + case QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL: + result |= QXcbWindowFunctions::Normal; + break; + case QXcbAtom::_NET_WM_WINDOW_TYPE_DESKTOP: + result |= QXcbWindowFunctions::Desktop; + break; + case QXcbAtom::_NET_WM_WINDOW_TYPE_DOCK: + result |= QXcbWindowFunctions::Dock; + break; + case QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLBAR: + result |= QXcbWindowFunctions::Toolbar; + break; + case QXcbAtom::_NET_WM_WINDOW_TYPE_MENU: + result |= QXcbWindowFunctions::Menu; + break; + case QXcbAtom::_NET_WM_WINDOW_TYPE_UTILITY: + result |= QXcbWindowFunctions::Utility; + break; + case QXcbAtom::_NET_WM_WINDOW_TYPE_SPLASH: + result |= QXcbWindowFunctions::Splash; + break; + case QXcbAtom::_NET_WM_WINDOW_TYPE_DIALOG: + result |= QXcbWindowFunctions::Dialog; + break; + case QXcbAtom::_NET_WM_WINDOW_TYPE_DROPDOWN_MENU: + result |= QXcbWindowFunctions::DropDownMenu; + break; + case QXcbAtom::_NET_WM_WINDOW_TYPE_POPUP_MENU: + result |= QXcbWindowFunctions::PopupMenu; + break; + case QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLTIP: + result |= QXcbWindowFunctions::Tooltip; + break; + case QXcbAtom::_NET_WM_WINDOW_TYPE_NOTIFICATION: + result |= QXcbWindowFunctions::Notification; + break; + case QXcbAtom::_NET_WM_WINDOW_TYPE_COMBO: + result |= QXcbWindowFunctions::Combo; + break; + case QXcbAtom::_NET_WM_WINDOW_TYPE_DND: + result |= QXcbWindowFunctions::Dnd; + break; + case QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE: + result |= QXcbWindowFunctions::KdeOverride; + break; + default: + break; + } + } + free(reply); + } + return result; +} + +void QXcbWindow::setWmWindowType(QXcbWindowFunctions::WmWindowTypes types) +{ + QVector<xcb_atom_t> atoms; + + if (types & QXcbWindowFunctions::Normal) + atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL)); + if (types & QXcbWindowFunctions::Desktop) + atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DESKTOP)); + if (types & QXcbWindowFunctions::Dock) + atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DOCK)); + if (types & QXcbWindowFunctions::Toolbar) + atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLBAR)); + if (types & QXcbWindowFunctions::Menu) + atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_MENU)); + if (types & QXcbWindowFunctions::Utility) + atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_UTILITY)); + if (types & QXcbWindowFunctions::Splash) + atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_SPLASH)); + if (types & QXcbWindowFunctions::Dialog) + atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DIALOG)); + if (types & QXcbWindowFunctions::DropDownMenu) + atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DROPDOWN_MENU)); + if (types & QXcbWindowFunctions::PopupMenu) + atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_POPUP_MENU)); + if (types & QXcbWindowFunctions::Tooltip) + atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLTIP)); + if (types & QXcbWindowFunctions::Notification) + atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NOTIFICATION)); + if (types & QXcbWindowFunctions::Combo) + atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_COMBO)); + if (types & QXcbWindowFunctions::Dnd) + atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DND)); + if (types & QXcbWindowFunctions::KdeOverride) + atoms.append(atom(QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE)); + + if (atoms.isEmpty()) { + Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE))); + } else { + Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32, + atoms.count(), atoms.constData())); + } + xcb_flush(xcb_connection()); +} + 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) { } @@ -1556,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; } @@ -1568,6 +1727,7 @@ public: private: xcb_window_t m_window; QRegion *m_region; + int m_dpr; bool m_pending; }; @@ -1581,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); @@ -1682,19 +1844,15 @@ 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); - if (!m_screen->availableGeometry().intersects(rect)) { - Q_FOREACH (QPlatformScreen* screen, m_screen->virtualSiblings()) { - if (screen->availableGeometry().intersects(rect)) { - m_screen = static_cast<QXcbScreen*>(screen); - QWindowSystemInterface::handleWindowScreenChanged(window(), m_screen->QPlatformScreen::screen()); - break; - } - } + QPlatformScreen *newScreen = screenForGeometry(rect); + if (newScreen != m_screen) { + m_screen = static_cast<QXcbScreen*>(newScreen); + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); } m_configureNotifyPending = false; @@ -1728,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); } @@ -1747,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); } @@ -1771,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()))); } } @@ -1802,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); @@ -1827,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) { @@ -1841,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); @@ -1892,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); } @@ -1914,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 { @@ -2068,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; @@ -2076,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; @@ -2194,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<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]); @@ -2221,4 +2387,18 @@ bool QXcbWindow::needsSync() const return m_syncState == SyncAndConfigureReceived; } +void QXcbWindow::postSyncWindowRequest() +{ + if (!m_pendingSyncRequest) { + QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this); + m_pendingSyncRequest = e; + QCoreApplication::postEvent(m_screen->connection(), e); + } +} + +qreal QXcbWindow::devicePixelRatio() const +{ + return m_screen ? m_screen->devicePixelRatio() : 1.0; +} + QT_END_NAMESPACE |