IDEA-152525 IDE loses focus after closing toolwindow with a Alt+[0-9] shortcut

IDEA-152472 Editor looses focus on entering Distraction Free or Presentatipn Modes
This commit is contained in:
Denis Fokin
2016-03-14 12:50:15 +03:00
parent 184ade8e11
commit 94d00ea76d
9 changed files with 72 additions and 212 deletions
@@ -22,7 +22,6 @@ import com.intellij.execution.ui.layout.actions.CloseViewAction;
import com.intellij.execution.ui.layout.actions.MinimizeViewAction;
import com.intellij.execution.ui.layout.actions.RestoreViewAction;
import com.intellij.ide.DataManager;
import com.intellij.ide.actions.CloseAction;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.Project;
@@ -32,10 +31,8 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.IdeGlassPaneUtil;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.JBColor;
import com.intellij.ui.ScreenUtil;
import com.intellij.ui.UIBundle;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.awt.RelativeRectangle;
@@ -91,7 +88,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
@NotNull private final ActionManager myActionManager;
private final String mySessionName;
private final MyComponent myComponent = new MyComponent();
private JComponent myComponent;
private final Wrapper myToolbar = new Wrapper();
final MyDragOutDelegate myDragOutDelegate = new MyDragOutDelegate();
@@ -235,7 +232,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
wrappper.add(myTabs.getComponent(), BorderLayout.CENTER);
wrappper.setBorder(new EmptyBorder(-1, 0, 0, 0));
myComponent.setContent(wrappper);
myComponent = wrappper;
myTabs.addListener(new TabsListener.Adapter() {
@@ -1387,102 +1384,6 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
}
private class MyComponent extends Wrapper.FocusHolder implements DataProvider, QuickActionProvider {
private boolean myWasEverAdded;
public MyComponent() {
setOpaque(true);
setFocusCycleRoot(true);
setBorder(new ToolWindow.Border(false, false, false, false));
}
@Override
@Nullable
public Object getData(@NonNls final String dataId) {
if (KEY.is(dataId)) {
return RunnerContentUi.this;
}
else if (CloseAction.CloseTarget.KEY.is(dataId)) {
Content content = getContentManager().getSelectedContent();
if (content != null && content.getManager().canCloseContents() && content.isCloseable()) {
return new CloseAction.CloseTarget() {
@Override
public void close() {
content.getManager().removeContent(content, true, true, true);
}
};
}
}
ContentManager originalContentManager = myOriginal == null ? null : myOriginal.getContentManager();
JComponent originalContentComponent = originalContentManager == null ? null : originalContentManager.getComponent();
if (originalContentComponent instanceof DataProvider) {
return ((DataProvider)originalContentComponent).getData(dataId);
}
return null;
}
@SuppressWarnings("NullableProblems")
@Override
public String getName() {
return RunnerContentUi.this.getName();
}
@Override
public List<AnAction> getActions(boolean originalProvider) {
return RunnerContentUi.this.getActions(originalProvider);
}
@Override
public JComponent getComponent() {
return RunnerContentUi.this.getComponent();
}
@Override
public boolean isCycleRoot() {
return RunnerContentUi.this.isCycleRoot();
}
@Override
public void addNotify() {
super.addNotify();
if (!myUiLastStateWasRestored && myOriginal == null) {
myUiLastStateWasRestored = true;
// [kirillk] this is done later since restoreUiState doesn't work properly in the addNotify call chain
//todo to investigate and to fix (may cause extra flickering)
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
restoreLastUiState().doWhenDone(new Runnable() {
@Override
public void run() {
if (!myWasEverAdded) {
myWasEverAdded = true;
attractOnStartup();
myInitialized.setDone();
}
}
});
}
});
}
}
@Override
public void removeNotify() {
super.removeNotify();
if (!ScreenUtil.isStandardAddRemoveNotify(this))
return;
if (Disposer.isDisposed(RunnerContentUi.this)) return;
saveUiState();
}
}
@SuppressWarnings({"SSBasedInspection"})
// [kirillk] this is done later since "startup" attractions should be done gently, only if no explicit calls are done
private void attractOnStartup() {
@@ -71,6 +71,69 @@ public class ThreeComponentsSplitter extends JPanel implements Disposable {
private boolean myShowDividerControls;
private int myDividerZone;
private class MyFocusTraversalPolicy extends FocusTraversalPolicy {
@Override
public Component getComponentAfter(Container aContainer, Component aComponent) {
if (aComponent == myFirstComponent) {
return findChildToFocus(myInnerComponent);
}
if (aComponent == myInnerComponent) {
return findChildToFocus(myLastComponent);
}
return findChildToFocus(myFirstComponent);
}
@Override
public Component getComponentBefore(Container aContainer, Component aComponent) {
if (aComponent == myInnerComponent) {
return findChildToFocus(myFirstComponent);
}
if (aComponent == myLastComponent) {
return findChildToFocus(myInnerComponent);
}
return findChildToFocus(myFirstComponent);
}
@Override
public Component getFirstComponent(Container aContainer) {
return findChildToFocus(myFirstComponent);
}
@Override
public Component getLastComponent(Container aContainer) {
return findChildToFocus(myLastComponent);
}
@Override
public Component getDefaultComponent(Container aContainer) {
return findChildToFocus(myInnerComponent);
}
Component findChildToFocus (Component component) {
if (component instanceof JPanel) {
JPanel container = (JPanel)component;
final FocusTraversalPolicy policy = container.getFocusTraversalPolicy();
if (policy == null) {
System.err.println ("Container must have provided a default focus traversal policy: " + container.getClass().getName());
return container;
}
final Component defaultComponent = policy.getDefaultComponent(container);
if (defaultComponent == null) {
System.err.println ("Container must have provided a default component: " + container.getClass().getName());
return container;
}
return policy.getDefaultComponent(container);
}
return component;
}
}
/**
* Creates horizontal split with proportion equals to .5f
@@ -97,6 +160,9 @@ public class ThreeComponentsSplitter extends JPanel implements Disposable {
myFirstDivider.setBackground(bg);
myLastDivider.setBackground(bg);
}
setFocusCycleRoot(true);
setFocusTraversalPolicy(new MyFocusTraversalPolicy());
setFocusable(false);
setOpaque(false);
add(myFirstDivider);
add(myLastDivider);
@@ -16,12 +16,9 @@
package com.intellij.ui.components.panels;
import com.intellij.openapi.ui.NullableComponent;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
public class Wrapper extends JPanel implements NullableComponent {
@@ -137,73 +134,6 @@ public class Wrapper extends JPanel implements NullableComponent {
return size;
}
public static class FocusHolder extends Wrapper implements FocusListener {
private Runnable myFocusGainedCallback;
public FocusHolder() {
init();
}
public FocusHolder(final JComponent wrapped) {
super(wrapped);
init();
}
public FocusHolder(final LayoutManager layout, final JComponent wrapped) {
super(layout, wrapped);
init();
}
public FocusHolder(final boolean isDoubleBuffered) {
super(isDoubleBuffered);
init();
}
public FocusHolder(final LayoutManager layout) {
super(layout);
init();
}
public FocusHolder(final LayoutManager layout, final boolean isDoubleBuffered) {
super(layout, isDoubleBuffered);
init();
}
private void init() {
UIUtil.setFocusProxy(this, true);
setFocusable(true);
addFocusListener(this);
}
public void requestFocus(Runnable callback) {
myFocusGainedCallback = callback;
if (isFocusOwner()) {
processCallback();
} else {
requestFocusInternal();
}
}
@Override
public void focusGained(final FocusEvent e) {
processCallback();
}
private void processCallback() {
if (myFocusGainedCallback != null) {
Runnable callback = myFocusGainedCallback;
myFocusGainedCallback = null;
callback.run();
}
}
@Override
public void focusLost(final FocusEvent e) {
}
}
public static class North extends Wrapper {
public North(JComponent wrapped) {
super(new BorderLayout());
@@ -17,7 +17,6 @@ package com.intellij.openapi.wm.impl;
import com.intellij.openapi.wm.IdeGlassPane;
import javax.swing.*;
import java.awt.*;
/**
@@ -31,6 +30,4 @@ public interface IdeGlassPaneEx extends IdeGlassPane {
Component getComponent(int index);
boolean isInModalContext();
JComponent getProxyComponent();
}
@@ -29,7 +29,6 @@ import com.intellij.openapi.util.Weighted;
import com.intellij.openapi.wm.IdeGlassPane;
import com.intellij.openapi.wm.IdeGlassPaneUtil;
import com.intellij.util.containers.FactoryMap;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.MouseEventAdapter;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -82,13 +81,6 @@ public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEvent
private Cursor myLastOriginalCursor;
private MouseEvent myPrevPressEvent;
private JPanel myFocusProxy = new JPanel(){
@Override
public String toString() {
return "FocusProxy";
}
};
public IdeGlassPaneImpl(JRootPane rootPane) {
myRootPane = rootPane;
setOpaque(false);
@@ -99,25 +91,11 @@ public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEvent
IdeBackgroundUtil.initFramePainters(getNamedPainters("ide"));
IdeBackgroundUtil.initEditorPainters(getNamedPainters("editor"));
}
myFocusProxy.setOpaque(false);
myFocusProxy.setPreferredSize(JBUI.emptySize());
myFocusProxy.setFocusable(true);
UIUtil.setFocusProxy(myFocusProxy, true);
}
@Override
public void addNotify() {
super.addNotify();
if (myFocusProxy.getParent() != null) {
myFocusProxy.getParent().remove(myFocusProxy);
}
if (myFocusProxy.getParent() != getParent()) {
getParent().add(myFocusProxy);
myFocusProxy.setBounds(0, 0, 0, 0);
}
}
public boolean dispatch(final AWTEvent e) {
@@ -625,9 +603,4 @@ public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEvent
public boolean isOptimizedDrawingEnabled() {
return !getPainters().hasPainters() && super.isOptimizedDrawingEnabled();
}
@Override
public JComponent getProxyComponent() {
return myFocusProxy;
}
}
@@ -100,6 +100,9 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr
myHideStripeButtonAction = new RemoveStripeButtonAction();
myToggleToolbarGroup = ToggleToolbarAction.createToggleToolbarGroup(myProject, myToolWindow);
setFocusable(false);
setFocusTraversalPolicy(new LayoutFocusTraversalPolicy());
myHeader = new ToolWindowHeader(toolWindow, info, new Producer<ActionGroup>() {
@Override
public ActionGroup produce() {
@@ -87,7 +87,6 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
@Override
public void addNotify() {
super.addNotify();
rootPane.remove(getProxyComponent());
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
public void run() {
@@ -464,7 +464,6 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
public void run() {
IdeEventQueue.getInstance().disableInputMethods(BalloonImpl.this);
originalFocusOwner.set(myFocusManager.getFocusOwner());
myFocusManager.requestFocus(glassPane.getProxyComponent(), true).notify(proxyFocusRequest.get());
focusRequestor.set(myFocusManager.getFurtherRequestor());
}
});
@@ -29,13 +29,11 @@ import com.intellij.openapi.wm.FocusCommand;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
import com.intellij.ui.components.panels.NonOpaquePanel;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.ui.content.*;
import com.intellij.ui.switcher.SwitchProvider;
import com.intellij.ui.switcher.SwitchTarget;
import com.intellij.util.EventDispatcher;
import com.intellij.util.SmartList;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -63,7 +61,6 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
private final List<Content> mySelection = new ArrayList<Content>();
private final boolean myCanCloseContents;
private Wrapper.FocusHolder myFocusProxy;
private MyNonOpaquePanel myComponent;
private final Set<Content> myContentWithChangedComponent = new HashSet<Content>();
@@ -99,15 +96,10 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
if (myComponent == null) {
myComponent = new MyNonOpaquePanel();
myFocusProxy = new Wrapper.FocusHolder();
myFocusProxy.setOpaque(false);
myFocusProxy.setPreferredSize(JBUI.emptySize());
MyContentComponent contentComponent = new MyContentComponent();
contentComponent.setContent(myUI.getComponent());
contentComponent.setFocusCycleRoot(true);
myComponent.add(myFocusProxy, BorderLayout.NORTH);
myComponent.add(contentComponent, BorderLayout.CENTER);
}
return myComponent;
@@ -530,7 +522,7 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
boolean enabledFocus = getFocusManager().isFocusTransferEnabled();
if (focused || requestFocus) {
if (enabledFocus) {
return getFocusManager().requestFocus(myFocusProxy, true).doWhenProcessed(new Runnable() {
return getFocusManager().requestFocus(myComponent, true).doWhenProcessed(new Runnable() {
@Override
public void run() {
selection.run().notify(result);