diff options
Diffstat (limited to 'platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java')
-rw-r--r-- | platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java | 68 |
1 files changed, 61 insertions, 7 deletions
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index 78802ccdf6bb..e50403abef45 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -162,6 +162,25 @@ public class AbstractPopup implements JBPopup { private UiActivity myActivityKey; private Disposable myProjectDisposable; + private volatile State myState = State.NEW; + + private enum State {NEW, INIT, SHOWING, SHOWN, CANCEL, DISPOSE} + + private void debugState(String message, State... states) { + if (LOG.isDebugEnabled()) { + LOG.debug(hashCode() + " - " + message); + if (!ApplicationManager.getApplication().isDispatchThread()) { + LOG.debug("unexpected thread"); + } + for (State state : states) { + if (state == myState) { + return; + } + } + LOG.debug(new IllegalStateException("myState=" + myState)); + } + } + AbstractPopup() { } AbstractPopup init(Project project, @@ -302,6 +321,8 @@ public class AbstractPopup implements JBPopup { } myKeyEventHandler = keyEventHandler; + debugState("popup initialized", State.NEW); + myState = State.INIT; return this; } @@ -582,10 +603,18 @@ public class AbstractPopup implements JBPopup { @Override public void cancel(InputEvent e) { + if (myState == State.CANCEL || myState == State.DISPOSE) { + return; + } + debugState("cancel popup", State.SHOWN); + myState = State.CANCEL; + if (isDisposed()) return; if (myPopup != null) { if (!canClose()) { + debugState("cannot cancel popup", State.CANCEL); + myState = State.SHOWN; return; } storeDimensionSize(myContent.getSize()); @@ -610,8 +639,13 @@ public class AbstractPopup implements JBPopup { } if (myInStack) { - myFocusTrackback.setForcedRestore(!myOk && myFocusable); - myFocusTrackback.restoreFocus(); + if (myFocusTrackback != null) { + myFocusTrackback.setForcedRestore(!myOk && myFocusable); + myFocusTrackback.restoreFocus(); + } + else if (LOG.isDebugEnabled()) { + LOG.debug("cancel before show @ " + Thread.currentThread()); + } } @@ -664,6 +698,9 @@ public class AbstractPopup implements JBPopup { assert ApplicationManager.getApplication().isDispatchThread(); + debugState("show popup", State.INIT); + myState = State.SHOWING; + installWindowHook(this); installProjectDisposer(); addActivity(); @@ -673,6 +710,8 @@ public class AbstractPopup implements JBPopup { final boolean shouldShow = beforeShow(); if (!shouldShow) { removeActivity(); + debugState("rejected to show popup", State.SHOWING); + myState = State.INIT; return; } @@ -758,10 +797,11 @@ public class AbstractPopup implements JBPopup { PopupComponent.Factory factory = getFactory(myForcedHeavyweight || myResizable, forcedDialog); myNativePopup = factory.isNativePopup(); Component popupOwner = myOwner; - if (popupOwner instanceof RootPaneContainer) { + if (popupOwner instanceof RootPaneContainer && !(popupOwner instanceof IdeFrame && !Registry.is("popup.fix.ide.frame.owner"))) { // JDK uses cached heavyweight popup for a window ancestor RootPaneContainer root = (RootPaneContainer)popupOwner; popupOwner = root.getRootPane(); + LOG.debug("popup owner fixed for JDK cache"); } if (LOG.isDebugEnabled()) { LOG.debug("expected preferred size: " + myContent.getPreferredSize()); @@ -957,6 +997,8 @@ public class AbstractPopup implements JBPopup { } }); } + debugState("popup shown", State.SHOWING); + myState = State.SHOWN; } public void focusPreferredComponent() { @@ -1232,6 +1274,16 @@ public class AbstractPopup implements JBPopup { @Override public void dispose() { + if (myState == State.SHOWN) { + LOG.debug("shown popup must be cancelled"); + cancel(); + } + if (myState == State.DISPOSE) { + return; + } + debugState("dispose popup", State.INIT, State.CANCEL); + myState = State.DISPOSE; + if (myDisposed) { return; } @@ -1480,8 +1532,8 @@ public class AbstractPopup implements JBPopup { @Override public Dimension getSize() { if (myPopup != null) { - final Window popupWindow = SwingUtilities.windowForComponent(myContent); - return popupWindow.getSize(); + final Window popupWindow = getContentWindow(myContent); + return (popupWindow == null) ? myForcedSize : popupWindow.getSize(); } else { return myForcedSize; } @@ -1491,7 +1543,8 @@ public class AbstractPopup implements JBPopup { public void moveToFitScreen() { if (myPopup == null) return; - final Window popupWindow = SwingUtilities.windowForComponent(myContent); + final Window popupWindow = getContentWindow(myContent); + if (popupWindow == null) return; Rectangle bounds = popupWindow.getBounds(); ScreenUtil.moveRectangleToFitTheScreen(bounds); @@ -1501,7 +1554,8 @@ public class AbstractPopup implements JBPopup { public static Window setSize(JComponent content, final Dimension size) { - final Window popupWindow = SwingUtilities.windowForComponent(content); + final Window popupWindow = getContentWindow(content); + if (popupWindow == null) return null; Insets insets = content.getInsets(); if (insets != null) { size.width += insets.left + insets.right; |