summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/kernel/qguiapplication.cpp4
-rw-r--r--src/gui/kernel/qplatformwindow.cpp5
-rw-r--r--src/gui/kernel/qscreen.cpp2
-rw-r--r--src/gui/kernel/qwindow.cpp14
-rw-r--r--src/gui/kernel/qwindow_p.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp3
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp7
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp7
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp36
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h1
-rw-r--r--src/widgets/kernel/qwidget.cpp2
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp3
12 files changed, 64 insertions, 25 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index d44a79b37e..92be903b41 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -2583,6 +2583,8 @@ void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::E
return;
QWindow *window = e->exposed.data();
+ if (!window)
+ return;
QWindowPrivate *p = qt_window_private(window);
if (!p->receivedExpose) {
@@ -2598,7 +2600,7 @@ void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::E
p->receivedExpose = true;
}
- p->exposed = e->isExposed;
+ p->exposed = e->isExposed && window->screen();
QExposeEvent exposeEvent(e->region);
QCoreApplication::sendSpontaneousEvent(window, &exposeEvent);
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index 167bd44f0e..763ab68868 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -83,7 +83,8 @@ QPlatformWindow *QPlatformWindow::parent() const
*/
QPlatformScreen *QPlatformWindow::screen() const
{
- return window()->screen()->handle();
+ QScreen *scr = window()->screen();
+ return scr ? scr->handle() : Q_NULLPTR;
}
/*!
@@ -479,7 +480,7 @@ QString QPlatformWindow::formatWindowTitle(const QString &title, const QString &
QPlatformScreen *QPlatformWindow::screenForGeometry(const QRect &newGeometry) const
{
QPlatformScreen *currentScreen = screen();
- if (!parent() && !currentScreen->geometry().intersects(newGeometry)) {
+ if (!parent() && currentScreen && !currentScreen->geometry().intersects(newGeometry)) {
Q_FOREACH (QPlatformScreen* screen, currentScreen->virtualSiblings()) {
if (screen->geometry().intersects(newGeometry))
return screen;
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp
index 8357e14354..0cc8f1082a 100644
--- a/src/gui/kernel/qscreen.cpp
+++ b/src/gui/kernel/qscreen.cpp
@@ -86,7 +86,7 @@ QScreen::~QScreen()
if (this == primaryScreen)
return;
- bool movingFromVirtualSibling = primaryScreen->handle()->virtualSiblings().contains(handle());
+ bool movingFromVirtualSibling = primaryScreen && primaryScreen->handle()->virtualSiblings().contains(handle());
// Move any leftover windows to the primary screen
foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index b679dd9bfc..773cce7a7f 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -338,7 +338,7 @@ inline bool QWindowPrivate::windowRecreationRequired(QScreen *newScreen) const
{
Q_Q(const QWindow);
const QScreen *oldScreen = q->screen();
- return oldScreen != newScreen && platformWindow
+ return oldScreen != newScreen && (platformWindow || !oldScreen)
&& !(oldScreen && oldScreen->virtualSiblings().contains(newScreen));
}
@@ -373,10 +373,13 @@ void QWindowPrivate::setTopLevelScreen(QScreen *newScreen, bool recreate)
}
if (newScreen != topLevelScreen) {
const bool shouldRecreate = recreate && windowRecreationRequired(newScreen);
- if (shouldRecreate)
+ const bool shouldShow = visibilityOnDestroy && !topLevelScreen;
+ if (shouldRecreate && platformWindow)
q->destroy();
connectToScreen(newScreen);
- if (newScreen && shouldRecreate)
+ if (shouldShow)
+ q->setVisible(true);
+ else if (newScreen && shouldRecreate)
create(true);
emitScreenChangedRecursion(newScreen);
}
@@ -1600,6 +1603,7 @@ void QWindow::destroy()
QGuiApplicationPrivate::tabletPressTarget = parent();
bool wasVisible = isVisible();
+ d->visibilityOnDestroy = wasVisible && d->platformWindow;
setVisible(false);
@@ -1683,7 +1687,7 @@ bool QWindow::setMouseGrabEnabled(bool grab)
QScreen *QWindow::screen() const
{
Q_D(const QWindow);
- return d->parentWindow ? d->parentWindow->screen() : d->topLevelScreen;
+ return d->parentWindow ? d->parentWindow->screen() : d->topLevelScreen.data();
}
/*!
@@ -1703,7 +1707,7 @@ void QWindow::setScreen(QScreen *newScreen)
Q_D(QWindow);
if (!newScreen)
newScreen = QGuiApplication::primaryScreen();
- d->setTopLevelScreen(newScreen, true /* recreate */);
+ d->setTopLevelScreen(newScreen, newScreen != 0);
}
/*!
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index c496d7716b..9151e76ea4 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -45,6 +45,7 @@
// We mean it.
//
+#include <QtGui/qscreen.h>
#include <QtGui/qwindow.h>
#include <qpa/qplatformwindow.h>
@@ -73,6 +74,7 @@ public:
, parentWindow(0)
, platformWindow(0)
, visible(false)
+ , visibilityOnDestroy(false)
, exposed(false)
, windowState(Qt::WindowNoState)
, visibility(QWindow::Hidden)
@@ -147,6 +149,7 @@ public:
QWindow *parentWindow;
QPlatformWindow *platformWindow;
bool visible;
+ bool visibilityOnDestroy;
bool exposed;
QSurfaceFormat requestedFormat;
QString windowTitle;
@@ -175,7 +178,7 @@ public:
int updateTimer;
QPointer<QWindow> transientParent;
- QScreen *topLevelScreen;
+ QPointer<QScreen> topLevelScreen;
#ifndef QT_NO_CURSOR
QCursor cursor;
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 93914c0cba..48cf366d28 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -332,6 +332,9 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
initializeXRandr();
updateScreens();
+ if (m_screens.isEmpty())
+ qFatal("QXcbConnection: no screens available");
+
initializeXFixes();
initializeXRender();
m_xi2Enabled = false;
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index 8974ab549f..915287d93e 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -249,8 +249,13 @@ void *QXcbNativeInterface::nativeResourceForContext(const QByteArray &resourceSt
void *QXcbNativeInterface::nativeResourceForScreen(const QByteArray &resourceString, QScreen *screen)
{
+ if (!screen) {
+ qWarning() << "nativeResourceForScreen: null screen";
+ return Q_NULLPTR;
+ }
+
QByteArray lowerCaseResource = resourceString.toLower();
- void *result = handlerNativeResourceForScreen(lowerCaseResource ,screen);
+ void *result = handlerNativeResourceForScreen(lowerCaseResource, screen);
if (result)
return result;
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 0f25d10aac..b5eed4f4fe 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -417,6 +417,13 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan
QDpi ldpi = logicalDpi();
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QPlatformScreen::screen(), ldpi.first, ldpi.second);
+
+ // Windows which had null screens have already had expose events by now.
+ // They need to be told the screen is back, it's OK to render.
+ foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
+ QXcbWindow *xcbWin = static_cast<QXcbWindow*>(window->handle());
+ xcbWin->maybeSetScreen(this);
+ }
}
void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index c407caae2f..0e28cf2698 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -556,6 +556,14 @@ void QXcbWindow::destroy()
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);
@@ -737,13 +745,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 = 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));
+ 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());
@@ -1794,7 +1804,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;
@@ -1807,7 +1819,7 @@ 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(),
xcbScreen()->root(), 0, 0);
@@ -1825,10 +1837,10 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
QPlatformWindow::setGeometry(rect);
QWindowSystemInterface::handleGeometryChange(window(), rect);
-
QPlatformScreen *newScreen = screenForNativeGeometry(nativeRect);
if (newScreen != screen()) {
- QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
+ if (newScreen)
+ QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
int newDpr = devicePixelRatio();
if (newDpr != dpr) {
QRect newRect = mapGeometryFromNative(nativeRect, newDpr);
@@ -2116,7 +2128,7 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
m_windowState = newState;
}
return;
- } else if (event->atom == atom(QXcbAtom::_NET_WORKAREA) && event->window == xcbScreen()->root()) {
+ } else if (event->atom == atom(QXcbAtom::_NET_WORKAREA) && xcbScreen() && event->window == xcbScreen()->root()) {
xcbScreen()->updateGeometry(event->time);
}
}
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 63fdb250da..981f4e7496 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -153,6 +153,7 @@ public:
virtual void create();
virtual void destroy();
+ void maybeSetScreen(QXcbScreen *screen);
QPlatformScreen *screenForNativeGeometry(const QRect &newGeometry) const;
public Q_SLOTS:
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index d6a106cef5..ca82dadabb 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -5536,7 +5536,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
}
// Native widgets need to be marked dirty on screen so painting will be done in correct context
- if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow()))
+ if (backingStore && !onScreen && !asRoot && (q->internalWinId() || (q->nativeParentWidget() && !q->nativeParentWidget()->isWindow())))
backingStore->markDirtyOnScreen(toBePainted, q, offset);
//restore
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index ed5d56c689..5724df6c55 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -635,7 +635,8 @@ void QWidgetWindow::handleScreenChange()
sendScreenChangeRecursively(m_widget);
// Invalidate the backing store buffer and repaint immediately.
- repaintWindow();
+ if (screen())
+ repaintWindow();
}
void QWidgetWindow::repaintWindow()