Commit e4fa083c authored by Vlad Zahorodnii's avatar Vlad Zahorodnii
Browse files

[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.


(cherry picked from commit 5f62d1c7)
parent 29e27620
......@@ -119,7 +119,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;
......@@ -265,12 +265,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 );
}
//_______________________________________________________
......@@ -368,11 +373,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(); }
......@@ -386,7 +400,7 @@ namespace Breeze
shadow->setLeftTile( tiles[ 6 ] );
shadow->setTopLeftTile( tiles[ 7 ] );
shadow->setPadding( shadowMargins( widget ) );
shadow->setWindow( widget->windowHandle() );
shadow->setWindow( window );
shadow->create();
}
......@@ -440,7 +454,7 @@ namespace Breeze
//_______________________________________________________
void ShadowHelper::uninstallShadows( QWidget* widget )
{
delete _shadows.take( widget );
delete _shadows.take( widget->windowHandle() );
}
}
......@@ -98,7 +98,10 @@ namespace Breeze
protected Q_SLOTS:
//* unregister widget
void objectDeleted( QObject* );
void widgetDeleted( QObject* );
//* unregister window
void windowDeleted( QObject* );
protected:
......@@ -141,7 +144,7 @@ namespace Breeze
QSet<QWidget*> _widgets;
//* managed shadows
QMap<QWidget*, KWindowShadow*> _shadows;
QMap<QWindow*, KWindowShadow*> _shadows;
//* tileset
TileSet _shadowTiles;
......
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