[scene] Rebuild window quads when sub-surface tree changes

Sub-surface contribute to the window quads cache. So, we must re-build
it, if any sub-surface has been changed.

Differential Revision: https://phabricator.kde.org/D29131
This commit is contained in:
Vlad Zahorodnii 2020-04-22 14:59:42 +03:00
parent f2c8981f7e
commit 9bfcfb7f74
4 changed files with 203 additions and 12 deletions

View file

@ -491,6 +491,7 @@ set(kwin_SRCS
scripting/workspace_wrapper.cpp
shadow.cpp
sm.cpp
subsurfacemonitor.cpp
syncalarmx11filter.cpp
thumbnailitem.cpp
toplevel.cpp

View file

@ -77,6 +77,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "overlaywindow.h"
#include "screens.h"
#include "shadow.h"
#include "subsurfacemonitor.h"
#include "wayland_server.h"
#include "thumbnailitem.h"
@ -395,25 +396,38 @@ void Scene::addToplevel(Toplevel *c)
Q_ASSERT(!m_windows.contains(c));
Scene::Window *w = createWindow(c);
m_windows[ c ] = w;
auto discardPixmap = [w]() { w->discardPixmap(); };
auto discardQuads = [w]() { w->invalidateQuadsCache(); };
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*)));
//A change of scale won't affect the geometry in compositor co-ordinates, but will affect the window quads.
if (c->surface()) {
connect(c->surface(), &KWaylandServer::SurfaceInterface::scaleChanged, this, std::bind(&Scene::windowGeometryShapeChanged, this, c));
// We generate window quads for sub-surfaces so it's quite important to discard
// the pixmap tree and cached window quads when the sub-surface tree is changed.
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, 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(c->surface(), &KWaylandServer::SurfaceInterface::scaleChanged, this, discardQuads);
}
connect(c, &Toplevel::screenScaleChanged, this,
[this, c] {
windowGeometryShapeChanged(c);
}
);
connect(c, &Toplevel::screenScaleChanged, this, discardQuads);
c->effectWindow()->setSceneWindow(w);
c->updateShadow();
w->updateShadow(c->shadow());
connect(c, &Toplevel::shadowChanged, this,
[w] {
w->invalidateQuadsCache();
}
);
connect(c, &Toplevel::shadowChanged, this, discardQuads);
}
void Scene::removeToplevel(Toplevel *toplevel)

95
subsurfacemonitor.cpp Normal file
View file

@ -0,0 +1,95 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "subsurfacemonitor.h"
#include <KWaylandServer/subcompositor_interface.h>
#include <KWaylandServer/surface_interface.h>
using namespace KWaylandServer;
namespace KWin
{
SubSurfaceMonitor::SubSurfaceMonitor(SurfaceInterface *surface, QObject *parent)
: QObject(parent)
{
registerSurface(surface);
}
void SubSurfaceMonitor::registerSubSurface(SubSurfaceInterface *subSurface)
{
SurfaceInterface *surface = subSurface->surface();
connect(subSurface, &SubSurfaceInterface::positionChanged,
this, &SubSurfaceMonitor::subSurfaceMoved);
connect(surface, &SurfaceInterface::sizeChanged,
this, &SubSurfaceMonitor::subSurfaceResized);
connect(surface, &SurfaceInterface::mapped,
this, &SubSurfaceMonitor::subSurfaceMapped);
connect(surface, &SurfaceInterface::unmapped,
this, &SubSurfaceMonitor::subSurfaceUnmapped);
registerSurface(surface);
}
void SubSurfaceMonitor::unregisterSubSurface(SubSurfaceInterface *subSurface)
{
SurfaceInterface *surface = subSurface->surface();
if (!surface)
return;
disconnect(subSurface, &SubSurfaceInterface::positionChanged,
this, &SubSurfaceMonitor::subSurfaceMoved);
disconnect(surface, &SurfaceInterface::sizeChanged,
this, &SubSurfaceMonitor::subSurfaceResized);
disconnect(surface, &SurfaceInterface::mapped,
this, &SubSurfaceMonitor::subSurfaceMapped);
disconnect(surface, &SurfaceInterface::unmapped,
this, &SubSurfaceMonitor::subSurfaceUnmapped);
unregisterSurface(surface);
}
void SubSurfaceMonitor::registerSurface(SurfaceInterface *surface)
{
connect(surface, &SurfaceInterface::childSubSurfaceAdded,
this, &SubSurfaceMonitor::subSurfaceAdded);
connect(surface, &SurfaceInterface::childSubSurfaceRemoved,
this, &SubSurfaceMonitor::subSurfaceRemoved);
connect(surface, &SurfaceInterface::childSubSurfaceAdded,
this, &SubSurfaceMonitor::registerSubSurface);
connect(surface, &SurfaceInterface::childSubSurfaceRemoved,
this, &SubSurfaceMonitor::unregisterSubSurface);
}
void SubSurfaceMonitor::unregisterSurface(SurfaceInterface *surface)
{
disconnect(surface, &SurfaceInterface::childSubSurfaceAdded,
this, &SubSurfaceMonitor::subSurfaceAdded);
disconnect(surface, &SurfaceInterface::childSubSurfaceRemoved,
this, &SubSurfaceMonitor::subSurfaceRemoved);
disconnect(surface, &SurfaceInterface::childSubSurfaceAdded,
this, &SubSurfaceMonitor::registerSubSurface);
disconnect(surface, &SurfaceInterface::childSubSurfaceRemoved,
this, &SubSurfaceMonitor::unregisterSubSurface);
}
} // namespace KWin

81
subsurfacemonitor.h Normal file
View file

@ -0,0 +1,81 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#pragma once
#include <QObject>
namespace KWaylandServer
{
class SurfaceInterface;
class SubSurfaceInterface;
}
namespace KWin
{
/**
* The SubSurfaceMonitor class provides a convenient way for monitoring changes in
* sub-surface trees, e.g. addition or removal of sub-surfaces, etc.
*/
class SubSurfaceMonitor : public QObject
{
Q_OBJECT
public:
/**
* Constructs a SubSurfaceTreeMonitor with the given @a surface and @a parent.
*/
SubSurfaceMonitor(KWaylandServer::SurfaceInterface *surface, QObject *parent);
Q_SIGNALS:
/**
* This signal is emitted when a new sub-surface has been added to the tree.
*/
void subSurfaceAdded();
/**
* This signal is emitted when a sub-surface has been removed from the tree.
*/
void subSurfaceRemoved();
/**
* This signal is emitted when a sub-surface has been moved relative to its parent.
*/
void subSurfaceMoved();
/**
* This signal is emitted when a sub-surface has been resized.
*/
void subSurfaceResized();
/**
* This signal is emitted when a sub-surface is mapped.
*/
void subSurfaceMapped();
/**
* This signal is emitted when a sub-surface is unmapped.
*/
void subSurfaceUnmapped();
private:
void registerSubSurface(KWaylandServer::SubSurfaceInterface *subSurface);
void unregisterSubSurface(KWaylandServer::SubSurfaceInterface *subSurface);
void registerSurface(KWaylandServer::SurfaceInterface *surface);
void unregisterSurface(KWaylandServer::SurfaceInterface *surface);
};
} // namespace KWin