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.
This commit is contained in:
Aleksey Pivovarov
2018-02-19 20:26:20 +03:00
parent d660da119f
commit ce0408fae1
9 changed files with 47 additions and 40 deletions
@@ -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();
}
@@ -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
@@ -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
@@ -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
@@ -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();
}
//
@@ -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) {
@@ -152,12 +152,12 @@ class DiffPreviewPanel implements PreviewPanel {
}
@Override
public boolean isFocused() {
public boolean isFocusedInWindow() {
return false;
}
@Override
public void requestFocus() {
public void requestFocusInWindow() {
}
}
@@ -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
}
@@ -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());
}
}