From ce0408fae105bbee710801d19f233ee0d1b56e7b Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 19 Feb 2018 20:23:52 +0300 Subject: [PATCH] IDEA-184963 diff: fix `runPreservingFocus` when switching panels from action popup * use Window.getMostRecentFocusOwner instead of global focus owner, because focus is still in popup. --- .../com/intellij/diff/FocusableContext.java | 4 ++-- .../diff/impl/DiffRequestProcessor.java | 19 +++++++++---------- .../diff/merge/MergeRequestProcessor.java | 17 ++++++++--------- .../com/intellij/diff/merge/MergeUtil.java | 8 ++++---- .../src/com/intellij/diff/util/DiffUtil.java | 16 ++++++++++++++-- .../com/intellij/diff/merge/MergeTestBase.kt | 4 ++-- .../diff/impl/settings/DiffPreviewPanel.java | 4 ++-- .../ChangeViewDiffRequestProcessor.java | 2 +- .../idea/svn/difftool/SvnDiffViewer.java | 13 +++++-------- 9 files changed, 47 insertions(+), 40 deletions(-) diff --git a/platform/diff-api/src/com/intellij/diff/FocusableContext.java b/platform/diff-api/src/com/intellij/diff/FocusableContext.java index eee77404c19a..bd8b8b88ae9e 100644 --- a/platform/diff-api/src/com/intellij/diff/FocusableContext.java +++ b/platform/diff-api/src/com/intellij/diff/FocusableContext.java @@ -22,7 +22,7 @@ package com.intellij.diff; * NB: focus requested via {@link java.awt.Component#requestFocusInWindow()}, ignoring {@link com.intellij.openapi.wm.IdeFocusManager} */ public interface FocusableContext { - boolean isFocused(); + boolean isFocusedInWindow(); - void requestFocus(); + void requestFocusInWindow(); } diff --git a/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java b/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java index 12db3df9af9f..1bae2d7e1e57 100644 --- a/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java +++ b/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java @@ -363,14 +363,13 @@ public abstract class DiffRequestProcessor implements Disposable { return window != null && window.isFocused(); } - protected boolean isFocused() { - return DiffUtil.isFocusedComponent(myProject, myContentPanel) || - DiffUtil.isFocusedComponent(myProject, myToolbar.getComponent()); + private boolean isFocusedInWindow() { + return DiffUtil.isFocusedComponentInWindow(myContentPanel) || + DiffUtil.isFocusedComponentInWindow(myToolbar.getComponent()); } - private void requestFocusInternal() { - JComponent component = getPreferredFocusedComponent(); - if (component != null) component.requestFocusInWindow(); + private void requestFocusInWindow() { + DiffUtil.requestFocusInWindow(getPreferredFocusedComponent()); } @NotNull @@ -973,8 +972,8 @@ public abstract class DiffRequestProcessor implements Disposable { } @Override - public boolean isFocused() { - return DiffRequestProcessor.this.isFocused(); + public boolean isFocusedInWindow() { + return DiffRequestProcessor.this.isFocusedInWindow(); } @Override @@ -983,8 +982,8 @@ public abstract class DiffRequestProcessor implements Disposable { } @Override - public void requestFocus() { - DiffRequestProcessor.this.requestFocusInternal(); + public void requestFocusInWindow() { + DiffRequestProcessor.this.requestFocusInWindow(); } @Nullable diff --git a/platform/diff-impl/src/com/intellij/diff/merge/MergeRequestProcessor.java b/platform/diff-impl/src/com/intellij/diff/merge/MergeRequestProcessor.java index 58cf2bd6e977..fc1ab061524d 100644 --- a/platform/diff-impl/src/com/intellij/diff/merge/MergeRequestProcessor.java +++ b/platform/diff-impl/src/com/intellij/diff/merge/MergeRequestProcessor.java @@ -329,13 +329,12 @@ public abstract class MergeRequestProcessor implements Disposable { // Misc // - private boolean isFocused() { - return DiffUtil.isFocusedComponent(myProject, myPanel); + private boolean isFocusedInWindow() { + return DiffUtil.isFocusedComponentInWindow(myPanel); } - private void requestFocusInternal() { - JComponent component = getPreferredFocusedComponent(); - if (component != null) component.requestFocusInWindow(); + private void requestFocusInWindow() { + DiffUtil.requestFocusInWindow(getPreferredFocusedComponent()); } // @@ -461,13 +460,13 @@ public abstract class MergeRequestProcessor implements Disposable { } @Override - public boolean isFocused() { - return MergeRequestProcessor.this.isFocused(); + public boolean isFocusedInWindow() { + return MergeRequestProcessor.this.isFocusedInWindow(); } @Override - public void requestFocus() { - MergeRequestProcessor.this.requestFocusInternal(); + public void requestFocusInWindow() { + MergeRequestProcessor.this.requestFocusInWindow(); } @Override diff --git a/platform/diff-impl/src/com/intellij/diff/merge/MergeUtil.java b/platform/diff-impl/src/com/intellij/diff/merge/MergeUtil.java index ea3d9f626aeb..44e22aced9f6 100644 --- a/platform/diff-impl/src/com/intellij/diff/merge/MergeUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/merge/MergeUtil.java @@ -108,13 +108,13 @@ public class MergeUtil { } @Override - public boolean isFocused() { - return myMergeContext.isFocused(); + public boolean isFocusedInWindow() { + return myMergeContext.isFocusedInWindow(); } @Override - public void requestFocus() { - myMergeContext.requestFocus(); + public void requestFocusInWindow() { + myMergeContext.requestFocusInWindow(); } @Nullable diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java index 292fd733c274..7ff2b8fe980c 100644 --- a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java @@ -668,11 +668,23 @@ public class DiffUtil { IdeFocusManager.getInstance(project).requestFocus(component, true); } + public static boolean isFocusedComponentInWindow(@Nullable Component component) { + if (component == null) return false; + Window window = UIUtil.getWindow(component); + if (window == null) return false; + Component windowFocusOwner = window.getMostRecentFocusOwner(); + return SwingUtilities.isDescendingFrom(windowFocusOwner, component); + } + + public static void requestFocusInWindow(@Nullable Component component) { + if (component != null) component.requestFocusInWindow(); + } + public static void runPreservingFocus(@NotNull FocusableContext context, @NotNull Runnable task) { - boolean hadFocus = context.isFocused(); + boolean hadFocus = context.isFocusedInWindow(); if (hadFocus) KeyboardFocusManager.getCurrentKeyboardFocusManager().clearFocusOwner(); task.run(); - if (hadFocus) context.requestFocus(); + if (hadFocus) context.requestFocusInWindow(); } // diff --git a/platform/diff-impl/tests/com/intellij/diff/merge/MergeTestBase.kt b/platform/diff-impl/tests/com/intellij/diff/merge/MergeTestBase.kt index e218efedb92d..2ce9f94e5e95 100644 --- a/platform/diff-impl/tests/com/intellij/diff/merge/MergeTestBase.kt +++ b/platform/diff-impl/tests/com/intellij/diff/merge/MergeTestBase.kt @@ -342,9 +342,9 @@ abstract class MergeTestBase : HeavyDiffTestCase() { private class MockMergeContext(private val myProject: Project?) : MergeContext() { override fun getProject(): Project? = myProject - override fun isFocused(): Boolean = false + override fun isFocusedInWindow(): Boolean = false - override fun requestFocus() { + override fun requestFocusInWindow() { } override fun finishMerge(result: MergeResult) { diff --git a/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffPreviewPanel.java b/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffPreviewPanel.java index 04790b1a848f..8c3ccde889b1 100644 --- a/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffPreviewPanel.java +++ b/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffPreviewPanel.java @@ -152,12 +152,12 @@ class DiffPreviewPanel implements PreviewPanel { } @Override - public boolean isFocused() { + public boolean isFocusedInWindow() { return false; } @Override - public void requestFocus() { + public void requestFocusInWindow() { } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeViewDiffRequestProcessor.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeViewDiffRequestProcessor.java index cae43290dcc6..a2d600874139 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeViewDiffRequestProcessor.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeViewDiffRequestProcessor.java @@ -151,7 +151,7 @@ public abstract class ChangeViewDiffRequestProcessor extends CacheDiffRequestPro Wrapper selectedChange = myCurrentChange != null ? ContainerUtil.find(selectedChanges, myCurrentChange) : null; if (selectedChange == null) { - if (myCurrentChange != null && isFocused()) { // Do not automatically switch file if focused + if (myCurrentChange != null && getContext().isWindowFocused() && getContext().isFocusedInWindow()) { // Do not automatically switch file if focused if (selectedChanges.size() == 1 && getAllChanges().contains(myCurrentChange)) { selectChange(myCurrentChange); // Restore selection if necessary } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnDiffViewer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnDiffViewer.java index 8d6dcdc887c9..f138006703f9 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnDiffViewer.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnDiffViewer.java @@ -27,7 +27,6 @@ import com.intellij.openapi.util.Key; import com.intellij.ui.EditorNotificationPanel; import com.intellij.ui.JBColor; import com.intellij.ui.components.panels.Wrapper; -import java.util.HashMap; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -43,10 +42,8 @@ import java.awt.*; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; -import java.util.ArrayList; -import java.util.Collections; +import java.util.*; import java.util.List; -import java.util.Map; public class SvnDiffViewer implements DiffViewer { private static final Logger LOG = Logger.getInstance(SvnDiffViewer.class); @@ -327,13 +324,13 @@ public class SvnDiffViewer implements DiffViewer { } @Override - public boolean isFocused() { - return DiffUtil.isFocusedComponent(getProject(), myPropertiesViewer.getComponent()); + public boolean isFocusedInWindow() { + return DiffUtil.isFocusedComponentInWindow(myPropertiesViewer.getComponent()); } @Override - public void requestFocus() { - DiffUtil.requestFocus(getProject(), myPropertiesViewer.getPreferredFocusedComponent()); + public void requestFocusInWindow() { + DiffUtil.requestFocusInWindow(myPropertiesViewer.getPreferredFocusedComponent()); } }