提交 87d9997a 编写于 作者: A ant

6981400: Tabbing between textfield do not work properly when ALT+TAB

7157015: [macosx] Situation when KeyEventDispatcher doesn't work on AWT but does on Swing.
7121442: Regression : Reopen CR 6458497 still reproducible using JDK 7.
Reviewed-by: art, leonidr
上级 1058f6e6
...@@ -1251,9 +1251,6 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent> ...@@ -1251,9 +1251,6 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
if (!target.isFocusOwner() && LWKeyboardFocusManagerPeer.shouldFocusOnClick(target)) { if (!target.isFocusOwner() && LWKeyboardFocusManagerPeer.shouldFocusOnClick(target)) {
LWKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT); LWKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT);
} else {
// Anyway request focus to the toplevel.
getWindowPeerOrSelf().requestWindowFocus(CausedFocusEvent.Cause.MOUSE_EVENT);
} }
} }
......
...@@ -798,6 +798,14 @@ public class LWWindowPeer ...@@ -798,6 +798,14 @@ public class LWWindowPeer
mouseClickButtons |= eventButtonMask; mouseClickButtons |= eventButtonMask;
} }
// The window should be focused on mouse click. If it gets activated by the native platform,
// this request will be no op. It will take effect when:
// 1. A simple not focused window is clicked.
// 2. An active but not focused owner frame/dialog is clicked.
// The mouse event then will trigger a focus request "in window" to the component, so the window
// should gain focus before.
requestWindowFocus(CausedFocusEvent.Cause.MOUSE_EVENT);
mouseDownTarget[targetIdx] = targetPeer; mouseDownTarget[targetIdx] = targetPeer;
} else if (id == MouseEvent.MOUSE_DRAGGED) { } else if (id == MouseEvent.MOUSE_DRAGGED) {
// Cocoa dragged event has the information about which mouse // Cocoa dragged event has the information about which mouse
...@@ -914,20 +922,16 @@ public class LWWindowPeer ...@@ -914,20 +922,16 @@ public class LWWindowPeer
public void dispatchKeyEvent(int id, long when, int modifiers, public void dispatchKeyEvent(int id, long when, int modifiers,
int keyCode, char keyChar, int keyLocation) int keyCode, char keyChar, int keyLocation)
{ {
KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); LWKeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
Component focusOwner = kfmPeer.getCurrentFocusOwner(); Component focusOwner = kfmPeer.getCurrentFocusOwner();
// Null focus owner may receive key event when if (focusOwner == null) {
// application hides the focused window upon ESC press focusOwner = kfmPeer.getCurrentFocusedWindow();
// (AWT transfers/clears the focus owner) and pending ESC release if (focusOwner == null) {
// may come to already hidden window. This check eliminates NPE. focusOwner = this.getTarget();
if (focusOwner != null) { }
KeyEvent event =
new KeyEvent(focusOwner, id, when, modifiers,
keyCode, keyChar, keyLocation);
LWComponentPeer peer = (LWComponentPeer)focusOwner.getPeer();
peer.postEvent(event);
} }
postEvent(new KeyEvent(focusOwner, id, when, modifiers, keyCode, keyChar, keyLocation));
} }
...@@ -1260,7 +1264,7 @@ public class LWWindowPeer ...@@ -1260,7 +1264,7 @@ public class LWWindowPeer
kfmPeer.setCurrentFocusedWindow(becomesFocused ? getTarget() : null); kfmPeer.setCurrentFocusedWindow(becomesFocused ? getTarget() : null);
int eventID = becomesFocused ? WindowEvent.WINDOW_GAINED_FOCUS : WindowEvent.WINDOW_LOST_FOCUS; int eventID = becomesFocused ? WindowEvent.WINDOW_GAINED_FOCUS : WindowEvent.WINDOW_LOST_FOCUS;
WindowEvent windowEvent = new WindowEvent(getTarget(), eventID, oppositeWindow); WindowEvent windowEvent = new TimedWindowEvent(getTarget(), eventID, oppositeWindow, System.currentTimeMillis());
// TODO: wrap in SequencedEvent // TODO: wrap in SequencedEvent
postEvent(windowEvent); postEvent(windowEvent);
......
...@@ -30,6 +30,8 @@ import java.awt.Container; ...@@ -30,6 +30,8 @@ import java.awt.Container;
import java.awt.Event; import java.awt.Event;
import java.awt.KeyEventPostProcessor; import java.awt.KeyEventPostProcessor;
import java.awt.Window; import java.awt.Window;
import java.awt.Toolkit;
import sun.awt.SunToolkit;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
...@@ -125,7 +127,19 @@ public class WindowsRootPaneUI extends BasicRootPaneUI { ...@@ -125,7 +127,19 @@ public class WindowsRootPaneUI extends BasicRootPaneUI {
} }
JMenu menu = mbar != null ? mbar.getMenu(0) : null; JMenu menu = mbar != null ? mbar.getMenu(0) : null;
if (menu != null) { // It might happen that the altRelease event is processed
// with a reasonable delay since it has been generated.
// Here we check the last deactivation time of the containing
// window. If this time appears to be greater than the altRelease
// event time the event is skipped to avoid unexpected menu
// activation. See 7121442.
boolean skip = false;
Toolkit tk = Toolkit.getDefaultToolkit();
if (tk instanceof SunToolkit) {
skip = ev.getWhen() <= ((SunToolkit)tk).getWindowDeactivationTime(winAncestor);
}
if (menu != null && !skip) {
MenuElement[] path = new MenuElement[2]; MenuElement[] path = new MenuElement[2];
path[0] = mbar; path[0] = mbar;
path[1] = menu; path[1] = menu;
......
...@@ -4710,7 +4710,10 @@ public abstract class Component implements ImageObserver, MenuContainer, ...@@ -4710,7 +4710,10 @@ public abstract class Component implements ImageObserver, MenuContainer,
/* /*
* 0. Set timestamp and modifiers of current event. * 0. Set timestamp and modifiers of current event.
*/ */
EventQueue.setCurrentEventAndMostRecentTime(e); if (!(e instanceof KeyEvent)) {
// Timestamp of a key event is set later in DKFM.preDispatchKeyEvent(KeyEvent).
EventQueue.setCurrentEventAndMostRecentTime(e);
}
/* /*
* 1. Pre-dispatchers. Do any necessary retargeting/reordering here * 1. Pre-dispatchers. Do any necessary retargeting/reordering here
...@@ -7606,13 +7609,33 @@ public abstract class Component implements ImageObserver, MenuContainer, ...@@ -7606,13 +7609,33 @@ public abstract class Component implements ImageObserver, MenuContainer,
boolean focusedWindowChangeAllowed, boolean focusedWindowChangeAllowed,
CausedFocusEvent.Cause cause) CausedFocusEvent.Cause cause)
{ {
// 1) Check if the event being dispatched is a system-generated mouse event.
AWTEvent currentEvent = EventQueue.getCurrentEvent();
if (currentEvent instanceof MouseEvent &&
SunToolkit.isSystemGenerated(currentEvent))
{
// 2) Sanity check: if the mouse event component source belongs to the same containing window.
Component source = ((MouseEvent)currentEvent).getComponent();
if (source == null || source.getContainingWindow() == getContainingWindow()) {
focusLog.finest("requesting focus by mouse event \"in window\"");
// If both the conditions are fulfilled the focus request should be strictly
// bounded by the toplevel window. It's assumed that the mouse event activates
// the window (if it wasn't active) and this makes it possible for a focus
// request with a strong in-window requirement to change focus in the bounds
// of the toplevel. If, by any means, due to asynchronous nature of the event
// dispatching mechanism, the window happens to be natively inactive by the time
// this focus request is eventually handled, it should not re-activate the
// toplevel. Otherwise the result may not meet user expectations. See 6981400.
focusedWindowChangeAllowed = false;
}
}
if (!isRequestFocusAccepted(temporary, focusedWindowChangeAllowed, cause)) { if (!isRequestFocusAccepted(temporary, focusedWindowChangeAllowed, cause)) {
if (focusLog.isLoggable(PlatformLogger.FINEST)) { if (focusLog.isLoggable(PlatformLogger.FINEST)) {
focusLog.finest("requestFocus is not accepted"); focusLog.finest("requestFocus is not accepted");
} }
return false; return false;
} }
// Update most-recent map // Update most-recent map
KeyboardFocusManager.setMostRecentFocusOwner(this); KeyboardFocusManager.setMostRecentFocusOwner(this);
...@@ -7645,7 +7668,15 @@ public abstract class Component implements ImageObserver, MenuContainer, ...@@ -7645,7 +7668,15 @@ public abstract class Component implements ImageObserver, MenuContainer,
} }
// Focus this Component // Focus this Component
long time = EventQueue.getMostRecentEventTime(); long time = 0;
if (EventQueue.isDispatchThread()) {
time = Toolkit.getEventQueue().getMostRecentKeyEventTime();
} else {
// A focus request made from outside EDT should not be associated with any event
// and so its time stamp is simply set to the current time.
time = System.currentTimeMillis();
}
boolean success = peer.requestFocus boolean success = peer.requestFocus
(this, temporary, focusedWindowChangeAllowed, time, cause); (this, temporary, focusedWindowChangeAllowed, time, cause);
if (!success) { if (!success) {
......
...@@ -2863,7 +2863,7 @@ public class Container extends Component { ...@@ -2863,7 +2863,7 @@ public class Container extends Component {
// keep the KeyEvents from being dispatched // keep the KeyEvents from being dispatched
// until the focus has been transfered // until the focus has been transfered
long time = Toolkit.getEventQueue().getMostRecentEventTime(); long time = Toolkit.getEventQueue().getMostRecentKeyEventTime();
Component predictedFocusOwner = (Component.isInstanceOf(this, "javax.swing.JInternalFrame")) ? ((javax.swing.JInternalFrame)(this)).getMostRecentFocusOwner() : null; Component predictedFocusOwner = (Component.isInstanceOf(this, "javax.swing.JInternalFrame")) ? ((javax.swing.JInternalFrame)(this)).getMostRecentFocusOwner() : null;
if (predictedFocusOwner != null) { if (predictedFocusOwner != null) {
KeyboardFocusManager.getCurrentKeyboardFocusManager(). KeyboardFocusManager.getCurrentKeyboardFocusManager().
......
...@@ -40,6 +40,7 @@ import sun.util.logging.PlatformLogger; ...@@ -40,6 +40,7 @@ import sun.util.logging.PlatformLogger;
import sun.awt.AppContext; import sun.awt.AppContext;
import sun.awt.SunToolkit; import sun.awt.SunToolkit;
import sun.awt.CausedFocusEvent; import sun.awt.CausedFocusEvent;
import sun.awt.TimedWindowEvent;
/** /**
* The default KeyboardFocusManager for AWT applications. Focus traversal is * The default KeyboardFocusManager for AWT applications. Focus traversal is
...@@ -71,8 +72,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ...@@ -71,8 +72,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
private WeakReference<Window> realOppositeWindowWR = NULL_WINDOW_WR; private WeakReference<Window> realOppositeWindowWR = NULL_WINDOW_WR;
private WeakReference<Component> realOppositeComponentWR = NULL_COMPONENT_WR; private WeakReference<Component> realOppositeComponentWR = NULL_COMPONENT_WR;
private int inSendMessage; private int inSendMessage;
private LinkedList enqueuedKeyEvents = new LinkedList(), private LinkedList<KeyEvent> enqueuedKeyEvents = new LinkedList<KeyEvent>();
typeAheadMarkers = new LinkedList(); private LinkedList<TypeAheadMarker> typeAheadMarkers = new LinkedList<TypeAheadMarker>();
private boolean consumeNextKeyTyped; private boolean consumeNextKeyTyped;
private static class TypeAheadMarker { private static class TypeAheadMarker {
...@@ -259,6 +260,31 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ...@@ -259,6 +260,31 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
return se.dispatched; return se.dispatched;
} }
/*
* Checks if the focus window event follows key events waiting in the type-ahead
* queue (if any). This may happen when a user types ahead in the window, the client
* listeners hang EDT for a while, and the user switches b/w toplevels. In that
* case the focus window events may be dispatched before the type-ahead events
* get handled. This may lead to wrong focus behavior and in order to avoid it,
* the focus window events are reposted to the end of the event queue. See 6981400.
*/
private boolean repostIfFollowsKeyEvents(WindowEvent e) {
if (!(e instanceof TimedWindowEvent)) {
return false;
}
TimedWindowEvent we = (TimedWindowEvent)e;
long time = we.getWhen();
synchronized (this) {
for (KeyEvent ke: enqueuedKeyEvents) {
if (time >= ke.getWhen()) {
SunToolkit.postEvent(AppContext.getAppContext(), new SequencedEvent(e));
return true;
}
}
}
return false;
}
/** /**
* This method is called by the AWT event dispatcher requesting that the * This method is called by the AWT event dispatcher requesting that the
* current KeyboardFocusManager dispatch the specified event on its behalf. * current KeyboardFocusManager dispatch the specified event on its behalf.
...@@ -277,6 +303,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ...@@ -277,6 +303,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
if (focusLog.isLoggable(PlatformLogger.FINE) && (e instanceof WindowEvent || e instanceof FocusEvent)) focusLog.fine("" + e); if (focusLog.isLoggable(PlatformLogger.FINE) && (e instanceof WindowEvent || e instanceof FocusEvent)) focusLog.fine("" + e);
switch (e.getID()) { switch (e.getID()) {
case WindowEvent.WINDOW_GAINED_FOCUS: { case WindowEvent.WINDOW_GAINED_FOCUS: {
if (repostIfFollowsKeyEvents((WindowEvent)e)) {
break;
}
WindowEvent we = (WindowEvent)e; WindowEvent we = (WindowEvent)e;
Window oldFocusedWindow = getGlobalFocusedWindow(); Window oldFocusedWindow = getGlobalFocusedWindow();
Window newFocusedWindow = we.getWindow(); Window newFocusedWindow = we.getWindow();
...@@ -636,6 +666,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ...@@ -636,6 +666,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
} }
case WindowEvent.WINDOW_LOST_FOCUS: { case WindowEvent.WINDOW_LOST_FOCUS: {
if (repostIfFollowsKeyEvents((WindowEvent)e)) {
break;
}
WindowEvent we = (WindowEvent)e; WindowEvent we = (WindowEvent)e;
Window currentFocusedWindow = getGlobalFocusedWindow(); Window currentFocusedWindow = getGlobalFocusedWindow();
Window losingFocusWindow = we.getWindow(); Window losingFocusWindow = we.getWindow();
...@@ -815,10 +849,9 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ...@@ -815,10 +849,9 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
ke = null; ke = null;
synchronized (this) { synchronized (this) {
if (enqueuedKeyEvents.size() != 0) { if (enqueuedKeyEvents.size() != 0) {
ke = (KeyEvent)enqueuedKeyEvents.getFirst(); ke = enqueuedKeyEvents.getFirst();
if (typeAheadMarkers.size() != 0) { if (typeAheadMarkers.size() != 0) {
TypeAheadMarker marker = (TypeAheadMarker) TypeAheadMarker marker = typeAheadMarkers.getFirst();
typeAheadMarkers.getFirst();
// Fixed 5064013: may appears that the events have the same time // Fixed 5064013: may appears that the events have the same time
// if (ke.getWhen() >= marker.after) { // if (ke.getWhen() >= marker.after) {
// The fix is rolled out. // The fix is rolled out.
...@@ -847,9 +880,9 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ...@@ -847,9 +880,9 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
focusLog.finest(">>> Markers dump, time: {0}", System.currentTimeMillis()); focusLog.finest(">>> Markers dump, time: {0}", System.currentTimeMillis());
synchronized (this) { synchronized (this) {
if (typeAheadMarkers.size() != 0) { if (typeAheadMarkers.size() != 0) {
Iterator iter = typeAheadMarkers.iterator(); Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
TypeAheadMarker marker = (TypeAheadMarker)iter.next(); TypeAheadMarker marker = iter.next();
focusLog.finest(" {0}", marker); focusLog.finest(" {0}", marker);
} }
} }
...@@ -871,8 +904,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ...@@ -871,8 +904,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
KeyEvent ke = (KeyEvent)e; KeyEvent ke = (KeyEvent)e;
synchronized (this) { synchronized (this) {
if (e.isPosted && typeAheadMarkers.size() != 0) { if (e.isPosted && typeAheadMarkers.size() != 0) {
TypeAheadMarker marker = (TypeAheadMarker) TypeAheadMarker marker = typeAheadMarkers.getFirst();
typeAheadMarkers.getFirst();
// Fixed 5064013: may appears that the events have the same time // Fixed 5064013: may appears that the events have the same time
// if (ke.getWhen() >= marker.after) { // if (ke.getWhen() >= marker.after) {
// The fix is rolled out. // The fix is rolled out.
...@@ -905,12 +937,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ...@@ -905,12 +937,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
synchronized (this) { synchronized (this) {
boolean found = false; boolean found = false;
if (hasMarker(target)) { if (hasMarker(target)) {
for (Iterator iter = typeAheadMarkers.iterator(); for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator();
iter.hasNext(); ) iter.hasNext(); )
{ {
if (((TypeAheadMarker)iter.next()).untilFocused == if (iter.next().untilFocused == target) {
target)
{
found = true; found = true;
} else if (found) { } else if (found) {
break; break;
...@@ -945,8 +975,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ...@@ -945,8 +975,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
* @since 1.5 * @since 1.5
*/ */
private boolean hasMarker(Component comp) { private boolean hasMarker(Component comp) {
for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
if (((TypeAheadMarker)iter.next()).untilFocused == comp) { if (iter.next().untilFocused == comp) {
return true; return true;
} }
} }
...@@ -972,11 +1002,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ...@@ -972,11 +1002,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
return true; return true;
} }
// Explicitly set the current event and most recent timestamp here in // Explicitly set the key event timestamp here (not in Component.dispatchEventImpl):
// addition to the call in Component.dispatchEventImpl. Because // - A key event is anyway passed to this method which starts its actual dispatching.
// KeyEvents can be delivered in response to a FOCUS_GAINED event, the // - If a key event is put to the type ahead queue, its time stamp should not be registered
// current timestamp may be incorrect. We need to set it here so that // until its dispatching actually starts (by this method).
// KeyEventDispatchers will use the correct time.
EventQueue.setCurrentEventAndMostRecentTime(ke); EventQueue.setCurrentEventAndMostRecentTime(ke);
/** /**
...@@ -1164,10 +1193,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ...@@ -1164,10 +1193,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
int insertionIndex = 0, int insertionIndex = 0,
i = typeAheadMarkers.size(); i = typeAheadMarkers.size();
ListIterator iter = typeAheadMarkers.listIterator(i); ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator(i);
for (; i > 0; i--) { for (; i > 0; i--) {
TypeAheadMarker marker = (TypeAheadMarker)iter.previous(); TypeAheadMarker marker = iter.previous();
if (marker.after <= after) { if (marker.after <= after) {
insertionIndex = i; insertionIndex = i;
break; break;
...@@ -1203,12 +1232,12 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ...@@ -1203,12 +1232,12 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
after, untilFocused); after, untilFocused);
TypeAheadMarker marker; TypeAheadMarker marker;
ListIterator iter = typeAheadMarkers.listIterator ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator
((after >= 0) ? typeAheadMarkers.size() : 0); ((after >= 0) ? typeAheadMarkers.size() : 0);
if (after < 0) { if (after < 0) {
while (iter.hasNext()) { while (iter.hasNext()) {
marker = (TypeAheadMarker)iter.next(); marker = iter.next();
if (marker.untilFocused == untilFocused) if (marker.untilFocused == untilFocused)
{ {
iter.remove(); iter.remove();
...@@ -1217,7 +1246,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ...@@ -1217,7 +1246,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
} }
} else { } else {
while (iter.hasPrevious()) { while (iter.hasPrevious()) {
marker = (TypeAheadMarker)iter.previous(); marker = iter.previous();
if (marker.untilFocused == untilFocused && if (marker.untilFocused == untilFocused &&
marker.after == after) marker.after == after)
{ {
...@@ -1245,8 +1274,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ...@@ -1245,8 +1274,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
long start = -1; long start = -1;
for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
TypeAheadMarker marker = (TypeAheadMarker)iter.next(); TypeAheadMarker marker = iter.next();
Component toTest = marker.untilFocused; Component toTest = marker.untilFocused;
boolean match = (toTest == comp); boolean match = (toTest == comp);
while (!match && toTest != null && !(toTest instanceof Window)) { while (!match && toTest != null && !(toTest instanceof Window)) {
...@@ -1277,8 +1306,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ...@@ -1277,8 +1306,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
return; return;
} }
for (Iterator iter = enqueuedKeyEvents.iterator(); iter.hasNext(); ) { for (Iterator<KeyEvent> iter = enqueuedKeyEvents.iterator(); iter.hasNext(); ) {
KeyEvent ke = (KeyEvent)iter.next(); KeyEvent ke = iter.next();
long time = ke.getWhen(); long time = ke.getWhen();
if (start < time && (end < 0 || time <= end)) { if (start < time && (end < 0 || time <= end)) {
......
...@@ -924,7 +924,7 @@ public class Dialog extends Window { ...@@ -924,7 +924,7 @@ public class Dialog extends Window {
isEnabled() && !isModalBlocked()) { isEnabled() && !isModalBlocked()) {
// keep the KeyEvents from being dispatched // keep the KeyEvents from being dispatched
// until the focus has been transfered // until the focus has been transfered
time.set(Toolkit.getEventQueue().getMostRecentEventTimeEx()); time.set(Toolkit.getEventQueue().getMostRecentKeyEventTime());
KeyboardFocusManager.getCurrentKeyboardFocusManager(). KeyboardFocusManager.getCurrentKeyboardFocusManager().
enqueueKeyEvents(time.get(), toFocus); enqueueKeyEvents(time.get(), toFocus);
} }
......
...@@ -163,6 +163,11 @@ public class EventQueue { ...@@ -163,6 +163,11 @@ public class EventQueue {
*/ */
private long mostRecentEventTime = System.currentTimeMillis(); private long mostRecentEventTime = System.currentTimeMillis();
/*
* The time stamp of the last KeyEvent .
*/
private long mostRecentKeyEventTime = System.currentTimeMillis();
/** /**
* The modifiers field of the current event, if the current event is an * The modifiers field of the current event, if the current event is an
* InputEvent or ActionEvent. * InputEvent or ActionEvent.
...@@ -1132,6 +1137,15 @@ public class EventQueue { ...@@ -1132,6 +1137,15 @@ public class EventQueue {
} }
} }
synchronized long getMostRecentKeyEventTime() {
pushPopLock.lock();
try {
return mostRecentKeyEventTime;
} finally {
pushPopLock.unlock();
}
}
static void setCurrentEventAndMostRecentTime(AWTEvent e) { static void setCurrentEventAndMostRecentTime(AWTEvent e) {
Toolkit.getEventQueue().setCurrentEventAndMostRecentTimeImpl(e); Toolkit.getEventQueue().setCurrentEventAndMostRecentTimeImpl(e);
} }
...@@ -1156,6 +1170,9 @@ public class EventQueue { ...@@ -1156,6 +1170,9 @@ public class EventQueue {
if (e instanceof InputEvent) { if (e instanceof InputEvent) {
InputEvent ie = (InputEvent)e; InputEvent ie = (InputEvent)e;
mostRecentEventTime2 = ie.getWhen(); mostRecentEventTime2 = ie.getWhen();
if (e instanceof KeyEvent) {
mostRecentKeyEventTime = ie.getWhen();
}
} else if (e instanceof InputMethodEvent) { } else if (e instanceof InputMethodEvent) {
InputMethodEvent ime = (InputMethodEvent)e; InputMethodEvent ime = (InputMethodEvent)e;
mostRecentEventTime2 = ime.getWhen(); mostRecentEventTime2 = ime.getWhen();
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
package java.awt; package java.awt;
import java.util.LinkedList; import java.util.LinkedList;
import sun.awt.AWTAccessor;
import sun.awt.AppContext; import sun.awt.AppContext;
import sun.awt.SunToolkit; import sun.awt.SunToolkit;
...@@ -54,6 +55,17 @@ class SequencedEvent extends AWTEvent implements ActiveEvent { ...@@ -54,6 +55,17 @@ class SequencedEvent extends AWTEvent implements ActiveEvent {
private AppContext appContext; private AppContext appContext;
private boolean disposed; private boolean disposed;
static {
AWTAccessor.setSequencedEventAccessor(new AWTAccessor.SequencedEventAccessor() {
public AWTEvent getNested(AWTEvent sequencedEvent) {
return ((SequencedEvent)sequencedEvent).nested;
}
public boolean isSequencedEvent(AWTEvent event) {
return event instanceof SequencedEvent;
}
});
}
/** /**
* Constructs a new SequencedEvent which will dispatch the specified * Constructs a new SequencedEvent which will dispatch the specified
* nested event. * nested event.
......
...@@ -486,6 +486,21 @@ public final class AWTAccessor { ...@@ -486,6 +486,21 @@ public final class AWTAccessor {
final int type); final int type);
} }
/*
* An accessor for the SequencedEventAccessor class
*/
public interface SequencedEventAccessor {
/*
* Returns the nested event.
*/
AWTEvent getNested(AWTEvent sequencedEvent);
/*
* Returns true if the event is an instances of SequencedEvent.
*/
boolean isSequencedEvent(AWTEvent event);
}
/* /*
* Accessor instances are initialized in the static initializers of * Accessor instances are initialized in the static initializers of
* corresponding AWT classes by using setters defined below. * corresponding AWT classes by using setters defined below.
...@@ -502,6 +517,7 @@ public final class AWTAccessor { ...@@ -502,6 +517,7 @@ public final class AWTAccessor {
private static PopupMenuAccessor popupMenuAccessor; private static PopupMenuAccessor popupMenuAccessor;
private static FileDialogAccessor fileDialogAccessor; private static FileDialogAccessor fileDialogAccessor;
private static ScrollPaneAdjustableAccessor scrollPaneAdjustableAccessor; private static ScrollPaneAdjustableAccessor scrollPaneAdjustableAccessor;
private static SequencedEventAccessor sequencedEventAccessor;
/* /*
* Set an accessor object for the java.awt.Component class. * Set an accessor object for the java.awt.Component class.
...@@ -709,4 +725,21 @@ public final class AWTAccessor { ...@@ -709,4 +725,21 @@ public final class AWTAccessor {
} }
return scrollPaneAdjustableAccessor; return scrollPaneAdjustableAccessor;
} }
/*
* Set an accessor object for the java.awt.SequencedEvent class.
*/
public static void setSequencedEventAccessor(SequencedEventAccessor sea) {
sequencedEventAccessor = sea;
}
/*
* Get the accessor object for the java.awt.SequencedEvent class.
*/
public static SequencedEventAccessor getSequencedEventAccessor() {
// The class is not public. So we can't ensure it's initialized.
// Null returned value means it's not initialized
// (so not a single instance of the event has been created).
return sequencedEventAccessor;
}
} }
...@@ -128,7 +128,7 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag ...@@ -128,7 +128,7 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag
if (focusLog.isLoggable(PlatformLogger.FINER)) if (focusLog.isLoggable(PlatformLogger.FINER))
focusLog.finer("Posting focus event: " + fl); focusLog.finer("Posting focus event: " + fl);
SunToolkit.postPriorityEvent(fl); SunToolkit.postEvent(SunToolkit.targetToAppContext(currentOwner), fl);
} }
FocusEvent fg = new CausedFocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED, FocusEvent fg = new CausedFocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED,
...@@ -136,7 +136,7 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag ...@@ -136,7 +136,7 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag
if (focusLog.isLoggable(PlatformLogger.FINER)) if (focusLog.isLoggable(PlatformLogger.FINER))
focusLog.finer("Posting focus event: " + fg); focusLog.finer("Posting focus event: " + fg);
SunToolkit.postPriorityEvent(fg); SunToolkit.postEvent(SunToolkit.targetToAppContext(lightweightChild), fg);
return true; return true;
} }
......
...@@ -513,6 +513,19 @@ public abstract class SunToolkit extends Toolkit ...@@ -513,6 +513,19 @@ public abstract class SunToolkit extends Toolkit
if (event == null) { if (event == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
AWTAccessor.SequencedEventAccessor sea = AWTAccessor.getSequencedEventAccessor();
if (sea != null && sea.isSequencedEvent(event)) {
AWTEvent nested = sea.getNested(event);
if (nested.getID() == WindowEvent.WINDOW_LOST_FOCUS &&
nested instanceof TimedWindowEvent)
{
TimedWindowEvent twe = (TimedWindowEvent)nested;
((SunToolkit)Toolkit.getDefaultToolkit()).
setWindowDeactivationTime((Window)twe.getSource(), twe.getWhen());
}
}
// All events posted via this method are system-generated. // All events posted via this method are system-generated.
// Placing the following call here reduces considerably the // Placing the following call here reduces considerably the
// number of places throughout the toolkit that would // number of places throughout the toolkit that would
...@@ -1964,6 +1977,28 @@ public abstract class SunToolkit extends Toolkit ...@@ -1964,6 +1977,28 @@ public abstract class SunToolkit extends Toolkit
return false; return false;
} }
private static final Object DEACTIVATION_TIMES_MAP_KEY = new Object();
public synchronized void setWindowDeactivationTime(Window w, long time) {
AppContext ctx = getAppContext(w);
WeakHashMap<Window, Long> map = (WeakHashMap<Window, Long>)ctx.get(DEACTIVATION_TIMES_MAP_KEY);
if (map == null) {
map = new WeakHashMap<Window, Long>();
ctx.put(DEACTIVATION_TIMES_MAP_KEY, map);
}
map.put(w, time);
}
public synchronized long getWindowDeactivationTime(Window w) {
AppContext ctx = getAppContext(w);
WeakHashMap<Window, Long> map = (WeakHashMap<Window, Long>)ctx.get(DEACTIVATION_TIMES_MAP_KEY);
if (map == null) {
return -1;
}
Long time = map.get(w);
return time == null ? -1 : time;
}
// Cosntant alpha // Cosntant alpha
public boolean isWindowOpacitySupported() { public boolean isWindowOpacitySupported() {
return false; return false;
......
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.event.WindowEvent;
import java.awt.Window;
public class TimedWindowEvent extends WindowEvent {
private long time;
public long getWhen() {
return time;
}
public TimedWindowEvent(Window source, int id, Window opposite, long time) {
super(source, id, opposite);
this.time = time;
}
public TimedWindowEvent(Window source, int id, Window opposite,
int oldState, int newState, long time)
{
super(source, id, opposite, oldState, newState);
this.time = time;
}
}
...@@ -1001,6 +1001,13 @@ public class XBaseWindow { ...@@ -1001,6 +1001,13 @@ public class XBaseWindow {
switch (xev.get_type()) { switch (xev.get_type()) {
case XConstants.ButtonPress: case XConstants.ButtonPress:
if (buttonState == 0) { if (buttonState == 0) {
XWindowPeer parent = getToplevelXWindow();
// See 6385277, 6981400.
if (parent != null && parent.isFocusableWindow()) {
// A click in a client area drops the actual focused window retaining.
parent.setActualFocusedWindow(null);
parent.requestWindowFocus(xbe.get_time(), true);
}
XAwtState.setAutoGrabWindow(this); XAwtState.setAutoGrabWindow(this);
} }
break; break;
......
...@@ -588,33 +588,6 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget ...@@ -588,33 +588,6 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
} }
public void handleButtonPressRelease(XEvent xev) {
/*
* Fix for 6385277.
* We request focus on simple Window by click in order
* to make it behave like Frame/Dialog in this case and also to unify
* the behaviour with what we have on MS Windows.
* handleJavaMouseEvent() would be more suitable place to do this
* but we want Swing to have this functionality also.
*/
if (xev.get_type() == XConstants.ButtonPress) {
final XWindowPeer parentXWindow = getParentTopLevel();
Window parentWindow = (Window)parentXWindow.getTarget();
if (parentXWindow.isFocusableWindow() && parentXWindow.isSimpleWindow() &&
XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() != parentWindow)
{
postEvent(new InvocationEvent(parentWindow, new Runnable() {
public void run() {
// Request focus on the EDT of 'parentWindow' because
// XDecoratedPeer.requestWindowFocus() calls client code.
parentXWindow.requestXFocus();
}
}));
}
}
super.handleButtonPressRelease(xev);
}
public Dimension getMinimumSize() { public Dimension getMinimumSize() {
return target.getSize(); return target.getSize();
} }
......
...@@ -1477,7 +1477,7 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite, ...@@ -1477,7 +1477,7 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite,
if (wClassEvent == NULL) { if (wClassEvent == NULL) {
if (env->PushLocalFrame(1) < 0) if (env->PushLocalFrame(1) < 0)
return; return;
wClassEvent = env->FindClass("java/awt/event/WindowEvent"); wClassEvent = env->FindClass("sun/awt/TimedWindowEvent");
if (wClassEvent != NULL) { if (wClassEvent != NULL) {
wClassEvent = (jclass)env->NewGlobalRef(wClassEvent); wClassEvent = (jclass)env->NewGlobalRef(wClassEvent);
} }
...@@ -1491,7 +1491,7 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite, ...@@ -1491,7 +1491,7 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite,
if (wEventInitMID == NULL) { if (wEventInitMID == NULL) {
wEventInitMID = wEventInitMID =
env->GetMethodID(wClassEvent, "<init>", env->GetMethodID(wClassEvent, "<init>",
"(Ljava/awt/Window;ILjava/awt/Window;II)V"); "(Ljava/awt/Window;ILjava/awt/Window;IIJ)V");
DASSERT(wEventInitMID); DASSERT(wEventInitMID);
if (wEventInitMID == NULL) { if (wEventInitMID == NULL) {
return; return;
...@@ -1532,7 +1532,7 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite, ...@@ -1532,7 +1532,7 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite,
} }
} }
jobject event = env->NewObject(wClassEvent, wEventInitMID, target, id, jobject event = env->NewObject(wClassEvent, wEventInitMID, target, id,
jOpposite, oldState, newState); jOpposite, oldState, newState, TimeHelper::getMessageTimeUTC());
DASSERT(!safe_ExceptionOccurred(env)); DASSERT(!safe_ExceptionOccurred(env));
DASSERT(event != NULL); DASSERT(event != NULL);
if (jOpposite != NULL) { if (jOpposite != NULL) {
......
/*
* Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 6981400
* @summary Tabbing between textfiled do not work properly when ALT+TAB
* @author anton.tarasov
* @library ../../regtesthelpers
* @build Util
* @run main Test1
*/
// This test shows a frame with four focusable components: b0, b1, b2, b3.
// Then it presses Tab three times. EDT is freezed for a while on the first FOCUS_LOST event.
// Meantime, the test clicks in a component of another frame and then clicks in the title
// of the original frame. When EDT awakes and all the queued events get processed,
// the other frame should ones gain focus and then pass it to the original frame.
// The b3 component of the orinial frame should finally become a focus owner.
// The FOCUS_LOST/FOCUS_GAINED events order in the original frame is tracked and should be:
// b0 -> b1 -> b2 -> b3.
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.*;
import test.java.awt.regtesthelpers.Util;
public class Test1 {
static JFrame f0 = new JFrame("base_frame") { public String getName() {return "base_frame";} };
static JButton f0b0 = new JB("b0");
static JButton f0b1 = new JB("b1");
static JButton f0b2 = new JB("b2");
static JButton f0b3 = new JB("b3");
static JFrame f1 = new JFrame("swing_frame") { public String getName() {return "swing_frame";} };
static JButton f1b0 = new JButton("button");
static Frame f2 = new Frame("awt_frame") { public String getName() {return "awt_frame";} };
static Button f2b0 = new Button("button");
static Robot robot;
static List<Component> gainedList = new ArrayList<Component>();
static List<Component> lostList = new ArrayList<Component>();
static Component[] refGainedList = new Component[] {f0b1, f0b2, f0b3, f0b3};
static Component[] refLostList = new Component[] {f0b0, f0b1, f0b2, f0b3};
static boolean tracking;
public static void main(String[] args) {
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
public void eventDispatched(AWTEvent e) {
System.out.println(e);
}
}, FocusEvent.FOCUS_EVENT_MASK | WindowEvent.WINDOW_EVENT_MASK);
try {
robot = new Robot();
} catch (AWTException ex) {
throw new RuntimeException("Error: can't create Robot");
}
f0.add(f0b0);
f0.add(f0b1);
f0.add(f0b2);
f0.add(f0b3);
f0.setLayout(new FlowLayout());
f0.setBounds(0, 100, 400, 200);
f1.add(f1b0);
f1.setBounds(0, 400, 400, 200);
f2.add(f2b0);
f2.setBounds(0, 400, 400, 200);
f0b0.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
try {
Thread.sleep(1000);
} catch (Exception ex) {}
}
});
//
// Case 1. Test against swing JFrame.
//
f1.setVisible(true);
f0.setVisible(true);
Util.waitForIdle(robot);
if (!f0b0.isFocusOwner()) {
Util.clickOnComp(f0b0, robot);
Util.waitForIdle(robot);
if (!f0b0.isFocusOwner()) {
throw new RuntimeException("Error: can't focus the component " + f0b0);
}
}
System.out.println("\nTest case 1: swing frame\n");
test(f1b0);
//
// Case 2. Test against awt Frame.
//
tracking = false;
gainedList.clear();
lostList.clear();
f1.dispose();
f2.setAutoRequestFocus(false);
f2.setVisible(true);
Util.waitForIdle(robot);
Util.clickOnComp(f0b0, robot);
Util.waitForIdle(robot);
if (!f0b0.isFocusOwner()) {
throw new RuntimeException("Error: can't focus the component " + f0b0);
}
System.out.println("\nTest case 2: awt frame\n");
test(f2b0);
System.out.println("\nTest passed.");
}
public static void test(Component compToClick) {
tracking = true;
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(50);
robot.keyRelease(KeyEvent.VK_TAB);
robot.delay(50);
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(50);
robot.keyRelease(KeyEvent.VK_TAB);
robot.delay(50);
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(50);
robot.keyRelease(KeyEvent.VK_TAB);
robot.delay(50);
Util.clickOnComp(compToClick, robot);
robot.delay(50);
Util.clickOnTitle(f0, robot);
Util.waitForIdle(robot);
if (!f0b3.isFocusOwner()) {
throw new RuntimeException("Test failed: f0b3 is not a focus owner");
}
if (!"sun.awt.X11.XToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) {
if (!Arrays.asList(refGainedList).equals(gainedList)) {
System.out.println("gained list: " + gainedList);
throw new RuntimeException("Test failed: wrong FOCUS_GAINED events order");
}
if (!Arrays.asList(refLostList).equals(lostList)) {
System.out.println("lost list: " + lostList);
throw new RuntimeException("Test failed: wrong FOCUS_LOST events order");
}
}
}
}
class JB extends JButton {
String name;
public JB(String name) {
super(name);
this.name = name;
addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
if (Test1.tracking)
Test1.gainedList.add(e.getComponent());
}
public void focusLost(FocusEvent e) {
if (Test1.tracking)
Test1.lostList.add(e.getComponent());
}
});
}
public String toString() {
return "[" + name + "]";
}
}
/*
* Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 6981400
* @summary Tabbing between textfiled do not work properly when ALT+TAB
* @author anton.tarasov
* @library ../../regtesthelpers
* @build Util
* @run main Test2
*/
// A focus request made after a char is typed ahead shouldn't affect the char's target component.
import java.awt.*;
import java.awt.event.*;
import test.java.awt.regtesthelpers.Util;
public class Test2 {
static Frame f = new Frame("frame");
static TextArea t0 = new TextArea(1, 10) { public String toString() { return "[TA-0]";} };
static TextArea t1 = new TextArea(1, 10) { public String toString() { return "[TA-1]";} };
static TextArea t2 = new TextArea(1, 10) { public String toString() { return "[TA-2]";} };
static volatile boolean passed = true;
static Robot robot;
public static void main(String[] args) {
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
public void eventDispatched(AWTEvent e) {
System.out.println(e);
if (e.getID() == KeyEvent.KEY_TYPED) {
if (e.getSource() != t1) {
passed = false;
throw new RuntimeException("Test failed: the key event has wrong source: " + e);
}
}
}
}, FocusEvent.FOCUS_EVENT_MASK | KeyEvent.KEY_EVENT_MASK);
try {
robot = new Robot();
} catch (AWTException ex) {
throw new RuntimeException("Error: can't create Robot");
}
f.add(t0);
f.add(t1);
f.add(t2);
f.setLayout(new FlowLayout());
f.pack();
t0.addFocusListener(new FocusAdapter() {
public void focusLost(FocusEvent e) {
try {
Thread.sleep(3000);
} catch (Exception ex) {}
}
});
// The request shouldn't affect the key event delivery.
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(2000);
} catch (Exception ex) {}
System.out.println("requesting focus to " + t2);
t2.requestFocus();
}
}).start();
f.setVisible(true);
Util.waitForIdle(robot);
test();
if (passed) System.out.println("\nTest passed.");
}
static void test() {
Util.clickOnComp(t1, robot);
// The key event should be eventually delivered to t1.
robot.delay(50);
robot.keyPress(KeyEvent.VK_A);
robot.delay(50);
robot.keyRelease(KeyEvent.VK_A);
Util.waitForIdle(robot);
}
}
/*
* Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 6981400
* @summary Tabbing between textfiled do not work properly when ALT+TAB
* @author anton.tarasov
* @library ../../regtesthelpers
* @build Util
* @run main Test3
*/
// A menu item in a frame should not be auto-selected when switching by Alt+TAB back and forth.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import test.java.awt.regtesthelpers.Util;
public class Test3 {
static JFrame f = new JFrame("Frame");
static JMenuBar bar = new JMenuBar();
static JMenu menu = new JMenu("File");
static JMenuItem item = new JMenuItem("Save");
static JButton b0 = new JButton("b0");
static JButton b1 = new JButton("b1");
static Robot robot;
public static void main(String[] args) {
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
public void eventDispatched(AWTEvent e) {
System.err.println(e);
}
}, KeyEvent.KEY_EVENT_MASK);
try {
robot = new Robot();
} catch (AWTException ex) {
throw new RuntimeException("Error: can't create Robot");
}
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception e) {}
b0.addFocusListener(new FocusAdapter() {
public void focusLost(FocusEvent f) {
try {
Thread.sleep(2000);
} catch (Exception e) {}
}
});
menu.add(item);
bar.add(menu);
f.setJMenuBar(bar);
f.add(b0);
f.add(b1);
f.setLayout(new FlowLayout());
f.setSize(400, 100);
f.setVisible(true);
Util.waitForIdle(robot);
if (!b0.hasFocus()) {
Util.clickOnComp(b0, robot);
Util.waitForIdle(robot);
if (!b0.hasFocus()) {
throw new RuntimeException("Error: can't focus " + b0);
}
}
test();
System.out.println("Test passed.");
}
public static void test() {
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(50);
robot.keyRelease(KeyEvent.VK_TAB);
robot.delay(50);
robot.keyPress(KeyEvent.VK_ALT);
robot.delay(50);
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(50);
robot.keyRelease(KeyEvent.VK_ALT);
robot.delay(50);
robot.keyRelease(KeyEvent.VK_TAB);
robot.delay(500);
robot.keyPress(KeyEvent.VK_ALT);
robot.delay(50);
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(50);
robot.keyRelease(KeyEvent.VK_ALT);
robot.delay(50);
robot.keyRelease(KeyEvent.VK_TAB);
// Control shot.
Util.clickOnTitle(f, robot);
Util.waitForIdle(robot);
if (menu.isSelected()) {
throw new RuntimeException("Test failed: the menu gets selected");
}
if (!b1.hasFocus()) {
throw new RuntimeException("Test failed: the button is not a focus owner " + b1);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册