linux focus stealing: toFront() is done vie IdeFocusManager
[fedora-idea.git] / platform / platform-impl / src / com / intellij / openapi / wm / impl / commands / RequestFocusInToolWindowCmd.java
blob6528fd5bf1d11f89ad6d1de28621b71588b9a4a7
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.openapi.wm.impl.commands;
18 import com.intellij.openapi.diagnostic.Logger;
19 import com.intellij.openapi.util.ActionCallback;
20 import com.intellij.openapi.util.Expirable;
21 import com.intellij.openapi.wm.FocusCommand;
22 import com.intellij.openapi.wm.FocusWatcher;
23 import com.intellij.openapi.wm.IdeFocusManager;
24 import com.intellij.openapi.wm.WindowManager;
25 import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
26 import com.intellij.openapi.wm.impl.FloatingDecorator;
27 import com.intellij.openapi.wm.impl.ToolWindowImpl;
28 import com.intellij.openapi.wm.impl.WindowManagerImpl;
29 import com.intellij.openapi.wm.impl.WindowWatcher;
31 import javax.swing.*;
32 import java.awt.*;
34 /**
35 * Requests focus for the specified tool window.
37 * @author Vladimir Kondratyev
39 public final class RequestFocusInToolWindowCmd extends FinalizableCommand {
40 private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.commands.RequestFocusInToolWindowCmd");
41 private final ToolWindowImpl myToolWindow;
42 private final FocusWatcher myFocusWatcher;
44 private final boolean myForced;
45 private IdeFocusManager myFocusManager;
46 private Expirable myTimestamp;
48 public RequestFocusInToolWindowCmd(IdeFocusManager focusManager, final ToolWindowImpl toolWindow, final FocusWatcher focusWatcher, final Runnable finishCallBack, boolean forced) {
49 super(finishCallBack);
50 myToolWindow = toolWindow;
51 myFocusWatcher = focusWatcher;
52 myForced = forced;
53 myFocusManager = focusManager;
55 myTimestamp = myFocusManager.getTimestamp(true);
58 public final void run() {
59 myToolWindow.getActivation().doWhenDone(new Runnable() {
60 public void run() {
61 processRequestFocus();
63 });
66 private void processRequestFocus() {
67 try {
69 if (myTimestamp.isExpired()) {
70 return;
73 Component preferredFocusedComponent = myFocusWatcher.getFocusedComponent();
75 if (preferredFocusedComponent == null && myToolWindow.getContentManager().getSelectedContent() != null) {
76 preferredFocusedComponent = myToolWindow.getContentManager().getSelectedContent().getPreferredFocusableComponent();
77 if (preferredFocusedComponent != null) {
78 preferredFocusedComponent = IdeFocusTraversalPolicy.getPreferredFocusedComponent((JComponent)preferredFocusedComponent);
82 if (preferredFocusedComponent == null) {
83 preferredFocusedComponent = myFocusWatcher.getNearestFocusableComponent();
84 if (preferredFocusedComponent instanceof JComponent) {
85 preferredFocusedComponent = IdeFocusTraversalPolicy.getPreferredFocusedComponent((JComponent)preferredFocusedComponent);
89 if (preferredFocusedComponent != null) {
90 // When we get remembered component this component can be already invisible
91 if (!preferredFocusedComponent.isShowing()) {
92 preferredFocusedComponent = null;
96 if (preferredFocusedComponent == null) {
97 final JComponent component = myToolWindow.getComponent();
98 preferredFocusedComponent = IdeFocusTraversalPolicy.getPreferredFocusedComponent(component);
101 // Try to focus component which is preferred one for the tool window
102 if (preferredFocusedComponent != null) {
103 requestFocus(preferredFocusedComponent).doWhenDone(new Runnable() {
104 public void run() {
105 bringOwnerToFront();
109 else {
110 // If there is no preferred component then try to focus tool window itself
111 final JComponent componentToFocus = myToolWindow.getComponent();
112 requestFocus(componentToFocus).doWhenDone(new Runnable() {
113 public void run() {
114 bringOwnerToFront();
119 finally {
120 finish();
124 private void bringOwnerToFront() {
125 final Window owner = SwingUtilities.getWindowAncestor(myToolWindow.getComponent());
126 //if (owner == null) {
127 // System.out.println("owner = " + owner);
128 // return;
130 // if owner is active window or it has active child window which isn't floating decorator then
131 // don't bring owner window to font. If we will make toFront every time then it's possible
132 // the following situation:
133 // 1. user prform refactoring
134 // 2. "Do not show preview" dialog is popping up.
135 // 3. At that time "preview" tool window is being activated and modal "don't show..." dialog
136 // isn't active.
137 if (owner != null && owner.getFocusOwner() == null) {
138 final Window activeWindow = getActiveWindow(owner.getOwnedWindows());
139 if (activeWindow == null || (activeWindow instanceof FloatingDecorator)) {
140 LOG.debug("owner.toFront()");
141 //Thread.dumpStack();
142 //System.out.println("------------------------------------------------------");
143 owner.toFront();
149 private ActionCallback requestFocus(final Component c) {
150 ActionCallback result = new ActionCallback();
151 final Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner();
152 if (owner != null && owner == c) {
153 myManager.getFocusManager().requestFocus(new FocusCommand() {
154 public ActionCallback run() {
155 return new ActionCallback.Done();
157 }, myForced).doWhenProcessed(new Runnable() {
158 public void run() {
159 updateToolWindow(c);
161 }).notify(result);
163 else {
164 myManager.getFocusManager().requestFocus(new FocusCommand.ByComponent(c, myToolWindow.getComponent()), myForced).doWhenProcessed(new Runnable() {
165 public void run() {
166 updateToolWindow(c);
168 }).notify(result);
171 return result;
174 private void updateToolWindow(Component c) {
175 if (c.isFocusOwner()) {
176 myFocusWatcher.setFocusedComponentImpl(c);
177 if (myToolWindow.isAvailable() && !myToolWindow.isActive()) {
178 myToolWindow.activate(null, true, false);
182 updateFocusedComponentForWatcher(c);
185 private void updateFocusedComponentForWatcher(final Component c) {
186 final WindowWatcher watcher = ((WindowManagerImpl)WindowManager.getInstance()).getWindowWatcher();
187 final FocusWatcher focusWatcher = watcher.getFocusWatcherFor(c);
188 if (focusWatcher != null && c.isFocusOwner()) {
189 focusWatcher.setFocusedComponentImpl(c);
194 * @return first active window from hierarchy with specified roots. Returns <code>null</code>
195 * if there is no active window in the hierarchy.
197 private Window getActiveWindow(final Window[] windows) {
198 for (int i = 0; i < windows.length; i++) {
199 Window window = windows[i];
200 if (window.isShowing() && window.isActive()) {
201 return window;
203 window = getActiveWindow(window.getOwnedWindows());
204 if (window != null) {
205 return window;
208 return null;