From 7532fb4e61fc4102fd11022f57f7d8195414167b Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Fri, 23 Oct 2015 10:37:49 +0200 Subject: [PATCH] Xcb: fix crash on screen power save Handle various cases where we have null QScreen or QPlatformScreen pointers. With this change, I can run Qt Creator for several days. Before, it would crash multiple times per day with a two-monitor setup. Change-Id: I0923d886ae2a4199ac37edd711ddd4f6f99df93d Reviewed-by: Friedemann Kleint Reviewed-by: Lars Knoll Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 13 +++++++++++-- src/plugins/platforms/xcb/qxcbbackingstore.h | 1 + src/plugins/platforms/xcb/qxcbwindow.cpp | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 25f1ea5236..1825a463d0 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -311,9 +311,12 @@ QPaintDevice *QXcbBackingStore::paintDevice() void QXcbBackingStore::beginPaint(const QRegion ®ion) { + if (!m_image && !m_size.isEmpty()) + resize(m_size, QRegion()); + if (!m_image) return; - + m_size = QSize(); m_paintRegion = region; m_image->preparePaint(m_paintRegion); @@ -420,7 +423,8 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &) return; Q_XCB_NOOP(connection()); - QXcbScreen *screen = static_cast(window()->screen()->handle()); + + QXcbScreen *screen = window()->screen() ? static_cast(window()->screen()->handle()) : 0; QPlatformWindow *pw = window()->handle(); if (!pw) { window()->create(); @@ -429,6 +433,11 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &) QXcbWindow* win = static_cast(pw); delete m_image; + if (!screen) { + m_image = 0; + m_size = size; + return; + } m_image = new QXcbShmImage(screen, size, win->depth(), win->imageFormat()); // Slow path for bgr888 VNC: Create an additional image, paint into that and // swap R and B while copying to m_image after each paint. diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h index b58a32d313..1bea36d423 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.h +++ b/src/plugins/platforms/xcb/qxcbbackingstore.h @@ -71,6 +71,7 @@ private: QXcbShmImage *m_image; QRegion m_paintRegion; QImage m_rgbImage; + QSize m_size; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index bde8826792..b691c7550f 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -652,7 +652,7 @@ void QXcbWindow::setGeometry(const QRect &rect) m_xcbScreen = newScreen; const QRect wmGeometry = windowToWmGeometry(rect); - if (newScreen != currentScreen) + if (newScreen && newScreen != currentScreen) QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen()); if (qt_window_private(window())->positionAutomatic) { @@ -1606,7 +1606,7 @@ void QXcbWindow::requestActivateWindow() return; } - if (!m_mapped) { + if (!m_mapped || !xcbScreen()) { m_deferredActivation = true; return; }