From 098fdda8efd28d0676f82d9fdb4e2dc4267ada91 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Thu, 1 Dec 2016 21:49:05 +0300 Subject: [PATCH] mem leaks: clear CWindow listeners and rootPane: unify listeners & DRY --- .../intellij/openapi/ui/DialogWrapper.java | 13 +++ .../com/intellij/openapi/ui/FrameWrapper.java | 7 +- .../ui/impl/DialogWrapperPeerImpl.java | 87 +++++++++---------- .../src/com/intellij/ui/FocusTrackback.java | 19 ++-- 4 files changed, 63 insertions(+), 63 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index edb4e6591cf3..b1df17b0363c 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -971,6 +971,19 @@ public abstract class DialogWrapper { } } + public static void cleanupWindowListeners(@Nullable Window window) { + if (window == null) return; + for (WindowListener listener : window.getWindowListeners()) { + if (listener.getClass().getName().startsWith("com.intellij.")) { + LOG.warn("Stale listener: " + listener); + } + else { + LOG.info("Stale listener: " + listener); + } + window.removeWindowListener(listener); + } + } + /** * This method is invoked by default implementation of "Cancel" action. It just closes dialog diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java b/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java index a4417d80b766..99ae5e71d43d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java @@ -25,7 +25,6 @@ import com.intellij.openapi.actionSystem.ex.ActionManagerEx; import com.intellij.openapi.actionSystem.ex.ActionUtil; import com.intellij.openapi.actionSystem.impl.MouseGestureManager; import com.intellij.openapi.application.impl.ApplicationInfoImpl; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectManagerAdapter; @@ -60,7 +59,6 @@ import java.io.File; import java.util.Map; public class FrameWrapper implements Disposable, DataProvider { - private static final Logger LOG = Logger.getInstance(FrameWrapper.class); private String myDimensionKey = null; private JComponent myComponent = null; @@ -253,10 +251,7 @@ public class FrameWrapper implements Disposable, DataProvider { frame.dispose(); - for (WindowListener listener : frame.getWindowListeners()) { - LOG.info("Clearing stale window listener: " + listener); - frame.removeWindowListener(listener); - } + DialogWrapper.cleanupWindowListeners(frame); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java index 00f87f78c8c9..305708c5d65d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java @@ -709,50 +709,6 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra ScreenUtil.fitToScreen(bounds); setBounds(bounds); } - addWindowListener(new WindowAdapter() { - @Override - public void windowActivated(WindowEvent e) { - final DialogWrapper wrapper = getDialogWrapper(); - if (wrapper != null && myFocusTrackback != null) { - myFocusTrackback.cleanParentWindow(); - myFocusTrackback.registerFocusComponent(new FocusTrackback.ComponentQuery() { - @Override - public Component getComponent() { - return wrapper.getPreferredFocusedComponent(); - } - }); - } - } - - @Override - public void windowDeactivated(WindowEvent e) { - if (!isModal()) { - final Ref focusManager = new Ref<>(null); - Project project = getProject(); - if (project != null && !project.isDisposed()) { - focusManager.set(getFocusManager()); - focusManager.get().doWhenFocusSettlesDown(() -> disposeFocusTrackbackIfNoChildWindowFocused(focusManager.get())); - } - else { - disposeFocusTrackbackIfNoChildWindowFocused(focusManager.get()); - } - } - } - - @Override - public void windowOpened(WindowEvent e) { - if (!SystemInfo.isMacOSLion) return; - Window window = e.getWindow(); - if (window instanceof Dialog) { - ID _native = MacUtil.findWindowForTitle(((Dialog)window).getTitle()); - if (_native != null && _native.intValue() > 0) { - // see MacMainFrameDecorator - // NSCollectionBehaviorFullScreenAuxiliary = 1 << 8 - Foundation.invoke(_native, "setCollectionBehavior:", 1 << 8); - } - } - } - }); if (Registry.is("actionSystem.fixLostTyping")) { final IdeEventQueue queue = IdeEventQueue.getInstance(); @@ -846,10 +802,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra myWindowListener = null; } - for (WindowListener listener : getWindowListeners()) { - LOG.info("Clearing stale window listener: " + listener); - removeWindowListener(listener); - } + DialogWrapper.cleanupWindowListeners(this); if (myFocusTrackback != null && !(myFocusTrackback.isScheduledForRestore() || myFocusTrackback.isWillBeScheduledForRestore())) { myFocusTrackback.dispose(); @@ -938,6 +891,17 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra @Override public void windowOpened(final WindowEvent e) { + if (SystemInfo.isMacOSLion) { + Window window = e.getWindow(); + if (window instanceof Dialog) { + ID _native = MacUtil.findWindowForTitle(((Dialog)window).getTitle()); + if (_native != null && _native.intValue() > 0) { + // see MacMainFrameDecorator + // NSCollectionBehaviorFullScreenAuxiliary = 1 << 8 + Foundation.invoke(_native, "setCollectionBehavior:", 1 << 8); + } + } + } SwingUtilities.invokeLater(() -> { myOpened = true; final DialogWrapper activeWrapper = getActiveWrapper(); @@ -953,6 +917,18 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra @Override public void windowActivated(final WindowEvent e) { + if (myFocusTrackback != null) { + DialogWrapper wrapper = getDialogWrapper(); + if (wrapper != null) { + myFocusTrackback.cleanParentWindow(); + myFocusTrackback.registerFocusComponent(new FocusTrackback.ComponentQuery() { + @Override + public Component getComponent() { + return wrapper.getPreferredFocusedComponent(); + } + }); + } + } SwingUtilities.invokeLater(() -> { final DialogWrapper wrapper = getActiveWrapper(); if (wrapper == null && !myFocusedCallback.isProcessed()) { @@ -991,6 +967,21 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra }); } + @Override + public void windowDeactivated(WindowEvent e) { + if (!isModal()) { + Ref focusManager = new Ref<>(null); + Project project = getProject(); + if (project != null && !project.isDisposed()) { + focusManager.set(getFocusManager()); + focusManager.get().doWhenFocusSettlesDown(() -> disposeFocusTrackbackIfNoChildWindowFocused(focusManager.get())); + } + else { + disposeFocusTrackbackIfNoChildWindowFocused(focusManager.get()); + } + } + } + private void notifyFocused(DialogWrapper wrapper) { myFocusedCallback.setDone(); final long timeout = wrapper.getTypeAheadTimeoutMs(); diff --git a/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java b/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java index 712a238387c7..5dcfca1858a1 100644 --- a/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java +++ b/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java @@ -39,10 +39,8 @@ import javax.swing.*; import java.awt.*; import java.lang.ref.WeakReference; import java.lang.reflect.Method; -import java.util.ArrayList; +import java.util.*; import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; public class FocusTrackback { @@ -79,8 +77,7 @@ public class FocusTrackback { myMustBeShown = mustBeShown; - final Application app = ApplicationManager.getApplication(); - if (app == null || app.isHeadlessEnvironment() || wrongOS()) return; + if (isHeadlessOrWrongOS()) return; register(parent); @@ -135,6 +132,11 @@ public class FocusTrackback { } } + private static boolean isHeadlessOrWrongOS() { + Application app = ApplicationManager.getApplication(); + return app == null || app.isHeadlessEnvironment() || wrongOS(); + } + private void setLocalFocusOwner(Component component) { myLocalFocusOwner = new WeakReference<>(component); } @@ -171,10 +173,10 @@ public class FocusTrackback { } private List getCleanStackForRoot() { - return getCleanStackForRoot(myRoot); + return myRoot == null ? Collections.emptyList() : getCleanStackForRoot(myRoot); } - private static List getCleanStackForRoot(final Window root) { + private static List getCleanStackForRoot(@NotNull Window root) { List stack = getStackForRoot(root); final FocusTrackback[] stackArray = stack.toArray(new FocusTrackback[stack.size()]); @@ -190,8 +192,7 @@ public class FocusTrackback { } public void restoreFocus() { - final Application app = ApplicationManager.getApplication(); - if (app == null || wrongOS() || myConsumed || isScheduledForRestore()) return; + if (isHeadlessOrWrongOS() || myConsumed || isScheduledForRestore()) return; Project project = null; DataManager dataManager = DataManager.getInstance();