This commit is contained in:
Xiomara Jayasena 2008-03-27 12:09:50 -07:00
commit b1415f3d2d
63 changed files with 4264 additions and 1054 deletions

View File

@ -85,3 +85,13 @@ vpath %.c $(PLATFORM_SRC)/native/$(PKGDIR)/splashscreen
CPPFLAGS += -I$(PLATFORM_SRC)/native/$(PKGDIR)/splashscreen -I$(SHARE_SRC)/native/$(PKGDIR)/splashscreen
CPPFLAGS += -I$(SHARE_SRC)/native/$(PKGDIR)/image/jpeg -I$(SHARE_SRC)/native/java/util/zip/zlib-1.1.3
ifeq ($(PLATFORM), linux)
ifeq ($(ARCH_DATA_MODEL), 64)
# 64-bit gcc has problems compiling MMX instructions.
# Google it for more details. Possibly the newer versions of
# the PNG-library and/or the new compiler will not need this
# option in the future.
CPPFLAGS += -DPNG_NO_MMX_CODE
endif
endif

View File

@ -1,5 +1,5 @@
#
# Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
# Copyright 2002-2008 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
@ -246,7 +246,7 @@ $(SIZES): $(SIZERS)
@if [ "$(DOCOMPARE)$(suffix $@)" = "true.64" ]; then \
$(ECHO) COMPARING $@ and $(STORED_SIZES_TMPL_$(PLATFORM)_$(LIBARCH)); \
$(DIFF) $@ $(STORED_SIZES_TMPL_$(PLATFORM)_$(LIBARCH)); \
fi
fi
$(TEMPDIR)/.gen.wrappers: $(SIZES) $(WRAPPER_GENERATOR_CLASS) $(XLIBTYPES)
$(BOOT_JAVA_CMD) -cp $(WRAPPER_GENERATOR_TEMPDIR) WrapperGenerator \
@ -256,10 +256,11 @@ touch.wrappers: $(TEMPDIR)/.gen.wrappers
$(MKDIR) -p $(TEMPDIR)
$(TOUCH) $(TEMPDIR)/.gen.wrappers
generated.clean:
generated.clean:
$(RM) -r $(WRAPPER_GENERATOR_TEMPDIR)
$(RM) -r $(WRAPPER_GENERATOR_DIR)
$(RM) -r $(GEN_DIR)/*.java
$(RM) -r $(TEMPDIR)/.gen_icons
ifdef OPENJDK
ICONS_PATH_PREFIX=$(PLATFORM_SRC)

View File

@ -634,6 +634,11 @@ public abstract class Component implements ImageObserver, MenuContainer,
*/
private PropertyChangeSupport changeSupport;
private transient final Object changeSupportLock = new Object();
private Object getChangeSupportLock() {
return changeSupportLock;
}
boolean isPacked = false;
/**
@ -935,24 +940,26 @@ public abstract class Component implements ImageObserver, MenuContainer,
*/
public GraphicsConfiguration getGraphicsConfiguration() {
synchronized(getTreeLock()) {
GraphicsConfiguration gc = graphicsConfig;
Component parent = getParent();
while ((gc == null) && (parent != null)) {
gc = parent.getGraphicsConfiguration();
parent = parent.getParent();
if (graphicsConfig != null) {
return graphicsConfig;
} else if (getParent() != null) {
return getParent().getGraphicsConfiguration();
} else {
return null;
}
return gc;
}
}
final GraphicsConfiguration getGraphicsConfiguration_NoClientCode() {
GraphicsConfiguration gc = this.graphicsConfig;
Component par = this.parent;
while ((gc == null) && (par != null)) {
gc = par.getGraphicsConfiguration_NoClientCode();
par = par.parent;
GraphicsConfiguration graphicsConfig = this.graphicsConfig;
Container parent = this.parent;
if (graphicsConfig != null) {
return graphicsConfig;
} else if (parent != null) {
return parent.getGraphicsConfiguration_NoClientCode();
} else {
return null;
}
return gc;
}
/**
@ -4602,7 +4609,8 @@ public abstract class Component implements ImageObserver, MenuContainer,
e.isPopupTrigger(),
e.getScrollType(),
e.getScrollAmount(),
e.getWheelRotation());
e.getWheelRotation(),
e.getPreciseWheelRotation());
((AWTEvent)e).copyPrivateDataInto(newMWE);
// When dispatching a wheel event to
// ancestor, there is no need trying to find descendant
@ -6484,7 +6492,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
// will need some help.
Container parent = this.parent;
if (parent != null && parent.peer instanceof LightweightPeer) {
nativeInLightFixer = new NativeInLightFixer();
relocateComponent();
}
}
invalidate();
@ -6595,10 +6603,6 @@ public abstract class Component implements ImageObserver, MenuContainer,
}
}
if (nativeInLightFixer != null) {
nativeInLightFixer.uninstall();
}
ComponentPeer p = peer;
if (p != null) {
boolean isLightweight = isLightweight();
@ -7836,15 +7840,17 @@ public abstract class Component implements ImageObserver, MenuContainer,
* @see #getPropertyChangeListeners
* @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
*/
public synchronized void addPropertyChangeListener(
public void addPropertyChangeListener(
PropertyChangeListener listener) {
if (listener == null) {
return;
synchronized (getChangeSupportLock()) {
if (listener == null) {
return;
}
if (changeSupport == null) {
changeSupport = new PropertyChangeSupport(this);
}
changeSupport.addPropertyChangeListener(listener);
}
if (changeSupport == null) {
changeSupport = new PropertyChangeSupport(this);
}
changeSupport.addPropertyChangeListener(listener);
}
/**
@ -7860,12 +7866,14 @@ public abstract class Component implements ImageObserver, MenuContainer,
* @see #getPropertyChangeListeners
* @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
*/
public synchronized void removePropertyChangeListener(
public void removePropertyChangeListener(
PropertyChangeListener listener) {
if (listener == null || changeSupport == null) {
return;
synchronized (getChangeSupportLock()) {
if (listener == null || changeSupport == null) {
return;
}
changeSupport.removePropertyChangeListener(listener);
}
changeSupport.removePropertyChangeListener(listener);
}
/**
@ -7882,11 +7890,13 @@ public abstract class Component implements ImageObserver, MenuContainer,
* @see java.beans.PropertyChangeSupport#getPropertyChangeListeners
* @since 1.4
*/
public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
if (changeSupport == null) {
return new PropertyChangeListener[0];
public PropertyChangeListener[] getPropertyChangeListeners() {
synchronized (getChangeSupportLock()) {
if (changeSupport == null) {
return new PropertyChangeListener[0];
}
return changeSupport.getPropertyChangeListeners();
}
return changeSupport.getPropertyChangeListeners();
}
/**
@ -7920,16 +7930,18 @@ public abstract class Component implements ImageObserver, MenuContainer,
* @see #getPropertyChangeListeners(java.lang.String)
* @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
*/
public synchronized void addPropertyChangeListener(
public void addPropertyChangeListener(
String propertyName,
PropertyChangeListener listener) {
if (listener == null) {
return;
synchronized (getChangeSupportLock()) {
if (listener == null) {
return;
}
if (changeSupport == null) {
changeSupport = new PropertyChangeSupport(this);
}
changeSupport.addPropertyChangeListener(propertyName, listener);
}
if (changeSupport == null) {
changeSupport = new PropertyChangeSupport(this);
}
changeSupport.addPropertyChangeListener(propertyName, listener);
}
/**
@ -7948,13 +7960,15 @@ public abstract class Component implements ImageObserver, MenuContainer,
* @see #getPropertyChangeListeners(java.lang.String)
* @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
*/
public synchronized void removePropertyChangeListener(
public void removePropertyChangeListener(
String propertyName,
PropertyChangeListener listener) {
if (listener == null || changeSupport == null) {
return;
synchronized (getChangeSupportLock()) {
if (listener == null || changeSupport == null) {
return;
}
changeSupport.removePropertyChangeListener(propertyName, listener);
}
changeSupport.removePropertyChangeListener(propertyName, listener);
}
/**
@ -7971,12 +7985,14 @@ public abstract class Component implements ImageObserver, MenuContainer,
* @see #getPropertyChangeListeners
* @since 1.4
*/
public synchronized PropertyChangeListener[] getPropertyChangeListeners(
public PropertyChangeListener[] getPropertyChangeListeners(
String propertyName) {
if (changeSupport == null) {
return new PropertyChangeListener[0];
synchronized (getChangeSupportLock()) {
if (changeSupport == null) {
return new PropertyChangeListener[0];
}
return changeSupport.getPropertyChangeListeners(propertyName);
}
return changeSupport.getPropertyChangeListeners(propertyName);
}
/**
@ -7991,7 +8007,10 @@ public abstract class Component implements ImageObserver, MenuContainer,
*/
protected void firePropertyChange(String propertyName,
Object oldValue, Object newValue) {
PropertyChangeSupport changeSupport = this.changeSupport;
PropertyChangeSupport changeSupport;
synchronized (getChangeSupportLock()) {
changeSupport = this.changeSupport;
}
if (changeSupport == null ||
(oldValue != null && newValue != null && oldValue.equals(newValue))) {
return;
@ -8491,8 +8510,6 @@ public abstract class Component implements ImageObserver, MenuContainer,
setComponentOrientation(orientation);
}
transient NativeInLightFixer nativeInLightFixer;
/**
* Checks that this component meets the prerequesites to be focus owner:
* - it is enabled, visible, focusable
@ -8518,188 +8535,25 @@ public abstract class Component implements ImageObserver, MenuContainer,
}
/**
* This odd class is to help out a native component that has been
* embedded in a lightweight component. Moving lightweight
* components around and changing their visibility is not seen
* by the native window system. This is a feature for lightweights,
* but a problem for native components that depend upon the
* lightweights. An instance of this class listens to the lightweight
* parents of an associated native component (the outer class).
*
* @author Timothy Prinzing
* Fix the location of the HW component in a LW container hierarchy.
*/
final class NativeInLightFixer implements ComponentListener, ContainerListener {
NativeInLightFixer() {
lightParents = new Vector();
install(parent);
}
void install(Container parent) {
lightParents.clear();
Container p = parent;
boolean isLwParentsVisible = true;
// stash a reference to the components that are being observed so that
// we can reliably remove ourself as a listener later.
for (; p.peer instanceof LightweightPeer; p = p.parent) {
// register listeners and stash a reference
p.addComponentListener(this);
p.addContainerListener(this);
lightParents.addElement(p);
isLwParentsVisible &= p.isVisible();
final void relocateComponent() {
synchronized (getTreeLock()) {
if (peer == null) {
return;
}
// register with the native host (native parent of associated native)
// to get notified if the top-level lightweight is removed.
nativeHost = p;
p.addContainerListener(this);
// kick start the fixup. Since the event isn't looked at
// we can simulate movement notification.
componentMoved(null);
if (!isLwParentsVisible) {
synchronized (getTreeLock()) {
if (peer != null) {
peer.hide();
}
}
}
}
void uninstall() {
if (nativeHost != null) {
removeReferences();
}
}
// --- ComponentListener -------------------------------------------
/**
* Invoked when one of the lightweight parents has been resized.
* This doesn't change the position of the native child so it
* is ignored.
*/
public void componentResized(ComponentEvent e) {
}
/**
* Invoked when one of the lightweight parents has been moved.
* The native peer must be told of the new position which is
* relative to the native container that is hosting the
* lightweight components.
*/
public void componentMoved(ComponentEvent e) {
synchronized (getTreeLock()) {
int nativeX = x;
int nativeY = y;
for(Component c = parent; (c != null) &&
(c.peer instanceof LightweightPeer);
c = c.parent) {
nativeX += c.x;
nativeY += c.y;
}
if (peer != null) {
peer.setBounds(nativeX, nativeY, width, height,
ComponentPeer.SET_LOCATION);
}
}
}
/**
* Invoked when a lightweight parent component has been
* shown. The associated native component must also be
* shown if it hasn't had an overriding hide done on it.
*/
public void componentShown(ComponentEvent e) {
if (shouldShow()) {
synchronized (getTreeLock()) {
if (peer != null) {
peer.show();
}
}
}
}
/**
* Invoked when one of the lightweight parents become visible.
* Returns true if component and all its lightweight
* parents are visible.
*/
private boolean shouldShow() {
boolean isLwParentsVisible = visible;
for (int i = lightParents.size() - 1;
i >= 0 && isLwParentsVisible;
i--)
int nativeX = x;
int nativeY = y;
for (Component cont = getContainer();
cont != null && cont.isLightweight();
cont = cont.getContainer())
{
isLwParentsVisible &=
((Container) lightParents.elementAt(i)).isVisible();
nativeX += cont.x;
nativeY += cont.y;
}
return isLwParentsVisible;
peer.setBounds(nativeX, nativeY, width, height,
ComponentPeer.SET_LOCATION);
}
/**
* Invoked when component has been hidden.
*/
public void componentHidden(ComponentEvent e) {
if (visible) {
synchronized (getTreeLock()) {
if (peer != null) {
peer.hide();
}
}
}
}
// --- ContainerListener ------------------------------------
/**
* Invoked when a component has been added to a lightweight
* parent. This doesn't effect the native component.
*/
public void componentAdded(ContainerEvent e) {
}
/**
* Invoked when a lightweight parent has been removed.
* This means the services of this listener are no longer
* required and it should remove all references (ie
* registered listeners).
*/
public void componentRemoved(ContainerEvent e) {
Component c = e.getChild();
if (c == Component.this) {
removeReferences();
} else {
int n = lightParents.size();
for (int i = 0; i < n; i++) {
Container p = (Container) lightParents.elementAt(i);
if (p == c) {
removeReferences();
break;
}
}
}
}
/**
* Removes references to this object so it can be
* garbage collected.
*/
void removeReferences() {
int n = lightParents.size();
for (int i = 0; i < n; i++) {
Container c = (Container) lightParents.elementAt(i);
c.removeComponentListener(this);
c.removeContainerListener(this);
}
nativeHost.removeContainerListener(this);
lightParents.clear();
nativeHost = null;
}
Vector lightParents;
Container nativeHost;
}
/**
@ -9452,6 +9306,19 @@ public abstract class Component implements ImageObserver, MenuContainer,
// ************************** MIXING CODE *******************************
/**
* Check whether we can trust the current bounds of the component.
* The return value of false indicates that the container of the
* component is invalid, and therefore needs to be layed out, which would
* probably mean changing the bounds of its children.
* Null-layout of the container or absence of the container mean
* the bounds of the component are final and can be trusted.
*/
private boolean areBoundsValid() {
Container cont = getContainer();
return cont == null || cont.isValid() || cont.getLayout() == null;
}
/**
* Applies the shape to the component
* @param shape Shape to be applied to the component
@ -9475,7 +9342,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
// to modify the object outside of the mixing code.
this.compoundShape = shape;
if (isValid()) {
if (areBoundsValid()) {
Point compAbsolute = getLocationOnWindow();
if (mixingLog.isLoggable(Level.FINER)) {
@ -9602,7 +9469,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
void applyCurrentShape() {
checkTreeLock();
if (!isValid()) {
if (!areBoundsValid()) {
return; // Because applyCompoundShape() ignores such components anyway
}
if (mixingLog.isLoggable(Level.FINE)) {

View File

@ -832,16 +832,8 @@ public class Container extends Component {
}
if (!comp.isLightweight() && isLightweight()) {
// If component is heavyweight and one of the containers is lightweight
// some NativeInLightFixer activity should be performed
if (!curParent.isLightweight()) {
// Moving from heavyweight container to lightweight container - should create NativeInLightFixer
// since addNotify does this
comp.nativeInLightFixer = new NativeInLightFixer();
} else {
// Component already has NativeInLightFixer - just reinstall it
// because hierarchy changed and he needs to rebuild list of parents to listen.
comp.nativeInLightFixer.install(this);
}
// the location of the component should be fixed.
comp.relocateComponent();
}
}
}
@ -2267,53 +2259,56 @@ public class Container extends Component {
EventTargetFilter filter,
boolean searchHeavyweightChildren,
boolean searchHeavyweightDescendants) {
int ncomponents = this.ncomponents;
Component component[] = this.component;
synchronized (getTreeLock()) {
int ncomponents = this.ncomponents;
Component component[] = this.component;
for (int i = 0 ; i < ncomponents ; i++) {
Component comp = component[i];
if (comp != null && comp.visible &&
((!searchHeavyweightChildren &&
comp.peer instanceof LightweightPeer) ||
(searchHeavyweightChildren &&
!(comp.peer instanceof LightweightPeer))) &&
comp.contains(x - comp.x, y - comp.y)) {
for (int i = 0 ; i < ncomponents ; i++) {
Component comp = component[i];
if (comp != null && comp.visible &&
((!searchHeavyweightChildren &&
comp.peer instanceof LightweightPeer) ||
(searchHeavyweightChildren &&
!(comp.peer instanceof LightweightPeer))) &&
comp.contains(x - comp.x, y - comp.y)) {
// found a component that intersects the point, see if there is
// a deeper possibility.
if (comp instanceof Container) {
Container child = (Container) comp;
Component deeper = child.getMouseEventTarget(x - child.x,
y - child.y,
includeSelf,
filter,
searchHeavyweightDescendants);
if (deeper != null) {
return deeper;
}
} else {
if (filter.accept(comp)) {
// there isn't a deeper target, but this component is a
// target
return comp;
// found a component that intersects the point, see if there
// is a deeper possibility.
if (comp instanceof Container) {
Container child = (Container) comp;
Component deeper = child.getMouseEventTarget(
x - child.x,
y - child.y,
includeSelf,
filter,
searchHeavyweightDescendants);
if (deeper != null) {
return deeper;
}
} else {
if (filter.accept(comp)) {
// there isn't a deeper target, but this component
// is a target
return comp;
}
}
}
}
boolean isPeerOK;
boolean isMouseOverMe;
isPeerOK = (peer instanceof LightweightPeer) || includeSelf;
isMouseOverMe = contains(x,y);
// didn't find a child target, return this component if it's
// a possible target
if (isMouseOverMe && isPeerOK && filter.accept(this)) {
return this;
}
// no possible target
return null;
}
boolean isPeerOK;
boolean isMouseOverMe;
isPeerOK = (peer instanceof LightweightPeer) || includeSelf;
isMouseOverMe = contains(x,y);
// didn't find a child target, return this component if it's a possible
// target
if (isMouseOverMe && isPeerOK && filter.accept(this)) {
return this;
}
// no possible target
return null;
}
static interface EventTargetFilter {
@ -3950,6 +3945,83 @@ public class Container extends Component {
}
}
private void recursiveShowHeavyweightChildren() {
if (!hasHeavyweightDescendants() || !isVisible()) {
return;
}
for (int index = 0; index < getComponentCount(); index++) {
Component comp = getComponent(index);
if (comp.isLightweight()) {
if (comp instanceof Container) {
((Container)comp).recursiveShowHeavyweightChildren();
}
} else {
if (comp.isVisible()) {
ComponentPeer peer = comp.getPeer();
if (peer != null) {
peer.show();
}
}
}
}
}
private void recursiveHideHeavyweightChildren() {
if (!hasHeavyweightDescendants()) {
return;
}
for (int index = 0; index < getComponentCount(); index++) {
Component comp = getComponent(index);
if (comp.isLightweight()) {
if (comp instanceof Container) {
((Container)comp).recursiveHideHeavyweightChildren();
}
} else {
if (comp.isVisible()) {
ComponentPeer peer = comp.getPeer();
if (peer != null) {
peer.hide();
}
}
}
}
}
private void recursiveRelocateHeavyweightChildren(Point origin) {
for (int index = 0; index < getComponentCount(); index++) {
Component comp = getComponent(index);
if (comp.isLightweight()) {
if (comp instanceof Container &&
((Container)comp).hasHeavyweightDescendants())
{
final Point newOrigin = new Point(origin);
newOrigin.translate(comp.getX(), comp.getY());
((Container)comp).recursiveRelocateHeavyweightChildren(newOrigin);
}
} else {
ComponentPeer peer = comp.getPeer();
if (peer != null) {
peer.setBounds(origin.x + comp.getX(), origin.y + comp.getY(),
comp.getWidth(), comp.getHeight(),
ComponentPeer.SET_LOCATION);
}
}
}
}
/*
* Consider the heavyweight container hides or shows the HW descendants
* automatically. Therefore we care of LW containers' visibility only.
*/
private boolean isRecursivelyVisibleUpToHeavyweightContainer() {
if (!isLightweight()) {
return true;
}
return isVisible() && (getContainer() == null ||
getContainer().isRecursivelyVisibleUpToHeavyweightContainer());
}
@Override
void mixOnShowing() {
synchronized (getTreeLock()) {
if (mixingLog.isLoggable(Level.FINE)) {
@ -3958,6 +4030,10 @@ public class Container extends Component {
boolean isLightweight = isLightweight();
if (isLightweight && isRecursivelyVisibleUpToHeavyweightContainer()) {
recursiveShowHeavyweightChildren();
}
if (!isLightweight || (isLightweight && hasHeavyweightDescendants())) {
recursiveApplyCurrentShape();
}
@ -3966,6 +4042,42 @@ public class Container extends Component {
}
}
@Override
void mixOnHiding(boolean isLightweight) {
synchronized (getTreeLock()) {
if (mixingLog.isLoggable(Level.FINE)) {
mixingLog.fine("this = " + this +
"; isLightweight=" + isLightweight);
}
if (isLightweight) {
recursiveHideHeavyweightChildren();
}
super.mixOnHiding(isLightweight);
}
}
@Override
void mixOnReshaping() {
synchronized (getTreeLock()) {
if (mixingLog.isLoggable(Level.FINE)) {
mixingLog.fine("this = " + this);
}
if (isLightweight() && hasHeavyweightDescendants()) {
final Point origin = new Point(getX(), getY());
for (Container cont = getContainer();
cont != null && cont.isLightweight();
cont = cont.getContainer())
{
origin.translate(cont.getX(), cont.getY());
}
recursiveRelocateHeavyweightChildren(origin);
}
super.mixOnReshaping();
}
}
@Override
void mixOnZOrderChanging(int oldZorder, int newZorder) {
synchronized (getTreeLock()) {
if (mixingLog.isLoggable(Level.FINE)) {
@ -4431,7 +4543,8 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
e.isPopupTrigger(),
((MouseWheelEvent)e).getScrollType(),
((MouseWheelEvent)e).getScrollAmount(),
((MouseWheelEvent)e).getWheelRotation());
((MouseWheelEvent)e).getWheelRotation(),
((MouseWheelEvent)e).getPreciseWheelRotation());
}
else {
retargeted = new MouseEvent(target,

View File

@ -154,7 +154,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
private boolean doRestoreFocus(Component toFocus, Component vetoedComponent,
boolean clearOnFailure)
{
if (toFocus.isShowing() && toFocus.isFocusable() &&
if (toFocus != vetoedComponent && toFocus.isShowing() && toFocus.isFocusable() &&
toFocus.requestFocus(false, CausedFocusEvent.Cause.ROLLBACK)) {
return true;
} else {

View File

@ -1,5 +1,5 @@
/*
* Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1995-2008 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 @@
*/
package java.awt;
import java.applet.Applet;
import java.awt.event.*;
import java.awt.im.InputContext;
import java.awt.image.BufferStrategy;
@ -355,18 +354,21 @@ public class Window extends Container implements Accessible {
static class WindowDisposerRecord implements sun.java2d.DisposerRecord {
final WeakReference<Window> owner;
final WeakReference weakThis;
final AppContext context;
final WeakReference<AppContext> context;
WindowDisposerRecord(AppContext context, Window victim) {
owner = new WeakReference<Window>(victim.getOwner());
weakThis = victim.weakThis;
this.context = context;
this.context = new WeakReference<AppContext>(context);
}
public void dispose() {
Window parent = owner.get();
if (parent != null) {
parent.removeOwnedWindow(weakThis);
}
Window.removeFromWindowList(context, weakThis);
AppContext ac = context.get();
if (null != ac) {
Window.removeFromWindowList(ac, weakThis);
}
}
}
@ -824,7 +826,10 @@ public class Window extends Container implements Accessible {
static private final AtomicBoolean
beforeFirstWindowShown = new AtomicBoolean(true);
static final void closeSplashScreen() {
final void closeSplashScreen() {
if (isTrayIconWindow) {
return;
}
if (beforeFirstWindowShown.getAndSet(false)) {
SunToolkit.closeSplashScreen();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1997-2008 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
@ -49,7 +49,6 @@ import java.util.WeakHashMap;
import sun.awt.datatransfer.DataTransferer;
/**
* The SystemFlavorMap is a configurable map between "natives" (Strings), which
* correspond to platform-specific data formats, and "flavors" (DataFlavors),
@ -117,15 +116,50 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
/**
* Maps native Strings to Lists of DataFlavors (or base type Strings for
* text DataFlavors).
* Do not use the field directly, use getNativeToFlavor() instead.
*/
private Map nativeToFlavor = new HashMap();
/**
* Accessor to nativeToFlavor map. Since we use lazy initialization we must
* use this accessor instead of direct access to the field which may not be
* initialized yet. This method will initialize the field if needed.
*
* @return nativeToFlavor
*/
private Map getNativeToFlavor() {
if (!isMapInitialized) {
initSystemFlavorMap();
}
return nativeToFlavor;
}
/**
* Maps DataFlavors (or base type Strings for text DataFlavors) to Lists of
* native Strings.
* Do not use the field directly, use getFlavorToNative() instead.
*/
private Map flavorToNative = new HashMap();
/**
* Accessor to flavorToNative map. Since we use lazy initialization we must
* use this accessor instead of direct access to the field which may not be
* initialized yet. This method will initialize the field if needed.
*
* @return flavorToNative
*/
private synchronized Map getFlavorToNative() {
if (!isMapInitialized) {
initSystemFlavorMap();
}
return flavorToNative;
}
/**
* Shows if the object has been initialized.
*/
private boolean isMapInitialized = false;
/**
* Caches the result of getNativesForFlavor(). Maps DataFlavors to
* SoftReferences which reference Lists of String natives.
@ -169,15 +203,24 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
return fm;
}
/**
* Constructs a SystemFlavorMap by reading flavormap.properties and
* AWT.DnD.flavorMapFileURL.
*/
private SystemFlavorMap() {
BufferedReader flavormapDotProperties = (BufferedReader)
}
/**
* Initializes a SystemFlavorMap by reading flavormap.properties and
* AWT.DnD.flavorMapFileURL.
* For thread-safety must be called under lock on this.
*/
private void initSystemFlavorMap() {
if (isMapInitialized) {
return;
}
isMapInitialized = true;
BufferedReader flavormapDotProperties =
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
new java.security.PrivilegedAction<BufferedReader>() {
public BufferedReader run() {
String fileName =
System.getProperty("java.home") +
File.separator +
@ -197,12 +240,11 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
}
});
BufferedReader flavormapURL = (BufferedReader)
BufferedReader flavormapURL =
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
String url = Toolkit.getDefaultToolkit().getProperty
("AWT.DnD.flavorMapFileURL", null);
new java.security.PrivilegedAction<BufferedReader>() {
public BufferedReader run() {
String url = Toolkit.getProperty("AWT.DnD.flavorMapFileURL", null);
if (url == null) {
return null;
@ -237,7 +279,6 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
}
}
}
/**
* Copied code from java.util.Properties. Parsing the data ourselves is the
* only way to handle duplicate keys and values.
@ -388,11 +429,11 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
// For text/* flavors, store mappings in separate maps to
// enable dynamic mapping generation at a run-time.
if ("text".equals(flavor.getPrimaryType())) {
store(value, key, flavorToNative);
store(key, value, nativeToFlavor);
store(value, key, getFlavorToNative());
store(key, value, getNativeToFlavor());
} else {
store(flavor, key, flavorToNative);
store(key, flavor, nativeToFlavor);
store(flavor, key, getFlavorToNative());
store(key, flavor, getNativeToFlavor());
}
}
}
@ -494,7 +535,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
* only if the specified native is encoded as a Java MIME type.
*/
private List nativeToFlavorLookup(String nat) {
List flavors = (List)nativeToFlavor.get(nat);
List flavors = (List)getNativeToFlavor().get(nat);
if (nat != null && !disabledMappingGenerationKeys.contains(nat)) {
DataTransferer transferer = DataTransferer.getInstance();
@ -530,15 +571,15 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
if (flavor != null) {
flavors = new ArrayList(1);
nativeToFlavor.put(nat, flavors);
getNativeToFlavor().put(nat, flavors);
flavors.add(flavor);
getFlavorsForNativeCache.remove(nat);
getFlavorsForNativeCache.remove(null);
List natives = (List)flavorToNative.get(flavor);
List natives = (List)getFlavorToNative().get(flavor);
if (natives == null) {
natives = new ArrayList(1);
flavorToNative.put(flavor, natives);
getFlavorToNative().put(flavor, natives);
}
natives.add(nat);
getNativesForFlavorCache.remove(flavor);
@ -559,7 +600,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
*/
private List flavorToNativeLookup(final DataFlavor flav,
final boolean synthesize) {
List natives = (List)flavorToNative.get(flav);
List natives = (List)getFlavorToNative().get(flav);
if (flav != null && !disabledMappingGenerationKeys.contains(flav)) {
DataTransferer transferer = DataTransferer.getInstance();
@ -584,15 +625,15 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
if (synthesize) {
String encoded = encodeDataFlavor(flav);
natives = new ArrayList(1);
flavorToNative.put(flav, natives);
getFlavorToNative().put(flav, natives);
natives.add(encoded);
getNativesForFlavorCache.remove(flav);
getNativesForFlavorCache.remove(null);
List flavors = (List)nativeToFlavor.get(encoded);
List flavors = (List)getNativeToFlavor().get(encoded);
if (flavors == null) {
flavors = new ArrayList(1);
nativeToFlavor.put(encoded, flavors);
getNativeToFlavor().put(encoded, flavors);
}
flavors.add(flav);
getFlavorsForNativeCache.remove(encoded);
@ -645,7 +686,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
}
if (flav == null) {
retval = new ArrayList(nativeToFlavor.keySet());
retval = new ArrayList(getNativeToFlavor().keySet());
} else if (disabledMappingGenerationKeys.contains(flav)) {
// In this case we shouldn't synthesize a native for this flavor,
// since its mappings were explicitly specified.
@ -655,7 +696,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
// For text/* flavors, flavor-to-native mappings specified in
// flavormap.properties are stored per flavor's base type.
if ("text".equals(flav.getPrimaryType())) {
retval = (List)flavorToNative.get(flav.mimeType.getBaseType());
retval = (List)getFlavorToNative().get(flav.mimeType.getBaseType());
if (retval != null) {
// To prevent the List stored in the map from modification.
retval = new ArrayList(retval);
@ -663,7 +704,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
}
// Also include text/plain natives, but don't duplicate Strings
List textPlainList = (List)flavorToNative.get(TEXT_PLAIN_BASE_TYPE);
List textPlainList = (List)getFlavorToNative().get(TEXT_PLAIN_BASE_TYPE);
if (textPlainList != null && !textPlainList.isEmpty()) {
// To prevent the List stored in the map from modification.
@ -699,7 +740,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
}
}
} else if (DataTransferer.isFlavorNoncharsetTextType(flav)) {
retval = (List)flavorToNative.get(flav.mimeType.getBaseType());
retval = (List)getFlavorToNative().get(flav.mimeType.getBaseType());
if (retval == null || retval.isEmpty()) {
retval = flavorToNativeLookup(flav, SYNTHESIZE_IF_NOT_FOUND);
@ -1025,10 +1066,10 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
throw new NullPointerException("null arguments not permitted");
}
List natives = (List)flavorToNative.get(flav);
List natives = (List)getFlavorToNative().get(flav);
if (natives == null) {
natives = new ArrayList(1);
flavorToNative.put(flav, natives);
getFlavorToNative().put(flav, natives);
} else if (natives.contains(nat)) {
return;
}
@ -1071,7 +1112,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
throw new NullPointerException("null arguments not permitted");
}
flavorToNative.remove(flav);
getFlavorToNative().remove(flav);
for (int i = 0; i < natives.length; i++) {
addUnencodedNativeForFlavor(flav, natives[i]);
}
@ -1105,10 +1146,10 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
throw new NullPointerException("null arguments not permitted");
}
List flavors = (List)nativeToFlavor.get(nat);
List flavors = (List)getNativeToFlavor().get(nat);
if (flavors == null) {
flavors = new ArrayList(1);
nativeToFlavor.put(nat, flavors);
getNativeToFlavor().put(nat, flavors);
} else if (flavors.contains(flav)) {
return;
}
@ -1150,7 +1191,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
throw new NullPointerException("null arguments not permitted");
}
nativeToFlavor.remove(nat);
getNativeToFlavor().remove(nat);
for (int i = 0; i < flavors.length; i++) {
addFlavorForUnencodedNative(nat, flavors[i]);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1997-2008 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
@ -110,7 +110,11 @@ public class DropTarget implements DropTargetListener, Serializable {
setActive(act);
}
if (fm != null) flavorMap = fm;
if (fm != null) {
flavorMap = fm;
} else {
flavorMap = SystemFlavorMap.getDefaultFlavorMap();
}
}
/**
@ -850,5 +854,5 @@ public class DropTarget implements DropTargetListener, Serializable {
* The FlavorMap
*/
private transient FlavorMap flavorMap = SystemFlavorMap.getDefaultFlavorMap();
private transient FlavorMap flavorMap;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2000-2007 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
@ -74,6 +74,19 @@ import java.awt.Component;
* methods for conforming to the underlying platform settings. These
* platform settings can be changed at any time by the user. MouseWheelEvents
* reflect the most recent settings.
* <P>
* The <code>MouseWheelEvent</code> class includes methods for
* getting the number of "clicks" by which the mouse wheel is rotated.
* The {@link #getWheelRotation} method returns the integer number
* of "clicks" corresponding to the number of notches by which the wheel was
* rotated. In addition to this method, the <code>MouseWheelEvent</code>
* class provides the {@link #getPreciseWheelRotation} method which returns
* a double number of "clicks" in case a partial rotation occurred.
* The {@link #getPreciseWheelRotation} method is useful if a mouse supports
* a high-resolution wheel, such as a freely rotating wheel with no
* notches. Applications can benefit by using this method to process
* mouse wheel events more precisely, and thus, making visual perception
* smoother.
*
* @author Brent Christian
* @see MouseWheelListener
@ -131,6 +144,13 @@ public class MouseWheelEvent extends MouseEvent {
*/
int wheelRotation;
/**
* Indicates how far the mouse wheel was rotated.
*
* @see #getPreciseWheelRotation
*/
double preciseWheelRotation;
/*
* serialVersionUID
*/
@ -165,8 +185,8 @@ public class MouseWheelEvent extends MouseEvent {
* <code>WHEEL_BLOCK_SCROLL</code>
* @param scrollAmount for scrollType <code>WHEEL_UNIT_SCROLL</code>,
* the number of units to be scrolled
* @param wheelRotation the amount that the mouse wheel was rotated (the
* number of "clicks")
* @param wheelRotation the integer number of "clicks" by which the mouse
* wheel was rotated
*
* @throws IllegalArgumentException if <code>source</code> is null
* @see MouseEvent#MouseEvent(java.awt.Component, int, long, int, int, int, int, boolean)
@ -211,8 +231,8 @@ public class MouseWheelEvent extends MouseEvent {
* <code>WHEEL_BLOCK_SCROLL</code>
* @param scrollAmount for scrollType <code>WHEEL_UNIT_SCROLL</code>,
* the number of units to be scrolled
* @param wheelRotation the amount that the mouse wheel was rotated (the
* number of "clicks")
* @param wheelRotation the integer number of "clicks" by which the mouse
* wheel was rotated
*
* @throws IllegalArgumentException if <code>source</code> is null
* @see MouseEvent#MouseEvent(java.awt.Component, int, long, int, int, int, int, boolean)
@ -223,12 +243,68 @@ public class MouseWheelEvent extends MouseEvent {
int x, int y, int xAbs, int yAbs, int clickCount, boolean popupTrigger,
int scrollType, int scrollAmount, int wheelRotation) {
this(source, id, when, modifiers, x, y, xAbs, yAbs, clickCount, popupTrigger,
scrollType, scrollAmount, wheelRotation, wheelRotation);
}
/**
* Constructs a <code>MouseWheelEvent</code> object with the specified
* source component, type, modifiers, coordinates, absolute coordinates,
* scroll type, scroll amount, and wheel rotation.
* <p>Note that passing in an invalid <code>id</code> parameter results
* in unspecified behavior. This method throws an
* <code>IllegalArgumentException</code> if <code>source</code> equals
* <code>null</code>.
* <p>Even if inconsistent values for relative and absolute coordinates
* are passed to the constructor, a <code>MouseWheelEvent</code> instance
* is still created and no exception is thrown.
*
* @param source the <code>Component</code> that originated the event
* @param id the integer value that identifies the event
* @param when a long value that gives the time when the event occurred
* @param modifiers the modifier keys down during event
* (shift, ctrl, alt, meta)
* @param x the horizontal <code>x</code> coordinate for the
* mouse location
* @param y the vertical <code>y</code> coordinate for the
* mouse location
* @param xAbs the absolute horizontal <code>x</code> coordinate for
* the mouse location
* @param yAbs the absolute vertical <code>y</code> coordinate for
* the mouse location
* @param clickCount the number of mouse clicks associated with the event
* @param popupTrigger a boolean value, <code>true</code> if this event is a trigger
* for a popup-menu
* @param scrollType the type of scrolling which should take place in
* response to this event; valid values are
* <code>WHEEL_UNIT_SCROLL</code> and
* <code>WHEEL_BLOCK_SCROLL</code>
* @param scrollAmount for scrollType <code>WHEEL_UNIT_SCROLL</code>,
* the number of units to be scrolled
* @param wheelRotation the integer number of "clicks" by which the mouse wheel
* was rotated
* @param preciseWheelRotation the double number of "clicks" by which the mouse wheel
* was rotated
*
* @throws IllegalArgumentException if <code>source</code> is null
* @see MouseEvent#MouseEvent(java.awt.Component, int, long, int, int, int, int, boolean)
* @see MouseEvent#MouseEvent(java.awt.Component, int, long, int, int, int, int, int, int, boolean, int)
* @since 1.7
*/
public MouseWheelEvent (Component source, int id, long when, int modifiers,
int x, int y, int xAbs, int yAbs, int clickCount, boolean popupTrigger,
int scrollType, int scrollAmount, int wheelRotation, double preciseWheelRotation) {
super(source, id, when, modifiers, x, y, xAbs, yAbs, clickCount,
popupTrigger, MouseEvent.NOBUTTON);
this.scrollType = scrollType;
this.scrollAmount = scrollAmount;
this.wheelRotation = wheelRotation;
this.preciseWheelRotation = preciseWheelRotation;
}
/**
@ -267,16 +343,34 @@ public class MouseWheelEvent extends MouseEvent {
}
/**
* Returns the number of "clicks" the mouse wheel was rotated.
* Returns the number of "clicks" the mouse wheel was rotated, as an integer.
* A partial rotation may occur if the mouse supports a high-resolution wheel.
* In this case, the method returns zero until a full "click" has been accumulated.
*
* @return negative values if the mouse wheel was rotated up/away from
* the user, and positive values if the mouse wheel was rotated down/
* towards the user
* @see #getPreciseWheelRotation
*/
public int getWheelRotation() {
return wheelRotation;
}
/**
* Returns the number of "clicks" the mouse wheel was rotated, as a double.
* A partial rotation may occur if the mouse supports a high-resolution wheel.
* In this case, the return value will include a fractional "click".
*
* @return negative values if the mouse wheel was rotated up or away from
* the user, and positive values if the mouse wheel was rotated down or
* towards the user
* @see #getWheelRotation
* @since 1.7
*/
public double getPreciseWheelRotation() {
return preciseWheelRotation;
}
/**
* This is a convenience method to aid in the implementation of
* the common-case MouseWheelListener - to scroll a ScrollPane or
@ -348,6 +442,6 @@ public class MouseWheelEvent extends MouseEvent {
}
return super.paramString()+",scrollType="+scrollTypeStr+
",scrollAmount="+getScrollAmount()+",wheelRotation="+
getWheelRotation();
getWheelRotation()+",preciseWheelRotation="+getPreciseWheelRotation();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1998-2008 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
@ -40,6 +40,8 @@ import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
@ -126,6 +128,7 @@ import java.beans.PropertyChangeListener;
* @author Fred Ecks
*/
public final class AppContext {
private static final Logger log = Logger.getLogger("sun.awt.AppContext");
/* Since the contents of an AppContext are unique to each Java
* session, this class should never be serialized. */
@ -143,13 +146,15 @@ public final class AppContext {
* Returns a set containing all <code>AppContext</code>s.
*/
public static Set<AppContext> getAppContexts() {
return new HashSet<AppContext>(threadGroup2appContext.values());
synchronized (threadGroup2appContext) {
return new HashSet<AppContext>(threadGroup2appContext.values());
}
}
/* The main "system" AppContext, used by everything not otherwise
contained in another AppContext.
*/
private static AppContext mainAppContext = null;
private static volatile AppContext mainAppContext = null;
/*
* The hash map associated with this AppContext. A private delegate
@ -174,31 +179,30 @@ public final class AppContext {
public static final String DISPOSED_PROPERTY_NAME = "disposed";
public static final String GUI_DISPOSED = "guidisposed";
private boolean isDisposed = false; // true if AppContext is disposed
private volatile boolean isDisposed = false; // true if AppContext is disposed
public boolean isDisposed() {
return isDisposed;
}
static {
// On the main Thread, we get the ThreadGroup, make a corresponding
// AppContext, and instantiate the Java EventQueue. This way, legacy
// code is unaffected by the move to multiple AppContext ability.
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
ThreadGroup currentThreadGroup =
Thread.currentThread().getThreadGroup();
ThreadGroup parentThreadGroup = currentThreadGroup.getParent();
while (parentThreadGroup != null) {
// Find the root ThreadGroup to construct our main AppContext
currentThreadGroup = parentThreadGroup;
parentThreadGroup = currentThreadGroup.getParent();
public Object run() {
ThreadGroup currentThreadGroup =
Thread.currentThread().getThreadGroup();
ThreadGroup parentThreadGroup = currentThreadGroup.getParent();
while (parentThreadGroup != null) {
// Find the root ThreadGroup to construct our main AppContext
currentThreadGroup = parentThreadGroup;
parentThreadGroup = currentThreadGroup.getParent();
}
mainAppContext = new AppContext(currentThreadGroup);
numAppContexts = 1;
return mainAppContext;
}
mainAppContext = new AppContext(currentThreadGroup);
numAppContexts = 1;
return mainAppContext;
}
});
}
@ -209,7 +213,7 @@ public final class AppContext {
* number is 1. If so, it returns the sole AppContext without
* checking Thread.currentThread().
*/
private static int numAppContexts;
private static volatile int numAppContexts;
/*
* The context ClassLoader that was used to create this AppContext.
@ -236,14 +240,15 @@ public final class AppContext {
threadGroup2appContext.put(threadGroup, this);
this.contextClassLoader =
(ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
}
private static MostRecentThreadAppContext mostRecentThreadAppContext = null;
private static final ThreadLocal<AppContext> threadAppContext =
new ThreadLocal<AppContext>();
/**
* Returns the appropriate AppContext for the caller,
@ -260,59 +265,46 @@ public final class AppContext {
if (numAppContexts == 1) // If there's only one system-wide,
return mainAppContext; // return the main system AppContext.
final Thread currentThread = Thread.currentThread();
AppContext appContext = threadAppContext.get();
AppContext appContext = null;
if (null == appContext) {
appContext = AccessController.doPrivileged(new PrivilegedAction<AppContext>()
{
public AppContext run() {
// Get the current ThreadGroup, and look for it and its
// parents in the hash from ThreadGroup to AppContext --
// it should be found, because we use createNewContext()
// when new AppContext objects are created.
ThreadGroup currentThreadGroup = Thread.currentThread().getThreadGroup();
ThreadGroup threadGroup = currentThreadGroup;
AppContext context = threadGroup2appContext.get(threadGroup);
while (context == null) {
threadGroup = threadGroup.getParent();
if (threadGroup == null) {
// If we get here, we're running under a ThreadGroup that
// has no AppContext associated with it. This should never
// happen, because createNewContext() should be used by the
// toolkit to create the ThreadGroup that everything runs
// under.
throw new RuntimeException("Invalid ThreadGroup");
}
context = threadGroup2appContext.get(threadGroup);
}
// In case we did anything in the above while loop, we add
// all the intermediate ThreadGroups to threadGroup2appContext
// so we won't spin again.
for (ThreadGroup tg = currentThreadGroup; tg != threadGroup; tg = tg.getParent()) {
threadGroup2appContext.put(tg, context);
}
// Now we're done, so we cache the latest key/value pair.
// (we do this before checking with any AWTSecurityManager, so if
// this Thread equates with the main AppContext in the cache, it
// still will)
threadAppContext.set(context);
// Note: this most recent Thread/AppContext caching is thread-hot.
// A simple test using SwingSet found that 96.8% of lookups
// were matched using the most recent Thread/AppContext. By
// instantiating a simple MostRecentThreadAppContext object on
// cache misses, the cache hits can be processed without
// synchronization.
MostRecentThreadAppContext recent = mostRecentThreadAppContext;
if ((recent != null) && (recent.thread == currentThread)) {
appContext = recent.appContext; // Cache hit
} else {
appContext = (AppContext)AccessController.doPrivileged(
new PrivilegedAction() {
public Object run() {
// Get the current ThreadGroup, and look for it and its
// parents in the hash from ThreadGroup to AppContext --
// it should be found, because we use createNewContext()
// when new AppContext objects are created.
ThreadGroup currentThreadGroup = currentThread.getThreadGroup();
ThreadGroup threadGroup = currentThreadGroup;
AppContext context = threadGroup2appContext.get(threadGroup);
while (context == null) {
threadGroup = threadGroup.getParent();
if (threadGroup == null) {
// If we get here, we're running under a ThreadGroup that
// has no AppContext associated with it. This should never
// happen, because createNewContext() should be used by the
// toolkit to create the ThreadGroup that everything runs
// under.
throw new RuntimeException("Invalid ThreadGroup");
return context;
}
context = threadGroup2appContext.get(threadGroup);
}
// In case we did anything in the above while loop, we add
// all the intermediate ThreadGroups to threadGroup2appContext
// so we won't spin again.
for (ThreadGroup tg = currentThreadGroup; tg != threadGroup; tg = tg.getParent()) {
threadGroup2appContext.put(tg, context);
}
// Now we're done, so we cache the latest key/value pair.
// (we do this before checking with any AWTSecurityManager, so if
// this Thread equates with the main AppContext in the cache, it
// still will)
mostRecentThreadAppContext =
new MostRecentThreadAppContext(currentThread, context);
return context;
}
});
});
}
if (appContext == mainAppContext) {
@ -321,9 +313,9 @@ public final class AppContext {
// allow it to choose the AppContext to return.
SecurityManager securityManager = System.getSecurityManager();
if ((securityManager != null) &&
(securityManager instanceof AWTSecurityManager)) {
AWTSecurityManager awtSecMgr =
(AWTSecurityManager)securityManager;
(securityManager instanceof AWTSecurityManager))
{
AWTSecurityManager awtSecMgr = (AWTSecurityManager)securityManager;
AppContext secAppContext = awtSecMgr.getAppContext();
if (secAppContext != null) {
appContext = secAppContext; // Return what we're told
@ -385,7 +377,13 @@ public final class AppContext {
public void run() {
Window[] windowsToDispose = Window.getOwnerlessWindows();
for (Window w : windowsToDispose) {
w.dispose();
try {
w.dispose();
} catch (Throwable t) {
if (log.isLoggable(Level.FINER)) {
log.log(Level.FINER, "exception occured while disposing app context", t);
}
}
}
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
@ -444,7 +442,7 @@ public final class AppContext {
// Threads in the ThreadGroup to exit.
long startTime = System.currentTimeMillis();
long endTime = startTime + (long)THREAD_INTERRUPT_TIMEOUT;
long endTime = startTime + THREAD_INTERRUPT_TIMEOUT;
while ((this.threadGroup.activeCount() > 0) &&
(System.currentTimeMillis() < endTime)) {
try {
@ -459,7 +457,7 @@ public final class AppContext {
// Threads in the ThreadGroup to die.
startTime = System.currentTimeMillis();
endTime = startTime + (long)THREAD_INTERRUPT_TIMEOUT;
endTime = startTime + THREAD_INTERRUPT_TIMEOUT;
while ((this.threadGroup.activeCount() > 0) &&
(System.currentTimeMillis() < endTime)) {
try {
@ -478,10 +476,7 @@ public final class AppContext {
}
threadGroup2appContext.remove(this.threadGroup);
MostRecentThreadAppContext recent = mostRecentThreadAppContext;
if ((recent != null) && (recent.appContext == this))
mostRecentThreadAppContext = null;
// If the "most recent" points to this, clear it for GC
threadAppContext.set(null);
// Finally, we destroy the ThreadGroup entirely.
try {
@ -664,6 +659,7 @@ public final class AppContext {
* Returns a string representation of this AppContext.
* @since 1.2
*/
@Override
public String toString() {
return getClass().getName() + "[threadGroup=" + threadGroup.getName() + "]";
}
@ -769,15 +765,6 @@ public final class AppContext {
}
}
final class MostRecentThreadAppContext {
final Thread thread;
final AppContext appContext;
MostRecentThreadAppContext(Thread key, AppContext value) {
thread = key;
appContext = value;
}
}
final class MostRecentKeyValue {
Object key;
Object value;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2000-2008 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
@ -270,62 +270,58 @@ public abstract class DataTransferer {
* instead, null will be returned.
*/
public static DataTransferer getInstance() {
if (transferer == null) {
synchronized (DataTransferer.class) {
if (transferer == null) {
final String name = SunToolkit.
getDataTransfererClassName();
if (name != null) {
PrivilegedAction action = new PrivilegedAction() {
public Object run() {
Class cls = null;
Method method = null;
Object ret = null;
synchronized (DataTransferer.class) {
if (transferer == null) {
final String name = SunToolkit.getDataTransfererClassName();
if (name != null) {
PrivilegedAction<DataTransferer> action = new PrivilegedAction<DataTransferer>()
{
public DataTransferer run() {
Class cls = null;
Method method = null;
DataTransferer ret = null;
try {
cls = Class.forName(name);
} catch (ClassNotFoundException e) {
ClassLoader cl = ClassLoader.
getSystemClassLoader();
if (cl != null) {
try {
cls = cl.loadClass(name);
} catch (ClassNotFoundException ee) {
ee.printStackTrace();
throw new AWTError("DataTransferer not found: " + name);
}
}
}
if (cls != null) {
try {
cls = Class.forName(name);
} catch (ClassNotFoundException e) {
ClassLoader cl = ClassLoader.
getSystemClassLoader();
if (cl != null) {
try {
method = cls.getDeclaredMethod
("getInstanceImpl");
method.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
throw new AWTError("Cannot instantiate DataTransferer: " + name);
} catch (SecurityException e) {
e.printStackTrace();
throw new AWTError("Access is denied for DataTransferer: " + name);
cls = cl.loadClass(name);
} catch (ClassNotFoundException ee) {
ee.printStackTrace();
throw new AWTError("DataTransferer not found: " + name);
}
}
if (method != null) {
try {
ret = method.invoke(null);
} catch (InvocationTargetException e) {
e.printStackTrace();
throw new AWTError("Cannot instantiate DataTransferer: " + name);
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new AWTError("Cannot access DataTransferer: " + name);
}
}
return ret;
}
};
transferer = (DataTransferer)
AccessController.doPrivileged(action);
}
if (cls != null) {
try {
method = cls.getDeclaredMethod("getInstanceImpl");
method.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
throw new AWTError("Cannot instantiate DataTransferer: " + name);
} catch (SecurityException e) {
e.printStackTrace();
throw new AWTError("Access is denied for DataTransferer: " + name);
}
}
if (method != null) {
try {
ret = (DataTransferer) method.invoke(null);
} catch (InvocationTargetException e) {
e.printStackTrace();
throw new AWTError("Cannot instantiate DataTransferer: " + name);
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new AWTError("Cannot access DataTransferer: " + name);
}
}
return ret;
}
};
transferer = AccessController.doPrivileged(action);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2008 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,6 +39,8 @@ import sun.misc.Unsafe;
* @since 1.5
*/
class MotifDnDConstants {
// utility class can not be instantiated
private MotifDnDConstants() {}
// Note that offsets in all native structures below do not depend on the
// architecture.
private static final Unsafe unsafe = XlibWrapper.unsafe;
@ -55,8 +57,7 @@ class MotifDnDConstants {
XAtom.get("XmTRANSFER_SUCCESS");
static final XAtom XA_XmTRANSFER_FAILURE =
XAtom.get("XmTRANSFER_FAILURE");
static final XSelection MotifDnDSelection =
new XSelection(XA_MOTIF_ATOM_0, null);
static final XSelection MotifDnDSelection = new XSelection(XA_MOTIF_ATOM_0);
public static final byte MOTIF_DND_PROTOCOL_VERSION = 0;
@ -231,6 +232,9 @@ class MotifDnDConstants {
}
public static final class Swapper {
// utility class can not be instantiated
private Swapper() {}
public static short swap(short s) {
return (short)(((s & 0xFF00) >>> 8) | ((s & 0xFF) << 8));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2008 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
@ -933,7 +933,7 @@ class MotifDnDDropTargetProtocol extends XDropTargetProtocol {
XSelection selection = XSelection.getSelection(selectionAtom);
if (selection == null) {
selection = new XSelection(selectionAtom, null);
selection = new XSelection(selectionAtom);
}
return selection.getData(format, time_stamp);
@ -1056,7 +1056,7 @@ class MotifDnDDropTargetProtocol extends XDropTargetProtocol {
// the original structure can be freed before this
// SunDropTargetEvent is dispatched.
if (xclient != null) {
int size = new XClientMessageEvent(nativeCtxt).getSize();
int size = XClientMessageEvent.getSize();
nativeCtxt = unsafe.allocateMemory(size + 4 * Native.getLongSize());

View File

@ -0,0 +1,30 @@
/*
* Copyright 2008 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.
*/
package sun.awt.X11;
interface OwnershipListener {
public void ownershipChanged(final boolean isOwner);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 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
@ -58,7 +58,7 @@ package sun.awt.X11;
import sun.misc.Unsafe;
import java.util.HashMap;
public class XAtom {
public final class XAtom {
// Order of lock: XAWTLock -> XAtom.class
@ -175,7 +175,7 @@ public class XAtom {
public static XAtom get(String name) {
XAtom xatom = lookup(name);
if (xatom == null) {
xatom = new XAtom(name);
xatom = new XAtom(XToolkit.getDisplay(), name);
}
return xatom;
}
@ -232,10 +232,6 @@ public class XAtom {
this(display, name, true);
}
private XAtom(String name) {
this(XToolkit.getDisplay(), name, true);
}
public XAtom(String name, boolean autoIntern) {
this(XToolkit.getDisplay(), name, autoIntern);
}
@ -262,7 +258,7 @@ public class XAtom {
* @since 1.5
*/
public XAtom(long display, String name, boolean autoIntern) {
private XAtom(long display, String name, boolean autoIntern) {
this.name = name;
this.display = display;
if (autoIntern) {
@ -651,28 +647,6 @@ public class XAtom {
}
}
/**
* Initializes atom with name and display values
*/
public void setValues(long display, String name, boolean autoIntern) {
this.display = display;
this.name = name;
if (autoIntern) {
XToolkit.awtLock();
try {
atom = XlibWrapper.InternAtom(display,name,0);
} finally {
XToolkit.awtUnlock();
}
}
register();
}
public void setValues(long display, long atom) {
this.display = display;
this.atom = atom;
register();
}
public void setValues(long display, String name, long atom) {
this.display = display;
this.atom = atom;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2008 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,30 +26,32 @@
package sun.awt.X11;
import java.awt.datatransfer.Transferable;
import java.util.SortedMap;
import java.util.Set;
import java.util.Iterator;
import java.util.HashSet;
import java.io.IOException;
import java.security.AccessController;
import java.util.HashMap;
import java.util.Map;
import sun.awt.UNIXToolkit;
import sun.awt.datatransfer.DataTransferer;
import sun.awt.datatransfer.SunClipboard;
import sun.awt.datatransfer.ClipboardTransferable;
import sun.security.action.GetIntegerAction;
/**
* A class which interfaces with the X11 selection service in order to support
* data transfer via Clipboard operations.
*/
public class XClipboard extends SunClipboard implements Runnable {
public final class XClipboard extends SunClipboard implements OwnershipListener
{
private final XSelection selection;
// Time of calling XConvertSelection().
private long convertSelectionTime;
// The flag used not to call XConvertSelection() if the previous SelectionNotify
// has not been processed by checkChange().
private volatile boolean isSelectionNotifyProcessed;
// The property in which the owner should place requested targets
// when tracking changes of available data flavors (practically targets).
private volatile XAtom targetsPropertyAtom;
private static final Object classLock = new Object();
@ -57,31 +59,33 @@ public class XClipboard extends SunClipboard implements Runnable {
private static int pollInterval;
private static Set listenedClipboards;
private static Map<Long, XClipboard> targetsAtom2Clipboard;
/**
* Creates a system clipboard object.
*/
public XClipboard(String name, String selectionName) {
super(name);
selection = new XSelection(XAtom.get(selectionName), this);
selection = new XSelection(XAtom.get(selectionName));
selection.registerOwershipListener(this);
}
/**
* The action to be run when we lose ownership
/*
* NOTE: This method may be called by privileged threads.
* DO NOT INVOKE CLIENT CODE ON THIS THREAD!
*/
public void run() {
lostOwnershipImpl();
public void ownershipChanged(final boolean isOwner) {
if (isOwner) {
checkChangeHere(contents);
} else {
lostOwnershipImpl();
}
}
protected synchronized void setContentsNative(Transferable contents) {
SortedMap formatMap = DataTransferer.getInstance().getFormatsForTransferable
(contents, DataTransferer.adaptFlavorMap(flavorMap));
long[] formats =
DataTransferer.getInstance().keysToLongArray(formatMap);
long[] formats = DataTransferer.keysToLongArray(formatMap);
if (!selection.setOwner(contents, formatMap, formats,
XToolkit.getCurrentServerTime())) {
@ -94,6 +98,7 @@ public class XClipboard extends SunClipboard implements Runnable {
return selection.getSelectionAtom().getAtom();
}
@Override
public synchronized Transferable getContents(Object requestor) {
if (contents != null) {
return contents;
@ -115,62 +120,163 @@ public class XClipboard extends SunClipboard implements Runnable {
return selection.getData(format, XToolkit.getCurrentServerTime());
}
// Called on the toolkit thread under awtLock.
public void checkChange(long[] formats) {
if (!selection.isOwner()) {
super.checkChange(formats);
}
}
void checkChangeHere(Transferable contents) {
private void checkChangeHere(Transferable contents) {
if (areFlavorListenersRegistered()) {
super.checkChange(DataTransferer.getInstance().
checkChange(DataTransferer.getInstance().
getFormatsForTransferableAsArray(contents, flavorMap));
}
}
protected void registerClipboardViewerChecked() {
if (pollInterval <= 0) {
pollInterval = ((Integer)AccessController.doPrivileged(
new GetIntegerAction("awt.datatransfer.clipboard.poll.interval",
defaultPollInterval))).intValue();
private static int getPollInterval() {
synchronized (XClipboard.classLock) {
if (pollInterval <= 0) {
pollInterval = defaultPollInterval;
pollInterval = AccessController.doPrivileged(
new GetIntegerAction("awt.datatransfer.clipboard.poll.interval",
defaultPollInterval));
if (pollInterval <= 0) {
pollInterval = defaultPollInterval;
}
}
return pollInterval;
}
selection.initializeSelectionForTrackingChanges();
}
private XAtom getTargetsPropertyAtom() {
if (null == targetsPropertyAtom) {
targetsPropertyAtom =
XAtom.get("XAWT_TARGETS_OF_SELECTION:" + selection.getSelectionAtom().getName());
}
return targetsPropertyAtom;
}
protected void registerClipboardViewerChecked() {
// for XConvertSelection() to be called for the first time in getTargetsDelayed()
isSelectionNotifyProcessed = true;
boolean mustSchedule = false;
synchronized (XClipboard.classLock) {
if (listenedClipboards == null) {
listenedClipboards = new HashSet(2);
if (targetsAtom2Clipboard == null) {
targetsAtom2Clipboard = new HashMap<Long, XClipboard>(2);
}
mustSchedule = targetsAtom2Clipboard.isEmpty();
targetsAtom2Clipboard.put(getTargetsPropertyAtom().getAtom(), this);
if (mustSchedule) {
XToolkit.addEventDispatcher(XWindow.getXAWTRootWindow().getWindow(),
new SelectionNotifyHandler());
}
mustSchedule = listenedClipboards.isEmpty();
listenedClipboards.add(this);
}
if (mustSchedule) {
XToolkit.schedule(new CheckChangeTimerTask(), pollInterval);
XToolkit.schedule(new CheckChangeTimerTask(), XClipboard.getPollInterval());
}
}
private static class CheckChangeTimerTask implements Runnable {
public void run() {
for (Iterator iter = listenedClipboards.iterator(); iter.hasNext();) {
XClipboard clpbrd = (XClipboard)iter.next();
clpbrd.selection.getTargetsDelayed();
for (XClipboard clpbrd : targetsAtom2Clipboard.values()) {
clpbrd.getTargetsDelayed();
}
synchronized (XClipboard.classLock) {
if (listenedClipboards != null && !listenedClipboards.isEmpty()) {
XToolkit.schedule(this, pollInterval);
if (targetsAtom2Clipboard != null && !targetsAtom2Clipboard.isEmpty()) {
XToolkit.schedule(this, XClipboard.getPollInterval());
}
}
}
}
private static class SelectionNotifyHandler implements XEventDispatcher {
public void dispatchEvent(XEvent ev) {
if (ev.get_type() == XlibWrapper.SelectionNotify) {
final XSelectionEvent xse = ev.get_xselection();
XClipboard clipboard = null;
synchronized (XClipboard.classLock) {
if (targetsAtom2Clipboard != null && !targetsAtom2Clipboard.isEmpty()) {
XToolkit.removeEventDispatcher(XWindow.getXAWTRootWindow().getWindow(), this);
return;
}
final long propertyAtom = xse.get_property();
clipboard = targetsAtom2Clipboard.get(propertyAtom);
}
if (null != clipboard) {
clipboard.checkChange(xse);
}
}
}
}
protected void unregisterClipboardViewerChecked() {
selection.deinitializeSelectionForTrackingChanges();
isSelectionNotifyProcessed = false;
synchronized (XClipboard.classLock) {
listenedClipboards.remove(this);
targetsAtom2Clipboard.remove(getTargetsPropertyAtom().getAtom());
}
}
// checkChange() will be called on SelectionNotify
private void getTargetsDelayed() {
XToolkit.awtLock();
try {
long curTime = System.currentTimeMillis();
if (isSelectionNotifyProcessed || curTime >= (convertSelectionTime + UNIXToolkit.getDatatransferTimeout()))
{
convertSelectionTime = curTime;
XlibWrapper.XConvertSelection(XToolkit.getDisplay(),
selection.getSelectionAtom().getAtom(),
XDataTransferer.TARGETS_ATOM.getAtom(),
getTargetsPropertyAtom().getAtom(),
XWindow.getXAWTRootWindow().getWindow(),
XlibWrapper.CurrentTime);
isSelectionNotifyProcessed = false;
}
} finally {
XToolkit.awtUnlock();
}
}
/*
* Tracks changes of available formats.
* NOTE: This method may be called by privileged threads.
* DO NOT INVOKE CLIENT CODE ON THIS THREAD!
*/
private void checkChange(XSelectionEvent xse) {
final long propertyAtom = xse.get_property();
if (propertyAtom != getTargetsPropertyAtom().getAtom()) {
// wrong atom
return;
}
final XAtom selectionAtom = XAtom.get(xse.get_selection());
final XSelection changedSelection = XSelection.getSelection(selectionAtom);
if (null == changedSelection || changedSelection != selection) {
// unknown selection - do nothing
return;
}
isSelectionNotifyProcessed = true;
if (selection.isOwner()) {
// selection is owner - do not need formats
return;
}
long[] formats = null;
if (propertyAtom == XlibWrapper.None) {
// We treat None property atom as "empty selection".
formats = new long[0];
} else {
WindowPropertyGetter targetsGetter =
new WindowPropertyGetter(XWindow.getXAWTRootWindow().getWindow(),
XAtom.get(propertyAtom), 0,
XSelection.MAX_LENGTH, true,
XlibWrapper.AnyPropertyType);
try {
targetsGetter.execute();
formats = XSelection.getFormats(targetsGetter);
} finally {
targetsGetter.dispose();
}
}
checkChange(formats);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 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
@ -31,17 +31,13 @@ import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.DefaultKeyboardFocusManager;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.MenuBar;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.SystemColor;
import java.awt.Toolkit;
@ -60,12 +56,9 @@ import java.awt.event.InvocationEvent;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.VolatileImage;
import java.awt.peer.CanvasPeer;
import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
import java.awt.peer.LightweightPeer;
import java.awt.peer.PanelPeer;
import java.awt.peer.WindowPeer;
import java.lang.reflect.*;
import java.security.*;
import java.util.Collection;
@ -821,7 +814,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
public void setFont(Font f) {
synchronized (getStateLock()) {
if (f == null) {
f = defaultFont;
f = XWindow.getDefaultFont();
}
font = f;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2008 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,16 +39,37 @@ import sun.awt.ComponentAccessor;
* This class implements window which serves as content window for decorated frames.
* Its purpose to provide correct events dispatching for the complex
* constructs such as decorated frames.
*
* It should always be located at (- left inset, - top inset) in the associated
* decorated window. So coordinates in it would be the same as java coordinates.
*/
public class XContentWindow extends XWindow implements XConstants {
public final class XContentWindow extends XWindow implements XConstants {
private static Logger insLog = Logger.getLogger("sun.awt.X11.insets.XContentWindow");
XDecoratedPeer parentFrame;
static XContentWindow createContent(XDecoratedPeer parentFrame) {
final WindowDimensions dims = parentFrame.getDimensions();
Rectangle rec = dims.getBounds();
// Fix for - set the location of the content window to the (-left inset, -top inset)
Insets ins = dims.getInsets();
if (ins != null) {
rec.x = -ins.left;
rec.y = -ins.top;
} else {
rec.x = 0;
rec.y = 0;
}
final XContentWindow cw = new XContentWindow(parentFrame, rec);
cw.xSetVisible(true);
return cw;
}
private final XDecoratedPeer parentFrame;
// A list of expose events that come when the parentFrame is iconified
private java.util.List<SavedExposeEvent> iconifiedExposeEvents = new java.util.ArrayList<SavedExposeEvent>();
private final java.util.List<SavedExposeEvent> iconifiedExposeEvents =
new java.util.ArrayList<SavedExposeEvent>();
XContentWindow(XDecoratedPeer parentFrame, Rectangle bounds) {
private XContentWindow(XDecoratedPeer parentFrame, Rectangle bounds) {
super((Component)parentFrame.getTarget(), parentFrame.getShell(), bounds);
this.parentFrame = parentFrame;
}
@ -63,9 +84,6 @@ public class XContentWindow extends XWindow implements XConstants {
}
}
void initialize() {
xSetVisible(true);
}
protected String getWMName() {
return "Content window";
}

View File

@ -36,7 +36,7 @@ import java.util.logging.Logger;
import sun.awt.ComponentAccessor;
import sun.awt.SunToolkit;
class XDecoratedPeer extends XWindowPeer {
abstract class XDecoratedPeer extends XWindowPeer {
private static final Logger log = Logger.getLogger("sun.awt.X11.XDecoratedPeer");
private static final Logger insLog = Logger.getLogger("sun.awt.X11.insets.XDecoratedPeer");
private static final Logger focusLog = Logger.getLogger("sun.awt.X11.focus.XDecoratedPeer");
@ -98,8 +98,7 @@ class XDecoratedPeer extends XWindowPeer {
// happen after the X window is created.
initResizability();
updateSizeHints(dimensions);
content = createContent(dimensions);
content.initialize();
content = XContentWindow.createContent(this);
if (warningWindow != null) {
warningWindow.toFront();
}
@ -160,20 +159,6 @@ class XDecoratedPeer extends XWindowPeer {
}
}
XContentWindow createContent(WindowDimensions dims) {
Rectangle rec = dims.getBounds();
// Fix for - set the location of the content window to the (-left inset, -top inset)
Insets ins = dims.getInsets();
if (ins != null) {
rec.x = -ins.left;
rec.y = -ins.top;
} else {
rec.x = 0;
rec.y = 0;
}
return new XContentWindow(this, rec);
}
XFocusProxyWindow createFocusProxy() {
return new XFocusProxyWindow(this);
}
@ -286,7 +271,7 @@ class XDecoratedPeer extends XWindowPeer {
return;
}
Component t = (Component)target;
if (getDecorations() == winAttr.AWT_DECOR_NONE) {
if (getDecorations() == XWindowAttributesData.AWT_DECOR_NONE) {
setReparented(true);
insets_corrected = true;
reshape(dimensions, SET_SIZE, false);
@ -471,6 +456,15 @@ class XDecoratedPeer extends XWindowPeer {
if (insLog.isLoggable(Level.FINE)) {
insLog.fine("Reshaping " + this + " to " + newDimensions + " op " + op + " user reshape " + userReshape);
}
if (userReshape) {
// We handle only userReshape == true cases. It means that
// if the window manager or any other part of the windowing
// system sets inappropriate size for this window, we can
// do nothing but accept it.
Rectangle reqBounds = newDimensions.getBounds();
Rectangle newBounds = constrainBounds(reqBounds.x, reqBounds.y, reqBounds.width, reqBounds.height);
newDimensions = new WindowDimensions(newBounds, newDimensions.getInsets(), newDimensions.isClientSizeSet());
}
XToolkit.awtLock();
try {
if (!isReparented() || !isVisible()) {
@ -586,6 +580,49 @@ class XDecoratedPeer extends XWindowPeer {
reshape(dims, operation, userReshape);
}
// This method gets overriden in XFramePeer & XDialogPeer.
abstract boolean isTargetUndecorated();
@Override
Rectangle constrainBounds(int x, int y, int width, int height) {
// We don't restrict the setBounds() operation if the code is trusted.
if (!hasWarningWindow()) {
return new Rectangle(x, y, width, height);
}
// If it's undecorated or is not currently visible,
// apply the same constraints as for the Window.
if (!isVisible() || isTargetUndecorated()) {
return super.constrainBounds(x, y, width, height);
}
// If it's visible & decorated, constraint the size only
int newX = x;
int newY = y;
int newW = width;
int newH = height;
GraphicsConfiguration gc = ((Window)target).getGraphicsConfiguration();
Rectangle sB = gc.getBounds();
Insets sIn = ((Window)target).getToolkit().getScreenInsets(gc);
Rectangle curBounds = getBounds();
int maxW = Math.max(sB.width - sIn.left - sIn.right, curBounds.width);
int maxH = Math.max(sB.height - sIn.top - sIn.bottom, curBounds.height);
// First make sure the size is withing the visible part of the screen
if (newW > maxW) {
newW = maxW;
}
if (newH > maxH) {
newH = maxH;
}
return new Rectangle(newX, newY, newW, newH);
}
/**
* @see java.awt.peer.ComponentPeer#setBounds
*/
@ -651,12 +688,12 @@ class XDecoratedPeer extends XWindowPeer {
}
if (!isReparented() && isVisible() && runningWM != XWM.NO_WM
&& !XWM.isNonReparentingWM()
&& getDecorations() != winAttr.AWT_DECOR_NONE) {
&& getDecorations() != XWindowAttributesData.AWT_DECOR_NONE) {
insLog.fine("- visible but not reparented, skipping");
return;
}
//Last chance to correct insets
if (!insets_corrected && getDecorations() != winAttr.AWT_DECOR_NONE) {
if (!insets_corrected && getDecorations() != XWindowAttributesData.AWT_DECOR_NONE) {
long parent = XlibUtil.getParentWindow(window);
Insets correctWM = (parent != -1) ? XWM.getWM().getInsets(this, window, parent) : null;
if (insLog.isLoggable(Level.FINER)) {
@ -824,7 +861,7 @@ class XDecoratedPeer extends XWindowPeer {
fs &= ~(MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE);
}
winAttr.functions = fs;
XWM.setShellNotResizable(this, dimensions, dimensions.getScreenBounds(), false);
XWM.setShellNotResizable(this, dimensions, dimensions.getBounds(), false);
}
}
@ -870,7 +907,7 @@ class XDecoratedPeer extends XWindowPeer {
return getSize().height;
}
public WindowDimensions getDimensions() {
final public WindowDimensions getDimensions() {
return dimensions;
}

View File

@ -88,7 +88,8 @@ class XDialogPeer extends XDecoratedPeer implements DialogPeer {
}
}
private boolean isTargetUndecorated() {
@Override
boolean isTargetUndecorated() {
if (undecorated != null) {
return undecorated.booleanValue();
} else {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2008 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
@ -48,8 +48,7 @@ class XDnDConstants {
static final XAtom XA_XdndStatus = XAtom.get("XdndStatus");
static final XAtom XA_XdndFinished = XAtom.get("XdndFinished");
static final XSelection XDnDSelection =
new XSelection(XA_XdndSelection, null);
static final XSelection XDnDSelection = new XSelection(XA_XdndSelection);
public static final int XDND_MIN_PROTOCOL_VERSION = 3;
public static final int XDND_PROTOCOL_VERSION = 5;

View File

@ -647,12 +647,6 @@ public class XEmbedCanvasPeer extends XCanvasPeer implements WindowFocusListener
}
if (isXEmbedActive()) {
switch ((int)msg.get_data(1)) {
case _SUN_XEMBED_START:
// Child has finished initialization and waits for notify
xembed.processXEmbedInfo();
notifyChildEmbedded();
break;
case XEMBED_REQUEST_FOCUS:
requestXEmbedFocus();
break;

View File

@ -74,7 +74,6 @@ public class XEmbedClientHelper extends XEmbedHelper implements XEventDispatcher
XToolkit.awtUnlock();
}
}
notifyReady();
}
void handleClientMessage(XEvent xev) {
@ -84,7 +83,6 @@ public class XEmbedClientHelper extends XEmbedHelper implements XEventDispatcher
if (xembedLog.isLoggable(Level.FINE)) xembedLog.fine("Embedded message: " + msgidToString((int)msg.get_data(1)));
switch ((int)msg.get_data(1)) {
case XEMBED_EMBEDDED_NOTIFY: // Notification about embedding protocol start
// NOTE: May be called two times because we send _SUN_XEMBED_START
active = true;
server = getEmbedder(embedded, msg);
// Check if window is reparented. If not - it was created with
@ -223,13 +221,4 @@ public class XEmbedClientHelper extends XEmbedHelper implements XEventDispatcher
long getX11Mods(AWTKeyStroke stroke) {
return XWindow.getXModifiers(stroke);
}
void notifyReady() {
long wnd = server;
if (wnd == 0) {
// Server is still 0, get the parent
wnd = embedded.getParentWindowHandle();
}
sendMessage(wnd, _SUN_XEMBED_START);
}
}

View File

@ -58,7 +58,6 @@ public class XEmbedHelper {
final static int XEMBED_REGISTER_ACCELERATOR = 12;
final static int XEMBED_UNREGISTER_ACCELERATOR= 13;
final static int XEMBED_ACTIVATE_ACCELERATOR = 14;
final static int _SUN_XEMBED_START = 1119;
final static int NON_STANDARD_XEMBED_GTK_GRAB_KEY = 108;
final static int NON_STANDARD_XEMBED_GTK_UNGRAB_KEY = 109;
@ -151,8 +150,6 @@ public class XEmbedHelper {
return "NON_STANDARD_XEMBED_GTK_UNGRAB_KEY";
case NON_STANDARD_XEMBED_GTK_GRAB_KEY:
return "NON_STANDARD_XEMBED_GTK_GRAB_KEY";
case _SUN_XEMBED_START:
return "XEMBED_START";
case XConstants.KeyPress | XEmbedServerTester.SYSTEM_EVENT_MASK:
return "KeyPress";
case XConstants.MapNotify | XEmbedServerTester.SYSTEM_EVENT_MASK:

View File

@ -177,13 +177,6 @@ public class XEmbedServerTester implements XEventDispatcher {
embedCompletely();
}
public void test3_2() {
embedCompletely();
int res = getEventPos();
sendMessage(XEmbedHelper._SUN_XEMBED_START);
waitEmbeddedNotify(res);
}
public void test3_3() {
reparent = true;
embedCompletely();

View File

@ -184,6 +184,12 @@ public class XEmbeddedFramePeer extends XFramePeer {
}
}
@Override
Rectangle constrainBounds(int x, int y, int width, int height) {
// We don't constrain the bounds of the EmbeddedFrames
return new Rectangle(x, y, width, height);
}
// don't use getBounds() inherited from XDecoratedPeer
public Rectangle getBounds() {
return new Rectangle(x, y, width, height);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 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,15 +24,18 @@
*/
package sun.awt.X11;
import java.util.Vector;
import java.awt.*;
import java.awt.peer.*;
import java.awt.event.*;
import sun.awt.im.*;
import sun.awt.*;
import java.util.logging.*;
import java.lang.reflect.Field;
import java.util.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.MenuBar;
import java.awt.Rectangle;
import java.awt.peer.FramePeer;
import java.util.logging.Level;
import java.util.logging.Logger;
class XFramePeer extends XDecoratedPeer implements FramePeer, XConstants {
private static Logger log = Logger.getLogger("sun.awt.X11.XFramePeer");
@ -92,7 +95,8 @@ class XFramePeer extends XDecoratedPeer implements FramePeer, XConstants {
}
}
private boolean isTargetUndecorated() {
@Override
boolean isTargetUndecorated() {
if (undecorated != null) {
return undecorated.booleanValue();
} else {
@ -285,19 +289,20 @@ class XFramePeer extends XDecoratedPeer implements FramePeer, XConstants {
* Let's see if this is a window state protocol message, and
* if it is - decode a new state in terms of java constants.
*/
Integer newState = XWM.getWM().isStateChange(this, ev);
if (newState == null) {
if (!XWM.getWM().isStateChange(this, ev)) {
stateLog.finer("either not a state atom or state has not been changed");
return;
}
int changed = state ^ newState.intValue();
final int newState = XWM.getWM().getState(this);
int changed = state ^ newState;
if (changed == 0) {
stateLog.finer("State is the same: " + state);
return;
}
int old_state = state;
state = newState.intValue();
state = newState;
if ((changed & Frame.ICONIFIED) != 0) {
if ((state & Frame.ICONIFIED) != 0) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 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
@ -218,7 +218,7 @@ public class XMenuItemPeer implements MenuItemPeer {
Font getTargetFont() {
if (target == null) {
return XWindow.defaultFont;
return XWindow.getDefaultFont();
}
try {
return (Font)m_getFont.invoke(target, new Object[0]);
@ -227,7 +227,7 @@ public class XMenuItemPeer implements MenuItemPeer {
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return XWindow.defaultFont;
return XWindow.getDefaultFont();
}
String getTargetLabel() {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2008 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,17 +26,15 @@
package sun.awt.X11;
import java.awt.*;
import java.awt.Frame;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.LogManager;
import java.awt.*;
import java.awt.image.*;
import java.util.*;
class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProtocol {
final static Logger log = Logger.getLogger("sun.awt.X11.XNETProtocol");
final class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProtocol
{
private final static Logger log = Logger.getLogger("sun.awt.X11.XNETProtocol");
private final static Logger iconLog = Logger.getLogger("sun.awt.X11.icon.XNETProtocol");
private static Logger stateLog = Logger.getLogger("sun.awt.X11.states.XNETProtocol");
/**
* XStateProtocol
@ -276,6 +274,7 @@ class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProtocol {
boolean doStateProtocol() {
boolean res = active() && checkProtocol(XA_NET_SUPPORTED, XA_NET_WM_STATE);
stateLog.finer("doStateProtocol() returns " + res);
return res;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 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
@ -187,7 +187,7 @@ public class XPopupMenuPeer extends XMenuWindow implements PopupMenuPeer {
//Fix for 6267144: PIT: Popup menu label is not shown, XToolkit
Font getTargetFont() {
if (popupMenuTarget == null) {
return XWindow.defaultFont;
return XWindow.getDefaultFont();
}
try {
return (Font)m_getFont.invoke(popupMenuTarget, new Object[0]);
@ -196,7 +196,7 @@ public class XPopupMenuPeer extends XMenuWindow implements PopupMenuPeer {
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return XWindow.defaultFont;
return XWindow.getDefaultFont();
}
String getTargetLabel() {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2008 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
@ -32,9 +32,6 @@ import java.io.IOException;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
@ -45,7 +42,7 @@ import sun.awt.datatransfer.DataTransferer;
/**
* A class which interfaces with the X11 selection service.
*/
public class XSelection {
public final class XSelection {
/* Maps atoms to XSelection instances. */
private static final Hashtable<XAtom, XSelection> table = new Hashtable<XAtom, XSelection>();
@ -69,8 +66,6 @@ public class XSelection {
XToolkit.awtUnlock();
}
}
/* The selection timeout. */
private static long SELECTION_TIMEOUT = UNIXToolkit.getDatatransferTimeout();
/* The PropertyNotify event handler for incremental data transfer. */
private static final XEventDispatcher incrementalTransferHandler =
@ -84,11 +79,6 @@ public class XSelection {
/* The X atom for the underlying selection. */
private final XAtom selectionAtom;
/*
* XClipboard.run() is to be called when we lose ownership.
* XClipbioard.checkChange() is to be called when tracking changes of flavors.
*/
private final XClipboard clipboard;
/*
* Owner-related variables - protected with synchronized (this).
@ -109,17 +99,8 @@ public class XSelection {
private long ownershipTime = 0;
// True if we are the owner of this selection.
private boolean isOwner;
// The property in which the owner should place requested targets
// when tracking changes of available data flavors (practically targets).
private volatile XAtom targetsPropertyAtom;
// A set of these property atoms.
private static volatile Set targetsPropertyAtoms;
// The flag used not to call XConvertSelection() if the previous SelectionNotify
// has not been processed by checkChange().
private volatile boolean isSelectionNotifyProcessed;
// Time of calling XConvertSelection().
private long convertSelectionTime;
private OwnershipListener ownershipListener = null;
private final Object stateLock = new Object();
static {
XToolkit.addEventDispatcher(XWindow.getXAWTRootWindow().getWindow(),
@ -141,12 +122,11 @@ public class XSelection {
* @param clpbrd the corresponding clipoboard
* @exception NullPointerException if atom is <code>null</code>.
*/
public XSelection(XAtom atom, XClipboard clpbrd) {
public XSelection(XAtom atom) {
if (atom == null) {
throw new NullPointerException("Null atom");
}
selectionAtom = atom;
clipboard = clpbrd;
table.put(selectionAtom, this);
}
@ -154,25 +134,9 @@ public class XSelection {
return selectionAtom;
}
void initializeSelectionForTrackingChanges() {
targetsPropertyAtom = XAtom.get("XAWT_TARGETS_OF_SELECTION:" + selectionAtom.getName());
if (targetsPropertyAtoms == null) {
targetsPropertyAtoms = Collections.synchronizedSet(new HashSet(2));
}
targetsPropertyAtoms.add(Long.valueOf(targetsPropertyAtom.getAtom()));
// for XConvertSelection() to be called for the first time in getTargetsDelayed()
isSelectionNotifyProcessed = true;
}
void deinitializeSelectionForTrackingChanges() {
if (targetsPropertyAtoms != null && targetsPropertyAtom != null) {
targetsPropertyAtoms.remove(Long.valueOf(targetsPropertyAtom.getAtom()));
}
isSelectionNotifyProcessed = false;
}
public synchronized boolean setOwner(Transferable contents, Map formatMap,
long[] formats, long time) {
long[] formats, long time)
{
long owner = XWindow.getXAWTRootWindow().getWindow();
long selection = selectionAtom.getAtom();
@ -192,15 +156,12 @@ public class XSelection {
XlibWrapper.XSetSelectionOwner(XToolkit.getDisplay(),
selection, owner, time);
if (XlibWrapper.XGetSelectionOwner(XToolkit.getDisplay(),
selection) != owner) {
selection) != owner)
{
reset();
return false;
}
isOwner = true;
if (clipboard != null) {
clipboard.checkChangeHere(contents);
}
setOwnerProp(true);
return true;
} finally {
XToolkit.awtUnlock();
@ -217,7 +178,7 @@ public class XSelection {
do {
DataTransferer.getInstance().processDataConversionRequests();
XToolkit.awtLockWait(250);
} while (propertyGetter == dataGetter && System.currentTimeMillis() < startTime + SELECTION_TIMEOUT);
} while (propertyGetter == dataGetter && System.currentTimeMillis() < startTime + UNIXToolkit.getDatatransferTimeout());
} finally {
XToolkit.awtUnlock();
}
@ -232,11 +193,9 @@ public class XSelection {
throw new Error("UNIMPLEMENTED");
}
long[] formats = null;
long[] targets = null;
synchronized (lock) {
SELECTION_TIMEOUT = UNIXToolkit.getDatatransferTimeout();
WindowPropertyGetter targetsGetter =
new WindowPropertyGetter(XWindow.getXAWTRootWindow().getWindow(),
selectionPropertyAtom, 0, MAX_LENGTH,
@ -267,23 +226,25 @@ public class XSelection {
} finally {
XToolkit.awtUnlock();
}
formats = getFormats(targetsGetter);
targets = getFormats(targetsGetter);
} finally {
targetsGetter.dispose();
}
}
return formats;
return targets;
}
private static long[] getFormats(WindowPropertyGetter targetsGetter) {
static long[] getFormats(WindowPropertyGetter targetsGetter) {
long[] formats = null;
if (targetsGetter.isExecuted() && !targetsGetter.isDisposed() &&
(targetsGetter.getActualType() == XAtom.XA_ATOM ||
targetsGetter.getActualType() == XDataTransferer.TARGETS_ATOM.getAtom()) &&
targetsGetter.getActualFormat() == 32) {
int count = (int)targetsGetter.getNumberOfItems();
targetsGetter.getActualFormat() == 32)
{
// we accept property with TARGETS type to be compatible with old jdks
// see 6607163
int count = targetsGetter.getNumberOfItems();
if (count > 0) {
long atoms = targetsGetter.getData();
formats = new long[count];
@ -297,26 +258,6 @@ public class XSelection {
return formats != null ? formats : new long[0];
}
// checkChange() will be called on SelectionNotify
void getTargetsDelayed() {
XToolkit.awtLock();
try {
long curTime = System.currentTimeMillis();
if (isSelectionNotifyProcessed || curTime >= convertSelectionTime + SELECTION_TIMEOUT) {
convertSelectionTime = curTime;
XlibWrapper.XConvertSelection(XToolkit.getDisplay(),
getSelectionAtom().getAtom(),
XDataTransferer.TARGETS_ATOM.getAtom(),
targetsPropertyAtom.getAtom(),
XWindow.getXAWTRootWindow().getWindow(),
XlibWrapper.CurrentTime);
isSelectionNotifyProcessed = false;
}
} finally {
XToolkit.awtUnlock();
}
}
/*
* Requests the selection data in the specified format and returns
* the data provided by the owner.
@ -329,8 +270,6 @@ public class XSelection {
byte[] data = null;
synchronized (lock) {
SELECTION_TIMEOUT = UNIXToolkit.getDatatransferTimeout();
WindowPropertyGetter dataGetter =
new WindowPropertyGetter(XWindow.getXAWTRootWindow().getWindow(),
selectionPropertyAtom, 0, MAX_LENGTH,
@ -379,7 +318,7 @@ public class XSelection {
dataGetter.getActualFormat());
}
int count = (int)dataGetter.getNumberOfItems();
int count = dataGetter.getNumberOfItems();
if (count <= 0) {
throw new IOException("INCR data is missed.");
@ -455,7 +394,7 @@ public class XSelection {
incrDataGetter.getActualFormat());
}
count = (int)incrDataGetter.getNumberOfItems();
count = incrDataGetter.getNumberOfItems();
if (count == 0) {
break;
@ -489,7 +428,7 @@ public class XSelection {
dataGetter.getActualFormat());
}
int count = (int)dataGetter.getNumberOfItems();
int count = dataGetter.getNumberOfItems();
if (count > 0) {
data = new byte[count];
long ptr = dataGetter.getData();
@ -511,11 +450,14 @@ public class XSelection {
return isOwner;
}
public void lostOwnership() {
isOwner = false;
if (clipboard != null) {
clipboard.run();
}
// To be MT-safe this method should be called under awtLock.
private void setOwnerProp(boolean f) {
isOwner = f;
fireOwnershipChanges(isOwner);
}
private void lostOwnership() {
setOwnerProp(false);
}
public synchronized void reset() {
@ -595,125 +537,39 @@ public class XSelection {
private void handleSelectionRequest(XSelectionRequestEvent xsre) {
long property = xsre.get_property();
long requestor = xsre.get_requestor();
long requestTime = xsre.get_time();
long format = xsre.get_target();
int dataFormat = 0;
final long requestor = xsre.get_requestor();
final long requestTime = xsre.get_time();
final long format = xsre.get_target();
boolean conversionSucceeded = false;
if (ownershipTime != 0 &&
(requestTime == XlibWrapper.CurrentTime ||
requestTime >= ownershipTime)) {
property = xsre.get_property();
(requestTime == XlibWrapper.CurrentTime || requestTime >= ownershipTime))
{
// Handle MULTIPLE requests as per ICCCM.
if (format == XDataTransferer.MULTIPLE_ATOM.getAtom()) {
// The property cannot be 0 for a MULTIPLE request.
if (property != 0) {
// First retrieve the list of requested targets.
WindowPropertyGetter wpg =
new WindowPropertyGetter(requestor, XAtom.get(property), 0,
MAX_LENGTH, false,
XlibWrapper.AnyPropertyType);
try {
wpg.execute();
if (wpg.getActualFormat() == 32 &&
(wpg.getNumberOfItems() % 2) == 0) {
long count = wpg.getNumberOfItems() / 2;
long pairsPtr = wpg.getData();
boolean writeBack = false;
for (int i = 0; i < count; i++) {
long target = Native.getLong(pairsPtr, 2*i);
long prop = Native.getLong(pairsPtr, 2*i + 1);
if (!convertAndStore(requestor, target, prop)) {
// To report failure, we should replace the
// target atom with 0 in the MULTIPLE property.
Native.putLong(pairsPtr, 2*i, 0);
writeBack = true;
}
}
if (writeBack) {
XToolkit.awtLock();
try {
XlibWrapper.XChangeProperty(XToolkit.getDisplay(), requestor,
property,
wpg.getActualType(),
wpg.getActualFormat(),
XlibWrapper.PropModeReplace,
wpg.getData(),
wpg.getNumberOfItems());
} finally {
XToolkit.awtUnlock();
}
}
conversionSucceeded = true;
}
} finally {
wpg.dispose();
}
}
conversionSucceeded = handleMultipleRequest(requestor, property);
} else {
// Support for obsolete clients as per ICCCM.
if (property == 0) {
if (property == XlibWrapper.None) {
property = format;
}
if (format == XDataTransferer.TARGETS_ATOM.getAtom()) {
long nativeDataPtr = 0;
int count = 0;
dataFormat = 32;
// Use a local copy to avoid synchronization.
long[] formatsLocal = formats;
if (formatsLocal == null) {
throw new IllegalStateException("Not an owner.");
}
count = formatsLocal.length;
try {
if (count > 0) {
nativeDataPtr = Native.allocateLongArray(count);
Native.put(nativeDataPtr, formatsLocal);
}
conversionSucceeded = true;
XToolkit.awtLock();
try {
XlibWrapper.XChangeProperty(XToolkit.getDisplay(), requestor,
property, format, dataFormat,
XlibWrapper.PropModeReplace,
nativeDataPtr, count);
} finally {
XToolkit.awtUnlock();
}
} finally {
if (nativeDataPtr != 0) {
XlibWrapper.unsafe.freeMemory(nativeDataPtr);
nativeDataPtr = 0;
}
}
conversionSucceeded = handleTargetsRequest(property, requestor);
} else {
conversionSucceeded = convertAndStore(requestor, format,
property);
conversionSucceeded = convertAndStore(requestor, format, property);
}
}
}
if (!conversionSucceeded) {
// Zero property indicates conversion failure.
property = 0;
// None property indicates conversion failure.
property = XlibWrapper.None;
}
XSelectionEvent xse = new XSelectionEvent();
try {
xse.set_type((int)XlibWrapper.SelectionNotify);
xse.set_type(XlibWrapper.SelectionNotify);
xse.set_send_event(true);
xse.set_requestor(requestor);
xse.set_selection(selectionAtom.getAtom());
@ -733,40 +589,123 @@ public class XSelection {
}
}
private static void checkChange(XSelectionEvent xse) {
if (targetsPropertyAtoms == null || targetsPropertyAtoms.isEmpty()) {
// We are not tracking changes.
return;
private boolean handleMultipleRequest(final long requestor, long property) {
if (XlibWrapper.None == property) {
// The property cannot be None for a MULTIPLE request.
return false;
}
long propertyAtom = xse.get_property();
long[] formats = null;
boolean conversionSucceeded = false;
if (propertyAtom == XlibWrapper.None) {
// We threat None property atom as "empty selection".
formats = new long[0];
} else if (!targetsPropertyAtoms.contains(Long.valueOf(propertyAtom))) {
return;
} else {
WindowPropertyGetter targetsGetter =
new WindowPropertyGetter(XWindow.getXAWTRootWindow().getWindow(),
XAtom.get(propertyAtom), 0, MAX_LENGTH,
true, XlibWrapper.AnyPropertyType);
// First retrieve the list of requested targets.
WindowPropertyGetter wpg =
new WindowPropertyGetter(requestor, XAtom.get(property),
0, MAX_LENGTH, false,
XlibWrapper.AnyPropertyType);
try {
wpg.execute();
if (wpg.getActualFormat() == 32 && (wpg.getNumberOfItems() % 2) == 0) {
final long count = wpg.getNumberOfItems() / 2;
final long pairsPtr = wpg.getData();
boolean writeBack = false;
for (int i = 0; i < count; i++) {
long target = Native.getLong(pairsPtr, 2 * i);
long prop = Native.getLong(pairsPtr, 2 * i + 1);
if (!convertAndStore(requestor, target, prop)) {
// To report failure, we should replace the
// target atom with 0 in the MULTIPLE property.
Native.putLong(pairsPtr, 2 * i, 0);
writeBack = true;
}
}
if (writeBack) {
XToolkit.awtLock();
try {
XlibWrapper.XChangeProperty(XToolkit.getDisplay(),
requestor,
property,
wpg.getActualType(),
wpg.getActualFormat(),
XlibWrapper.PropModeReplace,
wpg.getData(),
wpg.getNumberOfItems());
} finally {
XToolkit.awtUnlock();
}
}
conversionSucceeded = true;
}
} finally {
wpg.dispose();
}
return conversionSucceeded;
}
private boolean handleTargetsRequest(long property, long requestor)
throws IllegalStateException
{
boolean conversionSucceeded = false;
// Use a local copy to avoid synchronization.
long[] formatsLocal = formats;
if (formatsLocal == null) {
throw new IllegalStateException("Not an owner.");
}
long nativeDataPtr = 0;
try {
final int count = formatsLocal.length;
final int dataFormat = 32;
if (count > 0) {
nativeDataPtr = Native.allocateLongArray(count);
Native.put(nativeDataPtr, formatsLocal);
}
conversionSucceeded = true;
XToolkit.awtLock();
try {
targetsGetter.execute();
formats = getFormats(targetsGetter);
XlibWrapper.XChangeProperty(XToolkit.getDisplay(), requestor,
property, XAtom.XA_ATOM, dataFormat,
XlibWrapper.PropModeReplace,
nativeDataPtr, count);
} finally {
targetsGetter.dispose();
XToolkit.awtUnlock();
}
} finally {
if (nativeDataPtr != 0) {
XlibWrapper.unsafe.freeMemory(nativeDataPtr);
nativeDataPtr = 0;
}
}
return conversionSucceeded;
}
XAtom selectionAtom = XAtom.get(xse.get_selection());
XSelection selection = getSelection(selectionAtom);
if (selection != null) {
selection.isSelectionNotifyProcessed = true;
if (selection.clipboard != null) {
selection.clipboard.checkChange(formats);
}
private void fireOwnershipChanges(final boolean isOwner) {
OwnershipListener l = null;
synchronized (stateLock) {
l = ownershipListener;
}
if (null != l) {
l.ownershipChanged(isOwner);
}
}
void registerOwershipListener(OwnershipListener l) {
synchronized (stateLock) {
ownershipListener = l;
}
}
void unregisterOwnershipListener() {
synchronized (stateLock) {
ownershipListener = null;
}
}
@ -774,10 +713,9 @@ public class XSelection {
public void dispatchEvent(XEvent ev) {
switch (ev.get_type()) {
case XlibWrapper.SelectionNotify: {
XSelectionEvent xse = ev.get_xselection();
checkChange(xse);
XToolkit.awtLock();
try {
XSelectionEvent xse = ev.get_xselection();
// Ignore the SelectionNotify event if it is not the response to our last request.
if (propertyGetter != null && xse.get_time() == lastRequestServerTime) {
// The property will be None in case of convertion failure.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 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,11 +25,9 @@
package sun.awt.X11;
import java.awt.*;
import java.awt.event.*;
import java.awt.peer.*;
import java.beans.PropertyChangeListener;
import sun.awt.*;
import java.util.*;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.datatransfer.Clipboard;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureEvent;
@ -37,20 +35,27 @@ import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.MouseDragGestureRecognizer;
import java.awt.dnd.InvalidDnDOperationException;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.image.*;
import java.security.*;
import java.awt.im.InputMethodHighlight;
import java.awt.im.spi.InputMethodDescriptor;
import java.awt.datatransfer.Clipboard;
import java.awt.image.ColorModel;
import java.awt.peer.*;
import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.LookAndFeel;
import javax.swing.UIDefaults;
import java.util.logging.*;
import sun.awt.*;
import sun.font.FontManager;
import sun.misc.PerformanceLogger;
import sun.print.PrintJob2D;
import java.lang.reflect.*;
public class XToolkit extends UNIXToolkit implements Runnable, XConstants {
public final class XToolkit extends UNIXToolkit implements Runnable, XConstants
{
private static Logger log = Logger.getLogger("sun.awt.X11.XToolkit");
private static Logger eventLog = Logger.getLogger("sun.awt.X11.event.XToolkit");
private static final Logger timeoutTaskLog = Logger.getLogger("sun.awt.X11.timeoutTask.XToolkit");
@ -1871,9 +1876,7 @@ public class XToolkit extends UNIXToolkit implements Runnable, XConstants {
}
public boolean isAlwaysOnTopSupported() {
Iterator iter = XWM.getWM().getProtocols(XLayerProtocol.class).iterator();
while (iter.hasNext()) {
XLayerProtocol proto = (XLayerProtocol)iter.next();
for (XLayerProtocol proto : XWM.getWM().getProtocols(XLayerProtocol.class)) {
if (proto.supportsLayer(XLayerProtocol.LAYER_ALWAYS_ON_TOP)) {
return true;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2005-2008 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
@ -31,11 +31,8 @@ import java.awt.peer.TrayIconPeer;
import sun.awt.*;
import java.awt.image.*;
import java.text.BreakIterator;
import java.util.Vector;
import java.lang.reflect.Field;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.AbstractQueue;
import java.util.concurrent.ArrayBlockingQueue;
import java.security.AccessController;
import java.security.PrivilegedAction;
@ -629,7 +626,7 @@ public class XTrayIconPeer implements TrayIconPeer {
final static int TOOLTIP_MAX_LENGTH = 64;
final static int TOOLTIP_MOUSE_CURSOR_INDENT = 5;
final static Color TOOLTIP_BACKGROUND_COLOR = new Color(255, 255, 220);
final static Font TOOLTIP_TEXT_FONT = XWindow.defaultFont;
final static Font TOOLTIP_TEXT_FONT = XWindow.getDefaultFont();
Tooltip(XTrayIconPeer xtiPeer, Frame parent) {
super(parent, Color.black);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2008 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
@ -31,20 +31,23 @@
package sun.awt.X11;
import sun.misc.Unsafe;
import java.util.regex.*;
import java.awt.Insets;
import java.awt.Frame;
import java.awt.Rectangle;
import java.util.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import java.awt.Insets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Class incapsulating knowledge about window managers in general
* Descendants should provide some information about specific window manager.
*/
class XWM implements MWMConstants, XUtilConstants {
final class XWM implements MWMConstants, XUtilConstants
{
private final static Logger log = Logger.getLogger("sun.awt.X11.XWM");
private final static Logger insLog = Logger.getLogger("sun.awt.X11.insets.XWM");
@ -1026,21 +1029,21 @@ class XWM implements MWMConstants, XUtilConstants {
/*****************************************************************************\
* Protocols support
*/
HashMap<Class<?>, Collection<XProtocol>> protocolsMap = new HashMap<Class<?>, Collection<XProtocol>>();
private HashMap<Class<?>, Collection<?>> protocolsMap = new HashMap<Class<?>, Collection<?>>();
/**
* Returns all protocols supporting given protocol interface
*/
Collection<XProtocol> getProtocols(Class protocolInterface) {
Collection<XProtocol> res = protocolsMap.get(protocolInterface);
<T> Collection<T> getProtocols(Class<T> protocolInterface) {
Collection<T> res = (Collection<T>) protocolsMap.get(protocolInterface);
if (res != null) {
return (Collection<XProtocol>)res;
return res;
} else {
return new LinkedList<XProtocol>();
return new LinkedList<T>();
}
}
void addProtocol(Class protocolInterface, XProtocol protocol) {
Collection<XProtocol> protocols = getProtocols(protocolInterface);
private <T> void addProtocol(Class<T> protocolInterface, T protocol) {
Collection<T> protocols = getProtocols(protocolInterface);
protocols.add(protocol);
protocolsMap.put(protocolInterface, protocols);
}
@ -1085,9 +1088,7 @@ class XWM implements MWMConstants, XUtilConstants {
}
/* FALLTROUGH */
case Frame.MAXIMIZED_BOTH:
Iterator iter = getProtocols(XStateProtocol.class).iterator();
while (iter.hasNext()) {
XStateProtocol proto = (XStateProtocol)iter.next();
for (XStateProtocol proto : getProtocols(XStateProtocol.class)) {
if (proto.supportsState(state)) {
return true;
}
@ -1105,10 +1106,8 @@ class XWM implements MWMConstants, XUtilConstants {
int getExtendedState(XWindowPeer window) {
Iterator iter = getProtocols(XStateProtocol.class).iterator();
int state = 0;
while (iter.hasNext()) {
XStateProtocol proto = (XStateProtocol)iter.next();
for (XStateProtocol proto : getProtocols(XStateProtocol.class)) {
state |= proto.getState(window);
}
if (state != 0) {
@ -1127,18 +1126,17 @@ class XWM implements MWMConstants, XUtilConstants {
/*
* Check if property change is a window state protocol message.
* If it is - return the new state as Integer, otherwise return null
*/
Integer isStateChange(XDecoratedPeer window, XPropertyEvent e) {
boolean isStateChange(XDecoratedPeer window, XPropertyEvent e) {
if (!window.isShowing()) {
stateLog.finer("Window is not showing");
return null;
return false;
}
int wm_state = window.getWMState();
if (wm_state == XlibWrapper.WithdrawnState) {
stateLog.finer("WithdrawnState");
return null;
return false;
} else {
stateLog.finer("Window WM_STATE is " + wm_state);
}
@ -1147,26 +1145,26 @@ class XWM implements MWMConstants, XUtilConstants {
is_state_change = true;
}
Iterator iter = getProtocols(XStateProtocol.class).iterator();
while (iter.hasNext()) {
XStateProtocol proto = (XStateProtocol)iter.next();
for (XStateProtocol proto : getProtocols(XStateProtocol.class)) {
is_state_change |= proto.isStateChange(e);
stateLog.finest(proto + ": is state changed = " + is_state_change);
}
int res = 0;
return is_state_change;
}
if (is_state_change) {
if (wm_state == XlibWrapper.IconicState) {
res = Frame.ICONIFIED;
} else {
res = Frame.NORMAL;
}
res |= getExtendedState(window);
}
if (is_state_change) {
return Integer.valueOf(res);
/*
* Returns current state (including extended) of a given window.
*/
int getState(XDecoratedPeer window) {
int res = 0;
final int wm_state = window.getWMState();
if (wm_state == XlibWrapper.IconicState) {
res = Frame.ICONIFIED;
} else {
return null;
res = Frame.NORMAL;
}
res |= getExtendedState(window);
return res;
}
/*****************************************************************************\
@ -1180,9 +1178,7 @@ class XWM implements MWMConstants, XUtilConstants {
* in XLayerProtocol
*/
void setLayer(XWindowPeer window, int layer) {
Iterator iter = getProtocols(XLayerProtocol.class).iterator();
while (iter.hasNext()) {
XLayerProtocol proto = (XLayerProtocol)iter.next();
for (XLayerProtocol proto : getProtocols(XLayerProtocol.class)) {
if (proto.supportsLayer(layer)) {
proto.setLayer(window, layer);
}
@ -1191,9 +1187,7 @@ class XWM implements MWMConstants, XUtilConstants {
}
void setExtendedState(XWindowPeer window, int state) {
Iterator iter = getProtocols(XStateProtocol.class).iterator();
while (iter.hasNext()) {
XStateProtocol proto = (XStateProtocol)iter.next();
for (XStateProtocol proto : getProtocols(XStateProtocol.class)) {
if (proto.supportsState(state)) {
proto.setState(window, state);
break;
@ -1239,9 +1233,7 @@ class XWM implements MWMConstants, XUtilConstants {
void unshadeKludge(XDecoratedPeer window) {
assert(window.isShowing());
Iterator iter = getProtocols(XStateProtocol.class).iterator();
while (iter.hasNext()) {
XStateProtocol proto = (XStateProtocol)iter.next();
for (XStateProtocol proto : getProtocols(XStateProtocol.class)) {
proto.unshadeKludge(window);
}
XToolkit.XSync();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 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
@ -92,8 +92,16 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
SurfaceData surfaceData;
XRepaintArea paintArea;
// fallback default font object
final static Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
private static Font defaultFont;
static synchronized Font getDefaultFont() {
if (null == defaultFont) {
defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
}
return defaultFont;
}
/*
* Keeps all buttons which were pressed at the time of the last mouse
@ -333,7 +341,7 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
}
Font font = afont;
if (font == null) {
font = defaultFont;
font = XWindow.getDefaultFont();
}
return new SunGraphics2D(surfData, fgColor, bgColor, font);
}
@ -902,13 +910,11 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
super.handleConfigureNotifyEvent(xev);
insLog.log(Level.FINER, "Configure, {0}, event disabled: {1}",
new Object[] {xev, isEventDisabled(xev)});
new Object[] {xev.get_xconfigure(), isEventDisabled(xev)});
if (isEventDisabled(xev)) {
return;
}
long eventWindow = xev.get_xany().get_window();
// if ( Check if it's a resize, a move, or a stacking order change )
// {
Rectangle bounds = getBounds();
@ -982,7 +988,6 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
// called directly from this package, unlike handleKeyRelease.
// un-final it if you need to override it in a subclass.
final void handleKeyPress(XKeyEvent ev) {
int keycode = java.awt.event.KeyEvent.VK_UNDEFINED;
long keysym[] = new long[2];
char unicodeKey = 0;
keysym[0] = NoSymbol;
@ -1066,7 +1071,6 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
}
// un-private it if you need to call it from elsewhere
private void handleKeyRelease(XKeyEvent ev) {
int keycode = java.awt.event.KeyEvent.VK_UNDEFINED;
long keysym[] = new long[2];
char unicodeKey = 0;
keysym[0] = NoSymbol;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 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
@ -112,9 +112,6 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
PARENT_WINDOW, Long.valueOf(0)}));
}
// fallback default font object
static Font defaultFont;
/*
* This constant defines icon size recommended for using.
* Apparently, we should use XGetIconSizes which should
@ -162,10 +159,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
Font f = target.getFont();
if (f == null) {
if (defaultFont == null) {
defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
}
f = defaultFont;
f = XWindow.getDefaultFont();
target.setFont(f);
// we should not call setFont because it will call a repaint
// which the peer may not be ready to do yet.
@ -188,6 +182,9 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
GraphicsConfiguration gc = getGraphicsConfiguration();
((X11GraphicsDevice)gc.getDevice()).addDisplayChangedListener(this);
Rectangle bounds = (Rectangle)(params.get(BOUNDS));
params.put(BOUNDS, constrainBounds(bounds.x, bounds.y, bounds.width, bounds.height));
}
private void initWMProtocols() {
@ -437,6 +434,56 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
return ownerPeer;
}
// This method is overriden at the XDecoratedPeer to handle
// decorated windows a bit differently.
Rectangle constrainBounds(int x, int y, int width, int height) {
// We don't restrict the setBounds() operation if the code is trusted.
if (!hasWarningWindow()) {
return new Rectangle(x, y, width, height);
}
// The window bounds should be within the visible part of the screen
int newX = x;
int newY = y;
int newW = width;
int newH = height;
// Now check each point is within the visible part of the screen
GraphicsConfiguration gc = ((Window)target).getGraphicsConfiguration();
Rectangle sB = gc.getBounds();
Insets sIn = ((Window)target).getToolkit().getScreenInsets(gc);
int screenX = sB.x + sIn.left;
int screenY = sB.y + sIn.top;
int screenW = sB.width - sIn.left - sIn.right;
int screenH = sB.height - sIn.top - sIn.bottom;
// First make sure the size is withing the visible part of the screen
if (newW > screenW) {
newW = screenW;
}
if (newH > screenH) {
newH = screenH;
}
// Tweak the location if needed
if (newX < screenX) {
newX = screenX;
} else if (newX + newW > screenX + screenW) {
newX = screenX + screenW - newW;
}
if (newY < screenY) {
newY = screenY;
} else if (newY + newH > screenY + screenH) {
newY = screenY + screenH - newH;
}
return new Rectangle(newX, newY, newW, newH);
}
//Fix for 6318144: PIT:Setting Min Size bigger than current size enlarges
//the window but fails to revalidate, Sol-CDE
//This bug is regression for
@ -445,10 +492,14 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
//Note that this function is overriden in XDecoratedPeer so event
//posting is not changing for decorated peers
public void setBounds(int x, int y, int width, int height, int op) {
Rectangle newBounds = constrainBounds(x, y, width, height);
XToolkit.awtLock();
try {
Rectangle oldBounds = getBounds();
super.setBounds(x, y, width, height, op);
super.setBounds(newBounds.x, newBounds.y, newBounds.width, newBounds.height, op);
Rectangle bounds = getBounds();
XSizeHints hints = getHints();
@ -1035,7 +1086,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
return !(target instanceof Frame || target instanceof Dialog);
}
boolean hasWarningWindow() {
return warningWindow != null;
return ((Window)target).getWarningString() != null;
}
// The height of menu bar window

View File

@ -102,4 +102,9 @@ class MDialogPeer extends MWindowPeer implements DialogPeer, MInputMethodControl
public void blockWindows(java.util.List<Window> toBlock) {
// do nothing
}
@Override
final boolean isTargetUndecorated() {
return ((Dialog)target).isUndecorated();
}
}

View File

@ -204,4 +204,10 @@ public class MEmbeddedFramePeer extends MFramePeer {
}
public native Rectangle getBoundsPrivate();
@Override
Rectangle constrainBounds(int x, int y, int width, int height) {
// We don't constrain the bounds of the EmbeddedFrames
return new Rectangle(x, y, width, height);
}
}

View File

@ -503,4 +503,9 @@ class MFramePeer extends MWindowPeer implements FramePeer, MInputMethodControl {
public Rectangle getBoundsPrivate() {
return getBounds();
}
@Override
final boolean isTargetUndecorated() {
return ((Frame)target).isUndecorated();
}
}

View File

@ -113,6 +113,12 @@ DisplayChangedListener {
insets.right = getInset("awt.frame.rightInset", -1);
}
Rectangle bounds = target.getBounds();
sysX = bounds.x;
sysY = bounds.y;
sysW = bounds.width;
sysH = bounds.height;
super.init(target);
InputMethodManager imm = InputMethodManager.getInstance();
String menuString = imm.getTriggerMenuString();
@ -150,6 +156,7 @@ DisplayChangedListener {
GraphicsConfiguration gc = getGraphicsConfiguration();
((X11GraphicsDevice)gc.getDevice()).addDisplayChangedListener(this);
}
/* Support for multiple icons is not implemented in MAWT */
@ -246,6 +253,8 @@ DisplayChangedListener {
// NOTE: This method may be called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public void handleResize(int width, int height) {
sysW = width;
sysH = height;
// REMIND: Is this secure? Can client code subclass input method?
if (!tcList.isEmpty() &&
@ -268,6 +277,8 @@ DisplayChangedListener {
}
public void handleMoved(int x, int y) {
sysX = x;
sysY = y;
postEvent(new ComponentEvent(target, ComponentEvent.COMPONENT_MOVED));
}
@ -505,4 +516,87 @@ DisplayChangedListener {
}
return false;
}
private final boolean hasWarningWindow() {
return ((Window)target).getWarningString() != null;
}
// This method is overriden at Dialog and Frame peers.
boolean isTargetUndecorated() {
return true;
}
private volatile int sysX = 0;
private volatile int sysY = 0;
private volatile int sysW = 0;
private volatile int sysH = 0;
Rectangle constrainBounds(int x, int y, int width, int height) {
// We don't restrict the setBounds() operation if the code is trusted.
if (!hasWarningWindow()) {
return new Rectangle(x, y, width, height);
}
int newX = x;
int newY = y;
int newW = width;
int newH = height;
GraphicsConfiguration gc = ((Window)target).getGraphicsConfiguration();
Rectangle sB = gc.getBounds();
Insets sIn = ((Window)target).getToolkit().getScreenInsets(gc);
int screenW = sB.width - sIn.left - sIn.right;
int screenH = sB.height - sIn.top - sIn.bottom;
// If it's undecorated or is not currently visible,
// then check each point is within the visible part of the screen
if (!target.isVisible() || isTargetUndecorated()) {
int screenX = sB.x + sIn.left;
int screenY = sB.y + sIn.top;
// First make sure the size is withing the visible part of the screen
if (newW > screenW) {
newW = screenW;
}
if (newH > screenH) {
newH = screenH;
}
// Tweak the location if needed
if (newX < screenX) {
newX = screenX;
} else if (newX + newW > screenX + screenW) {
newX = screenX + screenW - newW;
}
if (newY < screenY) {
newY = screenY;
} else if (newY + newH > screenY + screenH) {
newY = screenY + screenH - newH;
}
} else {
int maxW = Math.max(screenW, sysW);
int maxH = Math.max(screenH, sysH);
// Make sure the size is withing the visible part of the screen
// OR is less that the current size of the window.
if (newW > maxW) {
newW = maxW;
}
if (newH > maxH) {
newH = maxH;
}
}
return new Rectangle(newX, newY, newW, newH);
}
public void setBounds(int x, int y, int width, int height, int op) {
Rectangle newBounds = constrainBounds(x, y, width, height);
super.setBounds(newBounds.x, newBounds.y, newBounds.width, newBounds.height, op);
}
}

View File

@ -108,11 +108,18 @@ class WDialogPeer extends WWindowPeer implements DialogPeer {
}
}
@Override
boolean isTargetUndecorated() {
return ((Dialog)target).isUndecorated();
}
public void reshape(int x, int y, int width, int height) {
Rectangle newBounds = constrainBounds(x, y, width, height);
if (((Dialog)target).isUndecorated()) {
super.reshape(x,y,width,height);
super.reshape(newBounds.x, newBounds.y, newBounds.width, newBounds.height);
} else {
reshapeFrame(x,y,width,height);
reshapeFrame(newBounds.x, newBounds.y, newBounds.width, newBounds.height);
}
}

View File

@ -65,4 +65,10 @@ public class WEmbeddedFramePeer extends WFramePeer {
public native Rectangle getBoundsPrivate();
public native void synthesizeWmActivate(boolean doActivate);
@Override
Rectangle constrainBounds(int x, int y, int width, int height) {
// We don't constrain the bounds of the EmbeddedFrames
return new Rectangle(x, y, width, height);
}
}

View File

@ -64,11 +64,18 @@ class WFramePeer extends WWindowPeer implements FramePeer {
}
}
@Override
boolean isTargetUndecorated() {
return ((Frame)target).isUndecorated();
}
public void reshape(int x, int y, int width, int height) {
Rectangle newBounds = constrainBounds(x, y, width, height);
if (((Frame)target).isUndecorated()) {
super.reshape(x,y,width,height);
super.reshape(newBounds.x, newBounds.y, newBounds.width, newBounds.height);
} else {
reshapeFrame(x,y,width,height);
reshapeFrame(newBounds.x, newBounds.y, newBounds.width, newBounds.height);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1996-2008 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,8 +30,12 @@ abstract class WObjectPeer {
initIDs();
}
long pData; // The Windows handle for the native widget.
Object target; // The associated AWT object.
// The Windows handle for the native widget.
long pData;
// if the native peer has been destroyed
boolean destroyed = false;
// The associated AWT object.
Object target;
private volatile boolean disposed;

View File

@ -434,6 +434,97 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer {
private native void nativeGrab();
private native void nativeUngrab();
private final boolean hasWarningWindow() {
return ((Window)target).getWarningString() != null;
}
boolean isTargetUndecorated() {
return true;
}
// These are the peer bounds. They get updated at:
// 1. the WWindowPeer.setBounds() method.
// 2. the native code (on WM_SIZE/WM_MOVE)
private volatile int sysX = 0;
private volatile int sysY = 0;
private volatile int sysW = 0;
private volatile int sysH = 0;
Rectangle constrainBounds(int x, int y, int width, int height) {
// We don't restrict the setBounds() operation if the code is trusted.
if (!hasWarningWindow()) {
return new Rectangle(x, y, width, height);
}
int newX = x;
int newY = y;
int newW = width;
int newH = height;
GraphicsConfiguration gc = ((Window)target).getGraphicsConfiguration();
Rectangle sB = gc.getBounds();
Insets sIn = ((Window)target).getToolkit().getScreenInsets(gc);
int screenW = sB.width - sIn.left - sIn.right;
int screenH = sB.height - sIn.top - sIn.bottom;
// If it's undecorated or is not currently visible
if (!((Window)target).isVisible() || isTargetUndecorated()) {
// Now check each point is within the visible part of the screen
int screenX = sB.x + sIn.left;
int screenY = sB.y + sIn.top;
// First make sure the size is withing the visible part of the screen
if (newW > screenW) {
newW = screenW;
}
if (newH > screenH) {
newH = screenH;
}
// Tweak the location if needed
if (newX < screenX) {
newX = screenX;
} else if (newX + newW > screenX + screenW) {
newX = screenX + screenW - newW;
}
if (newY < screenY) {
newY = screenY;
} else if (newY + newH > screenY + screenH) {
newY = screenY + screenH - newH;
}
} else {
int maxW = Math.max(screenW, sysW);
int maxH = Math.max(screenH, sysH);
// Make sure the size is withing the visible part of the screen
// OR less that the current size of the window.
if (newW > maxW) {
newW = maxW;
}
if (newH > maxH) {
newH = maxH;
}
}
return new Rectangle(newX, newY, newW, newH);
}
@Override
public void setBounds(int x, int y, int width, int height, int op) {
Rectangle newBounds = constrainBounds(x, y, width, height);
sysX = newBounds.x;
sysY = newBounds.y;
sysW = newBounds.width;
sysH = newBounds.height;
super.setBounds(newBounds.x, newBounds.y, newBounds.width, newBounds.height, op);
}
/*
* The method maps the list of the active windows to the window's AppContext,
* then the method registers ActiveWindowListener, GuiDisposedListener listeners;

View File

@ -1,5 +1,5 @@
/*
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1996-2008 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
@ -47,7 +47,7 @@ typedef AwtObject* PDATA;
JNI_CHECK_NULL_GOTO(peer, "peer", where); \
pData = JNI_GET_PDATA(peer); \
if (pData == NULL) { \
JNU_ThrowNullPointerException(env, "null pData"); \
THROW_NULL_PDATA_IF_NOT_DESTROYED(peer); \
goto where; \
} \
}
@ -63,7 +63,7 @@ typedef AwtObject* PDATA;
JNI_CHECK_NULL_RETURN(peer, "peer"); \
pData = JNI_GET_PDATA(peer); \
if (pData == NULL) { \
JNU_ThrowNullPointerException(env, "null pData"); \
THROW_NULL_PDATA_IF_NOT_DESTROYED(peer); \
return; \
} \
}
@ -96,7 +96,7 @@ typedef AwtObject* PDATA;
JNI_CHECK_NULL_RETURN_NULL(peer, "peer"); \
pData = JNI_GET_PDATA(peer); \
if (pData == NULL) { \
JNU_ThrowNullPointerException(env, "null pData"); \
THROW_NULL_PDATA_IF_NOT_DESTROYED(peer); \
return 0; \
} \
}
@ -105,16 +105,27 @@ typedef AwtObject* PDATA;
JNI_CHECK_NULL_RETURN_VAL(peer, "peer", val); \
pData = JNI_GET_PDATA(peer); \
if (pData == NULL) { \
JNU_ThrowNullPointerException(env, "null pData"); \
THROW_NULL_PDATA_IF_NOT_DESTROYED(peer); \
return val; \
} \
}
#define THROW_NULL_PDATA_IF_NOT_DESTROYED(peer) { \
jboolean destroyed = JNI_GET_DESTROYED(peer); \
if (destroyed != JNI_TRUE) { \
JNU_ThrowNullPointerException(env, "null pData"); \
} \
}
#define JNI_GET_PDATA(peer) (PDATA) env->GetLongField(peer, AwtObject::pDataID)
#define JNI_GET_DESTROYED(peer) env->GetBooleanField(peer, AwtObject::destroyedID)
#define JNI_SET_PDATA(peer, data) env->SetLongField(peer, \
AwtObject::pDataID, \
(jlong)data)
AwtObject::pDataID, \
(jlong)data)
#define JNI_SET_DESTROYED(peer) env->SetBooleanField(peer, \
AwtObject::destroyedID, \
JNI_TRUE)
/* /NEW JNI */
/*

View File

@ -1,5 +1,5 @@
/*
* Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1996-2008 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
@ -226,6 +226,8 @@ BOOL AwtComponent::m_QueryNewPaletteCalled = FALSE;
CriticalSection windowMoveLock;
BOOL windowMoveLockHeld = FALSE;
int AwtComponent::sm_wheelRotationAmount = 0;
/************************************************************************
* AwtComponent methods
*/
@ -2074,6 +2076,8 @@ MsgRouting AwtComponent::WmSetFocus(HWND hWndLostFocus)
sm_realFocusOpposite = NULL;
}
sm_wheelRotationAmount = 0;
SendFocusEvent(java_awt_event_FocusEvent_FOCUS_GAINED, hWndLostFocus);
return mrDoDefault;
@ -2105,6 +2109,7 @@ MsgRouting AwtComponent::WmKillFocus(HWND hWndGotFocus)
}
sm_focusOwner = NULL;
sm_wheelRotationAmount = 0;
SendFocusEvent(java_awt_event_FocusEvent_FOCUS_LOST, hWndGotFocus);
return mrDoDefault;
@ -2190,8 +2195,11 @@ AwtComponent::AwtSetFocus()
DWORD fgProcessID;
::GetWindowThreadProcessId(fgWindow, &fgProcessID);
if (fgProcessID != ::GetCurrentProcessId()) {
// fix for 6458497. we shouldn't request focus if it is out of our application.
if (fgProcessID != ::GetCurrentProcessId()
&& !AwtToolkit::GetInstance().IsEmbedderProcessId(fgProcessID))
{
// fix for 6458497. we shouldn't request focus if it is out of both
// our and embedder process.
return FALSE;
}
}
@ -2619,9 +2627,13 @@ MsgRouting AwtComponent::WmMouseWheel(UINT flags, int x, int y,
BOOL result;
UINT platformLines;
sm_wheelRotationAmount += wheelRotation;
// AWT interprets wheel rotation differently than win32, so we need to
// decode wheel amount.
jint newWheelRotation = wheelRotation / (-1 * WHEEL_DELTA);
jint roundedWheelRotation = sm_wheelRotationAmount / (-1 * WHEEL_DELTA);
jdouble preciseWheelRotation = (jdouble) wheelRotation / (-1 * WHEEL_DELTA);
MSG msg;
if (IS_WIN95 && !IS_WIN98) {
@ -2654,7 +2666,9 @@ MsgRouting AwtComponent::WmMouseWheel(UINT flags, int x, int y,
SendMouseWheelEvent(java_awt_event_MouseEvent_MOUSE_WHEEL, TimeHelper::getMessageTimeUTC(),
eventPt.x, eventPt.y, GetJavaModifiers(), 0, 0, scrollType,
scrollLines, newWheelRotation, &msg);
scrollLines, roundedWheelRotation, preciseWheelRotation, &msg);
sm_wheelRotationAmount %= WHEEL_DELTA;
return mrConsume;
}
@ -4986,8 +5000,8 @@ void
AwtComponent::SendMouseWheelEvent(jint id, jlong when, jint x, jint y,
jint modifiers, jint clickCount,
jboolean popupTrigger, jint scrollType,
jint scrollAmount, jint wheelRotation,
MSG *pMsg)
jint scrollAmount, jint roundedWheelRotation,
jdouble preciseWheelRotation, MSG *pMsg)
{
/* Code based not so loosely on AwtComponent::SendMouseEvent */
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
@ -5015,7 +5029,7 @@ AwtComponent::SendMouseWheelEvent(jint id, jlong when, jint x, jint y,
if (mouseWheelEventConst == NULL) {
mouseWheelEventConst =
env->GetMethodID(mouseWheelEventCls, "<init>",
"(Ljava/awt/Component;IJIIIIZIII)V");
"(Ljava/awt/Component;IJIIIIIIZIIID)V");
DASSERT(mouseWheelEventConst);
}
if (env->EnsureLocalCapacity(2) < 0) {
@ -5023,14 +5037,16 @@ AwtComponent::SendMouseWheelEvent(jint id, jlong when, jint x, jint y,
}
jobject target = GetTarget(env);
DTRACE_PRINTLN("creating MWE in JNI");
jobject mouseWheelEvent = env->NewObject(mouseWheelEventCls,
mouseWheelEventConst,
target,
id, when, modifiers,
x+insets.left, y+insets.top,
0, 0,
clickCount, popupTrigger,
scrollType, scrollAmount,
wheelRotation);
roundedWheelRotation, preciseWheelRotation);
if (safe_ExceptionOccurred(env)) {
env->ExceptionDescribe();
env->ExceptionClear();
@ -5400,6 +5416,7 @@ void AwtComponent::UnlinkObjects()
if (m_peerObject) {
env->SetLongField(m_peerObject, AwtComponent::hwndID, 0);
JNI_SET_PDATA(m_peerObject, static_cast<PDATA>(NULL));
JNI_SET_DESTROYED(m_peerObject);
env->DeleteGlobalRef(m_peerObject);
m_peerObject = NULL;
}
@ -5408,7 +5425,13 @@ void AwtComponent::UnlinkObjects()
void AwtComponent::Enable(BOOL bEnable)
{
sm_suppressFocusAndActivation = TRUE;
if (bEnable && IsTopLevel()) {
// we should not enable blocked toplevels
bEnable = !::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()));
}
::EnableWindow(GetHWnd(), bEnable);
sm_suppressFocusAndActivation = FALSE;
CriticalSection::Lock l(GetLock());
VerifyState();

View File

@ -392,7 +392,7 @@ public:
jint modifiers, jint clickCount,
jboolean popupTrigger, jint scrollType,
jint scrollAmount, jint wheelRotation,
MSG *msg = NULL);
jdouble preciseWheelRotation, MSG *msg = NULL);
/*
* Allocate and initialize a new java.awt.event.FocusEvent, and
@ -785,7 +785,9 @@ private:
int windowMoveLockPosCX;
int windowMoveLockPosCY;
private:
// 6524352: support finer-resolution
static int sm_wheelRotationAmount;
/*
* The association list of children's IDs and corresponding components.
* Some components like Choice or List are required their sizes while

View File

@ -273,6 +273,10 @@ LRESULT CALLBACK AwtDialog::MouseHookProc(int nCode,
{
HWND blocker = AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(hWnd));
HWND topMostBlocker = blocker;
HWND prevForegroundWindow = ::GetForegroundWindow();
if (::IsWindow(blocker)) {
::BringWindowToTop(hWnd);
}
while (::IsWindow(blocker)) {
topMostBlocker = blocker;
::BringWindowToTop(blocker);
@ -282,7 +286,7 @@ LRESULT CALLBACK AwtDialog::MouseHookProc(int nCode,
// no beep/flash if the mouse was clicked in the taskbar menu
// or the dialog is currently inactive
if ((::WindowFromPoint(mhs->pt) == hWnd) &&
(::GetForegroundWindow() == topMostBlocker))
(prevForegroundWindow == topMostBlocker))
{
::MessageBeep(MB_OK);
// some heuristics: 3 times x 64 milliseconds
@ -292,6 +296,7 @@ LRESULT CALLBACK AwtDialog::MouseHookProc(int nCode,
::BringWindowToTop(topMostBlocker);
::SetForegroundWindow(topMostBlocker);
}
return 1;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1996-2008 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
@ -221,8 +221,7 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent)
// Update target's dimensions to reflect this embedded window.
::GetClientRect(frame->m_hwnd, &rect);
::MapWindowPoints(frame->m_hwnd, hwndParent, (LPPOINT)&rect,
2);
::MapWindowPoints(frame->m_hwnd, hwndParent, (LPPOINT)&rect, 2);
env->SetIntField(target, AwtComponent::xID, rect.left);
env->SetIntField(target, AwtComponent::yID, rect.top);
@ -231,6 +230,7 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent)
env->SetIntField(target, AwtComponent::heightID,
rect.bottom-rect.top);
frame->InitPeerGraphicsConfig(env, self);
AwtToolkit::GetInstance().RegisterEmbedderProcessId(hwndParent);
} else {
jint state = env->GetIntField(target, AwtFrame::stateID);
DWORD exStyle;
@ -408,8 +408,9 @@ MsgRouting AwtFrame::WmShowWindow(BOOL show, UINT status)
* message. This breaks Java focus. To workaround the problem we
* set the toplevel being shown foreground programmatically.
* The fix is localized to non-foreground process case only.
* (See also: 6599270)
*/
if (show == TRUE && status == 0) {
if (!IsEmbeddedFrame() && show == TRUE && status == 0) {
HWND fgHWnd = ::GetForegroundWindow();
if (fgHWnd != NULL) {
DWORD fgProcessID;
@ -495,7 +496,7 @@ MsgRouting AwtFrame::WmMouseMove(UINT flags, int x, int y) {
::SetWindowPos(GetHWnd(), NULL, r.left, r.top,
r.right-r.left, r.bottom-r.top,
SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_NOZORDER |
SWP_NOACTIVATE | SWP_NOZORDER |
SWP_NOCOPYBITS | SWP_DEFERERASE);
}
return mrConsume;

View File

@ -1,5 +1,5 @@
/*
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1996-2008 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,6 +39,7 @@ static BOOL reportEvents = FALSE;
*/
jfieldID AwtObject::pDataID;
jfieldID AwtObject::destroyedID;
jfieldID AwtObject::targetID;
jclass AwtObject::wObjectPeerClass;
jmethodID AwtObject::getPeerForTargetMID;
@ -223,6 +224,7 @@ Java_sun_awt_windows_WObjectPeer_initIDs(JNIEnv *env, jclass cls) {
AwtObject::wObjectPeerClass = (jclass)env->NewGlobalRef(cls);
AwtObject::pDataID = env->GetFieldID(cls, "pData", "J");
AwtObject::destroyedID = env->GetFieldID(cls, "destroyed", "Z");
AwtObject::targetID = env->GetFieldID(cls, "target",
"Ljava/lang/Object;");
@ -233,6 +235,7 @@ Java_sun_awt_windows_WObjectPeer_initIDs(JNIEnv *env, jclass cls) {
AwtObject::createErrorID = env->GetFieldID(cls, "createError", "Ljava/lang/Error;");
DASSERT(AwtObject::pDataID != NULL);
DASSERT(AwtObject::destroyedID != NULL);
DASSERT(AwtObject::targetID != NULL);
DASSERT(AwtObject::getPeerForTargetMID != NULL);
DASSERT(AwtObject::createErrorID != NULL);

View File

@ -1,5 +1,5 @@
/*
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1996-2008 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
@ -51,6 +51,7 @@ public:
/* sun.awt.windows.WObjectPeer field and method ids */
static jfieldID pDataID;
static jfieldID destroyedID;
static jfieldID targetID;
static jmethodID getPeerForTargetMID;

View File

@ -1,5 +1,5 @@
/*
* Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1996-2008 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
@ -354,6 +354,7 @@ AwtToolkit::AwtToolkit() {
m_dllHandle = NULL;
m_displayChanged = FALSE;
m_embedderProcessID = 0;
// XXX: keyboard mapping should really be moved out of AwtComponent
AwtComponent::InitDynamicKeyMapTable();
@ -1442,49 +1443,17 @@ void hang_if_shutdown(void)
}
}
/*
* Returns a reference to the class java.awt.Component.
*/
jclass
getComponentClass(JNIEnv *env)
// for now we support only one embedder, but should be ready for future
void AwtToolkit::RegisterEmbedderProcessId(HWND embedder)
{
static jclass componentCls = NULL;
// get global reference of java/awt/Component class (run only once)
if (componentCls == NULL) {
jclass componentClsLocal = env->FindClass("java/awt/Component");
DASSERT(componentClsLocal != NULL);
if (componentClsLocal == NULL) {
/* exception already thrown */
return NULL;
}
componentCls = (jclass)env->NewGlobalRef(componentClsLocal);
env->DeleteLocalRef(componentClsLocal);
if (m_embedderProcessID) {
// we already set embedder process and do not expect
// two different processes to embed the same AwtToolkit
return;
}
return componentCls;
}
/*
* Returns a reference to the class java.awt.MenuComponent.
*/
jclass
getMenuComponentClass(JNIEnv *env)
{
static jclass menuComponentCls = NULL;
// get global reference of java/awt/MenuComponent class (run only once)
if (menuComponentCls == NULL) {
jclass menuComponentClsLocal = env->FindClass("java/awt/MenuComponent");
DASSERT(menuComponentClsLocal != NULL);
if (menuComponentClsLocal == NULL) {
/* exception already thrown */
return NULL;
}
menuComponentCls = (jclass)env->NewGlobalRef(menuComponentClsLocal);
env->DeleteLocalRef(menuComponentClsLocal);
}
return menuComponentCls;
embedder = ::GetAncestor(embedder, GA_ROOT);
::GetWindowThreadProcessId(embedder, &m_embedderProcessID);
}
JNIEnv* AwtToolkit::m_env;

View File

@ -1,5 +1,5 @@
/*
* Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1996-2008 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
@ -426,10 +426,17 @@ private:
*/
private:
BOOL m_displayChanged; /* Tracks displayChanged events */
// 0 means we are not embedded.
DWORD m_embedderProcessID;
public:
BOOL HasDisplayChanged() { return m_displayChanged; }
void ResetDisplayChanged() { m_displayChanged = FALSE; }
void RegisterEmbedderProcessId(HWND);
BOOL IsEmbedderProcessId(const DWORD processID) const
{
return m_embedderProcessID && (processID == m_embedderProcessID);
}
private:
static JNIEnv *m_env;

View File

@ -125,6 +125,11 @@ jfieldID AwtWindow::autoRequestFocusID;
jclass AwtWindow::wwindowPeerCls;
jmethodID AwtWindow::getActiveWindowsMID;
jfieldID AwtWindow::sysXID;
jfieldID AwtWindow::sysYID;
jfieldID AwtWindow::sysWID;
jfieldID AwtWindow::sysHID;
int AwtWindow::ms_instanceCounter = 0;
HHOOK AwtWindow::ms_hCBTFilter;
AwtWindow * AwtWindow::m_grabbedWindow = NULL;
@ -180,7 +185,6 @@ void AwtWindow::Dispose()
}
::RemoveProp(GetHWnd(), ModalBlockerProp);
::RemoveProp(GetHWnd(), ModalSaveWSEXProp);
if (m_grabbedWindow == this) {
Ungrab();
@ -330,8 +334,11 @@ LRESULT CALLBACK AwtWindow::CBTFilter(int nCode, WPARAM wParam, LPARAM lParam)
if (nCode == HCBT_ACTIVATE || nCode == HCBT_SETFOCUS) {
AwtComponent *comp = AwtComponent::GetComponent((HWND)wParam);
if (comp != NULL && comp->IsTopLevel() && !((AwtWindow*)comp)->IsFocusableWindow()) {
return 1; // Don't change focus/activation.
if (comp != NULL && comp->IsTopLevel()) {
AwtWindow* win = (AwtWindow*)comp;
if (!win->IsFocusableWindow() || win->m_filterFocusAndActivation) {
return 1; // Don't change focus/activation.
}
}
}
return ::CallNextHookEx(AwtWindow::ms_hCBTFilter, nCode, wParam, lParam);
@ -1053,6 +1060,8 @@ MsgRouting AwtWindow::WmMove(int x, int y)
(env)->SetIntField(target, AwtComponent::xID, rect.left);
(env)->SetIntField(target, AwtComponent::yID, rect.top);
(env)->SetIntField(peer, AwtWindow::sysXID, rect.left);
(env)->SetIntField(peer, AwtWindow::sysYID, rect.top);
SendComponentEvent(java_awt_event_ComponentEvent_COMPONENT_MOVED);
env->DeleteLocalRef(target);
@ -1116,6 +1125,11 @@ MsgRouting AwtWindow::WmSize(UINT type, int w, int h)
(env)->SetIntField(target, AwtComponent::widthID, newWidth);
(env)->SetIntField(target, AwtComponent::heightID, newHeight);
jobject peer = GetPeer(env);
(env)->SetIntField(peer, AwtWindow::sysWID, newWidth);
(env)->SetIntField(peer, AwtWindow::sysHID, newHeight);
if (!AwtWindow::IsResizing()) {
WindowResized();
}
@ -1455,20 +1469,17 @@ void AwtWindow::SetModalBlocker(HWND window, HWND blocker) {
if (!::IsWindow(window)) {
return;
}
DWORD exStyle = ::GetWindowLong(window, GWL_EXSTYLE);
if (::IsWindow(blocker)) {
// save WS_EX_NOACTIVATE and WS_EX_APPWINDOW styles
DWORD saveStyle = exStyle & (AWT_WS_EX_NOACTIVATE | WS_EX_APPWINDOW);
::SetProp(window, ModalSaveWSEXProp, reinterpret_cast<HANDLE>(saveStyle));
::SetWindowLong(window, GWL_EXSTYLE, (exStyle | AWT_WS_EX_NOACTIVATE) & ~WS_EX_APPWINDOW);
::SetProp(window, ModalBlockerProp, reinterpret_cast<HANDLE>(blocker));
::EnableWindow(window, FALSE);
} else {
// restore WS_EX_NOACTIVATE and WS_EX_APPWINDOW styles
DWORD saveStyle = reinterpret_cast<DWORD>(::GetProp(window, ModalSaveWSEXProp));
::SetWindowLong(window, GWL_EXSTYLE,
(exStyle & ~(AWT_WS_EX_NOACTIVATE | WS_EX_APPWINDOW)) | saveStyle);
::RemoveProp(window, ModalSaveWSEXProp);
::RemoveProp(window, ModalBlockerProp);
AwtComponent *comp = AwtComponent::GetComponent(window);
// we don't expect to be called with non-java HWNDs
DASSERT(comp && comp->IsTopLevel());
// we should not unblock disabled toplevels
::EnableWindow(window, comp->isEnabled());
}
}
@ -1754,17 +1765,22 @@ void AwtWindow::_ReshapeFrame(void *param)
// Fix for 4459064 : do not enforce thresholds for embedded frames
if (!p->IsEmbeddedFrame())
{
jobject peer = p->GetPeer(env);
int minWidth = ::GetSystemMetrics(SM_CXMIN);
int minHeight = ::GetSystemMetrics(SM_CYMIN);
if (w < minWidth)
{
env->SetIntField(target, AwtComponent::widthID,
w = minWidth);
env->SetIntField(peer, AwtWindow::sysWID,
w);
}
if (h < minHeight)
{
env->SetIntField(target, AwtComponent::heightID,
h = minHeight);
env->SetIntField(peer, AwtWindow::sysHID,
h);
}
}
env->DeleteLocalRef(target);
@ -2148,6 +2164,11 @@ Java_sun_awt_windows_WWindowPeer_initIDs(JNIEnv *env, jclass cls)
env->GetStaticMethodID(cls, "getActiveWindowHandles", "()[J");
DASSERT(AwtWindow::getActiveWindowsMID != NULL);
AwtWindow::sysXID = env->GetFieldID(cls, "sysX", "I");
AwtWindow::sysYID = env->GetFieldID(cls, "sysY", "I");
AwtWindow::sysWID = env->GetFieldID(cls, "sysW", "I");
AwtWindow::sysHID = env->GetFieldID(cls, "sysH", "I");
CATCH_BAD_ALLOC;
}

View File

@ -33,7 +33,6 @@
// property name tagging windows disabled by modality
static LPCTSTR ModalBlockerProp = TEXT("SunAwtModalBlockerProp");
static LPCTSTR ModalSaveWSEXProp = TEXT("SunAwtModalSaveWSEXProp");
static LPCTSTR ModalDialogPeerProp = TEXT("SunAwtModalDialogPeerProp");
#ifndef WH_MOUSE_LL
@ -63,6 +62,12 @@ public:
/* long[] getActiveWindowHandles() method in WWindowPeer */
static jmethodID getActiveWindowsMID;
// The coordinates at the peer.
static jfieldID sysXID;
static jfieldID sysYID;
static jfieldID sysWID;
static jfieldID sysHID;
AwtWindow();
virtual ~AwtWindow();

View File

@ -0,0 +1,413 @@
/*
* Copyright 2008 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 6581927
@summary Non-focusable frame should honor the size of the frame buttons/decorations when resizing
@library ../../regtesthelpers
@build Util
@author anthony.petrov@...: area=awt.toplevel
@run main NonFocusableResizableTooSmall
*/
/**
* NonFocusableResizableTooSmall.java
*
* summary: Non-focusable frame should honor the size of the frame buttons/decorations when resizing
*/
import java.awt.*;
import java.awt.event.*;
import test.java.awt.regtesthelpers.Util;
public class NonFocusableResizableTooSmall
{
//*** test-writer defined static variables go here ***
private static void init()
{
//*** Create instructions for the user here ***
String[] instructions =
{
"This is an AUTOMATIC test, simply wait until it is done.",
"The result (passed or failed) will be shown in the",
"message window below."
};
Sysout.createDialog( );
Sysout.printInstructions( instructions );
final Frame frame = new Frame();
frame.setFocusableWindowState(false);
frame.setSize(200, 100);
frame.setVisible(true);
final Robot robot = Util.createRobot();
robot.setAutoDelay(20);
// To be sure the window is shown and packed
Util.waitForIdle(robot);
final Insets insets = frame.getInsets();
System.out.println("The insets of the frame: " + insets);
if (insets.right == 0 || insets.bottom == 0) {
System.out.println("The test environment must have non-zero right & bottom insets!");
pass();
return;
}
// Let's move the mouse pointer to the bottom-right coner of the frame (the "size-grip")
final Rectangle bounds1 = frame.getBounds();
System.out.println("The bounds before resizing: " + bounds1);
robot.mouseMove(bounds1.x + bounds1.width - 1, bounds1.y + bounds1.height - 1);
// ... and start resizing to some very small
robot.mousePress( InputEvent.BUTTON1_MASK );
// Now resize the frame so that the width is smaller
// than the widths of the left and the right borders.
// The sum of widths of the icon of the frame + the control-buttons
// (close, minimize, etc.) should be definitely larger!
robot.mouseMove(bounds1.x + insets.left + insets.right - 5, bounds1.y + bounds1.height - 1);
Util.waitForIdle(robot);
robot.mouseRelease( InputEvent.BUTTON1_MASK );
Util.waitForIdle(robot);
// Check the current bounds of the frame
final Rectangle bounds2 = frame.getBounds();
System.out.println("The bounds after resizing: " + bounds2);
if (bounds2.width <= (insets.left + insets.right)) {
fail("The frame has been resized to very small.");
}
pass();
}//End init()
/*****************************************************
* Standard Test Machinery Section
* DO NOT modify anything in this section -- it's a
* standard chunk of code which has all of the
* synchronisation necessary for the test harness.
* By keeping it the same in all tests, it is easier
* to read and understand someone else's test, as
* well as insuring that all tests behave correctly
* with the test harness.
* There is a section following this for test-
* classes
******************************************************/
private static boolean theTestPassed = false;
private static boolean testGeneratedInterrupt = false;
private static String failureMessage = "";
private static Thread mainThread = null;
private static int sleepTime = 300000;
// Not sure about what happens if multiple of this test are
// instantiated in the same VM. Being static (and using
// static vars), it aint gonna work. Not worrying about
// it for now.
public static void main( String args[] ) throws InterruptedException
{
mainThread = Thread.currentThread();
try
{
init();
}
catch( TestPassedException e )
{
//The test passed, so just return from main and harness will
// interepret this return as a pass
return;
}
//At this point, neither test pass nor test fail has been
// called -- either would have thrown an exception and ended the
// test, so we know we have multiple threads.
//Test involves other threads, so sleep and wait for them to
// called pass() or fail()
try
{
Thread.sleep( sleepTime );
//Timed out, so fail the test
throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
}
catch (InterruptedException e)
{
//The test harness may have interrupted the test. If so, rethrow the exception
// so that the harness gets it and deals with it.
if( ! testGeneratedInterrupt ) throw e;
//reset flag in case hit this code more than once for some reason (just safety)
testGeneratedInterrupt = false;
if ( theTestPassed == false )
{
throw new RuntimeException( failureMessage );
}
}
}//main
public static synchronized void setTimeoutTo( int seconds )
{
sleepTime = seconds * 1000;
}
public static synchronized void pass()
{
Sysout.println( "The test passed." );
Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
//first check if this is executing in main thread
if ( mainThread == Thread.currentThread() )
{
//Still in the main thread, so set the flag just for kicks,
// and throw a test passed exception which will be caught
// and end the test.
theTestPassed = true;
throw new TestPassedException();
}
theTestPassed = true;
testGeneratedInterrupt = true;
mainThread.interrupt();
}//pass()
public static synchronized void fail()
{
//test writer didn't specify why test failed, so give generic
fail( "it just plain failed! :-)" );
}
public static synchronized void fail( String whyFailed )
{
Sysout.println( "The test failed: " + whyFailed );
Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
//check if this called from main thread
if ( mainThread == Thread.currentThread() )
{
//If main thread, fail now 'cause not sleeping
throw new RuntimeException( whyFailed );
}
theTestPassed = false;
testGeneratedInterrupt = true;
failureMessage = whyFailed;
mainThread.interrupt();
}//fail()
}// class NonFocusableResizableTooSmall
//This exception is used to exit from any level of call nesting
// when it's determined that the test has passed, and immediately
// end the test.
class TestPassedException extends RuntimeException
{
}
//*********** End Standard Test Machinery Section **********
//************ Begin classes defined for the test ****************
// if want to make listeners, here is the recommended place for them, then instantiate
// them in init()
/* Example of a class which may be written as part of a test
class NewClass implements anInterface
{
static int newVar = 0;
public void eventDispatched(AWTEvent e)
{
//Counting events to see if we get enough
eventCount++;
if( eventCount == 20 )
{
//got enough events, so pass
NonFocusableResizableTooSmall.pass();
}
else if( tries == 20 )
{
//tried too many times without getting enough events so fail
NonFocusableResizableTooSmall.fail();
}
}// eventDispatched()
}// NewClass class
*/
//************** End classes defined for the test *******************
/****************************************************
Standard Test Machinery
DO NOT modify anything below -- it's a standard
chunk of code whose purpose is to make user
interaction uniform, and thereby make it simpler
to read and understand someone else's test.
****************************************************/
/**
This is part of the standard test machinery.
It creates a dialog (with the instructions), and is the interface
for sending text messages to the user.
To print the instructions, send an array of strings to Sysout.createDialog
WithInstructions method. Put one line of instructions per array entry.
To display a message for the tester to see, simply call Sysout.println
with the string to be displayed.
This mimics System.out.println but works within the test harness as well
as standalone.
*/
class Sysout
{
private static TestDialog dialog;
public static void createDialogWithInstructions( String[] instructions )
{
dialog = new TestDialog( new Frame(), "Instructions" );
dialog.printInstructions( instructions );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
public static void createDialog( )
{
dialog = new TestDialog( new Frame(), "Instructions" );
String[] defInstr = { "Instructions will appear here. ", "" } ;
dialog.printInstructions( defInstr );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
public static void printInstructions( String[] instructions )
{
dialog.printInstructions( instructions );
}
public static void println( String messageIn )
{
dialog.displayMessage( messageIn );
System.out.println(messageIn);
}
}// Sysout class
/**
This is part of the standard test machinery. It provides a place for the
test instructions to be displayed, and a place for interactive messages
to the user to be displayed.
To have the test instructions displayed, see Sysout.
To have a message to the user be displayed, see Sysout.
Do not call anything in this dialog directly.
*/
class TestDialog extends Dialog
{
TextArea instructionsText;
TextArea messageText;
int maxStringLength = 80;
//DO NOT call this directly, go through Sysout
public TestDialog( Frame frame, String name )
{
super( frame, name );
int scrollBoth = TextArea.SCROLLBARS_BOTH;
instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
add( "North", instructionsText );
messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
add("Center", messageText);
pack();
setVisible(true);
}// TestDialog()
//DO NOT call this directly, go through Sysout
public void printInstructions( String[] instructions )
{
//Clear out any current instructions
instructionsText.setText( "" );
//Go down array of instruction strings
String printStr, remainingStr;
for( int i=0; i < instructions.length; i++ )
{
//chop up each into pieces maxSringLength long
remainingStr = instructions[ i ];
while( remainingStr.length() > 0 )
{
//if longer than max then chop off first max chars to print
if( remainingStr.length() >= maxStringLength )
{
//Try to chop on a word boundary
int posOfSpace = remainingStr.
lastIndexOf( ' ', maxStringLength - 1 );
if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
printStr = remainingStr.substring( 0, posOfSpace + 1 );
remainingStr = remainingStr.substring( posOfSpace + 1 );
}
//else just print
else
{
printStr = remainingStr;
remainingStr = "";
}
instructionsText.append( printStr + "\n" );
}// while
}// for
}//printInstructions()
//DO NOT call this directly, go through Sysout
public void displayMessage( String messageIn )
{
messageText.append( messageIn + "\n" );
System.out.println(messageIn);
}
}// TestDialog class

View File

@ -0,0 +1,108 @@
/*
* Copyright 2007 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 %W% %E%
@bug 6598089
@summary Tests restoring focus on a single disabled coponent
@author Anton Tarasov: area=awt-focus
@library ../../regtesthelpers
@build Util
@run main RestoreFocusOnDisabledComponentTest
*/
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import test.java.awt.regtesthelpers.Util;
/*
* The bug is not reproducible on Windows.
*/
public class RestoreFocusOnDisabledComponentTest extends Applet {
Frame frame = new Frame("Frame") {public String toString() {return "FRAME";}};
Button b0 = new Button("button0") {public String toString() {return "B-0";}};
Button b1 = new Button("button1") {public String toString() {return "B-1";}};
volatile int nFocused;
Robot robot;
public static void main(String[] args) {
RestoreFocusOnDisabledComponentTest app = new RestoreFocusOnDisabledComponentTest();
app.init();
app.start();
}
public void init() {
robot = Util.createRobot();
}
public void start() {
frame.add(b0);
frame.add(b1);
frame.setLayout(new FlowLayout());
frame.pack();
frame.setVisible(true);
Util.waitForIdle(robot);
KeyboardFocusManager.setCurrentKeyboardFocusManager(new DefaultKeyboardFocusManager() {
public boolean dispatchEvent(AWTEvent e) {
if (e.getID() == FocusEvent.FOCUS_GAINED) {
// Trying to emulate timings. b1 should be disabled just by the time it gets
// FOCUS_GAINED event. The latter is a result of disabling b0 that initiates
// focus auto transfer.
if (e.getSource() == b1) {
b1.setEnabled(false);
} else if (e.getSource() == b0) {
if (++nFocused > 10) {
nFocused = -1;
throw new TestFailedException("Focus went into busy loop!");
}
}
}
return super.dispatchEvent(e);
}
});
// Initiating focus auto transfer.
// Focus will be requested to b1. When FOCUS_GAINED is being dispatched to b1, it will
// be disabled. This will trigger focus restoring. Focus will be requested to b0 (the
// last opposite component). When FOCUS_GAINED is being dispatched to b0, it will
// also be disabled. However, the last opposite component (and the most recent focus owner)
// will still be b0. When DKFM initiates focus restoring it should detect restoring
// on the same component and break.
b0.setEnabled(false);
Util.waitForIdle(robot);
if (nFocused != -1) {
System.out.println("Test passed.");
}
}
}
class TestFailedException extends RuntimeException {
TestFailedException(String msg) {
super("Test failed: " + msg);
}
}

View File

@ -0,0 +1,411 @@
/*
* Copyright 2007 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 6637796
@summary Shape should be correctly updated on invalid components
@author anthony.petrov@...: area=awt.mixing
@library ../regtesthelpers
@build Util
@run main ValidBounds
*/
/**
* ValidBounds.java
*
* summary: Shape should be correctly updated on invalid components
*/
import java.awt.*;
import java.awt.event.*;
import test.java.awt.regtesthelpers.Util;
public class ValidBounds
{
static volatile boolean clickPassed = false;
private static void init()
{
//*** Create instructions for the user here ***
String[] instructions =
{
"This is an AUTOMATIC test, simply wait until it is done.",
"The result (passed or failed) will be shown in the",
"message window below."
};
Sysout.createDialog( );
Sysout.printInstructions( instructions );
// Create the frame and the button
Frame f = new Frame();
f.setBounds(100, 100, 400, 300);
Button b = new Button("OK");
f.setLayout(null);
f.add(b);
b.setBounds(50, 50, 200, 50);
b.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
clickPassed = true;
}
});
f.setVisible(true);
// Let's make the button much smaller first...
Robot robot = Util.createRobot();
robot.setAutoDelay(20);
Util.waitForIdle(robot);
b.setBounds(50, 50, 5, 5);
Util.waitForIdle(robot);
// ... and now let's enlarge it.
b.setBounds(50, 50, 200, 50);
Util.waitForIdle(robot);
// If the button doesn't receive the click, it means that the test
// failed: the shape of the button was not enlarged.
Point heavyLoc = b.getLocationOnScreen();
robot.mouseMove(heavyLoc.x + 20, heavyLoc.y + 20);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
Util.waitForIdle(robot);
if (clickPassed) {
pass();
} else {
fail("The button cannot be clicked.");
}
}//End init()
/*****************************************************
* Standard Test Machinery Section
* DO NOT modify anything in this section -- it's a
* standard chunk of code which has all of the
* synchronisation necessary for the test harness.
* By keeping it the same in all tests, it is easier
* to read and understand someone else's test, as
* well as insuring that all tests behave correctly
* with the test harness.
* There is a section following this for test-
* classes
******************************************************/
private static boolean theTestPassed = false;
private static boolean testGeneratedInterrupt = false;
private static String failureMessage = "";
private static Thread mainThread = null;
private static int sleepTime = 300000;
// Not sure about what happens if multiple of this test are
// instantiated in the same VM. Being static (and using
// static vars), it aint gonna work. Not worrying about
// it for now.
public static void main( String args[] ) throws InterruptedException
{
mainThread = Thread.currentThread();
try
{
init();
}
catch( TestPassedException e )
{
//The test passed, so just return from main and harness will
// interepret this return as a pass
return;
}
//At this point, neither test pass nor test fail has been
// called -- either would have thrown an exception and ended the
// test, so we know we have multiple threads.
//Test involves other threads, so sleep and wait for them to
// called pass() or fail()
try
{
Thread.sleep( sleepTime );
//Timed out, so fail the test
throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
}
catch (InterruptedException e)
{
//The test harness may have interrupted the test. If so, rethrow the exception
// so that the harness gets it and deals with it.
if( ! testGeneratedInterrupt ) throw e;
//reset flag in case hit this code more than once for some reason (just safety)
testGeneratedInterrupt = false;
if ( theTestPassed == false )
{
throw new RuntimeException( failureMessage );
}
}
}//main
public static synchronized void setTimeoutTo( int seconds )
{
sleepTime = seconds * 1000;
}
public static synchronized void pass()
{
Sysout.println( "The test passed." );
Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
//first check if this is executing in main thread
if ( mainThread == Thread.currentThread() )
{
//Still in the main thread, so set the flag just for kicks,
// and throw a test passed exception which will be caught
// and end the test.
theTestPassed = true;
throw new TestPassedException();
}
theTestPassed = true;
testGeneratedInterrupt = true;
mainThread.interrupt();
}//pass()
public static synchronized void fail()
{
//test writer didn't specify why test failed, so give generic
fail( "it just plain failed! :-)" );
}
public static synchronized void fail( String whyFailed )
{
Sysout.println( "The test failed: " + whyFailed );
Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
//check if this called from main thread
if ( mainThread == Thread.currentThread() )
{
//If main thread, fail now 'cause not sleeping
throw new RuntimeException( whyFailed );
}
theTestPassed = false;
testGeneratedInterrupt = true;
failureMessage = whyFailed;
mainThread.interrupt();
}//fail()
}// class ValidBounds
//This exception is used to exit from any level of call nesting
// when it's determined that the test has passed, and immediately
// end the test.
class TestPassedException extends RuntimeException
{
}
//*********** End Standard Test Machinery Section **********
//************ Begin classes defined for the test ****************
// if want to make listeners, here is the recommended place for them, then instantiate
// them in init()
/* Example of a class which may be written as part of a test
class NewClass implements anInterface
{
static int newVar = 0;
public void eventDispatched(AWTEvent e)
{
//Counting events to see if we get enough
eventCount++;
if( eventCount == 20 )
{
//got enough events, so pass
ValidBounds.pass();
}
else if( tries == 20 )
{
//tried too many times without getting enough events so fail
ValidBounds.fail();
}
}// eventDispatched()
}// NewClass class
*/
//************** End classes defined for the test *******************
/****************************************************
Standard Test Machinery
DO NOT modify anything below -- it's a standard
chunk of code whose purpose is to make user
interaction uniform, and thereby make it simpler
to read and understand someone else's test.
****************************************************/
/**
This is part of the standard test machinery.
It creates a dialog (with the instructions), and is the interface
for sending text messages to the user.
To print the instructions, send an array of strings to Sysout.createDialog
WithInstructions method. Put one line of instructions per array entry.
To display a message for the tester to see, simply call Sysout.println
with the string to be displayed.
This mimics System.out.println but works within the test harness as well
as standalone.
*/
class Sysout
{
private static TestDialog dialog;
public static void createDialogWithInstructions( String[] instructions )
{
dialog = new TestDialog( new Frame(), "Instructions" );
dialog.printInstructions( instructions );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
public static void createDialog( )
{
dialog = new TestDialog( new Frame(), "Instructions" );
String[] defInstr = { "Instructions will appear here. ", "" } ;
dialog.printInstructions( defInstr );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
public static void printInstructions( String[] instructions )
{
dialog.printInstructions( instructions );
}
public static void println( String messageIn )
{
dialog.displayMessage( messageIn );
System.out.println(messageIn);
}
}// Sysout class
/**
This is part of the standard test machinery. It provides a place for the
test instructions to be displayed, and a place for interactive messages
to the user to be displayed.
To have the test instructions displayed, see Sysout.
To have a message to the user be displayed, see Sysout.
Do not call anything in this dialog directly.
*/
class TestDialog extends Dialog
{
TextArea instructionsText;
TextArea messageText;
int maxStringLength = 80;
//DO NOT call this directly, go through Sysout
public TestDialog( Frame frame, String name )
{
super( frame, name );
int scrollBoth = TextArea.SCROLLBARS_BOTH;
instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
add( "North", instructionsText );
messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
add("Center", messageText);
pack();
setVisible(true);
}// TestDialog()
//DO NOT call this directly, go through Sysout
public void printInstructions( String[] instructions )
{
//Clear out any current instructions
instructionsText.setText( "" );
//Go down array of instruction strings
String printStr, remainingStr;
for( int i=0; i < instructions.length; i++ )
{
//chop up each into pieces maxSringLength long
remainingStr = instructions[ i ];
while( remainingStr.length() > 0 )
{
//if longer than max then chop off first max chars to print
if( remainingStr.length() >= maxStringLength )
{
//Try to chop on a word boundary
int posOfSpace = remainingStr.
lastIndexOf( ' ', maxStringLength - 1 );
if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
printStr = remainingStr.substring( 0, posOfSpace + 1 );
remainingStr = remainingStr.substring( posOfSpace + 1 );
}
//else just print
else
{
printStr = remainingStr;
remainingStr = "";
}
instructionsText.append( printStr + "\n" );
}// while
}// for
}//printInstructions()
//DO NOT call this directly, go through Sysout
public void displayMessage( String messageIn )
{
messageText.append( messageIn + "\n" );
System.out.println(messageIn);
}
}// TestDialog class

View File

@ -0,0 +1,466 @@
/*
* Copyright 2007 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 %I% %E%
@bug 4080029
@summary Modal Dialog block input to all frame windows not just its parent.
@author dmitry.cherepanov: area=awt.modal
@run main/manual CloseBlocker
*/
/**
* ManualMainTest.java
*
* summary: The test opens and closes blocker dialog, the test verifies
* that active window is correct when the dialog is closed.
*/
import java.awt.*;
import java.awt.event.*;
public class CloseBlocker
{
private static void init()
{
//*** Create instructions for the user here ***
String[] instructions =
{
" the test will be run 6 times, to start next test just close all ",
" windows of previous; the instructions are the same for all tests: ",
" 1) there are two frames (one the frames has 'show modal' button), ",
" 2) press the button to show a dialog, ",
" 3) close the dialog (an alternative scenario - activate another",
" native window before closing the dialog), ",
" 4) the frame with button should become next active window, ",
" if it's true, then the test passed, otherwise, it failed. ",
" Press 'pass' button only after all of the 6 tests are completed, ",
" the number of the currently executed test is displayed on the ",
" output window. "
};
Sysout.createDialog( );
Sysout.printInstructions( instructions );
test(true, true, false);
test(true, true, true);
test(false, true, false); // 3rd parameter has no affect for ownerless
test(true, false, false);
test(true, false, true);
test(false, false, false); // 3rd parameter has no affect for ownerless
}//End init()
private static final Object obj = new Object();
private static int counter = 0;
/*
* The ownerless parameter indicates whether the blocker dialog
* has owner. The usual parameter indicates whether the blocker
* dialog is a Java dialog (non-native dialog like file dialog).
*/
private static void test(final boolean ownerless, final boolean usual, final boolean initiallyOwnerIsActive) {
Sysout.print(" * test #" + (++counter) + " is running ... ");
final Frame active = new Frame();
final Frame nonactive = new Frame();
Button button = new Button("show modal");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
Dialog dialog = null;
Frame parent = ownerless ? null : (initiallyOwnerIsActive? active : nonactive);
if (usual) {
dialog = new Dialog(parent, "Sample", true);
} else {
dialog = new FileDialog(parent, "Sample", FileDialog.LOAD);
}
dialog.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
e.getWindow().dispose();
}
});
dialog.setBounds(200, 200, 200, 200);
dialog.setVisible(true);
}
});
active.add(button);
active.setBounds(200, 400, 200, 200);
WindowAdapter adapter = new WindowAdapter(){
public void windowClosing(WindowEvent e){
active.dispose();
nonactive.dispose();
synchronized(obj) {
obj.notify();
}
}
};
active.addWindowListener(adapter);
active.setVisible(true);
nonactive.setBounds(400, 400, 200, 200);
nonactive.addWindowListener(adapter);
nonactive.setVisible(true);
synchronized(obj) {
try{
obj.wait();
} catch(Exception e) {
throw new RuntimeException(e);
}
}
Sysout.println(" completed. ");
}
/*****************************************************
* Standard Test Machinery Section
* DO NOT modify anything in this section -- it's a
* standard chunk of code which has all of the
* synchronisation necessary for the test harness.
* By keeping it the same in all tests, it is easier
* to read and understand someone else's test, as
* well as insuring that all tests behave correctly
* with the test harness.
* There is a section following this for test-defined
* classes
******************************************************/
private static boolean theTestPassed = false;
private static boolean testGeneratedInterrupt = false;
private static String failureMessage = "";
private static Thread mainThread = null;
private static int sleepTime = 300000;
public static void main( String args[] ) throws InterruptedException
{
mainThread = Thread.currentThread();
try
{
init();
}
catch( TestPassedException e )
{
//The test passed, so just return from main and harness will
// interepret this return as a pass
return;
}
//At this point, neither test passed nor test failed has been
// called -- either would have thrown an exception and ended the
// test, so we know we have multiple threads.
//Test involves other threads, so sleep and wait for them to
// called pass() or fail()
try
{
Thread.sleep( sleepTime );
//Timed out, so fail the test
throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
}
catch (InterruptedException e)
{
if( ! testGeneratedInterrupt ) throw e;
//reset flag in case hit this code more than once for some reason (just safety)
testGeneratedInterrupt = false;
if ( theTestPassed == false )
{
throw new RuntimeException( failureMessage );
}
}
}//main
public static synchronized void setTimeoutTo( int seconds )
{
sleepTime = seconds * 1000;
}
public static synchronized void pass()
{
Sysout.println( "The test passed." );
Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
//first check if this is executing in main thread
if ( mainThread == Thread.currentThread() )
{
//Still in the main thread, so set the flag just for kicks,
// and throw a test passed exception which will be caught
// and end the test.
theTestPassed = true;
throw new TestPassedException();
}
//pass was called from a different thread, so set the flag and interrupt
// the main thead.
theTestPassed = true;
testGeneratedInterrupt = true;
mainThread.interrupt();
}//pass()
public static synchronized void fail()
{
//test writer didn't specify why test failed, so give generic
fail( "it just plain failed! :-)" );
}
public static synchronized void fail( String whyFailed )
{
Sysout.println( "The test failed: " + whyFailed );
Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
//check if this called from main thread
if ( mainThread == Thread.currentThread() )
{
//If main thread, fail now 'cause not sleeping
throw new RuntimeException( whyFailed );
}
theTestPassed = false;
testGeneratedInterrupt = true;
failureMessage = whyFailed;
mainThread.interrupt();
}//fail()
}// class ManualMainTest
//This exception is used to exit from any level of call nesting
// when it's determined that the test has passed, and immediately
// end the test.
class TestPassedException extends RuntimeException
{
}
//*********** End Standard Test Machinery Section **********
//************ Begin classes defined for the test ****************
// make listeners in a class defined here, and instantiate them in init()
/* Example of a class which may be written as part of a test
class NewClass implements anInterface
{
static int newVar = 0;
public void eventDispatched(AWTEvent e)
{
//Counting events to see if we get enough
eventCount++;
if( eventCount == 20 )
{
//got enough events, so pass
ManualMainTest.pass();
}
else if( tries == 20 )
{
//tried too many times without getting enough events so fail
ManualMainTest.fail();
}
}// eventDispatched()
}// NewClass class
*/
//************** End classes defined for the test *******************
/****************************************************
Standard Test Machinery
DO NOT modify anything below -- it's a standard
chunk of code whose purpose is to make user
interaction uniform, and thereby make it simpler
to read and understand someone else's test.
****************************************************/
/**
This is part of the standard test machinery.
It creates a dialog (with the instructions), and is the interface
for sending text messages to the user.
To print the instructions, send an array of strings to Sysout.createDialog
WithInstructions method. Put one line of instructions per array entry.
To display a message for the tester to see, simply call Sysout.println
with the string to be displayed.
This mimics System.out.println but works within the test harness as well
as standalone.
*/
class Sysout
{
private static TestDialog dialog;
public static void createDialogWithInstructions( String[] instructions )
{
dialog = new TestDialog( new Frame(), "Instructions" );
dialog.printInstructions( instructions );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
public static void createDialog( )
{
dialog = new TestDialog( new Frame(), "Instructions" );
String[] defInstr = { "Instructions will appear here. ", "" } ;
dialog.printInstructions( defInstr );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
public static void printInstructions( String[] instructions )
{
dialog.printInstructions( instructions );
}
public static void println( String messageIn )
{
dialog.displayMessage( messageIn, true );
}
public static void print( String messageIn )
{
dialog.displayMessage( messageIn, false );
}
}// Sysout class
/**
This is part of the standard test machinery. It provides a place for the
test instructions to be displayed, and a place for interactive messages
to the user to be displayed.
To have the test instructions displayed, see Sysout.
To have a message to the user be displayed, see Sysout.
Do not call anything in this dialog directly.
*/
class TestDialog extends Dialog implements ActionListener
{
TextArea instructionsText;
TextArea messageText;
int maxStringLength = 80;
Panel buttonP = new Panel();
Button passB = new Button( "pass" );
Button failB = new Button( "fail" );
//DO NOT call this directly, go through Sysout
public TestDialog( Frame frame, String name )
{
super( frame, name );
int scrollBoth = TextArea.SCROLLBARS_BOTH;
instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
add( "North", instructionsText );
messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
add("Center", messageText);
passB = new Button( "pass" );
passB.setActionCommand( "pass" );
passB.addActionListener( this );
buttonP.add( "East", passB );
failB = new Button( "fail" );
failB.setActionCommand( "fail" );
failB.addActionListener( this );
buttonP.add( "West", failB );
add( "South", buttonP );
pack();
setVisible(true);
}// TestDialog()
//DO NOT call this directly, go through Sysout
public void printInstructions( String[] instructions )
{
//Clear out any current instructions
instructionsText.setText( "" );
//Go down array of instruction strings
String printStr, remainingStr;
for( int i=0; i < instructions.length; i++ )
{
//chop up each into pieces maxSringLength long
remainingStr = instructions[ i ];
while( remainingStr.length() > 0 )
{
//if longer than max then chop off first max chars to print
if( remainingStr.length() >= maxStringLength )
{
//Try to chop on a word boundary
int posOfSpace = remainingStr.
lastIndexOf( ' ', maxStringLength - 1 );
if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
printStr = remainingStr.substring( 0, posOfSpace + 1 );
remainingStr = remainingStr.substring( posOfSpace + 1 );
}
//else just print
else
{
printStr = remainingStr;
remainingStr = "";
}
instructionsText.append( printStr + "\n" );
}// while
}// for
}//printInstructions()
//DO NOT call this directly, go through Sysout
public void displayMessage( String messageIn, boolean nextLine )
{
messageText.append( messageIn + (nextLine? "\n" : "") );
System.out.println(messageIn);
}
//catch presses of the passed and failed buttons.
//simply call the standard pass() or fail() static methods of
//ManualMainTest
public void actionPerformed( ActionEvent e )
{
if( e.getActionCommand() == "pass" )
{
CloseBlocker.pass();
}
else
{
CloseBlocker.fail();
}
}
}// TestDialog class

View File

@ -0,0 +1,456 @@
/*
* Copyright 2007 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 %I% %E%
@bug 4080029
@summary Modal Dialog block input to all frame windows not just its parent.
@author dmitry.cherepanov: area=awt.modal
@run main/manual OverBlocker
*/
/**
* OverBlocker.java
*
* summary: The test verifies that if user tries to activate the blocked dialog
* then the blocker dialog appears over the other windows
*/
import java.awt.*;
import java.awt.event.*;
public class OverBlocker
{
private static void init()
{
//*** Create instructions for the user here ***
String[] instructions =
{
" the test will be run 4 times, to start next test just close all ",
" windows of previous; the instructions are the same for all tests: ",
" 1) there is a frame with 'show modal' button, ",
" 2) press the button to show a dialog, ",
" 3) activate any non-Java application, move the app over the dialog, ",
" 4) click on the frame by mouse, ",
" 5) make sure that the dialog comes up from the application and ",
" now the dialog overlaps the app as well as the frame, ",
" if it's true, then the test passed, otherwise, it failed. ",
" Press 'pass' button only after all of the 4 tests are completed, ",
" the number of the currently executed test is displayed on the ",
" output window. "
};
Sysout.createDialog( );
Sysout.printInstructions( instructions );
test(false, true);
test(true, true);
test(true, false);
test(false, false);
}//End init()
private static final Object obj = new Object();
private static int counter = 0;
/*
* The ownerless parameter indicates whether the blocker dialog
* has owner. The usual parameter indicates whether the blocker
* dialog is a Java dialog (non-native dialog like file dialog).
*/
private static void test(final boolean ownerless, final boolean usual) {
Sysout.print(" * test #" + (++counter) + " is running ... ");
final Frame frame = new Frame();
Button button = new Button("show modal");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
Dialog dialog = null;
Frame parent = ownerless ? null : frame;
if (usual) {
dialog = new Dialog(parent, "Sample", true);
} else {
dialog = new FileDialog(parent, "Sample", FileDialog.LOAD);
}
dialog.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
e.getWindow().dispose();
}
});
dialog.setBounds(200, 200, 200, 200);
dialog.setVisible(true);
}
});
frame.add(button);
frame.setBounds(400, 400, 200, 200);
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
e.getWindow().dispose();
synchronized(obj) {
obj.notify();
}
}
});
frame.setVisible(true);
synchronized(obj) {
try{
obj.wait();
} catch(Exception e) {
throw new RuntimeException(e);
}
}
Sysout.println(" completed. ");
}
/*****************************************************
* Standard Test Machinery Section
* DO NOT modify anything in this section -- it's a
* standard chunk of code which has all of the
* synchronisation necessary for the test harness.
* By keeping it the same in all tests, it is easier
* to read and understand someone else's test, as
* well as insuring that all tests behave correctly
* with the test harness.
* There is a section following this for test-defined
* classes
******************************************************/
private static boolean theTestPassed = false;
private static boolean testGeneratedInterrupt = false;
private static String failureMessage = "";
private static Thread mainThread = null;
private static int sleepTime = 300000;
public static void main( String args[] ) throws InterruptedException
{
mainThread = Thread.currentThread();
try
{
init();
}
catch( TestPassedException e )
{
//The test passed, so just return from main and harness will
// interepret this return as a pass
return;
}
//At this point, neither test passed nor test failed has been
// called -- either would have thrown an exception and ended the
// test, so we know we have multiple threads.
//Test involves other threads, so sleep and wait for them to
// called pass() or fail()
try
{
Thread.sleep( sleepTime );
//Timed out, so fail the test
throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
}
catch (InterruptedException e)
{
if( ! testGeneratedInterrupt ) throw e;
//reset flag in case hit this code more than once for some reason (just safety)
testGeneratedInterrupt = false;
if ( theTestPassed == false )
{
throw new RuntimeException( failureMessage );
}
}
}//main
public static synchronized void setTimeoutTo( int seconds )
{
sleepTime = seconds * 1000;
}
public static synchronized void pass()
{
Sysout.println( "The test passed." );
Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
//first check if this is executing in main thread
if ( mainThread == Thread.currentThread() )
{
//Still in the main thread, so set the flag just for kicks,
// and throw a test passed exception which will be caught
// and end the test.
theTestPassed = true;
throw new TestPassedException();
}
//pass was called from a different thread, so set the flag and interrupt
// the main thead.
theTestPassed = true;
testGeneratedInterrupt = true;
mainThread.interrupt();
}//pass()
public static synchronized void fail()
{
//test writer didn't specify why test failed, so give generic
fail( "it just plain failed! :-)" );
}
public static synchronized void fail( String whyFailed )
{
Sysout.println( "The test failed: " + whyFailed );
Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
//check if this called from main thread
if ( mainThread == Thread.currentThread() )
{
//If main thread, fail now 'cause not sleeping
throw new RuntimeException( whyFailed );
}
theTestPassed = false;
testGeneratedInterrupt = true;
failureMessage = whyFailed;
mainThread.interrupt();
}//fail()
}// class ManualMainTest
//This exception is used to exit from any level of call nesting
// when it's determined that the test has passed, and immediately
// end the test.
class TestPassedException extends RuntimeException
{
}
//*********** End Standard Test Machinery Section **********
//************ Begin classes defined for the test ****************
// make listeners in a class defined here, and instantiate them in init()
/* Example of a class which may be written as part of a test
class NewClass implements anInterface
{
static int newVar = 0;
public void eventDispatched(AWTEvent e)
{
//Counting events to see if we get enough
eventCount++;
if( eventCount == 20 )
{
//got enough events, so pass
ManualMainTest.pass();
}
else if( tries == 20 )
{
//tried too many times without getting enough events so fail
ManualMainTest.fail();
}
}// eventDispatched()
}// NewClass class
*/
//************** End classes defined for the test *******************
/****************************************************
Standard Test Machinery
DO NOT modify anything below -- it's a standard
chunk of code whose purpose is to make user
interaction uniform, and thereby make it simpler
to read and understand someone else's test.
****************************************************/
/**
This is part of the standard test machinery.
It creates a dialog (with the instructions), and is the interface
for sending text messages to the user.
To print the instructions, send an array of strings to Sysout.createDialog
WithInstructions method. Put one line of instructions per array entry.
To display a message for the tester to see, simply call Sysout.println
with the string to be displayed.
This mimics System.out.println but works within the test harness as well
as standalone.
*/
class Sysout
{
private static TestDialog dialog;
public static void createDialogWithInstructions( String[] instructions )
{
dialog = new TestDialog( new Frame(), "Instructions" );
dialog.printInstructions( instructions );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
public static void createDialog( )
{
dialog = new TestDialog( new Frame(), "Instructions" );
String[] defInstr = { "Instructions will appear here. ", "" } ;
dialog.printInstructions( defInstr );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
public static void printInstructions( String[] instructions )
{
dialog.printInstructions( instructions );
}
public static void println( String messageIn )
{
dialog.displayMessage( messageIn, true );
}
public static void print( String messageIn )
{
dialog.displayMessage( messageIn, false );
}
}// Sysout class
/**
This is part of the standard test machinery. It provides a place for the
test instructions to be displayed, and a place for interactive messages
to the user to be displayed.
To have the test instructions displayed, see Sysout.
To have a message to the user be displayed, see Sysout.
Do not call anything in this dialog directly.
*/
class TestDialog extends Dialog implements ActionListener
{
TextArea instructionsText;
TextArea messageText;
int maxStringLength = 80;
Panel buttonP = new Panel();
Button passB = new Button( "pass" );
Button failB = new Button( "fail" );
//DO NOT call this directly, go through Sysout
public TestDialog( Frame frame, String name )
{
super( frame, name );
int scrollBoth = TextArea.SCROLLBARS_BOTH;
instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
add( "North", instructionsText );
messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
add("Center", messageText);
passB = new Button( "pass" );
passB.setActionCommand( "pass" );
passB.addActionListener( this );
buttonP.add( "East", passB );
failB = new Button( "fail" );
failB.setActionCommand( "fail" );
failB.addActionListener( this );
buttonP.add( "West", failB );
add( "South", buttonP );
pack();
setVisible(true);
}// TestDialog()
//DO NOT call this directly, go through Sysout
public void printInstructions( String[] instructions )
{
//Clear out any current instructions
instructionsText.setText( "" );
//Go down array of instruction strings
String printStr, remainingStr;
for( int i=0; i < instructions.length; i++ )
{
//chop up each into pieces maxSringLength long
remainingStr = instructions[ i ];
while( remainingStr.length() > 0 )
{
//if longer than max then chop off first max chars to print
if( remainingStr.length() >= maxStringLength )
{
//Try to chop on a word boundary
int posOfSpace = remainingStr.
lastIndexOf( ' ', maxStringLength - 1 );
if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
printStr = remainingStr.substring( 0, posOfSpace + 1 );
remainingStr = remainingStr.substring( posOfSpace + 1 );
}
//else just print
else
{
printStr = remainingStr;
remainingStr = "";
}
instructionsText.append( printStr + "\n" );
}// while
}// for
}//printInstructions()
//DO NOT call this directly, go through Sysout
public void displayMessage( String messageIn, boolean nextLine )
{
messageText.append( messageIn + (nextLine? "\n" : "") );
System.out.println(messageIn);
}
//catch presses of the passed and failed buttons.
//simply call the standard pass() or fail() static methods of
//ManualMainTest
public void actionPerformed( ActionEvent e )
{
if( e.getActionCommand() == "pass" )
{
OverBlocker.pass();
}
else
{
OverBlocker.fail();
}
}
}// TestDialog class

View File

@ -0,0 +1,403 @@
/*
* Copyright 2007 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 %I% %E%
@bug 6572263 6571808
@summary PIT:FileDialog minimized to taskbar(through 'Show Desktop')selecting the fileDialog using windowList
@author dmitry.cherepanov: area=awt.modal
@run main/manual Winkey
*/
/**
* Winkey.java
*
* summary: the test verifies that pressing combination of Windows key
* and M key to minimize all windows doesn't break AWT modality
*/
import java.awt.*;
import java.awt.event.*;
public class Winkey
{
private static void init()
{
//*** Create instructions for the user here ***
String[] instructions =
{
" 1. there is a frame with a 'show modal' button, ",
" 2. press the button to show a modal dialog, ",
" 3. the modal dialog will be shown over the frame, ",
" 4. please verify that all (5.1, 5.2.1, 5.2.2) the following tests pass: ",
" ",
" 5.1. press combination Windows Key and M key to minimize all windows, ",
" 5.2. press combination Windows Key and D key to show desktop, ",
" 5.2.1. restore the dialog by choosing this one in the ALT-TAB list, ",
" 5.2.2. restore the dialog by mouse click on taskbar (on java or any other item)",
" ",
" 6. make sure that the dialog and the frame are visible, ",
" the bounds of the windows should be the same as before, ",
" if it's true, then the test passed; otherwise, it failed. "
};
Sysout.createDialog( );
Sysout.printInstructions( instructions );
final Frame frame = new Frame();
Button button = new Button("show modal");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
FileDialog dialog = new FileDialog((Frame)null, "Sample", FileDialog.LOAD);
dialog.setVisible(true);
}
});
frame.add(button);
frame.setBounds(400, 400, 200, 200);
frame.setVisible(true);
}//End init()
/*****************************************************
* Standard Test Machinery Section
* DO NOT modify anything in this section -- it's a
* standard chunk of code which has all of the
* synchronisation necessary for the test harness.
* By keeping it the same in all tests, it is easier
* to read and understand someone else's test, as
* well as insuring that all tests behave correctly
* with the test harness.
* There is a section following this for test-defined
* classes
******************************************************/
private static boolean theTestPassed = false;
private static boolean testGeneratedInterrupt = false;
private static String failureMessage = "";
private static Thread mainThread = null;
private static int sleepTime = 300000;
public static void main( String args[] ) throws InterruptedException
{
mainThread = Thread.currentThread();
try
{
init();
}
catch( TestPassedException e )
{
//The test passed, so just return from main and harness will
// interepret this return as a pass
return;
}
//At this point, neither test passed nor test failed has been
// called -- either would have thrown an exception and ended the
// test, so we know we have multiple threads.
//Test involves other threads, so sleep and wait for them to
// called pass() or fail()
try
{
Thread.sleep( sleepTime );
//Timed out, so fail the test
throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
}
catch (InterruptedException e)
{
if( ! testGeneratedInterrupt ) throw e;
//reset flag in case hit this code more than once for some reason (just safety)
testGeneratedInterrupt = false;
if ( theTestPassed == false )
{
throw new RuntimeException( failureMessage );
}
}
}//main
public static synchronized void setTimeoutTo( int seconds )
{
sleepTime = seconds * 1000;
}
public static synchronized void pass()
{
Sysout.println( "The test passed." );
Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
//first check if this is executing in main thread
if ( mainThread == Thread.currentThread() )
{
//Still in the main thread, so set the flag just for kicks,
// and throw a test passed exception which will be caught
// and end the test.
theTestPassed = true;
throw new TestPassedException();
}
//pass was called from a different thread, so set the flag and interrupt
// the main thead.
theTestPassed = true;
testGeneratedInterrupt = true;
mainThread.interrupt();
}//pass()
public static synchronized void fail()
{
//test writer didn't specify why test failed, so give generic
fail( "it just plain failed! :-)" );
}
public static synchronized void fail( String whyFailed )
{
Sysout.println( "The test failed: " + whyFailed );
Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
//check if this called from main thread
if ( mainThread == Thread.currentThread() )
{
//If main thread, fail now 'cause not sleeping
throw new RuntimeException( whyFailed );
}
theTestPassed = false;
testGeneratedInterrupt = true;
failureMessage = whyFailed;
mainThread.interrupt();
}//fail()
}// class ManualMainTest
//This exception is used to exit from any level of call nesting
// when it's determined that the test has passed, and immediately
// end the test.
class TestPassedException extends RuntimeException
{
}
//*********** End Standard Test Machinery Section **********
//************ Begin classes defined for the test ****************
// make listeners in a class defined here, and instantiate them in init()
/* Example of a class which may be written as part of a test
class NewClass implements anInterface
{
static int newVar = 0;
public void eventDispatched(AWTEvent e)
{
//Counting events to see if we get enough
eventCount++;
if( eventCount == 20 )
{
//got enough events, so pass
ManualMainTest.pass();
}
else if( tries == 20 )
{
//tried too many times without getting enough events so fail
ManualMainTest.fail();
}
}// eventDispatched()
}// NewClass class
*/
//************** End classes defined for the test *******************
/****************************************************
Standard Test Machinery
DO NOT modify anything below -- it's a standard
chunk of code whose purpose is to make user
interaction uniform, and thereby make it simpler
to read and understand someone else's test.
****************************************************/
/**
This is part of the standard test machinery.
It creates a dialog (with the instructions), and is the interface
for sending text messages to the user.
To print the instructions, send an array of strings to Sysout.createDialog
WithInstructions method. Put one line of instructions per array entry.
To display a message for the tester to see, simply call Sysout.println
with the string to be displayed.
This mimics System.out.println but works within the test harness as well
as standalone.
*/
class Sysout
{
private static TestDialog dialog;
public static void createDialogWithInstructions( String[] instructions )
{
dialog = new TestDialog( new Frame(), "Instructions" );
dialog.printInstructions( instructions );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
public static void createDialog( )
{
dialog = new TestDialog( new Frame(), "Instructions" );
String[] defInstr = { "Instructions will appear here. ", "" } ;
dialog.printInstructions( defInstr );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
public static void printInstructions( String[] instructions )
{
dialog.printInstructions( instructions );
}
public static void println( String messageIn )
{
dialog.displayMessage( messageIn );
}
}// Sysout class
/**
This is part of the standard test machinery. It provides a place for the
test instructions to be displayed, and a place for interactive messages
to the user to be displayed.
To have the test instructions displayed, see Sysout.
To have a message to the user be displayed, see Sysout.
Do not call anything in this dialog directly.
*/
class TestDialog extends Dialog implements ActionListener
{
TextArea instructionsText;
TextArea messageText;
int maxStringLength = 80;
Panel buttonP = new Panel();
Button passB = new Button( "pass" );
Button failB = new Button( "fail" );
//DO NOT call this directly, go through Sysout
public TestDialog( Frame frame, String name )
{
super( frame, name );
int scrollBoth = TextArea.SCROLLBARS_BOTH;
instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
add( "North", instructionsText );
messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
add("Center", messageText);
passB = new Button( "pass" );
passB.setActionCommand( "pass" );
passB.addActionListener( this );
buttonP.add( "East", passB );
failB = new Button( "fail" );
failB.setActionCommand( "fail" );
failB.addActionListener( this );
buttonP.add( "West", failB );
add( "South", buttonP );
pack();
setVisible(true);
}// TestDialog()
//DO NOT call this directly, go through Sysout
public void printInstructions( String[] instructions )
{
//Clear out any current instructions
instructionsText.setText( "" );
//Go down array of instruction strings
String printStr, remainingStr;
for( int i=0; i < instructions.length; i++ )
{
//chop up each into pieces maxSringLength long
remainingStr = instructions[ i ];
while( remainingStr.length() > 0 )
{
//if longer than max then chop off first max chars to print
if( remainingStr.length() >= maxStringLength )
{
//Try to chop on a word boundary
int posOfSpace = remainingStr.
lastIndexOf( ' ', maxStringLength - 1 );
if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
printStr = remainingStr.substring( 0, posOfSpace + 1 );
remainingStr = remainingStr.substring( posOfSpace + 1 );
}
//else just print
else
{
printStr = remainingStr;
remainingStr = "";
}
instructionsText.append( printStr + "\n" );
}// while
}// for
}//printInstructions()
//DO NOT call this directly, go through Sysout
public void displayMessage( String messageIn )
{
messageText.append( messageIn + "\n" );
System.out.println(messageIn);
}
//catch presses of the passed and failed buttons.
//simply call the standard pass() or fail() static methods of
//ManualMainTest
public void actionPerformed( ActionEvent e )
{
if( e.getActionCommand() == "pass" )
{
Winkey.pass();
}
else
{
Winkey.fail();
}
}
}// TestDialog class

View File

@ -0,0 +1,432 @@
/*
* Copyright 2007 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 %W% %E% %I%, %G%
@bug 6524352
@summary support for high-resolution mouse wheel
@author dmitry cherepanov: area=awt.event
@run main/manual SmoothWheel
*/
/**
* SmoothWheel.java
*
* summary:
*/
import java.awt.*;
import java.awt.event.*;
public class SmoothWheel
{
//*** test-writer defined static variables go here ***
private static void init()
{
String[] instructions =
{
"1. the test is for high-resolution mouse wheel only, ",
" refer to the cr# 6524352 for more info about such devices, ",
"2. you'll see a frame, the frame contains a checkbox, ",
"3. initially, the state of the checkbox is off, ",
" use mouse wheel over the frame, ",
" and the frame will change its size gradually, ",
"4. turn on the checkbox, ",
" use mouse wheel again over the frame, ",
" now the frame will change its size smoothly, ",
"5. if the frame has always the same size or",
" if the frame changes its size equally in 3,4 cases, ",
" then the test failed. Otherwise, it passed."
};
Sysout.createDialog( );
Sysout.printInstructions( instructions );
final Frame frame = new Frame();
final Checkbox checkbox = new Checkbox("smooth wheel?");
checkbox.setState(false);
frame.setLayout (new FlowLayout());
frame.add(checkbox);
frame.addMouseWheelListener(new MouseWheelListener() {
public void mouseWheelMoved(MouseWheelEvent e) {
Sysout.println(e.toString());
double wheelRotation = 0;
if (checkbox.getState()) {
wheelRotation = e.getPreciseWheelRotation();
} else {
wheelRotation = e.getWheelRotation();
}
Dimension size = frame.getSize();
size.width += 10 * wheelRotation;
size.height += 10 * wheelRotation;
frame.setSize(size);
}
});
frame.setBounds(200, 200, 200, 200);
frame.setVisible(true);
}//End init()
/*****************************************************
* Standard Test Machinery Section
* DO NOT modify anything in this section -- it's a
* standard chunk of code which has all of the
* synchronisation necessary for the test harness.
* By keeping it the same in all tests, it is easier
* to read and understand someone else's test, as
* well as insuring that all tests behave correctly
* with the test harness.
* There is a section following this for test-defined
* classes
******************************************************/
private static boolean theTestPassed = false;
private static boolean testGeneratedInterrupt = false;
private static String failureMessage = "";
private static Thread mainThread = null;
private static int sleepTime = 300000;
public static void main( String args[] ) throws InterruptedException
{
mainThread = Thread.currentThread();
try
{
init();
}
catch( TestPassedException e )
{
//The test passed, so just return from main and harness will
// interepret this return as a pass
return;
}
//At this point, neither test passed nor test failed has been
// called -- either would have thrown an exception and ended the
// test, so we know we have multiple threads.
//Test involves other threads, so sleep and wait for them to
// called pass() or fail()
try
{
Thread.sleep( sleepTime );
//Timed out, so fail the test
throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
}
catch (InterruptedException e)
{
if( ! testGeneratedInterrupt ) throw e;
//reset flag in case hit this code more than once for some reason (just safety)
testGeneratedInterrupt = false;
if ( theTestPassed == false )
{
throw new RuntimeException( failureMessage );
}
}
}//main
public static synchronized void setTimeoutTo( int seconds )
{
sleepTime = seconds * 1000;
}
public static synchronized void pass()
{
Sysout.println( "The test passed." );
Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
//first check if this is executing in main thread
if ( mainThread == Thread.currentThread() )
{
//Still in the main thread, so set the flag just for kicks,
// and throw a test passed exception which will be caught
// and end the test.
theTestPassed = true;
throw new TestPassedException();
}
//pass was called from a different thread, so set the flag and interrupt
// the main thead.
theTestPassed = true;
testGeneratedInterrupt = true;
if (mainThread != null){
mainThread.interrupt();
}
}//pass()
public static synchronized void fail()
{
//test writer didn't specify why test failed, so give generic
fail( "it just plain failed! :-)" );
}
public static synchronized void fail( String whyFailed )
{
Sysout.println( "The test failed: " + whyFailed );
Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
//check if this called from main thread
if ( mainThread == Thread.currentThread() )
{
//If main thread, fail now 'cause not sleeping
throw new RuntimeException( whyFailed );
}
theTestPassed = false;
testGeneratedInterrupt = true;
failureMessage = whyFailed;
mainThread.interrupt();
}//fail()
}// class ManualMainTest
//This exception is used to exit from any level of call nesting
// when it's determined that the test has passed, and immediately
// end the test.
class TestPassedException extends RuntimeException
{
}
//*********** End Standard Test Machinery Section **********
//************ Begin classes defined for the test ****************
// make listeners in a class defined here, and instantiate them in init()
/* Example of a class which may be written as part of a test
class NewClass implements anInterface
{
static int newVar = 0;
public void eventDispatched(AWTEvent e)
{
//Counting events to see if we get enough
eventCount++;
if( eventCount == 20 )
{
//got enough events, so pass
ManualMainTest.pass();
}
else if( tries == 20 )
{
//tried too many times without getting enough events so fail
ManualMainTest.fail();
}
}// eventDispatched()
}// NewClass class
*/
//************** End classes defined for the test *******************
/****************************************************
Standard Test Machinery
DO NOT modify anything below -- it's a standard
chunk of code whose purpose is to make user
interaction uniform, and thereby make it simpler
to read and understand someone else's test.
****************************************************/
/**
This is part of the standard test machinery.
It creates a dialog (with the instructions), and is the interface
for sending text messages to the user.
To print the instructions, send an array of strings to Sysout.createDialog
WithInstructions method. Put one line of instructions per array entry.
To display a message for the tester to see, simply call Sysout.println
with the string to be displayed.
This mimics System.out.println but works within the test harness as well
as standalone.
*/
class Sysout
{
private static TestDialog dialog;
private static boolean numbering = false;
private static int messageNumber = 0;
public static void createDialogWithInstructions( String[] instructions )
{
dialog = new TestDialog( new Frame(), "Instructions" );
dialog.printInstructions( instructions );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
public static void createDialog( )
{
dialog = new TestDialog( new Frame(), "Instructions" );
String[] defInstr = { "Instructions will appear here. ", "" } ;
dialog.printInstructions( defInstr );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
/* Enables message counting for the tester. */
public static void enableNumbering(boolean enable){
numbering = enable;
}
public static void printInstructions( String[] instructions )
{
dialog.printInstructions( instructions );
}
public static void println( String messageIn )
{
if (numbering) {
messageIn = "" + messageNumber + " " + messageIn;
messageNumber++;
}
dialog.displayMessage( messageIn );
}
}// Sysout class
/**
This is part of the standard test machinery. It provides a place for the
test instructions to be displayed, and a place for interactive messages
to the user to be displayed.
To have the test instructions displayed, see Sysout.
To have a message to the user be displayed, see Sysout.
Do not call anything in this dialog directly.
*/
class TestDialog extends Dialog implements ActionListener
{
TextArea instructionsText;
TextArea messageText;
int maxStringLength = 80;
Panel buttonP = new Panel();
Button passB = new Button( "pass" );
Button failB = new Button( "fail" );
//DO NOT call this directly, go through Sysout
public TestDialog( Frame frame, String name )
{
super( frame, name );
int scrollBoth = TextArea.SCROLLBARS_BOTH;
instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
add( "North", instructionsText );
messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
add("Center", messageText);
passB = new Button( "pass" );
passB.setActionCommand( "pass" );
passB.addActionListener( this );
buttonP.add( "East", passB );
failB = new Button( "fail" );
failB.setActionCommand( "fail" );
failB.addActionListener( this );
buttonP.add( "West", failB );
add( "South", buttonP );
pack();
setVisible(true);
}// TestDialog()
//DO NOT call this directly, go through Sysout
public void printInstructions( String[] instructions )
{
//Clear out any current instructions
instructionsText.setText( "" );
//Go down array of instruction strings
String printStr, remainingStr;
for( int i=0; i < instructions.length; i++ )
{
//chop up each into pieces maxSringLength long
remainingStr = instructions[ i ];
while( remainingStr.length() > 0 )
{
//if longer than max then chop off first max chars to print
if( remainingStr.length() >= maxStringLength )
{
//Try to chop on a word boundary
int posOfSpace = remainingStr.
lastIndexOf( ' ', maxStringLength - 1 );
if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
printStr = remainingStr.substring( 0, posOfSpace + 1 );
remainingStr = remainingStr.substring( posOfSpace + 1 );
}
//else just print
else
{
printStr = remainingStr;
remainingStr = "";
}
instructionsText.append( printStr + "\n" );
}// while
}// for
}//printInstructions()
//DO NOT call this directly, go through Sysout
public void displayMessage( String messageIn )
{
messageText.append( messageIn + "\n" );
System.out.println(messageIn);
}
//catch presses of the passed and failed buttons.
//simply call the standard pass() or fail() static methods of
//ManualMainTest
public void actionPerformed( ActionEvent e )
{
if( e.getActionCommand() == "pass" )
{
SmoothWheel.pass();
}
else
{
SmoothWheel.fail();
}
}
}// TestDialog class