diff options
author | Marius Ungureanu <teromario@yahoo.com> | 2017-04-28 13:01:09 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-28 13:01:09 +0300 |
commit | 072d0b47edd511c176e557b267f81f6a031e4637 (patch) | |
tree | 5b76b3526058bc0af8cbe29dccf273777effb6fd /main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper | |
parent | 9f377413161fbd093cd48d6fa2387e8021da07ce (diff) |
[Atk] Fix leak caused by circular referencing in Atk code. (#2293)
The action code was creating a circular ref between the accessible and the object via the signals. Break all the refs.
Diffstat (limited to 'main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper')
-rw-r--r-- | main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelper.cs | 58 |
1 files changed, 33 insertions, 25 deletions
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelper.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelper.cs index 443255181a..cfb35700cc 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelper.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelper.cs @@ -113,34 +113,39 @@ namespace MonoDevelop.Components.AtkCocoaHelper return; } - var signal = GLib.Signal.Lookup (owner, "request-actions", typeof (GLib.SignalArgs)); - signal.AddDelegate (new EventHandler<GLib.SignalArgs> (RequestActionsHandler)); - - signal = GLib.Signal.Lookup (owner, "perform-cancel", typeof (GLib.SignalArgs)); - signal.AddDelegate (new EventHandler<GLib.SignalArgs> (PerformCancelHandler)); - signal = GLib.Signal.Lookup (owner, "perform-confirm", typeof (GLib.SignalArgs)); - signal.AddDelegate (new EventHandler<GLib.SignalArgs> (PerformConfirmHandler)); - signal = GLib.Signal.Lookup (owner, "perform-decrement", typeof (GLib.SignalArgs)); - signal.AddDelegate (new EventHandler<GLib.SignalArgs> (PerformDecrementHandler)); - signal = GLib.Signal.Lookup (owner, "perform-delete", typeof (GLib.SignalArgs)); - signal.AddDelegate (new EventHandler<GLib.SignalArgs> (PerformDeleteHandler)); - signal = GLib.Signal.Lookup (owner, "perform-increment", typeof (GLib.SignalArgs)); - signal.AddDelegate (new EventHandler<GLib.SignalArgs> (PerformIncrementHandler)); - signal = GLib.Signal.Lookup (owner, "perform-pick", typeof (GLib.SignalArgs)); - signal.AddDelegate (new EventHandler<GLib.SignalArgs> (PerformPickHandler)); - signal = GLib.Signal.Lookup (owner, "perform-press", typeof (GLib.SignalArgs)); - signal.AddDelegate (new EventHandler<GLib.SignalArgs> (PerformPressHandler)); - signal = GLib.Signal.Lookup (owner, "perform-raise", typeof (GLib.SignalArgs)); - signal.AddDelegate (new EventHandler<GLib.SignalArgs> (PerformRaiseHandler)); - signal = GLib.Signal.Lookup (owner, "perform-show-alternate-ui", typeof (GLib.SignalArgs)); - signal.AddDelegate (new EventHandler<GLib.SignalArgs> (PerformShowAlternateUIHandler)); - signal = GLib.Signal.Lookup (owner, "perform-show-default-ui", typeof (GLib.SignalArgs)); - signal.AddDelegate (new EventHandler<GLib.SignalArgs> (PerformShowDefaultUIHandler)); - signal = GLib.Signal.Lookup (owner, "perform-show-menu", typeof (GLib.SignalArgs)); - signal.AddDelegate (new EventHandler<GLib.SignalArgs> (PerformShowMenuHandler)); + HandleSignalAttachment (owner, (signal, handler) => signal.AddDelegate (handler)); } } + void HandleSignalAttachment (Atk.Object owner, Action<GLib.Signal, EventHandler<GLib.SignalArgs>> action) + { + var signal = GLib.Signal.Lookup (owner, "request-actions", typeof (GLib.SignalArgs)); + action (signal, new EventHandler<GLib.SignalArgs> (RequestActionsHandler)); + + signal = GLib.Signal.Lookup (owner, "perform-cancel", typeof (GLib.SignalArgs)); + action (signal, new EventHandler<GLib.SignalArgs> (PerformCancelHandler)); + signal = GLib.Signal.Lookup (owner, "perform-confirm", typeof (GLib.SignalArgs)); + action (signal, new EventHandler<GLib.SignalArgs> (PerformConfirmHandler)); + signal = GLib.Signal.Lookup (owner, "perform-decrement", typeof (GLib.SignalArgs)); + action (signal, new EventHandler<GLib.SignalArgs> (PerformDecrementHandler)); + signal = GLib.Signal.Lookup (owner, "perform-delete", typeof (GLib.SignalArgs)); + action (signal, new EventHandler<GLib.SignalArgs> (PerformDeleteHandler)); + signal = GLib.Signal.Lookup (owner, "perform-increment", typeof (GLib.SignalArgs)); + action (signal, new EventHandler<GLib.SignalArgs> (PerformIncrementHandler)); + signal = GLib.Signal.Lookup (owner, "perform-pick", typeof (GLib.SignalArgs)); + action (signal, new EventHandler<GLib.SignalArgs> (PerformPickHandler)); + signal = GLib.Signal.Lookup (owner, "perform-press", typeof (GLib.SignalArgs)); + action (signal, new EventHandler<GLib.SignalArgs> (PerformPressHandler)); + signal = GLib.Signal.Lookup (owner, "perform-raise", typeof (GLib.SignalArgs)); + action (signal, new EventHandler<GLib.SignalArgs> (PerformRaiseHandler)); + signal = GLib.Signal.Lookup (owner, "perform-show-alternate-ui", typeof (GLib.SignalArgs)); + action (signal, new EventHandler<GLib.SignalArgs> (PerformShowAlternateUIHandler)); + signal = GLib.Signal.Lookup (owner, "perform-show-default-ui", typeof (GLib.SignalArgs)); + action (signal, new EventHandler<GLib.SignalArgs> (PerformShowDefaultUIHandler)); + signal = GLib.Signal.Lookup (owner, "perform-show-menu", typeof (GLib.SignalArgs)); + action (signal, new EventHandler<GLib.SignalArgs> (PerformShowMenuHandler)); + } + public ActionDelegate (Gtk.Widget widget) { widget.Destroyed += WidgetDestroyed; @@ -150,6 +155,9 @@ namespace MonoDevelop.Components.AtkCocoaHelper void WidgetDestroyed (object sender, EventArgs e) { FreeActions (); + + HandleSignalAttachment (owner, (signal, handler) => signal.RemoveDelegate (handler)); + owner = null; } // Because the allocated memory is passed to unmanaged code where it cannot be freed |