Try to invalidate quad cache when shadow is changed
Summary:
213239a0ea
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
This commit is contained in:
parent
6f982e88a0
commit
90a26e2e8d
4 changed files with 34 additions and 19 deletions
12
scene.cpp
12
scene.cpp
|
@ -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;
|
||||
|
|
1
scene.h
1
scene.h
|
@ -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 ®ion, qreal textureScale = 1.0) const;
|
||||
|
|
34
shadow.cpp
34
shadow.cpp
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue