From 8a2dc52e4bd8ca751d4f5a02e513bb6375a134e2 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Thu, 19 Dec 2019 18:01:24 +0100 Subject: [PATCH] IDEA-229505 Focus is not returned to Editor from Tool window in Float or Window view mode by Esc button GitOrigin-RevId: d5aee42851410aee608387cd43edb129d1e3b2e8 --- .../debugger/ui/impl/DebuggerTreePanel.java | 11 +- .../diff/impl/DiffRequestProcessor.java | 6 + .../diff/merge/MergeRequestProcessor.java | 6 + .../intellij/openapi/wm/IdeFocusManager.java | 17 ++- .../intellij/openapi/wm/ToolWindowManager.kt | 15 --- .../fileEditor/impl/EditorsSplitters.java | 32 +++-- .../impl/FileEditorManagerImpl.java | 40 +++--- .../wm/ex/IdeFocusTraversalPolicy.java | 30 +++-- .../openapi/wm/impl/ToolWindowManagerImpl.kt | 64 ++++++++-- .../com/intellij/openapi/wm/impl/Windows.java | 117 ------------------ .../com/intellij/ui/TabbedPaneWrapper.java | 16 +-- 11 files changed, 140 insertions(+), 214 deletions(-) delete mode 100644 platform/platform-impl/src/com/intellij/openapi/wm/impl/Windows.java diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreePanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreePanel.java index 45c7a25da770..7b6f042c3ab3 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreePanel.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreePanel.java @@ -1,4 +1,4 @@ -// 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. +// Copyright 2000-2019 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. /* * @author Eugene Zhuravlev @@ -23,12 +23,13 @@ import com.intellij.xdebugger.impl.actions.XDebuggerActions; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; import com.sun.jdi.VMDisconnectedException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.awt.*; public abstract class DebuggerTreePanel extends UpdatableDebuggerView implements DataProvider, Disposable { public static final DataKey DATA_KEY = DataKey.create("DebuggerPanel"); - + private final SingleAlarm myRebuildAlarm = new SingleAlarm(() -> { try { final DebuggerContextImpl context = getContext(); @@ -59,6 +60,12 @@ public abstract class DebuggerTreePanel extends UpdatableDebuggerView implements myTree.addMouseListener(popupHandler); setFocusTraversalPolicy(new IdeFocusTraversalPolicy() { + @Nullable + @Override + protected Project getProject() { + return project; + } + @Override public Component getDefaultComponent(Container focusCycleRoot) { return myTree; 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 b999c475b1e0..6ac22f355cb0 100644 --- a/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java +++ b/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java @@ -1009,6 +1009,12 @@ public abstract class DiffRequestProcessor implements Disposable { if (component == null) return null; return IdeFocusTraversalPolicy.getPreferredFocusedComponent(component, this); } + + @Nullable + @Override + protected Project getProject() { + return myProject; + } } private class MyDiffContext extends DiffContextEx { 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 c548de986665..dc7ee13849cc 100644 --- a/platform/diff-impl/src/com/intellij/diff/merge/MergeRequestProcessor.java +++ b/platform/diff-impl/src/com/intellij/diff/merge/MergeRequestProcessor.java @@ -546,6 +546,12 @@ public abstract class MergeRequestProcessor implements Disposable { if (component == null) return null; return IdeFocusTraversalPolicy.getPreferredFocusedComponent(component, this); } + + @Nullable + @Override + protected Project getProject() { + return myProject; + } } private class MyDiffContext extends MergeContextEx { diff --git a/platform/platform-api/src/com/intellij/openapi/wm/IdeFocusManager.java b/platform/platform-api/src/com/intellij/openapi/wm/IdeFocusManager.java index 4d36fcbaff5c..086fa9125906 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/IdeFocusManager.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/IdeFocusManager.java @@ -10,7 +10,7 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.ExpirableRunnable; -import com.intellij.util.ui.UIUtil; +import com.intellij.ui.ComponentUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -166,18 +166,15 @@ public abstract class IdeFocusManager implements FocusRequestor { } @NotNull - public static IdeFocusManager findInstanceByComponent(@NotNull Component c) { - final IdeFocusManager instance = findByComponent(c); - return instance != null ? instance : findInstanceByContext(null); + public static IdeFocusManager findInstanceByComponent(@NotNull Component component) { + IdeFocusManager instance = findByComponent(component); + return instance == null ? findInstanceByContext(null) : instance; } @Nullable - private static IdeFocusManager findByComponent(Component c) { - final Component parent = UIUtil.findUltimateParent(c); - if (parent instanceof IdeFrame) { - return getInstanceSafe(((IdeFrame)parent).getProject()); - } - return null; + private static IdeFocusManager findByComponent(@NotNull Component component) { + Component parent = ComponentUtil.findUltimateParent(component); + return parent instanceof IdeFrame ? getInstanceSafe(((IdeFrame)parent).getProject()) : null; } diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.kt b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.kt index cb8d384f488b..d66b45d204a0 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.kt +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.kt @@ -18,19 +18,6 @@ abstract class ToolWindowManager { @JvmStatic fun getInstance(project: Project): ToolWindowManager = project.getService(ToolWindowManager::class.java) - @JvmStatic - fun getActiveToolWindow(): ToolWindow? { - val frame = IdeFocusManager.getGlobalInstance().lastFocusedFrame - val project = frame?.project - if (project == null || project.isDisposed || project.isDefault) { - return null - } - - val toolWindowManager = getInstance(project) - val activeId = toolWindowManager.activeToolWindowId - return activeId?.let { toolWindowManager.getToolWindow(it) } - } - @JvmStatic fun getActiveId(): String? { val project = IdeFocusManager.getGlobalInstance().lastFocusedFrame?.project ?: return null @@ -112,8 +99,6 @@ abstract class ToolWindowManager { @Deprecated("Use ToolWindowFactory and toolWindow extension point") abstract fun unregisterToolWindow(id: String) - /** - */ abstract fun activateEditorComponent() /** diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java index b7baa72435dd..0453e0822e6f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java @@ -557,6 +557,12 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener } return IdeFocusTraversalPolicy.getPreferredFocusedComponent(EditorsSplitters.this, this); } + + @NotNull + @Override + protected Project getProject() { + return myManager.getProject(); + } } @Nullable @@ -964,16 +970,17 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener } @Nullable - private static EditorsSplitters getSplittersToFocus() { + private static EditorsSplitters getSplittersToFocus(@Nullable Project project) { Window activeWindow = WindowManagerEx.getInstanceEx().getMostRecentFocusedWindow(); if (activeWindow instanceof FloatingDecorator) { - IdeFocusManager ideFocusManager = IdeFocusManager.findInstanceByComponent(activeWindow); - IdeFrame lastFocusedFrame = ideFocusManager.getLastFocusedFrame(); + IdeFrame lastFocusedFrame = IdeFocusManager.findInstanceByComponent(activeWindow).getLastFocusedFrame(); JComponent frameComponent = lastFocusedFrame != null ? lastFocusedFrame.getComponent() : null; - Window lastFocusedWindow = frameComponent != null ? SwingUtilities.getWindowAncestor(frameComponent) : null; + Window lastFocusedWindow = frameComponent == null ? null : SwingUtilities.getWindowAncestor(frameComponent); activeWindow = ObjectUtils.notNull(lastFocusedWindow, activeWindow); - Project project = lastFocusedFrame == null ? null : lastFocusedFrame.getProject(); + if (project == null) { + project = lastFocusedFrame == null ? null : lastFocusedFrame.getProject(); + } FileEditorManagerEx fileEditorManager = project == null || project.isDisposed() ? null : FileEditorManagerEx.getInstanceEx(project); if (fileEditorManager == null) { return null; @@ -983,7 +990,9 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener } if (activeWindow instanceof IdeFrame.Child) { - Project project = ((IdeFrame.Child)activeWindow).getProject(); + if (project == null) { + project = ((IdeFrame.Child)activeWindow).getProject(); + } return getSplittersForProject(WindowManager.getInstance().getFrame(project), project); } @@ -1006,8 +1015,8 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener } @Nullable - public static JComponent findDefaultComponentInSplitters() { - EditorsSplitters splittersToFocus = getSplittersToFocus(); + public static JComponent findDefaultComponentInSplitters(@Nullable Project project) { + EditorsSplitters splittersToFocus = getSplittersToFocus(project); if (splittersToFocus == null) { return null; } @@ -1023,10 +1032,11 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener return null; } - public static boolean focusDefaultComponentInSplittersIfPresent() { - JComponent defaultFocusedComponentInEditor = findDefaultComponentInSplitters(); + public static boolean focusDefaultComponentInSplittersIfPresent(@NotNull Project project) { + JComponent defaultFocusedComponentInEditor = findDefaultComponentInSplitters(project); if (defaultFocusedComponentInEditor != null) { - defaultFocusedComponentInEditor.requestFocusInWindow(); + // not requestFocus because if floating or windowed tool window is deactivated (or, ESC pressed to focus editor), then we should focus our window + defaultFocusedComponentInEditor.requestFocus(); return true; } return false; diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java index 3b93ff048c03..546e12bbe1f1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java @@ -54,7 +54,6 @@ import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import com.intellij.openapi.vfs.newvfs.events.VFileMoveEvent; import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent; import com.intellij.openapi.wm.IdeFocusManager; -import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.ex.StatusBarEx; import com.intellij.reference.SoftReference; @@ -902,7 +901,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Persis Window windowAncestor = SwingUtilities.getWindowAncestor(window.myPanel); if (windowAncestor != null && windowAncestor.equals(KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow())) { - ToolWindowManager.getInstance(myProject).activateEditorComponent(); + EditorsSplitters.focusDefaultComponentInSplittersIfPresent(myProject); IdeFocusManager.getInstance(myProject).toFront(window.getOwner()); } } @@ -1458,23 +1457,21 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Persis return; } - ToolWindowManager.getInstance(myProject).invokeLater(() -> { - if (!myProject.isDisposed()) { - CommandProcessor.getInstance().executeCommand(myProject, () -> { - ApplicationManager.getApplication().invokeLater(() -> { - long currentTime = System.nanoTime(); - Long startTime = myProject.getUserData(ProjectImpl.CREATION_TIME); - if (startTime != null) { - long time = (currentTime - startTime.longValue()) / 1000000; - LifecycleUsageTriggerCollector.onProjectOpenFinished(myProject, time); + ApplicationManager.getApplication().invokeLater(() -> { + CommandProcessor.getInstance().executeCommand(myProject, () -> { + ApplicationManager.getApplication().invokeLater(() -> { + long currentTime = System.nanoTime(); + Long startTime = myProject.getUserData(ProjectImpl.CREATION_TIME); + if (startTime != null) { + long time = (currentTime - startTime.longValue()) / 1000000; + LifecycleUsageTriggerCollector.onProjectOpenFinished(myProject, time); - LOG.info("Project opening took " + time + " ms"); - } - }, myProject.getDisposed()); - // group 1 - }, "", null); - } - }); + LOG.info("Project opening took " + time + " ms"); + } + }, myProject.getDisposed()); + // group 1 + }, "", null); + }, myProject.getDisposed()); }); } @@ -1602,9 +1599,10 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Persis final FileEditor selectedEditor = editor.getSelectedEditor(); for (int i = editors.length - 1; i >= 0; i--) { - final FileEditor editor1 = editors[i]; - final FileEditorProvider provider = providers[i]; - if (!editor.equals(selectedEditor)) { // we already notified the myEditor (when fire event) + FileEditor editor1 = editors[i]; + FileEditorProvider provider = providers[i]; + if (!editor.equals(selectedEditor)) { + // we already notified the myEditor (when fire event) if (selectedEditor.equals(editor1)) { editor1.deselectNotify(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java index 592ebd7b1d62..e4da750daa9c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java @@ -4,6 +4,7 @@ package com.intellij.openapi.wm.ex; import com.intellij.openapi.editor.impl.EditorComponentImpl; import com.intellij.openapi.fileEditor.impl.EditorWindowHolder; import com.intellij.openapi.fileEditor.impl.EditorsSplitters; +import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -30,30 +31,34 @@ public class IdeFocusTraversalPolicy extends LayoutFocusTraversalPolicy { @Override public Component getComponentAfter(Container aContainer, Component aComponent) { Component after = super.getComponentAfter(aContainer, aComponent); - Component defaultFocusableComponent = findDefaultFocusedComponentIfSplitters(after); - if (defaultFocusableComponent != null) return defaultFocusableComponent; - if (after != null) return after.isFocusable() ? after : findFocusableComponentIn((JComponent)after, null); - return findFocusableComponentIn(aContainer, aComponent); + return doFind(aContainer, aComponent, after); } @Override public Component getComponentBefore(Container aContainer, Component aComponent) { Component before = super.getComponentBefore(aContainer, aComponent); - Component defaultFocusableComponent = findDefaultFocusedComponentIfSplitters(before); - if (defaultFocusableComponent != null) return defaultFocusableComponent; - if (before != null) return before.isFocusable() ? before : findFocusableComponentIn((JComponent)before, null); - return findFocusableComponentIn(aContainer, aComponent); + return doFind(aContainer, aComponent, before); } @Nullable - private static Component findDefaultFocusedComponentIfSplitters(Component componentToSearchInto) { - if (componentToSearchInto instanceof EditorsSplitters) { - JComponent defaultFocusableComponent = EditorsSplitters.findDefaultComponentInSplitters(); + protected Project getProject() { + return null; + } + + @Nullable + private Component doFind(Container aContainer, Component aComponent, @Nullable Component siblingComponent) { + if (siblingComponent == null) { + return findFocusableComponentIn(aContainer, aComponent); + } + + if (siblingComponent instanceof EditorsSplitters) { + Component defaultFocusableComponent = EditorsSplitters.findDefaultComponentInSplitters(getProject()); if (defaultFocusableComponent != null) { return defaultFocusableComponent; } } - return null; + + return siblingComponent.isFocusable() ? siblingComponent : findFocusableComponentIn((JComponent)siblingComponent, null); } /** @@ -141,7 +146,6 @@ public class IdeFocusTraversalPolicy extends LayoutFocusTraversalPolicy { return false; } - /* TODO[anton,vova] implement Policy in Editor component instead */ if (component instanceof EditorComponentImpl || component instanceof EditorWindowHolder) { return true; } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.kt index ac20f62c8b18..6ad474815c5b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.kt @@ -70,7 +70,6 @@ import java.beans.PropertyChangeListener import java.util.* import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicReference -import java.util.function.Predicate import javax.swing.* import javax.swing.event.HyperlinkEvent import javax.swing.event.HyperlinkListener @@ -167,18 +166,14 @@ open class ToolWindowManagerImpl(val project: Project) : ToolWindowManagerEx(), } }) - Windows.ToolWindowProvider(Windows.Signal(Predicate { event -> - event.id == FocusEvent.FOCUS_LOST || event.id == FocusEvent.FOCUS_GAINED || event.id == MouseEvent.MOUSE_PRESSED || event.id == KeyEvent.KEY_PRESSED - })) - .withEscAction() - .handleFocusLostOnPinned { toolWindowId -> + addFocusLostListener(pinnedWindowFocusLostHandler = { toolWindowId -> process { manager -> val entry = manager.idToEntry.get(toolWindowId) ?: return@process val info = manager.layout.getInfo(toolWindowId) ?: return@process manager.doDeactivateToolWindow(info, entry) } } - .bind(ApplicationManager.getApplication()) + ) connection.subscribe(KeymapManagerListener.TOPIC, object : KeymapManagerListener { override fun activeKeymapChanged(keymap: Keymap?) { @@ -500,8 +495,9 @@ open class ToolWindowManagerImpl(val project: Project) : ToolWindowManagerEx(), } override fun activateEditorComponent() { - if (!EditorsSplitters.focusDefaultComponentInSplittersIfPresent()) { - frame?.rootPane?.requestFocusInWindow() + if (!EditorsSplitters.focusDefaultComponentInSplittersIfPresent(project)) { + // see note about requestFocus in focusDefaultComponentInSplittersIfPresent + frame?.rootPane?.requestFocus() } } @@ -1907,4 +1903,52 @@ private const val LAYOUT_TO_RESTORE = "layout-to-restore" internal enum class ToolWindowProperty { TITLE, ICON, AVAILABLE, STRIPE_TITLE -} \ No newline at end of file +} + +private fun addFocusLostListener(pinnedWindowFocusLostHandler: (String) -> Unit) { + val listener = AWTEventListener { event -> + val eventId = event.id + if (event !is FocusEvent || !(eventId == FocusEvent.FOCUS_LOST || eventId == FocusEvent.FOCUS_LOST || eventId == FocusEvent.FOCUS_GAINED)) { + return@AWTEventListener + } + + val id = ToolWindowManager.getActiveId() ?: return@AWTEventListener + + // let's check that it is a toolwindow who loses the focus + if (event.oppositeComponent != null && isInActiveToolWindow(event.source) && !isInActiveToolWindow(event.oppositeComponent)) { + // a toolwindow lost focus + val activeToolWindow = getActiveToolWindow() + val focusGoesToPopup = JBPopupFactory.getInstance().getParentBalloonFor(event.oppositeComponent) != null + if (!event.isTemporary && + !focusGoesToPopup && activeToolWindow != null && + (activeToolWindow.isAutoHide || activeToolWindow.type == ToolWindowType.SLIDING)) { + pinnedWindowFocusLostHandler(id) + } + } + } + Toolkit.getDefaultToolkit().addAWTEventListener(listener, AWTEvent.FOCUS_EVENT_MASK) +} + +private fun isInActiveToolWindow(component: Any?): Boolean { + val activeToolWindow = getActiveToolWindow() ?: return false + var source = if (component is JComponent) component else null + val activeToolWindowComponent = activeToolWindow.getComponentIfInitialized() + if (activeToolWindowComponent != null) { + while (source != null && source !== activeToolWindowComponent) { + source = if (source.parent != null && source.parent is JComponent) source.parent as JComponent else null + } + } + return source != null +} + +private fun getActiveToolWindow(): ToolWindowImpl? { + val frame = IdeFocusManager.getGlobalInstance().lastFocusedFrame + val project = frame?.project + if (project == null || project.isDisposed || project.isDefault) { + return null + } + + val toolWindowManager = ToolWindowManager.getInstance(project) + val activeId = toolWindowManager.activeToolWindowId + return activeId?.let { toolWindowManager.getToolWindow(it) as ToolWindowImpl } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/Windows.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/Windows.java deleted file mode 100644 index e0230e0c573f..000000000000 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/Windows.java +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2000-2019 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.impl; - -import com.intellij.openapi.Disposable; -import com.intellij.openapi.ui.popup.JBPopupFactory; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.wm.ToolWindow; -import com.intellij.openapi.wm.ToolWindowManager; -import com.intellij.openapi.wm.ToolWindowType; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.AWTEventListener; -import java.awt.event.FocusEvent; -import java.util.function.Consumer; -import java.util.function.Predicate; - -@ApiStatus.Internal -public final class Windows { - public final static class ToolWindowProvider { - private final Signal mySignal; - - private Consumer pinnedWindowFocusLostHandler; - - public ToolWindowProvider(@NotNull Signal signal) { - mySignal = signal; - } - - public ToolWindowProvider handleFocusLostOnPinned(@NotNull Consumer value) { - pinnedWindowFocusLostHandler = value; - return this; - } - - public ToolWindowProvider withEscAction() { - return this; - } - - public static boolean isInActiveToolWindow(@Nullable Object component) { - ToolWindowImpl activeToolWindow = (ToolWindowImpl)ToolWindowManager.getActiveToolWindow(); - if (activeToolWindow == null) { - return false; - } - - JComponent source = component instanceof JComponent ? (JComponent)component : null; - JComponent activeToolWindowComponent = activeToolWindow.getComponentIfInitialized(); - if (activeToolWindowComponent != null) { - while (source != null && source != activeToolWindowComponent) { - source = ((source.getParent() != null) && (source.getParent() instanceof JComponent)) ? ((JComponent)source.getParent()) : null; - } - } - return source != null; - } - - public void bind(@NotNull Disposable parentDisposable) { - AWTEventListener listener = new AWTEventListener() { - @Override - public void eventDispatched(AWTEvent event) { - if (!mySignal.isAppropriatePredicate.test(event)) { - return; - } - - // Find toolwindows from the event - // pass the toolwindow to the appropriate consumers - - // FocusEvent - // for now we are interested in focus lost events - String id = ToolWindowManager.getActiveId(); - if (event.getID() != FocusEvent.FOCUS_LOST) { - return; - } - // let's check that it is a toolwindow who loses the focus - - FocusEvent focusEvent = (FocusEvent)event; - - if (isInActiveToolWindow(focusEvent.getSource()) - && !isInActiveToolWindow(focusEvent.getOppositeComponent()) - && focusEvent.getOppositeComponent() != null) { - //System.err.println("Tool window is loosing focus: " + ToolWindowManager.getActiveToolWindow().getStripeTitle()); - - // A toolwindow lost focus - ToolWindow activeToolWindow = ToolWindowManager.getActiveToolWindow(); - boolean focusGoesToPopup = JBPopupFactory.getInstance().getParentBalloonFor(focusEvent.getOppositeComponent()) != null; - if (!focusEvent.isTemporary() && - !focusGoesToPopup && - activeToolWindow != null && - (activeToolWindow.isAutoHide() || activeToolWindow.getType() == ToolWindowType.SLIDING)) { - pinnedWindowFocusLostHandler.accept(id); - } - } - } - }; - - Toolkit.getDefaultToolkit().addAWTEventListener(listener, AWTEvent.MOUSE_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK | AWTEvent.KEY_EVENT_MASK); - Disposer.register(parentDisposable, new Disposable() { - @Override - public void dispose() { - Toolkit.getDefaultToolkit().removeAWTEventListener(listener); - } - }); - } - } - - static final class Signal { - private final Predicate isAppropriatePredicate; - - Signal(Predicate isAppropriatePredicate) { - this.isAppropriatePredicate = isAppropriatePredicate; - } - - public boolean appropriate(AWTEvent event) { - return isAppropriatePredicate.test(event); - } - } -} diff --git a/platform/platform-impl/src/com/intellij/ui/TabbedPaneWrapper.java b/platform/platform-impl/src/com/intellij/ui/TabbedPaneWrapper.java index dd34522bc601..b53951b1c3f1 100644 --- a/platform/platform-impl/src/com/intellij/ui/TabbedPaneWrapper.java +++ b/platform/platform-impl/src/com/intellij/ui/TabbedPaneWrapper.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 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.ui; import com.intellij.openapi.Disposable;