Source code: com/flexstor/common/awt/FlexFocusManager.java
1 /*
2 * FlexFocusManager.java
3 *
4 * Copyright $Date: 2003/08/11 02:22:32 $ FLEXSTOR.net Inc.
5 *
6 * This work is licensed for use and distribution under license terms found at
7 * http://www.flexstor.org/license.html
8 *
9 */
10
11 package com.flexstor.common.awt;
12
13 /**
14 * Posted as a workaround on the SUN bug parade for several focus bugs.
15 *
16 * A brute force method i have found to get around this
17 * bug, though im not crazy about it....it repeatedly
18 * calls requestFocus in successive threads (since requestFocus
19 * does not take effect until its current thread yields [or dies? hmm])
20 *
21 * Various methods are used to determine if the component
22 * actually got the focus or not, and if a compound-component
23 * (that proxies requestFocus to a child component) is the target,
24 * it figures that out also.
25 */
26
27
28 import java.awt.Component;
29 import java.awt.Container;
30 import java.awt.Window;
31 import java.awt.event.FocusAdapter;
32 import java.awt.event.FocusEvent;
33
34 /**
35 * (almost) Foolproof component focus setter, will repeatedly call requestFocus for a
36 * component in a different thread each time.
37 * Uses getCurrentFocus() and focusGained methods to check for success.
38 * Brute forces its way through a myriad of
39 * jdk bugs that put the focus all over the place, kill the requestFocus method, etc.
40 */
41
42 public class FlexFocusManager
43 extends FocusAdapter
44 implements Runnable
45 {
46 boolean focusGained = false;
47 Window surface;
48 Component targetfocus;
49 Component currentfocus;
50 int recursion = 0;
51 int countdown; // additional reqfocus calls after its hit
52
53 public FlexFocusManager(Component targetfocus)
54 {
55 this(findWindow(targetfocus),targetfocus);
56 }
57
58 public FlexFocusManager(Window surface,Component targetfocus)
59 {
60 this.surface=surface;
61 this.targetfocus=targetfocus;
62 }
63
64 private static Window findWindow(Component c)
65 {
66 while (c!=null && !(c instanceof Window))
67 c=c.getParent();
68 if (c!=null)
69 return (Window)c;
70 else
71 return null;
72 }
73
74 public void setFocus()
75 {
76 if (surface == null)
77 return;
78
79 if (targetfocus == null)
80 targetfocus = getDefaultFocusComponent(surface);
81 if (targetfocus == null)
82 return;
83
84 // send a focus lost to the current focus
85 currentfocus = surface.getFocusOwner();
86 if (currentfocus != null)
87 {
88 //Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(
89 currentfocus.dispatchEvent(
90 new FocusEvent(currentfocus,FocusEvent.FOCUS_LOST,false));
91 }
92 focusGained = false;
93 recursion = 0;
94 countdown = 3;
95 targetfocus.addFocusListener(this);
96
97 new Thread(this).start();
98 }
99
100 public void focusGained(FocusEvent e)
101 {
102 focusGained=true;
103 targetfocus.removeFocusListener(this);
104 }
105
106 private void reqFocus()
107 {
108 recursion++;
109 if (recursion > 20)
110 {
111 //System.err.println("FocusSetter recursion count exceeded 20");
112 recursion=0;
113 countdown=0;
114 return;
115 }
116
117 // check if the component has focus
118 currentfocus=surface.getFocusOwner();
119 if (isEqualOrChild(currentfocus, targetfocus))
120 {
121 countdown--;
122 if (countdown<=0)
123 {
124 recursion=0;
125 return;
126 }
127 }
128
129 // check if the component got a focusgained event
130 if (focusGained)
131 {
132 countdown--;
133 if (countdown<=0)
134 {
135 recursion=0;
136 return;
137 }
138 }
139
140 // try requesting focus again
141 //new Thread(this).start();
142 targetfocus.requestFocus();
143 }
144
145 public void run()
146 {
147 while(countdown > 0)
148 {
149 //targetfocus.requestFocus();
150 //System.out.println("FocusManager: requestFocus on " + targetfocus);
151 reqFocus();
152 try {Thread.currentThread().sleep(200);}catch (Exception e9) {}
153 }
154 //System.out.println("FocusManager: ended on " + targetfocus);
155 }
156
157
158 // determine if a==b or a is a child of b
159 private static boolean isEqualOrChild(Component currentFocus,Component targetFocus)
160 {
161 Container c;
162 if (targetFocus instanceof Container)
163 c = (Container)targetFocus;
164 else
165 return (currentFocus == targetFocus);
166
167 while (currentFocus != null && currentFocus != targetFocus)
168 currentFocus = currentFocus.getParent();
169
170 return (currentFocus!=null);
171 }
172
173 public static Component getDefaultFocusComponent(Container start)
174 {
175 int len=start.getComponentCount();
176
177 if (len == 0)
178 return null;
179
180 for (int i=0; i<len; i++)
181 {
182 Component c=start.getComponent(i);
183
184 // NOTE: isFocusTraversable is sometimes false for some java.awt.* components
185 // in some JDK's...you might want to replace this with a different method
186 if (c.isFocusTraversable())
187 return c;
188 else
189 if (c instanceof Container)
190 {
191 c = getDefaultFocusComponent((Container)c);
192 if (c == null)
193 continue;
194 else
195 return c;
196 }
197 }
198 return null;
199 }
200
201 } // end of class
202
203