--- a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java Wed Sep 05 20:01:40 2012 -0700
@@ -40,6 +40,7 @@
import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
+import java.awt.peer.KeyboardFocusManagerPeer;
import java.util.concurrent.atomic.AtomicBoolean;
import java.lang.reflect.Field;
import java.security.AccessController;
@@ -894,15 +895,15 @@
", focusedWindowChangeAllowed=" + focusedWindowChangeAllowed +
", time= " + time + ", cause=" + cause);
}
- if (LWKeyboardFocusManagerPeer.getInstance(getAppContext()).
- processSynchronousLightweightTransfer(getTarget(), lightweightChild, temporary,
- focusedWindowChangeAllowed, time)) {
+ if (LWKeyboardFocusManagerPeer.processSynchronousLightweightTransfer(
+ getTarget(), lightweightChild, temporary,
+ focusedWindowChangeAllowed, time)) {
return true;
}
- int result = LWKeyboardFocusManagerPeer.getInstance(getAppContext()).
- shouldNativelyFocusHeavyweight(getTarget(), lightweightChild, temporary,
- focusedWindowChangeAllowed, time, cause);
+ int result = LWKeyboardFocusManagerPeer.shouldNativelyFocusHeavyweight(
+ getTarget(), lightweightChild, temporary,
+ focusedWindowChangeAllowed, time, cause);
switch (result) {
case LWKeyboardFocusManagerPeer.SNFH_FAILURE:
return false;
@@ -951,14 +952,13 @@
return false;
}
- LWComponentPeer focusOwnerPeer =
- LWKeyboardFocusManagerPeer.getInstance(getAppContext()).
- getFocusOwner();
- Component focusOwner = (focusOwnerPeer != null) ? focusOwnerPeer.getTarget() : null;
+ KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
+ Component focusOwner = kfmPeer.getCurrentFocusOwner();
return LWKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
getTarget(), temporary,
focusedWindowChangeAllowed,
time, cause, focusOwner);
+
case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
return true;
}
@@ -1251,9 +1251,6 @@
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);
}
}
@@ -1263,8 +1260,8 @@
protected void handleJavaFocusEvent(FocusEvent e) {
// Note that the peer receives all the FocusEvents from
// its lightweight children as well
- LWKeyboardFocusManagerPeer.getInstance(getAppContext()).
- setFocusOwner(e.getID() == FocusEvent.FOCUS_GAINED ? this : null);
+ KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
+ kfmPeer.setCurrentFocusOwner(e.getID() == FocusEvent.FOCUS_GAINED ? getTarget() : null);
}
/**
--- a/jdk/src/macosx/classes/sun/lwawt/LWKeyboardFocusManagerPeer.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/LWKeyboardFocusManagerPeer.java Wed Sep 05 20:01:40 2012 -0700
@@ -26,85 +26,47 @@
package sun.lwawt;
import java.awt.Component;
-import java.awt.KeyboardFocusManager;
import java.awt.Window;
-
-import java.util.Map;
-import java.util.HashMap;
-
-import sun.awt.AWTAccessor;
-import sun.awt.AppContext;
import sun.awt.KeyboardFocusManagerPeerImpl;
public class LWKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
-
- private Object lock = new Object();
- private LWWindowPeer focusedWindow;
- private LWComponentPeer focusOwner;
+ private static final LWKeyboardFocusManagerPeer inst = new LWKeyboardFocusManagerPeer();
- private static Map<KeyboardFocusManager, LWKeyboardFocusManagerPeer> instances =
- new HashMap<KeyboardFocusManager, LWKeyboardFocusManagerPeer>();
+ private Window focusedWindow;
+ private Component focusOwner;
- public static synchronized LWKeyboardFocusManagerPeer getInstance(AppContext ctx) {
- return getInstance(AWTAccessor.getKeyboardFocusManagerAccessor().
- getCurrentKeyboardFocusManager(ctx));
+ public static LWKeyboardFocusManagerPeer getInstance() {
+ return inst;
}
- public static synchronized LWKeyboardFocusManagerPeer getInstance(KeyboardFocusManager manager) {
- LWKeyboardFocusManagerPeer instance = instances.get(manager);
- if (instance == null) {
- instance = new LWKeyboardFocusManagerPeer(manager);
- instances.put(manager, instance);
- }
- return instance;
+ private LWKeyboardFocusManagerPeer() {
}
- public LWKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
- super(manager);
+ @Override
+ public void setCurrentFocusedWindow(Window win) {
+ synchronized (this) {
+ focusedWindow = win;
+ }
}
@Override
public Window getCurrentFocusedWindow() {
- synchronized (lock) {
- return (focusedWindow != null) ? (Window)focusedWindow.getTarget() : null;
+ synchronized (this) {
+ return focusedWindow;
}
}
@Override
public Component getCurrentFocusOwner() {
- synchronized (lock) {
- return (focusOwner != null) ? focusOwner.getTarget() : null;
+ synchronized (this) {
+ return focusOwner;
}
}
@Override
public void setCurrentFocusOwner(Component comp) {
- synchronized (lock) {
- focusOwner = (comp != null) ? (LWComponentPeer)comp.getPeer() : null;
- }
- }
-
- void setFocusedWindow(LWWindowPeer peer) {
- synchronized (lock) {
- focusedWindow = peer;
- }
- }
-
- LWWindowPeer getFocusedWindow() {
- synchronized (lock) {
- return focusedWindow;
- }
- }
-
- void setFocusOwner(LWComponentPeer peer) {
- synchronized (lock) {
- focusOwner = peer;
- }
- }
-
- LWComponentPeer getFocusOwner() {
- synchronized (lock) {
- return focusOwner;
+ synchronized (this) {
+ focusOwner = comp;
}
}
}
--- a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java Wed Sep 05 20:01:40 2012 -0700
@@ -415,8 +415,8 @@
}
@Override
- public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
- return LWKeyboardFocusManagerPeer.getInstance(manager);
+ public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() {
+ return LWKeyboardFocusManagerPeer.getInstance();
}
@Override
--- a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java Wed Sep 05 20:01:40 2012 -0700
@@ -88,10 +88,16 @@
private volatile int windowState = Frame.NORMAL;
+ // check that the mouse is over the window
+ private volatile boolean isMouseOver = false;
+
+ // A peer where the last mouse event came to. Used by cursor manager to
+ // find the component under cursor
+ private static volatile LWComponentPeer lastCommonMouseEventPeer = null;
+
// A peer where the last mouse event came to. Used to generate
- // MOUSE_ENTERED/EXITED notifications and by cursor manager to
- // find the component under cursor
- private static volatile LWComponentPeer lastMouseEventPeer = null;
+ // MOUSE_ENTERED/EXITED notifications
+ private volatile LWComponentPeer lastMouseEventPeer;
// Peers where all dragged/released events should come to,
// depending on what mouse button is being dragged according to Cocoa
@@ -232,8 +238,7 @@
// TODO: update graphicsConfig, see 4868278
platformWindow.setVisible(visible);
if (isSimpleWindow()) {
- LWKeyboardFocusManagerPeer manager = LWKeyboardFocusManagerPeer.
- getInstance(getAppContext());
+ KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
if (visible) {
if (!getTarget().isAutoRequestFocus()) {
@@ -242,7 +247,7 @@
requestWindowFocus(CausedFocusEvent.Cause.ACTIVATION);
}
// Focus the owner in case this window is focused.
- } else if (manager.getCurrentFocusedWindow() == getTarget()) {
+ } else if (kfmPeer.getCurrentFocusedWindow() == getTarget()) {
// Transfer focus to the owner.
LWWindowPeer owner = getOwnerFrameDialog(LWWindowPeer.this);
if (owner != null) {
@@ -707,66 +712,65 @@
Rectangle r = getBounds();
// findPeerAt() expects parent coordinates
LWComponentPeer targetPeer = findPeerAt(r.x + x, r.y + y);
- LWWindowPeer lastWindowPeer =
- (lastMouseEventPeer != null) ? lastMouseEventPeer.getWindowPeerOrSelf() : null;
- LWWindowPeer curWindowPeer =
- (targetPeer != null) ? targetPeer.getWindowPeerOrSelf() : null;
if (id == MouseEvent.MOUSE_EXITED) {
- // Sometimes we may get MOUSE_EXITED after lastMouseEventPeer is switched
- // to a peer from another window. So we must first check if this peer is
- // the same as lastWindowPeer
- if (lastWindowPeer == this) {
- if (isEnabled()) {
+ isMouseOver = false;
+ if (lastMouseEventPeer != null) {
+ if (lastMouseEventPeer.isEnabled()) {
Point lp = lastMouseEventPeer.windowToLocal(x, y,
- lastWindowPeer);
+ this);
postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
- MouseEvent.MOUSE_EXITED, when,
- modifiers, lp.x, lp.y, screenX,
- screenY, clickCount, popupTrigger,
- button));
+ MouseEvent.MOUSE_EXITED, when,
+ modifiers, lp.x, lp.y, screenX,
+ screenY, clickCount, popupTrigger,
+ button));
+ }
+
+ // Sometimes we may get MOUSE_EXITED after lastCommonMouseEventPeer is switched
+ // to a peer from another window. So we must first check if this peer is
+ // the same as lastWindowPeer
+ if (lastCommonMouseEventPeer != null && lastCommonMouseEventPeer.getWindowPeerOrSelf() == this) {
+ lastCommonMouseEventPeer = null;
}
lastMouseEventPeer = null;
}
- } else {
- if (targetPeer != lastMouseEventPeer) {
-
- if (id != MouseEvent.MOUSE_DRAGGED || lastMouseEventPeer == null) {
- // lastMouseEventPeer may be null if mouse was out of Java windows
- if (lastMouseEventPeer != null && lastMouseEventPeer.isEnabled()) {
- // Sometimes, MOUSE_EXITED is not sent by delegate (or is sent a bit
- // later), in which case lastWindowPeer is another window
- if (lastWindowPeer != this) {
- Point oldp = lastMouseEventPeer.windowToLocal(x, y, lastWindowPeer);
- // Additionally translate from this to lastWindowPeer coordinates
- Rectangle lr = lastWindowPeer.getBounds();
- oldp.x += r.x - lr.x;
- oldp.y += r.y - lr.y;
- postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
- MouseEvent.MOUSE_EXITED,
- when, modifiers,
- oldp.x, oldp.y, screenX, screenY,
- clickCount, popupTrigger, button));
- } else {
- Point oldp = lastMouseEventPeer.windowToLocal(x, y, this);
- postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
- MouseEvent.MOUSE_EXITED,
- when, modifiers,
- oldp.x, oldp.y, screenX, screenY,
- clickCount, popupTrigger, button));
- }
- }
- if (targetPeer != null && targetPeer.isEnabled() && id != MouseEvent.MOUSE_ENTERED) {
- Point newp = targetPeer.windowToLocal(x, y, curWindowPeer);
+ } else if(id == MouseEvent.MOUSE_ENTERED) {
+ isMouseOver = true;
+ if (targetPeer != null) {
+ if (targetPeer.isEnabled()) {
+ Point lp = targetPeer.windowToLocal(x, y, this);
postEvent(new MouseEvent(targetPeer.getTarget(),
- MouseEvent.MOUSE_ENTERED,
- when, modifiers,
- newp.x, newp.y, screenX, screenY,
- clickCount, popupTrigger, button));
- }
+ MouseEvent.MOUSE_ENTERED, when,
+ modifiers, lp.x, lp.y, screenX,
+ screenY, clickCount, popupTrigger,
+ button));
}
+ lastCommonMouseEventPeer = targetPeer;
lastMouseEventPeer = targetPeer;
}
+ } else {
+ PlatformWindow topmostPlatforWindow =
+ platformWindow.getTopmostPlatformWindowUnderMouse();
+
+ LWWindowPeer topmostWindowPeer =
+ topmostPlatforWindow != null ? topmostPlatforWindow.getPeer() : null;
+
+ // topmostWindowPeer == null condition is added for the backward
+ // compatibility with applets. It can be removed when the
+ // getTopmostPlatformWindowUnderMouse() method will be properly
+ // implemented in CPlatformEmbeddedFrame class
+ if (topmostWindowPeer == this || topmostWindowPeer == null) {
+ generateMouseEnterExitEventsForComponents(when, button, x, y,
+ screenX, screenY, modifiers, clickCount, popupTrigger,
+ targetPeer);
+ } else {
+ LWComponentPeer topmostTargetPeer =
+ topmostWindowPeer != null ? topmostWindowPeer.findPeerAt(r.x + x, r.y + y) : null;
+ topmostWindowPeer.generateMouseEnterExitEventsForComponents(when, button, x, y,
+ screenX, screenY, modifiers, clickCount, popupTrigger,
+ topmostTargetPeer);
+ }
+
// TODO: fill "bdata" member of AWTEvent
int eventButtonMask = (button > 0)? MouseEvent.getMaskForButton(button) : 0;
@@ -794,6 +798,14 @@
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
@@ -816,19 +828,13 @@
// mouseClickButtons is updated below, after MOUSE_CLICK is sent
}
- // check if we receive mouseEvent from outside the window's bounds
- // it can be either mouseDragged or mouseReleased
- if (curWindowPeer == null) {
- //TODO This can happen if this window is invisible. this is correct behavior in this case?
- curWindowPeer = this;
- }
if (targetPeer == null) {
//TODO This can happen if this window is invisible. this is correct behavior in this case?
targetPeer = this;
}
- Point lp = targetPeer.windowToLocal(x, y, curWindowPeer);
+ Point lp = targetPeer.windowToLocal(x, y, this);
if (targetPeer.isEnabled()) {
MouseEvent event = new MouseEvent(targetPeer.getTarget(), id,
when, modifiers, lp.x, lp.y,
@@ -852,6 +858,38 @@
notifyUpdateCursor();
}
+ private void generateMouseEnterExitEventsForComponents(long when,
+ int button, int x, int y, int screenX, int screenY,
+ int modifiers, int clickCount, boolean popupTrigger,
+ LWComponentPeer targetPeer) {
+
+ if (!isMouseOver || targetPeer == lastMouseEventPeer) {
+ return;
+ }
+
+ // Generate Mouse Exit for components
+ if (lastMouseEventPeer != null && lastMouseEventPeer.isEnabled()) {
+ Point oldp = lastMouseEventPeer.windowToLocal(x, y, this);
+ postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
+ MouseEvent.MOUSE_EXITED,
+ when, modifiers,
+ oldp.x, oldp.y, screenX, screenY,
+ clickCount, popupTrigger, button));
+ }
+ lastCommonMouseEventPeer = targetPeer;
+ lastMouseEventPeer = targetPeer;
+
+ // Generate Mouse Enter for components
+ if (targetPeer != null && targetPeer.isEnabled()) {
+ Point newp = targetPeer.windowToLocal(x, y, this);
+ postEvent(new MouseEvent(targetPeer.getTarget(),
+ MouseEvent.MOUSE_ENTERED,
+ when, modifiers,
+ newp.x, newp.y, screenX, screenY,
+ clickCount, popupTrigger, button));
+ }
+ }
+
public void dispatchMouseWheelEvent(long when, int x, int y, int modifiers,
int scrollType, int scrollAmount,
int wheelRotation, double preciseWheelRotation,
@@ -884,20 +922,16 @@
public void dispatchKeyEvent(int id, long when, int modifiers,
int keyCode, char keyChar, int keyLocation)
{
- LWComponentPeer focusOwner =
- LWKeyboardFocusManagerPeer.getInstance(getAppContext()).
- getFocusOwner();
+ 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.getTarget(), id, when, modifiers,
- keyCode, keyChar, keyLocation);
- focusOwner.postEvent(event);
+ if (focusOwner == null) {
+ focusOwner = kfmPeer.getCurrentFocusedWindow();
+ if (focusOwner == null) {
+ focusOwner = this.getTarget();
+ }
}
+ postEvent(new KeyEvent(focusOwner, id, when, modifiers, keyCode, keyChar, keyLocation));
}
@@ -1096,11 +1130,11 @@
}
public static LWWindowPeer getWindowUnderCursor() {
- return lastMouseEventPeer != null ? lastMouseEventPeer.getWindowPeerOrSelf() : null;
+ return lastCommonMouseEventPeer != null ? lastCommonMouseEventPeer.getWindowPeerOrSelf() : null;
}
public static LWComponentPeer<?, ?> getPeerUnderCursor() {
- return lastMouseEventPeer;
+ return lastCommonMouseEventPeer;
}
/*
@@ -1213,10 +1247,8 @@
}
}
- LWKeyboardFocusManagerPeer manager = LWKeyboardFocusManagerPeer.
- getInstance(getAppContext());
-
- Window oppositeWindow = becomesFocused ? manager.getCurrentFocusedWindow() : null;
+ KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
+ Window oppositeWindow = becomesFocused ? kfmPeer.getCurrentFocusedWindow() : null;
// Note, the method is not called:
// - when the opposite (gaining focus) window is an owned/owner window.
@@ -1229,10 +1261,10 @@
grabbingWindow.ungrab();
}
- manager.setFocusedWindow(becomesFocused ? LWWindowPeer.this : null);
+ 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);
--- a/jdk/src/macosx/classes/sun/lwawt/PlatformWindow.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/PlatformWindow.java Wed Sep 05 20:01:40 2012 -0700
@@ -118,6 +118,8 @@
public void setAlwaysOnTop(boolean value);
+ public PlatformWindow getTopmostPlatformWindowUnderMouse();
+
public void updateFocusableWindowState();
public boolean rejectFocusRequest(CausedFocusEvent.Cause cause);
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java Wed Sep 05 20:01:40 2012 -0700
@@ -151,6 +151,10 @@
@Override
public void setAlwaysOnTop(boolean value) {}
+ // This method should be properly implemented for applets.
+ // It returns null just as a stub.
+ public PlatformWindow getTopmostPlatformWindowUnderMouse() { return null; }
+
@Override
public void updateFocusableWindowState() {}
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Sep 05 20:01:40 2012 -0700
@@ -61,8 +61,9 @@
private static native void nativeSetNSWindowRepresentedFilename(long nsWindowPtr, String representedFilename);
private static native void nativeSetNSWindowSecurityWarningPositioning(long nsWindowPtr, double x, double y, float biasX, float biasY);
private static native void nativeSetEnabled(long nsWindowPtr, boolean isEnabled);
- private static native void nativeSynthesizeMouseEnteredExitedEvents(long nsWindowPtr);
+ private static native void nativeSynthesizeMouseEnteredExitedEvents();
private static native void nativeDispose(long nsWindowPtr);
+ private static native CPlatformWindow nativeGetTopmostPlatformWindowUnderMouse();
private static native int nativeGetNSWindowDisplayID_AppKitThread(long nsWindowPtr);
@@ -588,7 +589,7 @@
}
}
- nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr);
+ nativeSynthesizeMouseEnteredExitedEvents();
// Configure stuff #2
updateFocusabilityForAutoRequestFocus(true);
@@ -729,6 +730,10 @@
setStyleBits(ALWAYS_ON_TOP, isAlwaysOnTop);
}
+ public PlatformWindow getTopmostPlatformWindowUnderMouse(){
+ return CPlatformWindow.nativeGetTopmostPlatformWindowUnderMouse();
+ }
+
@Override
public void setOpacity(float opacity) {
CWrapper.NSWindow.setAlphaValue(getNSWindowPtr(), opacity);
@@ -803,7 +808,7 @@
throw new RuntimeException("Unknown window state: " + windowState);
}
- nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr);
+ nativeSynthesizeMouseEnteredExitedEvents();
// NOTE: the SWP.windowState field gets updated to the newWindowState
// value when the native notification comes to us
--- a/jdk/src/macosx/native/sun/awt/AWTView.h Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/macosx/native/sun/awt/AWTView.h Wed Sep 05 20:01:40 2012 -0700
@@ -33,8 +33,8 @@
@private
jobject m_cPlatformView;
- // Handler for the tracking rect needed for Enter/Exit events management.
- NSTrackingRectTag rolloverTrackingRectTag;
+ // Handler for the tracking area needed for Enter/Exit events management.
+ NSTrackingArea* rolloverTrackingArea;
// TODO: NSMenu *contextualMenu;
@@ -61,7 +61,7 @@
- (id) initWithRect:(NSRect) rect platformView:(jobject)cPlatformView windowLayer:(CALayer*)windowLayer;
- (void) deliverJavaMouseEvent: (NSEvent *) event;
-- (void) resetTrackingRect;
+- (void) resetTrackingArea;
- (void) deliverJavaKeyEventHelper: (NSEvent *) event;
- (jobject) awtComponent:(JNIEnv *)env;
--- a/jdk/src/macosx/native/sun/awt/AWTView.m Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/macosx/native/sun/awt/AWTView.m Wed Sep 05 20:01:40 2012 -0700
@@ -82,6 +82,7 @@
fPAHNeedsToSelect = NO;
mouseIsOver = NO;
+ [self resetTrackingArea];
if (windowLayer != nil) {
self.cglLayer = windowLayer;
@@ -146,7 +147,7 @@
[[self window] makeFirstResponder: self];
}];
if ([self window] != NULL) {
- [self resetTrackingRect];
+ [self resetTrackingArea];
}
}
@@ -368,30 +369,31 @@
JNFCallVoidMethod(env, m_cPlatformView, jm_deliverMouseEvent, jEvent);
}
-
-- (void) clearTrackingRect {
- if (rolloverTrackingRectTag > 0) {
- [self removeTrackingRect:rolloverTrackingRectTag];
- rolloverTrackingRectTag = 0;
+- (void) resetTrackingArea {
+ if (rolloverTrackingArea != nil) {
+ [self removeTrackingArea:rolloverTrackingArea];
+ [rolloverTrackingArea release];
}
-}
+
+ int options = (NSTrackingActiveInActiveApp | NSTrackingMouseEnteredAndExited |
+ NSTrackingMouseMoved | NSTrackingEnabledDuringMouseDrag);
-- (void) resetTrackingRect {
- [self clearTrackingRect];
- rolloverTrackingRectTag = [self addTrackingRect:[self visibleRect]
- owner:self
- userData:NULL
- assumeInside:NO];
+ rolloverTrackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect]
+ options: options
+ owner:self
+ userInfo:nil
+ ];
+ [self addTrackingArea:rolloverTrackingArea];
}
- (void)updateTrackingAreas {
[super updateTrackingAreas];
- [self resetTrackingRect];
+ [self resetTrackingArea];
}
- (void) resetCursorRects {
[super resetCursorRects];
- [self resetTrackingRect];
+ [self resetTrackingArea];
}
-(void) deliverJavaKeyEventHelper: (NSEvent *) event {
@@ -402,7 +404,7 @@
}
[sLastKeyEvent release];
sLastKeyEvent = [event retain];
-
+
[AWTToolkit eventCountPlusPlus];
JNIEnv *env = [ThreadUtilities getJNIEnv];
--- a/jdk/src/macosx/native/sun/awt/AWTWindow.m Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m Wed Sep 05 20:01:40 2012 -0700
@@ -238,10 +238,12 @@
return self;
}
-// checks that this window is under the mouse cursor and this point is not overlapped by others windows
-- (BOOL) isTopmostWindowUnderMouse {
++ (BOOL) isAWTWindow:(NSWindow *)window {
+ return [window isKindOfClass: [AWTWindow_Panel class]] || [window isKindOfClass: [AWTWindow_Normal class]];
+}
- int currentWinID = [self.nsWindow windowNumber];
+// returns id for the topmost window under mouse
++ (NSInteger) getTopmostWindowUnderMouseID {
NSRect screenRect = [[NSScreen mainScreen] frame];
NSPoint nsMouseLocation = [NSEvent mouseLocation];
@@ -249,53 +251,77 @@
NSMutableArray *windows = (NSMutableArray *)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
-
for (NSDictionary *window in windows) {
- int layer = [[window objectForKey:(id)kCGWindowLayer] intValue];
+ NSInteger layer = [[window objectForKey:(id)kCGWindowLayer] integerValue];
if (layer == 0) {
- int winID = [[window objectForKey:(id)kCGWindowNumber] intValue];
CGRect rect;
CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect);
if (CGRectContainsPoint(rect, cgMouseLocation)) {
- return currentWinID == winID;
- } else if (currentWinID == winID) {
- return NO;
+ return [[window objectForKey:(id)kCGWindowNumber] integerValue];
}
}
}
- return NO;
+ return -1;
+}
+
+// checks that this window is under the mouse cursor and this point is not overlapped by others windows
+- (BOOL) isTopmostWindowUnderMouse {
+ return [self.nsWindow windowNumber] == [AWTWindow getTopmostWindowUnderMouseID];
}
-- (void) synthesizeMouseEnteredExitedEvents {
++ (AWTWindow *) getTopmostWindowUnderMouse {
+ NSEnumerator *windowEnumerator = [[NSApp windows] objectEnumerator];
+ NSWindow *window;
- int eventType = 0;
- BOOL isUnderMouse = [self isTopmostWindowUnderMouse];
- BOOL mouseIsOver = [[self.nsWindow contentView] mouseIsOver];
+ NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID];
- if (isUnderMouse && !mouseIsOver) {
- eventType = NSMouseEntered;
- } else if (!isUnderMouse && mouseIsOver) {
- eventType = NSMouseExited;
- } else {
- return;
+ while ((window = [windowEnumerator nextObject]) != nil) {
+ if ([window windowNumber] == topmostWindowUnderMouseID) {
+ BOOL isAWTWindow = [AWTWindow isAWTWindow: window];
+ return isAWTWindow ? (AWTWindow *) [window delegate] : nil;
+ }
}
+ return nil;
+}
+
++ (void) synthesizeMouseEnteredExitedEvents:(NSWindow*)window withType:(NSEventType)eventType {
NSPoint screenLocation = [NSEvent mouseLocation];
- NSPoint windowLocation = [self.nsWindow convertScreenToBase: screenLocation];
+ NSPoint windowLocation = [window convertScreenToBase: screenLocation];
int modifierFlags = (eventType == NSMouseEntered) ? NSMouseEnteredMask : NSMouseExitedMask;
NSEvent *mouseEvent = [NSEvent enterExitEventWithType: eventType
- location: windowLocation
- modifierFlags: modifierFlags
- timestamp: 0
- windowNumber: [self.nsWindow windowNumber]
- context: nil
- eventNumber: 0
- trackingNumber: 0
- userData: nil
- ];
+ location: windowLocation
+ modifierFlags: modifierFlags
+ timestamp: 0
+ windowNumber: [window windowNumber]
+ context: nil
+ eventNumber: 0
+ trackingNumber: 0
+ userData: nil
+ ];
+
+ [[window contentView] deliverJavaMouseEvent: mouseEvent];
+}
+
++ (void) synthesizeMouseEnteredExitedEventsForAllWindows {
- [[self.nsWindow contentView] deliverJavaMouseEvent: mouseEvent];
+ NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID];
+ NSArray *windows = [NSApp windows];
+ NSWindow *window;
+
+ NSEnumerator *windowEnumerator = [windows objectEnumerator];
+ while ((window = [windowEnumerator nextObject]) != nil) {
+ if ([AWTWindow isAWTWindow: window]) {
+ BOOL isUnderMouse = ([window windowNumber] == topmostWindowUnderMouseID);
+ BOOL mouseIsOver = [[window contentView] mouseIsOver];
+ if (isUnderMouse && !mouseIsOver) {
+ [AWTWindow synthesizeMouseEnteredExitedEvents:window withType:NSMouseEntered];
+ } else if (!isUnderMouse && mouseIsOver) {
+ [AWTWindow synthesizeMouseEnteredExitedEvents:window withType:NSMouseExited];
+ }
+ }
+ }
}
- (void) dealloc {
@@ -825,7 +851,7 @@
// (this will also re-enable screen updates, which were disabled above)
// TODO: send PaintEvent
- [window synthesizeMouseEnteredExitedEvents];
+ [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
}];
JNF_COCOA_EXIT(env);
@@ -1040,22 +1066,42 @@
/*
* Class: sun_lwawt_macosx_CPlatformWindow
+ * Method: nativeGetTopmostPlatformWindowUnderMouse
+ * Signature: (J)V
+ */
+JNIEXPORT jobject
+JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetTopmostPlatformWindowUnderMouse
+(JNIEnv *env, jclass clazz)
+{
+ jobject topmostWindowUnderMouse = nil;
+
+ JNF_COCOA_ENTER(env);
+ AWT_ASSERT_APPKIT_THREAD;
+
+ AWTWindow *awtWindow = [AWTWindow getTopmostWindowUnderMouse];
+ if (awtWindow != nil) {
+ topmostWindowUnderMouse = [awtWindow.javaPlatformWindow jObject];
+ }
+
+ JNF_COCOA_EXIT(env);
+
+ return topmostWindowUnderMouse;
+}
+
+/*
+ * Class: sun_lwawt_macosx_CPlatformWindow
* Method: nativeSynthesizeMouseEnteredExitedEvents
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents
-(JNIEnv *env, jclass clazz, jlong windowPtr)
+(JNIEnv *env, jclass clazz)
{
JNF_COCOA_ENTER(env);
AWT_ASSERT_NOT_APPKIT_THREAD;
- NSWindow *nsWindow = OBJC(windowPtr);
[JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
AWT_ASSERT_APPKIT_THREAD;
-
- AWTWindow *window = (AWTWindow*)[nsWindow delegate];
-
- [window synthesizeMouseEnteredExitedEvents];
+ [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
}];
JNF_COCOA_EXIT(env);
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java Wed Sep 05 20:01:40 2012 -0700
@@ -30,6 +30,8 @@
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 @@
}
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;
--- a/jdk/src/share/classes/java/awt/Component.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/java/awt/Component.java Wed Sep 05 20:01:40 2012 -0700
@@ -4710,7 +4710,10 @@
/*
* 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 @@
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 @@
}
// 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) {
--- a/jdk/src/share/classes/java/awt/Container.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/java/awt/Container.java Wed Sep 05 20:01:40 2012 -0700
@@ -2863,7 +2863,7 @@
// 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().
--- a/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java Wed Sep 05 20:01:40 2012 -0700
@@ -41,6 +41,7 @@
import sun.awt.SunToolkit;
import sun.awt.AWTAccessor;
import sun.awt.CausedFocusEvent;
+import sun.awt.TimedWindowEvent;
/**
* The default KeyboardFocusManager for AWT applications. Focus traversal is
@@ -72,8 +73,8 @@
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;
static {
@@ -269,6 +270,31 @@
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.
@@ -287,6 +313,10 @@
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();
@@ -646,6 +676,10 @@
}
case WindowEvent.WINDOW_LOST_FOCUS: {
+ if (repostIfFollowsKeyEvents((WindowEvent)e)) {
+ break;
+ }
+
WindowEvent we = (WindowEvent)e;
Window currentFocusedWindow = getGlobalFocusedWindow();
Window losingFocusWindow = we.getWindow();
@@ -825,10 +859,9 @@
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.
@@ -857,9 +890,9 @@
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);
}
}
@@ -881,8 +914,7 @@
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.
@@ -915,12 +947,10 @@
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;
@@ -955,8 +985,8 @@
* @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;
}
}
@@ -982,11 +1012,10 @@
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);
/**
@@ -1174,10 +1203,10 @@
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;
@@ -1213,12 +1242,12 @@
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();
@@ -1227,7 +1256,7 @@
}
} else {
while (iter.hasPrevious()) {
- marker = (TypeAheadMarker)iter.previous();
+ marker = iter.previous();
if (marker.untilFocused == untilFocused &&
marker.after == after)
{
@@ -1255,8 +1284,8 @@
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)) {
@@ -1287,8 +1316,8 @@
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)) {
--- a/jdk/src/share/classes/java/awt/Dialog.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/java/awt/Dialog.java Wed Sep 05 20:01:40 2012 -0700
@@ -924,7 +924,7 @@
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);
}
--- a/jdk/src/share/classes/java/awt/EventQueue.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/java/awt/EventQueue.java Wed Sep 05 20:01:40 2012 -0700
@@ -162,6 +162,11 @@
*/
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.
@@ -1142,6 +1147,15 @@
}
}
+ synchronized long getMostRecentKeyEventTime() {
+ pushPopLock.lock();
+ try {
+ return mostRecentKeyEventTime;
+ } finally {
+ pushPopLock.unlock();
+ }
+ }
+
static void setCurrentEventAndMostRecentTime(AWTEvent e) {
Toolkit.getEventQueue().setCurrentEventAndMostRecentTimeImpl(e);
}
@@ -1166,6 +1180,9 @@
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();
--- a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java Wed Sep 05 20:01:40 2012 -0700
@@ -445,7 +445,7 @@
private void initPeer() {
Toolkit tk = Toolkit.getDefaultToolkit();
KeyboardFocusManagerPeerProvider peerProvider = (KeyboardFocusManagerPeerProvider)tk;
- peer = peerProvider.createKeyboardFocusManagerPeer(this);
+ peer = peerProvider.getKeyboardFocusManagerPeer();
}
/**
--- a/jdk/src/share/classes/java/awt/SequencedEvent.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/java/awt/SequencedEvent.java Wed Sep 05 20:01:40 2012 -0700
@@ -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 @@
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.
--- a/jdk/src/share/classes/java/awt/peer/KeyboardFocusManagerPeer.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/java/awt/peer/KeyboardFocusManagerPeer.java Wed Sep 05 20:01:40 2012 -0700
@@ -34,6 +34,14 @@
public interface KeyboardFocusManagerPeer {
/**
+ * Sets the window that should become the focused window.
+ *
+ * @param win the window that should become the focused window
+ *
+ */
+ void setCurrentFocusedWindow(Window win);
+
+ /**
* Returns the currently focused window.
*
* @return the currently focused window
--- a/jdk/src/share/classes/java/beans/Introspector.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/java/beans/Introspector.java Wed Sep 05 20:01:40 2012 -0700
@@ -1460,7 +1460,7 @@
private PropertyDescriptor[] properties;
private int defaultProperty;
private MethodDescriptor[] methods;
- private final Reference<BeanInfo> targetBeanInfoRef;
+ private Reference<BeanInfo> targetBeanInfoRef;
public GenericBeanInfo(BeanDescriptor beanDescriptor,
EventSetDescriptor[] events, int defaultEvent,
@@ -1472,7 +1472,9 @@
this.properties = properties;
this.defaultProperty = defaultProperty;
this.methods = methods;
- this.targetBeanInfoRef = new SoftReference<>(targetBeanInfo);
+ this.targetBeanInfoRef = (targetBeanInfo != null)
+ ? new SoftReference<>(targetBeanInfo)
+ : null;
}
/**
@@ -1539,10 +1541,25 @@
}
public java.awt.Image getIcon(int iconKind) {
- BeanInfo targetBeanInfo = this.targetBeanInfoRef.get();
+ BeanInfo targetBeanInfo = getTargetBeanInfo();
if (targetBeanInfo != null) {
return targetBeanInfo.getIcon(iconKind);
}
return super.getIcon(iconKind);
}
+
+ private BeanInfo getTargetBeanInfo() {
+ if (this.targetBeanInfoRef == null) {
+ return null;
+ }
+ BeanInfo targetBeanInfo = this.targetBeanInfoRef.get();
+ if (targetBeanInfo == null) {
+ targetBeanInfo = ThreadGroupContext.getContext().getBeanInfoFinder()
+ .find(this.beanDescriptor.getBeanClass());
+ if (targetBeanInfo != null) {
+ this.targetBeanInfoRef = new SoftReference<>(targetBeanInfo);
+ }
+ }
+ return targetBeanInfo;
+ }
}
--- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java Wed Sep 05 20:01:40 2012 -0700
@@ -109,6 +109,10 @@
if (writeMethodName != null && getWriteMethod() == null) {
throw new IntrospectionException("Method not found: " + writeMethodName);
}
+ boundInitialization(beanClass);
+ }
+
+ private void boundInitialization(Class<?> beanClass) {
// If this class or one of its base classes allow PropertyChangeListener,
// then we assume that any properties we discover are "bound".
// See Introspector.getTargetPropertyInfo() method.
@@ -159,6 +163,7 @@
setReadMethod(read);
setWriteMethod(write);
this.baseName = base;
+ boundInitialization(bean);
}
/**
@@ -588,7 +593,7 @@
Method yw = y.getWriteMethod();
try {
- if (yw != null && yw.getDeclaringClass() == getClass0()) {
+ if (yw != null) {
setWriteMethod(yw);
} else {
setWriteMethod(xw);
--- a/jdk/src/share/classes/java/beans/XMLEncoder.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/java/beans/XMLEncoder.java Wed Sep 05 20:01:40 2012 -0700
@@ -631,7 +631,12 @@
}
if (d.name != null) {
- outputXML(isArgument ? "object" : "void", " idref=" + quote(d.name), value);
+ if (isArgument) {
+ writeln("<object idref=" + quote(d.name) + "/>");
+ }
+ else {
+ outputXML("void", " idref=" + quote(d.name), value);
+ }
}
else if (d.exp != null) {
outputStatement(d.exp, outer, isArgument);
@@ -710,12 +715,14 @@
}
else {
d.refs = 2;
- getValueData(target).refs++;
- List<Statement> statements = statementList(target);
- if (!statements.contains(exp)) {
- statements.add(exp);
+ if (d.name == null) {
+ getValueData(target).refs++;
+ List<Statement> statements = statementList(target);
+ if (!statements.contains(exp)) {
+ statements.add(exp);
+ }
+ outputValue(target, outer, false);
}
- outputValue(target, outer, false);
if (expression) {
outputValue(value, outer, isArgument);
}
--- a/jdk/src/share/classes/sun/awt/AWTAccessor.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java Wed Sep 05 20:01:40 2012 -0700
@@ -667,6 +667,21 @@
}
/*
+ * 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.
*/
@@ -692,6 +707,7 @@
private static SystemTrayAccessor systemTrayAccessor;
private static TrayIconAccessor trayIconAccessor;
private static DefaultKeyboardFocusManagerAccessor defaultKeyboardFocusManagerAccessor;
+ private static SequencedEventAccessor sequencedEventAccessor;
/*
* Set an accessor object for the java.awt.Component class.
@@ -1069,4 +1085,20 @@
}
return defaultKeyboardFocusManagerAccessor;
}
+ /*
+ * 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;
+ }
}
--- a/jdk/src/share/classes/sun/awt/HToolkit.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/sun/awt/HToolkit.java Wed Sep 05 20:01:40 2012 -0700
@@ -44,6 +44,14 @@
public class HToolkit extends SunToolkit
implements ComponentFactory {
+ private static final KeyboardFocusManagerPeer kfmPeer = new KeyboardFocusManagerPeer() {
+ public void setCurrentFocusedWindow(Window win) {}
+ public Window getCurrentFocusedWindow() { return null; }
+ public void setCurrentFocusOwner(Component comp) {}
+ public Component getCurrentFocusOwner() { return null; }
+ public void clearGlobalFocusOwner(Window activeWindow) {}
+ };
+
public HToolkit() {
}
@@ -152,15 +160,9 @@
throw new HeadlessException();
}
- public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
+ public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() {
// See 6833019.
- return
- new KeyboardFocusManagerPeer() {
- public Window getCurrentFocusedWindow() { return null; }
- public void setCurrentFocusOwner(Component comp) {}
- public Component getCurrentFocusOwner() { return null; }
- public void clearGlobalFocusOwner(Window activeWindow) {}
- };
+ return kfmPeer;
}
public TrayIconPeer createTrayIcon(TrayIcon target)
--- a/jdk/src/share/classes/sun/awt/HeadlessToolkit.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/sun/awt/HeadlessToolkit.java Wed Sep 05 20:01:40 2012 -0700
@@ -30,22 +30,25 @@
import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.event.*;
import java.awt.im.InputMethodHighlight;
-import java.awt.im.spi.InputMethodDescriptor;
import java.awt.image.*;
import java.awt.datatransfer.Clipboard;
import java.awt.peer.*;
import java.beans.PropertyChangeListener;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.Map;
import java.util.Properties;
-import sun.awt.im.InputContext;
-import sun.awt.image.ImageRepresentation;
public class HeadlessToolkit extends Toolkit
implements ComponentFactory, KeyboardFocusManagerPeerProvider {
+ private static final KeyboardFocusManagerPeer kfmPeer = new KeyboardFocusManagerPeer() {
+ public void setCurrentFocusedWindow(Window win) {}
+ public Window getCurrentFocusedWindow() { return null; }
+ public void setCurrentFocusOwner(Component comp) {}
+ public Component getCurrentFocusOwner() { return null; }
+ public void clearGlobalFocusOwner(Window activeWindow) {}
+ };
+
private Toolkit tk;
private ComponentFactory componentFactory;
@@ -179,15 +182,9 @@
throw new HeadlessException();
}
- public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
+ public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() {
// See 6833019.
- return
- new KeyboardFocusManagerPeer() {
- public Window getCurrentFocusedWindow() { return null; }
- public void setCurrentFocusOwner(Component comp) {}
- public Component getCurrentFocusOwner() { return null; }
- public void clearGlobalFocusOwner(Window activeWindow) {}
- };
+ return kfmPeer;
}
public TrayIconPeer createTrayIcon(TrayIcon target)
--- a/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java Wed Sep 05 20:01:40 2012 -0700
@@ -53,12 +53,6 @@
public static final int SNFH_SUCCESS_HANDLED = 1;
public static final int SNFH_SUCCESS_PROCEED = 2;
- protected KeyboardFocusManager manager;
-
- public KeyboardFocusManagerPeerImpl(KeyboardFocusManager manager) {
- this.manager = manager;
- }
-
@Override
public void clearGlobalFocusOwner(Window activeWindow) {
if (activeWindow != null) {
@@ -134,7 +128,7 @@
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,
@@ -142,7 +136,7 @@
if (focusLog.isLoggable(PlatformLogger.FINER))
focusLog.finer("Posting focus event: " + fg);
- SunToolkit.postPriorityEvent(fg);
+ SunToolkit.postEvent(SunToolkit.targetToAppContext(lightweightChild), fg);
return true;
}
--- a/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerProvider.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerProvider.java Wed Sep 05 20:01:40 2012 -0700
@@ -25,20 +25,19 @@
package sun.awt;
-import java.awt.KeyboardFocusManager;
import java.awt.peer.KeyboardFocusManagerPeer;
/**
* {@link KeyboardFocusManagerPeerProvider} is required to be implemented by
* the currently used {@link java.awt.Toolkit} instance. In order to initialize
- * {@link java.awt.KeyboardFocusManager}, an instance of {@link KeyboardFocusManagerPeer}
- * is needed. To create that instance, the {@link #createKeyboardFocusManagerPeer}
+ * {@link java.awt.KeyboardFocusManager}, a singleton instance of {@link KeyboardFocusManagerPeer}
+ * is needed. To obtain that instance, the {@link #getKeyboardFocusManagerPeer}
* method of the current toolkit is called.
*/
public interface KeyboardFocusManagerPeerProvider {
/**
- * Creates a KeyboardFocusManagerPeer for the specified KeyboardFocusManager.
+ * Gets a singleton KeyboardFocusManagerPeer instance.
*/
- KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager);
+ KeyboardFocusManagerPeer getKeyboardFocusManagerPeer();
}
--- a/jdk/src/share/classes/sun/awt/SunToolkit.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/classes/sun/awt/SunToolkit.java Wed Sep 05 20:01:40 2012 -0700
@@ -197,7 +197,7 @@
public abstract RobotPeer createRobot(Robot target, GraphicsDevice screen)
throws AWTException;
- public abstract KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager)
+ public abstract KeyboardFocusManagerPeer getKeyboardFocusManagerPeer()
throws HeadlessException;
/**
@@ -463,6 +463,19 @@
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
@@ -1863,6 +1876,28 @@
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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/awt/TimedWindowEvent.java Wed Sep 05 20:01:40 2012 -0700
@@ -0,0 +1,51 @@
+/*
+ * 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;
+ }
+}
+
--- a/jdk/src/share/demo/applets/CardTest/example1.html Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/demo/applets/CardTest/example1.html Wed Sep 05 20:01:40 2012 -0700
@@ -5,7 +5,7 @@
<body>
<h1>Card Test (1.1)</h1>
<hr>
- <applet code=CardTest.class width=400 height=300>
+ <applet code=CardTest.class width=455 height=300>
alt="Your browser understands the <APPLET> tag but isn't running the applet, for some reason."
Your browser is completely ignoring the <APPLET> tag!
</applet>
--- a/jdk/src/share/demo/applets/DitherTest/example1.html Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/share/demo/applets/DitherTest/example1.html Wed Sep 05 20:01:40 2012 -0700
@@ -5,7 +5,7 @@
<body>
<h1>Dither Test (1.1)</h1>
<hr>
- <applet code=DitherTest.class width=425 height=400>
+ <applet code=DitherTest.class width=455 height=400>
alt="Your browser understands the <APPLET> tag but isn't running the applet, for some reason."
Your browser is completely ignoring the <APPLET> tag!
</applet>
--- a/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java Wed Sep 05 20:01:40 2012 -0700
@@ -1001,6 +1001,13 @@
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;
--- a/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java Wed Sep 05 20:01:40 2012 -0700
@@ -588,33 +588,6 @@
}
- 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.getCurrentNativeFocusedWindow() != 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();
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java Wed Sep 05 20:01:40 2012 -0700
@@ -1108,7 +1108,7 @@
focusLog.fine("Request for decorated window focus");
// If this is Frame or Dialog we can't assure focus request success - but we still can try
// If this is Window and its owner Frame is active we can be sure request succedded.
- Window focusedWindow = XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow();
+ Window focusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow();
Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow);
focusLog.finer("Current window is: active={0}, focused={1}",
@@ -1201,7 +1201,7 @@
}
public void handleWindowFocusOut(Window oppositeWindow, long serial) {
- Window actualFocusedWindow = XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow();
+ Window actualFocusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow();
// If the actual focused window is not this decorated window then retain it.
if (actualFocusedWindow != null && actualFocusedWindow != target) {
--- a/jdk/src/solaris/classes/sun/awt/X11/XDialogPeer.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDialogPeer.java Wed Sep 05 20:01:40 2012 -0700
@@ -135,7 +135,7 @@
* Thus we don't have to perform any transitive (a blocker of a blocker) checks.
*/
boolean isFocusedWindowModalBlocker() {
- Window focusedWindow = XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow();
+ Window focusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow();
XWindowPeer focusedWindowPeer = null;
if (focusedWindow != null) {
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbedChildProxyPeer.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbedChildProxyPeer.java Wed Sep 05 20:01:40 2012 -0700
@@ -96,11 +96,11 @@
public void handleEvent(AWTEvent e) {
switch (e.getID()) {
case FocusEvent.FOCUS_GAINED:
- XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(proxy);
+ XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(proxy);
container.focusGained(handle);
break;
case FocusEvent.FOCUS_LOST:
- XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(null);
+ XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(null);
container.focusLost(handle);
break;
case KeyEvent.KEY_PRESSED:
@@ -172,7 +172,7 @@
if (lightweightChild == null) {
lightweightChild = (Component)proxy;
}
- Component currentOwner = XKeyboardFocusManagerPeer.getCurrentNativeFocusOwner();
+ Component currentOwner = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusOwner();
if (currentOwner != null && currentOwner.getPeer() == null) {
currentOwner = null;
}
@@ -224,7 +224,8 @@
if (parent != null) {
Window parentWindow = (Window)parent;
// and check that it is focused
- if (!parentWindow.isFocused() && XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() == parentWindow) {
+ if (!parentWindow.isFocused() &&
+ XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() == parentWindow) {
// if it is not - skip requesting focus on Solaris
// but return true for compatibility.
return true;
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java Wed Sep 05 20:01:40 2012 -0700
@@ -204,7 +204,7 @@
// XEMBED_FOCUS_OUT client messages), so we first need to check if
// embedded is an active window before sending WINDOW_LOST_FOCUS
// to shared code
- if (XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() == embedded.target) {
+ if (XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() == embedded.target) {
embedded.handleWindowFocusOut(null, 0);
}
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XKeyboardFocusManagerPeer.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XKeyboardFocusManagerPeer.java Wed Sep 05 20:01:40 2012 -0700
@@ -25,66 +25,48 @@
package sun.awt.X11;
import java.awt.Component;
-import java.awt.KeyboardFocusManager;
import java.awt.Window;
-
-import java.awt.event.FocusEvent;
-
-import java.awt.peer.KeyboardFocusManagerPeer;
-import java.awt.peer.ComponentPeer;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
import sun.util.logging.PlatformLogger;
-
import sun.awt.CausedFocusEvent;
-import sun.awt.SunToolkit;
import sun.awt.KeyboardFocusManagerPeerImpl;
public class XKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.X11.focus.XKeyboardFocusManagerPeer");
+ private static final XKeyboardFocusManagerPeer inst = new XKeyboardFocusManagerPeer();
- private static Object lock = new Object() {};
- private static Component currentFocusOwner;
- private static Window currentFocusedWindow;
+ private Component currentFocusOwner;
+ private Window currentFocusedWindow;
- XKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
- super(manager);
+ public static XKeyboardFocusManagerPeer getInstance() {
+ return inst;
+ }
+
+ private XKeyboardFocusManagerPeer() {
}
@Override
public void setCurrentFocusOwner(Component comp) {
- setCurrentNativeFocusOwner(comp);
+ synchronized (this) {
+ currentFocusOwner = comp;
+ }
}
@Override
public Component getCurrentFocusOwner() {
- return getCurrentNativeFocusOwner();
- }
-
- @Override
- public Window getCurrentFocusedWindow() {
- return getCurrentNativeFocusedWindow();
- }
-
- public static void setCurrentNativeFocusOwner(Component comp) {
- synchronized (lock) {
- currentFocusOwner = comp;
- }
- }
-
- public static Component getCurrentNativeFocusOwner() {
- synchronized(lock) {
+ synchronized(this) {
return currentFocusOwner;
}
}
- public static void setCurrentNativeFocusedWindow(Window win) {
- if (focusLog.isLoggable(PlatformLogger.FINER)) focusLog.finer("Setting current native focused window " + win);
+ @Override
+ public void setCurrentFocusedWindow(Window win) {
+ if (focusLog.isLoggable(PlatformLogger.FINER)) {
+ focusLog.finer("Setting current focused window " + win);
+ }
+
XWindowPeer from = null, to = null;
- synchronized(lock) {
+ synchronized(this) {
if (currentFocusedWindow != null) {
from = (XWindowPeer)currentFocusedWindow.getPeer();
}
@@ -104,8 +86,9 @@
}
}
- public static Window getCurrentNativeFocusedWindow() {
- synchronized(lock) {
+ @Override
+ public Window getCurrentFocusedWindow() {
+ synchronized(this) {
return currentFocusedWindow;
}
}
@@ -124,6 +107,6 @@
focusedWindowChangeAllowed,
time,
cause,
- getCurrentNativeFocusOwner());
+ getInstance().getCurrentFocusOwner());
}
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Wed Sep 05 20:01:40 2012 -0700
@@ -663,7 +663,7 @@
long w = 0;
if (windowToXWindow(ev.get_xany().get_window()) != null) {
Component owner =
- XKeyboardFocusManagerPeer.getCurrentNativeFocusOwner();
+ XKeyboardFocusManagerPeer.getInstance().getCurrentFocusOwner();
if (owner != null) {
XWindow ownerWindow = (XWindow) AWTAccessor.getComponentAccessor().getPeer(owner);
if (ownerWindow != null) {
@@ -1155,9 +1155,8 @@
return peer;
}
- public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) throws HeadlessException {
- XKeyboardFocusManagerPeer peer = new XKeyboardFocusManagerPeer(manager);
- return peer;
+ public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() throws HeadlessException {
+ return XKeyboardFocusManagerPeer.getInstance();
}
/**
--- a/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java Wed Sep 05 20:01:40 2012 -0700
@@ -617,7 +617,7 @@
public void handleWindowFocusIn_Dispatch() {
if (EventQueue.isDispatchThread()) {
- XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow((Window) target);
+ XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow((Window) target);
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS);
SunToolkit.setSystemGenerated(we);
target.dispatchEvent(we);
@@ -626,7 +626,7 @@
public void handleWindowFocusInSync(long serial) {
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS);
- XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow((Window) target);
+ XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow((Window) target);
sendEvent(we);
}
// NOTE: This method may be called by privileged threads.
@@ -634,7 +634,7 @@
public void handleWindowFocusIn(long serial) {
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS);
/* wrap in Sequenced, then post*/
- XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow((Window) target);
+ XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow((Window) target);
postEvent(wrapInSequenced((AWTEvent) we));
}
@@ -642,15 +642,15 @@
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public void handleWindowFocusOut(Window oppositeWindow, long serial) {
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow);
- XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow(null);
- XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(null);
+ XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow(null);
+ XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(null);
/* wrap in Sequenced, then post*/
postEvent(wrapInSequenced((AWTEvent) we));
}
public void handleWindowFocusOutSync(Window oppositeWindow, long serial) {
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow);
- XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow(null);
- XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(null);
+ XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow(null);
+ XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(null);
sendEvent(we);
}
@@ -1138,7 +1138,7 @@
// getWMState() always returns 0 (Withdrawn) for simple windows. Hence
// we ignore the state for such windows.
if (isVisible() && (state == XUtilConstants.NormalState || isSimpleWindow())) {
- if (XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() ==
+ if (XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() ==
getTarget())
{
show = true;
@@ -1165,15 +1165,25 @@
}
public void dispose() {
+ if (isGrabbed()) {
+ if (grabLog.isLoggable(PlatformLogger.FINE)) {
+ grabLog.fine("Generating UngrabEvent on {0} because of the window disposal", this);
+ }
+ postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource()));
+ }
+
SunToolkit.awtLock();
+
try {
windows.remove(this);
} finally {
SunToolkit.awtUnlock();
}
+
if (warningWindow != null) {
warningWindow.destroy();
}
+
removeRootPropertyEventDispatcher();
mustControlStackPosition = false;
super.dispose();
@@ -1185,12 +1195,13 @@
* receive WM_TAKE_FOCUS.
*/
if (isSimpleWindow()) {
- if (target == XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow()) {
+ if (target == XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow()) {
Window owner = getDecoratedOwner((Window)target);
((XWindowPeer)AWTAccessor.getComponentAccessor().getPeer(owner)).requestWindowFocus();
}
}
}
+
boolean isResizable() {
return winAttr.isResizable;
}
@@ -1825,7 +1836,7 @@
// If this is Frame or Dialog we can't assure focus request success - but we still can try
// If this is Window and its owner Frame is active we can be sure request succedded.
Window ownerWindow = XWindowPeer.getDecoratedOwner((Window)target);
- Window focusedWindow = XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow();
+ Window focusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow();
Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow);
if (isWMStateNetHidden()) {
--- a/jdk/src/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java Wed Sep 05 20:01:40 2012 -0700
@@ -25,7 +25,6 @@
package sun.awt.windows;
-import java.awt.KeyboardFocusManager;
import java.awt.Window;
import java.awt.Component;
import java.awt.peer.ComponentPeer;
@@ -37,8 +36,13 @@
static native Component getNativeFocusOwner();
static native Window getNativeFocusedWindow();
- WKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
- super(manager);
+ private static final WKeyboardFocusManagerPeer inst = new WKeyboardFocusManagerPeer();
+
+ public static WKeyboardFocusManagerPeer getInstance() {
+ return inst;
+ }
+
+ private WKeyboardFocusManagerPeer() {
}
@Override
@@ -52,6 +56,12 @@
}
@Override
+ public void setCurrentFocusedWindow(Window win) {
+ // Not used on Windows
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
public Window getCurrentFocusedWindow() {
return getNativeFocusedWindow();
}
--- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java Wed Sep 05 20:01:40 2012 -0700
@@ -506,10 +506,10 @@
return true;
}
- public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager)
+ public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer()
throws HeadlessException
{
- return new WKeyboardFocusManagerPeer(manager);
+ return WKeyboardFocusManagerPeer.getInstance();
}
protected native void setDynamicLayoutNative(boolean b);
--- a/jdk/src/windows/native/sun/windows/awt_Window.cpp Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Window.cpp Wed Sep 05 20:01:40 2012 -0700
@@ -1477,7 +1477,7 @@
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 @@
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 @@
}
}
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) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Focus/6981400/Test1.java Wed Sep 05 20:01:40 2012 -0700
@@ -0,0 +1,222 @@
+/*
+ * 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 + "]";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Focus/6981400/Test2.java Wed Sep 05 20:01:40 2012 -0700
@@ -0,0 +1,118 @@
+/*
+ * 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);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Focus/6981400/Test3.java Wed Sep 05 20:01:40 2012 -0700
@@ -0,0 +1,141 @@
+/*
+ * 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);
+ }
+ }
+}
+
+
--- a/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java Wed Sep 05 20:01:40 2012 -0700
@@ -38,8 +38,7 @@
import java.beans.BeanInfo;
import java.beans.Introspector;
-import java.lang.ref.Reference;
-import java.lang.reflect.Field;
+import java.lang.reflect.Method;
public class TestBeanInfo implements Runnable {
@@ -60,10 +59,9 @@
try {
actual = Introspector.getBeanInfo(type);
type = actual.getClass();
- Field field = type.getDeclaredField("targetBeanInfoRef"); // NON-NLS: field name
- field.setAccessible(true);
- Reference ref = (Reference) field.get(actual);
- actual = (BeanInfo) ref.get();
+ Method method = type.getDeclaredMethod("getTargetBeanInfo"); // NON-NLS: method name
+ method.setAccessible(true);
+ actual = (BeanInfo) method.invoke(actual);
}
catch (Exception exception) {
throw new Error("unexpected error", exception);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/Test7186794.java Wed Sep 05 20:01:40 2012 -0700
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ *
+ * 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 7186794
+ * @summary Tests setter in the super class
+ * @author Sergey Malenkov
+ */
+
+import java.util.List;
+
+public class Test7186794 {
+
+ public static void main(String[] args) {
+ if (null == BeanUtils.findPropertyDescriptor(MyBean.class, "value").getWriteMethod()) {
+ throw new Error("The property setter is not found");
+ }
+ }
+
+ public static class BaseBean {
+
+ protected List<String> value;
+
+ public void setValue(List<String> value) {
+ this.value = value;
+ }
+ }
+
+ public static class MyBean extends BaseBean {
+ public List<String> getValue() {
+ return super.value;
+ }
+ }
+}
--- a/jdk/test/java/beans/Introspector/Test7189112.java Wed Sep 05 13:50:00 2012 -0700
+++ b/jdk/test/java/beans/Introspector/Test7189112.java Wed Sep 05 20:01:40 2012 -0700
@@ -28,17 +28,11 @@
* @author Sergey Malenkov
*/
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-
public class Test7189112 {
- public static void main(String[] args) throws IntrospectionException {
- for (PropertyDescriptor pd : Introspector.getBeanInfo(MyBean.class).getPropertyDescriptors()) {
- if (pd.getName().equals("value") && (null == pd.getWriteMethod())) {
- throw new Error("The property setter is not found");
- }
+ public static void main(String[] args) {
+ if (null == BeanUtils.findPropertyDescriptor(MyBean.class, "value").getWriteMethod()) {
+ throw new Error("The property setter is not found");
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/Test7192955.java Wed Sep 05 20:01:40 2012 -0700
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ *
+ * 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 7192955
+ * @summary Tests that all properties are bound
+ * @author Sergey Malenkov
+ */
+
+import java.beans.PropertyChangeListener;
+import java.util.List;
+
+public class Test7192955 {
+
+ public static void main(String[] args) {
+ if (!BeanUtils.findPropertyDescriptor(MyBean.class, "test").isBound()) {
+ throw new Error("a simple property is not bound");
+ }
+ if (!BeanUtils.findPropertyDescriptor(MyBean.class, "list").isBound()) {
+ throw new Error("a generic property is not bound");
+ }
+ if (!BeanUtils.findPropertyDescriptor(MyBean.class, "readOnly").isBound()) {
+ throw new Error("a read-only property is not bound");
+ }
+ }
+
+ public static class BaseBean {
+
+ private List<String> list;
+
+ public List<String> getList() {
+ return this.list;
+ }
+
+ public void setList(List<String> list) {
+ this.list = list;
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener listener) {
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener listener) {
+ }
+
+ public List<String> getReadOnly() {
+ return this.list;
+ }
+ }
+
+ public static class MyBean extends BaseBean {
+
+ private String test;
+
+ public String getTest() {
+ return this.test;
+ }
+
+ public void setTest(String test) {
+ this.test = test;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/Test7195106.java Wed Sep 05 20:01:40 2012 -0700
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ *
+ * 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 7195106
+ * @summary Tests that explicit BeanInfo is not collected
+ * @author Sergey Malenkov
+ */
+
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.SimpleBeanInfo;
+
+public class Test7195106 {
+
+ public static void main(String[] arg) throws Exception {
+ BeanInfo info = Introspector.getBeanInfo(My.class);
+ if (null == info.getIcon(BeanInfo.ICON_COLOR_16x16)) {
+ throw new Error("Unexpected behavior");
+ }
+ try {
+ int[] array = new int[1024];
+ while (true) {
+ array = new int[array.length << 1];
+ }
+ }
+ catch (OutOfMemoryError error) {
+ System.gc();
+ }
+ if (null == info.getIcon(BeanInfo.ICON_COLOR_16x16)) {
+ throw new Error("Explicit BeanInfo is collected");
+ }
+ }
+
+ public static class My {
+ }
+
+ public static class MyBeanInfo extends SimpleBeanInfo {
+ @Override
+ public Image getIcon(int type) {
+ return new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/Test7169395.java Wed Sep 05 20:01:40 2012 -0700
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ *
+ * 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 7169395
+ * @summary Tests that array list initialized correctly
+ * @author Sergey Malenkov
+ */
+
+import java.beans.ConstructorProperties;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.TreeMap;
+
+public class Test7169395 extends AbstractTest {
+
+ public static void main(String[] args) {
+ new Test7169395().test(true);
+ }
+
+ protected Object getObject() {
+ Container container = new Container();
+ container.add("test-null", null);
+ container.add("test-value", "value");
+ container.add("test-other", "other");
+ return container;
+ }
+
+ public static class Component {
+
+ private final Container container;
+ private final String name;
+ private String value;
+
+ @ConstructorProperties({ "container", "name" })
+ public Component(Container container, String name) {
+ this.container = container;
+ this.name = name;
+ }
+
+ public Container getContainer() {
+ return this.container;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+ }
+
+ public static class Container {
+
+ private final Map<String, Component> map = new TreeMap<String, Component>();
+
+ public Collection<Component> getComponents() {
+ return new ArrayList<Component>(this.map.values());
+ }
+
+ public void setComponents(Collection<Component> components) {
+ this.map.clear();
+ for (Component component : components){
+ this.map.put(component.getName(), component);
+ }
+ }
+
+ public void add(String name, String value) {
+ Component list = new Component(this, name);
+ list.setValue(value);
+ this.map.put(name, list);
+ }
+ }
+}