diff options
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbwindow.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 260 |
1 files changed, 133 insertions, 127 deletions
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index c0076a9977..eed8b19013 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. ** @@ -10,9 +10,9 @@ ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -23,8 +23,8 @@ ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ @@ -97,15 +97,6 @@ #include <X11/extensions/XInput2.h> #endif -#if defined(XCB_USE_GLX) -#include "qglxintegration.h" -#include <QtPlatformSupport/private/qglxconvenience_p.h> -#elif defined(XCB_USE_EGL) -#include "qxcbeglsurface.h" -#include <QtPlatformSupport/private/qeglconvenience_p.h> -#include <QtPlatformSupport/private/qxlibeglintegration_p.h> -#endif - #define XCOORD_MAX 16383 enum { defaultWindowWidth = 160, @@ -164,6 +155,11 @@ static inline QPoint dpr_ceil(const QPoint &p, int dpr) return QPoint((p.x() + dpr - 1) / dpr, (p.y() + dpr - 1) / dpr); } +static inline QSize dpr_ceil(const QSize &s, int dpr) +{ + return QSize((s.width() + dpr - 1) / dpr, (s.height() + dpr - 1) / dpr); +} + static inline QRect mapExposeFromNative(const QRect &xRect, int dpr) { return QRect(dpr_floor(xRect.topLeft(), dpr), dpr_ceil(xRect.bottomRight(), dpr)); @@ -171,7 +167,7 @@ static inline QRect mapExposeFromNative(const QRect &xRect, int dpr) static inline QRect mapGeometryFromNative(const QRect &xRect, int dpr) { - return QRect(xRect.topLeft() / dpr, xRect.bottomRight() / dpr); + return QRect(xRect.topLeft() / dpr, dpr_ceil(xRect.size(), dpr)); } // Returns \c true if we should set WM_TRANSIENT_FOR on \a w @@ -186,8 +182,10 @@ static inline bool isTransient(const QWindow *w) || w->type() == Qt::Popup; } -static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, quint32 blue_mask) +static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, quint32 blue_mask, bool *rgbSwap) { + if (rgbSwap) + *rgbSwap = false; switch (depth) { case 32: if (blue_mask == 0xff) @@ -196,6 +194,11 @@ static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, q return QImage::Format_A2BGR30_Premultiplied; if (blue_mask == 0x3ff) return QImage::Format_A2RGB30_Premultiplied; + if (red_mask == 0xff) { + if (rgbSwap) + *rgbSwap = true; + return QImage::Format_ARGB32_Premultiplied; + } break; case 30: if (red_mask == 0x3ff) @@ -206,6 +209,11 @@ static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, q case 24: if (blue_mask == 0xff) return QImage::Format_RGB32; + if (red_mask == 0xff) { + if (rgbSwap) + *rgbSwap = true; + return QImage::Format_RGB32; + } break; case 16: if (blue_mask == 0x1f) @@ -250,21 +258,11 @@ QXcbWindow::QXcbWindow(QWindow *window) , m_alertState(false) , m_netWmUserTimeWindow(XCB_NONE) , m_dirtyFrameMargins(false) -#if defined(XCB_USE_EGL) - , m_eglSurface(0) -#endif , m_lastWindowStateEvent(-1) , m_syncState(NoSyncNeeded) , m_pendingSyncRequest(0) { - m_screen = static_cast<QXcbScreen *>(window->screen()->handle()); - - setConnection(m_screen->connection()); - - if (window->type() != Qt::ForeignWindow) - create(); - else - m_window = window->winId(); + setConnection(xcbScreen()->connection()); } #ifdef Q_COMPILER_CLASS_ENUM @@ -290,6 +288,11 @@ enum { void QXcbWindow::create() { + if (window()->type() == Qt::ForeignWindow) { + m_window = window()->winId(); + return; + } + destroy(); m_deferredExpose = false; @@ -298,12 +301,14 @@ void QXcbWindow::create() Qt::WindowType type = window()->type(); + QXcbScreen *platformScreen = xcbScreen(); + if (type == Qt::Desktop) { - m_window = m_screen->root(); - m_depth = m_screen->screen()->root_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); + m_window = platformScreen->root(); + m_depth = platformScreen->screen()->root_depth; + m_visualId = platformScreen->screen()->root_visual; + const xcb_visualtype_t *visual = platformScreen->visualForId(m_visualId); + m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap); connection()->addWindowEventListener(m_window, this); return; } @@ -325,6 +330,12 @@ void QXcbWindow::create() // currently no way to implement it for frame-exclusive geometries. QRect rect = window()->geometry(); QPlatformWindow::setGeometry(rect); + QXcbScreen *currentScreen = xcbScreen(); + QPlatformScreen *newScreen = screenForGeometry(rect); + + if (newScreen != currentScreen) + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); + const int dpr = int(devicePixelRatio()); QSize minimumSize = window()->minimumSize(); @@ -338,7 +349,7 @@ void QXcbWindow::create() rect.setHeight(defaultWindowHeight); } - xcb_window_t xcb_parent_id = m_screen->root(); + xcb_window_t xcb_parent_id = platformScreen->root(); if (parent()) { xcb_parent_id = static_cast<QXcbWindow *>(parent())->xcb_window(); m_embedded = parent()->window()->type() == Qt::ForeignWindow; @@ -348,27 +359,12 @@ void QXcbWindow::create() window()->setFormat(parentFormat); } } - m_format = window()->requestedFormat(); -#if (defined(XCB_USE_GLX) || defined(XCB_USE_EGL)) && defined(XCB_USE_XLIB) + resolveFormat(); + +#ifdef XCB_USE_XLIB if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) { -#if defined(XCB_USE_GLX) - XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), &m_format); -#elif defined(XCB_USE_EGL) - EGLDisplay eglDisplay = connection()->egl_display(); - EGLConfig eglConfig = q_configFromGLFormat(eglDisplay, m_format, true); - m_format = q_glFormatFromConfig(eglDisplay, eglConfig, m_format); - - VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this), eglDisplay, eglConfig); - - XVisualInfo visualInfoTemplate; - memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); - visualInfoTemplate.visualid = id; - - XVisualInfo *visualInfo; - int matchingCount = 0; - visualInfo = XGetVisualInfo(DISPLAY_FROM_XCB(this), VisualIDMask, &visualInfoTemplate, &matchingCount); -#endif //XCB_USE_GLX + XVisualInfo *visualInfo = static_cast<XVisualInfo *>(createVisual()); if (!visualInfo && window()->surfaceType() == QSurface::OpenGLSurface) qFatal("Could not initialize OpenGL"); @@ -376,14 +372,15 @@ void QXcbWindow::create() qWarning("Could not initialize OpenGL for RasterGLSurface, reverting to RasterSurface."); window()->setSurfaceType(QSurface::RasterSurface); } + if (visualInfo) { m_depth = visualInfo->depth; - m_imageFormat = imageFormatForVisual(visualInfo->depth, visualInfo->red_mask, visualInfo->blue_mask); + m_imageFormat = imageFormatForVisual(visualInfo->depth, visualInfo->red_mask, visualInfo->blue_mask, &m_imageRgbSwap); Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), xcb_parent_id, visualInfo->visual, AllocNone); XSetWindowAttributes a; - a.background_pixel = WhitePixel(DISPLAY_FROM_XCB(this), m_screen->screenNumber()); - a.border_pixel = BlackPixel(DISPLAY_FROM_XCB(this), m_screen->screenNumber()); + a.background_pixel = WhitePixel(DISPLAY_FROM_XCB(this), platformScreen->screenNumber()); + a.border_pixel = BlackPixel(DISPLAY_FROM_XCB(this), platformScreen->screenNumber()); a.colormap = cmap; m_visualId = visualInfo->visualid; @@ -397,19 +394,19 @@ void QXcbWindow::create() XFree(visualInfo); } } +#endif if (!m_window) -#endif //defined(XCB_USE_GLX) || defined(XCB_USE_EGL) { m_window = xcb_generate_id(xcb_connection()); - m_visualId = m_screen->screen()->root_visual; - m_depth = m_screen->screen()->root_depth; + m_visualId = platformScreen->screen()->root_visual; + m_depth = platformScreen->screen()->root_depth; uint32_t mask = 0; uint32_t values[3]; if (m_format.alphaBufferSize() == 8) { - xcb_depth_iterator_t depthIter = xcb_screen_allowed_depths_iterator(m_screen->screen()); + xcb_depth_iterator_t depthIter = xcb_screen_allowed_depths_iterator(platformScreen->screen()); while (depthIter.rem) { if (depthIter.data->depth == 32) { xcb_visualtype_iterator_t visualIter = xcb_depth_visuals_iterator(depthIter.data); @@ -420,8 +417,8 @@ void QXcbWindow::create() xcb_create_colormap(xcb_connection(), XCB_COLORMAP_ALLOC_NONE, colormap, xcb_parent_id, m_visualId); mask |= XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP; - values[0] = m_screen->screen()->white_pixel; - values[1] = m_screen->screen()->black_pixel; + values[0] = platformScreen->screen()->white_pixel; + values[1] = platformScreen->screen()->black_pixel; values[2] = colormap; break; } @@ -430,8 +427,8 @@ void QXcbWindow::create() } } - const xcb_visualtype_t *visual = m_screen->visualForId(m_visualId); - m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask); + const xcb_visualtype_t *visual = platformScreen->visualForId(m_visualId); + m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap); Q_XCB_CALL(xcb_create_window(xcb_connection(), m_depth, @@ -460,12 +457,10 @@ void QXcbWindow::create() properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS); properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING); - m_usingSyncProtocol = m_screen->syncRequestSupported(); -#if !defined(XCB_USE_GLX) - // synced resize only implemented on GLX - if (window()->supportsOpenGL()) + if (platformScreen->syncRequestSupported()) + m_usingSyncProtocol = supportsSyncProtocol(); + else m_usingSyncProtocol = false; -#endif if (m_usingSyncProtocol) properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST); @@ -484,7 +479,7 @@ void QXcbWindow::create() m_syncValue.hi = 0; m_syncValue.lo = 0; - const QByteArray wmClass = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration())->wmClass(); + const QByteArray wmClass = QXcbIntegration::instance()->wmClass(); if (!wmClass.isEmpty()) { Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::WM_CLASS), @@ -519,7 +514,7 @@ void QXcbWindow::create() xcb_set_wm_hints(xcb_connection(), m_window, &hints); - xcb_window_t leader = m_screen->clientLeader(); + xcb_window_t leader = platformScreen->clientLeader(); Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::WM_CLIENT_LEADER), XCB_ATOM_WINDOW, 32, 1, &leader)); @@ -545,7 +540,7 @@ void QXcbWindow::create() #ifdef XCB_USE_XLIB // force sync to read outstanding requests - see QTBUG-29106 - XSync(DISPLAY_FROM_XCB(m_screen), false); + XSync(DISPLAY_FROM_XCB(platformScreen), false); #endif #ifndef QT_NO_DRAGANDDROP @@ -587,24 +582,36 @@ void QXcbWindow::destroy() } m_mapped = false; -#if defined(XCB_USE_EGL) - delete m_eglSurface; - m_eglSurface = 0; -#endif - if (m_pendingSyncRequest) m_pendingSyncRequest->invalidate(); } +void QXcbWindow::maybeSetScreen(QXcbScreen *screen) +{ + if (!window()->screen() && screen->geometry().contains(geometry().topLeft() * int(devicePixelRatio()))) { + QWindowSystemInterface::handleWindowScreenChanged(window(), static_cast<QPlatformScreen *>(screen)->screen()); + QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(0, 0), window()->size()))); + } +} + void QXcbWindow::setGeometry(const QRect &rect) { QPlatformWindow::setGeometry(rect); propagateSizeHints(); - const QRect xRect = mapToNative(rect, int(devicePixelRatio())); + QXcbScreen *currentScreen = xcbScreen(); + QPlatformScreen *newScreen = screenForGeometry(rect); + if (!newScreen) + newScreen = currentScreen; + + const QRect xRect = mapToNative(rect, int(newScreen->devicePixelRatio())); const QRect wmGeometry = windowToWmGeometry(xRect); + + if (newScreen != currentScreen) + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); + if (qt_window_private(window())->positionAutomatic) { const quint32 mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; const qint32 values[] = { @@ -742,7 +749,7 @@ void QXcbWindow::show() // Default to client leader if there is no transient parent, else modal dialogs can // be hidden by their parents. if (!transientXcbParent) - transientXcbParent = static_cast<QXcbScreen *>(screen())->clientLeader(); + transientXcbParent = xcbScreen()->clientLeader(); if (transientXcbParent) { // ICCCM 4.1.2.6 Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, @@ -773,7 +780,7 @@ void QXcbWindow::show() if (QGuiApplication::modalWindow() == window()) requestActivateWindow(); - m_screen->windowShown(this); + xcbScreen()->windowShown(this); connection()->sync(); } @@ -783,13 +790,15 @@ void QXcbWindow::hide() Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window)); // send synthetic UnmapNotify event according to icccm 4.1.4 - xcb_unmap_notify_event_t event; - event.response_type = XCB_UNMAP_NOTIFY; - event.event = m_screen->root(); - event.window = m_window; - event.from_configure = false; - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, m_screen->root(), - XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); + if (xcbScreen()) { + xcb_unmap_notify_event_t event; + event.response_type = XCB_UNMAP_NOTIFY; + event.event = xcbScreen()->root(); + event.window = m_window; + event.from_configure = false; + Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbScreen()->root(), + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); + } xcb_flush(xcb_connection()); @@ -1108,7 +1117,7 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two) event.data.data32[3] = 0; event.data.data32[4] = 0; - Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->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)); } void QXcbWindow::setWindowState(Qt::WindowState state) @@ -1149,7 +1158,7 @@ void QXcbWindow::setWindowState(Qt::WindowState state) event.data.data32[3] = 0; event.data.data32[4] = 0; - Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->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)); } break; case Qt::WindowMaximized: @@ -1392,7 +1401,9 @@ void QXcbWindow::setParent(const QPlatformWindow *parent) xcb_parent_id = qXcbParent->xcb_window(); m_embedded = qXcbParent->window()->type() == Qt::ForeignWindow; } else { - xcb_parent_id = m_screen->root(); + if (!xcbScreen()) + return; + xcb_parent_id = xcbScreen()->root(); m_embedded = false; } Q_XCB_CALL(xcb_reparent_window(xcb_connection(), xcb_window(), xcb_parent_id, topLeft.x(), topLeft.y())); @@ -1560,7 +1571,7 @@ void QXcbWindow::requestActivateWindow() event.data.data32[3] = 0; event.data.data32[4] = 0; - Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->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)); } else { Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, connection()->time())); } @@ -1570,25 +1581,9 @@ void QXcbWindow::requestActivateWindow() QSurfaceFormat QXcbWindow::format() const { - // ### return actual format return m_format; } -#if defined(XCB_USE_EGL) -QXcbEGLSurface *QXcbWindow::eglSurface() const -{ - if (!m_eglSurface) { - EGLDisplay display = connection()->egl_display(); - EGLConfig config = q_configFromGLFormat(display, window()->requestedFormat(), true); - EGLSurface surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)m_window, 0); - - m_eglSurface = new QXcbEGLSurface(display, surface); - } - - return m_eglSurface; -} -#endif - void QXcbWindow::setWmWindowTypeStatic(QWindow *window, QXcbWindowFunctions::WmWindowTypes windowTypes) { if (window->handle()) @@ -1797,15 +1792,15 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even relayFocusToModalWindow(); return; } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_PING)) { - if (event->window == m_screen->root()) + if (event->window == xcbScreen()->root()) return; xcb_client_message_event_t reply = *event; reply.response_type = XCB_CLIENT_MESSAGE; - reply.window = m_screen->root(); + reply.window = xcbScreen()->root(); - xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&reply); + xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&reply); xcb_flush(xcb_connection()); } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_SYNC_REQUEST)) { connection()->setTime(event->data.data32[1]); @@ -1856,7 +1851,9 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even QPlatformScreen *QXcbWindow::screenForNativeGeometry(const QRect &newGeometry) const { QXcbScreen *currentScreen = static_cast<QXcbScreen*>(screen()); - if (!parent() && !currentScreen->nativeGeometry().intersects(newGeometry)) { + if (!currentScreen && QGuiApplication::primaryScreen()) + currentScreen = static_cast<QXcbScreen*>(QGuiApplication::primaryScreen()->handle()); + if (currentScreen && !parent() && !currentScreen->nativeGeometry().intersects(newGeometry)) { Q_FOREACH (QPlatformScreen* screen, currentScreen->virtualSiblings()) { if (static_cast<QXcbScreen*>(screen)->nativeGeometry().intersects(newGeometry)) return screen; @@ -1869,10 +1866,10 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * { bool fromSendEvent = (event->response_type & 0x80); QPoint pos(event->x, event->y); - if (!parent() && !fromSendEvent) { + if (!parent() && !fromSendEvent && xcbScreen()) { // Do not trust the position, query it instead. xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(), - m_screen->root(), 0, 0); + xcbScreen()->root(), 0, 0); xcb_translate_coordinates_reply_t *reply = xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); if (reply) { pos.setX(reply->dst_x); @@ -1887,12 +1884,11 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * QPlatformWindow::setGeometry(rect); QWindowSystemInterface::handleGeometryChange(window(), rect); - QPlatformScreen *newScreen = screenForNativeGeometry(nativeRect); - if (newScreen != m_screen) { - m_screen = static_cast<QXcbScreen*>(newScreen); - QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); - int newDpr = devicePixelRatio(); + if (newScreen != screen()) { + if (newScreen) + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); + int newDpr = newScreen->devicePixelRatio(); if (newDpr != dpr) { QRect newRect = mapGeometryFromNative(nativeRect, newDpr); QPlatformWindow::setGeometry(newRect); @@ -1934,7 +1930,7 @@ QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const const int dpr = int(devicePixelRatio()); QPoint ret; xcb_translate_coordinates_cookie_t cookie = - xcb_translate_coordinates(xcb_connection(), xcb_window(), m_screen->root(), + xcb_translate_coordinates(xcb_connection(), xcb_window(), xcbScreen()->root(), pos.x() * dpr, pos.y() * dpr); xcb_translate_coordinates_reply_t *reply = xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); @@ -1955,7 +1951,7 @@ QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const const int dpr = int(devicePixelRatio()); QPoint ret; xcb_translate_coordinates_cookie_t cookie = - xcb_translate_coordinates(xcb_connection(), m_screen->root(), xcb_window(), + xcb_translate_coordinates(xcb_connection(), xcbScreen()->root(), xcb_window(), pos.x() *dpr, pos.y() * dpr); xcb_translate_coordinates_reply_t *reply = xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); @@ -2179,8 +2175,8 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev m_windowState = newState; } return; - } else if (event->atom == atom(QXcbAtom::_NET_WORKAREA) && event->window == m_screen->root()) { - m_screen->updateGeometry(event->time); + } else if (event->atom == atom(QXcbAtom::_NET_WORKAREA) && xcbScreen() && event->window == xcbScreen()->root()) { + xcbScreen()->updateGeometry(event->time); } } @@ -2309,7 +2305,7 @@ bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) xev.data.data32[3] = XCB_BUTTON_INDEX_1; xev.data.data32[4] = 0; xcb_ungrab_pointer(connection()->xcb_connection(), XCB_CURRENT_TIME); - xcb_send_event(connection()->xcb_connection(), false, m_screen->root(), + xcb_send_event(connection()->xcb_connection(), false, xcbScreen()->root(), XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, (const char *)&xev); return true; @@ -2354,7 +2350,12 @@ void QXcbWindow::handleXEmbedMessage(const xcb_client_message_event_t *event) break; case XEMBED_EMBEDDED_NOTIFY: Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); - m_screen->windowShown(this); + xcbScreen()->windowShown(this); + // Without Qt::WA_TranslucentBackground, we use a ParentRelative BackPixmap. + // Clear the whole tray icon window to its background color as early as possible + // so that we can get a clean result from grabWindow() later. + Q_XCB_CALL(xcb_clear_area(xcb_connection(), false, m_window, 0, 0, geometry().width(), geometry().height())); + xcb_flush(xcb_connection()); break; case XEMBED_FOCUS_IN: Qt::FocusReason reason; @@ -2448,13 +2449,18 @@ void QXcbWindow::postSyncWindowRequest() if (!m_pendingSyncRequest) { QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this); m_pendingSyncRequest = e; - QCoreApplication::postEvent(m_screen->connection(), e); + QCoreApplication::postEvent(xcbScreen()->connection(), e); } } qreal QXcbWindow::devicePixelRatio() const { - return m_screen ? m_screen->devicePixelRatio() : 1.0; + return xcbScreen() ? xcbScreen()->devicePixelRatio() : 1.0; +} + +QXcbScreen *QXcbWindow::xcbScreen() const +{ + return static_cast<QXcbScreen *>(screen()); } QT_END_NAMESPACE |