diff options
author | Michael Hutchinson <mhutch@xamarin.com> | 2012-01-12 02:20:03 +0400 |
---|---|---|
committer | Jeffrey Stedfast <jeff@xamarin.com> | 2012-01-14 01:26:39 +0400 |
commit | 411a2dfb6492138e4a8b624307e52961b038b517 (patch) | |
tree | ae43ee05822f617654d7ee4c902b653b487bcea8 | |
parent | c72deca23c5259a6a37560d1627992eb26aa59b8 (diff) |
[Docking] Fix a case where a widget could be parented twice
The DockItem widgets can be parented into a floating window, the DockFrame's
DockContainer, or an AutoHideDock. In the latter two cases, it's possible
that a race could cause the widget to be added to its new parent before it's
removed from its old parent.
May fix bug 1445 - MD crashes with SIGABRT occasionally when stopping debugging
4 files changed, 37 insertions, 6 deletions
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/AutoHideBox.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/AutoHideBox.cs index 0670fe8f81..78bda70723 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/AutoHideBox.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/AutoHideBox.cs @@ -104,6 +104,10 @@ namespace MonoDevelop.Components.Docking scrollable.ScrollMode = false; scrollable.Show (); + if (item.Widget.Parent != null) { + ((Gtk.Container)item.Widget.Parent).Remove (item.Widget); + } + item.Widget.Show (); scrollable.Add (item.Widget); fr.PackStart (scrollable, true, true, 0); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockContainer.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockContainer.cs index ca750a94fe..3eb050fcb2 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockContainer.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockContainer.cs @@ -173,6 +173,29 @@ namespace MonoDevelop.Components.Docking return res; } + protected override void OnAdded (Widget widget) + { + System.Diagnostics.Debug.Assert ( + widget.Parent == null, + "Widget is already parented on another widget"); + System.Diagnostics.Debug.Assert ( + System.Linq.Enumerable.Any (items, item => item.Widget == widget), + "Can only add widgets to the container that are in the parent DockFrame's DockItem collection"); + + widget.Parent = this; + } + + protected override void OnRemoved (Widget widget) + { + System.Diagnostics.Debug.Assert ( + widget.Parent != this, + "Widget is not parented on this widget"); + System.Diagnostics.Debug.Assert ( + System.Linq.Enumerable.Any (items, item => item.Widget == widget), + "Can only remove widgets from the container that are in the parent DockFrame's DockItem collection"); + + widget.Unparent (); + } public void RelayoutWidgets () { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockGroup.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockGroup.cs index 2dfc4ef7ca..685a6f502b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockGroup.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockGroup.cs @@ -693,8 +693,12 @@ namespace MonoDevelop.Components.Docking foreach (DockObject ob in VisibleObjects) { DockGroupItem it = ob as DockGroupItem; if (it != null) { - if (it.Item.Widget.Parent == null) - it.Item.Widget.Parent = Frame.Container; + if (it.Item.Widget.Parent != Frame.Container) { + if (it.Item.Widget.Parent != null) { + ((Gtk.Container)it.Item.Widget.Parent).Remove (it.Item.Widget); + } + Frame.Container.Add (it.Item.Widget); + } if (!it.Item.Widget.Visible && type != DockGroupType.Tabbed) it.Item.Widget.Show (); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItem.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItem.cs index 7e9f354389..e8a356cd3c 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItem.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItem.cs @@ -365,8 +365,7 @@ namespace MonoDevelop.Components.Docking { ResetBarUndockMode (); if (floatingWindow == null) { - if (Widget.Parent is Gtk.Container) { - MonoDevelop.Core.LoggingService.LogError ("Unparenting {0} from {1} even though it should already be unparented", Widget, widget.Parent); + if (Widget.Parent != null) { ((Gtk.Container) Widget.Parent).Remove (Widget); } floatingWindow = new Window (GetWindowTitle ()); @@ -422,8 +421,9 @@ namespace MonoDevelop.Components.Docking ResetMode (); if (widget != null) { widget.Hide (); // Avoids size allocation warning - if (widget.Parent is Gtk.Container) - widget.Unparent (); + if (widget.Parent != null) { + ((Gtk.Container)widget.Parent).Remove (widget); + } } dockBarItem = frame.BarDock (pos, this, size); if (widget != null) |