diff --git a/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java b/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java index e5b9fe16bdec..a54edfba71e6 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java @@ -31,6 +31,8 @@ public abstract class FocusCommand extends ActiveRunnable implements Expirable { private Component myDominationComponent; private Throwable myAllocation; + private ActionCallback myCallback; + protected FocusCommand() { } @@ -56,6 +58,14 @@ public abstract class FocusCommand extends ActiveRunnable implements Expirable { myDominationComponent = dominationComp; } + public final ActionCallback getCallback() { + return myCallback; + } + + public final void setCallback(ActionCallback callback) { + myCallback = callback; + } + public boolean isExpired() { return false; } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java index 552c15a08bc5..ae1ede41ea4b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java @@ -15,7 +15,6 @@ */ package com.intellij.openapi.wm.impl; -import com.intellij.Patches; import com.intellij.ide.IdeEventQueue; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.Application; @@ -41,6 +40,7 @@ import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -151,6 +151,7 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable { if (checkForRejectOrByPass(command, forced, result)) return; setCommand(command); + command.setCallback(result); if (forced) { myForcedFocusRequestsAlarm.cancelAllRequests(); @@ -190,7 +191,7 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable { } }).doWhenProcessed(new Runnable() { public void run() { - resetCommand(command); + resetCommand(command, true); if (forced) { myForcedFocusRequestsAlarm.addRequest(new EdtRunnable() { @@ -258,7 +259,7 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable { } } - private void resetCommand(FocusCommand cmd) { + private void resetCommand(FocusCommand cmd, boolean reject) { if (cmd == myRequestFocusCmd) { myRequestFocusCmd = null; } @@ -269,6 +270,13 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable { } myFocusRequests.remove(cmd); + + if (reject) { + ActionCallback cb = cmd.getCallback(); + if (cb != null && !cb.isProcessed()) { + cmd.getCallback().setRejected(); + } + } } private void resetUnforcedCommand(FocusCommand cmd) { @@ -381,12 +389,31 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable { } public boolean isFocusTransferReady() { + invalidateFocusRequestsQueue(); + if (!myFocusRequests.isEmpty()) return false; if (myQueue == null) return true; return !myQueue.isSuspendMode() && !myQueue.hasFocusEventsPending(); } + private void invalidateFocusRequestsQueue() { + if (myFocusRequests.size() == 0) return; + + FocusCommand[] requests = myFocusRequests.toArray(new FocusCommand[myFocusRequests.size()]); + boolean wasChanged = false; + for (FocusCommand each : requests) { + if (each.isExpired()) { + resetCommand(each, true); + wasChanged = true; + } + } + + if (wasChanged && myFocusRequests.size() == 0) { + restartIdleAlarm(); + } + } + private boolean isIdleQueueEmpty() { return isPendingKeyEventsRedispatched() && myIdleRequests.isEmpty(); } @@ -461,7 +488,7 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable { private void rejectCommand(FocusCommand cmd, ActionCallback callback) { - resetCommand(cmd); + resetCommand(cmd, true); resetUnforcedCommand(cmd); callback.setRejected();