提交 91f02508 编写于 作者: A ant

6806217: implement synthetic focus model for MS Windows

Reviewed-by: art, dcherepanov
上级 1dc9e578
此差异已折叠。
...@@ -851,6 +851,12 @@ public abstract class Component implements ImageObserver, MenuContainer, ...@@ -851,6 +851,12 @@ public abstract class Component implements ImageObserver, MenuContainer,
{ {
comp.setGraphicsConfiguration(gc); comp.setGraphicsConfiguration(gc);
} }
public boolean requestFocus(Component comp, CausedFocusEvent.Cause cause) {
return comp.requestFocus(cause);
}
public boolean canBeFocusOwner(Component comp) {
return comp.canBeFocusOwner();
}
}); });
} }
...@@ -7147,8 +7153,8 @@ public abstract class Component implements ImageObserver, MenuContainer, ...@@ -7147,8 +7153,8 @@ public abstract class Component implements ImageObserver, MenuContainer,
requestFocusHelper(false, true); requestFocusHelper(false, true);
} }
void requestFocus(CausedFocusEvent.Cause cause) { boolean requestFocus(CausedFocusEvent.Cause cause) {
requestFocusHelper(false, true, cause); return requestFocusHelper(false, true, cause);
} }
/** /**
......
...@@ -61,6 +61,7 @@ import sun.awt.HeadlessToolkit; ...@@ -61,6 +61,7 @@ import sun.awt.HeadlessToolkit;
import sun.awt.SunToolkit; import sun.awt.SunToolkit;
import sun.awt.CausedFocusEvent; import sun.awt.CausedFocusEvent;
import sun.awt.KeyboardFocusManagerPeerProvider; import sun.awt.KeyboardFocusManagerPeerProvider;
import sun.awt.AWTAccessor;
/** /**
* The KeyboardFocusManager is responsible for managing the active and focused * The KeyboardFocusManager is responsible for managing the active and focused
...@@ -118,6 +119,32 @@ public abstract class KeyboardFocusManager ...@@ -118,6 +119,32 @@ public abstract class KeyboardFocusManager
if (!GraphicsEnvironment.isHeadless()) { if (!GraphicsEnvironment.isHeadless()) {
initIDs(); initIDs();
} }
AWTAccessor.setKeyboardFocusManagerAccessor(
new AWTAccessor.KeyboardFocusManagerAccessor() {
public int shouldNativelyFocusHeavyweight(Component heavyweight,
Component descendant,
boolean temporary,
boolean focusedWindowChangeAllowed,
long time,
CausedFocusEvent.Cause cause)
{
return KeyboardFocusManager.shouldNativelyFocusHeavyweight(
heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause);
}
public boolean processSynchronousLightweightTransfer(Component heavyweight,
Component descendant,
boolean temporary,
boolean focusedWindowChangeAllowed,
long time)
{
return KeyboardFocusManager.processSynchronousLightweightTransfer(
heavyweight, descendant, temporary, focusedWindowChangeAllowed, time);
}
public void removeLastFocusRequest(Component heavyweight) {
KeyboardFocusManager.removeLastFocusRequest(heavyweight);
}
}
);
} }
transient KeyboardFocusManagerPeer peer; transient KeyboardFocusManagerPeer peer;
...@@ -2443,79 +2470,7 @@ public abstract class KeyboardFocusManager ...@@ -2443,79 +2470,7 @@ public abstract class KeyboardFocusManager
} }
} }
} }
static void heavyweightButtonDown(Component heavyweight, long time) {
heavyweightButtonDown(heavyweight, time, false);
}
static void heavyweightButtonDown(Component heavyweight, long time, boolean acceptDuplicates) {
if (log.isLoggable(Level.FINE)) {
if (heavyweight == null) {
log.log(Level.FINE, "Assertion (heavyweight != null) failed");
}
if (time == 0) {
log.log(Level.FINE, "Assertion (time != 0) failed");
}
}
KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(heavyweight));
synchronized (heavyweightRequests) {
HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
Component currentNativeFocusOwner = (hwFocusRequest == null)
? manager.getNativeFocusOwner()
: hwFocusRequest.heavyweight;
// Behavior for all use cases:
// 1. Heavyweight leaf Components (e.g., Button, Checkbox, Choice,
// List, TextComponent, Canvas) that respond to button down.
//
// Native platform will generate a FOCUS_GAINED if and only if
// the Component is not the focus owner (or, will not be the
// focus owner when all outstanding focus requests are
// processed).
//
// 2. Panel with no descendants.
//
// Same as (1).
//
// 3. Panel with at least one heavyweight descendant.
//
// This function should NOT be called for this case!
//
// 4. Panel with only lightweight descendants.
//
// Native platform will generate a FOCUS_GAINED if and only if
// neither the Panel, nor any of its recursive, lightweight
// descendants, is the focus owner. However, we want a
// requestFocus() for any lightweight descendant to win out over
// the focus request for the Panel. To accomplish this, we
// differ from the algorithm for shouldNativelyFocusHeavyweight
// as follows:
// a. If the requestFocus() for a lightweight descendant has
// been fully handled by the time this function is invoked,
// then 'hwFocusRequest' will be null and 'heavyweight'
// will be the native focus owner. Do *not* synthesize a
// focus transfer to the Panel.
// b. If the requestFocus() for a lightweight descendant has
// been recorded, but not handled, then 'hwFocusRequest'
// will be non-null and 'hwFocusRequest.heavyweight' will
// equal 'heavyweight'. Do *not* append 'heavyweight' to
// hwFocusRequest.lightweightRequests.
// c. If the requestFocus() for a lightweight descendant is
// yet to be made, then post a new HeavyweightFocusRequest.
// If no lightweight descendant ever requests focus, then
// the Panel will get focus. If some descendant does, then
// the descendant will get focus by either a synthetic
// focus transfer, or a lightweightRequests focus transfer.
if (acceptDuplicates || heavyweight != currentNativeFocusOwner) {
getCurrentKeyboardFocusManager
(SunToolkit.targetToAppContext(heavyweight)).
enqueueKeyEvents(time, heavyweight);
heavyweightRequests.add
(new HeavyweightFocusRequest(heavyweight, heavyweight,
false, CausedFocusEvent.Cause.MOUSE_EVENT));
}
}
}
/** /**
* Returns the Window which will be active after processing this request, * Returns the Window which will be active after processing this request,
* or null if this is a duplicate request. The active Window is useful * or null if this is a duplicate request. The active Window is useful
......
...@@ -31,7 +31,8 @@ import java.awt.image.BufferedImage; ...@@ -31,7 +31,8 @@ import java.awt.image.BufferedImage;
import sun.misc.Unsafe; import sun.misc.Unsafe;
/** The AWTAccessor utility class. /**
* The AWTAccessor utility class.
* The main purpose of this class is to enable accessing * The main purpose of this class is to enable accessing
* private and package-private fields of classes from * private and package-private fields of classes from
* different classes/packages. See sun.misc.SharedSecretes * different classes/packages. See sun.misc.SharedSecretes
...@@ -83,6 +84,14 @@ public final class AWTAccessor { ...@@ -83,6 +84,14 @@ public final class AWTAccessor {
* Sets GraphicsConfiguration value for the component. * Sets GraphicsConfiguration value for the component.
*/ */
void setGraphicsConfiguration(Component comp, GraphicsConfiguration gc); void setGraphicsConfiguration(Component comp, GraphicsConfiguration gc);
/*
* Requests focus to the component.
*/
boolean requestFocus(Component comp, CausedFocusEvent.Cause cause);
/*
* Determines if the component can gain focus.
*/
boolean canBeFocusOwner(Component comp);
} }
/* /*
...@@ -151,6 +160,35 @@ public final class AWTAccessor { ...@@ -151,6 +160,35 @@ public final class AWTAccessor {
int getExtendedState(Frame frame); int getExtendedState(Frame frame);
} }
/*
* An interface of accessor for the java.awt.Component class.
*/
public interface KeyboardFocusManagerAccessor {
/*
* Indicates whether the native implementation should
* proceed with a pending focus request for the heavyweight.
*/
int shouldNativelyFocusHeavyweight(Component heavyweight,
Component descendant,
boolean temporary,
boolean focusedWindowChangeAllowed,
long time,
CausedFocusEvent.Cause cause);
/*
* Delivers focus for the lightweight descendant of the heavyweight
* synchronously.
*/
boolean processSynchronousLightweightTransfer(Component heavyweight,
Component descendant,
boolean temporary,
boolean focusedWindowChangeAllowed,
long time);
/*
* Removes the last focus request for the heavyweight from the queue.
*/
void removeLastFocusRequest(Component heavyweight);
}
/* /*
* The java.awt.Component class accessor object. * The java.awt.Component class accessor object.
*/ */
...@@ -171,6 +209,11 @@ public final class AWTAccessor { ...@@ -171,6 +209,11 @@ public final class AWTAccessor {
*/ */
private static FrameAccessor frameAccessor; private static FrameAccessor frameAccessor;
/*
* The java.awt.KeyboardFocusManager class accessor object.
*/
private static KeyboardFocusManagerAccessor kfmAccessor;
/* /*
* Set an accessor object for the java.awt.Component class. * Set an accessor object for the java.awt.Component class.
*/ */
...@@ -236,4 +279,21 @@ public final class AWTAccessor { ...@@ -236,4 +279,21 @@ public final class AWTAccessor {
} }
return frameAccessor; return frameAccessor;
} }
/*
* Set an accessor object for the java.awt.KeyboardFocusManager class.
*/
public static void setKeyboardFocusManagerAccessor(KeyboardFocusManagerAccessor kfma) {
kfmAccessor = kfma;
}
/*
* Retrieve the accessor object for the java.awt.KeyboardFocusManager class.
*/
public static KeyboardFocusManagerAccessor getKeyboardFocusManagerAccessor() {
if (kfmAccessor == null) {
unsafe.ensureClassInitialized(KeyboardFocusManager.class);
}
return kfmAccessor;
}
} }
...@@ -179,9 +179,9 @@ public class HeadlessToolkit extends Toolkit ...@@ -179,9 +179,9 @@ public class HeadlessToolkit extends Toolkit
throw new HeadlessException(); throw new HeadlessException();
} }
public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) throws HeadlessException { public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager)
KeyboardFocusManagerPeerImpl peer = new KeyboardFocusManagerPeerImpl(manager); throws HeadlessException {
return peer; throw new HeadlessException();
} }
public TrayIconPeer createTrayIcon(TrayIcon target) public TrayIconPeer createTrayIcon(TrayIcon target)
......
/* /*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -27,47 +27,150 @@ package sun.awt; ...@@ -27,47 +27,150 @@ package sun.awt;
import java.awt.Component; import java.awt.Component;
import java.awt.KeyboardFocusManager; import java.awt.KeyboardFocusManager;
import java.awt.Window; import java.awt.Window;
import java.awt.Canvas;
import java.awt.Scrollbar;
import java.awt.Panel;
import java.awt.event.FocusEvent;
import java.awt.peer.KeyboardFocusManagerPeer; import java.awt.peer.KeyboardFocusManagerPeer;
import java.awt.peer.ComponentPeer;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManagerPeer {
private static final Logger focusLog = Logger.getLogger("sun.awt.focus.KeyboardFocusManagerPeerImpl");
private static AWTAccessor.KeyboardFocusManagerAccessor kfmAccessor =
AWTAccessor.getKeyboardFocusManagerAccessor();
public class KeyboardFocusManagerPeerImpl implements KeyboardFocusManagerPeer { // The constants are copied from java.awt.KeyboardFocusManager
static native Window getNativeFocusedWindow(); public static final int SNFH_FAILURE = 0;
static native Component getNativeFocusOwner(); public static final int SNFH_SUCCESS_HANDLED = 1;
static native void clearNativeGlobalFocusOwner(Window activeWindow); public static final int SNFH_SUCCESS_PROCEED = 2;
KeyboardFocusManagerPeerImpl(KeyboardFocusManager manager) { protected KeyboardFocusManager manager;
public KeyboardFocusManagerPeerImpl(KeyboardFocusManager manager) {
this.manager = manager;
} }
public Window getCurrentFocusedWindow() { @Override
return getNativeFocusedWindow(); public void clearGlobalFocusOwner(Window activeWindow) {
if (activeWindow != null) {
Component focusOwner = activeWindow.getFocusOwner();
if (focusLog.isLoggable(Level.FINE)) focusLog.fine("Clearing global focus owner " + focusOwner);
if (focusOwner != null) {
FocusEvent fl = new CausedFocusEvent(focusOwner, FocusEvent.FOCUS_LOST, false, null,
CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
SunToolkit.postPriorityEvent(fl);
}
}
}
/*
* WARNING: Don't call it on the Toolkit thread.
*
* Checks if the component:
* 1) accepts focus on click (in general)
* 2) may be a focus owner (in particular)
*/
public static boolean shouldFocusOnClick(Component component) {
boolean acceptFocusOnClick = false;
// A component is generally allowed to accept focus on click
// if its peer is focusable. There're some exceptions though.
// CANVAS & SCROLLBAR accept focus on click
if (component instanceof Canvas ||
component instanceof Scrollbar)
{
acceptFocusOnClick = true;
// PANEL, empty only, accepts focus on click
} else if (component instanceof Panel) {
acceptFocusOnClick = (((Panel)component).getComponentCount() == 0);
// Other components
} else {
ComponentPeer peer = (component != null ? component.getPeer() : null);
acceptFocusOnClick = (peer != null ? peer.isFocusable() : false);
}
return acceptFocusOnClick &&
AWTAccessor.getComponentAccessor().canBeFocusOwner(component);
} }
public void setCurrentFocusOwner(Component comp) { /*
* Posts proper lost/gain focus events to the event queue.
*/
public static boolean deliverFocus(Component lightweightChild,
Component target,
boolean temporary,
boolean focusedWindowChangeAllowed,
long time,
CausedFocusEvent.Cause cause,
Component currentFocusOwner) // provided by the descendant peers
{
if (lightweightChild == null) {
lightweightChild = (Component)target;
}
Component currentOwner = currentFocusOwner;
if (currentOwner != null && currentOwner.getPeer() == null) {
currentOwner = null;
}
if (currentOwner != null) {
FocusEvent fl = new CausedFocusEvent(currentOwner, FocusEvent.FOCUS_LOST,
false, lightweightChild, cause);
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Posting focus event: " + fl);
SunToolkit.postPriorityEvent(fl);
}
FocusEvent fg = new CausedFocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED,
false, currentOwner, cause);
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Posting focus event: " + fg);
SunToolkit.postPriorityEvent(fg);
return true;
} }
public Component getCurrentFocusOwner() { // WARNING: Don't call it on the Toolkit thread.
return getNativeFocusOwner(); public static boolean requestFocusFor(Component target, CausedFocusEvent.Cause cause) {
return AWTAccessor.getComponentAccessor().requestFocus(target, cause);
} }
public void clearGlobalFocusOwner(Window activeWindow) {
clearNativeGlobalFocusOwner(activeWindow); // WARNING: Don't call it on the Toolkit thread.
public static int shouldNativelyFocusHeavyweight(Component heavyweight,
Component descendant,
boolean temporary,
boolean focusedWindowChangeAllowed,
long time,
CausedFocusEvent.Cause cause)
{
return kfmAccessor.shouldNativelyFocusHeavyweight(
heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause);
} }
static Method m_removeLastFocusRequest = null;
public static void removeLastFocusRequest(Component heavyweight) { public static void removeLastFocusRequest(Component heavyweight) {
try { kfmAccessor.removeLastFocusRequest(heavyweight);
if (m_removeLastFocusRequest == null) { }
m_removeLastFocusRequest = SunToolkit.getMethod(KeyboardFocusManager.class, "removeLastFocusRequest",
new Class[] {Component.class}); // WARNING: Don't call it on the Toolkit thread.
} public static boolean processSynchronousLightweightTransfer(Component heavyweight,
m_removeLastFocusRequest.invoke(null, new Object[]{heavyweight}); Component descendant,
} catch (InvocationTargetException ite) { boolean temporary,
ite.printStackTrace(); boolean focusedWindowChangeAllowed,
} catch (IllegalAccessException ex) { long time)
ex.printStackTrace(); {
} return kfmAccessor.processSynchronousLightweightTransfer(
heavyweight, descendant, temporary, focusedWindowChangeAllowed, time);
} }
} }
...@@ -220,10 +220,8 @@ public abstract class SunToolkit extends Toolkit ...@@ -220,10 +220,8 @@ public abstract class SunToolkit extends Toolkit
public abstract RobotPeer createRobot(Robot target, GraphicsDevice screen) public abstract RobotPeer createRobot(Robot target, GraphicsDevice screen)
throws AWTException; throws AWTException;
public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) throws HeadlessException { public abstract KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager)
KeyboardFocusManagerPeerImpl peer = new KeyboardFocusManagerPeerImpl(manager); throws HeadlessException;
return peer;
}
/** /**
* The AWT lock is typically only used on Unix platforms to synchronize * The AWT lock is typically only used on Unix platforms to synchronize
......
...@@ -77,11 +77,6 @@ import sun.java2d.pipe.Region; ...@@ -77,11 +77,6 @@ import sun.java2d.pipe.Region;
public class XComponentPeer extends XWindow implements ComponentPeer, DropTargetPeer, public class XComponentPeer extends XWindow implements ComponentPeer, DropTargetPeer,
BackBufferCapsProvider BackBufferCapsProvider
{ {
/* FIX ME: these constants copied from java.awt.KeyboardFocusManager */
static final int SNFH_FAILURE = 0;
static final int SNFH_SUCCESS_HANDLED = 1;
static final int SNFH_SUCCESS_PROCEED = 2;
private static final Logger log = Logger.getLogger("sun.awt.X11.XComponentPeer"); private static final Logger log = Logger.getLogger("sun.awt.X11.XComponentPeer");
private static final Logger buffersLog = Logger.getLogger("sun.awt.X11.XComponentPeer.multibuffer"); private static final Logger buffersLog = Logger.getLogger("sun.awt.X11.XComponentPeer.multibuffer");
private static final Logger focusLog = Logger.getLogger("sun.awt.X11.focus.XComponentPeer"); private static final Logger focusLog = Logger.getLogger("sun.awt.X11.focus.XComponentPeer");
...@@ -315,113 +310,27 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget ...@@ -315,113 +310,27 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
return null; return null;
} }
/** // TODO: consider moving it to KeyboardFocusManagerPeerImpl
* Returns whether or not this component should be given focus on mouse click.
* Default implementation return whether or not this peer is "focusable"
* Descendants might want to override it to extend/restrict conditions at which this
* component should be focused by click (see MCanvasPeer and MPanelPeer)
*/
protected boolean shouldFocusOnClick() {
return isFocusable();
}
/**
* Checks whether or not this component would be focused by native system if it would be allowed to do so.
* Currently it checks that it displayable, visible, enabled and focusable.
*/
static boolean canBeFocusedByClick(Component component) {
if (component == null) {
return false;
} else {
return component.isDisplayable() && component.isVisible() && component.isEnabled() && component.isFocusable();
}
}
static Window getContainingWindow(Component comp) {
while (comp != null && !(comp instanceof Window)) {
comp = comp.getParent();
}
return (Window)comp;
}
static Method processSynchronousLightweightTransferMethod;
static boolean processSynchronousLightweightTransfer(Component heavyweight, Component descendant,
boolean temporary, boolean focusedWindowChangeAllowed,
long time)
{
try {
if (processSynchronousLightweightTransferMethod == null) {
processSynchronousLightweightTransferMethod =
(Method)AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run() throws IllegalAccessException, NoSuchMethodException
{
Method m = KeyboardFocusManager.class.
getDeclaredMethod("processSynchronousLightweightTransfer",
new Class[] {Component.class, Component.class,
Boolean.TYPE, Boolean.TYPE,
Long.TYPE});
m.setAccessible(true);
return m;
}
});
}
Object[] params = new Object[] {
heavyweight,
descendant,
Boolean.valueOf(temporary),
Boolean.valueOf(focusedWindowChangeAllowed),
Long.valueOf(time)
};
return ((Boolean)processSynchronousLightweightTransferMethod.invoke(null, params)).booleanValue();
} catch (PrivilegedActionException pae) {
pae.printStackTrace();
return false;
} catch (IllegalAccessException iae) {
iae.printStackTrace();
return false;
} catch (IllegalArgumentException iaee) {
iaee.printStackTrace();
return false;
} catch (InvocationTargetException ite) {
ite.printStackTrace();
return false;
}
}
static Method requestFocusWithCause;
static void callRequestFocus(Component target, CausedFocusEvent.Cause cause) {
if (requestFocusWithCause == null) {
requestFocusWithCause = SunToolkit.getMethod(Component.class, "requestFocus", new Class[] {CausedFocusEvent.Cause.class});
}
if (requestFocusWithCause != null) {
try {
requestFocusWithCause.invoke(target, new Object[] {cause});
} catch (Exception e) {
e.printStackTrace();
}
}
}
final public boolean requestFocus(Component lightweightChild, boolean temporary, final public boolean requestFocus(Component lightweightChild, boolean temporary,
boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) boolean focusedWindowChangeAllowed, long time,
CausedFocusEvent.Cause cause)
{ {
if (processSynchronousLightweightTransfer(target, lightweightChild, temporary, if (XKeyboardFocusManagerPeer.
processSynchronousLightweightTransfer(target, lightweightChild, temporary,
focusedWindowChangeAllowed, time)) focusedWindowChangeAllowed, time))
{ {
return true; return true;
} }
int result = XKeyboardFocusManagerPeer int result = XKeyboardFocusManagerPeer.
.shouldNativelyFocusHeavyweight(target, lightweightChild, shouldNativelyFocusHeavyweight(target, lightweightChild,
temporary, focusedWindowChangeAllowed, time, cause); temporary, focusedWindowChangeAllowed,
time, cause);
switch (result) { switch (result) {
case SNFH_FAILURE: case XKeyboardFocusManagerPeer.SNFH_FAILURE:
return false; return false;
case SNFH_SUCCESS_PROCEED: case XKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:
// Currently we just generate focus events like we deal with lightweight instead of calling // Currently we just generate focus events like we deal with lightweight instead of calling
// XSetInputFocus on native window // XSetInputFocus on native window
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Proceeding with request to " + if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Proceeding with request to " +
...@@ -434,7 +343,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget ...@@ -434,7 +343,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
* focus owner which had focus before WLF. So, we should not add request record for such requests * focus owner which had focus before WLF. So, we should not add request record for such requests
* but store this component in mostRecent - and return true as before for compatibility. * but store this component in mostRecent - and return true as before for compatibility.
*/ */
Window parentWindow = getContainingWindow(target); Window parentWindow = SunToolkit.getContainingWindow(target);
if (parentWindow == null) { if (parentWindow == null) {
return rejectFocusRequestHelper("WARNING: Parent window is null"); return rejectFocusRequestHelper("WARNING: Parent window is null");
} }
...@@ -455,14 +364,13 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget ...@@ -455,14 +364,13 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
if (!(res && parentWindow.isFocused())) { if (!(res && parentWindow.isFocused())) {
return rejectFocusRequestHelper("Waiting for asynchronous processing of the request"); return rejectFocusRequestHelper("Waiting for asynchronous processing of the request");
} }
return XKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
// NOTE: We simulate heavyweight behavior of Motif - component receives focus right (Component)target,
// after request, not after event. Normally, we should better listen for event temporary,
// by listeners. focusedWindowChangeAllowed,
return XKeyboardFocusManagerPeer.simulateMotifRequestFocus(lightweightChild, target, temporary, time, cause);
focusedWindowChangeAllowed, time, cause);
// Motif compatibility code // Motif compatibility code
case SNFH_SUCCESS_HANDLED: case XKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
// Either lightweight or excessive request - all events are generated. // Either lightweight or excessive request - all events are generated.
return true; return true;
} }
...@@ -471,7 +379,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget ...@@ -471,7 +379,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
private boolean rejectFocusRequestHelper(String logMsg) { private boolean rejectFocusRequestHelper(String logMsg) {
if (focusLog.isLoggable(Level.FINER)) focusLog.finer(logMsg); if (focusLog.isLoggable(Level.FINER)) focusLog.finer(logMsg);
KeyboardFocusManagerPeerImpl.removeLastFocusRequest(target); XKeyboardFocusManagerPeer.removeLastFocusRequest(target);
return false; return false;
} }
...@@ -615,8 +523,9 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget ...@@ -615,8 +523,9 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
void handleJavaMouseEvent(MouseEvent e) { void handleJavaMouseEvent(MouseEvent e) {
switch (e.getID()) { switch (e.getID()) {
case MouseEvent.MOUSE_PRESSED: case MouseEvent.MOUSE_PRESSED:
if (target == e.getSource() && shouldFocusOnClick() if (target == e.getSource() &&
&& !target.isFocusOwner() && canBeFocusedByClick(target)) !target.isFocusOwner() &&
XKeyboardFocusManagerPeer.shouldFocusOnClick(target))
{ {
XWindowPeer parentXWindow = getParentTopLevel(); XWindowPeer parentXWindow = getParentTopLevel();
Window parentWindow = ((Window)parentXWindow.getTarget()); Window parentWindow = ((Window)parentXWindow.getTarget());
...@@ -630,7 +539,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget ...@@ -630,7 +539,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
// WindowEvent wfg = new WindowEvent(parentWindow, WindowEvent.WINDOW_GAINED_FOCUS); // WindowEvent wfg = new WindowEvent(parentWindow, WindowEvent.WINDOW_GAINED_FOCUS);
// parentWindow.dispatchEvent(wfg); // parentWindow.dispatchEvent(wfg);
// } // }
callRequestFocus(target, CausedFocusEvent.Cause.MOUSE_EVENT); XKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT);
} }
break; break;
} }
......
...@@ -184,6 +184,7 @@ public class XEmbedChildProxyPeer implements ComponentPeer, XEventDispatcher{ ...@@ -184,6 +184,7 @@ public class XEmbedChildProxyPeer implements ComponentPeer, XEventDispatcher{
fl = new FocusEvent(currentOwner, FocusEvent.FOCUS_LOST, false, lightweightChild); fl = new FocusEvent(currentOwner, FocusEvent.FOCUS_LOST, false, lightweightChild);
} }
// TODO: do we need to wrap in sequenced?
if (fl != null) { if (fl != null) {
postEvent(XComponentPeer.wrapInSequenced(fl)); postEvent(XComponentPeer.wrapInSequenced(fl));
} }
...@@ -203,9 +204,9 @@ public class XEmbedChildProxyPeer implements ComponentPeer, XEventDispatcher{ ...@@ -203,9 +204,9 @@ public class XEmbedChildProxyPeer implements ComponentPeer, XEventDispatcher{
temporary, false, time, cause); temporary, false, time, cause);
switch (result) { switch (result) {
case XComponentPeer.SNFH_FAILURE: case XKeyboardFocusManagerPeer.SNFH_FAILURE:
return false; return false;
case XComponentPeer.SNFH_SUCCESS_PROCEED: case XKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:
// Currently we just generate focus events like we deal with lightweight instead of calling // Currently we just generate focus events like we deal with lightweight instead of calling
// XSetInputFocus on native window // XSetInputFocus on native window
...@@ -235,9 +236,11 @@ public class XEmbedChildProxyPeer implements ComponentPeer, XEventDispatcher{ ...@@ -235,9 +236,11 @@ public class XEmbedChildProxyPeer implements ComponentPeer, XEventDispatcher{
// NOTE: We simulate heavyweight behavior of Motif - component receives focus right // NOTE: We simulate heavyweight behavior of Motif - component receives focus right
// after request, not after event. Normally, we should better listen for event // after request, not after event. Normally, we should better listen for event
// by listeners. // by listeners.
// TODO: consider replacing with XKeyboardFocusManagerPeer.deliverFocus
return simulateMotifRequestFocus(lightweightChild, temporary, focusedWindowChangeAllowed, time); return simulateMotifRequestFocus(lightweightChild, temporary, focusedWindowChangeAllowed, time);
// Motif compatibility code // Motif compatibility code
case XComponentPeer.SNFH_SUCCESS_HANDLED: case XKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
// Either lightweight or excessive requiest - all events are generated. // Either lightweight or excessive requiest - all events are generated.
return true; return true;
} }
......
...@@ -31,6 +31,7 @@ import java.awt.Window; ...@@ -31,6 +31,7 @@ import java.awt.Window;
import java.awt.event.FocusEvent; import java.awt.event.FocusEvent;
import java.awt.peer.KeyboardFocusManagerPeer; import java.awt.peer.KeyboardFocusManagerPeer;
import java.awt.peer.ComponentPeer;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
...@@ -40,136 +41,73 @@ import java.util.logging.Logger; ...@@ -40,136 +41,73 @@ import java.util.logging.Logger;
import sun.awt.CausedFocusEvent; import sun.awt.CausedFocusEvent;
import sun.awt.SunToolkit; import sun.awt.SunToolkit;
import sun.awt.KeyboardFocusManagerPeerImpl;
public class XKeyboardFocusManagerPeer implements KeyboardFocusManagerPeer { public class XKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
private static final Logger focusLog = Logger.getLogger("sun.awt.X11.focus.XKeyboardFocusManagerPeer"); private static final Logger focusLog = Logger.getLogger("sun.awt.X11.focus.XKeyboardFocusManagerPeer");
KeyboardFocusManager manager;
XKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
this.manager = manager;
}
private static Object lock = new Object() {}; private static Object lock = new Object() {};
private static Component currentFocusOwner; private static Component currentFocusOwner;
private static Window currentFocusedWindow; private static Window currentFocusedWindow;
static void setCurrentNativeFocusOwner(Component comp) { XKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Setting current native focus owner " + comp); super(manager);
synchronized(lock) {
currentFocusOwner = comp;
}
}
static void setCurrentNativeFocusedWindow(Window win) {
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Setting current native focused window " + win);
synchronized(lock) {
currentFocusedWindow = win;
}
} }
static Component getCurrentNativeFocusOwner() { @Override
synchronized(lock) { public void setCurrentFocusOwner(Component comp) {
return currentFocusOwner; setCurrentNativeFocusOwner(comp);
}
} }
static Window getCurrentNativeFocusedWindow() { @Override
synchronized(lock) { public Component getCurrentFocusOwner() {
return currentFocusedWindow; return getCurrentNativeFocusOwner();
}
} }
@Override
public Window getCurrentFocusedWindow() { public Window getCurrentFocusedWindow() {
return getCurrentNativeFocusedWindow(); return getCurrentNativeFocusedWindow();
} }
public void setCurrentFocusOwner(Component comp) { public static void setCurrentNativeFocusOwner(Component comp) {
setCurrentNativeFocusOwner(comp); synchronized (lock) {
} currentFocusOwner = comp;
}
public Component getCurrentFocusOwner() {
return getCurrentNativeFocusOwner();
} }
public void clearGlobalFocusOwner(Window activeWindow) { public static Component getCurrentNativeFocusOwner() {
if (activeWindow != null) { synchronized(lock) {
Component focusOwner = activeWindow.getFocusOwner(); return currentFocusOwner;
if (focusLog.isLoggable(Level.FINE)) focusLog.fine("Clearing global focus owner " + focusOwner);
if (focusOwner != null) {
// XComponentPeer nativePeer = XComponentPeer.getNativeContainer(focusOwner);
// if (nativePeer != null) {
FocusEvent fl = new CausedFocusEvent(focusOwner, FocusEvent.FOCUS_LOST, false, null,
CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
XWindow.sendEvent(fl);
// }
}
} }
} }
static boolean simulateMotifRequestFocus(Component lightweightChild, Component target, boolean temporary, public static void setCurrentNativeFocusedWindow(Window win) {
boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Setting current native focused window " + win);
{ synchronized(lock) {
if (lightweightChild == null) { currentFocusedWindow = win;
lightweightChild = (Component)target;
}
Component currentOwner = XKeyboardFocusManagerPeer.getCurrentNativeFocusOwner();
if (currentOwner != null && currentOwner.getPeer() == null) {
currentOwner = null;
}
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Simulating transfer from " + currentOwner + " to " + lightweightChild);
FocusEvent fg = new CausedFocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED, false, currentOwner, cause);
FocusEvent fl = null;
if (currentOwner != null) {
fl = new CausedFocusEvent(currentOwner, FocusEvent.FOCUS_LOST, false, lightweightChild, cause);
} }
}
if (fl != null) { public static Window getCurrentNativeFocusedWindow() {
XWindow.sendEvent(fl); synchronized(lock) {
return currentFocusedWindow;
} }
XWindow.sendEvent(fg);
return true;
} }
static Method shouldNativelyFocusHeavyweightMethod; // TODO: do something to eliminate this forwarding
public static boolean deliverFocus(Component lightweightChild,
static int shouldNativelyFocusHeavyweight(Component heavyweight, Component target,
Component descendant, boolean temporary, boolean temporary,
boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) boolean focusedWindowChangeAllowed,
long time,
CausedFocusEvent.Cause cause)
{ {
if (shouldNativelyFocusHeavyweightMethod == null) { return KeyboardFocusManagerPeerImpl.deliverFocus(lightweightChild,
Class[] arg_types = target,
new Class[] { Component.class, temporary,
Component.class, focusedWindowChangeAllowed,
Boolean.TYPE, time,
Boolean.TYPE, cause,
Long.TYPE, getCurrentNativeFocusOwner());
CausedFocusEvent.Cause.class
};
shouldNativelyFocusHeavyweightMethod =
SunToolkit.getMethod(KeyboardFocusManager.class,
"shouldNativelyFocusHeavyweight",
arg_types);
}
Object[] args = new Object[] { heavyweight,
descendant,
Boolean.valueOf(temporary),
Boolean.valueOf(focusedWindowChangeAllowed),
Long.valueOf(time), cause};
int result = XComponentPeer.SNFH_FAILURE;
if (shouldNativelyFocusHeavyweightMethod != null) {
try {
result = ((Integer) shouldNativelyFocusHeavyweightMethod.invoke(null, args)).intValue();
}
catch (IllegalAccessException e) {
assert false;
}
catch (InvocationTargetException e) {
assert false;
}
}
return result;
} }
} }
...@@ -27,6 +27,10 @@ package sun.awt.windows; ...@@ -27,6 +27,10 @@ package sun.awt.windows;
import java.awt.*; import java.awt.*;
import java.awt.peer.*; import java.awt.peer.*;
import java.awt.event.ItemEvent; import java.awt.event.ItemEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.event.WindowAdapter;
import sun.awt.SunToolkit;
class WChoicePeer extends WComponentPeer implements ChoicePeer { class WChoicePeer extends WComponentPeer implements ChoicePeer {
...@@ -70,6 +74,8 @@ class WChoicePeer extends WComponentPeer implements ChoicePeer { ...@@ -70,6 +74,8 @@ class WChoicePeer extends WComponentPeer implements ChoicePeer {
public synchronized native void reshape(int x, int y, int width, int height); public synchronized native void reshape(int x, int y, int width, int height);
private WindowListener windowListener;
// Toolkit & peer internals // Toolkit & peer internals
WChoicePeer(Choice target) { WChoicePeer(Choice target) {
...@@ -91,9 +97,38 @@ class WChoicePeer extends WComponentPeer implements ChoicePeer { ...@@ -91,9 +97,38 @@ class WChoicePeer extends WComponentPeer implements ChoicePeer {
select(opt.getSelectedIndex()); select(opt.getSelectedIndex());
} }
} }
Window parentWindow = SunToolkit.getContainingWindow((Component)target);
if (parentWindow != null) {
WWindowPeer wpeer = (WWindowPeer)parentWindow.getPeer();
if (wpeer != null) {
windowListener = new WindowAdapter() {
public void windowIconified(WindowEvent e) {
closeList();
}
public void windowClosing(WindowEvent e) {
closeList();
}
};
wpeer.addWindowListener(windowListener);
}
}
super.initialize(); super.initialize();
} }
protected void disposeImpl() {
// TODO: we should somehow reset the listener when the choice
// is moved to another toplevel without destroying its peer.
Window parentWindow = SunToolkit.getContainingWindow((Component)target);
if (parentWindow != null) {
WWindowPeer wpeer = (WWindowPeer)parentWindow.getPeer();
if (wpeer != null) {
wpeer.removeWindowListener(windowListener);
}
}
super.disposeImpl();
}
// native callbacks // native callbacks
void handleAction(final int index) { void handleAction(final int index) {
...@@ -121,4 +156,5 @@ class WChoicePeer extends WComponentPeer implements ChoicePeer { ...@@ -121,4 +156,5 @@ class WChoicePeer extends WComponentPeer implements ChoicePeer {
return getMinimumSize(); return getMinimumSize();
} }
native void closeList();
} }
...@@ -38,6 +38,10 @@ import java.awt.image.ColorModel; ...@@ -38,6 +38,10 @@ import java.awt.image.ColorModel;
import java.awt.event.PaintEvent; import java.awt.event.PaintEvent;
import java.awt.event.InvocationEvent; import java.awt.event.InvocationEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.awt.event.FocusEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.InputEvent;
import sun.awt.Win32GraphicsConfig; import sun.awt.Win32GraphicsConfig;
import sun.awt.Win32GraphicsEnvironment; import sun.awt.Win32GraphicsEnvironment;
import sun.java2d.InvalidPipeException; import sun.java2d.InvalidPipeException;
...@@ -68,6 +72,7 @@ public abstract class WComponentPeer extends WObjectPeer ...@@ -68,6 +72,7 @@ public abstract class WComponentPeer extends WObjectPeer
private static final Logger log = Logger.getLogger("sun.awt.windows.WComponentPeer"); private static final Logger log = Logger.getLogger("sun.awt.windows.WComponentPeer");
private static final Logger shapeLog = Logger.getLogger("sun.awt.windows.shape.WComponentPeer"); private static final Logger shapeLog = Logger.getLogger("sun.awt.windows.shape.WComponentPeer");
private static final Logger focusLog = Logger.getLogger("sun.awt.windows.focus.WComponentPeer");
// ComponentPeer implementation // ComponentPeer implementation
SurfaceData surfaceData; SurfaceData surfaceData;
...@@ -296,14 +301,35 @@ public abstract class WComponentPeer extends WObjectPeer ...@@ -296,14 +301,35 @@ public abstract class WComponentPeer extends WObjectPeer
// on handling '\n' to prevent it from being passed to native code // on handling '\n' to prevent it from being passed to native code
public boolean handleJavaKeyEvent(KeyEvent e) { return false; } public boolean handleJavaKeyEvent(KeyEvent e) { return false; }
public void handleJavaMouseEvent(MouseEvent e) {
switch (e.getID()) {
case MouseEvent.MOUSE_PRESSED:
// Note that Swing requests focus in its own mouse event handler.
if (target == e.getSource() &&
!((Component)target).isFocusOwner() &&
WKeyboardFocusManagerPeer.shouldFocusOnClick((Component)target))
{
WKeyboardFocusManagerPeer.requestFocusFor((Component)target,
CausedFocusEvent.Cause.MOUSE_EVENT);
}
break;
}
}
native void nativeHandleEvent(AWTEvent e); native void nativeHandleEvent(AWTEvent e);
public void handleEvent(AWTEvent e) { public void handleEvent(AWTEvent e) {
int id = e.getID(); int id = e.getID();
if (((Component)target).isEnabled() && (e instanceof KeyEvent) && !((KeyEvent)e).isConsumed()) { if ((e instanceof InputEvent) && !((InputEvent)e).isConsumed() &&
if (handleJavaKeyEvent((KeyEvent)e)) { ((Component)target).isEnabled())
return; {
if (e instanceof MouseEvent && !(e instanceof MouseWheelEvent)) {
handleJavaMouseEvent((MouseEvent) e);
} else if (e instanceof KeyEvent) {
if (handleJavaKeyEvent((KeyEvent)e)) {
return;
}
} }
} }
...@@ -319,6 +345,9 @@ public abstract class WComponentPeer extends WObjectPeer ...@@ -319,6 +345,9 @@ public abstract class WComponentPeer extends WObjectPeer
paintArea.paint(target,shouldClearRectBeforePaint()); paintArea.paint(target,shouldClearRectBeforePaint());
} }
return; return;
case FocusEvent.FOCUS_LOST:
case FocusEvent.FOCUS_GAINED:
handleJavaFocusEvent((FocusEvent)e);
default: default:
break; break;
} }
...@@ -327,6 +356,13 @@ public abstract class WComponentPeer extends WObjectPeer ...@@ -327,6 +356,13 @@ public abstract class WComponentPeer extends WObjectPeer
nativeHandleEvent(e); nativeHandleEvent(e);
} }
void handleJavaFocusEvent(FocusEvent fe) {
if (focusLog.isLoggable(Level.FINER)) focusLog.finer(fe.toString());
setFocus(fe.getID() == FocusEvent.FOCUS_GAINED);
}
native void setFocus(boolean doSetFocus);
public Dimension getMinimumSize() { public Dimension getMinimumSize() {
return ((Component)target).getSize(); return ((Component)target).getSize();
} }
...@@ -572,22 +608,64 @@ public abstract class WComponentPeer extends WObjectPeer ...@@ -572,22 +608,64 @@ public abstract class WComponentPeer extends WObjectPeer
WGlobalCursorManager.getCursorManager().updateCursorImmediately(); WGlobalCursorManager.getCursorManager().updateCursorImmediately();
} }
native static boolean processSynchronousLightweightTransfer(Component heavyweight, Component descendant, // TODO: consider moving it to KeyboardFocusManagerPeerImpl
boolean temporary, boolean focusedWindowChangeAllowed, public boolean requestFocus(Component lightweightChild, boolean temporary,
long time); boolean focusedWindowChangeAllowed, long time,
public boolean requestFocus CausedFocusEvent.Cause cause)
(Component lightweightChild, boolean temporary, {
boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) { if (WKeyboardFocusManagerPeer.
if (processSynchronousLightweightTransfer((Component)target, lightweightChild, temporary, processSynchronousLightweightTransfer((Component)target, lightweightChild, temporary,
focusedWindowChangeAllowed, time)) { focusedWindowChangeAllowed, time))
{
return true; return true;
} else {
return _requestFocus(lightweightChild, temporary, focusedWindowChangeAllowed, time, cause);
} }
int result = WKeyboardFocusManagerPeer
.shouldNativelyFocusHeavyweight((Component)target, lightweightChild,
temporary, focusedWindowChangeAllowed,
time, cause);
switch (result) {
case WKeyboardFocusManagerPeer.SNFH_FAILURE:
return false;
case WKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:
if (focusLog.isLoggable(Level.FINER)) {
focusLog.finer("Proceeding with request to " + lightweightChild + " in " + target);
}
Window parentWindow = SunToolkit.getContainingWindow((Component)target);
if (parentWindow == null) {
return rejectFocusRequestHelper("WARNING: Parent window is null");
}
WWindowPeer wpeer = (WWindowPeer)parentWindow.getPeer();
if (wpeer == null) {
return rejectFocusRequestHelper("WARNING: Parent window's peer is null");
}
boolean res = wpeer.requestWindowFocus(cause);
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Requested window focus: " + res);
// If parent window can be made focused and has been made focused(synchronously)
// then we can proceed with children, otherwise we retreat.
if (!(res && parentWindow.isFocused())) {
return rejectFocusRequestHelper("Waiting for asynchronous processing of the request");
}
return WKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
(Component)target,
temporary,
focusedWindowChangeAllowed,
time, cause);
case WKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
// Either lightweight or excessive request - all events are generated.
return true;
}
return false;
}
private boolean rejectFocusRequestHelper(String logMsg) {
if (focusLog.isLoggable(Level.FINER)) focusLog.finer(logMsg);
WKeyboardFocusManagerPeer.removeLastFocusRequest((Component)target);
return false;
} }
public native boolean _requestFocus
(Component lightweightChild, boolean temporary,
boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause);
public Image createImage(ImageProducer producer) { public Image createImage(ImageProducer producer) {
return new ToolkitImage(producer); return new ToolkitImage(producer);
...@@ -718,9 +796,12 @@ public abstract class WComponentPeer extends WObjectPeer ...@@ -718,9 +796,12 @@ public abstract class WComponentPeer extends WObjectPeer
* Post an event. Queue it for execution by the callback thread. * Post an event. Queue it for execution by the callback thread.
*/ */
void postEvent(AWTEvent event) { void postEvent(AWTEvent event) {
preprocessPostEvent(event);
WToolkit.postEvent(WToolkit.targetToAppContext(target), event); WToolkit.postEvent(WToolkit.targetToAppContext(target), event);
} }
void preprocessPostEvent(AWTEvent event) {}
// Routines to support deferred window positioning. // Routines to support deferred window positioning.
public void beginLayout() { public void beginLayout() {
// Skip all painting till endLayout // Skip all painting till endLayout
......
/* /*
* Copyright 2001-2002 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -23,21 +23,53 @@ ...@@ -23,21 +23,53 @@
* have any questions. * have any questions.
*/ */
#ifndef AWT_KEYBOARDFOCUSMANAGER_H package sun.awt.windows;
#define AWT_KEYBOARDFOCUSMANAGER_H
#include <jni.h> import java.awt.KeyboardFocusManager;
import java.awt.Window;
import java.awt.Component;
import java.awt.peer.ComponentPeer;
import sun.awt.KeyboardFocusManagerPeerImpl;
import sun.awt.CausedFocusEvent;
class AwtKeyboardFocusManager { class WKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
public: static native void setNativeFocusOwner(ComponentPeer peer);
static native Component getNativeFocusOwner();
static native Window getNativeFocusedWindow();
static jclass keyboardFocusManagerCls; WKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
static jmethodID shouldNativelyFocusHeavyweightMID; super(manager);
static jmethodID heavyweightButtonDownMID; }
static jmethodID markClearGlobalFocusOwnerMID;
static jmethodID removeLastFocusRequestMID;
static jfieldID isProxyActive;
static jmethodID processSynchronousTransfer;
};
#endif // AWT_KEYBOARDFOCUSMANAGER_H @Override
public void setCurrentFocusOwner(Component comp) {
setNativeFocusOwner(comp != null ? comp.getPeer() : null);
}
@Override
public Component getCurrentFocusOwner() {
return getNativeFocusOwner();
}
@Override
public Window getCurrentFocusedWindow() {
return getNativeFocusedWindow();
}
public static boolean deliverFocus(Component lightweightChild,
Component target,
boolean temporary,
boolean focusedWindowChangeAllowed,
long time,
CausedFocusEvent.Cause cause)
{
// TODO: do something to eliminate this forwarding
return KeyboardFocusManagerPeerImpl.deliverFocus(lightweightChild,
target,
temporary,
focusedWindowChangeAllowed,
time,
cause,
getNativeFocusOwner());
}
}
...@@ -494,6 +494,12 @@ public class WToolkit extends SunToolkit implements Runnable { ...@@ -494,6 +494,12 @@ public class WToolkit extends SunToolkit implements Runnable {
return true; return true;
} }
public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager)
throws HeadlessException
{
return new WKeyboardFocusManagerPeer(manager);
}
protected native void setDynamicLayoutNative(boolean b); protected native void setDynamicLayoutNative(boolean b);
public void setDynamicLayout(boolean b) { public void setDynamicLayout(boolean b) {
......
...@@ -77,6 +77,12 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer, ...@@ -77,6 +77,12 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
private final static PropertyChangeListener guiDisposedListener = private final static PropertyChangeListener guiDisposedListener =
new GuiDisposedListener(); new GuiDisposedListener();
/*
* Called (on the Toolkit thread) before the appropriate
* WindowStateEvent is posted to the EventQueue.
*/
private WindowListener windowListener;
/** /**
* Initialize JNI field IDs * Initialize JNI field IDs
*/ */
...@@ -232,27 +238,64 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer, ...@@ -232,27 +238,64 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
int[] smallIconRaster, int smw, int smh); int[] smallIconRaster, int smw, int smh);
synchronized native void reshapeFrame(int x, int y, int width, int height); synchronized native void reshapeFrame(int x, int y, int width, int height);
public boolean requestWindowFocus() {
// Win32 window doesn't need this public boolean requestWindowFocus(CausedFocusEvent.Cause cause) {
return false; if (!focusAllowedFor()) {
return false;
}
return requestWindowFocus(cause == CausedFocusEvent.Cause.MOUSE_EVENT);
} }
public native boolean requestWindowFocus(boolean isMouseEventCause);
public boolean focusAllowedFor() { public boolean focusAllowedFor() {
Window target = (Window)this.target; Window window = (Window)this.target;
if (!target.isVisible() || if (!window.isVisible() ||
!target.isEnabled() || !window.isEnabled() ||
!target.isFocusable()) !window.isFocusableWindow())
{ {
return false; return false;
} }
if (isModalBlocked()) { if (isModalBlocked()) {
return false; return false;
} }
return true; return true;
} }
public void hide() {
WindowListener listener = windowListener;
if (listener != null) {
// We're not getting WINDOW_CLOSING from the native code when hiding
// the window programmatically. So, create it and notify the listener.
listener.windowClosing(new WindowEvent((Window)target, WindowEvent.WINDOW_CLOSING));
}
super.hide();
}
// WARNING: it's called on the Toolkit thread!
void preprocessPostEvent(AWTEvent event) {
if (event instanceof WindowEvent) {
WindowListener listener = windowListener;
if (listener != null) {
switch(event.getID()) {
case WindowEvent.WINDOW_CLOSING:
listener.windowClosing((WindowEvent)event);
break;
case WindowEvent.WINDOW_ICONIFIED:
listener.windowIconified((WindowEvent)event);
break;
}
}
}
}
synchronized void addWindowListener(WindowListener l) {
windowListener = AWTEventMulticaster.add(windowListener, l);
}
synchronized void removeWindowListener(WindowListener l) {
windowListener = AWTEventMulticaster.remove(windowListener, l);
}
public void updateMinimumSize() { public void updateMinimumSize() {
Dimension minimumSize = null; Dimension minimumSize = null;
if (((Component)target).isMinimumSizeSet()) { if (((Component)target).isMinimumSizeSet()) {
......
/* /*
* Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include "awt_Button.h" #include "awt_Button.h"
#include "awt_Canvas.h" #include "awt_Canvas.h"
#include "awt_Window.h" #include "awt_Window.h"
#include "awt_KeyboardFocusManager.h"
/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
*/ */
...@@ -143,19 +142,6 @@ done: ...@@ -143,19 +142,6 @@ done:
return c; return c;
} }
BOOL AwtButton::ActMouseMessage(MSG * pMsg) {
if (!IsFocusingMessage(pMsg->message)) {
return FALSE;
}
if (pMsg->message == WM_LBUTTONDOWN) {
SendMessage(BM_SETSTATE, TRUE, 0);
} else if (pMsg->message == WM_LBUTTONUP) {
SendMessage(BM_SETSTATE, FALSE, 0);
}
return TRUE;
}
MsgRouting MsgRouting
AwtButton::WmMouseDown(UINT flags, int x, int y, int button) AwtButton::WmMouseDown(UINT flags, int x, int y, int button)
{ {
...@@ -204,23 +190,6 @@ AwtButton::NotifyListeners() ...@@ -204,23 +190,6 @@ AwtButton::NotifyListeners()
(jint)AwtComponent::GetJavaModifiers()); (jint)AwtComponent::GetJavaModifiers());
} }
/* 4531849 fix. Previous to 1.4, mouse clicks and typing space bar on a
* Button would notify ActionListeners via WM_COMMAND/WmNotify(). In 1.4, mouse
* grabs are done for all presses in order to correctly send drag and release
* events. However, WM_COMMAND message aren't sent when the mouse is grabbed,
* so ActionListeners for mouse clicks are sent via WmMouseUp/WmNotify().
* For some reason, if the right mouse button is held down when left-clicking
* on a Button, WM_COMMAND _IS_ sent. This resulted in two ActionEvents being
* sent in this case. To fix the problem, we handle typing space bar similar to
* left clicks - in WmKeyUp(), and do nothing for WM_COMMAND. -bchristi
*/
MsgRouting
AwtButton::WmKeyUp(UINT wkey, UINT repCnt, UINT flags, BOOL system)
{
MsgRouting mrResult = AwtComponent::WmKeyUp(wkey, repCnt, flags, system);
return mrResult;
}
MsgRouting MsgRouting
AwtButton::OwnerDrawItem(UINT /*ctrlId*/, DRAWITEMSTRUCT& drawInfo) AwtButton::OwnerDrawItem(UINT /*ctrlId*/, DRAWITEMSTRUCT& drawInfo)
{ {
...@@ -293,18 +262,26 @@ MsgRouting AwtButton::WmPaint(HDC) ...@@ -293,18 +262,26 @@ MsgRouting AwtButton::WmPaint(HDC)
return mrDoDefault; return mrDoDefault;
} }
BOOL AwtButton::IsFocusingMouseMessage(MSG *pMsg) {
return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONUP;
}
BOOL AwtButton::IsFocusingKeyMessage(MSG *pMsg) {
return (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP) &&
pMsg->wParam == VK_SPACE;
}
MsgRouting AwtButton::HandleEvent(MSG *msg, BOOL synthetic) MsgRouting AwtButton::HandleEvent(MSG *msg, BOOL synthetic)
{ {
if (AwtComponent::sm_focusOwner != GetHWnd() && if (IsFocusingMouseMessage(msg)) {
(msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK)) SendMessage(BM_SETSTATE, msg->message == WM_LBUTTONDOWN ? TRUE : FALSE, 0);
{ delete msg;
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); return mrConsume;
jobject target = GetTarget(env); }
env->CallStaticVoidMethod if (IsFocusingKeyMessage(msg)) {
(AwtKeyboardFocusManager::keyboardFocusManagerCls, SendMessage(BM_SETSTATE, msg->message == WM_KEYDOWN ? TRUE : FALSE, 0);
AwtKeyboardFocusManager::heavyweightButtonDownMID, delete msg;
target, ((jlong)msg->time) & 0xFFFFFFFF); return mrConsume;
env->DeleteLocalRef(target);
} }
return AwtComponent::HandleEvent(msg, synthetic); return AwtComponent::HandleEvent(msg, synthetic);
} }
......
/* /*
* Copyright 1996-2004 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -50,13 +50,13 @@ public: ...@@ -50,13 +50,13 @@ public:
/* Windows message handler functions */ /* Windows message handler functions */
MsgRouting WmMouseDown(UINT flags, int x, int y, int button); MsgRouting WmMouseDown(UINT flags, int x, int y, int button);
MsgRouting WmMouseUp(UINT flags, int x, int y, int button); MsgRouting WmMouseUp(UINT flags, int x, int y, int button);
MsgRouting WmKeyUp(UINT vkey, UINT repCnt, UINT flags, BOOL system);
MsgRouting OwnerDrawItem(UINT ctrlId, DRAWITEMSTRUCT& drawInfo); MsgRouting OwnerDrawItem(UINT ctrlId, DRAWITEMSTRUCT& drawInfo);
MsgRouting WmPaint(HDC hDC); MsgRouting WmPaint(HDC hDC);
MsgRouting HandleEvent(MSG *msg, BOOL synthetic); MsgRouting HandleEvent(MSG *msg, BOOL synthetic);
BOOL ActMouseMessage(MSG * pMsg); BOOL IsFocusingMouseMessage(MSG *pMsg);
BOOL IsFocusingKeyMessage(MSG *pMsg);
// called on Toolkit thread from JNI // called on Toolkit thread from JNI
static void _SetLabel(void *param); static void _SetLabel(void *param);
......
/* /*
* Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "awt_Toolkit.h" #include "awt_Toolkit.h"
#include "awt_Canvas.h" #include "awt_Canvas.h"
#include "awt_Win32GraphicsConfig.h" #include "awt_Win32GraphicsConfig.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Window.h" #include "awt_Window.h"
/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
...@@ -176,27 +175,9 @@ MsgRouting AwtCanvas::WmPaint(HDC) ...@@ -176,27 +175,9 @@ MsgRouting AwtCanvas::WmPaint(HDC)
MsgRouting AwtCanvas::HandleEvent(MSG *msg, BOOL synthetic) MsgRouting AwtCanvas::HandleEvent(MSG *msg, BOOL synthetic)
{ {
if (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) { if (IsFocusingMouseMessage(msg)) {
/* delete msg;
* Fix for BugTraq ID 4041703: keyDown not being invoked. return mrConsume;
* Give the focus to a Canvas or Panel if it doesn't have heavyweight
* subcomponents so that they will behave the same way as on Solaris
* providing a possibility of giving keyboard focus to an empty Applet.
* Since ScrollPane doesn't receive focus on mouse press on Solaris,
* HandleEvent() is overriden there to do nothing with focus.
*/
if (AwtComponent::sm_focusOwner != GetHWnd() &&
::GetWindow(GetHWnd(), GW_CHILD) == NULL)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject target = GetTarget(env);
env->CallStaticVoidMethod
(AwtKeyboardFocusManager::keyboardFocusManagerCls,
AwtKeyboardFocusManager::heavyweightButtonDownMID,
target, ((jlong)msg->time) & 0xFFFFFFFF);
env->DeleteLocalRef(target);
AwtSetFocus();
}
} }
return AwtComponent::HandleEvent(msg, synthetic); return AwtComponent::HandleEvent(msg, synthetic);
} }
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "awt.h" #include "awt.h"
#include "awt_Toolkit.h" #include "awt_Toolkit.h"
#include "awt_Checkbox.h" #include "awt_Checkbox.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Canvas.h" #include "awt_Canvas.h"
#include "awt_Window.h" #include "awt_Window.h"
...@@ -143,17 +142,6 @@ done: ...@@ -143,17 +142,6 @@ done:
return checkbox; return checkbox;
} }
BOOL AwtCheckbox::ActMouseMessage(MSG* pMsg) {
if (!IsFocusingMessage(pMsg->message)) {
return FALSE;
}
if (pMsg->message == WM_LBUTTONDOWN) {
SendMessage(BM_SETSTATE, ~SendMessage(BM_GETSTATE, 0, 0), 0);
}
return TRUE;
}
MsgRouting MsgRouting
AwtCheckbox::WmMouseUp(UINT flags, int x, int y, int button) AwtCheckbox::WmMouseUp(UINT flags, int x, int y, int button)
{ {
...@@ -329,18 +317,32 @@ MsgRouting AwtCheckbox::WmPaint(HDC) ...@@ -329,18 +317,32 @@ MsgRouting AwtCheckbox::WmPaint(HDC)
return mrDoDefault; return mrDoDefault;
} }
BOOL AwtCheckbox::IsFocusingMouseMessage(MSG *pMsg) {
return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONUP;
}
BOOL AwtCheckbox::IsFocusingKeyMessage(MSG *pMsg) {
return (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP) &&
pMsg->wParam == VK_SPACE;
}
MsgRouting AwtCheckbox::HandleEvent(MSG *msg, BOOL synthetic) MsgRouting AwtCheckbox::HandleEvent(MSG *msg, BOOL synthetic)
{ {
if (IsFocusable() && AwtComponent::sm_focusOwner != GetHWnd() && if (IsFocusingMouseMessage(msg)) {
(msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK)) SendMessage(BM_SETSTATE, (WPARAM)(msg->message == WM_LBUTTONDOWN ? TRUE : FALSE));
{ delete msg;
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); return mrConsume;
jobject target = GetTarget(env); }
env->CallStaticVoidMethod if (IsFocusingKeyMessage(msg)) {
(AwtKeyboardFocusManager::keyboardFocusManagerCls, SendMessage(BM_SETSTATE, (WPARAM)(msg->message == WM_KEYDOWN ? TRUE : FALSE));
AwtKeyboardFocusManager::heavyweightButtonDownMID, if (msg->message == WM_KEYDOWN) {
target, ((jlong)msg->time) & 0xFFFFFFFF); m_fLButtonDowned = TRUE;
env->DeleteLocalRef(target); } else if (m_fLButtonDowned == TRUE) {
WmNotify(BN_CLICKED);
m_fLButtonDowned = TRUE;
}
delete msg;
return mrConsume;
} }
return AwtComponent::HandleEvent(msg, synthetic); return AwtComponent::HandleEvent(msg, synthetic);
} }
......
...@@ -69,7 +69,8 @@ public: ...@@ -69,7 +69,8 @@ public:
MsgRouting HandleEvent(MSG *msg, BOOL synthetic); MsgRouting HandleEvent(MSG *msg, BOOL synthetic);
BOOL ActMouseMessage(MSG* pMsg); BOOL IsFocusingMouseMessage(MSG *pMsg);
BOOL IsFocusingKeyMessage(MSG *pMsg);
// called on Toolkit thread from JNI // called on Toolkit thread from JNI
static void _SetLabel(void *param); static void _SetLabel(void *param);
......
...@@ -23,14 +23,17 @@ ...@@ -23,14 +23,17 @@
* have any questions. * have any questions.
*/ */
#include <windowsx.h>
#include "awt_Toolkit.h" #include "awt_Toolkit.h"
#include "awt_Choice.h" #include "awt_Choice.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Canvas.h" #include "awt_Canvas.h"
#include "awt_Dimension.h" #include "awt_Dimension.h"
#include "awt_Container.h" #include "awt_Container.h"
#include "ComCtl32Util.h"
#include <java_awt_Toolkit.h> #include <java_awt_Toolkit.h>
#include <java_awt_FontMetrics.h> #include <java_awt_FontMetrics.h>
#include <java_awt_event_InputEvent.h> #include <java_awt_event_InputEvent.h>
...@@ -71,18 +74,29 @@ BOOL AwtChoice::mouseCapture = FALSE; ...@@ -71,18 +74,29 @@ BOOL AwtChoice::mouseCapture = FALSE;
/* Bug #4338368: consume the spurious MouseUp when the choice loses focus */ /* Bug #4338368: consume the spurious MouseUp when the choice loses focus */
BOOL AwtChoice::skipNextMouseUp = FALSE; BOOL AwtChoice::skipNextMouseUp = FALSE;
BOOL AwtChoice::sm_isMouseMoveInList = FALSE;
/************************************************************************* /*************************************************************************
* AwtChoice class methods * AwtChoice class methods
*/ */
AwtChoice::AwtChoice() { AwtChoice::AwtChoice() {
killFocusRouting = mrPassAlong; m_hList = NULL;
m_listDefWindowProc = NULL;
} }
LPCTSTR AwtChoice::GetClassName() { LPCTSTR AwtChoice::GetClassName() {
return TEXT("COMBOBOX"); /* System provided combobox class */ return TEXT("COMBOBOX"); /* System provided combobox class */
} }
void AwtChoice::Dispose() {
if (m_hList != NULL && m_listDefWindowProc != NULL) {
ComCtl32Util::GetInstance().UnsubclassHWND(m_hList, ListWindowProc, m_listDefWindowProc);
}
AwtComponent::Dispose();
}
AwtChoice* AwtChoice::Create(jobject peer, jobject parent) { AwtChoice* AwtChoice::Create(jobject peer, jobject parent) {
...@@ -175,17 +189,6 @@ done: ...@@ -175,17 +189,6 @@ done:
return c; return c;
} }
BOOL AwtChoice::ActMouseMessage(MSG* pMsg) {
if (!IsFocusingMessage(pMsg->message)) {
return FALSE;
}
if (pMsg->message == WM_LBUTTONDOWN) {
SendMessage(CB_SHOWDROPDOWN, ~SendMessage(CB_GETDROPPEDSTATE, 0, 0), 0);
}
return TRUE;
}
// calculate height of drop-down list part of the combobox // calculate height of drop-down list part of the combobox
// to show all the items up to a maximum of eight // to show all the items up to a maximum of eight
int AwtChoice::GetDropDownHeight() int AwtChoice::GetDropDownHeight()
...@@ -253,6 +256,7 @@ void AwtChoice::SetDragCapture(UINT flags) ...@@ -253,6 +256,7 @@ void AwtChoice::SetDragCapture(UINT flags)
} }
return; return;
} }
// don't want to interfere with other controls // don't want to interfere with other controls
if (::GetCapture() == NULL) { if (::GetCapture() == NULL) {
::SetCapture(GetHWnd()); ::SetCapture(GetHWnd());
...@@ -370,6 +374,58 @@ void AwtChoice::SetFont(AwtFont* font) ...@@ -370,6 +374,58 @@ void AwtChoice::SetFont(AwtFont* font)
env->DeleteLocalRef(target); env->DeleteLocalRef(target);
} }
static int lastClickX = -1;
static int lastClickY = -1;
LRESULT CALLBACK AwtChoice::ListWindowProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
/*
* We don't pass the choice WM_LBUTTONDOWN message. As the result the choice's list
* doesn't forward mouse messages it captures. Below we do forward what we need.
*/
TRY;
DASSERT(::IsWindow(hwnd));
switch (message) {
case WM_LBUTTONDOWN: {
DWORD curPos = ::GetMessagePos();
lastClickX = GET_X_LPARAM(curPos);
lastClickY = GET_Y_LPARAM(curPos);
break;
}
case WM_MOUSEMOVE: {
RECT rect;
::GetClientRect(hwnd, &rect);
POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
if (::PtInRect(&rect, pt)) {
sm_isMouseMoveInList = TRUE;
}
POINT lastPt = {lastClickX, lastClickY};
::ScreenToClient(hwnd, &lastPt);
if (::PtInRect(&rect, lastPt)) {
break; // ignore when dragging inside the list
}
}
case WM_LBUTTONUP: {
lastClickX = -1;
lastClickY = -1;
AwtChoice *c = (AwtChoice *)::GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (c != NULL) {
// forward the msg to the choice
c->WindowProc(message, wParam, lParam);
}
}
}
return ComCtl32Util::GetInstance().DefWindowProc(NULL, hwnd, message, wParam, lParam);
CATCH_BAD_ALLOC_RET(0);
}
MsgRouting AwtChoice::WmNotify(UINT notifyCode) MsgRouting AwtChoice::WmNotify(UINT notifyCode)
...@@ -379,15 +435,24 @@ MsgRouting AwtChoice::WmNotify(UINT notifyCode) ...@@ -379,15 +435,24 @@ MsgRouting AwtChoice::WmNotify(UINT notifyCode)
if (itemSelect != CB_ERR){ if (itemSelect != CB_ERR){
DoCallback("handleAction", "(I)V", itemSelect); DoCallback("handleAction", "(I)V", itemSelect);
} }
} else if (notifyCode == CBN_DROPDOWN && !IsFocusable()) { } else if (notifyCode == CBN_DROPDOWN) {
// While non-focusable Choice is shown all WM_KILLFOCUS messages should be consumed.
killFocusRouting = mrConsume; if (m_hList == NULL) {
} else if (notifyCode == CBN_CLOSEUP && !IsFocusable()) { COMBOBOXINFO cbi;
// When non-focusable Choice is about to close, send it synthetic WM_KILLFOCUS cbi.cbSize = sizeof(COMBOBOXINFO);
// message that should be processed by the native widget only. This will allow ::GetComboBoxInfo(GetHWnd(), &cbi);
// the native widget to properly process WM_KILLFOCUS that was earlier consumed. m_hList = cbi.hwndList;
killFocusRouting = mrDoDefault; m_listDefWindowProc = ComCtl32Util::GetInstance().SubclassHWND(m_hList, ListWindowProc);
::PostMessage(GetHWnd(), WM_KILLFOCUS, (LPARAM)sm_focusOwner, 0); DASSERT(::GetWindowLongPtr(m_hList, GWLP_USERDATA) == NULL);
::SetWindowLongPtr(m_hList, GWLP_USERDATA, (LONG_PTR)this);
}
sm_isMouseMoveInList = FALSE;
// Clicking in the dropdown list steals focus from the proxy.
// So, set the focus-restore flag up.
SetRestoreFocus(TRUE);
} else if (notifyCode == CBN_CLOSEUP) {
SetRestoreFocus(FALSE);
} }
return mrDoDefault; return mrDoDefault;
} }
...@@ -414,19 +479,7 @@ MsgRouting ...@@ -414,19 +479,7 @@ MsgRouting
AwtChoice::WmKillFocus(HWND hWndGotFocus) AwtChoice::WmKillFocus(HWND hWndGotFocus)
{ {
skipNextMouseUp = TRUE; skipNextMouseUp = TRUE;
return AwtComponent::WmKillFocus(hWndGotFocus);
switch (killFocusRouting) {
case mrConsume:
return mrConsume;
case mrDoDefault:
killFocusRouting = mrPassAlong;
return mrDoDefault;
case mrPassAlong:
return AwtComponent::WmKillFocus(hWndGotFocus);
}
DASSERT(false); // must never reach here
return mrDoDefault;
} }
MsgRouting MsgRouting
...@@ -441,27 +494,17 @@ AwtChoice::WmMouseUp(UINT flags, int x, int y, int button) ...@@ -441,27 +494,17 @@ AwtChoice::WmMouseUp(UINT flags, int x, int y, int button)
MsgRouting AwtChoice::HandleEvent(MSG *msg, BOOL synthetic) MsgRouting AwtChoice::HandleEvent(MSG *msg, BOOL synthetic)
{ {
/* if (IsFocusingMouseMessage(msg)) {
* 6366006 SendMessage(CB_SHOWDROPDOWN, ~SendMessage(CB_GETDROPPEDSTATE, 0, 0), 0);
* Note: the event can be sent in two cases: delete msg;
* 1) The Choice is closed and user clicks on it to drop it down. return mrConsume;
* 2) The Choice is non-focusable, it's droped down, user }
* clicks on it (or outside) to close it. // To simulate the native behavior, we close the list on WM_LBUTTONUP if
* So, if the Choice is in droped down state, we shouldn't call // WM_MOUSEMOVE has been dedected on the list since it has been dropped down.
* heavyweightButtonDown() method. Otherwise it will set a typeahead marker if (msg->message == WM_LBUTTONUP && SendMessage(CB_GETDROPPEDSTATE, 0, 0) &&
* that won't be removed, because no focus events will be generated. sm_isMouseMoveInList)
*/
if (AwtComponent::sm_focusOwner != GetHWnd() &&
(msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) &&
!IsChoiceOpened())
{ {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); SendMessage(CB_SHOWDROPDOWN, FALSE, 0);
jobject target = GetTarget(env);
env->CallStaticVoidMethod
(AwtKeyboardFocusManager::keyboardFocusManagerCls,
AwtKeyboardFocusManager::heavyweightButtonDownMID,
target, ((jlong)msg->time) & 0xFFFFFFFF);
env->DeleteLocalRef(target);
} }
return AwtComponent::HandleEvent(msg, synthetic); return AwtComponent::HandleEvent(msg, synthetic);
} }
...@@ -618,6 +661,26 @@ done: ...@@ -618,6 +661,26 @@ done:
env->DeleteGlobalRef(choice); env->DeleteGlobalRef(choice);
} }
void AwtChoice::_CloseList(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject choice = (jobject)param;
AwtChoice *c = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(choice, done);
c = (AwtChoice *)pData;
if (::IsWindow(c->GetHWnd()) && c->SendMessage(CB_GETDROPPEDSTATE, 0, 0)) {
c->SendMessage(CB_SHOWDROPDOWN, FALSE, 0);
}
done:
env->DeleteGlobalRef(choice);
}
/************************************************************************ /************************************************************************
* WChoicePeer native methods * WChoicePeer native methods
*/ */
...@@ -752,6 +815,23 @@ Java_sun_awt_windows_WChoicePeer_create(JNIEnv *env, jobject self, ...@@ -752,6 +815,23 @@ Java_sun_awt_windows_WChoicePeer_create(JNIEnv *env, jobject self,
CATCH_BAD_ALLOC; CATCH_BAD_ALLOC;
} }
/*
* Class: sun_awt_windows_WChoicePeer
* Method: closeList
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WChoicePeer_closeList(JNIEnv *env, jobject self)
{
TRY;
jobject selfGlobalRef = env->NewGlobalRef(self);
AwtToolkit::GetInstance().SyncCall(AwtChoice::_CloseList, (void *)selfGlobalRef);
// global ref is deleted in _CloseList
CATCH_BAD_ALLOC;
}
} /* extern "C" */ } /* extern "C" */
......
...@@ -43,6 +43,8 @@ public: ...@@ -43,6 +43,8 @@ public:
virtual LPCTSTR GetClassName(); virtual LPCTSTR GetClassName();
static AwtChoice* Create(jobject peer, jobject hParent); static AwtChoice* Create(jobject peer, jobject hParent);
virtual void Dispose();
virtual void Reshape(int x, int y, int w, int h); virtual void Reshape(int x, int y, int w, int h);
void ResetDropDownHeight(); void ResetDropDownHeight();
int GetDropDownHeight(); int GetDropDownHeight();
...@@ -75,9 +77,6 @@ public: ...@@ -75,9 +77,6 @@ public:
virtual void SetDragCapture(UINT flags); virtual void SetDragCapture(UINT flags);
virtual void ReleaseDragCapture(UINT flags); virtual void ReleaseDragCapture(UINT flags);
BOOL ActMouseMessage(MSG * pMsg);
INLINE BOOL AwtChoice::IsChoiceOpened() {return SendMessage(CB_GETDROPPEDSTATE, 0, 0);}
static BOOL mouseCapture; static BOOL mouseCapture;
static BOOL skipNextMouseUp; static BOOL skipNextMouseUp;
...@@ -87,11 +86,16 @@ public: ...@@ -87,11 +86,16 @@ public:
static void _AddItems(void *param); static void _AddItems(void *param);
static void _Remove(void *param); static void _Remove(void *param);
static void _RemoveAll(void *param); static void _RemoveAll(void *param);
static void _CloseList(void *param);
private: private:
int GetFieldHeight(); int GetFieldHeight();
int GetTotalHeight(); int GetTotalHeight();
MsgRouting killFocusRouting; static BOOL sm_isMouseMoveInList;
HWND m_hList;
WNDPROC m_listDefWindowProc;
static LRESULT CALLBACK ListWindowProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam);
}; };
#endif /* AWT_CHOICE_H */ #endif /* AWT_CHOICE_H */
...@@ -78,8 +78,6 @@ class AwtPopupMenu; ...@@ -78,8 +78,6 @@ class AwtPopupMenu;
class AwtDropTarget; class AwtDropTarget;
struct WmComponentSetFocusData;
/* /*
* Message routing codes * Message routing codes
*/ */
...@@ -221,17 +219,10 @@ public: ...@@ -221,17 +219,10 @@ public:
virtual BOOL IsContainer() { return FALSE;} // Plain components can't virtual BOOL IsContainer() { return FALSE;} // Plain components can't
/** /**
* Perform some actions which by default are being performed by Default Window procedure of * Returns TRUE if this message will trigger native focus change, FALSE otherwise.
* this window class
* For detailed comments see implementation in awt_Component.cpp
*/
virtual BOOL ActMouseMessage(MSG * pMsg);
/**
* Returns TRUE if this message will this component to become focused. Returns FALSE otherwise.
*/ */
inline BOOL IsFocusingMessage(UINT message) { virtual BOOL IsFocusingKeyMessage(MSG *pMsg);
return message == WM_LBUTTONDOWN || message == WM_LBUTTONUP || message == WM_LBUTTONDBLCLK; virtual BOOL IsFocusingMouseMessage(MSG *pMsg);
}
BOOL IsFocusable(); BOOL IsFocusable();
...@@ -477,6 +468,12 @@ public: ...@@ -477,6 +468,12 @@ public:
HIMC ImmGetContext(); HIMC ImmGetContext();
HIMC ImmAssociateContext(HIMC himc); HIMC ImmAssociateContext(HIMC himc);
HWND GetProxyFocusOwner(); HWND GetProxyFocusOwner();
INLINE HWND GetProxyToplevelContainer() {
HWND proxyHWnd = GetProxyFocusOwner();
return ::GetAncestor(proxyHWnd, GA_ROOT); // a browser in case of EmbeddedFrame
}
void CallProxyDefWindowProc(UINT message, void CallProxyDefWindowProc(UINT message,
WPARAM wParam, WPARAM wParam,
LPARAM lParam, LPARAM lParam,
...@@ -514,11 +511,6 @@ public: ...@@ -514,11 +511,6 @@ public:
virtual MsgRouting WmShowWindow(BOOL show, UINT status); virtual MsgRouting WmShowWindow(BOOL show, UINT status);
virtual MsgRouting WmSetFocus(HWND hWndLost); virtual MsgRouting WmSetFocus(HWND hWndLost);
virtual MsgRouting WmKillFocus(HWND hWndGot); virtual MsgRouting WmKillFocus(HWND hWndGot);
jboolean WmComponentSetFocus(WmComponentSetFocusData *data);
// Use instead of ::SetFocus to maintain special focusing semantics for
// Windows which are not Frames/Dialogs.
BOOL AwtSetFocus();
virtual MsgRouting WmCtlColor(HDC hDC, HWND hCtrl, virtual MsgRouting WmCtlColor(HDC hDC, HWND hCtrl,
UINT ctlColor, HBRUSH& retBrush); UINT ctlColor, HBRUSH& retBrush);
virtual MsgRouting WmHScroll(UINT scrollCode, UINT pos, HWND hScrollBar); virtual MsgRouting WmHScroll(UINT scrollCode, UINT pos, HWND hScrollBar);
...@@ -608,10 +600,6 @@ public: ...@@ -608,10 +600,6 @@ public:
jintArray CreatePrintedPixels(SIZE &loc, SIZE &size); jintArray CreatePrintedPixels(SIZE &loc, SIZE &size);
static void * GetNativeFocusOwner();
static void * GetNativeFocusedWindow();
static void ClearGlobalFocusOwner();
/* /*
* HWND, AwtComponent and Java Peer interaction * HWND, AwtComponent and Java Peer interaction
* *
...@@ -670,7 +658,6 @@ public: ...@@ -670,7 +658,6 @@ public:
static void _SetForeground(void *param); static void _SetForeground(void *param);
static void _SetBackground(void *param); static void _SetBackground(void *param);
static void _SetFont(void *param); static void _SetFont(void *param);
static jboolean _RequestFocus(void *param);
static void _Start(void *param); static void _Start(void *param);
static void _BeginValidate(void *param); static void _BeginValidate(void *param);
static void _EndValidate(void *param); static void _EndValidate(void *param);
...@@ -685,6 +672,29 @@ public: ...@@ -685,6 +672,29 @@ public:
static HWND sm_focusOwner; static HWND sm_focusOwner;
static HWND sm_focusedWindow; static HWND sm_focusedWindow;
static void _SetFocus(void *param);
static void *SetNativeFocusOwner(void *self);
static void *GetNativeFocusedWindow();
static void *GetNativeFocusOwner();
static BOOL sm_inSynthesizeFocus;
// Execute on Toolkit only.
INLINE static LRESULT SynthesizeWmSetFocus(HWND targetHWnd, HWND oppositeHWnd) {
sm_inSynthesizeFocus = TRUE;
LRESULT res = ::SendMessage(targetHWnd, WM_SETFOCUS, (WPARAM)oppositeHWnd, 0);
sm_inSynthesizeFocus = FALSE;
return res;
}
// Execute on Toolkit only.
INLINE static LRESULT SynthesizeWmKillFocus(HWND targetHWnd, HWND oppositeHWnd) {
sm_inSynthesizeFocus = TRUE;
LRESULT res = ::SendMessage(targetHWnd, WM_KILLFOCUS, (WPARAM)oppositeHWnd, 0);
sm_inSynthesizeFocus = FALSE;
return res;
}
static BOOL sm_bMenuLoop; static BOOL sm_bMenuLoop;
static INLINE BOOL isMenuLoopActive() { static INLINE BOOL isMenuLoopActive() {
return sm_bMenuLoop; return sm_bMenuLoop;
...@@ -708,7 +718,18 @@ protected: ...@@ -708,7 +718,18 @@ protected:
BOOL m_visible; /* copy of Component.visible */ BOOL m_visible; /* copy of Component.visible */
static BOOL sm_suppressFocusAndActivation; static BOOL sm_suppressFocusAndActivation;
static HWND sm_realFocusOpposite; static BOOL sm_restoreFocusAndActivation;
/*
* The function sets the focus-restore flag ON/OFF.
* When the flag is ON, focus is restored immidiately after the proxy loses it.
* All focus messages are suppressed. It's also assumed that sm_focusedWindow and
* sm_focusOwner don't change after the flag is set ON and before it's set OFF.
*/
static INLINE void SetRestoreFocus(BOOL doSet) {
sm_suppressFocusAndActivation = doSet;
sm_restoreFocusAndActivation = doSet;
}
virtual void SetDragCapture(UINT flags); virtual void SetDragCapture(UINT flags);
virtual void ReleaseDragCapture(UINT flags); virtual void ReleaseDragCapture(UINT flags);
...@@ -778,8 +799,6 @@ private: ...@@ -778,8 +799,6 @@ private:
static BOOL m_QueryNewPaletteCalled; static BOOL m_QueryNewPaletteCalled;
BOOL m_skipNextSetFocus;
static AwtComponent* sm_getComponentCache; // a cache for the GetComponent(..) method. static AwtComponent* sm_getComponentCache; // a cache for the GetComponent(..) method.
int windowMoveLockPosX; int windowMoveLockPosX;
...@@ -874,14 +893,6 @@ public: ...@@ -874,14 +893,6 @@ public:
void RealizePalettes(int screen); void RealizePalettes(int screen);
}; };
struct WmComponentSetFocusData {
jobject lightweightChild;
jboolean temporary;
jboolean focusedWindowChangeAllowed;
jlong time;
jobject cause;
};
void ReleaseDCList(HWND hwnd, DCList &list); void ReleaseDCList(HWND hwnd, DCList &list);
void MoveDCToPassiveList(HDC hDC); void MoveDCToPassiveList(HDC hDC);
......
/* /*
* Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -39,8 +39,6 @@ ...@@ -39,8 +39,6 @@
#include <sun_awt_windows_WEmbeddedFramePeer.h> #include <sun_awt_windows_WEmbeddedFramePeer.h>
BOOL isAppActive = FALSE;
/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
*/ */
...@@ -112,6 +110,7 @@ AwtFrame::AwtFrame() { ...@@ -112,6 +110,7 @@ AwtFrame::AwtFrame() {
m_isInputMethodWindow = FALSE; m_isInputMethodWindow = FALSE;
m_isUndecorated = FALSE; m_isUndecorated = FALSE;
m_proxyFocusOwner = NULL; m_proxyFocusOwner = NULL;
m_lastProxiedFocusOwner = NULL;
m_actualFocusedWindow = NULL; m_actualFocusedWindow = NULL;
m_iconic = FALSE; m_iconic = FALSE;
m_zoomed = FALSE; m_zoomed = FALSE;
...@@ -287,7 +286,6 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent) ...@@ -287,7 +286,6 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent)
::GetSysColor(COLOR_WINDOWTEXT), ::GetSysColor(COLOR_WINDOWTEXT),
::GetSysColor(COLOR_WINDOWFRAME), ::GetSysColor(COLOR_WINDOWFRAME),
self); self);
/* /*
* Reshape here instead of during create, so that a * Reshape here instead of during create, so that a
* WM_NCCALCSIZE is sent. * WM_NCCALCSIZE is sent.
...@@ -327,7 +325,7 @@ LRESULT CALLBACK AwtFrame::ProxyWindowProc(HWND hwnd, UINT message, ...@@ -327,7 +325,7 @@ LRESULT CALLBACK AwtFrame::ProxyWindowProc(HWND hwnd, UINT message,
return ComCtl32Util::GetInstance().DefWindowProc(NULL, hwnd, message, wParam, lParam); return ComCtl32Util::GetInstance().DefWindowProc(NULL, hwnd, message, wParam, lParam);
} }
AwtComponent *p = NULL; AwtComponent *focusOwner = NULL;
// IME and input language related messages need to be sent to a window // IME and input language related messages need to be sent to a window
// which has the Java input focus // which has the Java input focus
switch (message) { switch (message) {
...@@ -345,16 +343,37 @@ LRESULT CALLBACK AwtFrame::ProxyWindowProc(HWND hwnd, UINT message, ...@@ -345,16 +343,37 @@ LRESULT CALLBACK AwtFrame::ProxyWindowProc(HWND hwnd, UINT message,
case WM_IME_KEYUP: case WM_IME_KEYUP:
case WM_INPUTLANGCHANGEREQUEST: case WM_INPUTLANGCHANGEREQUEST:
case WM_INPUTLANGCHANGE: case WM_INPUTLANGCHANGE:
p = AwtComponent::GetComponent(sm_focusOwner); // TODO: when a Choice's list is dropped down and we're scrolling in
if (p != NULL) { // the list WM_MOUSEWHEEL messages come to the poxy, not to the list. Why?
return p->WindowProc(message, wParam, lParam); case WM_MOUSEWHEEL:
focusOwner = AwtComponent::GetComponent(parent->GetLastProxiedFocusOwner());
if (focusOwner != NULL) {
return focusOwner->WindowProc(message, wParam, lParam);
} }
break; break;
case WM_SETFOCUS:
if (!sm_suppressFocusAndActivation && parent->IsEmbeddedFrame()) {
parent->AwtSetActiveWindow();
}
return 0;
case WM_KILLFOCUS:
if (!sm_suppressFocusAndActivation && parent->IsEmbeddedFrame()) {
AwtWindow::SynthesizeWmActivate(FALSE, parent->GetHWnd(), NULL);
} else if (sm_restoreFocusAndActivation) {
if (sm_focusedWindow != NULL) {
AwtWindow *focusedWindow = (AwtWindow*)GetComponent(sm_focusedWindow);
if (focusedWindow != NULL) {
// Will just silently restore native focus & activation.
focusedWindow->AwtSetActiveWindow();
}
}
}
return 0;
case 0x0127: // WM_CHANGEUISTATE case 0x0127: // WM_CHANGEUISTATE
case 0x0128: // WM_UPDATEUISTATE case 0x0128: // WM_UPDATEUISTATE
return 0; return 0;
} }
return parent->WindowProc(message, wParam, lParam); return parent->WindowProc(message, wParam, lParam);
CATCH_BAD_ALLOC_RET(0); CATCH_BAD_ALLOC_RET(0);
...@@ -557,7 +576,6 @@ MsgRouting AwtFrame::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) { ...@@ -557,7 +576,6 @@ MsgRouting AwtFrame::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
if (m_grabbedWindow != NULL/* && !m_grabbedWindow->IsOneOfOwnersOf(this)*/) { if (m_grabbedWindow != NULL/* && !m_grabbedWindow->IsOneOfOwnersOf(this)*/) {
m_grabbedWindow->Ungrab(); m_grabbedWindow->Ungrab();
} }
if (!IsFocusableWindow() && (button & LEFT_BUTTON)) { if (!IsFocusableWindow() && (button & LEFT_BUTTON)) {
switch (hitTest) { switch (hitTest) {
case HTTOP: case HTTOP:
...@@ -915,33 +933,16 @@ MsgRouting AwtFrame::WmSize(UINT type, int w, int h) ...@@ -915,33 +933,16 @@ MsgRouting AwtFrame::WmSize(UINT type, int w, int h)
MsgRouting AwtFrame::WmActivate(UINT nState, BOOL fMinimized, HWND opposite) MsgRouting AwtFrame::WmActivate(UINT nState, BOOL fMinimized, HWND opposite)
{ {
jint type; jint type;
BOOL doActivateFrame = TRUE;
if (nState != WA_INACTIVE) { if (nState != WA_INACTIVE) {
if (!::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()))) { if (::IsWindow(AwtWindow::GetModalBlocker(GetHWnd())) ||
::SetFocus(NULL); // The KeyboardFocusManager will set focus later CheckActivateActualFocusedWindow(opposite))
type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS; {
isAppActive = TRUE; return mrConsume;
sm_focusedWindow = GetHWnd();
/*
* Fix for 4823903.
* If the window to be focused is actually not this Frame
* and it's visible then send it WM_ACTIVATE.
*/
if (m_actualFocusedWindow != NULL) {
HWND hwnd = m_actualFocusedWindow->GetHWnd();
if (hwnd != NULL && ::IsWindowVisible(hwnd)) {
::SendMessage(hwnd, WM_ACTIVATE, MAKEWPARAM(nState, fMinimized), (LPARAM)opposite);
doActivateFrame = FALSE;
}
m_actualFocusedWindow = NULL;
}
} else {
doActivateFrame = FALSE;
} }
type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS;
sm_focusedWindow = GetHWnd();
} else { } else {
if (!::IsWindow(AwtWindow::GetModalBlocker(opposite))) { if (!::IsWindow(AwtWindow::GetModalBlocker(opposite))) {
// If deactivation happens because of press on grabbing // If deactivation happens because of press on grabbing
...@@ -963,37 +964,63 @@ MsgRouting AwtFrame::WmActivate(UINT nState, BOOL fMinimized, HWND opposite) ...@@ -963,37 +964,63 @@ MsgRouting AwtFrame::WmActivate(UINT nState, BOOL fMinimized, HWND opposite)
} }
} }
} }
CheckRetainActualFocusedWindow(opposite);
// If actual focused window is not this Frame type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS;
if (sm_focusedWindow != GetHWnd()) { sm_focusedWindow = NULL;
sm_focusOwner = NULL;
}
}
// Check that the Frame is going to be really inactive (i.e. the opposite is not its owned window) SendWindowEvent(type, opposite);
if (opposite != NULL) { return mrConsume;
AwtWindow *wOpposite = (AwtWindow *)AwtComponent::GetComponent(opposite); }
if (wOpposite != NULL && BOOL AwtFrame::CheckActivateActualFocusedWindow(HWND deactivatedOpositeHWnd)
wOpposite->GetOwningFrameOrDialog() != this) {
{ if (m_actualFocusedWindow != NULL) {
AwtWindow *window = (AwtWindow *)AwtComponent::GetComponent(sm_focusedWindow); HWND hwnd = m_actualFocusedWindow->GetHWnd();
if (hwnd != NULL && ::IsWindowVisible(hwnd)) {
SynthesizeWmActivate(TRUE, hwnd, deactivatedOpositeHWnd);
return TRUE;
}
m_actualFocusedWindow = NULL;
}
return FALSE;
}
// If actual focused window is one of Frame's owned windows void AwtFrame::CheckRetainActualFocusedWindow(HWND activatedOpositeHWnd)
if (window != NULL && window->GetOwningFrameOrDialog() == this) { {
m_actualFocusedWindow = window; // If actual focused window is not this Frame
} if (sm_focusedWindow != GetHWnd()) {
} // Make sure the actual focused window is an owned window of this frame
AwtWindow *focusedWindow = (AwtWindow *)AwtComponent::GetComponent(sm_focusedWindow);
if (focusedWindow != NULL && focusedWindow->GetOwningFrameOrDialog() == this) {
// Check that the opposite window is not this frame, nor an owned window of this frame
if (activatedOpositeHWnd != NULL) {
AwtWindow *oppositeWindow = (AwtWindow *)AwtComponent::GetComponent(activatedOpositeHWnd);
if (oppositeWindow && oppositeWindow != this &&
oppositeWindow->GetOwningFrameOrDialog() != this)
{
m_actualFocusedWindow = focusedWindow;
} }
} else {
m_actualFocusedWindow = focusedWindow;
} }
type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS;
isAppActive = FALSE;
sm_focusedWindow = NULL;
} }
} }
}
if (doActivateFrame) { BOOL AwtFrame::AwtSetActiveWindow(BOOL isMouseEventCause, UINT hittest)
SendWindowEvent(type, opposite); {
if (hittest == HTCLIENT) {
// Don't let the actualFocusedWindow to steal focus if:
// a) the frame is clicked in its client area;
// b) focus is requested to some of the frame's child.
m_actualFocusedWindow = NULL;
} }
return mrConsume; return AwtWindow::AwtSetActiveWindow(isMouseEventCause);
} }
MsgRouting AwtFrame::WmEnterMenuLoop(BOOL isTrackPopupMenu) MsgRouting AwtFrame::WmEnterMenuLoop(BOOL isTrackPopupMenu)
...@@ -1169,60 +1196,6 @@ LRESULT AwtFrame::WinThreadExecProc(ExecuteArgs * args) ...@@ -1169,60 +1196,6 @@ LRESULT AwtFrame::WinThreadExecProc(ExecuteArgs * args)
return 0L; return 0L;
} }
/*
* hWndLostFocus - the opposite component
* Returns TRUE if WM_SETFOCUS may be processed further, otherwise FALSE.
*/
BOOL AwtFrame::activateEmbeddedFrameOnSetFocus(HWND hWndLostFocus) {
// If the EmbeddedFrame is not yet active, then this is either:
// - requesting focus on smth in the EmbeddedFrame, or
// - Alt hitting in IE while its menu is active (see 6374321).
// In both these cases we get WM_SETFOCUS without WM_ACTIVATE
// on the EmbeddedFrame.
if (sm_focusedWindow != GetHWnd()) {
HWND oppositeToplevelHWnd = AwtComponent::GetTopLevelParentForWindow(hWndLostFocus);
// As we get WM_SETFOCUS from the native system we expect
// the native toplevel be set to the active window.
HWND activeWindowHWnd = ::GetActiveWindow();
DASSERT(activeWindowHWnd == ::GetAncestor(GetHWnd(), GA_ROOT));
// See 6538154.
::BringWindowToTop(activeWindowHWnd);
::SetForegroundWindow(activeWindowHWnd);
SynthesizeWmActivate(TRUE, oppositeToplevelHWnd);
return FALSE;
}
// If the EmbeddedFrame is already active, then this is a mouse click
// or activation (by Alt-Tab, start etc).
return TRUE;
}
/*
* hWndGotFocus - the opposite component
* Returns TRUE if WM_KILLFOCUS may be processed further, otherwise FALSE.
*/
BOOL AwtFrame::deactivateEmbeddedFrameOnKillFocus(HWND hWndGotFocus) {
HWND oppositeToplevelHWnd = AwtComponent::GetTopLevelParentForWindow(hWndGotFocus);
if (oppositeToplevelHWnd != sm_focusedWindow) {
SynthesizeWmActivate(FALSE, oppositeToplevelHWnd);
}
return TRUE;
}
/*
* Execute on Toolkit only.
*/
void AwtFrame::SynthesizeWmActivate(BOOL doActivate, HWND opposite) {
if (::IsWindowVisible(GetHWnd())) {
::SendMessage(GetHWnd(), WM_ACTIVATE, MAKEWPARAM(doActivate ? WA_ACTIVE : WA_INACTIVE, FALSE), (LPARAM) opposite);
}
}
void AwtFrame::_SynthesizeWmActivate(void *param) void AwtFrame::_SynthesizeWmActivate(void *param)
{ {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
...@@ -1237,7 +1210,7 @@ void AwtFrame::_SynthesizeWmActivate(void *param) ...@@ -1237,7 +1210,7 @@ void AwtFrame::_SynthesizeWmActivate(void *param)
JNI_CHECK_PEER_GOTO(self, ret); JNI_CHECK_PEER_GOTO(self, ret);
frame = (AwtFrame *)pData; frame = (AwtFrame *)pData;
frame->SynthesizeWmActivate(doActivate, NULL); SynthesizeWmActivate(doActivate, frame->GetHWnd(), NULL);
ret: ret:
env->DeleteGlobalRef(self); env->DeleteGlobalRef(self);
......
/* /*
* Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -133,11 +133,6 @@ public: ...@@ -133,11 +133,6 @@ public:
// adjusts the IME candidate window position if needed // adjusts the IME candidate window position if needed
void AdjustCandidateWindowPos(); void AdjustCandidateWindowPos();
void SynthesizeWmActivate(BOOL doActivate, HWND opposite);
BOOL activateEmbeddedFrameOnSetFocus(HWND hWndLostFocus);
BOOL deactivateEmbeddedFrameOnKillFocus(HWND hWndGotFocus);
// invoked on Toolkit thread // invoked on Toolkit thread
static jobject _GetBoundsPrivate(void *param); static jobject _GetBoundsPrivate(void *param);
...@@ -153,6 +148,14 @@ public: ...@@ -153,6 +148,14 @@ public:
virtual void Reshape(int x, int y, int width, int height); virtual void Reshape(int x, int y, int width, int height);
virtual BOOL AwtSetActiveWindow(BOOL isMouseEventCause = FALSE, UINT hittest = HTCLIENT);
void CheckRetainActualFocusedWindow(HWND activatedOpositeHWnd);
BOOL CheckActivateActualFocusedWindow(HWND deactivatedOpositeHWnd);
INLINE HWND GetLastProxiedFocusOwner() { return m_lastProxiedFocusOwner; }
INLINE void SetLastProxiedFocusOwner(HWND hwnd) { m_lastProxiedFocusOwner = hwnd; }
protected: protected:
/* The frame is undecorated. */ /* The frame is undecorated. */
BOOL m_isUndecorated; BOOL m_isUndecorated;
...@@ -189,6 +192,10 @@ private: ...@@ -189,6 +192,10 @@ private:
or an AwtDialog (or one of its children) has the logical input focus. */ or an AwtDialog (or one of its children) has the logical input focus. */
HWND m_proxyFocusOwner; HWND m_proxyFocusOwner;
/* Retains the last/current sm_focusOwner proxied. Actually, it should be
* a component of an owned window last/currently active. */
HWND m_lastProxiedFocusOwner;
/* /*
* Fix for 4823903. * Fix for 4823903.
* Retains a focus proxied window to set the focus correctly * Retains a focus proxied window to set the focus correctly
......
/* /*
* Copyright 2000-2004 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -24,30 +24,20 @@ ...@@ -24,30 +24,20 @@
*/ */
#include "awt.h" #include "awt.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Component.h" #include "awt_Component.h"
#include "awt_Toolkit.h" #include "awt_Toolkit.h"
#include <java_awt_KeyboardFocusManager.h> #include <java_awt_KeyboardFocusManager.h>
#include <jni.h>
jclass AwtKeyboardFocusManager::keyboardFocusManagerCls;
jmethodID AwtKeyboardFocusManager::shouldNativelyFocusHeavyweightMID;
jmethodID AwtKeyboardFocusManager::heavyweightButtonDownMID;
jmethodID AwtKeyboardFocusManager::markClearGlobalFocusOwnerMID;
jmethodID AwtKeyboardFocusManager::removeLastFocusRequestMID;
jfieldID AwtKeyboardFocusManager::isProxyActive;
jmethodID AwtKeyboardFocusManager::processSynchronousTransfer;
static jobject getNativeFocusState(JNIEnv *env, void*(*ftn)()) { static jobject getNativeFocusState(JNIEnv *env, void*(*ftn)()) {
jobject lFocusState = NULL; jobject gFocusState = (jobject)AwtToolkit::GetInstance().SyncCall(ftn);
jobject gFocusState = reinterpret_cast<jobject>(AwtToolkit::GetInstance().
InvokeFunction(ftn));
if (gFocusState != NULL) { if (gFocusState != NULL) {
lFocusState = env->NewLocalRef(gFocusState); jobject lFocusState = env->NewLocalRef(gFocusState);
env->DeleteGlobalRef(gFocusState); env->DeleteGlobalRef(gFocusState);
return lFocusState;
} }
return NULL;
return lFocusState;
} }
extern "C" { extern "C" {
...@@ -61,53 +51,35 @@ JNIEXPORT void JNICALL ...@@ -61,53 +51,35 @@ JNIEXPORT void JNICALL
Java_java_awt_KeyboardFocusManager_initIDs Java_java_awt_KeyboardFocusManager_initIDs
(JNIEnv *env, jclass cls) (JNIEnv *env, jclass cls)
{ {
TRY; }
AwtKeyboardFocusManager::keyboardFocusManagerCls = (jclass)
env->NewGlobalRef(cls);
AwtKeyboardFocusManager::shouldNativelyFocusHeavyweightMID =
env->GetStaticMethodID(cls, "shouldNativelyFocusHeavyweight",
"(Ljava/awt/Component;Ljava/awt/Component;ZZJLsun/awt/CausedFocusEvent$Cause;)I");
AwtKeyboardFocusManager::heavyweightButtonDownMID =
env->GetStaticMethodID(cls, "heavyweightButtonDown",
"(Ljava/awt/Component;J)V");
AwtKeyboardFocusManager::markClearGlobalFocusOwnerMID =
env->GetStaticMethodID(cls, "markClearGlobalFocusOwner",
"()Ljava/awt/Window;");
AwtKeyboardFocusManager::removeLastFocusRequestMID =
env->GetStaticMethodID(cls, "removeLastFocusRequest",
"(Ljava/awt/Component;)V");
AwtKeyboardFocusManager::processSynchronousTransfer =
env->GetStaticMethodID(cls, "processSynchronousLightweightTransfer",
"(Ljava/awt/Component;Ljava/awt/Component;ZZJ)Z");
jclass keyclass = env->FindClass("java/awt/event/KeyEvent"); /*
DASSERT (keyclass != NULL); * Class: sun_awt_windows_WKeyboardFocusManagerPeer
* Method: setNativeFocusOwner
* Signature: (Lsun/awt/windows/WComponentPeer)
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WKeyboardFocusManagerPeer_setNativeFocusOwner
(JNIEnv *env, jclass cls, jobject compPeer)
{
TRY;
AwtKeyboardFocusManager::isProxyActive = jobject peerGlobalRef = env->NewGlobalRef(compPeer);
env->GetFieldID(keyclass, "isProxyActive", "Z");
env->DeleteLocalRef(keyclass); AwtToolkit::GetInstance().SyncCall(AwtComponent::SetNativeFocusOwner,
(void*)peerGlobalRef);
// peerGlobalRef is deleted in SetNativeFocusOwner
DASSERT(AwtKeyboardFocusManager::keyboardFocusManagerCls != NULL);
DASSERT(AwtKeyboardFocusManager::shouldNativelyFocusHeavyweightMID !=
NULL);
DASSERT(AwtKeyboardFocusManager::heavyweightButtonDownMID != NULL);
DASSERT(AwtKeyboardFocusManager::markClearGlobalFocusOwnerMID != NULL);
DASSERT(AwtKeyboardFocusManager::removeLastFocusRequestMID != NULL);
DASSERT(AwtKeyboardFocusManager::processSynchronousTransfer != NULL);
CATCH_BAD_ALLOC; CATCH_BAD_ALLOC;
} }
/* /*
* Class: sun_awt_KeyboardFocusManagerPeerImpl * Class: sun_awt_windows_WKeyboardFocusManagerPeer
* Method: getNativeFocusOwner * Method: getNativeFocusOwner
* Signature: ()Ljava/awt/Component; * Signature: (Lsun/awt/windows/WComponentPeer)
*/ */
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_sun_awt_KeyboardFocusManagerPeerImpl_getNativeFocusOwner Java_sun_awt_windows_WKeyboardFocusManagerPeer_getNativeFocusOwner
(JNIEnv *env, jclass cls) (JNIEnv *env, jclass cls)
{ {
TRY; TRY;
...@@ -118,12 +90,12 @@ Java_sun_awt_KeyboardFocusManagerPeerImpl_getNativeFocusOwner ...@@ -118,12 +90,12 @@ Java_sun_awt_KeyboardFocusManagerPeerImpl_getNativeFocusOwner
} }
/* /*
* Class: sun_awt_KeyboardFocusManagerPeerImpl * Class: sun_awt_windows_WKeyboardFocusManagerPeer
* Method: getNativeFocusedWindow * Method: getNativeFocusedWindow
* Signature: ()Ljava/awt/Window; * Signature: ()Ljava/awt/Window;
*/ */
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_sun_awt_KeyboardFocusManagerPeerImpl_getNativeFocusedWindow Java_sun_awt_windows_WKeyboardFocusManagerPeer_getNativeFocusedWindow
(JNIEnv *env, jclass cls) (JNIEnv *env, jclass cls)
{ {
TRY; TRY;
...@@ -132,21 +104,4 @@ Java_sun_awt_KeyboardFocusManagerPeerImpl_getNativeFocusedWindow ...@@ -132,21 +104,4 @@ Java_sun_awt_KeyboardFocusManagerPeerImpl_getNativeFocusedWindow
CATCH_BAD_ALLOC_RET(NULL); CATCH_BAD_ALLOC_RET(NULL);
} }
/*
* Class: sun_awt_KeyboardFocusManagerPeerImpl
* Method: clearNativeGlobalFocusOwner
* Signature: (Ljava/awt/Window;)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_KeyboardFocusManagerPeerImpl_clearNativeGlobalFocusOwner
(JNIEnv *env, jobject self, jobject activeWindow)
{
TRY;
AwtToolkit::GetInstance().InvokeFunction
((void*(*)(void))AwtComponent::ClearGlobalFocusOwner);
CATCH_BAD_ALLOC;
}
} }
/* /*
* Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
*/ */
#include "awt_List.h" #include "awt_List.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Canvas.h" #include "awt_Canvas.h"
#include "awt_Dimension.h" #include "awt_Dimension.h"
#include "awt_Toolkit.h" #include "awt_Toolkit.h"
...@@ -154,28 +153,6 @@ done: ...@@ -154,28 +153,6 @@ done:
return c; return c;
} }
BOOL AwtList::ActMouseMessage(MSG * pMsg) {
if (!IsFocusingMessage(pMsg->message)) {
return FALSE;
}
if (pMsg->message == WM_LBUTTONDOWN) {
LONG item = static_cast<LONG>(SendListMessage(LB_ITEMFROMPOINT, 0, pMsg->lParam));
if (item != LB_ERR) {
if (isMultiSelect) {
if (IsItemSelected(item)) {
Deselect(item);
} else {
Select(item);
}
} else {
Select(item);
}
}
}
return TRUE;
}
void AwtList::SetDragCapture(UINT flags) void AwtList::SetDragCapture(UINT flags)
{ {
// don't want to interfere with other controls // don't want to interfere with other controls
...@@ -473,17 +450,11 @@ AwtList::WmMouseDown(UINT flags, int x, int y, int button) ...@@ -473,17 +450,11 @@ AwtList::WmMouseDown(UINT flags, int x, int y, int button)
} }
/* /*
* Fix for 6240202. List being inside a non-focusable Window (or non-focusable List * As we consume WM_LBUTONDOWN the list won't trigger ActionEvent by double click.
* being a single component inside a focusable Window) won't trigger ActionEvent by * We trigger it ourselves. (see also 6240202)
* double click. All focus events will be filtered (in the AWT focus hook) for such
* a Window containing the List. In such a case OS Windows won't generate WM_COMMAND
* (and no WmNotify() will be called for the List). Here we call WmCommand()
* synthetically.
*/ */
int clickCount = GetClickCount(); int clickCount = GetClickCount();
if (button == LEFT_BUTTON && clickCount >= 2 && clickCount % 2 == 0 && if (button == LEFT_BUTTON && clickCount >= 2 && clickCount % 2 == 0) {
!GetContainer()->IsFocusableWindow())
{
WmCommand(0, GetListHandle(), LBN_DBLCLK); WmCommand(0, GetListHandle(), LBN_DBLCLK);
} }
return mrResult; return mrResult;
...@@ -500,67 +471,32 @@ AwtList::WmCtlColor(HDC hDC, HWND hCtrl, UINT ctlColor, HBRUSH& retBrush) ...@@ -500,67 +471,32 @@ AwtList::WmCtlColor(HDC hDC, HWND hCtrl, UINT ctlColor, HBRUSH& retBrush)
return mrConsume; return mrConsume;
} }
// Override WmSetFocus and WmKillFocus so that they operate on the List handle BOOL AwtList::IsFocusingMouseMessage(MSG *pMsg)
// instead of the wrapper handle. Otherwise, the methods are the same as their {
// AwtComponent counterparts. return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK;
MsgRouting AwtList::WmSetFocus(HWND hWndLostFocus) {
if (sm_focusOwner == GetListHandle()) {
sm_realFocusOpposite = NULL;
return mrConsume;
}
sm_focusOwner = GetListHandle();
if (sm_realFocusOpposite != NULL) {
hWndLostFocus = sm_realFocusOpposite;
sm_realFocusOpposite = NULL;
}
SendFocusEvent(java_awt_event_FocusEvent_FOCUS_GAINED, hWndLostFocus);
return mrDoDefault;
} }
MsgRouting AwtList::WmKillFocus(HWND hWndGotFocus) { MsgRouting AwtList::HandleEvent(MSG *msg, BOOL synthetic)
if (sm_focusOwner != NULL && sm_focusOwner == hWndGotFocus) { {
return mrConsume; if (IsFocusingMouseMessage(msg)) {
} LONG item = static_cast<LONG>(SendListMessage(LB_ITEMFROMPOINT, 0, msg->lParam));
if (item != LB_ERR) {
if (sm_focusOwner != GetListHandle()) { if (isMultiSelect) {
if (sm_focusOwner != NULL) { if (IsItemSelected(item)) {
if (hWndGotFocus != NULL && Deselect(item);
AwtComponent::GetComponent(hWndGotFocus) != NULL) } else {
{ Select(item);
sm_realFocusOpposite = sm_focusOwner;
} }
::SendMessage(sm_focusOwner, WM_KILLFOCUS, (WPARAM)hWndGotFocus, } else {
0); Select(item);
}
} }
delete msg;
return mrConsume; return mrConsume;
} }
if (msg->message == WM_KEYDOWN && msg->wParam == VK_RETURN) {
sm_focusOwner = NULL; WmNotify(LBN_DBLCLK);
SendFocusEvent(java_awt_event_FocusEvent_FOCUS_LOST, hWndGotFocus);
return mrDoDefault;
}
MsgRouting AwtList::HandleEvent(MSG *msg, BOOL synthetic)
{
if (AwtComponent::sm_focusOwner != GetListHandle() &&
(msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK))
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject target = GetTarget(env);
env->CallStaticVoidMethod
(AwtKeyboardFocusManager::keyboardFocusManagerCls,
AwtKeyboardFocusManager::heavyweightButtonDownMID,
target, ((jlong)msg->time) & 0xFFFFFFFF);
env->DeleteLocalRef(target);
} }
return AwtComponent::HandleEvent(msg, synthetic); return AwtComponent::HandleEvent(msg, synthetic);
} }
...@@ -607,15 +543,6 @@ AwtList::WmNotify(UINT notifyCode) ...@@ -607,15 +543,6 @@ AwtList::WmNotify(UINT notifyCode)
return mrDoDefault; return mrDoDefault;
} }
MsgRouting
AwtList::WmKeyDown(UINT wkey, UINT repCnt, UINT flags, BOOL system)
{
if (wkey == VK_RETURN) {
WmNotify(LBN_DBLCLK);
}
return AwtComponent::WmKeyDown(wkey, repCnt, flags, system);
}
BOOL AwtList::InheritsNativeMouseWheelBehavior() {return true;} BOOL AwtList::InheritsNativeMouseWheelBehavior() {return true;}
jint AwtList::_GetMaxWidth(void *param) jint AwtList::_GetMaxWidth(void *param)
......
/* /*
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -97,8 +97,6 @@ public: ...@@ -97,8 +97,6 @@ public:
} }
} }
BOOL ActMouseMessage(MSG* pMsg);
// Netscape : Change the font on the list and redraw the // Netscape : Change the font on the list and redraw the
// items nicely. // items nicely.
virtual void SetFont(AwtFont *pFont); virtual void SetFont(AwtFont *pFont);
...@@ -116,7 +114,6 @@ public: ...@@ -116,7 +114,6 @@ public:
MsgRouting WmMouseDown(UINT flags, int x, int y, int button); MsgRouting WmMouseDown(UINT flags, int x, int y, int button);
MsgRouting WmMouseUp(UINT flags, int x, int y, int button); MsgRouting WmMouseUp(UINT flags, int x, int y, int button);
MsgRouting WmNotify(UINT notifyCode); MsgRouting WmNotify(UINT notifyCode);
MsgRouting WmKeyDown(UINT vkey, UINT repCnt, UINT flags, BOOL system);
/* for multifont list */ /* for multifont list */
MsgRouting OwnerDrawItem(UINT ctrlId, DRAWITEMSTRUCT& drawInfo); MsgRouting OwnerDrawItem(UINT ctrlId, DRAWITEMSTRUCT& drawInfo);
...@@ -127,8 +124,6 @@ public: ...@@ -127,8 +124,6 @@ public:
MsgRouting WmCtlColor(HDC hDC, HWND hCtrl, UINT ctlColor, MsgRouting WmCtlColor(HDC hDC, HWND hCtrl, UINT ctlColor,
HBRUSH& retBrush); HBRUSH& retBrush);
MsgRouting WmSetFocus(HWND hWndLostFocus);
MsgRouting WmKillFocus(HWND hWndGotFocus);
MsgRouting HandleEvent(MSG *msg, BOOL synthetic); MsgRouting HandleEvent(MSG *msg, BOOL synthetic);
...@@ -170,6 +165,8 @@ public: ...@@ -170,6 +165,8 @@ public:
virtual BOOL InheritsNativeMouseWheelBehavior(); virtual BOOL InheritsNativeMouseWheelBehavior();
virtual BOOL IsFocusingMouseMessage(MSG *pMsg);
// some methods called on Toolkit thread // some methods called on Toolkit thread
static jint _GetMaxWidth(void *param); static jint _GetMaxWidth(void *param);
static void _UpdateMaxItemWidth(void *param); static void _UpdateMaxItemWidth(void *param);
......
...@@ -88,7 +88,7 @@ PrintDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) ...@@ -88,7 +88,7 @@ PrintDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
DWORD style = ::GetClassLong(hdlg, GCL_STYLE); DWORD style = ::GetClassLong(hdlg, GCL_STYLE);
::SetClassLong(hdlg,GCL_STYLE, style & ~CS_SAVEBITS); ::SetClassLong(hdlg,GCL_STYLE, style & ~CS_SAVEBITS);
::SetFocus(hdlg); ::SetFocus(hdlg); // will not break synthetic focus as hdlg is a native toplevel
// set appropriate icon for parentless dialogs // set appropriate icon for parentless dialogs
jobject awtParent = env->GetObjectField(peer, AwtPrintDialog::parentID); jobject awtParent = env->GetObjectField(peer, AwtPrintDialog::parentID);
......
/* /*
* Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -361,13 +361,6 @@ void AwtScrollPane::PostScrollEvent(int orient, int scrollCode, int pos) { ...@@ -361,13 +361,6 @@ void AwtScrollPane::PostScrollEvent(int orient, int scrollCode, int pos) {
DASSERT(!safe_ExceptionOccurred(env)); DASSERT(!safe_ExceptionOccurred(env));
} }
BOOL AwtScrollPane::ActMouseMessage(MSG* pMsg) {
if (!IsFocusingMessage(pMsg->message)) {
return FALSE;
}
return TRUE;
}
MsgRouting MsgRouting
AwtScrollPane::WmNcHitTest(UINT x, UINT y, LRESULT& retVal) AwtScrollPane::WmNcHitTest(UINT x, UINT y, LRESULT& retVal)
{ {
...@@ -412,13 +405,10 @@ MsgRouting AwtScrollPane::WmHScroll(UINT scrollCode, UINT pos, HWND hScrollPane) ...@@ -412,13 +405,10 @@ MsgRouting AwtScrollPane::WmHScroll(UINT scrollCode, UINT pos, HWND hScrollPane)
return mrConsume; return mrConsume;
} }
/*
* Fix for BugTraq ID 4041703: keyDown not being invoked.
* This method overrides AwtCanvas::HandleEvent() since we
* don't want ScrollPanel to receive focus on mouse press.
*/
MsgRouting AwtScrollPane::HandleEvent(MSG *msg, BOOL synthetic) MsgRouting AwtScrollPane::HandleEvent(MSG *msg, BOOL synthetic)
{ {
// SunAwtScrollPane control doesn't cause activation on mouse/key events,
// so we can safely (for synthetic focus) pass them to the system proc.
return AwtComponent::HandleEvent(msg, synthetic); return AwtComponent::HandleEvent(msg, synthetic);
} }
......
/* /*
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -65,7 +65,6 @@ public: ...@@ -65,7 +65,6 @@ public:
virtual void Reshape(int x, int y, int w, int h); virtual void Reshape(int x, int y, int w, int h);
virtual void BeginValidate() {} virtual void BeginValidate() {}
virtual void EndValidate() {} virtual void EndValidate() {}
BOOL ActMouseMessage(MSG* pMsg);
/* /*
* Fix for bug 4046446 * Fix for bug 4046446
......
/* /*
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include "awt_Scrollbar.h" #include "awt_Scrollbar.h"
#include "awt_Canvas.h" #include "awt_Canvas.h"
#include "awt_Window.h" #include "awt_Window.h"
#include "awt_KeyboardFocusManager.h"
/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
*/ */
...@@ -61,7 +60,6 @@ AwtScrollbar::AwtScrollbar() { ...@@ -61,7 +60,6 @@ AwtScrollbar::AwtScrollbar() {
m_orientation = SB_HORZ; m_orientation = SB_HORZ;
m_lineIncr = 0; m_lineIncr = 0;
m_pageIncr = 0; m_pageIncr = 0;
m_ignoreFocusEvents = FALSE;
m_prevCallback = NULL; m_prevCallback = NULL;
m_prevCallbackPos = 0; m_prevCallbackPos = 0;
ms_instanceCounter++; ms_instanceCounter++;
...@@ -221,7 +219,6 @@ AwtScrollbar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) ...@@ -221,7 +219,6 @@ AwtScrollbar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
return retValue; return retValue;
} }
MsgRouting MsgRouting
AwtScrollbar::WmNcHitTest(UINT x, UINT y, LRESULT& retVal) AwtScrollbar::WmNcHitTest(UINT x, UINT y, LRESULT& retVal)
{ {
...@@ -265,17 +262,10 @@ AwtScrollbar::WmMouseDown(UINT flags, int x, int y, int button) ...@@ -265,17 +262,10 @@ AwtScrollbar::WmMouseDown(UINT flags, int x, int y, int button)
MsgRouting MsgRouting
AwtScrollbar::HandleEvent(MSG *msg, BOOL synthetic) AwtScrollbar::HandleEvent(MSG *msg, BOOL synthetic)
{ {
if (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) { // SCROLLBAR control doesn't cause activation on mouse/key events,
if (IsFocusable() && AwtComponent::sm_focusOwner != GetHWnd()) { // so we can safely (for synthetic focus) pass them to the system proc.
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject target = GetTarget(env); if (IsFocusingMouseMessage(msg)) {
env->CallStaticVoidMethod
(AwtKeyboardFocusManager::keyboardFocusManagerCls,
AwtKeyboardFocusManager::heavyweightButtonDownMID,
target, ((jlong)msg->time) & 0xFFFFFFFF);
env->DeleteLocalRef(target);
AwtSetFocus();
}
// Left button press was already routed to default window // Left button press was already routed to default window
// procedure in the WmMouseDown above. Propagating synthetic // procedure in the WmMouseDown above. Propagating synthetic
// press seems like a bad idea as internal message loop // press seems like a bad idea as internal message loop
...@@ -283,54 +273,19 @@ AwtScrollbar::HandleEvent(MSG *msg, BOOL synthetic) ...@@ -283,54 +273,19 @@ AwtScrollbar::HandleEvent(MSG *msg, BOOL synthetic)
delete msg; delete msg;
return mrConsume; return mrConsume;
} }
else { return AwtComponent::HandleEvent(msg, synthetic);
return AwtComponent::HandleEvent(msg, synthetic);
}
} }
// Work around a windows bug descrbed in KB article Q73839. Reset // Work around a windows bug descrbed in KB article Q73839. Reset
// focus on scrollbars to update focus indicator. The article advises // focus on scrollbars to update focus indicator. The article advises
// to disable/enable the scrollbar, but simply resetting the focus is // to disable/enable the scrollbar.
// sufficient.
void void
AwtScrollbar::UpdateFocusIndicator() AwtScrollbar::UpdateFocusIndicator()
{ {
if (IsFocusable()) { if (IsFocusable()) {
m_ignoreFocusEvents = TRUE; // todo: doesn't work
::SetFocus(NULL); SendMessage((WPARAM)ESB_DISABLE_BOTH);
AwtSetFocus(); SendMessage((WPARAM)ESB_ENABLE_BOTH);
m_ignoreFocusEvents = FALSE;
}
}
MsgRouting
AwtScrollbar::WmKillFocus(HWND hWndGot)
{
if (m_ignoreFocusEvents) {
// We are voluntary giving up focus and will get it back
// immediately. This is necessary to force windows to update
// the focus indicator.
sm_focusOwner = NULL;
return mrDoDefault;
}
else {
return AwtComponent::WmKillFocus(hWndGot);
}
}
MsgRouting
AwtScrollbar::WmSetFocus(HWND hWndLost)
{
if (m_ignoreFocusEvents) {
// We have voluntary gave up focus and are getting it back
// now. This is necessary to force windows to update the
// focus indicator.
sm_focusOwner = GetHWnd();
return mrDoDefault;
}
else {
return AwtComponent::WmSetFocus(hWndLost);
} }
} }
......
/* /*
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -69,10 +69,6 @@ public: ...@@ -69,10 +69,6 @@ public:
virtual MsgRouting WmHScroll(UINT scrollCode, UINT pos, HWND hScrollBar); virtual MsgRouting WmHScroll(UINT scrollCode, UINT pos, HWND hScrollBar);
virtual MsgRouting WmVScroll(UINT scrollCode, UINT pos, HWND hScrollBar); virtual MsgRouting WmVScroll(UINT scrollCode, UINT pos, HWND hScrollBar);
// Work around KB Q73839 bug.
virtual MsgRouting WmSetFocus(HWND hWndLost);
virtual MsgRouting WmKillFocus(HWND hWndGot);
// Prevent KB Q102552 race. // Prevent KB Q102552 race.
virtual MsgRouting WmMouseDown(UINT flags, int x, int y, int button); virtual MsgRouting WmMouseDown(UINT flags, int x, int y, int button);
virtual MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT& retVal); virtual MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT& retVal);
...@@ -91,7 +87,6 @@ private: ...@@ -91,7 +87,6 @@ private:
int m_pageIncr; int m_pageIncr;
// Work around KB Q73839 bug. // Work around KB Q73839 bug.
BOOL m_ignoreFocusEvents;
void UpdateFocusIndicator(); void UpdateFocusIndicator();
// Don't do redundant callbacks. // Don't do redundant callbacks.
......
/* /*
* Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -26,9 +26,9 @@ ...@@ -26,9 +26,9 @@
#include "awt_Toolkit.h" #include "awt_Toolkit.h"
#include "awt_TextArea.h" #include "awt_TextArea.h"
#include "awt_TextComponent.h" #include "awt_TextComponent.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Canvas.h" #include "awt_Canvas.h"
#include "awt_Window.h" #include "awt_Window.h"
#include "awt_Frame.h"
/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
*/ */
...@@ -362,13 +362,6 @@ AwtTextArea::EditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { ...@@ -362,13 +362,6 @@ AwtTextArea::EditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
DASSERT(::IsWindow(::GetParent(hWnd))); DASSERT(::IsWindow(::GetParent(hWnd)));
switch (message) { switch (message) {
case WM_SETFOCUS:
::SendMessage(::GetParent(hWnd), EM_HIDESELECTION, FALSE, 0);
break;
case WM_KILLFOCUS:
::SendMessage(::GetParent(hWnd), EM_HIDESELECTION, TRUE, 0);
break;
case WM_UNDO: case WM_UNDO:
case WM_CUT: case WM_CUT:
case WM_COPY: case WM_COPY:
...@@ -400,7 +393,6 @@ AwtTextArea::EditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { ...@@ -400,7 +393,6 @@ AwtTextArea::EditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
MsgRouting MsgRouting
AwtTextArea::WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos) { AwtTextArea::WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos) {
/* Use the system provided edit control class to generate context menu. */ /* Use the system provided edit control class to generate context menu. */
if (m_hEditCtrl == NULL) { if (m_hEditCtrl == NULL) {
DWORD dwStyle = WS_CHILD; DWORD dwStyle = WS_CHILD;
...@@ -494,22 +486,11 @@ AwtTextArea::WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos) { ...@@ -494,22 +486,11 @@ AwtTextArea::WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos) {
VERIFY(::ClientToScreen(GetHWnd(), &p)); VERIFY(::ClientToScreen(GetHWnd(), &p));
} }
::SendMessage(m_hEditCtrl, WM_CONTEXTMENU, (WPARAM)m_hEditCtrl, // The context menu steals focus from the proxy.
MAKELPARAM(p.x, p.y)); // So, set the focus-restore flag up.
/* SetRestoreFocus(TRUE);
* After the context menu is dismissed focus is owned by the edit contol. ::SendMessage(m_hEditCtrl, WM_CONTEXTMENU, (WPARAM)m_hEditCtrl, MAKELPARAM(p.x, p.y));
* Return focus to parent. SetRestoreFocus(FALSE);
*/
if (IsFocusable() && AwtComponent::sm_focusOwner != GetHWnd()) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject target = GetTarget(env);
env->CallStaticVoidMethod
(AwtKeyboardFocusManager::keyboardFocusManagerCls,
AwtKeyboardFocusManager::heavyweightButtonDownMID,
target, TimeHelper::getMessageTimeUTC());
env->DeleteLocalRef(target);
AwtSetFocus();
}
return mrConsume; return mrConsume;
} }
...@@ -558,20 +539,11 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic) ...@@ -558,20 +539,11 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic)
* By consuming WM_MOUSEMOVE messages we also don't give * By consuming WM_MOUSEMOVE messages we also don't give
* the RichEdit control a chance to recognize a drag gesture * the RichEdit control a chance to recognize a drag gesture
* and initiate its own drag-n-drop operation. * and initiate its own drag-n-drop operation.
*
* The workaround also allows us to implement synthetic focus mechanism.
*
*/ */
if (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) { if (IsFocusingMouseMessage(msg)) {
if (IsFocusable() && AwtComponent::sm_focusOwner != GetHWnd()) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject target = GetTarget(env);
env->CallStaticVoidMethod
(AwtKeyboardFocusManager::keyboardFocusManagerCls,
AwtKeyboardFocusManager::heavyweightButtonDownMID,
target, ((jlong)msg->time) & 0xFFFFFFFF);
env->DeleteLocalRef(target);
AwtSetFocus();
}
CHARRANGE cr; CHARRANGE cr;
LONG lCurPos = EditGetCharFromPos(msg->pt); LONG lCurPos = EditGetCharFromPos(msg->pt);
...@@ -717,6 +689,7 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic) ...@@ -717,6 +689,7 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic)
p.x = -1; p.x = -1;
p.y = -1; p.y = -1;
} }
if (!::PostMessage(GetHWnd(), WM_CONTEXTMENU, (WPARAM)GetHWnd(), if (!::PostMessage(GetHWnd(), WM_CONTEXTMENU, (WPARAM)GetHWnd(),
MAKELPARAM(p.x, p.y))) { MAKELPARAM(p.x, p.y))) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
...@@ -724,6 +697,8 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic) ...@@ -724,6 +697,8 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic)
env->ExceptionDescribe(); env->ExceptionDescribe();
env->ExceptionClear(); env->ExceptionClear();
} }
delete msg;
return mrConsume;
} else if (msg->message == WM_MOUSEWHEEL) { } else if (msg->message == WM_MOUSEWHEEL) {
// 4417236: If there is an old version of RichEd32.dll which // 4417236: If there is an old version of RichEd32.dll which
// does not provide the mouse wheel scrolling we have to // does not provide the mouse wheel scrolling we have to
......
/* /*
* Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "awt_Toolkit.h" #include "awt_Toolkit.h"
#include "awt_TextComponent.h" #include "awt_TextComponent.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Canvas.h" #include "awt_Canvas.h"
#include "jni.h" #include "jni.h"
...@@ -62,9 +61,9 @@ jfieldID AwtTextComponent::canAccessClipboardID; ...@@ -62,9 +61,9 @@ jfieldID AwtTextComponent::canAccessClipboardID;
AwtTextComponent::AwtTextComponent() { AwtTextComponent::AwtTextComponent() {
m_synthetic = FALSE; m_synthetic = FALSE;
m_lStartPos = -1; m_lStartPos = -1;
m_lEndPos = -1; m_lEndPos = -1;
m_lLastPos = -1; m_lLastPos = -1;
m_isLFonly = FALSE; m_isLFonly = FALSE;
m_EOLchecked = FALSE; m_EOLchecked = FALSE;
// javaEventsMask = 0; // accessibility support // javaEventsMask = 0; // accessibility support
...@@ -74,10 +73,6 @@ LPCTSTR AwtTextComponent::GetClassName() { ...@@ -74,10 +73,6 @@ LPCTSTR AwtTextComponent::GetClassName() {
return TEXT("EDIT"); /* System provided edit control class */ return TEXT("EDIT"); /* System provided edit control class */
} }
BOOL AwtTextComponent::ActMouseMessage(MSG* pMsg) {
return FALSE;
}
/* Set a suitable font to IME against the component font. */ /* Set a suitable font to IME against the component font. */
void AwtTextComponent::SetFont(AwtFont* font) void AwtTextComponent::SetFont(AwtFont* font)
{ {
...@@ -143,23 +138,16 @@ AwtTextComponent::WmNotify(UINT notifyCode) ...@@ -143,23 +138,16 @@ AwtTextComponent::WmNotify(UINT notifyCode)
return mrDoDefault; return mrDoDefault;
} }
BOOL AwtTextComponent::IsFocusingMouseMessage(MSG *pMsg)
{
return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK;
}
MsgRouting MsgRouting
AwtTextComponent::HandleEvent(MSG *msg, BOOL synthetic) AwtTextComponent::HandleEvent(MSG *msg, BOOL synthetic)
{ {
MsgRouting returnVal; MsgRouting returnVal;
if (AwtComponent::sm_focusOwner != GetHWnd() && IsFocusable() &&
(msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK))
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject target = GetTarget(env);
env->CallStaticVoidMethod
(AwtKeyboardFocusManager::keyboardFocusManagerCls,
AwtKeyboardFocusManager::heavyweightButtonDownMID,
target, ((jlong)msg->time) & 0xFFFFFFFF);
env->DeleteLocalRef(target);
}
/* /*
* Store the 'synthetic' parameter so that the WM_PASTE security check * Store the 'synthetic' parameter so that the WM_PASTE security check
* happens only for synthetic events. * happens only for synthetic events.
......
/* /*
* Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -69,8 +69,6 @@ public: ...@@ -69,8 +69,6 @@ public:
// called on Toolkit thread from JNI // called on Toolkit thread from JNI
static jstring _GetText(void *param); static jstring _GetText(void *param);
BOOL ActMouseMessage(MSG* pMsg);
void SetFont(AwtFont* font); void SetFont(AwtFont* font);
/* /*
...@@ -80,6 +78,8 @@ public: ...@@ -80,6 +78,8 @@ public:
MsgRouting HandleEvent(MSG *msg, BOOL synthetic); MsgRouting HandleEvent(MSG *msg, BOOL synthetic);
MsgRouting WmPaste(); MsgRouting WmPaste();
virtual BOOL IsFocusingMouseMessage(MSG *pMsg);
/* To be fully implemented in a future release /* To be fully implemented in a future release
MsgRouting WmKeyDown(UINT wkey, UINT repCnt, MsgRouting WmKeyDown(UINT wkey, UINT repCnt,
...@@ -125,7 +125,6 @@ private: ...@@ -125,7 +125,6 @@ private:
LONG m_lEndPos; LONG m_lEndPos;
LONG m_lLastPos; LONG m_lLastPos;
HFONT m_hFont; HFONT m_hFont;
//im --- end //im --- end
......
/* /*
* Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "awt_Toolkit.h" #include "awt_Toolkit.h"
#include "awt_TextField.h" #include "awt_TextField.h"
#include "awt_TextComponent.h" #include "awt_TextComponent.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Canvas.h" #include "awt_Canvas.h"
/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
...@@ -150,135 +149,130 @@ AwtTextField::HandleEvent(MSG *msg, BOOL synthetic) ...@@ -150,135 +149,130 @@ AwtTextField::HandleEvent(MSG *msg, BOOL synthetic)
* By consuming WM_MOUSEMOVE messages we also don't give * By consuming WM_MOUSEMOVE messages we also don't give
* the RichEdit control a chance to recognize a drag gesture * the RichEdit control a chance to recognize a drag gesture
* and initiate its own drag-n-drop operation. * and initiate its own drag-n-drop operation.
*
* The workaround also allows us to implement synthetic focus mechanism.
*/ */
/** if (IsFocusingMouseMessage(msg)) {
* In non-focusable mode we don't pass mouse messages to native window thus making user unable CHARRANGE cr;
* to select the text. Below is the code from awt_TextArea.cpp which implements selection
* functionality. For safety this code is only being executed in non-focusable mode. LONG lCurPos = EditGetCharFromPos(msg->pt);
*/
if (!IsFocusable()) { EditGetSel(cr);
if (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) { /*
* NOTE: Plain EDIT control always clears selection on mouse
* button press. We are clearing the current selection only if
* the mouse pointer is not over the selected region.
* In this case we sacrifice backward compatibility
* to allow dnd of the current selection.
*/
if (msg->message == WM_LBUTTONDBLCLK) {
SetStartSelectionPos(static_cast<LONG>(SendMessage(
EM_FINDWORDBREAK, WB_MOVEWORDLEFT, lCurPos)));
SetEndSelectionPos(static_cast<LONG>(SendMessage(
EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, lCurPos)));
} else {
SetStartSelectionPos(lCurPos);
SetEndSelectionPos(lCurPos);
}
cr.cpMin = GetStartSelectionPos();
cr.cpMax = GetEndSelectionPos();
EditSetSel(cr);
delete msg;
return mrConsume;
} else if (msg->message == WM_LBUTTONUP) {
/*
* If the left mouse button is pressed on the selected region
* we don't clear the current selection. We clear it on button
* release instead. This is to allow dnd of the current selection.
*/
if (GetStartSelectionPos() == -1 && GetEndSelectionPos() == -1) {
CHARRANGE cr; CHARRANGE cr;
LONG lCurPos = EditGetCharFromPos(msg->pt); LONG lCurPos = EditGetCharFromPos(msg->pt);
EditGetSel(cr); cr.cpMin = lCurPos;
/* cr.cpMax = lCurPos;
* NOTE: Plain EDIT control always clears selection on mouse
* button press. We are clearing the current selection only if
* the mouse pointer is not over the selected region.
* In this case we sacrifice backward compatibility
* to allow dnd of the current selection.
*/
if (msg->message == WM_LBUTTONDBLCLK) {
SetStartSelectionPos(static_cast<LONG>(SendMessage(
EM_FINDWORDBREAK, WB_MOVEWORDLEFT, lCurPos)));
SetEndSelectionPos(static_cast<LONG>(SendMessage(
EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, lCurPos)));
} else {
SetStartSelectionPos(lCurPos);
SetEndSelectionPos(lCurPos);
}
cr.cpMin = GetStartSelectionPos();
cr.cpMax = GetEndSelectionPos();
EditSetSel(cr); EditSetSel(cr);
}
delete msg; /*
return mrConsume; * Cleanup the state variables when left mouse button is released.
} else if (msg->message == WM_LBUTTONUP) { * These state variables are designed to reflect the selection state
* while the left mouse button is pressed and be set to -1 otherwise.
*/
SetStartSelectionPos(-1);
SetEndSelectionPos(-1);
SetLastSelectionPos(-1);
delete msg;
return mrConsume;
} else if (msg->message == WM_MOUSEMOVE && (msg->wParam & MK_LBUTTON)) {
/*
* We consume WM_MOUSEMOVE while the left mouse button is pressed,
* so we have to simulate autoscrolling when mouse is moved outside
* of the client area.
*/
POINT p;
RECT r;
BOOL bScrollLeft = FALSE;
BOOL bScrollRight = FALSE;
BOOL bScrollUp = FALSE;
BOOL bScrollDown = FALSE;
p.x = msg->pt.x;
p.y = msg->pt.y;
VERIFY(::GetClientRect(GetHWnd(), &r));
if (p.x < 0) {
bScrollLeft = TRUE;
p.x = 0;
} else if (p.x > r.right) {
bScrollRight = TRUE;
p.x = r.right - 1;
}
LONG lCurPos = EditGetCharFromPos(p);
/* if (GetStartSelectionPos() != -1 &&
* If the left mouse button is pressed on the selected region GetEndSelectionPos() != -1 &&
* we don't clear the current selection. We clear it on button lCurPos != GetLastSelectionPos()) {
* release instead. This is to allow dnd of the current selection.
*/
if (GetStartSelectionPos() == -1 && GetEndSelectionPos() == -1) {
CHARRANGE cr;
LONG lCurPos = EditGetCharFromPos(msg->pt); CHARRANGE cr;
cr.cpMin = lCurPos; SetLastSelectionPos(lCurPos);
cr.cpMax = lCurPos;
EditSetSel(cr);
}
/* cr.cpMin = GetStartSelectionPos();
* Cleanup the state variables when left mouse button is released. cr.cpMax = GetLastSelectionPos();
* These state variables are designed to reflect the selection state
* while the left mouse button is pressed and be set to -1 otherwise.
*/
SetStartSelectionPos(-1);
SetEndSelectionPos(-1);
SetLastSelectionPos(-1);
delete msg; EditSetSel(cr);
return mrConsume; }
} else if (msg->message == WM_MOUSEMOVE && (msg->wParam & MK_LBUTTON)) {
if (bScrollLeft == TRUE || bScrollRight == TRUE) {
SCROLLINFO si;
memset(&si, 0, sizeof(si));
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
VERIFY(::GetScrollInfo(GetHWnd(), SB_HORZ, &si));
if (bScrollLeft == TRUE) {
si.nPos = si.nPos - si.nPage / 2;
si.nPos = max(si.nMin, si.nPos);
} else if (bScrollRight == TRUE) {
si.nPos = si.nPos + si.nPage / 2;
si.nPos = min(si.nPos, si.nMax);
}
/* /*
* We consume WM_MOUSEMOVE while the left mouse button is pressed, * Okay to use 16-bit position since RichEdit control adjusts
* so we have to simulate autoscrolling when mouse is moved outside * its scrollbars so that their range is always 16-bit.
* of the client area.
*/ */
POINT p; DASSERT(abs(si.nPos) < 0x8000);
RECT r; SendMessage(WM_HSCROLL,
BOOL bScrollLeft = FALSE; MAKEWPARAM(SB_THUMBPOSITION, LOWORD(si.nPos)));
BOOL bScrollRight = FALSE;
BOOL bScrollUp = FALSE;
BOOL bScrollDown = FALSE;
p.x = msg->pt.x;
p.y = msg->pt.y;
VERIFY(::GetClientRect(GetHWnd(), &r));
if (p.x < 0) {
bScrollLeft = TRUE;
p.x = 0;
} else if (p.x > r.right) {
bScrollRight = TRUE;
p.x = r.right - 1;
}
LONG lCurPos = EditGetCharFromPos(p);
if (GetStartSelectionPos() != -1 &&
GetEndSelectionPos() != -1 &&
lCurPos != GetLastSelectionPos()) {
CHARRANGE cr;
SetLastSelectionPos(lCurPos);
cr.cpMin = GetStartSelectionPos();
cr.cpMax = GetLastSelectionPos();
EditSetSel(cr);
}
if (bScrollLeft == TRUE || bScrollRight == TRUE) {
SCROLLINFO si;
memset(&si, 0, sizeof(si));
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
VERIFY(::GetScrollInfo(GetHWnd(), SB_HORZ, &si));
if (bScrollLeft == TRUE) {
si.nPos = si.nPos - si.nPage / 2;
si.nPos = max(si.nMin, si.nPos);
} else if (bScrollRight == TRUE) {
si.nPos = si.nPos + si.nPage / 2;
si.nPos = min(si.nPos, si.nMax);
}
/*
* Okay to use 16-bit position since RichEdit control adjusts
* its scrollbars so that their range is always 16-bit.
*/
DASSERT(abs(si.nPos) < 0x8000);
SendMessage(WM_HSCROLL,
MAKEWPARAM(SB_THUMBPOSITION, LOWORD(si.nPos)));
}
delete msg;
return mrConsume;
} }
delete msg;
return mrConsume;
} }
/* /*
* Store the 'synthetic' parameter so that the WM_PASTE security check * Store the 'synthetic' parameter so that the WM_PASTE security check
......
...@@ -131,6 +131,11 @@ struct UpdateWindowStruct { ...@@ -131,6 +131,11 @@ struct UpdateWindowStruct {
HBITMAP hBitmap; HBITMAP hBitmap;
jint width, height; jint width, height;
}; };
// Struct for _RequestWindowFocus() method
struct RequestWindowFocusStruct {
jobject component;
jboolean isMouseEventCause;
};
/************************************************************************ /************************************************************************
* AwtWindow fields * AwtWindow fields
...@@ -395,7 +400,7 @@ AwtWindow* AwtWindow::Create(jobject self, jobject parent) ...@@ -395,7 +400,7 @@ AwtWindow* AwtWindow::Create(jobject self, jobject parent)
window->m_isRetainingHierarchyZOrder = TRUE; window->m_isRetainingHierarchyZOrder = TRUE;
} }
DWORD style = WS_CLIPCHILDREN | WS_POPUP; DWORD style = WS_CLIPCHILDREN | WS_POPUP;
DWORD exStyle = 0; DWORD exStyle = WS_EX_NOACTIVATE;
if (GetRTL()) { if (GetRTL()) {
exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR; exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR;
if (GetRTLReadingOrder()) if (GetRTLReadingOrder())
...@@ -886,45 +891,92 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite, ...@@ -886,45 +891,92 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite,
env->DeleteLocalRef(event); env->DeleteLocalRef(event);
} }
BOOL AwtWindow::AwtSetActiveWindow(BOOL isMouseEventCause, UINT hittest)
{
// Fix for 6458497.
// Retreat if current foreground window is out of both our and embedder process.
// The exception is when activation is requested due to a mouse event.
if (!isMouseEventCause) {
HWND fgWindow = ::GetForegroundWindow();
if (NULL != fgWindow) {
DWORD fgProcessID;
::GetWindowThreadProcessId(fgWindow, &fgProcessID);
if (fgProcessID != ::GetCurrentProcessId()
&& !AwtToolkit::GetInstance().IsEmbedderProcessId(fgProcessID))
{
return FALSE;
}
}
}
HWND proxyContainerHWnd = GetProxyToplevelContainer();
HWND proxyHWnd = GetProxyFocusOwner();
if (proxyContainerHWnd == NULL || proxyHWnd == NULL) {
return FALSE;
}
// Activate the proxy toplevel container
if (::GetActiveWindow() != proxyContainerHWnd) {
sm_suppressFocusAndActivation = TRUE;
::BringWindowToTop(proxyContainerHWnd);
::SetForegroundWindow(proxyContainerHWnd);
sm_suppressFocusAndActivation = FALSE;
if (::GetActiveWindow() != proxyContainerHWnd) {
return FALSE; // activation has been rejected
}
}
// Focus the proxy itself
if (::GetFocus() != proxyHWnd) {
sm_suppressFocusAndActivation = TRUE;
::SetFocus(proxyHWnd);
sm_suppressFocusAndActivation = FALSE;
if (::GetFocus() != proxyHWnd) {
return FALSE; // focus has been rejected (that is unlikely)
}
}
if (sm_focusedWindow != GetHWnd()) {
if (sm_focusedWindow != NULL) {
// Deactivate the old focused window
AwtWindow::SynthesizeWmActivate(FALSE, sm_focusedWindow, GetHWnd());
}
// Activate the new focused window.
AwtWindow::SynthesizeWmActivate(TRUE, GetHWnd(), sm_focusedWindow);
}
return TRUE;
}
MsgRouting AwtWindow::WmActivate(UINT nState, BOOL fMinimized, HWND opposite) MsgRouting AwtWindow::WmActivate(UINT nState, BOOL fMinimized, HWND opposite)
{ {
jint type; jint type;
if (nState != WA_INACTIVE) { if (nState != WA_INACTIVE) {
::SetFocus((sm_focusOwner == NULL ||
AwtComponent::GetTopLevelParentForWindow(sm_focusOwner) !=
GetHWnd()) ? NULL : sm_focusOwner);
type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS; type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS;
AwtToolkit::GetInstance().
InvokeFunctionLater(BounceActivation, this);
sm_focusedWindow = GetHWnd(); sm_focusedWindow = GetHWnd();
} else { } else {
// The owner is not necassarily getting WM_ACTIVATE(WA_INACTIVE).
// So, initiate retaining the actualFocusedWindow.
AwtFrame *owner = GetOwningFrameOrDialog();
if (owner) {
owner->CheckRetainActualFocusedWindow(opposite);
}
if (m_grabbedWindow != NULL && !m_grabbedWindow->IsOneOfOwnersOf(this)) { if (m_grabbedWindow != NULL && !m_grabbedWindow->IsOneOfOwnersOf(this)) {
m_grabbedWindow->Ungrab(); m_grabbedWindow->Ungrab();
} }
type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS; type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS;
sm_focusedWindow = NULL; sm_focusedWindow = NULL;
sm_focusOwner = NULL;
} }
SendWindowEvent(type, opposite); SendWindowEvent(type, opposite);
return mrConsume; return mrConsume;
} }
void AwtWindow::BounceActivation(void *self) {
AwtWindow *wSelf = (AwtWindow *)self;
if (::GetActiveWindow() == wSelf->GetHWnd()) {
AwtFrame *owner = wSelf->GetOwningFrameOrDialog();
if (owner != NULL) {
sm_suppressFocusAndActivation = TRUE;
::SetActiveWindow(owner->GetHWnd());
::SetFocus(owner->GetProxyFocusOwner());
sm_suppressFocusAndActivation = FALSE;
}
}
}
MsgRouting AwtWindow::WmCreate() MsgRouting AwtWindow::WmCreate()
{ {
return mrDoDefault; return mrDoDefault;
...@@ -948,17 +1000,20 @@ MsgRouting AwtWindow::WmShowWindow(BOOL show, UINT status) ...@@ -948,17 +1000,20 @@ MsgRouting AwtWindow::WmShowWindow(BOOL show, UINT status)
{ {
/* /*
* Original fix for 4810575. Modified for 6386592. * Original fix for 4810575. Modified for 6386592.
* If an owned window (not frame/dialog) gets disposed we should synthesize * If a simple window gets disposed we should synthesize
* WM_ACTIVATE for its nearest owner. This is not performed by default because * WM_ACTIVATE for its nearest owner. This is not performed by default because
* the owner frame/dialog is natively active. * the owner frame/dialog is natively active.
*/ */
HWND hwndSelf = GetHWnd(); HWND hwndSelf = GetHWnd();
HWND hwndParent = ::GetParent(hwndSelf); HWND hwndOwner = ::GetParent(hwndSelf);
if (!show && IsSimpleWindow() && hwndSelf == sm_focusedWindow && if (!show && IsSimpleWindow() && hwndSelf == sm_focusedWindow &&
hwndParent != NULL && ::IsWindowVisible(hwndParent)) hwndOwner != NULL && ::IsWindowVisible(hwndOwner))
{ {
::PostMessage(hwndParent, WM_ACTIVATE, (WPARAM)WA_ACTIVE, (LPARAM)hwndSelf); AwtFrame *owner = (AwtFrame*)AwtComponent::GetComponent(hwndOwner);
if (owner != NULL) {
owner->AwtSetActiveWindow();
}
} }
//Fixed 4842599: REGRESSION: JPopupMenu not Hidden Properly After Iconified and Deiconified //Fixed 4842599: REGRESSION: JPopupMenu not Hidden Properly After Iconified and Deiconified
...@@ -1453,6 +1508,38 @@ void AwtWindow::FlashWindowEx(HWND hWnd, UINT count, DWORD timeout, DWORD flags) ...@@ -1453,6 +1508,38 @@ void AwtWindow::FlashWindowEx(HWND hWnd, UINT count, DWORD timeout, DWORD flags)
::FlashWindowEx(&fi); ::FlashWindowEx(&fi);
} }
jboolean
AwtWindow::_RequestWindowFocus(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
RequestWindowFocusStruct *rfs = (RequestWindowFocusStruct *)param;
jobject self = rfs->component;
jboolean isMouseEventCause = rfs->isMouseEventCause;
jboolean result = JNI_FALSE;
AwtWindow *window = NULL;
PDATA pData;
JNI_CHECK_NULL_GOTO(self, "peer", ret);
pData = JNI_GET_PDATA(self);
if (pData == NULL) {
// do nothing just return false
goto ret;
}
window = (AwtWindow *)pData;
if (::IsWindow(window->GetHWnd())) {
result = (jboolean)window->SendMessage(WM_AWT_WINDOW_SETACTIVE, (WPARAM)isMouseEventCause, 0);
}
ret:
env->DeleteGlobalRef(self);
delete rfs;
return result;
}
void AwtWindow::_ToFront(void *param) void AwtWindow::_ToFront(void *param)
{ {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
...@@ -2173,11 +2260,14 @@ void AwtWindow::_SetFocusableWindow(void *param) ...@@ -2173,11 +2260,14 @@ void AwtWindow::_SetFocusableWindow(void *param)
window->m_isFocusableWindow = isFocusableWindow; window->m_isFocusableWindow = isFocusableWindow;
if (!window->m_isFocusableWindow) { // A simple window is permanently set to WS_EX_NOACTIVATE
LONG isPopup = window->GetStyle() & WS_POPUP; if (!window->IsSimpleWindow()) {
window->SetStyleEx(window->GetStyleEx() | (isPopup ? 0 : WS_EX_APPWINDOW) | AWT_WS_EX_NOACTIVATE); if (!window->m_isFocusableWindow) {
} else { LONG isPopup = window->GetStyle() & WS_POPUP;
window->SetStyleEx(window->GetStyleEx() & ~WS_EX_APPWINDOW & ~AWT_WS_EX_NOACTIVATE); window->SetStyleEx(window->GetStyleEx() | (isPopup ? 0 : WS_EX_APPWINDOW) | WS_EX_NOACTIVATE);
} else {
window->SetStyleEx(window->GetStyleEx() & ~WS_EX_APPWINDOW & ~WS_EX_NOACTIVATE);
}
} }
ret: ret:
...@@ -2843,4 +2933,27 @@ void AwtWindow_UpdateWindow(JNIEnv *env, jobject peer, ...@@ -2843,4 +2933,27 @@ void AwtWindow_UpdateWindow(JNIEnv *env, jobject peer,
CATCH_BAD_ALLOC; CATCH_BAD_ALLOC;
} }
/*
* Class: sun_awt_windows_WComponentPeer
* Method: requestFocus
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_sun_awt_windows_WWindowPeer_requestWindowFocus
(JNIEnv *env, jobject self, jboolean isMouseEventCause)
{
TRY;
jobject selfGlobalRef = env->NewGlobalRef(self);
RequestWindowFocusStruct *rfs = new RequestWindowFocusStruct;
rfs->component = selfGlobalRef;
rfs->isMouseEventCause = isMouseEventCause;
return (jboolean)AwtToolkit::GetInstance().SyncCall(
(void*(*)(void*))AwtWindow::_RequestWindowFocus, rfs);
// global refs and rfs are deleted in _RequestWindowFocus
CATCH_BAD_ALLOC_RET(JNI_FALSE);
}
} /* extern "C" */ } /* extern "C" */
...@@ -40,9 +40,6 @@ static LPCTSTR NativeDialogWndProcProp = TEXT("SunAwtNativeDialogWndProcProp"); ...@@ -40,9 +40,6 @@ static LPCTSTR NativeDialogWndProcProp = TEXT("SunAwtNativeDialogWndProcProp");
#define WH_MOUSE_LL 14 #define WH_MOUSE_LL 14
#endif #endif
// WS_EX_NOACTIVATE is not defined in the headers we build with
#define AWT_WS_EX_NOACTIVATE 0x08000000L
class AwtFrame; class AwtFrame;
/************************************************************************ /************************************************************************
...@@ -157,7 +154,6 @@ public: ...@@ -157,7 +154,6 @@ public:
* Windows message handler functions * Windows message handler functions
*/ */
virtual MsgRouting WmActivate(UINT nState, BOOL fMinimized, HWND opposite); virtual MsgRouting WmActivate(UINT nState, BOOL fMinimized, HWND opposite);
static void BounceActivation(void *self); // used by WmActivate
virtual MsgRouting WmCreate(); virtual MsgRouting WmCreate();
virtual MsgRouting WmClose(); virtual MsgRouting WmClose();
virtual MsgRouting WmDestroy(); virtual MsgRouting WmDestroy();
...@@ -181,6 +177,20 @@ public: ...@@ -181,6 +177,20 @@ public:
virtual MsgRouting HandleEvent(MSG *msg, BOOL synthetic); virtual MsgRouting HandleEvent(MSG *msg, BOOL synthetic);
virtual void WindowResized(); virtual void WindowResized();
static jboolean _RequestWindowFocus(void *param);
virtual BOOL AwtSetActiveWindow(BOOL isMouseEventCause = FALSE, UINT hittest = HTCLIENT);
// Execute on Toolkit only.
INLINE static LRESULT SynthesizeWmActivate(BOOL doActivate, HWND targetHWnd, HWND oppositeHWnd) {
if (::IsWindowVisible(targetHWnd)) {
return ::SendMessage(targetHWnd, WM_ACTIVATE,
MAKEWPARAM(doActivate ? WA_ACTIVE : WA_INACTIVE, FALSE),
(LPARAM) oppositeHWnd);
}
return 1; // if not processed
}
void moveToDefaultLocation(); /* moves Window to X,Y specified by Window Manger */ void moveToDefaultLocation(); /* moves Window to X,Y specified by Window Manger */
void UpdateWindow(JNIEnv* env, jintArray data, int width, int height, void UpdateWindow(JNIEnv* env, jintArray data, int width, int height,
......
/* /*
* Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -194,6 +194,7 @@ enum { ...@@ -194,6 +194,7 @@ enum {
WM_AWT_COMPONENT_SHOW, WM_AWT_COMPONENT_SHOW,
WM_AWT_COMPONENT_HIDE, WM_AWT_COMPONENT_HIDE,
WM_AWT_COMPONENT_SETFOCUS, WM_AWT_COMPONENT_SETFOCUS,
WM_AWT_WINDOW_SETACTIVE,
WM_AWT_LIST_SETMULTISELECT, WM_AWT_LIST_SETMULTISELECT,
WM_AWT_HANDLE_EVENT, WM_AWT_HANDLE_EVENT,
WM_AWT_PRINT_COMPONENT, WM_AWT_PRINT_COMPONENT,
......
/*
* Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
@test
@bug 4390555
@summary Synopsis: clearGlobalFocusOwner() is not trigerring permanent FOCUS_LOST event
@author son@sparc.spb.su, anton.tarasov: area=awt.focus
@library ../../regtesthelpers
@build Util
@run main ClearGlobalFocusOwnerTest
*/
import java.awt.*;
import java.awt.event.*;
import test.java.awt.regtesthelpers.Util;
public class ClearGlobalFocusOwnerTest {
static volatile boolean isFocusLost = false;
static Frame frame = new Frame("Test frame");
static Button button = new Button("Test button");
public static void main(String[] args) {
button.addFocusListener(new FocusAdapter() {
public void focusLost(FocusEvent fe) {
if (fe.isTemporary()) {
throw new TestFailedException("the FocusLost event is temporary: " + fe);
}
isFocusLost = true;
}
});
frame.add(button);
frame.pack();
frame.setVisible(true);
Util.waitForIdle(null);
if (!button.hasFocus()) {
button.requestFocus();
Util.waitForIdle(null);
if (!button.hasFocus()) {
throw new TestErrorException("couldn't focus " + button);
}
}
KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
Util.waitForIdle(null);
if (!isFocusLost) {
throw new TestFailedException("no FocusLost event happened on clearGlobalFocusOwner");
}
System.out.println("Test passed.");
}
}
/**
* Thrown when the behavior being verified is found wrong.
*/
class TestFailedException extends RuntimeException {
TestFailedException(String msg) {
super("Test failed: " + msg);
}
}
/**
* Thrown when an error not related to the behavior being verified is encountered.
*/
class TestErrorException extends RuntimeException {
TestErrorException(String msg) {
super("Unexpected error: " + msg);
}
}
...@@ -71,8 +71,14 @@ public class IconifiedFrameFocusChangeTest extends Applet { ...@@ -71,8 +71,14 @@ public class IconifiedFrameFocusChangeTest extends Applet {
testFrame.setVisible(true); testFrame.setVisible(true);
Util.waitForIdle(robot); Util.waitForIdle(robot);
robot.delay(1000); // additional delay is required
if (!testButton.hasFocus()) { if (!testButton.hasFocus()) {
throw new TestErrorException("wrong initial focus"); testButton.requestFocus();
Util.waitForIdle(robot);
if (!testButton.hasFocus()) {
throw new TestErrorException("couldn't focus " + testButton);
}
} }
/* /*
......
/*
* Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
@test
@bug 6411406
@summary Components automatically transfer focus on removal, even if developer requests focus elsewhere first
@author oleg.sukhodolsky, anton.tarasov: area=awt.focus
@library ../../regtesthelpers
@build Util
@run main RemoveAfterRequest
*/
/**
* RemoveAfterRequest.java
*
* summary: Components automatically transfer focus on removal, even if developer requests focus elsewhere first
*/
import java.awt.*;
import java.awt.event.*;
import test.java.awt.regtesthelpers.Util;
public class RemoveAfterRequest {
final static Frame frame = new Frame("test frame");
final static Button btn1 = new Button("btn1");
final static Button btn2 = new Button("btn2");
final static Button btn3 = new Button("btn3");
public static void main(String[] args) {
frame.setLayout(new GridLayout(3, 1));
frame.add(btn1);
frame.add(btn2);
frame.add(btn3);
frame.pack();
frame.setVisible(true);
Util.waitForIdle(null);
if (!btn1.hasFocus()) {
btn1.requestFocus();
Util.waitForIdle(null);
if (!btn1.hasFocus()) {
throw new TestErrorException("couldn't focus " + btn1);
}
}
if (!Util.trackFocusGained(btn3, new Runnable() {
public void run() {
btn3.requestFocus();
frame.remove(btn1);
frame.invalidate();
frame.validate();
frame.repaint();
}
}, 2000, true))
{
throw new TestFailedException("focus request on removal failed");
}
System.out.println("Test passed.");
}
}
/**
* Thrown when the behavior being verified is found wrong.
*/
class TestFailedException extends RuntimeException {
TestFailedException(String msg) {
super("Test failed: " + msg);
}
}
/**
* Thrown when an error not related to the behavior being verified is encountered.
*/
class TestErrorException extends RuntimeException {
TestErrorException(String msg) {
super("Unexpected error: " + msg);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册