From 801e8f77fa1e272bd6bb74d9c10e3034dd7162bd Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Fri, 26 Apr 2019 15:02:39 +0300 Subject: [PATCH] IDEA-211596 Prevent IDE dialogs stealing focus on activation Evaluate dialog and other non-modal dialogs are fixed GitOrigin-RevId: 6a9c2983bc07acb5d42894990274490bafae3f5c --- .../com/intellij/openapi/ui/FrameWrapper.java | 11 +-- .../ui/impl/DialogWrapperPeerImpl.java | 69 +++++++------------ 2 files changed, 26 insertions(+), 54 deletions(-) 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 d12c160c233e..fd3e59b623cb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java @@ -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; 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 84cb9fde68d8..506928f09f0c 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 @@ -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 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 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() {