From c890996a333c2cf3f961c0f8b2f0a522f8a6015f Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Wed, 10 Jun 2020 09:28:48 +0300 Subject: [PATCH] [scene] Setup scene window connections with correct receiver object We need a couple of connections to ensure that the window pixmap, the window quad cache, and the window shape get discarded when the geometry of the toplevel has been changed. Currently, those connections are created with the receiver object being the scene. The problem is that the associated wayland surface may outlive the toplevel and we don't cleanup the connections after the scene window has been destroyed. The fact that the connections don't get destroyed can lead to accessing dangling pointers, which may result in a crash. In order to ensure that the connections are broken automatically when the scene window is destroyed, we need to ensure that the received object is the scene window. That way, the connections will be destroyed automatically. --- scene.cpp | 43 ++++++++++++++++--------------------------- scene.h | 2 -- 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/scene.cpp b/scene.cpp index a094508557..93e5c1db2d 100644 --- a/scene.cpp +++ b/scene.cpp @@ -397,10 +397,6 @@ void Scene::addToplevel(Toplevel *c) Scene::Window *w = createWindow(c); m_windows[ c ] = w; - auto discardPixmap = [w]() { w->discardPixmap(); }; - auto discardQuads = [w]() { w->discardQuads(); }; - - connect(c, SIGNAL(geometryShapeChanged(KWin::Toplevel*,QRect)), SLOT(windowGeometryShapeChanged(KWin::Toplevel*))); connect(c, SIGNAL(windowClosed(KWin::Toplevel*,KWin::Deleted*)), SLOT(windowClosed(KWin::Toplevel*,KWin::Deleted*))); if (c->surface()) { // We generate window quads for sub-surfaces so it's quite important to discard @@ -408,25 +404,26 @@ void Scene::addToplevel(Toplevel *c) SubSurfaceMonitor *monitor = new SubSurfaceMonitor(c->surface(), this); // TODO(vlad): Is there a more efficient way to manage window pixmap trees? - connect(monitor, &SubSurfaceMonitor::subSurfaceAdded, this, discardPixmap); - connect(monitor, &SubSurfaceMonitor::subSurfaceRemoved, this, discardPixmap); - connect(monitor, &SubSurfaceMonitor::subSurfaceResized, this, discardPixmap); - connect(monitor, &SubSurfaceMonitor::subSurfaceMapped, this, discardPixmap); - connect(monitor, &SubSurfaceMonitor::subSurfaceUnmapped, this, discardPixmap); + connect(monitor, &SubSurfaceMonitor::subSurfaceAdded, w, &Window::discardPixmap); + connect(monitor, &SubSurfaceMonitor::subSurfaceRemoved, w, &Window::discardPixmap); + connect(monitor, &SubSurfaceMonitor::subSurfaceResized, w, &Window::discardPixmap); + connect(monitor, &SubSurfaceMonitor::subSurfaceMapped, w, &Window::discardPixmap); + connect(monitor, &SubSurfaceMonitor::subSurfaceUnmapped, w, &Window::discardPixmap); - connect(monitor, &SubSurfaceMonitor::subSurfaceAdded, this, discardQuads); - connect(monitor, &SubSurfaceMonitor::subSurfaceRemoved, this, discardQuads); - connect(monitor, &SubSurfaceMonitor::subSurfaceMoved, this, discardQuads); - connect(monitor, &SubSurfaceMonitor::subSurfaceResized, this, discardQuads); - connect(monitor, &SubSurfaceMonitor::subSurfaceMapped, this, discardQuads); - connect(monitor, &SubSurfaceMonitor::subSurfaceUnmapped, this, discardQuads); + connect(monitor, &SubSurfaceMonitor::subSurfaceAdded, w, &Window::discardQuads); + connect(monitor, &SubSurfaceMonitor::subSurfaceRemoved, w, &Window::discardQuads); + connect(monitor, &SubSurfaceMonitor::subSurfaceMoved, w, &Window::discardQuads); + connect(monitor, &SubSurfaceMonitor::subSurfaceResized, w, &Window::discardQuads); + connect(monitor, &SubSurfaceMonitor::subSurfaceMapped, w, &Window::discardQuads); + connect(monitor, &SubSurfaceMonitor::subSurfaceUnmapped, w, &Window::discardQuads); - connect(c->surface(), &KWaylandServer::SurfaceInterface::scaleChanged, this, discardQuads); - connect(c->surface(), &KWaylandServer::SurfaceInterface::viewportChanged, this, discardQuads); + connect(c->surface(), &KWaylandServer::SurfaceInterface::scaleChanged, w, &Window::discardQuads); + connect(c->surface(), &KWaylandServer::SurfaceInterface::viewportChanged, w, &Window::discardQuads); } - connect(c, &Toplevel::screenScaleChanged, this, discardQuads); - connect(c, &Toplevel::shadowChanged, this, discardQuads); + connect(c, &Toplevel::screenScaleChanged, w, &Window::discardQuads); + connect(c, &Toplevel::shadowChanged, w, &Window::discardQuads); + connect(c, &Toplevel::geometryShapeChanged, w, &Window::discardShape); c->effectWindow()->setSceneWindow(w); c->updateShadow(); @@ -456,14 +453,6 @@ void Scene::windowClosed(Toplevel *toplevel, Deleted *deleted) m_windows[deleted] = window; } -void Scene::windowGeometryShapeChanged(Toplevel *c) -{ - if (!m_windows.contains(c)) // this is ok, shape is not valid by default - return; - Window *w = m_windows[ c ]; - w->discardShape(); -} - void Scene::createStackingOrder(const QList &toplevels) { // TODO: cache the stacking_order in case it has not changed diff --git a/scene.h b/scene.h index bb4d26425a..dda98097af 100644 --- a/scene.h +++ b/scene.h @@ -200,8 +200,6 @@ Q_SIGNALS: void resetCompositing(); public Q_SLOTS: - // shape/size of a window changed - void windowGeometryShapeChanged(KWin::Toplevel* c); // a window has been closed void windowClosed(KWin::Toplevel* c, KWin::Deleted* deleted); protected: