[kstyle] Ensure that shadows are destroyed after decorated windows

The order in which the underlying window and the shadow are destroyed is
undefined. In most cases, the shadow is destroyed after the window, but
in rare cases it may be vice versa, for example it's the case with popup
menus in Dolphin. If the shadow is destroyed before the window, then
the window will be shadowless when the compositor animates it.

The only way to guarantee that the shadow is destroyed after the window
is to create a parent-child relationship between two.

Given that the widget and the window have different lifetimes, we have
to be extra careful with keeping dangling pointers out of _shadows.
wilder-5.19
Vlad Zahorodnii 6 years ago
parent ff99df34ee
commit 5f62d1c74e
  1. 28
      kstyle/breezeshadowhelper.cpp
  2. 7
      kstyle/breezeshadowhelper.h

@ -132,7 +132,7 @@ namespace Breeze
widget->installEventFilter( this );
// connect destroy signal
connect( widget, &QObject::destroyed, this, &ShadowHelper::objectDeleted );
connect( widget, &QObject::destroyed, this, &ShadowHelper::widgetDeleted );
return true;
@ -278,12 +278,17 @@ namespace Breeze
//_______________________________________________________
void ShadowHelper::objectDeleted( QObject* object )
void ShadowHelper::widgetDeleted( QObject* object )
{
QWidget* widget( static_cast<QWidget*>( object ) );
_widgets.remove( widget );
_shadows.remove( widget );
}
//_______________________________________________________
void ShadowHelper::windowDeleted( QObject* object )
{
QWindow* window( static_cast<QWindow*>( object ) );
_shadows.remove( window );
}
//_______________________________________________________
@ -381,11 +386,20 @@ namespace Breeze
const QVector<KWindowShadowTile::Ptr>& tiles = createShadowTiles();
if( tiles.count() != numTiles ) return;
// get the underlying window for the widget
QWindow* window = widget->windowHandle();
// find a shadow associated with the widget
KWindowShadow*& shadow = _shadows[ widget ];
KWindowShadow*& shadow = _shadows[ window ];
if( !shadow )
{ shadow = new KWindowShadow( widget ); }
{
// if there is no shadow yet, create one
shadow = new KWindowShadow( window );
// connect destroy signal
connect( window, &QWindow::destroyed, this, &ShadowHelper::windowDeleted );
}
if( shadow->isCreated() )
{ shadow->destroy(); }
@ -399,7 +413,7 @@ namespace Breeze
shadow->setLeftTile( tiles[ 6 ] );
shadow->setTopLeftTile( tiles[ 7 ] );
shadow->setPadding( shadowMargins( widget ) );
shadow->setWindow( widget->windowHandle() );
shadow->setWindow( window );
shadow->create();
}
@ -453,7 +467,7 @@ namespace Breeze
//_______________________________________________________
void ShadowHelper::uninstallShadows( QWidget* widget )
{
delete _shadows.take( widget );
delete _shadows.take( widget->windowHandle() );
}
}

@ -111,7 +111,10 @@ namespace Breeze
protected Q_SLOTS:
//* unregister widget
void objectDeleted( QObject* );
void widgetDeleted( QObject* );
//* unregister window
void windowDeleted( QObject* );
protected:
@ -154,7 +157,7 @@ namespace Breeze
QSet<QWidget*> _widgets;
//* managed shadows
QMap<QWidget*, KWindowShadow*> _shadows;
QMap<QWindow*, KWindowShadow*> _shadows;
//* tileset
TileSet _shadowTiles;

Loading…
Cancel
Save