--- a/jdk/make/sun/splashscreen/Makefile Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/make/sun/splashscreen/Makefile Thu Mar 27 12:28:53 2008 -0700
@@ -85,3 +85,13 @@
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
+
--- a/jdk/make/sun/xawt/Makefile Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/make/sun/xawt/Makefile Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
@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 @@
$(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)
--- a/jdk/src/share/classes/java/awt/Component.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/share/classes/java/awt/Component.java Thu Mar 27 12:28:53 2008 -0700
@@ -634,6 +634,11 @@
*/
private PropertyChangeSupport changeSupport;
+ private transient final Object changeSupportLock = new Object();
+ private Object getChangeSupportLock() {
+ return changeSupportLock;
+ }
+
boolean isPacked = false;
/**
@@ -935,24 +940,26 @@
*/
public GraphicsConfiguration getGraphicsConfiguration() {
synchronized(getTreeLock()) {
- GraphicsConfiguration gc = graphicsConfig;
- Component parent = getParent();
- while ((gc == null) && (parent != null)) {
- gc = parent.getGraphicsConfiguration();
- parent = parent.getParent();
- }
- return gc;
+ if (graphicsConfig != null) {
+ return graphicsConfig;
+ } else if (getParent() != null) {
+ return getParent().getGraphicsConfiguration();
+ } else {
+ return null;
+ }
}
}
final GraphicsConfiguration getGraphicsConfiguration_NoClientCode() {
- GraphicsConfiguration gc = this.graphicsConfig;
- Component par = this.parent;
- while ((gc == null) && (par != null)) {
- gc = par.getGraphicsConfiguration_NoClientCode();
- par = par.parent;
- }
- return gc;
+ GraphicsConfiguration graphicsConfig = this.graphicsConfig;
+ Container parent = this.parent;
+ if (graphicsConfig != null) {
+ return graphicsConfig;
+ } else if (parent != null) {
+ return parent.getGraphicsConfiguration_NoClientCode();
+ } else {
+ return null;
+ }
}
/**
@@ -4602,7 +4609,8 @@
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 @@
// will need some help.
Container parent = this.parent;
if (parent != null && parent.peer instanceof LightweightPeer) {
- nativeInLightFixer = new NativeInLightFixer();
+ relocateComponent();
}
}
invalidate();
@@ -6595,10 +6603,6 @@
}
}
- if (nativeInLightFixer != null) {
- nativeInLightFixer.uninstall();
- }
-
ComponentPeer p = peer;
if (p != null) {
boolean isLightweight = isLightweight();
@@ -7836,15 +7840,17 @@
* @see #getPropertyChangeListeners
* @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
*/
- public synchronized void addPropertyChangeListener(
+ public void addPropertyChangeListener(
PropertyChangeListener listener) {
- if (listener == null) {
- return;
- }
- if (changeSupport == null) {
- changeSupport = new PropertyChangeSupport(this);
- }
- changeSupport.addPropertyChangeListener(listener);
+ synchronized (getChangeSupportLock()) {
+ if (listener == null) {
+ return;
+ }
+ if (changeSupport == null) {
+ changeSupport = new PropertyChangeSupport(this);
+ }
+ changeSupport.addPropertyChangeListener(listener);
+ }
}
/**
@@ -7860,12 +7866,14 @@
* @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;
- }
- changeSupport.removePropertyChangeListener(listener);
+ synchronized (getChangeSupportLock()) {
+ if (listener == null || changeSupport == null) {
+ return;
+ }
+ changeSupport.removePropertyChangeListener(listener);
+ }
}
/**
@@ -7882,11 +7890,13 @@
* @see java.beans.PropertyChangeSupport#getPropertyChangeListeners
* @since 1.4
*/
- public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
- if (changeSupport == null) {
- return new PropertyChangeListener[0];
- }
- return changeSupport.getPropertyChangeListeners();
+ public PropertyChangeListener[] getPropertyChangeListeners() {
+ synchronized (getChangeSupportLock()) {
+ if (changeSupport == null) {
+ return new PropertyChangeListener[0];
+ }
+ return changeSupport.getPropertyChangeListeners();
+ }
}
/**
@@ -7920,16 +7930,18 @@
* @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;
- }
- if (changeSupport == null) {
- changeSupport = new PropertyChangeSupport(this);
- }
- changeSupport.addPropertyChangeListener(propertyName, listener);
+ synchronized (getChangeSupportLock()) {
+ if (listener == null) {
+ return;
+ }
+ if (changeSupport == null) {
+ changeSupport = new PropertyChangeSupport(this);
+ }
+ changeSupport.addPropertyChangeListener(propertyName, listener);
+ }
}
/**
@@ -7948,13 +7960,15 @@
* @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;
- }
- changeSupport.removePropertyChangeListener(propertyName, listener);
+ synchronized (getChangeSupportLock()) {
+ if (listener == null || changeSupport == null) {
+ return;
+ }
+ changeSupport.removePropertyChangeListener(propertyName, listener);
+ }
}
/**
@@ -7971,12 +7985,14 @@
* @see #getPropertyChangeListeners
* @since 1.4
*/
- public synchronized PropertyChangeListener[] getPropertyChangeListeners(
+ public PropertyChangeListener[] getPropertyChangeListeners(
String propertyName) {
- if (changeSupport == null) {
- return new PropertyChangeListener[0];
- }
- return changeSupport.getPropertyChangeListeners(propertyName);
+ synchronized (getChangeSupportLock()) {
+ if (changeSupport == null) {
+ return new PropertyChangeListener[0];
+ }
+ return changeSupport.getPropertyChangeListeners(propertyName);
+ }
}
/**
@@ -7991,7 +8007,10 @@
*/
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 @@
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 @@
}
/**
- * 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
- */
- 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();
- }
- // 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--)
+ * Fix the location of the HW component in a LW container hierarchy.
+ */
+ final void relocateComponent() {
+ synchronized (getTreeLock()) {
+ if (peer == null) {
+ return;
+ }
+ int nativeX = x;
+ int nativeY = y;
+ for (Component cont = getContainer();
+ cont != null && cont.isLightweight();
+ cont = cont.getContainer())
{
- isLwParentsVisible &=
- ((Container) lightParents.elementAt(i)).isVisible();
- }
- return isLwParentsVisible;
- }
-
- /**
- * 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;
+ nativeX += cont.x;
+ nativeY += cont.y;
+ }
+ peer.setBounds(nativeX, nativeY, width, height,
+ ComponentPeer.SET_LOCATION);
+ }
}
/**
@@ -9453,6 +9307,19 @@
// ************************** 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 @@
// 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 @@
void applyCurrentShape() {
checkTreeLock();
- if (!isValid()) {
+ if (!areBoundsValid()) {
return; // Because applyCompoundShape() ignores such components anyway
}
if (mixingLog.isLoggable(Level.FINE)) {
--- a/jdk/src/share/classes/java/awt/Container.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/share/classes/java/awt/Container.java Thu Mar 27 12:28:53 2008 -0700
@@ -832,16 +832,8 @@
}
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 @@
EventTargetFilter filter,
boolean searchHeavyweightChildren,
boolean searchHeavyweightDescendants) {
- 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)) {
-
- // 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;
+ 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)) {
+
+ // 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 @@
}
}
+ 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 @@
boolean isLightweight = isLightweight();
+ if (isLightweight && isRecursivelyVisibleUpToHeavyweightContainer()) {
+ recursiveShowHeavyweightChildren();
+ }
+
if (!isLightweight || (isLightweight && hasHeavyweightDescendants())) {
recursiveApplyCurrentShape();
}
@@ -3966,6 +4042,42 @@
}
}
+ @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 @@
e.isPopupTrigger(),
((MouseWheelEvent)e).getScrollType(),
((MouseWheelEvent)e).getScrollAmount(),
- ((MouseWheelEvent)e).getWheelRotation());
+ ((MouseWheelEvent)e).getWheelRotation(),
+ ((MouseWheelEvent)e).getPreciseWheelRotation());
}
else {
retargeted = new MouseEvent(target,
--- a/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java Thu Mar 27 12:28:53 2008 -0700
@@ -154,7 +154,7 @@
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 {
--- a/jdk/src/share/classes/java/awt/Window.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/share/classes/java/awt/Window.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
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 @@
static private final AtomicBoolean
beforeFirstWindowShown = new AtomicBoolean(true);
- static final void closeSplashScreen() {
+ final void closeSplashScreen() {
+ if (isTrayIconWindow) {
+ return;
+ }
if (beforeFirstWindowShown.getAndSet(false)) {
SunToolkit.closeSplashScreen();
}
--- a/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 sun.awt.datatransfer.DataTransferer;
-
/**
* The SystemFlavorMap is a configurable map between "natives" (Strings), which
* correspond to platform-specific data formats, and "flavors" (DataFlavors),
@@ -117,16 +116,51 @@
/**
* 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 @@
return fm;
}
+ private SystemFlavorMap() {
+ }
+
/**
- * Constructs a SystemFlavorMap by reading flavormap.properties and
+ * Initializes a SystemFlavorMap by reading flavormap.properties and
* AWT.DnD.flavorMapFileURL.
+ * For thread-safety must be called under lock on this.
*/
- private SystemFlavorMap() {
- BufferedReader flavormapDotProperties = (BufferedReader)
+ 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 @@
}
});
- 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 @@
}
}
}
-
/**
* Copied code from java.util.Properties. Parsing the data ourselves is the
* only way to handle duplicate keys and values.
@@ -388,11 +429,11 @@
// 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 @@
* 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 @@
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 @@
*/
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 @@
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 @@
}
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 @@
// 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 @@
}
// 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 @@
}
}
} 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 @@
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 @@
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 @@
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 @@
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]);
}
--- a/jdk/src/share/classes/java/awt/dnd/DropTarget.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/share/classes/java/awt/dnd/DropTarget.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
setActive(act);
}
- if (fm != null) flavorMap = fm;
+ if (fm != null) {
+ flavorMap = fm;
+ } else {
+ flavorMap = SystemFlavorMap.getDefaultFlavorMap();
+ }
}
/**
@@ -850,5 +854,5 @@
* The FlavorMap
*/
- private transient FlavorMap flavorMap = SystemFlavorMap.getDefaultFlavorMap();
+ private transient FlavorMap flavorMap;
}
--- a/jdk/src/share/classes/java/awt/event/MouseWheelEvent.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/share/classes/java/awt/event/MouseWheelEvent.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
* 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 @@
*/
int wheelRotation;
+ /**
+ * Indicates how far the mouse wheel was rotated.
+ *
+ * @see #getPreciseWheelRotation
+ */
+ double preciseWheelRotation;
+
/*
* serialVersionUID
*/
@@ -165,8 +185,8 @@
* <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 @@
* <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 @@
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,17 +343,35 @@
}
/**
- * 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
* JScrollPane by an amount which conforms to the platform settings.
@@ -348,6 +442,6 @@
}
return super.paramString()+",scrollType="+scrollTypeStr+
",scrollAmount="+getScrollAmount()+",wheelRotation="+
- getWheelRotation();
+ getWheelRotation()+",preciseWheelRotation="+getPreciseWheelRotation();
}
}
--- a/jdk/src/share/classes/sun/awt/AppContext.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/share/classes/sun/awt/AppContext.java Thu Mar 27 12:28:53 2008 -0700
@@ -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.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 @@
* @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 @@
* 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 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 @@
* 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 @@
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 @@
if (numAppContexts == 1) // If there's only one system-wide,
return mainAppContext; // return the main system AppContext.
- final Thread currentThread = Thread.currentThread();
-
- AppContext appContext = null;
-
- // 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.
+ AppContext appContext = threadAppContext.get();
- 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");
+ 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);
+
+ 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 @@
// 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 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 @@
// 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 @@
// 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 @@
}
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 @@
* Returns a string representation of this AppContext.
* @since 1.2
*/
+ @Override
public String toString() {
return getClass().getName() + "[threadGroup=" + threadGroup.getName() + "]";
}
@@ -769,15 +765,6 @@
}
}
-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;
--- a/jdk/src/share/classes/sun/awt/datatransfer/DataTransferer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/share/classes/sun/awt/datatransfer/DataTransferer.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
* 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);
- }
+ 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 {
- 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 (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 = 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);
- }
+ }
+ 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 = (DataTransferer)
- AccessController.doPrivileged(action);
- }
+ return ret;
+ }
+ };
+ transferer = AccessController.doPrivileged(action);
}
}
}
--- a/jdk/src/solaris/classes/sun/awt/X11/MotifDnDConstants.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/MotifDnDConstants.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
* @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 @@
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 @@
}
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));
}
--- a/jdk/src/solaris/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
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 @@
// 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());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/awt/X11/OwnershipListener.java Thu Mar 27 12:28:53 2008 -0700
@@ -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);
+}
--- a/jdk/src/solaris/classes/sun/awt/X11/XAtom.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XAtom.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
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 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 @@
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 @@
* @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 @@
}
}
- /**
- * 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;
--- a/jdk/src/solaris/classes/sun/awt/X11/XClipboard.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XClipboard.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
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 @@
return selection.getSelectionAtom().getAtom();
}
+ @Override
public synchronized Transferable getContents(Object requestor) {
if (contents != null) {
return contents;
@@ -115,62 +120,163 @@
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));
}
}
+ private static int getPollInterval() {
+ synchronized (XClipboard.classLock) {
+ if (pollInterval <= 0) {
+ pollInterval = AccessController.doPrivileged(
+ new GetIntegerAction("awt.datatransfer.clipboard.poll.interval",
+ defaultPollInterval));
+ if (pollInterval <= 0) {
+ pollInterval = defaultPollInterval;
+ }
+ }
+ return pollInterval;
+ }
+ }
+
+ private XAtom getTargetsPropertyAtom() {
+ if (null == targetsPropertyAtom) {
+ targetsPropertyAtom =
+ XAtom.get("XAWT_TARGETS_OF_SELECTION:" + selection.getSelectionAtom().getName());
+ }
+ return targetsPropertyAtom;
+ }
+
protected void registerClipboardViewerChecked() {
- if (pollInterval <= 0) {
- pollInterval = ((Integer)AccessController.doPrivileged(
- new GetIntegerAction("awt.datatransfer.clipboard.poll.interval",
- defaultPollInterval))).intValue();
- if (pollInterval <= 0) {
- pollInterval = defaultPollInterval;
+ // for XConvertSelection() to be called for the first time in getTargetsDelayed()
+ isSelectionNotifyProcessed = true;
+
+ boolean mustSchedule = false;
+ synchronized (XClipboard.classLock) {
+ 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());
}
}
- selection.initializeSelectionForTrackingChanges();
- boolean mustSchedule = false;
- synchronized (XClipboard.classLock) {
- if (listenedClipboards == null) {
- listenedClipboards = new HashSet(2);
- }
- 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);
+ }
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -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.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.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 void setFont(Font f) {
synchronized (getStateLock()) {
if (f == null) {
- f = defaultFont;
+ f = XWindow.getDefaultFont();
}
font = f;
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XContentWindow.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XContentWindow.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
* 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 @@
}
}
- void initialize() {
- xSetVisible(true);
- }
protected String getWMName() {
return "Content window";
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -36,7 +36,7 @@
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 @@
// 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 @@
}
}
- 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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
return getSize().height;
}
- public WindowDimensions getDimensions() {
+ final public WindowDimensions getDimensions() {
return dimensions;
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XDialogPeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDialogPeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -88,7 +88,8 @@
}
}
- private boolean isTargetUndecorated() {
+ @Override
+ boolean isTargetUndecorated() {
if (undecorated != null) {
return undecorated.booleanValue();
} else {
--- a/jdk/src/solaris/classes/sun/awt/X11/XDnDConstants.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDnDConstants.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
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;
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbedCanvasPeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbedCanvasPeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -647,12 +647,6 @@
}
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;
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java Thu Mar 27 12:28:53 2008 -0700
@@ -74,7 +74,6 @@
XToolkit.awtUnlock();
}
}
- notifyReady();
}
void handleClientMessage(XEvent xev) {
@@ -84,7 +83,6 @@
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 @@
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);
- }
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbedHelper.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbedHelper.java Thu Mar 27 12:28:53 2008 -0700
@@ -58,7 +58,6 @@
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 @@
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:
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbedServerTester.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbedServerTester.java Thu Mar 27 12:28:53 2008 -0700
@@ -177,13 +177,6 @@
embedCompletely();
}
- public void test3_2() {
- embedCompletely();
- int res = getEventPos();
- sendMessage(XEmbedHelper._SUN_XEMBED_START);
- waitEmbeddedNotify(res);
- }
-
public void test3_3() {
reparent = true;
embedCompletely();
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -184,6 +184,12 @@
}
}
+ @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);
--- a/jdk/src/solaris/classes/sun/awt/X11/XFramePeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XFramePeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
}
}
- private boolean isTargetUndecorated() {
+ @Override
+ boolean isTargetUndecorated() {
if (undecorated != null) {
return undecorated.booleanValue();
} else {
@@ -285,19 +289,20 @@
* 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) {
--- a/jdk/src/solaris/classes/sun/awt/X11/XMenuItemPeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XMenuItemPeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
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 @@
} catch (InvocationTargetException e) {
e.printStackTrace();
}
- return XWindow.defaultFont;
+ return XWindow.getDefaultFont();
}
String getTargetLabel() {
--- a/jdk/src/solaris/classes/sun/awt/X11/XNETProtocol.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XNETProtocol.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
boolean doStateProtocol() {
boolean res = active() && checkProtocol(XA_NET_SUPPORTED, XA_NET_WM_STATE);
+ stateLog.finer("doStateProtocol() returns " + res);
return res;
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XPopupMenuPeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XPopupMenuPeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
//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 @@
} catch (InvocationTargetException e) {
e.printStackTrace();
}
- return XWindow.defaultFont;
+ return XWindow.getDefaultFont();
}
String getTargetLabel() {
--- a/jdk/src/solaris/classes/sun/awt/X11/XSelection.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XSelection.java Thu Mar 27 12:28:53 2008 -0700
@@ -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.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 @@
/**
* 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 @@
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 @@
/* 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 @@
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 @@
* @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 @@
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 @@
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 @@
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 @@
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 @@
} 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 @@
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 @@
byte[] data = null;
synchronized (lock) {
- SELECTION_TIMEOUT = UNIXToolkit.getDatatransferTimeout();
-
WindowPropertyGetter dataGetter =
new WindowPropertyGetter(XWindow.getXAWTRootWindow().getWindow(),
selectionPropertyAtom, 0, MAX_LENGTH,
@@ -379,7 +318,7 @@
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 @@
incrDataGetter.getActualFormat());
}
- count = (int)incrDataGetter.getNumberOfItems();
+ count = incrDataGetter.getNumberOfItems();
if (count == 0) {
break;
@@ -489,7 +428,7 @@
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 @@
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 @@
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 @@
}
}
- 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;
+ }
+
+ boolean conversionSucceeded = false;
+
+ // 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();
}
- long propertyAtom = xse.get_property();
- long[] formats = null;
+ 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 (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);
+ 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 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.
--- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Thu Mar 27 12:28:53 2008 -0700
@@ -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.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 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;
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XTrayIconPeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XTrayIconPeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 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 @@
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);
--- a/jdk/src/solaris/classes/sun/awt/X11/XWM.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWM.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
/*****************************************************************************\
* 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 @@
}
/* 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 @@
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 @@
/*
* 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 @@
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);
+ /*
+ * 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 {
+ res = Frame.NORMAL;
}
- if (is_state_change) {
- return Integer.valueOf(res);
- } else {
- return null;
- }
+ res |= getExtendedState(window);
+ return res;
}
/*****************************************************************************\
@@ -1180,9 +1178,7 @@
* 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 @@
}
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 @@
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();
--- a/jdk/src/solaris/classes/sun/awt/X11/XWindow.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWindow.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
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 @@
}
Font font = afont;
if (font == null) {
- font = defaultFont;
+ font = XWindow.getDefaultFont();
}
return new SunGraphics2D(surfData, fgColor, bgColor, font);
}
@@ -902,13 +910,11 @@
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 @@
// 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 @@
}
// 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;
--- a/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
//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 @@
return !(target instanceof Frame || target instanceof Dialog);
}
boolean hasWarningWindow() {
- return warningWindow != null;
+ return ((Window)target).getWarningString() != null;
}
// The height of menu bar window
--- a/jdk/src/solaris/classes/sun/awt/motif/MDialogPeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/motif/MDialogPeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -102,4 +102,9 @@
public void blockWindows(java.util.List<Window> toBlock) {
// do nothing
}
+
+ @Override
+ final boolean isTargetUndecorated() {
+ return ((Dialog)target).isUndecorated();
+ }
}
--- a/jdk/src/solaris/classes/sun/awt/motif/MEmbeddedFramePeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/motif/MEmbeddedFramePeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -204,4 +204,10 @@
}
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);
+ }
}
--- a/jdk/src/solaris/classes/sun/awt/motif/MFramePeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/motif/MFramePeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -503,4 +503,9 @@
public Rectangle getBoundsPrivate() {
return getBounds();
}
+
+ @Override
+ final boolean isTargetUndecorated() {
+ return ((Frame)target).isUndecorated();
+ }
}
--- a/jdk/src/solaris/classes/sun/awt/motif/MWindowPeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/solaris/classes/sun/awt/motif/MWindowPeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -113,6 +113,12 @@
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 @@
GraphicsConfiguration gc = getGraphicsConfiguration();
((X11GraphicsDevice)gc.getDevice()).addDisplayChangedListener(this);
+
}
/* Support for multiple icons is not implemented in MAWT */
@@ -246,6 +253,8 @@
// 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 @@
}
public void handleMoved(int x, int y) {
+ sysX = x;
+ sysY = y;
postEvent(new ComponentEvent(target, ComponentEvent.COMPONENT_MOVED));
}
@@ -505,4 +516,87 @@
}
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);
+ }
+
}
--- a/jdk/src/windows/classes/sun/awt/windows/WDialogPeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WDialogPeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -108,11 +108,18 @@
}
}
+ @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);
}
}
--- a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -65,4 +65,10 @@
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);
+ }
}
--- a/jdk/src/windows/classes/sun/awt/windows/WFramePeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WFramePeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -64,11 +64,18 @@
}
}
+ @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);
}
}
--- a/jdk/src/windows/classes/sun/awt/windows/WObjectPeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WObjectPeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
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;
--- a/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java Thu Mar 27 12:28:53 2008 -0700
@@ -434,6 +434,97 @@
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;
--- a/jdk/src/windows/native/sun/windows/awt.h Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/native/sun/windows/awt.h Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
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 @@
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 @@
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 @@
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 */
/*
--- a/jdk/src/windows/native/sun/windows/awt_Component.cpp Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
CriticalSection windowMoveLock;
BOOL windowMoveLockHeld = FALSE;
+int AwtComponent::sm_wheelRotationAmount = 0;
+
/************************************************************************
* AwtComponent methods
*/
@@ -2074,6 +2076,8 @@
sm_realFocusOpposite = NULL;
}
+ sm_wheelRotationAmount = 0;
+
SendFocusEvent(java_awt_event_FocusEvent_FOCUS_GAINED, hWndLostFocus);
return mrDoDefault;
@@ -2105,6 +2109,7 @@
}
sm_focusOwner = NULL;
+ sm_wheelRotationAmount = 0;
SendFocusEvent(java_awt_event_FocusEvent_FOCUS_LOST, hWndGotFocus);
return mrDoDefault;
@@ -2190,8 +2195,11 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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::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();
--- a/jdk/src/windows/native/sun/windows/awt_Component.h Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Component.h Thu Mar 27 12:28:53 2008 -0700
@@ -392,7 +392,7 @@
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 @@
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
--- a/jdk/src/windows/native/sun/windows/awt_Dialog.cpp Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Dialog.cpp Thu Mar 27 12:28:53 2008 -0700
@@ -273,6 +273,10 @@
{
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 @@
// 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 @@
::BringWindowToTop(topMostBlocker);
::SetForegroundWindow(topMostBlocker);
}
+ return 1;
}
}
}
--- a/jdk/src/windows/native/sun/windows/awt_Frame.cpp Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Frame.cpp Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
// 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 @@
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 @@
* 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 @@
::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;
--- a/jdk/src/windows/native/sun/windows/awt_Object.cpp Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Object.cpp Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
*/
jfieldID AwtObject::pDataID;
+jfieldID AwtObject::destroyedID;
jfieldID AwtObject::targetID;
jclass AwtObject::wObjectPeerClass;
jmethodID AwtObject::getPeerForTargetMID;
@@ -223,6 +224,7 @@
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 @@
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);
--- a/jdk/src/windows/native/sun/windows/awt_Object.h Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Object.h Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
/* sun.awt.windows.WObjectPeer field and method ids */
static jfieldID pDataID;
+ static jfieldID destroyedID;
static jfieldID targetID;
static jmethodID getPeerForTargetMID;
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
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 @@
}
}
-/*
- * 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;
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.h Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.h Thu Mar 27 12:28:53 2008 -0700
@@ -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:
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;
--- a/jdk/src/windows/native/sun/windows/awt_Window.cpp Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Window.cpp Thu Mar 27 12:28:53 2008 -0700
@@ -125,6 +125,11 @@
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 @@
}
::RemoveProp(GetHWnd(), ModalBlockerProp);
- ::RemoveProp(GetHWnd(), ModalSaveWSEXProp);
if (m_grabbedWindow == this) {
Ungrab();
@@ -330,8 +334,11 @@
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 @@
(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 @@
(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 @@
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 @@
// 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 @@
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;
}
--- a/jdk/src/windows/native/sun/windows/awt_Window.h Wed Mar 26 17:48:05 2008 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Window.h Thu Mar 27 12:28:53 2008 -0700
@@ -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 @@
/* 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();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Focus/NonFocusableResizableTooSmall/NonFocusableResizableTooSmall.java Thu Mar 27 12:28:53 2008 -0700
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Focus/RestoreFocusOnDisabledComponentTest/RestoreFocusOnDisabledComponentTest.java Thu Mar 27 12:28:53 2008 -0700
@@ -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);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Mixing/ValidBounds.java Thu Mar 27 12:28:53 2008 -0700
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Modal/WsDisabledStyle/CloseBlocker/CloseBlocker.java Thu Mar 27 12:28:53 2008 -0700
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Modal/WsDisabledStyle/OverBlocker/OverBlocker.java Thu Mar 27 12:28:53 2008 -0700
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Modal/WsDisabledStyle/Winkey/Winkey.java Thu Mar 27 12:28:53 2008 -0700
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/MouseEvent/SmoothWheel/SmoothWheel.java Thu Mar 27 12:28:53 2008 -0700
@@ -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