IDEA-183801: force request focus in StructureView by mouse pressed

This commit is contained in:
Sergey Malenkov
2018-07-12 21:32:45 +03:00
parent 76decd7435
commit a2573e94a5
4 changed files with 50 additions and 3 deletions
@@ -64,6 +64,7 @@ import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -71,6 +72,8 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import static com.intellij.openapi.keymap.impl.IdeMouseEventDispatcher.requestFocusInNonFocusedWindow;
public class StructureViewComponent extends SimpleToolWindowPanel implements TreeActionsOwner, DataProvider, StructureView.Scrollable {
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.structureView.newStructureView.StructureViewComponent");
@@ -852,6 +855,12 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre
public String getPlace() {
return ActionPlaces.STRUCTURE_VIEW_TOOLBAR;
}
@Override
public void processMouseEvent(MouseEvent event) {
requestFocusInNonFocusedWindow(event);
super.processMouseEvent(event);
}
}
private static class MyPsiTreeChangeListener extends PsiTreeChangeAdapter {
@@ -33,6 +33,7 @@ import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import static com.intellij.openapi.keymap.impl.IdeMouseEventDispatcher.requestFocusInNonFocusedWindow;
import static java.awt.event.KeyEvent.VK_SPACE;
public class ActionButton extends JComponent implements ActionButtonComponent, AnActionHolder, Accessible {
@@ -360,6 +361,7 @@ public class ActionButton extends JComponent implements ActionButtonComponent, A
}
protected void processMouseEvent(MouseEvent e) {
requestFocusInNonFocusedWindow(e);
super.processMouseEvent(e);
if (e.isConsumed()) return;
boolean skipPress = checkSkipPressForEvent(e);
@@ -419,4 +419,35 @@ public final class IdeMouseEventDispatcher {
blockMode = mode;
}
}
public static void requestFocusInNonFocusedWindow(@NotNull MouseEvent event) {
if (event.getID() == MOUSE_PRESSED) {
// request focus by mouse pressed before it settles down
requestFocusInNonFocusedWindow(event.getComponent());
}
}
private static void requestFocusInNonFocusedWindow(@Nullable Component component) {
Window window = UIUtil.getWindow(component);
if (window != null && !UIUtil.isFocusAncestor(window)) {
Component focusable = UIUtil.isFocusable(component) ? component : findDefaultFocusableComponent(component);
if (focusable != null) focusable.requestFocus();
}
}
@Nullable
private static Component findDefaultFocusableComponent(@Nullable Component component) {
Container provider = findFocusTraversalPolicyProvider(component);
return provider == null ? null : provider.getFocusTraversalPolicy().getDefaultComponent(provider);
}
@Nullable
private static Container findFocusTraversalPolicyProvider(@Nullable Component component) {
Container container = component == null || component instanceof Container ? (Container)component : component.getParent();
while (container != null) {
if (container.isFocusCycleRoot() && container.isFocusTraversalPolicyProvider()) return container;
container = container.getParent();
}
return null;
}
}
@@ -2556,8 +2556,13 @@ public class UIUtil {
drawCenteredString(g, rect, str, true, true);
}
public static boolean isFocusAncestor(@NotNull final JComponent component) {
final Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
/**
* @param component to check whether it has focus within its component hierarchy
* @return {@code true} if component or one of its children has focus
* @see Component#isFocusOwner()
*/
public static boolean isFocusAncestor(@NotNull Component component) {
Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (owner == null) return false;
if (owner == component) return true;
return SwingUtilities.isDescendingFrom(owner, component);
@@ -2691,7 +2696,7 @@ public class UIUtil {
* @return {@code true} if component is not {@code null} and can be focused
* @see Component#isRequestFocusAccepted(boolean, boolean, sun.awt.CausedFocusEvent.Cause)
*/
public static boolean isFocusable(JComponent component) {
public static boolean isFocusable(@Nullable Component component) {
return component != null && component.isFocusable() && component.isEnabled() && component.isShowing();
}