x11: Fix BadDamage warning

The XDamageDestroy has a weird requirement saying that it can be called
as long as the X11 window is still valid. On the other hand, one could
argue that it is more intuitive if the damage handle becomes inert if the
associated window is destroyed. Unfortunately, that's not the case and
as git history shows, it's an easy way to shoot yourself in the foot, we
had the exact warning many years ago.

The problem with the XDamageDestroy API is that it is simply unreliable
given the asynchronous nature of communication between kwin and xorg.

Anyway, with X11 sunsetting, let's destroy the damage handle only when
the X11 window is unmapped and not bother too much about it.
This commit is contained in:
Vlad Zahorodnii 2021-07-05 15:17:29 +03:00
parent 770875a76e
commit 29ff0d30ad
2 changed files with 9 additions and 3 deletions

View file

@ -19,8 +19,6 @@ SurfaceItemX11::SurfaceItemX11(Scene::Window *window, Item *parent)
connect(toplevel, &Toplevel::bufferGeometryChanged,
this, &SurfaceItemX11::handleBufferGeometryChanged);
connect(toplevel, &Toplevel::markedAsZombie,
this, &SurfaceItemX11::destroyDamage);
connect(toplevel, &Toplevel::geometryShapeChanged,
this, &SurfaceItemX11::discardQuads);
@ -33,6 +31,7 @@ SurfaceItemX11::SurfaceItemX11(Scene::Window *window, Item *parent)
SurfaceItemX11::~SurfaceItemX11()
{
// destroyDamage() will be called by the associated Toplevel.
}
void SurfaceItemX11::preprocess()

View file

@ -20,6 +20,7 @@
#include "screens.h"
#include "shadow.h"
#include "shadowitem.h"
#include "surfaceitem_x11.h"
#include "windowitem.h"
#include "workspace.h"
@ -276,8 +277,14 @@ bool Toplevel::setupCompositing()
return true;
}
void Toplevel::finishCompositing(ReleaseReason)
void Toplevel::finishCompositing(ReleaseReason releaseReason)
{
// If the X11 window has been destroyed, avoid calling XDamageDestroy.
if (releaseReason != ReleaseReason::Destroyed) {
if (SurfaceItemX11 *item = qobject_cast<SurfaceItemX11 *>(surfaceItem())) {
item->destroyDamage();
}
}
if (effect_window && effect_window->window() == this) { // otherwise it's already passed to Deleted, don't free data
deleteEffectWindow();
}