IDEA-211596 Prevent IDE dialogs stealing focus on activation

Evaluate dialog and other non-modal dialogs are fixed

GitOrigin-RevId: 6a9c2983bc07acb5d42894990274490bafae3f5c
This commit is contained in:
Denis Fokin
2019-04-28 18:19:01 +03:00
committed by intellij-monorepo-bot
parent 6190075173
commit 801e8f77fa
2 changed files with 26 additions and 54 deletions
@@ -55,7 +55,6 @@ public class FrameWrapper implements Disposable, DataProvider {
private final ProjectManagerListener myProjectListener = new MyProjectManagerListener();
private FocusWatcher myFocusWatcher;
private ActionCallback myFocusedCallback;
private boolean myDisposing;
private boolean myDisposed;
@@ -104,11 +103,6 @@ public class FrameWrapper implements Disposable, DataProvider {
}
public void show(boolean restoreBounds) {
myFocusedCallback = new ActionCallback();
if (myProject != null) {
IdeFocusManager.getInstance(myProject).typeAheadUntil(myFocusedCallback);
}
final Window frame = getFrame();
@@ -141,9 +135,7 @@ public class FrameWrapper implements Disposable, DataProvider {
}
if (toFocus != null) {
fm.requestFocus(toFocus, true).notify(myFocusedCallback);
} else {
myFocusedCallback.setRejected();
fm.requestFocus(toFocus, true);
}
}
};
@@ -216,7 +208,6 @@ public class FrameWrapper implements Disposable, DataProvider {
myFocusWatcher.deinstall(myComponent);
}
myFocusWatcher = null;
myFocusedCallback = null;
myComponent = null;
myImages = null;
@@ -11,6 +11,7 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.application.impl.LaterInvocator;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.CommandProcessorEx;
@@ -72,12 +73,10 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer {
private final WindowManagerEx myWindowManager;
private final List<Runnable> myDisposeActions = new ArrayList<>();
private Project myProject;
private ActionCallback myTypeAheadCallback;
protected DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper, @Nullable Project project, boolean canBeParent, @NotNull DialogWrapper.IdeModalityType ideModalityType) {
boolean headless = isHeadlessEnv();
myWrapper = wrapper;
myTypeAheadCallback = myWrapper.isTypeAheadEnabled() ? new ActionCallback() : null;
myWindowManager = getWindowManager();
Window window = null;
@@ -118,7 +117,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer {
owner = null;
}
myDialog = createDialog(headless, owner, wrapper, myProject, myTypeAheadCallback, ideModalityType);
myDialog = createDialog(headless, owner, wrapper, myProject, ideModalityType);
myCanBeParent = headless || canBeParent;
}
@@ -147,7 +146,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer {
boolean headless = isHeadlessEnv();
myWrapper = wrapper;
myWindowManager = getWindowManager();
myDialog = createDialog(headless, OwnerOptional.fromComponent(parent).get(), wrapper, null, null, DialogWrapper.IdeModalityType.IDE);
myDialog = createDialog(headless, OwnerOptional.fromComponent(parent).get(), wrapper, null, DialogWrapper.IdeModalityType.IDE);
myCanBeParent = headless || canBeParent;
}
@@ -155,7 +154,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer {
boolean headless = isHeadlessEnv();
myWrapper = wrapper;
myWindowManager = getWindowManager();
myDialog = createDialog(headless, owner, wrapper, null, null, DialogWrapper.IdeModalityType.IDE);
myDialog = createDialog(headless, owner, wrapper, null, DialogWrapper.IdeModalityType.IDE);
myCanBeParent = headless || canBeParent;
if (!headless) {
@@ -180,15 +179,13 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer {
Window owner,
DialogWrapper wrapper,
Project project,
ActionCallback typeAhead,
DialogWrapper.IdeModalityType ideModalityType) {
if (headless) {
return new HeadlessDialog(wrapper);
}
else {
ActionCallback focused = new ActionCallback("DialogFocusedCallback");
ActionCallback typeAheadDone = new ActionCallback("DialogTypeAheadDone");
MyDialog dialog = new MyDialog(OwnerOptional.fromComponent(owner).get(), wrapper, project, focused, typeAheadDone, typeAhead);
MyDialog dialog = new MyDialog(OwnerOptional.fromComponent(owner).get(), wrapper, project, focused);
dialog.setModalityType(ideModalityType.toAwtModality());
return dialog;
}
@@ -384,9 +381,6 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer {
@Override
public ActionCallback show() {
LOG.assertTrue(EventQueue.isDispatchThread(), "Access is allowed from event dispatch thread only");
if (myTypeAheadCallback != null) {
IdeFocusManager.getInstance(myProject).typeAheadUntil(myTypeAheadCallback);
} LOG.assertTrue(EventQueue.isDispatchThread(), "Access is allowed from event dispatch thread only");
final ActionCallback result = new ActionCallback();
final AnCancelAction anCancelAction = new AnCancelAction();
@@ -427,7 +421,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer {
hidePopupsIfNeeded();
}
myDialog.getWindow().setAutoRequestFocus(true);
myDialog.getWindow().setAutoRequestFocus(!Registry.is("suppress.focus.stealing"));
final Disposable tb = TouchBarsManager.showDialogWrapperButtons(myDialog.getContentPane());
if (tb != null)
@@ -523,15 +517,11 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer {
private final WeakReference<Project> myProject;
private final ActionCallback myFocusedCallback;
private final ActionCallback myTypeAheadDone;
private final ActionCallback myTypeAheadCallback;
MyDialog(Window owner,
DialogWrapper dialogWrapper,
Project project,
@NotNull ActionCallback focused,
@NotNull ActionCallback typeAheadDone,
ActionCallback typeAheadCallback) {
@NotNull ActionCallback focused) {
super(owner);
UIUtil.markAsTypeAheadAware(this);
myDialogWrapper = new WeakReference<>(dialogWrapper);
@@ -546,20 +536,26 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer {
});
myFocusedCallback = focused;
myTypeAheadDone = typeAheadDone;
myTypeAheadCallback = typeAheadCallback;
final long typeAhead = getDialogWrapper().getTypeAheadTimeoutMs();
if (typeAhead <= 0) {
myTypeAheadDone.setDone();
}
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
myWindowListener = new MyWindowListener();
addWindowListener(myWindowListener);
UIUtil.setAutoRequestFocus(this, true);
UIUtil.setAutoRequestFocus(this, !Registry.is("suppress.focus.stealing"));
}
@Deprecated
MyDialog(Window owner,
DialogWrapper dialogWrapper,
Project project,
@NotNull ActionCallback focused,
@NotNull ActionCallback typeAheadDone,
ActionCallback typeAheadCallback) {
this(owner, dialogWrapper, project, focused);
}
@Override
public JDialog getWindow() {
return this;
@@ -823,17 +819,11 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer {
}
if (activeWrapper == null) {
myFocusedCallback.setRejected();
myTypeAheadDone.setRejected();
}
});
}
@Override
public void windowActivated(final WindowEvent e) {
final DialogWrapper wrapper = getActiveWrapper();
if (wrapper == null && !myFocusedCallback.isProcessed()) {
myFocusedCallback.setRejected();
myTypeAheadDone.setRejected();
return;
}
@@ -852,31 +842,22 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer {
setupSelectionOnPreferredComponent(toFocus);
if (toFocus != null) {
if (isShowing()) {
toFocus.requestFocus();
notifyFocused(wrapper);
if (isShowing() && ApplicationManagerEx.getApplicationEx().isActive()) {
toFocus.requestFocus();
} else {
toFocus.requestFocusInWindow();
}
notifyFocused(wrapper);
} else {
if (isShowing()) {
notifyFocused(wrapper);
}
}
if (myTypeAheadCallback != null) {
myTypeAheadCallback.setDone();
}
});
}
private void notifyFocused(DialogWrapper wrapper) {
myFocusedCallback.setDone();
final long timeout = wrapper.getTypeAheadTimeoutMs();
if (timeout > 0) {
SimpleTimer.getInstance().setUp(new EdtRunnable() {
@Override
public void runEdt() {
myTypeAheadDone.setDone();
}
}, timeout);
}
}
private DialogWrapper getActiveWrapper() {