Fix hang when reparenting a frozen window in wxOSX
The wrong order of changing parent and freezing/thawing could result in hanging the application when reparenting frozen windows, e.g. when switching order of pages in a notebook. Closes #16722.
This commit is contained in:
@@ -769,6 +769,30 @@ void wxWidgetCocoaImpl::SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEve
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SetDrawingEnabledIfFrozenRecursive(wxWidgetCocoaImpl *impl, bool enable)
|
||||||
|
{
|
||||||
|
if (!impl->GetWXPeer())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (impl->GetWXPeer()->IsFrozen())
|
||||||
|
impl->SetDrawingEnabled(enable);
|
||||||
|
|
||||||
|
for ( wxWindowList::iterator i = impl->GetWXPeer()->GetChildren().begin();
|
||||||
|
i != impl->GetWXPeer()->GetChildren().end();
|
||||||
|
++i )
|
||||||
|
{
|
||||||
|
wxWindow *child = *i;
|
||||||
|
if ( child->IsTopLevel() || !child->IsFrozen() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Skip any user panes as they'll handle this themselves
|
||||||
|
if ( !child->GetPeer() || child->GetPeer()->IsUserPane() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SetDrawingEnabledIfFrozenRecursive((wxWidgetCocoaImpl *)child->GetPeer(), enable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@implementation wxNSView
|
@implementation wxNSView
|
||||||
|
|
||||||
+ (void)initialize
|
+ (void)initialize
|
||||||
@@ -887,6 +911,24 @@ void wxWidgetCocoaImpl::SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEve
|
|||||||
return [super hitTest:aPoint];
|
return [super hitTest:aPoint];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) viewWillMoveToWindow:(NSWindow *)newWindow
|
||||||
|
{
|
||||||
|
wxWidgetCocoaImpl* viewimpl = (wxWidgetCocoaImpl*) wxWidgetImpl::FindFromWXWidget( self );
|
||||||
|
if (viewimpl)
|
||||||
|
SetDrawingEnabledIfFrozenRecursive(viewimpl, true);
|
||||||
|
|
||||||
|
[super viewWillMoveToWindow:newWindow];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) viewDidMoveToWindow
|
||||||
|
{
|
||||||
|
wxWidgetCocoaImpl* viewimpl = (wxWidgetCocoaImpl*) wxWidgetImpl::FindFromWXWidget( self );
|
||||||
|
if (viewimpl)
|
||||||
|
SetDrawingEnabledIfFrozenRecursive(viewimpl, false);
|
||||||
|
|
||||||
|
[super viewDidMoveToWindow];
|
||||||
|
}
|
||||||
|
|
||||||
@end // wxNSView
|
@end // wxNSView
|
||||||
|
|
||||||
// We need to adopt NSTextInputClient protocol in order to interpretKeyEvents: to work.
|
// We need to adopt NSTextInputClient protocol in order to interpretKeyEvents: to work.
|
||||||
@@ -2486,7 +2528,7 @@ void wxWidgetCocoaImpl::Init()
|
|||||||
wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
|
wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
|
||||||
{
|
{
|
||||||
if ( GetWXPeer() && GetWXPeer()->IsFrozen() )
|
if ( GetWXPeer() && GetWXPeer()->IsFrozen() )
|
||||||
[[m_osxView window] enableFlushWindow];
|
SetDrawingEnabled(true);
|
||||||
|
|
||||||
RemoveAssociations( this );
|
RemoveAssociations( this );
|
||||||
|
|
||||||
@@ -3034,6 +3076,10 @@ void wxWidgetCocoaImpl::SetDropTarget(wxDropTarget* target)
|
|||||||
|
|
||||||
void wxWidgetCocoaImpl::RemoveFromParent()
|
void wxWidgetCocoaImpl::RemoveFromParent()
|
||||||
{
|
{
|
||||||
|
// User panes will be thawed in the removeFromSuperview call below
|
||||||
|
if (!IsUserPane() && m_wxPeer->IsFrozen())
|
||||||
|
SetDrawingEnabled(true);
|
||||||
|
|
||||||
[m_osxView removeFromSuperview];
|
[m_osxView removeFromSuperview];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3043,8 +3089,9 @@ void wxWidgetCocoaImpl::Embed( wxWidgetImpl *parent )
|
|||||||
wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
|
wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
|
||||||
[container addSubview:m_osxView];
|
[container addSubview:m_osxView];
|
||||||
|
|
||||||
if( m_wxPeer->IsFrozen() )
|
// User panes will be frozen elsewhere
|
||||||
[[m_osxView window] disableFlushWindow];
|
if( m_wxPeer->IsFrozen() && !IsUserPane() )
|
||||||
|
SetDrawingEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxWidgetCocoaImpl::SetBackgroundColour( const wxColour &col )
|
void wxWidgetCocoaImpl::SetBackgroundColour( const wxColour &col )
|
||||||
@@ -3693,6 +3740,9 @@ void wxWidgetCocoaImpl::SetFlipped(bool flipped)
|
|||||||
|
|
||||||
void wxWidgetCocoaImpl::SetDrawingEnabled(bool enabled)
|
void wxWidgetCocoaImpl::SetDrawingEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
|
if ( [m_osxView window] == nil )
|
||||||
|
return;
|
||||||
|
|
||||||
if ( enabled )
|
if ( enabled )
|
||||||
{
|
{
|
||||||
[[m_osxView window] enableFlushWindow];
|
[[m_osxView window] enableFlushWindow];
|
||||||
|
@@ -1638,6 +1638,15 @@ void wxWindowMac::RemoveChild( wxWindowBase *child )
|
|||||||
if ( child == m_growBox )
|
if ( child == m_growBox )
|
||||||
m_growBox = NULL ;
|
m_growBox = NULL ;
|
||||||
#endif
|
#endif
|
||||||
|
if (!child->IsBeingDeleted() && !child->IsTopLevel())
|
||||||
|
{
|
||||||
|
// Must be removed prior to RemoveChild and next AddChild call
|
||||||
|
// Otherwise the next AddChild may freeze the wrong window
|
||||||
|
wxWindowMac *mac = (wxWindowMac *)child;
|
||||||
|
if (mac->GetPeer() && mac->GetPeer()->IsOk())
|
||||||
|
mac->GetPeer()->RemoveFromParent();
|
||||||
|
}
|
||||||
|
|
||||||
wxWindowBase::RemoveChild( child ) ;
|
wxWindowBase::RemoveChild( child ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2458,10 +2467,9 @@ bool wxWindowMac::Reparent(wxWindowBase *newParentBase)
|
|||||||
if ( !wxWindowBase::Reparent(newParent) )
|
if ( !wxWindowBase::Reparent(newParent) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
GetPeer()->RemoveFromParent();
|
|
||||||
GetPeer()->Embed( GetParent()->GetPeer() );
|
GetPeer()->Embed( GetParent()->GetPeer() );
|
||||||
|
|
||||||
MacChildAdded();
|
GetParent()->MacChildAdded();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user