提交 fe967584 编写于 作者: A ant

6806217: implement synthetic focus model for MS Windows

Reviewed-by: art, dcherepanov
上级 38def681
此差异已折叠。
......@@ -851,6 +851,12 @@ public abstract class Component implements ImageObserver, MenuContainer,
{
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,
requestFocusHelper(false, true);
}
void requestFocus(CausedFocusEvent.Cause cause) {
requestFocusHelper(false, true, cause);
boolean requestFocus(CausedFocusEvent.Cause cause) {
return requestFocusHelper(false, true, cause);
}
/**
......
......@@ -61,6 +61,7 @@ import sun.awt.HeadlessToolkit;
import sun.awt.SunToolkit;
import sun.awt.CausedFocusEvent;
import sun.awt.KeyboardFocusManagerPeerProvider;
import sun.awt.AWTAccessor;
/**
* The KeyboardFocusManager is responsible for managing the active and focused
......@@ -118,6 +119,32 @@ public abstract class KeyboardFocusManager
if (!GraphicsEnvironment.isHeadless()) {
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;
......@@ -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,
* or null if this is a duplicate request. The active Window is useful
......
......@@ -31,7 +31,8 @@ import java.awt.image.BufferedImage;
import sun.misc.Unsafe;
/** The AWTAccessor utility class.
/**
* The AWTAccessor utility class.
* The main purpose of this class is to enable accessing
* private and package-private fields of classes from
* different classes/packages. See sun.misc.SharedSecretes
......@@ -83,6 +84,14 @@ public final class AWTAccessor {
* Sets GraphicsConfiguration value for the component.
*/
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 {
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.
*/
......@@ -171,6 +209,11 @@ public final class AWTAccessor {
*/
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.
*/
......@@ -236,4 +279,21 @@ public final class AWTAccessor {
}
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
throw new HeadlessException();
}
public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) throws HeadlessException {
KeyboardFocusManagerPeerImpl peer = new KeyboardFocusManagerPeerImpl(manager);
return peer;
public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager)
throws HeadlessException {
throw new HeadlessException();
}
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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -27,47 +27,150 @@ package sun.awt;
import java.awt.Component;
import java.awt.KeyboardFocusManager;
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.ComponentPeer;
import java.lang.reflect.InvocationTargetException;
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 {
static native Window getNativeFocusedWindow();
static native Component getNativeFocusOwner();
static native void clearNativeGlobalFocusOwner(Window activeWindow);
// The constants are copied from java.awt.KeyboardFocusManager
public static final int SNFH_FAILURE = 0;
public static final int SNFH_SUCCESS_HANDLED = 1;
public static final int SNFH_SUCCESS_PROCEED = 2;
KeyboardFocusManagerPeerImpl(KeyboardFocusManager manager) {
protected KeyboardFocusManager manager;
public KeyboardFocusManagerPeerImpl(KeyboardFocusManager manager) {
this.manager = manager;
}
public Window getCurrentFocusedWindow() {
return getNativeFocusedWindow();
@Override
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() {
return getNativeFocusOwner();
// WARNING: Don't call it on the Toolkit thread.
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) {
try {
if (m_removeLastFocusRequest == null) {
m_removeLastFocusRequest = SunToolkit.getMethod(KeyboardFocusManager.class, "removeLastFocusRequest",
new Class[] {Component.class});
}
m_removeLastFocusRequest.invoke(null, new Object[]{heavyweight});
} catch (InvocationTargetException ite) {
ite.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
kfmAccessor.removeLastFocusRequest(heavyweight);
}
// WARNING: Don't call it on the Toolkit thread.
public static boolean processSynchronousLightweightTransfer(Component heavyweight,
Component descendant,
boolean temporary,
boolean focusedWindowChangeAllowed,
long time)
{
return kfmAccessor.processSynchronousLightweightTransfer(
heavyweight, descendant, temporary, focusedWindowChangeAllowed, time);
}
}
......@@ -220,10 +220,8 @@ public abstract class SunToolkit extends Toolkit
public abstract RobotPeer createRobot(Robot target, GraphicsDevice screen)
throws AWTException;
public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) throws HeadlessException {
KeyboardFocusManagerPeerImpl peer = new KeyboardFocusManagerPeerImpl(manager);
return peer;
}
public abstract KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager)
throws HeadlessException;
/**
* The AWT lock is typically only used on Unix platforms to synchronize
......
......@@ -77,11 +77,6 @@ import sun.java2d.pipe.Region;
public class XComponentPeer extends XWindow implements ComponentPeer, DropTargetPeer,
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 buffersLog = Logger.getLogger("sun.awt.X11.XComponentPeer.multibuffer");
private static final Logger focusLog = Logger.getLogger("sun.awt.X11.focus.XComponentPeer");
......@@ -315,113 +310,27 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
return null;
}
/**
* 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();
}
}
}
// TODO: consider moving it to KeyboardFocusManagerPeerImpl
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))
{
return true;
}
int result = XKeyboardFocusManagerPeer
.shouldNativelyFocusHeavyweight(target, lightweightChild,
temporary, focusedWindowChangeAllowed, time, cause);
int result = XKeyboardFocusManagerPeer.
shouldNativelyFocusHeavyweight(target, lightweightChild,
temporary, focusedWindowChangeAllowed,
time, cause);
switch (result) {
case SNFH_FAILURE:
case XKeyboardFocusManagerPeer.SNFH_FAILURE:
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
// XSetInputFocus on native window
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Proceeding with request to " +
......@@ -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
* 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) {
return rejectFocusRequestHelper("WARNING: Parent window is null");
}
......@@ -455,14 +364,13 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
if (!(res && parentWindow.isFocused())) {
return rejectFocusRequestHelper("Waiting for asynchronous processing of the request");
}
// NOTE: We simulate heavyweight behavior of Motif - component receives focus right
// after request, not after event. Normally, we should better listen for event
// by listeners.
return XKeyboardFocusManagerPeer.simulateMotifRequestFocus(lightweightChild, target, temporary,
focusedWindowChangeAllowed, time, cause);
return XKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
(Component)target,
temporary,
focusedWindowChangeAllowed,
time, cause);
// Motif compatibility code
case SNFH_SUCCESS_HANDLED:
case XKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
// Either lightweight or excessive request - all events are generated.
return true;
}
......@@ -471,7 +379,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
private boolean rejectFocusRequestHelper(String logMsg) {
if (focusLog.isLoggable(Level.FINER)) focusLog.finer(logMsg);
KeyboardFocusManagerPeerImpl.removeLastFocusRequest(target);
XKeyboardFocusManagerPeer.removeLastFocusRequest(target);
return false;
}
......@@ -615,8 +523,9 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
void handleJavaMouseEvent(MouseEvent e) {
switch (e.getID()) {
case MouseEvent.MOUSE_PRESSED:
if (target == e.getSource() && shouldFocusOnClick()
&& !target.isFocusOwner() && canBeFocusedByClick(target))
if (target == e.getSource() &&
!target.isFocusOwner() &&
XKeyboardFocusManagerPeer.shouldFocusOnClick(target))
{
XWindowPeer parentXWindow = getParentTopLevel();
Window parentWindow = ((Window)parentXWindow.getTarget());
......@@ -630,7 +539,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
// WindowEvent wfg = new WindowEvent(parentWindow, WindowEvent.WINDOW_GAINED_FOCUS);
// parentWindow.dispatchEvent(wfg);
// }
callRequestFocus(target, CausedFocusEvent.Cause.MOUSE_EVENT);
XKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT);
}
break;
}
......
......@@ -184,6 +184,7 @@ public class XEmbedChildProxyPeer implements ComponentPeer, XEventDispatcher{
fl = new FocusEvent(currentOwner, FocusEvent.FOCUS_LOST, false, lightweightChild);
}
// TODO: do we need to wrap in sequenced?
if (fl != null) {
postEvent(XComponentPeer.wrapInSequenced(fl));
}
......@@ -203,9 +204,9 @@ public class XEmbedChildProxyPeer implements ComponentPeer, XEventDispatcher{
temporary, false, time, cause);
switch (result) {
case XComponentPeer.SNFH_FAILURE:
case XKeyboardFocusManagerPeer.SNFH_FAILURE:
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
// XSetInputFocus on native window
......@@ -235,9 +236,11 @@ public class XEmbedChildProxyPeer implements ComponentPeer, XEventDispatcher{
// NOTE: We simulate heavyweight behavior of Motif - component receives focus right
// after request, not after event. Normally, we should better listen for event
// by listeners.
// TODO: consider replacing with XKeyboardFocusManagerPeer.deliverFocus
return simulateMotifRequestFocus(lightweightChild, temporary, focusedWindowChangeAllowed, time);
// Motif compatibility code
case XComponentPeer.SNFH_SUCCESS_HANDLED:
case XKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
// Either lightweight or excessive requiest - all events are generated.
return true;
}
......
......@@ -31,6 +31,7 @@ import java.awt.Window;
import java.awt.event.FocusEvent;
import java.awt.peer.KeyboardFocusManagerPeer;
import java.awt.peer.ComponentPeer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
......@@ -40,136 +41,73 @@ import java.util.logging.Logger;
import sun.awt.CausedFocusEvent;
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");
KeyboardFocusManager manager;
XKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
this.manager = manager;
}
private static Object lock = new Object() {};
private static Component currentFocusOwner;
private static Window currentFocusedWindow;
static void setCurrentNativeFocusOwner(Component comp) {
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Setting current native focus owner " + comp);
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;
}
XKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
super(manager);
}
static Component getCurrentNativeFocusOwner() {
synchronized(lock) {
return currentFocusOwner;
}
@Override
public void setCurrentFocusOwner(Component comp) {
setCurrentNativeFocusOwner(comp);
}
static Window getCurrentNativeFocusedWindow() {
synchronized(lock) {
return currentFocusedWindow;
}
@Override
public Component getCurrentFocusOwner() {
return getCurrentNativeFocusOwner();
}
@Override
public Window getCurrentFocusedWindow() {
return getCurrentNativeFocusedWindow();
}
public void setCurrentFocusOwner(Component comp) {
setCurrentNativeFocusOwner(comp);
}
public Component getCurrentFocusOwner() {
return getCurrentNativeFocusOwner();
public static void setCurrentNativeFocusOwner(Component comp) {
synchronized (lock) {
currentFocusOwner = comp;
}
}
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) {
// 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);
// }
}
public static Component getCurrentNativeFocusOwner() {
synchronized(lock) {
return currentFocusOwner;
}
}
}
static boolean simulateMotifRequestFocus(Component lightweightChild, Component target, boolean temporary,
boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
{
if (lightweightChild == null) {
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);
public static void setCurrentNativeFocusedWindow(Window win) {
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Setting current native focused window " + win);
synchronized(lock) {
currentFocusedWindow = win;
}
}
if (fl != null) {
XWindow.sendEvent(fl);
public static Window getCurrentNativeFocusedWindow() {
synchronized(lock) {
return currentFocusedWindow;
}
XWindow.sendEvent(fg);
return true;
}
static Method shouldNativelyFocusHeavyweightMethod;
static int shouldNativelyFocusHeavyweight(Component heavyweight,
Component descendant, boolean temporary,
boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
// TODO: do something to eliminate this forwarding
public static boolean deliverFocus(Component lightweightChild,
Component target,
boolean temporary,
boolean focusedWindowChangeAllowed,
long time,
CausedFocusEvent.Cause cause)
{
if (shouldNativelyFocusHeavyweightMethod == null) {
Class[] arg_types =
new Class[] { Component.class,
Component.class,
Boolean.TYPE,
Boolean.TYPE,
Long.TYPE,
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;
return KeyboardFocusManagerPeerImpl.deliverFocus(lightweightChild,
target,
temporary,
focusedWindowChangeAllowed,
time,
cause,
getCurrentNativeFocusOwner());
}
}
......@@ -27,6 +27,10 @@ package sun.awt.windows;
import java.awt.*;
import java.awt.peer.*;
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 {
......@@ -70,6 +74,8 @@ class WChoicePeer extends WComponentPeer implements ChoicePeer {
public synchronized native void reshape(int x, int y, int width, int height);
private WindowListener windowListener;
// Toolkit & peer internals
WChoicePeer(Choice target) {
......@@ -91,9 +97,38 @@ class WChoicePeer extends WComponentPeer implements ChoicePeer {
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();
}
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
void handleAction(final int index) {
......@@ -121,4 +156,5 @@ class WChoicePeer extends WComponentPeer implements ChoicePeer {
return getMinimumSize();
}
native void closeList();
}
......@@ -38,6 +38,10 @@ import java.awt.image.ColorModel;
import java.awt.event.PaintEvent;
import java.awt.event.InvocationEvent;
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.Win32GraphicsEnvironment;
import sun.java2d.InvalidPipeException;
......@@ -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 shapeLog = Logger.getLogger("sun.awt.windows.shape.WComponentPeer");
private static final Logger focusLog = Logger.getLogger("sun.awt.windows.focus.WComponentPeer");
// ComponentPeer implementation
SurfaceData surfaceData;
......@@ -296,14 +301,35 @@ public abstract class WComponentPeer extends WObjectPeer
// on handling '\n' to prevent it from being passed to native code
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);
public void handleEvent(AWTEvent e) {
int id = e.getID();
if (((Component)target).isEnabled() && (e instanceof KeyEvent) && !((KeyEvent)e).isConsumed()) {
if (handleJavaKeyEvent((KeyEvent)e)) {
return;
if ((e instanceof InputEvent) && !((InputEvent)e).isConsumed() &&
((Component)target).isEnabled())
{
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
paintArea.paint(target,shouldClearRectBeforePaint());
}
return;
case FocusEvent.FOCUS_LOST:
case FocusEvent.FOCUS_GAINED:
handleJavaFocusEvent((FocusEvent)e);
default:
break;
}
......@@ -327,6 +356,13 @@ public abstract class WComponentPeer extends WObjectPeer
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() {
return ((Component)target).getSize();
}
......@@ -572,22 +608,64 @@ public abstract class WComponentPeer extends WObjectPeer
WGlobalCursorManager.getCursorManager().updateCursorImmediately();
}
native static boolean processSynchronousLightweightTransfer(Component heavyweight, Component descendant,
boolean temporary, boolean focusedWindowChangeAllowed,
long time);
public boolean requestFocus
(Component lightweightChild, boolean temporary,
boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) {
if (processSynchronousLightweightTransfer((Component)target, lightweightChild, temporary,
focusedWindowChangeAllowed, time)) {
// TODO: consider moving it to KeyboardFocusManagerPeerImpl
public boolean requestFocus(Component lightweightChild, boolean temporary,
boolean focusedWindowChangeAllowed, long time,
CausedFocusEvent.Cause cause)
{
if (WKeyboardFocusManagerPeer.
processSynchronousLightweightTransfer((Component)target, lightweightChild, temporary,
focusedWindowChangeAllowed, time))
{
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) {
return new ToolkitImage(producer);
......@@ -718,9 +796,12 @@ public abstract class WComponentPeer extends WObjectPeer
* Post an event. Queue it for execution by the callback thread.
*/
void postEvent(AWTEvent event) {
preprocessPostEvent(event);
WToolkit.postEvent(WToolkit.targetToAppContext(target), event);
}
void preprocessPostEvent(AWTEvent event) {}
// Routines to support deferred window positioning.
public void beginLayout() {
// 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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -23,21 +23,53 @@
* have any questions.
*/
#ifndef AWT_KEYBOARDFOCUSMANAGER_H
#define AWT_KEYBOARDFOCUSMANAGER_H
package sun.awt.windows;
#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 {
public:
class WKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
static native void setNativeFocusOwner(ComponentPeer peer);
static native Component getNativeFocusOwner();
static native Window getNativeFocusedWindow();
static jclass keyboardFocusManagerCls;
static jmethodID shouldNativelyFocusHeavyweightMID;
static jmethodID heavyweightButtonDownMID;
static jmethodID markClearGlobalFocusOwnerMID;
static jmethodID removeLastFocusRequestMID;
static jfieldID isProxyActive;
static jmethodID processSynchronousTransfer;
};
WKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
super(manager);
}
#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 {
return true;
}
public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager)
throws HeadlessException
{
return new WKeyboardFocusManagerPeer(manager);
}
protected native void setDynamicLayoutNative(boolean b);
public void setDynamicLayout(boolean b) {
......
......@@ -77,6 +77,12 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
private final static PropertyChangeListener guiDisposedListener =
new GuiDisposedListener();
/*
* Called (on the Toolkit thread) before the appropriate
* WindowStateEvent is posted to the EventQueue.
*/
private WindowListener windowListener;
/**
* Initialize JNI field IDs
*/
......@@ -232,27 +238,64 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
int[] smallIconRaster, int smw, int smh);
synchronized native void reshapeFrame(int x, int y, int width, int height);
public boolean requestWindowFocus() {
// Win32 window doesn't need this
return false;
public boolean requestWindowFocus(CausedFocusEvent.Cause cause) {
if (!focusAllowedFor()) {
return false;
}
return requestWindowFocus(cause == CausedFocusEvent.Cause.MOUSE_EVENT);
}
public native boolean requestWindowFocus(boolean isMouseEventCause);
public boolean focusAllowedFor() {
Window target = (Window)this.target;
if (!target.isVisible() ||
!target.isEnabled() ||
!target.isFocusable())
Window window = (Window)this.target;
if (!window.isVisible() ||
!window.isEnabled() ||
!window.isFocusableWindow())
{
return false;
}
if (isModalBlocked()) {
return false;
}
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() {
Dimension minimumSize = null;
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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -30,7 +30,6 @@
#include "awt_Button.h"
#include "awt_Canvas.h"
#include "awt_Window.h"
#include "awt_KeyboardFocusManager.h"
/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
*/
......@@ -143,19 +142,6 @@ done:
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
AwtButton::WmMouseDown(UINT flags, int x, int y, int button)
{
......@@ -204,23 +190,6 @@ AwtButton::NotifyListeners()
(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
AwtButton::OwnerDrawItem(UINT /*ctrlId*/, DRAWITEMSTRUCT& drawInfo)
{
......@@ -293,18 +262,26 @@ MsgRouting AwtButton::WmPaint(HDC)
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)
{
if (AwtComponent::sm_focusOwner != GetHWnd() &&
(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);
if (IsFocusingMouseMessage(msg)) {
SendMessage(BM_SETSTATE, msg->message == WM_LBUTTONDOWN ? TRUE : FALSE, 0);
delete msg;
return mrConsume;
}
if (IsFocusingKeyMessage(msg)) {
SendMessage(BM_SETSTATE, msg->message == WM_KEYDOWN ? TRUE : FALSE, 0);
delete msg;
return mrConsume;
}
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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -50,13 +50,13 @@ public:
/* Windows message handler functions */
MsgRouting WmMouseDown(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 WmPaint(HDC hDC);
MsgRouting HandleEvent(MSG *msg, BOOL synthetic);
BOOL ActMouseMessage(MSG * pMsg);
BOOL IsFocusingMouseMessage(MSG *pMsg);
BOOL IsFocusingKeyMessage(MSG *pMsg);
// called on Toolkit thread from JNI
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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -26,7 +26,6 @@
#include "awt_Toolkit.h"
#include "awt_Canvas.h"
#include "awt_Win32GraphicsConfig.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Window.h"
/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
......@@ -176,27 +175,9 @@ MsgRouting AwtCanvas::WmPaint(HDC)
MsgRouting AwtCanvas::HandleEvent(MSG *msg, BOOL synthetic)
{
if (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) {
/*
* Fix for BugTraq ID 4041703: keyDown not being invoked.
* 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();
}
if (IsFocusingMouseMessage(msg)) {
delete msg;
return mrConsume;
}
return AwtComponent::HandleEvent(msg, synthetic);
}
......
......@@ -26,7 +26,6 @@
#include "awt.h"
#include "awt_Toolkit.h"
#include "awt_Checkbox.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Canvas.h"
#include "awt_Window.h"
......@@ -143,17 +142,6 @@ done:
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
AwtCheckbox::WmMouseUp(UINT flags, int x, int y, int button)
{
......@@ -329,18 +317,32 @@ MsgRouting AwtCheckbox::WmPaint(HDC)
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)
{
if (IsFocusable() && AwtComponent::sm_focusOwner != GetHWnd() &&
(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);
if (IsFocusingMouseMessage(msg)) {
SendMessage(BM_SETSTATE, (WPARAM)(msg->message == WM_LBUTTONDOWN ? TRUE : FALSE));
delete msg;
return mrConsume;
}
if (IsFocusingKeyMessage(msg)) {
SendMessage(BM_SETSTATE, (WPARAM)(msg->message == WM_KEYDOWN ? TRUE : FALSE));
if (msg->message == WM_KEYDOWN) {
m_fLButtonDowned = TRUE;
} else if (m_fLButtonDowned == TRUE) {
WmNotify(BN_CLICKED);
m_fLButtonDowned = TRUE;
}
delete msg;
return mrConsume;
}
return AwtComponent::HandleEvent(msg, synthetic);
}
......
......@@ -69,7 +69,8 @@ public:
MsgRouting HandleEvent(MSG *msg, BOOL synthetic);
BOOL ActMouseMessage(MSG* pMsg);
BOOL IsFocusingMouseMessage(MSG *pMsg);
BOOL IsFocusingKeyMessage(MSG *pMsg);
// called on Toolkit thread from JNI
static void _SetLabel(void *param);
......
......@@ -23,14 +23,17 @@
* have any questions.
*/
#include <windowsx.h>
#include "awt_Toolkit.h"
#include "awt_Choice.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Canvas.h"
#include "awt_Dimension.h"
#include "awt_Container.h"
#include "ComCtl32Util.h"
#include <java_awt_Toolkit.h>
#include <java_awt_FontMetrics.h>
#include <java_awt_event_InputEvent.h>
......@@ -71,18 +74,29 @@ BOOL AwtChoice::mouseCapture = FALSE;
/* Bug #4338368: consume the spurious MouseUp when the choice loses focus */
BOOL AwtChoice::skipNextMouseUp = FALSE;
BOOL AwtChoice::sm_isMouseMoveInList = FALSE;
/*************************************************************************
* AwtChoice class methods
*/
AwtChoice::AwtChoice() {
killFocusRouting = mrPassAlong;
m_hList = NULL;
m_listDefWindowProc = NULL;
}
LPCTSTR AwtChoice::GetClassName() {
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) {
......@@ -175,17 +189,6 @@ done:
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
// to show all the items up to a maximum of eight
int AwtChoice::GetDropDownHeight()
......@@ -253,6 +256,7 @@ void AwtChoice::SetDragCapture(UINT flags)
}
return;
}
// don't want to interfere with other controls
if (::GetCapture() == NULL) {
::SetCapture(GetHWnd());
......@@ -370,6 +374,58 @@ void AwtChoice::SetFont(AwtFont* font)
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)
......@@ -379,15 +435,24 @@ MsgRouting AwtChoice::WmNotify(UINT notifyCode)
if (itemSelect != CB_ERR){
DoCallback("handleAction", "(I)V", itemSelect);
}
} else if (notifyCode == CBN_DROPDOWN && !IsFocusable()) {
// While non-focusable Choice is shown all WM_KILLFOCUS messages should be consumed.
killFocusRouting = mrConsume;
} else if (notifyCode == CBN_CLOSEUP && !IsFocusable()) {
// When non-focusable Choice is about to close, send it synthetic WM_KILLFOCUS
// message that should be processed by the native widget only. This will allow
// the native widget to properly process WM_KILLFOCUS that was earlier consumed.
killFocusRouting = mrDoDefault;
::PostMessage(GetHWnd(), WM_KILLFOCUS, (LPARAM)sm_focusOwner, 0);
} else if (notifyCode == CBN_DROPDOWN) {
if (m_hList == NULL) {
COMBOBOXINFO cbi;
cbi.cbSize = sizeof(COMBOBOXINFO);
::GetComboBoxInfo(GetHWnd(), &cbi);
m_hList = cbi.hwndList;
m_listDefWindowProc = ComCtl32Util::GetInstance().SubclassHWND(m_hList, ListWindowProc);
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;
}
......@@ -414,19 +479,7 @@ MsgRouting
AwtChoice::WmKillFocus(HWND hWndGotFocus)
{
skipNextMouseUp = TRUE;
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;
return AwtComponent::WmKillFocus(hWndGotFocus);
}
MsgRouting
......@@ -441,27 +494,17 @@ AwtChoice::WmMouseUp(UINT flags, int x, int y, int button)
MsgRouting AwtChoice::HandleEvent(MSG *msg, BOOL synthetic)
{
/*
* 6366006
* Note: the event can be sent in two cases:
* 1) The Choice is closed and user clicks on it to drop it down.
* 2) The Choice is non-focusable, it's droped down, user
* clicks on it (or outside) to close it.
* So, if the Choice is in droped down state, we shouldn't call
* heavyweightButtonDown() method. Otherwise it will set a typeahead marker
* that won't be removed, because no focus events will be generated.
*/
if (AwtComponent::sm_focusOwner != GetHWnd() &&
(msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) &&
!IsChoiceOpened())
if (IsFocusingMouseMessage(msg)) {
SendMessage(CB_SHOWDROPDOWN, ~SendMessage(CB_GETDROPPEDSTATE, 0, 0), 0);
delete msg;
return mrConsume;
}
// To simulate the native behavior, we close the list on WM_LBUTTONUP if
// WM_MOUSEMOVE has been dedected on the list since it has been dropped down.
if (msg->message == WM_LBUTTONUP && SendMessage(CB_GETDROPPEDSTATE, 0, 0) &&
sm_isMouseMoveInList)
{
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);
SendMessage(CB_SHOWDROPDOWN, FALSE, 0);
}
return AwtComponent::HandleEvent(msg, synthetic);
}
......@@ -618,6 +661,26 @@ done:
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
*/
......@@ -752,6 +815,23 @@ Java_sun_awt_windows_WChoicePeer_create(JNIEnv *env, jobject self,
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" */
......
......@@ -43,6 +43,8 @@ public:
virtual LPCTSTR GetClassName();
static AwtChoice* Create(jobject peer, jobject hParent);
virtual void Dispose();
virtual void Reshape(int x, int y, int w, int h);
void ResetDropDownHeight();
int GetDropDownHeight();
......@@ -75,9 +77,6 @@ public:
virtual void SetDragCapture(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 skipNextMouseUp;
......@@ -87,11 +86,16 @@ public:
static void _AddItems(void *param);
static void _Remove(void *param);
static void _RemoveAll(void *param);
static void _CloseList(void *param);
private:
int GetFieldHeight();
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 */
......@@ -78,8 +78,6 @@ class AwtPopupMenu;
class AwtDropTarget;
struct WmComponentSetFocusData;
/*
* Message routing codes
*/
......@@ -221,17 +219,10 @@ public:
virtual BOOL IsContainer() { return FALSE;} // Plain components can't
/**
* Perform some actions which by default are being performed by Default Window procedure of
* 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.
* Returns TRUE if this message will trigger native focus change, FALSE otherwise.
*/
inline BOOL IsFocusingMessage(UINT message) {
return message == WM_LBUTTONDOWN || message == WM_LBUTTONUP || message == WM_LBUTTONDBLCLK;
}
virtual BOOL IsFocusingKeyMessage(MSG *pMsg);
virtual BOOL IsFocusingMouseMessage(MSG *pMsg);
BOOL IsFocusable();
......@@ -477,6 +468,12 @@ public:
HIMC ImmGetContext();
HIMC ImmAssociateContext(HIMC himc);
HWND GetProxyFocusOwner();
INLINE HWND GetProxyToplevelContainer() {
HWND proxyHWnd = GetProxyFocusOwner();
return ::GetAncestor(proxyHWnd, GA_ROOT); // a browser in case of EmbeddedFrame
}
void CallProxyDefWindowProc(UINT message,
WPARAM wParam,
LPARAM lParam,
......@@ -514,11 +511,6 @@ public:
virtual MsgRouting WmShowWindow(BOOL show, UINT status);
virtual MsgRouting WmSetFocus(HWND hWndLost);
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,
UINT ctlColor, HBRUSH& retBrush);
virtual MsgRouting WmHScroll(UINT scrollCode, UINT pos, HWND hScrollBar);
......@@ -608,10 +600,6 @@ public:
jintArray CreatePrintedPixels(SIZE &loc, SIZE &size);
static void * GetNativeFocusOwner();
static void * GetNativeFocusedWindow();
static void ClearGlobalFocusOwner();
/*
* HWND, AwtComponent and Java Peer interaction
*
......@@ -670,7 +658,6 @@ public:
static void _SetForeground(void *param);
static void _SetBackground(void *param);
static void _SetFont(void *param);
static jboolean _RequestFocus(void *param);
static void _Start(void *param);
static void _BeginValidate(void *param);
static void _EndValidate(void *param);
......@@ -685,6 +672,29 @@ public:
static HWND sm_focusOwner;
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 INLINE BOOL isMenuLoopActive() {
return sm_bMenuLoop;
......@@ -708,7 +718,18 @@ protected:
BOOL m_visible; /* copy of Component.visible */
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 ReleaseDragCapture(UINT flags);
......@@ -778,8 +799,6 @@ private:
static BOOL m_QueryNewPaletteCalled;
BOOL m_skipNextSetFocus;
static AwtComponent* sm_getComponentCache; // a cache for the GetComponent(..) method.
int windowMoveLockPosX;
......@@ -874,14 +893,6 @@ public:
void RealizePalettes(int screen);
};
struct WmComponentSetFocusData {
jobject lightweightChild;
jboolean temporary;
jboolean focusedWindowChangeAllowed;
jlong time;
jobject cause;
};
void ReleaseDCList(HWND hwnd, DCList &list);
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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -39,8 +39,6 @@
#include <sun_awt_windows_WEmbeddedFramePeer.h>
BOOL isAppActive = FALSE;
/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
*/
......@@ -112,6 +110,7 @@ AwtFrame::AwtFrame() {
m_isInputMethodWindow = FALSE;
m_isUndecorated = FALSE;
m_proxyFocusOwner = NULL;
m_lastProxiedFocusOwner = NULL;
m_actualFocusedWindow = NULL;
m_iconic = FALSE;
m_zoomed = FALSE;
......@@ -287,7 +286,6 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent)
::GetSysColor(COLOR_WINDOWTEXT),
::GetSysColor(COLOR_WINDOWFRAME),
self);
/*
* Reshape here instead of during create, so that a
* WM_NCCALCSIZE is sent.
......@@ -327,7 +325,7 @@ LRESULT CALLBACK AwtFrame::ProxyWindowProc(HWND hwnd, UINT message,
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
// which has the Java input focus
switch (message) {
......@@ -345,16 +343,37 @@ LRESULT CALLBACK AwtFrame::ProxyWindowProc(HWND hwnd, UINT message,
case WM_IME_KEYUP:
case WM_INPUTLANGCHANGEREQUEST:
case WM_INPUTLANGCHANGE:
p = AwtComponent::GetComponent(sm_focusOwner);
if (p != NULL) {
return p->WindowProc(message, wParam, lParam);
// TODO: when a Choice's list is dropped down and we're scrolling in
// the list WM_MOUSEWHEEL messages come to the poxy, not to the list. Why?
case WM_MOUSEWHEEL:
focusOwner = AwtComponent::GetComponent(parent->GetLastProxiedFocusOwner());
if (focusOwner != NULL) {
return focusOwner->WindowProc(message, wParam, lParam);
}
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 0x0128: // WM_UPDATEUISTATE
return 0;
}
return parent->WindowProc(message, wParam, lParam);
CATCH_BAD_ALLOC_RET(0);
......@@ -557,7 +576,6 @@ MsgRouting AwtFrame::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
if (m_grabbedWindow != NULL/* && !m_grabbedWindow->IsOneOfOwnersOf(this)*/) {
m_grabbedWindow->Ungrab();
}
if (!IsFocusableWindow() && (button & LEFT_BUTTON)) {
switch (hitTest) {
case HTTOP:
......@@ -915,33 +933,16 @@ MsgRouting AwtFrame::WmSize(UINT type, int w, int h)
MsgRouting AwtFrame::WmActivate(UINT nState, BOOL fMinimized, HWND opposite)
{
jint type;
BOOL doActivateFrame = TRUE;
if (nState != WA_INACTIVE) {
if (!::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()))) {
::SetFocus(NULL); // The KeyboardFocusManager will set focus later
type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS;
isAppActive = TRUE;
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;
if (::IsWindow(AwtWindow::GetModalBlocker(GetHWnd())) ||
CheckActivateActualFocusedWindow(opposite))
{
return mrConsume;
}
type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS;
sm_focusedWindow = GetHWnd();
} else {
if (!::IsWindow(AwtWindow::GetModalBlocker(opposite))) {
// If deactivation happens because of press on grabbing
......@@ -963,37 +964,63 @@ MsgRouting AwtFrame::WmActivate(UINT nState, BOOL fMinimized, HWND opposite)
}
}
}
CheckRetainActualFocusedWindow(opposite);
// If actual focused window is not this Frame
if (sm_focusedWindow != GetHWnd()) {
type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS;
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)
if (opposite != NULL) {
AwtWindow *wOpposite = (AwtWindow *)AwtComponent::GetComponent(opposite);
SendWindowEvent(type, opposite);
return mrConsume;
}
if (wOpposite != NULL &&
wOpposite->GetOwningFrameOrDialog() != this)
{
AwtWindow *window = (AwtWindow *)AwtComponent::GetComponent(sm_focusedWindow);
BOOL AwtFrame::CheckActivateActualFocusedWindow(HWND deactivatedOpositeHWnd)
{
if (m_actualFocusedWindow != NULL) {
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
if (window != NULL && window->GetOwningFrameOrDialog() == this) {
m_actualFocusedWindow = window;
}
}
void AwtFrame::CheckRetainActualFocusedWindow(HWND activatedOpositeHWnd)
{
// 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) {
SendWindowEvent(type, opposite);
BOOL AwtFrame::AwtSetActiveWindow(BOOL isMouseEventCause, UINT hittest)
{
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)
......@@ -1169,60 +1196,6 @@ LRESULT AwtFrame::WinThreadExecProc(ExecuteArgs * args)
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)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
......@@ -1237,7 +1210,7 @@ void AwtFrame::_SynthesizeWmActivate(void *param)
JNI_CHECK_PEER_GOTO(self, ret);
frame = (AwtFrame *)pData;
frame->SynthesizeWmActivate(doActivate, NULL);
SynthesizeWmActivate(doActivate, frame->GetHWnd(), NULL);
ret:
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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -133,11 +133,6 @@ public:
// adjusts the IME candidate window position if needed
void AdjustCandidateWindowPos();
void SynthesizeWmActivate(BOOL doActivate, HWND opposite);
BOOL activateEmbeddedFrameOnSetFocus(HWND hWndLostFocus);
BOOL deactivateEmbeddedFrameOnKillFocus(HWND hWndGotFocus);
// invoked on Toolkit thread
static jobject _GetBoundsPrivate(void *param);
......@@ -153,6 +148,14 @@ public:
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:
/* The frame is undecorated. */
BOOL m_isUndecorated;
......@@ -189,6 +192,10 @@ private:
or an AwtDialog (or one of its children) has the logical input focus. */
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.
* 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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -24,30 +24,20 @@
*/
#include "awt.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Component.h"
#include "awt_Toolkit.h"
#include <java_awt_KeyboardFocusManager.h>
jclass AwtKeyboardFocusManager::keyboardFocusManagerCls;
jmethodID AwtKeyboardFocusManager::shouldNativelyFocusHeavyweightMID;
jmethodID AwtKeyboardFocusManager::heavyweightButtonDownMID;
jmethodID AwtKeyboardFocusManager::markClearGlobalFocusOwnerMID;
jmethodID AwtKeyboardFocusManager::removeLastFocusRequestMID;
jfieldID AwtKeyboardFocusManager::isProxyActive;
jmethodID AwtKeyboardFocusManager::processSynchronousTransfer;
#include <jni.h>
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) {
lFocusState = env->NewLocalRef(gFocusState);
jobject lFocusState = env->NewLocalRef(gFocusState);
env->DeleteGlobalRef(gFocusState);
return lFocusState;
}
return lFocusState;
return NULL;
}
extern "C" {
......@@ -61,53 +51,35 @@ JNIEXPORT void JNICALL
Java_java_awt_KeyboardFocusManager_initIDs
(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 =
env->GetFieldID(keyclass, "isProxyActive", "Z");
jobject peerGlobalRef = env->NewGlobalRef(compPeer);
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;
}
/*
* Class: sun_awt_KeyboardFocusManagerPeerImpl
* Class: sun_awt_windows_WKeyboardFocusManagerPeer
* Method: getNativeFocusOwner
* Signature: ()Ljava/awt/Component;
* Signature: (Lsun/awt/windows/WComponentPeer)
*/
JNIEXPORT jobject JNICALL
Java_sun_awt_KeyboardFocusManagerPeerImpl_getNativeFocusOwner
Java_sun_awt_windows_WKeyboardFocusManagerPeer_getNativeFocusOwner
(JNIEnv *env, jclass cls)
{
TRY;
......@@ -118,12 +90,12 @@ Java_sun_awt_KeyboardFocusManagerPeerImpl_getNativeFocusOwner
}
/*
* Class: sun_awt_KeyboardFocusManagerPeerImpl
* Class: sun_awt_windows_WKeyboardFocusManagerPeer
* Method: getNativeFocusedWindow
* Signature: ()Ljava/awt/Window;
*/
JNIEXPORT jobject JNICALL
Java_sun_awt_KeyboardFocusManagerPeerImpl_getNativeFocusedWindow
Java_sun_awt_windows_WKeyboardFocusManagerPeer_getNativeFocusedWindow
(JNIEnv *env, jclass cls)
{
TRY;
......@@ -132,21 +104,4 @@ Java_sun_awt_KeyboardFocusManagerPeerImpl_getNativeFocusedWindow
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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -24,7 +24,6 @@
*/
#include "awt_List.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Canvas.h"
#include "awt_Dimension.h"
#include "awt_Toolkit.h"
......@@ -154,28 +153,6 @@ done:
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)
{
// don't want to interfere with other controls
......@@ -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
* being a single component inside a focusable Window) won't trigger ActionEvent by
* 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.
* As we consume WM_LBUTONDOWN the list won't trigger ActionEvent by double click.
* We trigger it ourselves. (see also 6240202)
*/
int clickCount = GetClickCount();
if (button == LEFT_BUTTON && clickCount >= 2 && clickCount % 2 == 0 &&
!GetContainer()->IsFocusableWindow())
{
if (button == LEFT_BUTTON && clickCount >= 2 && clickCount % 2 == 0) {
WmCommand(0, GetListHandle(), LBN_DBLCLK);
}
return mrResult;
......@@ -500,67 +471,32 @@ AwtList::WmCtlColor(HDC hDC, HWND hCtrl, UINT ctlColor, HBRUSH& retBrush)
return mrConsume;
}
// Override WmSetFocus and WmKillFocus so that they operate on the List handle
// instead of the wrapper handle. Otherwise, the methods are the same as their
// AwtComponent counterparts.
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;
BOOL AwtList::IsFocusingMouseMessage(MSG *pMsg)
{
return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK;
}
MsgRouting AwtList::WmKillFocus(HWND hWndGotFocus) {
if (sm_focusOwner != NULL && sm_focusOwner == hWndGotFocus) {
return mrConsume;
}
if (sm_focusOwner != GetListHandle()) {
if (sm_focusOwner != NULL) {
if (hWndGotFocus != NULL &&
AwtComponent::GetComponent(hWndGotFocus) != NULL)
{
sm_realFocusOpposite = sm_focusOwner;
MsgRouting AwtList::HandleEvent(MSG *msg, BOOL synthetic)
{
if (IsFocusingMouseMessage(msg)) {
LONG item = static_cast<LONG>(SendListMessage(LB_ITEMFROMPOINT, 0, msg->lParam));
if (item != LB_ERR) {
if (isMultiSelect) {
if (IsItemSelected(item)) {
Deselect(item);
} else {
Select(item);
}
::SendMessage(sm_focusOwner, WM_KILLFOCUS, (WPARAM)hWndGotFocus,
0);
} else {
Select(item);
}
}
delete msg;
return mrConsume;
}
sm_focusOwner = NULL;
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);
if (msg->message == WM_KEYDOWN && msg->wParam == VK_RETURN) {
WmNotify(LBN_DBLCLK);
}
return AwtComponent::HandleEvent(msg, synthetic);
}
......@@ -607,15 +543,6 @@ AwtList::WmNotify(UINT notifyCode)
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;}
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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -97,8 +97,6 @@ public:
}
}
BOOL ActMouseMessage(MSG* pMsg);
// Netscape : Change the font on the list and redraw the
// items nicely.
virtual void SetFont(AwtFont *pFont);
......@@ -116,7 +114,6 @@ public:
MsgRouting WmMouseDown(UINT flags, int x, int y, int button);
MsgRouting WmMouseUp(UINT flags, int x, int y, int button);
MsgRouting WmNotify(UINT notifyCode);
MsgRouting WmKeyDown(UINT vkey, UINT repCnt, UINT flags, BOOL system);
/* for multifont list */
MsgRouting OwnerDrawItem(UINT ctrlId, DRAWITEMSTRUCT& drawInfo);
......@@ -127,8 +124,6 @@ public:
MsgRouting WmCtlColor(HDC hDC, HWND hCtrl, UINT ctlColor,
HBRUSH& retBrush);
MsgRouting WmSetFocus(HWND hWndLostFocus);
MsgRouting WmKillFocus(HWND hWndGotFocus);
MsgRouting HandleEvent(MSG *msg, BOOL synthetic);
......@@ -170,6 +165,8 @@ public:
virtual BOOL InheritsNativeMouseWheelBehavior();
virtual BOOL IsFocusingMouseMessage(MSG *pMsg);
// some methods called on Toolkit thread
static jint _GetMaxWidth(void *param);
static void _UpdateMaxItemWidth(void *param);
......
......@@ -88,7 +88,7 @@ PrintDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
DWORD style = ::GetClassLong(hdlg, GCL_STYLE);
::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
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.
*
* 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) {
DASSERT(!safe_ExceptionOccurred(env));
}
BOOL AwtScrollPane::ActMouseMessage(MSG* pMsg) {
if (!IsFocusingMessage(pMsg->message)) {
return FALSE;
}
return TRUE;
}
MsgRouting
AwtScrollPane::WmNcHitTest(UINT x, UINT y, LRESULT& retVal)
{
......@@ -412,13 +405,10 @@ MsgRouting AwtScrollPane::WmHScroll(UINT scrollCode, UINT pos, HWND hScrollPane)
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)
{
// 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);
}
......
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -65,7 +65,6 @@ public:
virtual void Reshape(int x, int y, int w, int h);
virtual void BeginValidate() {}
virtual void EndValidate() {}
BOOL ActMouseMessage(MSG* pMsg);
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -27,7 +27,6 @@
#include "awt_Scrollbar.h"
#include "awt_Canvas.h"
#include "awt_Window.h"
#include "awt_KeyboardFocusManager.h"
/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
*/
......@@ -61,7 +60,6 @@ AwtScrollbar::AwtScrollbar() {
m_orientation = SB_HORZ;
m_lineIncr = 0;
m_pageIncr = 0;
m_ignoreFocusEvents = FALSE;
m_prevCallback = NULL;
m_prevCallbackPos = 0;
ms_instanceCounter++;
......@@ -221,7 +219,6 @@ AwtScrollbar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
return retValue;
}
MsgRouting
AwtScrollbar::WmNcHitTest(UINT x, UINT y, LRESULT& retVal)
{
......@@ -265,17 +262,10 @@ AwtScrollbar::WmMouseDown(UINT flags, int x, int y, int button)
MsgRouting
AwtScrollbar::HandleEvent(MSG *msg, BOOL synthetic)
{
if (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) {
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();
}
// SCROLLBAR control doesn't cause activation on mouse/key events,
// so we can safely (for synthetic focus) pass them to the system proc.
if (IsFocusingMouseMessage(msg)) {
// Left button press was already routed to default window
// procedure in the WmMouseDown above. Propagating synthetic
// press seems like a bad idea as internal message loop
......@@ -283,54 +273,19 @@ AwtScrollbar::HandleEvent(MSG *msg, BOOL synthetic)
delete msg;
return mrConsume;
}
else {
return AwtComponent::HandleEvent(msg, synthetic);
}
return AwtComponent::HandleEvent(msg, synthetic);
}
// Work around a windows bug descrbed in KB article Q73839. Reset
// focus on scrollbars to update focus indicator. The article advises
// to disable/enable the scrollbar, but simply resetting the focus is
// sufficient.
// to disable/enable the scrollbar.
void
AwtScrollbar::UpdateFocusIndicator()
{
if (IsFocusable()) {
m_ignoreFocusEvents = TRUE;
::SetFocus(NULL);
AwtSetFocus();
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);
// todo: doesn't work
SendMessage((WPARAM)ESB_DISABLE_BOTH);
SendMessage((WPARAM)ESB_ENABLE_BOTH);
}
}
......
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -69,10 +69,6 @@ public:
virtual MsgRouting WmHScroll(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.
virtual MsgRouting WmMouseDown(UINT flags, int x, int y, int button);
virtual MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT& retVal);
......@@ -91,7 +87,6 @@ private:
int m_pageIncr;
// Work around KB Q73839 bug.
BOOL m_ignoreFocusEvents;
void UpdateFocusIndicator();
// 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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -26,9 +26,9 @@
#include "awt_Toolkit.h"
#include "awt_TextArea.h"
#include "awt_TextComponent.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Canvas.h"
#include "awt_Window.h"
#include "awt_Frame.h"
/* 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) {
DASSERT(::IsWindow(::GetParent(hWnd)));
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_CUT:
case WM_COPY:
......@@ -400,7 +393,6 @@ AwtTextArea::EditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
MsgRouting
AwtTextArea::WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos) {
/* Use the system provided edit control class to generate context menu. */
if (m_hEditCtrl == NULL) {
DWORD dwStyle = WS_CHILD;
......@@ -494,22 +486,11 @@ AwtTextArea::WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos) {
VERIFY(::ClientToScreen(GetHWnd(), &p));
}
::SendMessage(m_hEditCtrl, WM_CONTEXTMENU, (WPARAM)m_hEditCtrl,
MAKELPARAM(p.x, p.y));
/*
* After the context menu is dismissed focus is owned by the edit contol.
* Return focus to parent.
*/
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();
}
// The context menu steals focus from the proxy.
// So, set the focus-restore flag up.
SetRestoreFocus(TRUE);
::SendMessage(m_hEditCtrl, WM_CONTEXTMENU, (WPARAM)m_hEditCtrl, MAKELPARAM(p.x, p.y));
SetRestoreFocus(FALSE);
return mrConsume;
}
......@@ -558,20 +539,11 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic)
* By consuming WM_MOUSEMOVE messages we also don't give
* the RichEdit control a chance to recognize a drag gesture
* 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 (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();
}
if (IsFocusingMouseMessage(msg)) {
CHARRANGE cr;
LONG lCurPos = EditGetCharFromPos(msg->pt);
......@@ -717,6 +689,7 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic)
p.x = -1;
p.y = -1;
}
if (!::PostMessage(GetHWnd(), WM_CONTEXTMENU, (WPARAM)GetHWnd(),
MAKELPARAM(p.x, p.y))) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
......@@ -724,6 +697,8 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic)
env->ExceptionDescribe();
env->ExceptionClear();
}
delete msg;
return mrConsume;
} else if (msg->message == WM_MOUSEWHEEL) {
// 4417236: If there is an old version of RichEd32.dll which
// 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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -25,7 +25,6 @@
#include "awt_Toolkit.h"
#include "awt_TextComponent.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Canvas.h"
#include "jni.h"
......@@ -62,9 +61,9 @@ jfieldID AwtTextComponent::canAccessClipboardID;
AwtTextComponent::AwtTextComponent() {
m_synthetic = FALSE;
m_lStartPos = -1;
m_lEndPos = -1;
m_lLastPos = -1;
m_lStartPos = -1;
m_lEndPos = -1;
m_lLastPos = -1;
m_isLFonly = FALSE;
m_EOLchecked = FALSE;
// javaEventsMask = 0; // accessibility support
......@@ -74,10 +73,6 @@ LPCTSTR AwtTextComponent::GetClassName() {
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. */
void AwtTextComponent::SetFont(AwtFont* font)
{
......@@ -143,23 +138,16 @@ AwtTextComponent::WmNotify(UINT notifyCode)
return mrDoDefault;
}
BOOL AwtTextComponent::IsFocusingMouseMessage(MSG *pMsg)
{
return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK;
}
MsgRouting
AwtTextComponent::HandleEvent(MSG *msg, BOOL synthetic)
{
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
* 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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -69,8 +69,6 @@ public:
// called on Toolkit thread from JNI
static jstring _GetText(void *param);
BOOL ActMouseMessage(MSG* pMsg);
void SetFont(AwtFont* font);
/*
......@@ -80,6 +78,8 @@ public:
MsgRouting HandleEvent(MSG *msg, BOOL synthetic);
MsgRouting WmPaste();
virtual BOOL IsFocusingMouseMessage(MSG *pMsg);
/* To be fully implemented in a future release
MsgRouting WmKeyDown(UINT wkey, UINT repCnt,
......@@ -125,7 +125,6 @@ private:
LONG m_lEndPos;
LONG m_lLastPos;
HFONT m_hFont;
//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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -26,7 +26,6 @@
#include "awt_Toolkit.h"
#include "awt_TextField.h"
#include "awt_TextComponent.h"
#include "awt_KeyboardFocusManager.h"
#include "awt_Canvas.h"
/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
......@@ -150,135 +149,130 @@ AwtTextField::HandleEvent(MSG *msg, BOOL synthetic)
* By consuming WM_MOUSEMOVE messages we also don't give
* the RichEdit control a chance to recognize a drag gesture
* and initiate its own drag-n-drop operation.
*
* The workaround also allows us to implement synthetic focus mechanism.
*/
/**
* In non-focusable mode we don't pass mouse messages to native window thus making user unable
* 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.
*/
if (!IsFocusable()) {
if (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) {
if (IsFocusingMouseMessage(msg)) {
CHARRANGE cr;
LONG lCurPos = EditGetCharFromPos(msg->pt);
EditGetSel(cr);
/*
* 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;
LONG lCurPos = EditGetCharFromPos(msg->pt);
EditGetSel(cr);
/*
* 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();
cr.cpMin = lCurPos;
cr.cpMax = lCurPos;
EditSetSel(cr);
}
delete msg;
return mrConsume;
} else if (msg->message == WM_LBUTTONUP) {
/*
* Cleanup the state variables when left mouse button is released.
* 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 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;
if (GetStartSelectionPos() != -1 &&
GetEndSelectionPos() != -1 &&
lCurPos != GetLastSelectionPos()) {
LONG lCurPos = EditGetCharFromPos(msg->pt);
CHARRANGE cr;
cr.cpMin = lCurPos;
cr.cpMax = lCurPos;
EditSetSel(cr);
}
SetLastSelectionPos(lCurPos);
/*
* Cleanup the state variables when left mouse button is released.
* 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);
cr.cpMin = GetStartSelectionPos();
cr.cpMax = GetLastSelectionPos();
delete msg;
return mrConsume;
} else if (msg->message == WM_MOUSEMOVE && (msg->wParam & MK_LBUTTON)) {
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);
}
/*
* 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.
* Okay to use 16-bit position since RichEdit control adjusts
* its scrollbars so that their range is always 16-bit.
*/
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 &&
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;
DASSERT(abs(si.nPos) < 0x8000);
SendMessage(WM_HSCROLL,
MAKEWPARAM(SB_THUMBPOSITION, LOWORD(si.nPos)));
}
delete msg;
return mrConsume;
}
/*
* Store the 'synthetic' parameter so that the WM_PASTE security check
......
......@@ -131,6 +131,11 @@ struct UpdateWindowStruct {
HBITMAP hBitmap;
jint width, height;
};
// Struct for _RequestWindowFocus() method
struct RequestWindowFocusStruct {
jobject component;
jboolean isMouseEventCause;
};
/************************************************************************
* AwtWindow fields
......@@ -395,7 +400,7 @@ AwtWindow* AwtWindow::Create(jobject self, jobject parent)
window->m_isRetainingHierarchyZOrder = TRUE;
}
DWORD style = WS_CLIPCHILDREN | WS_POPUP;
DWORD exStyle = 0;
DWORD exStyle = WS_EX_NOACTIVATE;
if (GetRTL()) {
exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR;
if (GetRTLReadingOrder())
......@@ -886,45 +891,92 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite,
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)
{
jint type;
if (nState != WA_INACTIVE) {
::SetFocus((sm_focusOwner == NULL ||
AwtComponent::GetTopLevelParentForWindow(sm_focusOwner) !=
GetHWnd()) ? NULL : sm_focusOwner);
type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS;
AwtToolkit::GetInstance().
InvokeFunctionLater(BounceActivation, this);
sm_focusedWindow = GetHWnd();
} 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)) {
m_grabbedWindow->Ungrab();
}
type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS;
sm_focusedWindow = NULL;
sm_focusOwner = NULL;
}
SendWindowEvent(type, opposite);
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()
{
return mrDoDefault;
......@@ -948,17 +1000,20 @@ MsgRouting AwtWindow::WmShowWindow(BOOL show, UINT status)
{
/*
* 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
* the owner frame/dialog is natively active.
*/
HWND hwndSelf = GetHWnd();
HWND hwndParent = ::GetParent(hwndSelf);
HWND hwndOwner = ::GetParent(hwndSelf);
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
......@@ -1453,6 +1508,38 @@ void AwtWindow::FlashWindowEx(HWND hWnd, UINT count, DWORD timeout, DWORD flags)
::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)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
......@@ -2173,11 +2260,14 @@ void AwtWindow::_SetFocusableWindow(void *param)
window->m_isFocusableWindow = isFocusableWindow;
if (!window->m_isFocusableWindow) {
LONG isPopup = window->GetStyle() & WS_POPUP;
window->SetStyleEx(window->GetStyleEx() | (isPopup ? 0 : WS_EX_APPWINDOW) | AWT_WS_EX_NOACTIVATE);
} else {
window->SetStyleEx(window->GetStyleEx() & ~WS_EX_APPWINDOW & ~AWT_WS_EX_NOACTIVATE);
// A simple window is permanently set to WS_EX_NOACTIVATE
if (!window->IsSimpleWindow()) {
if (!window->m_isFocusableWindow) {
LONG isPopup = window->GetStyle() & WS_POPUP;
window->SetStyleEx(window->GetStyleEx() | (isPopup ? 0 : WS_EX_APPWINDOW) | WS_EX_NOACTIVATE);
} else {
window->SetStyleEx(window->GetStyleEx() & ~WS_EX_APPWINDOW & ~WS_EX_NOACTIVATE);
}
}
ret:
......@@ -2843,4 +2933,27 @@ void AwtWindow_UpdateWindow(JNIEnv *env, jobject peer,
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" */
......@@ -40,9 +40,6 @@ static LPCTSTR NativeDialogWndProcProp = TEXT("SunAwtNativeDialogWndProcProp");
#define WH_MOUSE_LL 14
#endif
// WS_EX_NOACTIVATE is not defined in the headers we build with
#define AWT_WS_EX_NOACTIVATE 0x08000000L
class AwtFrame;
/************************************************************************
......@@ -157,7 +154,6 @@ public:
* Windows message handler functions
*/
virtual MsgRouting WmActivate(UINT nState, BOOL fMinimized, HWND opposite);
static void BounceActivation(void *self); // used by WmActivate
virtual MsgRouting WmCreate();
virtual MsgRouting WmClose();
virtual MsgRouting WmDestroy();
......@@ -181,6 +177,20 @@ public:
virtual MsgRouting HandleEvent(MSG *msg, BOOL synthetic);
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 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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -194,6 +194,7 @@ enum {
WM_AWT_COMPONENT_SHOW,
WM_AWT_COMPONENT_HIDE,
WM_AWT_COMPONENT_SETFOCUS,
WM_AWT_WINDOW_SETACTIVE,
WM_AWT_LIST_SETMULTISELECT,
WM_AWT_HANDLE_EVENT,
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 {
testFrame.setVisible(true);
Util.waitForIdle(robot);
robot.delay(1000); // additional delay is required
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.
先完成此消息的编辑!
想要评论请 注册