Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit 90a26e2e authored by Vlad Zahorodnii's avatar Vlad Zahorodnii

Try to invalidate quad cache when shadow is changed

Summary:
213239a0 tried to address the case when
a wayland client gets shadow after it was mapped, but because of poor
testing from my side, another bug was introduced. If a decoration tooltip
or the user actions popup is shown, then in some cases it can be blank.

Usually, SurfaceInterface::shadowChanged proceeds SurfaceInterface::sizeChanged,
so when the shadow is installed, window quads cache is rebuilt. But
because shell client already knows the geometry of the internal client,
goemetryShapeChanged is not emitted, thus the cache is not updated.

It would be better just to invalidate the cache when the shadow is
installed, uninstalled, or updated. This reduces the number of
unnecessary invocations of Scene::Window::buildQuads and also moves
handling of the window quads cache away from the Shadow class.

BUG: 399490
FIXED-IN: 5.15.0

Test Plan: Decoration tooltips are no longer blank.

Reviewers: #kwin, davidedmundson

Reviewed By: #kwin, davidedmundson

Subscribers: davidedmundson, graesslin, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D17215
parent 6f982e88
......@@ -405,6 +405,11 @@ void Scene::windowAdded(Toplevel *c)
c->effectWindow()->setSceneWindow(w);
c->getShadow();
w->updateShadow(c->shadow());
connect(c, &Toplevel::shadowChanged, this,
[w] {
w->invalidateQuadsCache();
}
);
}
void Scene::windowClosed(Toplevel *c, Deleted *deleted)
......@@ -732,7 +737,7 @@ void Scene::Window::discardShape()
// it is created on-demand and cached, simply
// reset the flag
shape_valid = false;
cached_quad_list.reset();
invalidateQuadsCache();
}
// Find out the shape of the window using the XShape extension
......@@ -936,6 +941,11 @@ WindowQuadList Scene::Window::makeDecorationQuads(const QRect *rects, const QReg
return list;
}
void Scene::Window::invalidateQuadsCache()
{
cached_quad_list.reset();
}
WindowQuadList Scene::Window::makeQuads(WindowQuadType type, const QRegion& reg, const QPoint &textureOffset, qreal scale) const
{
WindowQuadList ret;
......
......@@ -336,6 +336,7 @@ public:
Shadow* shadow();
void referencePreviousPixmap();
void unreferencePreviousPixmap();
void invalidateQuadsCache();
protected:
WindowQuadList makeQuads(WindowQuadType type, const QRegion& reg, const QPoint &textureOffset = QPoint(0, 0), qreal textureScale = 1.0) const;
WindowQuadList makeDecorationQuads(const QRect *rects, const QRegion &region, qreal textureScale = 1.0) const;
......
......@@ -65,9 +65,7 @@ Shadow *Shadow::createShadow(Toplevel *toplevel)
}
if (toplevel->effectWindow() && toplevel->effectWindow()->sceneWindow()) {
toplevel->effectWindow()->sceneWindow()->updateShadow(shadow);
}
if (toplevel->effectWindow()) {
toplevel->effectWindow()->buildQuads(true);
emit toplevel->shadowChanged();
}
return shadow;
}
......@@ -333,21 +331,24 @@ void Shadow::buildQuads()
bool Shadow::updateShadow()
{
auto clear = [this]() {
if (m_topLevel && m_topLevel->effectWindow() && m_topLevel->effectWindow()->sceneWindow() &&
m_topLevel->effectWindow()->sceneWindow()->shadow()) {
auto clear = [this] {
if (m_topLevel && m_topLevel->shadow()) {
auto w = m_topLevel->effectWindow();
// this also deletes the shadow
w->sceneWindow()->updateShadow(nullptr);
w->buildQuads(true);
emit m_topLevel->shadowChanged();
}
};
if (!m_topLevel) {
return false;
}
if (m_decorationShadow) {
if (AbstractClient *c = qobject_cast<AbstractClient*>(m_topLevel)) {
if (c->decoration()) {
if (init(c->decoration())) {
if (m_topLevel && m_topLevel->effectWindow())
m_topLevel->effectWindow()->buildQuads(true);
emit m_topLevel->shadowChanged();
return true;
}
}
......@@ -355,30 +356,27 @@ bool Shadow::updateShadow()
clear();
return false;
}
if (waylandServer()) {
if (m_topLevel && m_topLevel->surface()) {
if (const auto &s = m_topLevel->surface()->shadow()) {
if (init(s)) {
if (m_topLevel->effectWindow()) {
m_topLevel->effectWindow()->buildQuads(true);
}
emit m_topLevel->shadowChanged();
return true;
}
}
}
}
if (!m_topLevel) {
clear();
return false;
}
auto data = Shadow::readX11ShadowProperty(m_topLevel->window());
if (data.isEmpty()) {
clear();
return false;
}
init(data);
if (m_topLevel && m_topLevel->effectWindow())
m_topLevel->effectWindow()->buildQuads(true);
emit m_topLevel->shadowChanged();
return true;
}
......
......@@ -527,6 +527,12 @@ Q_SIGNALS:
*/
void screenScaleChanged();
/**
* Emitted whenever the client's shadow changes.
* @since 5.15
**/
void shadowChanged();
protected Q_SLOTS:
/**
* Checks whether the screen number for this Toplevel changed and updates if needed.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment