From 5ad3469deb14835c061bc38cf69c6ccf7da190ea Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Mon, 28 May 2018 16:38:26 +0300 Subject: [PATCH] IDEA-192055 Focus goes nowhere after breakpoint popup --- .../openapi/wm/WeakFocusStackManager.java | 53 +++++++++++++++++++ .../openapi/wm/impl/IdeFocusManagerImpl.java | 2 + .../src/com/intellij/ui/BalloonImpl.java | 32 +++++++++-- 3 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 platform/platform-api/src/com/intellij/openapi/wm/WeakFocusStackManager.java diff --git a/platform/platform-api/src/com/intellij/openapi/wm/WeakFocusStackManager.java b/platform/platform-api/src/com/intellij/openapi/wm/WeakFocusStackManager.java new file mode 100644 index 000000000000..e7fddfeb5ffd --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/wm/WeakFocusStackManager.java @@ -0,0 +1,53 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.openapi.wm; + +import com.intellij.util.containers.WeakList; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.AWTEventListener; +import java.awt.event.FocusEvent; +import java.util.List; + +public class WeakFocusStackManager { + + private final WeakList focusOwners = new WeakList<>(); + + private static final WeakFocusStackManager instance = new WeakFocusStackManager(); + + public Component getLastFocusedOutside(Container container) { + Component[] components = focusOwners.toStrongList().toArray(new Component[0]); + for (int i = components.length - 1; i >= 0; i--) { + if (!SwingUtilities.isDescendingFrom(components[i], container)) { + return components[i]; + } + } + return null; + } + + public static WeakFocusStackManager getInstance() { + return instance; + } + + private WeakFocusStackManager () { + Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { + @Override + public void eventDispatched(AWTEvent event) { + // We are interested only in FOCUS_GAINED events + if (event.getID() == FocusEvent.FOCUS_GAINED) { + focusOwners.add((Component)event.getSource()); + } + } + }, AWTEvent.FOCUS_EVENT_MASK); + } + + public Component getLastFocusedComponent() { + List strongList = focusOwners.toStrongList(); + return strongList.isEmpty() ? null : strongList.get(strongList.size() - 1); + } + + public Component getLastButOneFocusedComponent() { + List strongList = focusOwners.toStrongList(); + return strongList.size() < 2 ? null : strongList.get(strongList.size() - 2); + } +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFocusManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFocusManagerImpl.java index bbdce310cd7b..318c4f5d4354 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFocusManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFocusManagerImpl.java @@ -22,6 +22,7 @@ import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.ExpirableRunnable; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.IdeFrame; +import com.intellij.openapi.wm.WeakFocusStackManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,6 +34,7 @@ public class IdeFocusManagerImpl extends IdeFocusManager { public IdeFocusManagerImpl(ToolWindowManagerImpl twManager) { myToolWindowManager = twManager; + WeakFocusStackManager.getInstance(); } @Override diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java index 02966809f86a..8c6d261e506f 100644 --- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java @@ -18,10 +18,7 @@ import com.intellij.openapi.ui.popup.JBPopupListener; import com.intellij.openapi.ui.popup.LightweightWindowEvent; import com.intellij.openapi.util.*; import com.intellij.openapi.util.registry.Registry; -import com.intellij.openapi.wm.FocusRequestor; -import com.intellij.openapi.wm.IdeFocusManager; -import com.intellij.openapi.wm.IdeGlassPane; -import com.intellij.openapi.wm.IdeGlassPaneUtil; +import com.intellij.openapi.wm.*; import com.intellij.openapi.wm.impl.IdeGlassPaneEx; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.components.panels.NonOpaquePanel; @@ -1626,6 +1623,33 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui { myContent.setOpaque(false); add(myContent); + setFocusTraversalPolicyProvider(true); + setFocusTraversalPolicy(new FocusTraversalPolicy() { + @Override + public Component getComponentAfter(Container aContainer, Component aComponent) { + return WeakFocusStackManager.getInstance().getLastFocusedOutside(MyComponent.this); + } + + @Override + public Component getComponentBefore(Container aContainer, Component aComponent) { + return WeakFocusStackManager.getInstance().getLastFocusedOutside(MyComponent.this); + } + + @Override + public Component getFirstComponent(Container aContainer) { + return WeakFocusStackManager.getInstance().getLastFocusedOutside(MyComponent.this); + } + + @Override + public Component getLastComponent(Container aContainer) { + return WeakFocusStackManager.getInstance().getLastFocusedOutside(MyComponent.this); + } + + @Override + public Component getDefaultComponent(Container aContainer) { + return WeakFocusStackManager.getInstance().getLastFocusedOutside(MyComponent.this); + } + }); } public Rectangle getContentBounds() {