提交 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>
if (!target.isFocusOwner() && LWKeyboardFocusManagerPeer.shouldFocusOnClick(target)) {
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
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;
} else if (id == MouseEvent.MOUSE_DRAGGED) {
// Cocoa dragged event has the information about which mouse
......@@ -914,20 +922,16 @@ public class LWWindowPeer
public void dispatchKeyEvent(int id, long when, int modifiers,
int keyCode, char keyChar, int keyLocation)
{
KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
LWKeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
Component focusOwner = kfmPeer.getCurrentFocusOwner();
// Null focus owner may receive key event when
// application hides the focused window upon ESC press
// (AWT transfers/clears the focus owner) and pending ESC release
// may come to already hidden window. This check eliminates NPE.
if (focusOwner != null) {
KeyEvent event =
new KeyEvent(focusOwner, id, when, modifiers,
keyCode, keyChar, keyLocation);
LWComponentPeer peer = (LWComponentPeer)focusOwner.getPeer();
peer.postEvent(event);
if (focusOwner == null) {
focusOwner = kfmPeer.getCurrentFocusedWindow();
if (focusOwner == null) {
focusOwner = this.getTarget();
}
}
postEvent(new KeyEvent(focusOwner, id, when, modifiers, keyCode, keyChar, keyLocation));
}
......@@ -1260,7 +1264,7 @@ public class LWWindowPeer
kfmPeer.setCurrentFocusedWindow(becomesFocused ? getTarget() : null);
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
postEvent(windowEvent);
......
......@@ -30,6 +30,8 @@ import java.awt.Container;
import java.awt.Event;
import java.awt.KeyEventPostProcessor;
import java.awt.Window;
import java.awt.Toolkit;
import sun.awt.SunToolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
......@@ -125,7 +127,19 @@ public class WindowsRootPaneUI extends BasicRootPaneUI {
}
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];
path[0] = mbar;
path[1] = menu;
......
......@@ -4710,7 +4710,10 @@ public abstract class Component implements ImageObserver, MenuContainer,
/*
* 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
......@@ -7606,13 +7609,33 @@ public abstract class Component implements ImageObserver, MenuContainer,
boolean focusedWindowChangeAllowed,
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 (focusLog.isLoggable(PlatformLogger.FINEST)) {
focusLog.finest("requestFocus is not accepted");
}
return false;
}
// Update most-recent map
KeyboardFocusManager.setMostRecentFocusOwner(this);
......@@ -7645,7 +7668,15 @@ public abstract class Component implements ImageObserver, MenuContainer,
}
// 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
(this, temporary, focusedWindowChangeAllowed, time, cause);
if (!success) {
......
......@@ -2863,7 +2863,7 @@ public class Container extends Component {
// keep the KeyEvents from being dispatched
// 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;
if (predictedFocusOwner != null) {
KeyboardFocusManager.getCurrentKeyboardFocusManager().
......
......@@ -40,6 +40,7 @@ import sun.util.logging.PlatformLogger;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
import sun.awt.CausedFocusEvent;
import sun.awt.TimedWindowEvent;
/**
* The default KeyboardFocusManager for AWT applications. Focus traversal is
......@@ -71,8 +72,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
private WeakReference<Window> realOppositeWindowWR = NULL_WINDOW_WR;
private WeakReference<Component> realOppositeComponentWR = NULL_COMPONENT_WR;
private int inSendMessage;
private LinkedList enqueuedKeyEvents = new LinkedList(),
typeAheadMarkers = new LinkedList();
private LinkedList<KeyEvent> enqueuedKeyEvents = new LinkedList<KeyEvent>();
private LinkedList<TypeAheadMarker> typeAheadMarkers = new LinkedList<TypeAheadMarker>();
private boolean consumeNextKeyTyped;
private static class TypeAheadMarker {
......@@ -259,6 +260,31 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
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
* current KeyboardFocusManager dispatch the specified event on its behalf.
......@@ -277,6 +303,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
if (focusLog.isLoggable(PlatformLogger.FINE) && (e instanceof WindowEvent || e instanceof FocusEvent)) focusLog.fine("" + e);
switch (e.getID()) {
case WindowEvent.WINDOW_GAINED_FOCUS: {
if (repostIfFollowsKeyEvents((WindowEvent)e)) {
break;
}
WindowEvent we = (WindowEvent)e;
Window oldFocusedWindow = getGlobalFocusedWindow();
Window newFocusedWindow = we.getWindow();
......@@ -636,6 +666,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
}
case WindowEvent.WINDOW_LOST_FOCUS: {
if (repostIfFollowsKeyEvents((WindowEvent)e)) {
break;
}
WindowEvent we = (WindowEvent)e;
Window currentFocusedWindow = getGlobalFocusedWindow();
Window losingFocusWindow = we.getWindow();
......@@ -815,10 +849,9 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
ke = null;
synchronized (this) {
if (enqueuedKeyEvents.size() != 0) {
ke = (KeyEvent)enqueuedKeyEvents.getFirst();
ke = enqueuedKeyEvents.getFirst();
if (typeAheadMarkers.size() != 0) {
TypeAheadMarker marker = (TypeAheadMarker)
typeAheadMarkers.getFirst();
TypeAheadMarker marker = typeAheadMarkers.getFirst();
// Fixed 5064013: may appears that the events have the same time
// if (ke.getWhen() >= marker.after) {
// The fix is rolled out.
......@@ -847,9 +880,9 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
focusLog.finest(">>> Markers dump, time: {0}", System.currentTimeMillis());
synchronized (this) {
if (typeAheadMarkers.size() != 0) {
Iterator iter = typeAheadMarkers.iterator();
Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator();
while (iter.hasNext()) {
TypeAheadMarker marker = (TypeAheadMarker)iter.next();
TypeAheadMarker marker = iter.next();
focusLog.finest(" {0}", marker);
}
}
......@@ -871,8 +904,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
KeyEvent ke = (KeyEvent)e;
synchronized (this) {
if (e.isPosted && typeAheadMarkers.size() != 0) {
TypeAheadMarker marker = (TypeAheadMarker)
typeAheadMarkers.getFirst();
TypeAheadMarker marker = typeAheadMarkers.getFirst();
// Fixed 5064013: may appears that the events have the same time
// if (ke.getWhen() >= marker.after) {
// The fix is rolled out.
......@@ -905,12 +937,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
synchronized (this) {
boolean found = false;
if (hasMarker(target)) {
for (Iterator iter = typeAheadMarkers.iterator();
for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator();
iter.hasNext(); )
{
if (((TypeAheadMarker)iter.next()).untilFocused ==
target)
{
if (iter.next().untilFocused == target) {
found = true;
} else if (found) {
break;
......@@ -945,8 +975,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
* @since 1.5
*/
private boolean hasMarker(Component comp) {
for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
if (((TypeAheadMarker)iter.next()).untilFocused == comp) {
for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
if (iter.next().untilFocused == comp) {
return true;
}
}
......@@ -972,11 +1002,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
return true;
}
// Explicitly set the current event and most recent timestamp here in
// addition to the call in Component.dispatchEventImpl. Because
// KeyEvents can be delivered in response to a FOCUS_GAINED event, the
// current timestamp may be incorrect. We need to set it here so that
// KeyEventDispatchers will use the correct time.
// Explicitly set the key event timestamp here (not in Component.dispatchEventImpl):
// - A key event is anyway passed to this method which starts its actual dispatching.
// - If a key event is put to the type ahead queue, its time stamp should not be registered
// until its dispatching actually starts (by this method).
EventQueue.setCurrentEventAndMostRecentTime(ke);
/**
......@@ -1164,10 +1193,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
int insertionIndex = 0,
i = typeAheadMarkers.size();
ListIterator iter = typeAheadMarkers.listIterator(i);
ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator(i);
for (; i > 0; i--) {
TypeAheadMarker marker = (TypeAheadMarker)iter.previous();
TypeAheadMarker marker = iter.previous();
if (marker.after <= after) {
insertionIndex = i;
break;
......@@ -1203,12 +1232,12 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
after, untilFocused);
TypeAheadMarker marker;
ListIterator iter = typeAheadMarkers.listIterator
ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator
((after >= 0) ? typeAheadMarkers.size() : 0);
if (after < 0) {
while (iter.hasNext()) {
marker = (TypeAheadMarker)iter.next();
marker = iter.next();
if (marker.untilFocused == untilFocused)
{
iter.remove();
......@@ -1217,7 +1246,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
}
} else {
while (iter.hasPrevious()) {
marker = (TypeAheadMarker)iter.previous();
marker = iter.previous();
if (marker.untilFocused == untilFocused &&
marker.after == after)
{
......@@ -1245,8 +1274,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
long start = -1;
for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
TypeAheadMarker marker = (TypeAheadMarker)iter.next();
for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
TypeAheadMarker marker = iter.next();
Component toTest = marker.untilFocused;
boolean match = (toTest == comp);
while (!match && toTest != null && !(toTest instanceof Window)) {
......@@ -1277,8 +1306,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
return;
}
for (Iterator iter = enqueuedKeyEvents.iterator(); iter.hasNext(); ) {
KeyEvent ke = (KeyEvent)iter.next();
for (Iterator<KeyEvent> iter = enqueuedKeyEvents.iterator(); iter.hasNext(); ) {
KeyEvent ke = iter.next();
long time = ke.getWhen();
if (start < time && (end < 0 || time <= end)) {
......
......@@ -924,7 +924,7 @@ public class Dialog extends Window {
isEnabled() && !isModalBlocked()) {
// keep the KeyEvents from being dispatched
// until the focus has been transfered
time.set(Toolkit.getEventQueue().getMostRecentEventTimeEx());
time.set(Toolkit.getEventQueue().getMostRecentKeyEventTime());
KeyboardFocusManager.getCurrentKeyboardFocusManager().
enqueueKeyEvents(time.get(), toFocus);
}
......
......@@ -163,6 +163,11 @@ public class EventQueue {
*/
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
* InputEvent or ActionEvent.
......@@ -1132,6 +1137,15 @@ public class EventQueue {
}
}
synchronized long getMostRecentKeyEventTime() {
pushPopLock.lock();
try {
return mostRecentKeyEventTime;
} finally {
pushPopLock.unlock();
}
}
static void setCurrentEventAndMostRecentTime(AWTEvent e) {
Toolkit.getEventQueue().setCurrentEventAndMostRecentTimeImpl(e);
}
......@@ -1156,6 +1170,9 @@ public class EventQueue {
if (e instanceof InputEvent) {
InputEvent ie = (InputEvent)e;
mostRecentEventTime2 = ie.getWhen();
if (e instanceof KeyEvent) {
mostRecentKeyEventTime = ie.getWhen();
}
} else if (e instanceof InputMethodEvent) {
InputMethodEvent ime = (InputMethodEvent)e;
mostRecentEventTime2 = ime.getWhen();
......
......@@ -26,6 +26,7 @@
package java.awt;
import java.util.LinkedList;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
......@@ -54,6 +55,17 @@ class SequencedEvent extends AWTEvent implements ActiveEvent {
private AppContext appContext;
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
* nested event.
......
......@@ -486,6 +486,21 @@ public final class AWTAccessor {
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
* corresponding AWT classes by using setters defined below.
......@@ -502,6 +517,7 @@ public final class AWTAccessor {
private static PopupMenuAccessor popupMenuAccessor;
private static FileDialogAccessor fileDialogAccessor;
private static ScrollPaneAdjustableAccessor scrollPaneAdjustableAccessor;
private static SequencedEventAccessor sequencedEventAccessor;
/*
* Set an accessor object for the java.awt.Component class.
......@@ -709,4 +725,21 @@ public final class AWTAccessor {
}
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
if (focusLog.isLoggable(PlatformLogger.FINER))
focusLog.finer("Posting focus event: " + fl);
SunToolkit.postPriorityEvent(fl);
SunToolkit.postEvent(SunToolkit.targetToAppContext(currentOwner), fl);
}
FocusEvent fg = new CausedFocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED,
......@@ -136,7 +136,7 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag
if (focusLog.isLoggable(PlatformLogger.FINER))
focusLog.finer("Posting focus event: " + fg);
SunToolkit.postPriorityEvent(fg);
SunToolkit.postEvent(SunToolkit.targetToAppContext(lightweightChild), fg);
return true;
}
......
......@@ -513,6 +513,19 @@ public abstract class SunToolkit extends Toolkit
if (event == null) {
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.
// Placing the following call here reduces considerably the
// number of places throughout the toolkit that would
......@@ -1964,6 +1977,28 @@ public abstract class SunToolkit extends Toolkit
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
public boolean isWindowOpacitySupported() {
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 {
switch (xev.get_type()) {
case XConstants.ButtonPress:
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);
}
break;
......
......@@ -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() {
return target.getSize();
}
......
......@@ -1477,7 +1477,7 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite,
if (wClassEvent == NULL) {
if (env->PushLocalFrame(1) < 0)
return;
wClassEvent = env->FindClass("java/awt/event/WindowEvent");
wClassEvent = env->FindClass("sun/awt/TimedWindowEvent");
if (wClassEvent != NULL) {
wClassEvent = (jclass)env->NewGlobalRef(wClassEvent);
}
......@@ -1491,7 +1491,7 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite,
if (wEventInitMID == NULL) {
wEventInitMID =
env->GetMethodID(wClassEvent, "<init>",
"(Ljava/awt/Window;ILjava/awt/Window;II)V");
"(Ljava/awt/Window;ILjava/awt/Window;IIJ)V");
DASSERT(wEventInitMID);
if (wEventInitMID == NULL) {
return;
......@@ -1532,7 +1532,7 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite,
}
}
jobject event = env->NewObject(wClassEvent, wEventInitMID, target, id,
jOpposite, oldState, newState);
jOpposite, oldState, newState, TimeHelper::getMessageTimeUTC());
DASSERT(!safe_ExceptionOccurred(env));
DASSERT(event != 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.
先完成此消息的编辑!
想要评论请 注册