001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.awt;
019:
020: import java.awt.event.FocusEvent;
021: import java.awt.event.InputEvent;
022: import java.awt.event.KeyEvent;
023: import java.awt.event.WindowEvent;
024: import java.util.Collections;
025: import java.util.HashSet;
026: import java.util.Set;
027:
028: public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
029:
030: private static Window prevFocusedWindow;
031: private static Component prevFocusOwner;
032: private static Window prevActiveWindow;
033: private static boolean consumeKeyTyped;
034:
035: private final Toolkit toolkit = Toolkit.getDefaultToolkit();
036:
037: static boolean isActivateable(Window w) {
038: // return true if activeWindow can be set to w
039: return ((w == null) || w.isActivateable());
040: }
041:
042: @Override
043: protected void dequeueKeyEvents(long a0, Component a1) {
044: toolkit.lockAWT();
045: try {
046: // currently do nothing, this method
047: // is never called by AWT implementation
048: } finally {
049: toolkit.unlockAWT();
050: }
051: }
052:
053: @Override
054: protected void discardKeyEvents(Component a0) {
055: toolkit.lockAWT();
056: try {
057: // currently do nothing, this method
058: // is never called by AWT implementation
059: } finally {
060: toolkit.unlockAWT();
061: }
062: }
063:
064: @Override
065: public boolean dispatchEvent(AWTEvent e) {
066: if (e instanceof KeyEvent) {
067: KeyEvent ke = (KeyEvent) e;
068: return (preProcessKeyEvent(ke) || dispatchKeyEvent(ke));
069: } else if (e instanceof FocusEvent) {
070: FocusEvent fe = (FocusEvent) e;
071: return dispatchFocusEvent(fe);
072: } else if (e instanceof WindowEvent) {
073: WindowEvent we = (WindowEvent) e;
074: return dispatchWindowEvent(we);
075: } else if (e == null) {
076: throw new NullPointerException();
077: }
078: return false;
079: }
080:
081: private boolean preProcessKeyEvent(KeyEvent ke) {
082: // first pass event to every key event dispatcher:
083: for (KeyEventDispatcher ked : getKeyEventDispatchers()) {
084: if (ked.dispatchKeyEvent(ke)) {
085: return true;
086: }
087: }
088:
089: return false;
090: }
091:
092: private boolean dispatchFocusEvent(FocusEvent fe) {
093: boolean doRedispatch = false;
094: Component comp = fe.getComponent();
095: toolkit.lockAWT();
096: try {
097: Component newFocusOwner = focusOwner;
098: switch (fe.getID()) {
099: case FocusEvent.FOCUS_GAINED:
100: if ((focusedWindow != null)
101: && (comp.getWindowAncestor() == focusedWindow)) {
102:
103: newFocusOwner = comp;
104: }
105: break;
106: case FocusEvent.FOCUS_LOST:
107: // Focus changes in which a Component
108: // loses focus to itself must be discarded
109: if (comp == fe.getOppositeComponent()) {
110: return true;
111: }
112: if (focusOwner != null) {
113: Container hwContainer = ((comp instanceof Container) ? (Container) comp
114: : null);
115:
116: if ((hwContainer != null)
117: && hwContainer.isAncestorOf(focusOwner)) {
118:
119: comp = focusOwner;
120: fe.setSource(comp);
121: }
122:
123: if (comp == focusOwner) {
124: newFocusOwner = null;
125: prevFocusOwner = focusOwner;
126: }
127: }
128: break;
129: default:
130: return false;
131: }
132: if (newFocusOwner == focusOwner) {
133: return true;
134: }
135: boolean temp = fe.isTemporary();
136: setFocusOwner(newFocusOwner, temp);
137:
138: // rejection recovery [if (newFocusOwner != focusOwner)]
139: boolean success = (newFocusOwner == getFocusOwner());
140:
141: if (success) {
142: doRedispatch = true;
143: } else {
144: recoverFocusOwner(temp);
145: }
146: } finally {
147: toolkit.unlockAWT();
148: }
149: if (doRedispatch) {
150: redispatchEvent(comp, fe);
151: }
152: return true;
153: }
154:
155: private boolean recoverFocusOwner(boolean temp) {
156: if (focusOwner == null) {
157: return true;
158: }
159:
160: // focus owner will be reset to the Component
161: // which was previously the focus owner
162: boolean success = prevFocusOwner.requestFocusImpl(temp, true,
163: true);
164:
165: // If that is not possible,
166: // then it will be reset to the next Component
167: // in the focus traversal cycle after the previous focus owner
168: if (!success) {
169: Container root = prevFocusOwner.getFocusCycleRootAncestor();
170: Component newFocusOwner = root.getFocusTraversalPolicy()
171: .getComponentAfter(root, focusOwner);
172: success = ((newFocusOwner != null) && newFocusOwner
173: .requestFocusImpl(temp, true, true));
174: }
175:
176: // If that is also not possible,
177: // then the KeyboardFocusManager will clear the global focus owner
178: if (!success) {
179: clearGlobalFocusOwner();
180: }
181: return success;
182: }
183:
184: private void setFocusOwner(Component newFocusOwner, boolean temp) {
185: if (temp) {
186: setGlobalFocusOwner(newFocusOwner);
187: } else {
188: setGlobalPermanentFocusOwner(newFocusOwner);
189: }
190: }
191:
192: private boolean dispatchWindowEvent(WindowEvent we) {
193: Window win = we.getWindow();
194: Window opposite = we.getOppositeWindow();
195: int id = we.getID();
196: switch (id) {
197: case WindowEvent.WINDOW_ACTIVATED:
198: case WindowEvent.WINDOW_DEACTIVATED:
199: processWindowActivation(we);
200: return true;
201:
202: case WindowEvent.WINDOW_GAINED_FOCUS:
203:
204: boolean doRedispatch = false;
205: toolkit.lockAWT();
206: try {
207: // skip events in illegal state(to preserve their order),
208: // don't reorder them [as opposed to spec]
209: if (win.getFrameDialogOwner() != getGlobalActiveWindow()) {
210: return true;
211: }
212: if (((opposite != null) && (opposite == win))
213: || (win == focusedWindow)) {
214: return true;
215: }
216:
217: setGlobalFocusedWindow(win);
218:
219: // rejection recovery before redispatching
220: doRedispatch = (getFocusedWindow() == win);
221: if (!doRedispatch) {
222: recoverWindow(prevFocusedWindow);
223: }
224: } finally {
225: toolkit.unlockAWT();
226: }
227: if (doRedispatch) {
228: redispatchEvent(win, we);
229: }
230: return true;
231:
232: case WindowEvent.WINDOW_LOST_FOCUS:
233: if ((focusedWindow != null) && (opposite == focusedWindow)) {
234: return true;
235: }
236:
237: // Events posted by the peer layer claiming
238: // that the active Window has lost focus to
239: // the focused Window must be discarded
240: if ((win == activeWindow) && (focusedWindow != null)
241: && (opposite == focusedWindow)) {
242: return true;
243: }
244:
245: dispatchWindowLostFocus(we, win, opposite);
246: return true;
247:
248: }
249: return false;
250: }
251:
252: private void dispatchWindowLostFocus(WindowEvent we, Window win,
253: Window opposite) {
254:
255: boolean doRedispatch = false;
256: toolkit.lockAWT();
257: try {
258: if ((focusedWindow != null) && (win != focusedWindow)) {
259: win = focusedWindow;
260: }
261: we.setSource(win);
262: if (win == focusedWindow) {
263: // remember last focused window to request focus back if
264: // needed
265: prevFocusedWindow = focusedWindow;
266: setGlobalFocusedWindow(null);
267:
268: doRedispatch = true;
269: }
270: } finally {
271: toolkit.unlockAWT();
272: }
273:
274: if (doRedispatch) {
275: redispatchEvent(win, we);
276: }
277: }
278:
279: private boolean recoverWindow(Window prevWindow) {
280: // focused Window will be reset to the Window
281: // which was previously the focused Window
282:
283: if (prevWindow != null) {
284: // do the same thing as when native "focus gained" event comes on
285: // prevFocusedWindow, but call behavior
286: // to generate native event & activate ancestor Frame
287: requestFocusInWindow(prevWindow, true);
288: } else {
289: // If there is no such Window,
290: // then the KeyboardFocusManager will clear the global focus owner.
291: clearGlobalFocusOwner();
292: return false;
293: }
294: return true;
295: }
296:
297: private void processWindowActivation(WindowEvent we) {
298: boolean active = (we.getID() == WindowEvent.WINDOW_ACTIVATED);
299: Window win = we.getWindow();
300: win = (isActivateable(win) ? win : win.getFrameDialogOwner());
301:
302: // ignore activating already active window
303: // & deactivating any not active window
304: if (active == (activeWindow == win)) {
305: return;
306: }
307:
308: Window newActiveWindow = (active ? win : null);
309: Window oldActiveWindow = activeWindow;
310: setGlobalActiveWindow(newActiveWindow);
311: if (getGlobalActiveWindow() == newActiveWindow) {
312: if (!active) {
313: prevActiveWindow = oldActiveWindow;
314: }
315: we.setSource(win);
316: redispatchEvent(win, we);
317: } else if (active) {
318: // initiate activeWindow recovery if the change was
319: // rejected by a vetoable change listener
320: // recover only after WINDOW_ACTIVATED
321:
322: Window winToRecover = null;
323: if ((prevFocusedWindow != null)
324: && (prevFocusedWindow.getFrameDialogOwner() == prevActiveWindow)) {
325:
326: winToRecover = prevFocusedWindow;
327: }
328: recoverWindow(winToRecover);
329: }
330:
331: }
332:
333: @Override
334: public boolean dispatchKeyEvent(KeyEvent e) {
335: boolean doRedispatch = false;
336: toolkit.lockAWT();
337: try {
338: if ((focusOwner != null) && focusOwner.isKeyEnabled()) {
339: doRedispatch = !e.isConsumed();
340: }
341: } finally {
342: toolkit.unlockAWT();
343: }
344:
345: if (doRedispatch) {
346: e.setSource(focusOwner);
347: redispatchEvent(focusOwner, e);
348: }
349: postProcessKeyEvent(e);
350: return true; // no further dispatching
351: }
352:
353: @Override
354: public void downFocusCycle(Container aContainer) {
355: toolkit.lockAWT();
356: try {
357: if (aContainer != null) {
358: aContainer.transferFocusDownCycle();
359: }
360: } finally {
361: toolkit.unlockAWT();
362: }
363: }
364:
365: @Override
366: protected void enqueueKeyEvents(long a0, Component a1) {
367: toolkit.lockAWT();
368: try {
369: // currently do nothing,
370: // this method is never called by AWT implementation
371: } finally {
372: toolkit.unlockAWT();
373: }
374: }
375:
376: @Override
377: public void focusNextComponent(Component aComponent) {
378: toolkit.lockAWT();
379: try {
380: if (aComponent != null) {
381: aComponent.transferFocus();
382: }
383: } finally {
384: toolkit.unlockAWT();
385: }
386: }
387:
388: @Override
389: public void focusPreviousComponent(Component aComponent) {
390: toolkit.lockAWT();
391: try {
392: if (aComponent != null) {
393: aComponent.transferFocusBackward();
394: }
395: } finally {
396: toolkit.unlockAWT();
397: }
398: }
399:
400: @Override
401: public boolean postProcessKeyEvent(KeyEvent ke) {
402: // pass event to every key event postprocessor:
403: for (KeyEventPostProcessor kep : getKeyEventPostProcessors()) {
404: if (kep.postProcessKeyEvent(ke)) {
405: return true;
406: }
407: }
408:
409: // postprocess the event if no KeyEventPostProcessor dispatched it
410: if (!ke.isConsumed()) {
411: handleShortcut(ke);
412: }
413: return true;// discard KeyEvents if there's no focus owner
414:
415: }
416:
417: private void handleShortcut(KeyEvent ke) {
418: toolkit.lockAWT();
419: try {
420: if (MenuShortcut.isShortcut(ke)
421: && (activeWindow instanceof Frame)) {
422: MenuBar mb = ((Frame) activeWindow).getMenuBar();
423: if (mb != null) {
424: mb.handleShortcut(ke);
425: }
426: }
427: } finally {
428: toolkit.unlockAWT();
429: }
430: }
431:
432: @Override
433: public void processKeyEvent(Component focusedComponent, KeyEvent e) {
434: toolkit.lockAWT();
435: try {
436: AWTKeyStroke ks = ((e.getID() == KeyEvent.KEY_TYPED) ? null
437: : AWTKeyStroke.getAWTKeyStrokeForEvent(e));
438: Container container = ((focusedComponent instanceof Container) ? (Container) focusedComponent
439: : null);
440: Set<?> back = focusedComponent
441: .getFocusTraversalKeys(BACKWARD_TRAVERSAL_KEYS);
442: Set<?> forward = focusedComponent
443: .getFocusTraversalKeys(FORWARD_TRAVERSAL_KEYS);
444: Set<?> up = focusedComponent
445: .getFocusTraversalKeys(UP_CYCLE_TRAVERSAL_KEYS);
446: Set<?> down = (((container != null) && container
447: .isFocusCycleRoot()) ? container
448: .getFocusTraversalKeys(DOWN_CYCLE_TRAVERSAL_KEYS)
449: : null);
450:
451: // all KeyEvents related to the focus traversal key, including the
452: // associated KEY_TYPED event,
453: // will be consumed, and will not be dispatched to any Component
454:
455: Set[] sets = { back, forward, up, down };
456: consume(e, sets);
457:
458: if (back.contains(ks)) {
459: focusPreviousComponent(focusedComponent);
460: } else if (forward.contains(ks)) {
461: focusNextComponent(focusedComponent);
462: } else if (up.contains(ks)) {
463: upFocusCycle(focusedComponent);
464: } else if ((down != null) && (container != null)
465: && down.contains(ks)) {
466: downFocusCycle(container);
467: }
468: } finally {
469: toolkit.unlockAWT();
470: }
471: }
472:
473: /**
474: * @param sets
475: * @param e
476: * Consumes key event e if any set of focus-traversal keystrokes
477: * (i. e. not of type KEY_TYPED) from sets contains a keystroke
478: * with same code (or char) & modifiers as e
479: */
480: private void consume(KeyEvent e, Set<?>[] sets) {
481: int keyCode = e.getKeyCode();
482: int mod = (e.getModifiersEx() | e.getModifiers());
483: boolean codeDefined = (keyCode != KeyEvent.VK_UNDEFINED);
484: if (!codeDefined) {
485: // consume any KEY_TYPED event after
486: // consumed KEY_PRESSED and before
487: // any unconsumed KEY_PRESSED or any
488: // KEY_RELEASED
489: if (consumeKeyTyped) {
490: e.consume();
491: }
492: return;
493: }
494: for (Set<?> s : sets) {
495: if (s != null) {
496: AWTKeyStroke[] keys = s.toArray(new AWTKeyStroke[0]);
497: for (AWTKeyStroke key : keys) {
498: if ((key.getKeyCode() == keyCode)
499: && (key.getModifiers() == mod)) {
500: e.consume();
501: if (e.getID() == KeyEvent.KEY_PRESSED) {
502: // consume next KEY_TYPED event
503: consumeKeyTyped = true;
504: } else {
505: consumeKeyTyped = false;
506: }
507:
508: return;
509: }
510: }
511: }
512: }
513: consumeKeyTyped = false;
514: }
515:
516: @Override
517: public void upFocusCycle(Component aComponent) {
518: toolkit.lockAWT();
519: try {
520: if (aComponent != null) {
521: aComponent.transferFocusUpCycle();
522: }
523: } finally {
524: toolkit.unlockAWT();
525: }
526: }
527:
528: }
|