mem leaks: clear CWindow listeners and rootPane: unify listeners & DRY

This commit is contained in:
Gregory.Shrago
2016-12-01 22:21:05 +03:00
parent c363f002ce
commit 098fdda8ef
4 changed files with 63 additions and 63 deletions
@@ -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
@@ -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);
}
}
@@ -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<IdeFocusManager> 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<IdeFocusManager> 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();
@@ -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<FocusTrackback> getCleanStackForRoot() {
return getCleanStackForRoot(myRoot);
return myRoot == null ? Collections.emptyList() : getCleanStackForRoot(myRoot);
}
private static List<FocusTrackback> getCleanStackForRoot(final Window root) {
private static List<FocusTrackback> getCleanStackForRoot(@NotNull Window root) {
List<FocusTrackback> 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();