Commit c7c8a213 authored by Vlad Zahorodnii's avatar Vlad Zahorodnii Committed by Vlad Zahorodnii
Browse files

[style] Fix crash during app tear down sequence

We want to destroy a shadow after its decorated window has been destroyed
or unmapped. In order to do that, we install an event filter on the widget
and make the shadow a child of the window.

Unfortunately, the underlying window and the widget have different life
times. To ensure that _shadows has no dangling pointers, we will remove
the shadow when it's destroyed. The problem with doing so is that it will
invalidate iterators when ShadowHelper destroys all shadows during app
tear down, which will eventually result in a crash.

In order to keep iterators valid when ShadowHelper destroys shadows, we
need to clean up _shadows after the decorated window has been destroyed.
parent 25fe85e6
......@@ -94,7 +94,7 @@ namespace Oxygen
widget->installEventFilter( this );
// connect destroy signal
connect( widget, SIGNAL(destroyed(QObject*)), SLOT(objectDeleted(QObject*)) );
connect( widget, SIGNAL(destroyed(QObject*)), SLOT(widgetDeleted(QObject*)) );
return true;
......@@ -183,11 +183,17 @@ namespace Oxygen
}
//_______________________________________________________
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 );
}
//_______________________________________________________
......@@ -301,15 +307,19 @@ namespace Oxygen
const QVector<KWindowShadowTile::Ptr>& tiles = createPlatformTiles( isDockWidget );
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 ];
// we want the shadow to be deleted after the decorated window is destroyed
if( !shadow )
{
shadow = new KWindowShadow( widget->windowHandle() );
// if there is no shadow yet, create one
shadow = new KWindowShadow( window );
connect( shadow, &QObject::destroyed, this, [this, widget] { _shadows.remove( widget ); } );
// connect destroy signal
connect( window, &QWindow::destroyed, this, &ShadowHelper::windowDeleted );
}
if( shadow->isCreated() )
......@@ -323,7 +333,7 @@ namespace Oxygen
shadow->setBottomLeftTile( tiles[5] );
shadow->setLeftTile( tiles[6] );
shadow->setTopLeftTile( tiles[7] );
shadow->setWindow( widget->windowHandle() );
shadow->setWindow( window );
shadow->setPadding( shadowMargins( widget ) );
shadow->create();
}
......@@ -388,7 +398,7 @@ namespace Oxygen
//_______________________________________________________
void ShadowHelper::uninstallShadows( QWidget* widget )
{
delete _shadows.take( widget );
delete _shadows.take( widget->windowHandle() );
}
}
......@@ -80,7 +80,10 @@ namespace Oxygen
private Q_SLOTS:
//* unregister widget
void objectDeleted( QObject* );
void widgetDeleted( QObject* );
//* unregister window
void windowDeleted( QObject* );
private:
......@@ -132,7 +135,7 @@ namespace Oxygen
QSet<QWidget*> _widgets;
//* map of managed shadows
QMap<QWidget*, KWindowShadow*> _shadows;
QMap<QWindow*, KWindowShadow*> _shadows;
//*@name shadow tilesets
//@{
......
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