From 8bd0ab03e5b6b608943cb5af609a3d511da192f6 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 21 Nov 2018 14:58:56 +0100 Subject: [PATCH] don't leak progress dialog UI if PCE happens during its parent window calculation take care to fully initialize ProgressDialog and register it in disposer after PCE do other side-effectful stuff also after possible PCE fixes memory leak after action update being interrupted by timeout: at com.intellij.openapi.util.Disposer.register(Disposer.java:93) at com.intellij.util.Alarm.(Alarm.java:136) at com.intellij.util.Alarm.(Alarm.java:105) at com.intellij.openapi.progress.util.ProgressDialog.(ProgressDialog.java:40) at com.intellij.openapi.progress.util.ProgressWindow.(ProgressWindow.java:102) at com.intellij.openapi.progress.util.ProgressWindow.(ProgressWindow.java:84) at com.intellij.openapi.progress.impl.BackgroundableProcessIndicator.(BackgroundableProcessIndicator.java:57) at com.intellij.openapi.progress.impl.BackgroundableProcessIndicator.(BackgroundableProcessIndicator.java:42) at com.intellij.openapi.progress.impl.ProgressManagerImpl.runProcessWithProgressAsynchronously(ProgressManagerImpl.java:131) at com.intellij.openapi.progress.impl.CoreProgressManager.runAsynchronously(CoreProgressManager.java:328) at com.intellij.openapi.progress.impl.CoreProgressManager.run(CoreProgressManager.java:312) at com.intellij.openapi.progress.Task.queue(Task.java:115) at com.intellij.lang.ant.config.impl.AntConfigurationImpl.queueLater(AntConfigurationImpl.java:736) --- .../openapi/progress/util/ProgressDialog.java | 18 ++--------- .../openapi/progress/util/ProgressWindow.java | 32 +++++++++++-------- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressDialog.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressDialog.java index 1f5337950a82..45ca402362fe 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressDialog.java @@ -13,7 +13,6 @@ import com.intellij.openapi.ui.impl.GlassPaneDialogWrapperPeer; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.wm.WindowManager; -import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.ui.PopupBorder; import com.intellij.ui.TitlePanel; import com.intellij.ui.WindowMoveListener; @@ -85,22 +84,9 @@ class ProgressDialog implements Disposable { private final SingleAlarm myDisableCancelAlarm = new SingleAlarm(this::setCancelButtonDisabledInEDT, 500, ModalityState.any(),this); private final SingleAlarm myEnableCancelAlarm = new SingleAlarm(this::setCancelButtonEnabledInEDT, 500, ModalityState.any(),this); - ProgressDialog(@NotNull ProgressWindow progressWindow, - boolean shouldShowBackground, - @Nullable Component parent, - @Nullable Project project, - String cancelText) { + ProgressDialog(@NotNull ProgressWindow progressWindow, boolean shouldShowBackground, String cancelText, @Nullable Window parentWindow) { myProgressWindow = progressWindow; - if (parent != null) { - myParentWindow = UIUtil.getWindow(parent); - } - else { - Window parentWindow = WindowManager.getInstance().suggestParentWindow(project); - if (parentWindow == null) { - parentWindow = WindowManagerEx.getInstanceEx().getMostRecentFocusedWindow(); - } - myParentWindow = parentWindow; - } + myParentWindow = parentWindow; initDialog(shouldShowBackground, cancelText); } diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java index 76d44e7b8da3..cb309cf45eba 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java @@ -30,7 +30,9 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.ex.ProgressIndicatorEx; +import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.util.IncorrectOperationException; import com.intellij.util.messages.Topic; import com.intellij.util.ui.UIUtil; @@ -92,23 +94,27 @@ public class ProgressWindow extends ProgressIndicatorBase implements BlockingPro myProject = project; myShouldShowCancel = shouldShowCancel; myCancelText = cancelText; - setModalityProgress(shouldShowBackground ? null : this); - - Component parent = parentComponent; - if (parent == null && project == null && !ApplicationManager.getApplication().isHeadlessEnvironment()) { - parent = JOptionPane.getRootFrame(); - } - - myDialog = new ProgressDialog(this, shouldShowBackground, parent, myProject, myCancelText); - - Disposer.register(this, myDialog); - - addStateDelegate(new MyDelegate()); - ApplicationManager.getApplication().getMessageBus().syncPublisher(TOPIC).progressWindowCreated(this); if (myProject != null) { Disposer.register(myProject, this); } + myDialog = new ProgressDialog(this, shouldShowBackground, myCancelText, calcParentWindow(parentComponent)); + Disposer.register(this, myDialog); + + setModalityProgress(shouldShowBackground ? null : this); + addStateDelegate(new MyDelegate()); + ApplicationManager.getApplication().getMessageBus().syncPublisher(TOPIC).progressWindowCreated(this); + } + + private Window calcParentWindow(@Nullable Component parent) { + if (parent == null && myProject == null && !ApplicationManager.getApplication().isHeadlessEnvironment()) { + parent = JOptionPane.getRootFrame(); + } + if (parent != null) { + return UIUtil.getWindow(parent); + } + Window parentWindow = WindowManager.getInstance().suggestParentWindow(myProject); + return parentWindow != null ? parentWindow : WindowManagerEx.getInstanceEx().getMostRecentFocusedWindow(); } @Override