From cf1c4d810a043ca5fe60623569c131a2a7a417df Mon Sep 17 00:00:00 2001 From: Sandro Mani Date: Mon, 2 Feb 2015 11:15:13 +0100 Subject: QXcbWindow: use an accessor to get the screen instead of storing it Applications which construct a window with one screen configuration and show the window later on after a screen configuration change crash because the QXcbWindow::m_screen still pointed to the screen present at the time of window construction. In QXcbWindow::handleConfigureNotifyEvent the m_screen should get updated with the new screen, but I didn't see that method called in the scenario outlined. Looking at the other platform backends, I however see that they take the screen directly from the QPlatformWindow instead of storing the instance, hence this patch which makes QXcbWindow do the same. Change-Id: I13759a5939315c3aac36ec6e2c25bd0a6d7b1c35 Reviewed-by: Shawn Rutledge Reviewed-by: Laszlo Agocs --- .../xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp | 5 +- src/plugins/platforms/xcb/qxcbwindow.cpp | 84 +++++++++++----------- src/plugins/platforms/xcb/qxcbwindow.h | 4 +- 3 files changed, 50 insertions(+), 43 deletions(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp index 8aabde8129..8d5bfb13d3 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp @@ -62,7 +62,10 @@ void QXcbGlxWindow::resolveFormat() void *QXcbGlxWindow::createVisual() { - return qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), &m_format); + QXcbScreen *scr = xcbScreen(); + if (!scr) + return Q_NULLPTR; + return qglx_findVisualInfo(DISPLAY_FROM_XCB(scr), scr->screenNumber(), &m_format); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 4676133777..8dd6b6c1a6 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -233,9 +233,7 @@ QXcbWindow::QXcbWindow(QWindow *window) , m_syncState(NoSyncNeeded) , m_pendingSyncRequest(0) { - m_screen = static_cast(window->screen()->handle()); - - setConnection(m_screen->connection()); + setConnection(xcbScreen()->connection()); } #ifdef Q_COMPILER_CLASS_ENUM @@ -274,11 +272,13 @@ 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_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); connection()->addWindowEventListener(m_window, this); return; @@ -319,7 +319,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(parent())->xcb_window(); m_embedded = parent()->window()->type() == Qt::ForeignWindow; @@ -349,8 +349,8 @@ void QXcbWindow::create() 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; @@ -369,14 +369,14 @@ void QXcbWindow::create() if (!m_window) { 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); @@ -387,8 +387,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; } @@ -397,7 +397,7 @@ void QXcbWindow::create() } } - const xcb_visualtype_t *visual = m_screen->visualForId(m_visualId); + const xcb_visualtype_t *visual = platformScreen->visualForId(m_visualId); m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask); Q_XCB_CALL(xcb_create_window(xcb_connection(), @@ -427,7 +427,7 @@ void QXcbWindow::create() properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS); properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING); - if (m_screen->syncRequestSupported()) + if (platformScreen->syncRequestSupported()) m_usingSyncProtocol = supportsSyncProtocol(); else m_usingSyncProtocol = false; @@ -484,7 +484,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)); @@ -510,7 +510,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 @@ -699,7 +699,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(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, @@ -727,7 +727,7 @@ void QXcbWindow::show() if (QGuiApplication::modalWindow() == window()) requestActivateWindow(); - m_screen->windowShown(this); + xcbScreen()->windowShown(this); connection()->sync(); } @@ -739,10 +739,10 @@ void QXcbWindow::hide() // 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.event = xcbScreen()->root(); event.window = m_window; event.from_configure = false; - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, m_screen->root(), + 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()); @@ -1062,7 +1062,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) @@ -1103,7 +1103,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: @@ -1346,7 +1346,7 @@ 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(); + 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())); @@ -1514,7 +1514,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())); } @@ -1736,15 +1736,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]); @@ -1811,7 +1811,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * if (!parent() && !fromSendEvent) { // 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); @@ -1828,8 +1828,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * QWindowSystemInterface::handleGeometryChange(window(), rect); QPlatformScreen *newScreen = screenForNativeGeometry(nativeRect); - if (newScreen != m_screen) { - m_screen = static_cast(newScreen); + if (newScreen != screen()) { QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); int newDpr = devicePixelRatio(); if (newDpr != dpr) { @@ -1873,7 +1872,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); @@ -1894,7 +1893,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); @@ -2118,8 +2117,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) && event->window == xcbScreen()->root()) { + xcbScreen()->updateGeometry(event->time); } } @@ -2248,7 +2247,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; @@ -2384,13 +2383,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(screen()); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index b78bf779d0..63fdb250da 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -149,6 +149,8 @@ public: qreal devicePixelRatio() const Q_DECL_OVERRIDE; + QXcbScreen *xcbScreen() const; + virtual void create(); virtual void destroy(); QPlatformScreen *screenForNativeGeometry(const QRect &newGeometry) const; @@ -186,8 +188,6 @@ protected: void doFocusIn(); void doFocusOut(); - QXcbScreen *m_screen; - xcb_window_t m_window; uint m_depth; -- cgit v1.2.3