# HG changeset patch # User lana # Date 1334769490 25200 # Node ID b81249542f140e64e65733105d3f1b2a2ee25e2d # Parent 2b900319e3ae65f3a50ac7f5544945f40f516228# Parent f749f1ed92ca0b3121ea4fdca56f1c29fa19fc8a Merge diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java --- a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java Wed Apr 18 10:18:10 2012 -0700 @@ -213,16 +213,8 @@ SwingUtilities3.setDelegateRepaintManager(delegate, new RepaintManager() { @Override public void addDirtyRegion(final JComponent c, final int x, final int y, final int w, final int h) { - if (SunToolkit.isDispatchThreadForAppContext(getTarget())) { - synchronized (getDelegateLock()) { - if (getDelegate().isPaintingForPrint()) { - return; - } - } - } - Rectangle res = SwingUtilities.convertRectangle( - c, new Rectangle(x, y, w, h), getDelegate()); - repaintPeer(res); + repaintPeer(SwingUtilities.convertRectangle( + c, new Rectangle(x, y, w, h), getDelegate())); } }); } @@ -616,6 +608,17 @@ windowLocation.y + locationInWindow.y); } + /** + * Returns the cursor of the peer, which is cursor of the target by default, + * but peer can override this behavior. + * + * @param p Point relative to the peer. + * @return Cursor of the peer or null if default cursor should be used. + */ + protected Cursor getCursor(final Point p) { + return getTarget().getCursor(); + } + @Override public void setBackground(final Color c) { final Color oldBg = getBackground(); @@ -982,16 +985,23 @@ // DropTargetPeer Method @Override public void addDropTarget(DropTarget dt) { - synchronized (dropTargetLock){ - // 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only - // if it's the first (or last) one for the component. Otherwise this call is a no-op. - if (++fNumDropTargets == 1) { - // Having a non-null drop target would be an error but let's check just in case: - if (fDropTarget != null) - System.err.println("CComponent.addDropTarget(): current drop target is non-null."); + LWWindowPeer winPeer = getWindowPeerOrSelf(); + if (winPeer != null && winPeer != this) { + // We need to register the DropTarget in the + // peer of the window ancestor of the component + winPeer.addDropTarget(dt); + } else { + synchronized (dropTargetLock) { + // 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only + // if it's the first (or last) one for the component. Otherwise this call is a no-op. + if (++fNumDropTargets == 1) { + // Having a non-null drop target would be an error but let's check just in case: + if (fDropTarget != null) + System.err.println("CComponent.addDropTarget(): current drop target is non-null."); - // Create a new drop target: - fDropTarget = CDropTarget.createDropTarget(dt, target, this); + // Create a new drop target: + fDropTarget = CDropTarget.createDropTarget(dt, target, this); + } } } } @@ -999,17 +1009,24 @@ // DropTargetPeer Method @Override public void removeDropTarget(DropTarget dt) { - synchronized (dropTargetLock){ - // 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only - // if it's the first (or last) one for the component. Otherwise this call is a no-op. - if (--fNumDropTargets == 0) { - // Having a null drop target would be an error but let's check just in case: - if (fDropTarget != null) { - // Dispose of the drop target: - fDropTarget.dispose(); - fDropTarget = null; - } else - System.err.println("CComponent.removeDropTarget(): current drop target is null."); + LWWindowPeer winPeer = getWindowPeerOrSelf(); + if (winPeer != null && winPeer != this) { + // We need to unregister the DropTarget in the + // peer of the window ancestor of the component + winPeer.removeDropTarget(dt); + } else { + synchronized (dropTargetLock){ + // 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only + // if it's the first (or last) one for the component. Otherwise this call is a no-op. + if (--fNumDropTargets == 0) { + // Having a null drop target would be an error but let's check just in case: + if (fDropTarget != null) { + // Dispose of the drop target: + fDropTarget.dispose(); + fDropTarget = null; + } else + System.err.println("CComponent.removeDropTarget(): current drop target is null."); + } } } } diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/classes/sun/lwawt/LWCursorManager.java --- a/jdk/src/macosx/classes/sun/lwawt/LWCursorManager.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/LWCursorManager.java Wed Apr 18 10:18:10 2012 -0700 @@ -36,32 +36,34 @@ public abstract class LWCursorManager { - // A flag to indicate if the update is scheduled, so we don't - // process it twice - private AtomicBoolean updatePending = new AtomicBoolean(false); + /** + * A flag to indicate if the update is scheduled, so we don't process it + * twice. + */ + private final AtomicBoolean updatePending = new AtomicBoolean(false); protected LWCursorManager() { } - /* + /** * Sets the cursor to correspond the component currently under mouse. * * This method should not be executed on the toolkit thread as it * calls to user code (e.g. Container.findComponentAt). */ - public void updateCursor() { + public final void updateCursor() { updatePending.set(false); updateCursorImpl(); } - /* + /** * Schedules updating the cursor on the corresponding event dispatch * thread for the given window. * * This method is called on the toolkit thread as a result of a * native update cursor request (e.g. WM_SETCURSOR on Windows). */ - public void updateCursorLater(LWWindowPeer window) { + public final void updateCursorLater(final LWWindowPeer window) { if (updatePending.compareAndSet(false, true)) { Runnable r = new Runnable() { @Override @@ -74,45 +76,58 @@ } private void updateCursorImpl() { - LWWindowPeer windowUnderCursor = LWWindowPeer.getWindowUnderCursor(); - Point cursorPos = getCursorPosition(); - LWComponentPeer componentUnderCursor = null; - // TODO: it's possible to get the component under cursor directly as - // it's stored in LWWindowPee anyway (lastMouseEventPeer) - if (windowUnderCursor != null) { - componentUnderCursor = windowUnderCursor.findPeerAt(cursorPos.x, cursorPos.y); + final Point cursorPos = getCursorPosition(); + final Component c = findComponent(cursorPos); + final Cursor cursor; + final Object peer = LWToolkit.targetToPeer(c); + if (peer instanceof LWComponentPeer) { + final LWComponentPeer lwpeer = (LWComponentPeer) peer; + final Point p = lwpeer.getLocationOnScreen(); + cursor = lwpeer.getCursor(new Point(cursorPos.x - p.x, + cursorPos.y - p.y)); + } else { + cursor = (c != null) ? c.getCursor() : null; } - Cursor cursor = null; - if (componentUnderCursor != null) { - Component c = componentUnderCursor.getTarget(); + // TODO: default cursor for modal blocked windows + setCursor(cursor); + } + + /** + * Returns the first visible, enabled and showing component under cursor. + * + * @param cursorPos Current cursor position. + * @return Component + */ + private static final Component findComponent(final Point cursorPos) { + final LWComponentPeer peer = LWWindowPeer.getPeerUnderCursor(); + Component c = null; + if (peer != null) { + c = peer.getTarget(); if (c instanceof Container) { - Point p = componentUnderCursor.getLocationOnScreen(); - c = ((Container)c).findComponentAt(cursorPos.x - p.x, cursorPos.y - p.y); + final Point p = peer.getLocationOnScreen(); + c = ((Container) c).findComponentAt(cursorPos.x - p.x, + cursorPos.y - p.y); } - // Traverse up to the first visible, enabled and showing component while (c != null) { if (c.isVisible() && c.isEnabled() && (c.getPeer() != null)) { break; } c = c.getParent(); } - if (c != null) { - cursor = c.getCursor(); - } } - // TODO: default cursor for modal blocked windows - setCursor(windowUnderCursor, cursor); + return c; } - /* + /** * Returns the current cursor position. */ // TODO: make it public to reuse for MouseInfo protected abstract Point getCursorPosition(); - /* - * Sets a cursor. The cursor can be null if the mouse is not over a Java window. + /** + * Sets a cursor. The cursor can be null if the mouse is not over a Java + * window. + * @param cursor the new {@code Cursor}. */ - protected abstract void setCursor(LWWindowPeer windowUnderCursor, Cursor cursor); - + protected abstract void setCursor(Cursor cursor); } diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/classes/sun/lwawt/LWRepaintArea.java --- a/jdk/src/macosx/classes/sun/lwawt/LWRepaintArea.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/LWRepaintArea.java Wed Apr 18 10:18:10 2012 -0700 @@ -39,12 +39,8 @@ @Override protected void updateComponent(final Component comp, final Graphics g) { if (comp != null) { - final LWComponentPeer peer = (LWComponentPeer) comp.getPeer(); - if (peer != null) { - peer.paintPeer(g); - } super.updateComponent(comp, g); - flushBuffers(peer); + flushBuffers((LWComponentPeer) comp.getPeer()); } } diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java --- a/jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java Wed Apr 18 10:18:10 2012 -0700 @@ -27,6 +27,7 @@ package sun.lwawt; import java.awt.Component; +import java.awt.Cursor; import java.awt.Dimension; import java.awt.Point; import java.awt.TextArea; @@ -72,6 +73,15 @@ } @Override + protected Cursor getCursor(final Point p) { + final boolean isContains; + synchronized (getDelegateLock()) { + isContains = getDelegate().getViewport().getBounds().contains(p); + } + return isContains ? super.getCursor(p) : null; + } + + @Override protected Component getDelegateFocusOwner() { return getTextComponent(); } diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/classes/sun/lwawt/LWTextFieldPeer.java --- a/jdk/src/macosx/classes/sun/lwawt/LWTextFieldPeer.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/LWTextFieldPeer.java Wed Apr 18 10:18:10 2012 -0700 @@ -31,6 +31,7 @@ import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; import java.awt.peer.TextFieldPeer; import javax.swing.JPasswordField; @@ -97,6 +98,21 @@ getText(), e.getWhen(), e.getModifiers())); } + /** + * Restoring native behavior. We should sets the selection range to zero, + * when component lost its focus. + * + * @param e the focus event + */ + @Override + protected void handleJavaFocusEvent(final FocusEvent e) { + if (e.getID() == FocusEvent.FOCUS_LOST) { + // In order to de-select the selection + setCaretPosition(0); + } + super.handleJavaFocusEvent(e); + } + private final class JTextAreaDelegate extends JPasswordField { // Empty non private constructor was added because access to this diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java --- a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java Wed Apr 18 10:18:10 2012 -0700 @@ -784,9 +784,8 @@ } mouseClickButtons &= ~eventButtonMask; } - - notifyUpdateCursor(); } + notifyUpdateCursor(); } public void dispatchMouseWheelEvent(long when, int x, int y, int modifiers, @@ -1057,6 +1056,10 @@ return lastMouseEventPeer != null ? lastMouseEventPeer.getWindowPeerOrSelf() : null; } + public static LWComponentPeer getPeerUnderCursor() { + return lastMouseEventPeer; + } + public boolean requestWindowFocus(CausedFocusEvent.Cause cause) { if (focusLog.isLoggable(PlatformLogger.FINE)) { focusLog.fine("requesting native focus to " + this); diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/classes/sun/lwawt/macosx/CCursorManager.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CCursorManager.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CCursorManager.java Wed Apr 18 10:18:10 2012 -0700 @@ -25,24 +25,26 @@ package sun.lwawt.macosx; -import java.awt.*; +import sun.lwawt.LWCursorManager; + +import java.awt.Cursor; +import java.awt.Point; import java.awt.geom.Point2D; -import sun.lwawt.*; +final class CCursorManager extends LWCursorManager { -public class CCursorManager extends LWCursorManager { private static native Point2D nativeGetCursorPosition(); private static native void nativeSetBuiltInCursor(final int type, final String name); private static native void nativeSetCustomCursor(final long imgPtr, final double x, final double y); private static final int NAMED_CURSOR = -1; - private final static CCursorManager theInstance = new CCursorManager(); + private static final CCursorManager theInstance = new CCursorManager(); public static CCursorManager getInstance() { return theInstance; } - Cursor currentCursor; + private volatile Cursor currentCursor; private CCursorManager() { } @@ -62,8 +64,11 @@ } @Override - protected void setCursor(final LWWindowPeer windowUnderCursor, final Cursor cursor) { - if (cursor == currentCursor) return; + protected void setCursor(final Cursor cursor) { + if (cursor == currentCursor) { + return; + } + currentCursor = cursor; if (cursor == null) { nativeSetBuiltInCursor(Cursor.DEFAULT_CURSOR, null); @@ -71,10 +76,12 @@ } if (cursor instanceof CCustomCursor) { - final CCustomCursor customCursor = ((CCustomCursor)cursor); + final CCustomCursor customCursor = (CCustomCursor) cursor; final long imagePtr = customCursor.getImageData(); - final Point hotSpot = customCursor.getHotSpot(); - if(imagePtr != 0L) nativeSetCustomCursor(imagePtr, hotSpot.x, hotSpot.y); + if (imagePtr != 0L) { + final Point hotSpot = customCursor.getHotSpot(); + nativeSetCustomCursor(imagePtr, hotSpot.x, hotSpot.y); + } return; } @@ -94,13 +101,6 @@ throw new RuntimeException("Unimplemented"); } - static long getNativeWindow(final LWWindowPeer window) { - if (window == null) return 0; - final CPlatformWindow platformWindow = (CPlatformWindow)window.getPlatformWindow(); - if (platformWindow == null) return 0; - return platformWindow.getNSWindowPtr(); - } - // package private methods to handle cursor change during drag-and-drop private boolean isDragging = false; private Point dragPos = null; @@ -109,9 +109,7 @@ if (isDragging) { throw new RuntimeException("Invalid Drag state in CCursorManager!"); } - isDragging = true; - dragPos = new Point(x, y); } diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java Wed Apr 18 10:18:10 2012 -0700 @@ -89,12 +89,19 @@ } public void handleKeyEvent(int eventType, int modifierFlags, String characters, + String charsIgnoringMods, boolean isRepeat, short keyCode, + boolean needsKeyTyped) { + responder.handleKeyEvent(eventType, modifierFlags, charsIgnoringMods, keyCode, needsKeyTyped); + } + + // REMIND: delete this method once 'deploy' changes for 7156194 is pushed + public void handleKeyEvent(int eventType, int modifierFlags, String characters, String charsIgnoringMods, boolean isRepeat, short keyCode) { - responder.handleKeyEvent(eventType, modifierFlags, charsIgnoringMods, keyCode); + handleKeyEvent(eventType, modifierFlags, characters, charsIgnoringMods, isRepeat, keyCode, true); } public void handleInputEvent(String text) { - new RuntimeException("Not implemented"); + responder.handleInputEvent(text); } public void handleFocusEvent(boolean focused) { diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/classes/sun/lwawt/macosx/CImage.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CImage.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CImage.java Wed Apr 18 10:18:10 2012 -0700 @@ -29,10 +29,14 @@ import java.awt.geom.Dimension2D; import java.awt.image.*; +import java.util.Arrays; +import java.util.List; + import sun.awt.image.SunWritableRaster; public class CImage extends CFRetainedResource { private static native long nativeCreateNSImageFromArray(int[] buffer, int w, int h); + private static native long nativeCreateNSImageFromArrays(int[][] buffers, int w[], int h[]); private static native long nativeCreateNSImageFromFileContents(String file); private static native long nativeCreateNSImageOfFileFromLaunchServices(String file); private static native long nativeCreateNSImageFromImageName(String name); @@ -93,8 +97,7 @@ return createImageUsingNativeSize(nativeCreateNSImageFromImageName(name)); } - // This is used to create a CImage from a Image - public CImage createFromImage(final Image image) { + private static int[] imageToArray(Image image) { if (image == null) return null; MediaTracker mt = new MediaTracker(new Label()); @@ -117,8 +120,50 @@ g2.setComposite(AlphaComposite.Src); g2.drawImage(image, 0, 0, null); g2.dispose(); - int[] buffer = ((DataBufferInt)bimg.getRaster().getDataBuffer()).getData(); - return new CImage(nativeCreateNSImageFromArray(buffer, w, h)); + return ((DataBufferInt)bimg.getRaster().getDataBuffer()).getData(); + } + + // This is used to create a CImage from a Image + public CImage createFromImage(final Image image) { + int[] buffer = imageToArray(image); + if (buffer == null) { + return null; + } + return new CImage(nativeCreateNSImageFromArray(buffer, image.getWidth(null), image.getHeight(null))); + } + + public CImage createFromImages(List images) { + if (images == null || images.isEmpty()) { + return null; + } + + int num = images.size(); + + int[][] buffers = new int[num][]; + int[] w = new int[num]; + int[] h = new int[num]; + + num = 0; + + for (Image img : images) { + buffers[num] = imageToArray(img); + if (buffers[num] == null) { + // Unable to process the image + continue; + } + w[num] = img.getWidth(null); + h[num] = img.getHeight(null); + num++; + } + + if (num == 0) { + return null; + } + + return new CImage(nativeCreateNSImageFromArrays( + Arrays.copyOf(buffers, num), + Arrays.copyOf(w, num), + Arrays.copyOf(h, num))); } static int getSelectorAsInt(final String fromString) { diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java Wed Apr 18 10:18:10 2012 -0700 @@ -117,7 +117,7 @@ * Handles key events. */ void handleKeyEvent(int eventType, int modifierFlags, String chars, - short keyCode) { + short keyCode, boolean needsKeyTyped) { boolean isFlagsChangedEvent = isNpapiCallback ? (eventType == CocoaConstants.NPCocoaEventFlagsChanged) : (eventType == CocoaConstants.NSFlagsChanged); @@ -158,11 +158,24 @@ NSEvent.nsToJavaEventType(eventType); } + char javaChar = NSEvent.nsToJavaChar(testChar, modifierFlags); + // Some keys may generate a KEY_TYPED, but we can't determine + // what that character is. That's likely a bug, but for now we + // just check for CHAR_UNDEFINED. + if (javaChar == KeyEvent.CHAR_UNDEFINED) { + postsTyped = false; + } + + int jmodifiers = NSEvent.nsToJavaKeyModifiers(modifierFlags); long when = System.currentTimeMillis(); peer.dispatchKeyEvent(jeventType, when, jmodifiers, - jkeyCode, testChar, jkeyLocation); + jkeyCode, javaChar, jkeyLocation); + + // Current browser may be sending input events, so don't + // post the KEY_TYPED here. + postsTyped &= needsKeyTyped; // That's the reaction on the PRESSED (not RELEASED) event as it comes to // appear in MacOSX. @@ -172,8 +185,23 @@ boolean isMetaDown = (jmodifiers & KeyEvent.META_DOWN_MASK) != 0; if (jeventType == KeyEvent.KEY_PRESSED && postsTyped && !isMetaDown) { peer.dispatchKeyEvent(KeyEvent.KEY_TYPED, when, jmodifiers, - KeyEvent.VK_UNDEFINED, testChar, + KeyEvent.VK_UNDEFINED, javaChar, KeyEvent.KEY_LOCATION_UNKNOWN); } } + + void handleInputEvent(String text) { + if (text != null) { + int index = 0, length = text.length(); + char c; + while (index < length) { + c = text.charAt(index); + peer.dispatchKeyEvent(KeyEvent.KEY_TYPED, + System.currentTimeMillis(), + 0, KeyEvent.VK_UNDEFINED, c, + KeyEvent.KEY_LOCATION_UNKNOWN); + index++; + } + } + } } diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java Wed Apr 18 10:18:10 2012 -0700 @@ -199,7 +199,7 @@ private void deliverKeyEvent(NSEvent event) { responder.handleKeyEvent(event.getType(), event.getModifierFlags(), - event.getCharactersIgnoringModifiers(), event.getKeyCode()); + event.getCharactersIgnoringModifiers(), event.getKeyCode(), true); } private void deliverWindowDidExposeEvent() { diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Apr 18 10:18:10 2012 -0700 @@ -661,11 +661,19 @@ @Override public void setResizable(boolean resizable) { setStyleBits(RESIZABLE, resizable); + + // Re-apply the size constraints and the size to ensure the space + // occupied by the grow box is counted properly + setMinimumSize(1, 1); // the method ignores its arguments + + Rectangle bounds = peer.getBounds(); + setBounds(bounds.x, bounds.y, bounds.width, bounds.height); } @Override public void setMinimumSize(int width, int height) { //TODO width, height should be used + //NOTE: setResizable() calls setMinimumSize(1,1) relaying on the logic below final long nsWindowPtr = getNSWindowPtr(); final Dimension min = target.getMinimumSize(); final Dimension max = target.getMaximumSize(); @@ -802,11 +810,7 @@ if (icons == null || icons.size() == 0) { return null; } - - // TODO: need a walk-through to find the best image. - // The best mean with higher resolution. Otherwise an icon looks bad. - final Image image = icons.get(0); - return CImage.getCreator().createFromImage(image); + return CImage.getCreator().createFromImages(icons); } /* diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed Apr 18 10:18:10 2012 -0700 @@ -647,6 +647,15 @@ return InputEvent.CTRL_MASK | InputEvent.ALT_MASK; } + /** + * Tests whether specified key modifiers mask can be used to enter a printable + * character. + */ + @Override + public boolean isPrintableCharacterModifiersMask(int mods) { + return ((mods & (InputEvent.META_MASK | InputEvent.CTRL_MASK)) == 0); + } + // Extends PeerEvent because we want to pass long an ObjC mediator object and because we want these events to be posted early // Typically, rather than relying on the notifier to call notifyAll(), we use the mediator to stop the runloop public static class CPeerEvent extends PeerEvent { diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/classes/sun/lwawt/macosx/event/NSEvent.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/event/NSEvent.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/event/NSEvent.java Wed Apr 18 10:18:10 2012 -0700 @@ -245,6 +245,12 @@ */ public static native void nsKeyModifiersToJavaKeyInfo(int[] in, int[] out); + /* + * There is a small number of NS characters that need to be converted + * into other characters before we pass them to AWT. + */ + public static native char nsToJavaChar(char nsChar, int modifierFlags); + public static boolean isPopupTrigger(int jmodifiers) { final boolean isRightButtonDown = ((jmodifiers & InputEvent.BUTTON3_DOWN_MASK) != 0); final boolean isLeftButtonDown = ((jmodifiers & InputEvent.BUTTON1_DOWN_MASK) != 0); diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/native/sun/awt/AWTEvent.m --- a/jdk/src/macosx/native/sun/awt/AWTEvent.m Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/native/sun/awt/AWTEvent.m Wed Apr 18 10:18:10 2012 -0700 @@ -124,7 +124,7 @@ {0x32, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_QUOTE}, {0x33, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SPACE}, {0x34, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_ENTER}, - {0x35, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_ESCAPE}, + {0x35, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_ESCAPE}, {0x36, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, {0x37, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_META}, // **** {0x38, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_SHIFT}, // **** @@ -308,6 +308,9 @@ * Almost all unicode characters just go from NS to Java with no translation. * For the few exceptions, we handle it here with this small table. */ +#define ALL_NS_KEY_MODIFIERS_MASK \ + (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask) + static struct _char { NSUInteger modifier; unichar nsChar; @@ -315,17 +318,17 @@ } const charTable[] = { // map enter on keypad to same as return key - {0, NSEnterCharacter, NSNewlineCharacter}, + {0, NSEnterCharacter, NSNewlineCharacter}, // [3134616] return newline instead of carriage return - {0, NSCarriageReturnCharacter, NSNewlineCharacter}, + {0, NSCarriageReturnCharacter, NSNewlineCharacter}, // "delete" means backspace in Java - {0, NSDeleteCharacter, NSBackspaceCharacter}, - {0, NSDeleteFunctionKey, NSDeleteCharacter}, + {ALL_NS_KEY_MODIFIERS_MASK, NSDeleteCharacter, NSBackspaceCharacter}, + {ALL_NS_KEY_MODIFIERS_MASK, NSDeleteFunctionKey, NSDeleteCharacter}, // back-tab is only differentiated from tab by Shift flag - {NSShiftKeyMask, NSBackTabCharacter, NSTabCharacter}, + {NSShiftKeyMask, NSBackTabCharacter, NSTabCharacter}, {0, 0, 0} }; @@ -334,12 +337,8 @@ NsCharToJavaChar(unichar nsChar, NSUInteger modifiers) { const struct _char *cur; - NSUInteger keyModifierFlags = - NSShiftKeyMask | NSControlKeyMask | - NSAlternateKeyMask | NSCommandKeyMask; - // Mask off just the keyboard modifiers from the event modifier mask. - NSUInteger testableFlags = (modifiers & keyModifierFlags); + NSUInteger testableFlags = (modifiers & ALL_NS_KEY_MODIFIERS_MASK); // walk through table & find the match for (cur = charTable; cur->nsChar != 0 ; cur++) { @@ -507,189 +506,6 @@ return javaModifiers; } -/* - * Returns the correct java character for a key event. Most unicode - * characters don't require any fussing, but a few seem to need adjusting, - * see nsCharToJavaChar. - */ -static unichar -GetJavaCharacter(NSEvent *event, unsigned int index) -{ - unichar returnValue = java_awt_event_KeyEvent_CHAR_UNDEFINED; - NSString *chars = nil; - unichar testChar = 0, testDeadChar = 0; - jint javaModifiers = NsKeyModifiersToJavaModifiers([event modifierFlags]); - - switch ([event type]) { - case NSFlagsChanged: - // no character for modifier keys - returnValue = java_awt_event_KeyEvent_CHAR_UNDEFINED; - break; - - case NSKeyDown: - case NSKeyUp: - chars = [event characters]; - if ([chars length] > 0) { - testChar = [chars characterAtIndex:index]; - } - - if (javaModifiers == 0) { - // TODO: uses SPI... - //if (TSMGetDeadKeyState() != 0) { - // testDeadChar = [self deadKeyCharacter]; - //} - } - - if (testChar != 0) { - returnValue = NsCharToJavaChar(testChar, [event modifierFlags]); - } else if (testDeadChar != 0) { - returnValue = NsCharToJavaChar(testDeadChar, [event modifierFlags]); - } else { - returnValue = java_awt_event_KeyEvent_CHAR_UNDEFINED; - } - break; - - default: - //[NSException raise:@"AWT error" format:@"Attempt to get character code from non-key event!"]; - break; - } - - return returnValue; -} - -/* -static jchar -GetDeadKeyCharacter(NSEvent *event) -{ - // If the current event is not a dead key, return 0. - // TODO: this uses SPI; it's an optimization but not strictly necessary - //if (TSMGetDeadKeyState() == 0) { - // return 0; - //} - - // AppKit does not track dead-key states directly, but TSM does. Even then, - // it's not necessarily all that accurate, because the dead key can change - // given some combination of modifier keys on certain layouts. - // As a result, finding the unicode value for the front end of the dead - // key is a bit of a heuristic. - - // This algorithm was suggested by Aki Inoue. - // When you get a dead key, you need to simiulate what would happen in - // the current dead-key and modifier state if the user hit the spacebar. - // That will tell you the front end of the dead-key combination. - - unichar returnValue = 0; - const UInt16 VIRTUAL_KEY_SPACE = 49; - UInt32 deadKeyState = 0; - UInt32 appkitFlags = [event modifierFlags]; - UniCharCount actualStringLength; - UniChar unicodeInputString[16]; - TISInputSourceRef keyLayout; - const void *chrData; - - keyLayout = TISCopyCurrentKeyboardLayoutInputSource(); - CFDataRef cfUchrData = - TISGetInputSourceProperty(keyLayout, kTISPropertyUnicodeKeyLayoutData); - - if (cfUchrData == NULL) { - return returnValue; - } - - // The actual 'uchr' table is inside the CFDataRef. - chrData = CFDataGetBytePtr(cfUchrData); - - UInt8 keyboardType = LMGetKbdType(); - UInt32 keyEventModifiers = 0; - if (appkitFlags & NSShiftKeyMask) keyEventModifiers |= shiftKey; - if (appkitFlags & NSCommandKeyMask) keyEventModifiers |= cmdKey; - if (appkitFlags & NSAlphaShiftKeyMask) keyEventModifiers |= alphaLock; - if (appkitFlags & NSControlKeyMask) keyEventModifiers |= controlKey; - if (appkitFlags & NSAlternateKeyMask) keyEventModifiers |= optionKey; - - if (noErr == UCKeyTranslate(chrData, - VIRTUAL_KEY_SPACE, - ([event type] == NSKeyDown ? kUCKeyActionDown : kUCKeyActionUp), - keyEventModifiers, - keyboardType, - kUCKeyTranslateNoDeadKeysMask, - &deadKeyState, - 16, - &actualStringLength, - unicodeInputString)) - { - if (actualStringLength > 0) { - returnValue = unicodeInputString[0]; - } - } - - return returnValue; -} -*/ - - -// REMIND: The fix for MACOSX_PORT-539 introduces Java-level implementation -// of the function below (see CPlatformResponder). Consider removing this code. - -void -DeliverJavaKeyEvent(JNIEnv *env, NSEvent *event, jobject peer) -{ - jint javaKeyType = java_awt_event_KeyEvent_KEY_PRESSED; - jint javaKeyCode = java_awt_event_KeyEvent_VK_UNDEFINED; - jint javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN; - NSString *chars = nil; - BOOL postsTyped; - unichar testChar = java_awt_event_KeyEvent_CHAR_UNDEFINED; - unichar testDeadChar = 0; - jint javaModifiers = 0; - - switch ([event type]) { - case NSFlagsChanged: - NsKeyModifiersToJavaKeyInfo([event modifierFlags], - [event keyCode], - &javaKeyCode, - &javaKeyLocation, - &javaKeyType); - break; - - case NSKeyDown: - case NSKeyUp: - chars = [event charactersIgnoringModifiers]; - if ([chars length] > 0) { - testChar = [chars characterAtIndex:0]; - } - - javaModifiers = NsKeyModifiersToJavaModifiers([event modifierFlags]); - if (javaModifiers == 0) { - // TODO: dead key chars -// testDeadChar = GetDeadKeyCharacter(event); - } - - NsCharToJavaVirtualKeyCode(testChar, testDeadChar, - [event modifierFlags], [event keyCode], - &javaKeyCode, &javaKeyLocation, &postsTyped); - if( !postsTyped ) { - testChar = java_awt_event_KeyEvent_CHAR_UNDEFINED; - } - - javaKeyType = ([event type] == NSKeyDown) ? - java_awt_event_KeyEvent_KEY_PRESSED : - java_awt_event_KeyEvent_KEY_RELEASED; - break; - - default: - //[NSException raise:@"AWT error" format:@"Attempt to get virtual key code from non-key event!"]; - break; - } - - if (env != NULL) { - static JNF_CLASS_CACHE(jc_CPlatformView, "sun/lwawt/macosx/CPlatformView"); - static JNF_MEMBER_CACHE(jm_deliverKeyEvent, jc_CPlatformView, "deliverKeyEvent", "(IICII)V"); - JNFCallVoidMethod(env, peer, jm_deliverKeyEvent, - javaKeyType, javaModifiers, - testChar, javaKeyCode, javaKeyLocation); - } -} - jint GetJavaMouseModifiers(NSInteger button, NSUInteger modifierFlags) { // Mousing needs the key modifiers @@ -726,217 +542,6 @@ return modifiers; } -/* - * Converts an NSEvent button number to a MouseEvent constant. - */ -static jint -NSButtonToJavaButton(NSInteger nsButtonNumber) -{ - jint jbutton = java_awt_event_MouseEvent_NOBUTTON; - - if (nsButtonNumber == 0) { // left - jbutton = java_awt_event_MouseEvent_BUTTON1; - } else if (nsButtonNumber == 1) { // right - jbutton = java_awt_event_MouseEvent_BUTTON3; - } else if (nsButtonNumber == 2) { // middle - jbutton = java_awt_event_MouseEvent_BUTTON2; - } - - return jbutton; -} - - -static BOOL isDragging = NO; - -void -DeliverMouseClickedEvent(JNIEnv *env, NSEvent *event, jobject peer) -{ - NSPoint pt = [event locationInWindow]; - NSPoint pOnScreen = [NSEvent mouseLocation]; - jint etype = java_awt_event_MouseEvent_MOUSE_CLICKED; - jint modifiers = GetJavaMouseModifiers([event buttonNumber], [event modifierFlags]); - jint clickCount = [event clickCount]; - jint button = NSButtonToJavaButton([event buttonNumber]); - - if (env != NULL) { - static JNF_CLASS_CACHE(jc_CPlatformView, "sun/lwawt/macosx/CPlatformView"); - static JNF_MEMBER_CACHE(jm_deliverMouseEvent, jc_CPlatformView, - "deliverMouseEvent", "(IIIIFFFF)V"); - JNFCallVoidMethod(env, peer, jm_deliverMouseEvent, - etype, modifiers, - clickCount, button, - pt.x, pt.y, - pOnScreen.x, pOnScreen.y); - } -} - -/* - * After every key down event, this is called to make the matching - * KEY_TYPED (if this key posts those). We use the same NSEvent for it, - * but create a KEY_TYPED java event this time. - * If this key doesn't post typed, we don't post the event. - * - * TODO: some duplicated effort here; could just fold it - * into DeliverJavaKeyEvent... - */ -static void -DeliverKeyTypedEvents(JNIEnv *env, NSEvent *nsEvent, jobject peer) -{ - if (peer == NULL) { - return; - } - - jint javaKeyCode, javaKeyLocation; - BOOL postsTyped = NO; - unichar testChar, testDeadChar = 0; - jint javaModifiers = NsKeyModifiersToJavaModifiers([nsEvent modifierFlags]); - - if (javaModifiers == 0) { - testDeadChar = [nsEvent deadKeyCharacter]; - } - - NSString *theChars = [nsEvent characters]; - unsigned i, stringLength = [theChars length]; - - for (i = 0; i < stringLength; i++) { - testChar = [theChars characterAtIndex:i]; - NsCharToJavaVirtualKeyCode(testChar, testDeadChar, - [nsEvent modifierFlags], [nsEvent keyCode], - &javaKeyCode, &javaKeyLocation, &postsTyped); - - if (postsTyped) { - // Some keys may generate a KEY_TYPED, but we can't determine - // what that character is. That's likely a bug, but for now we - // just check for CHAR_UNDEFINED. - unichar theChar = GetJavaCharacter(nsEvent, i); - if (theChar != java_awt_event_KeyEvent_CHAR_UNDEFINED) { - if (env != NULL) { - static JNF_CLASS_CACHE(jc_CPlatformView, - "sun/lwawt/macosx/CPlatformView"); - static JNF_MEMBER_CACHE(jm_deliverKeyEvent, jc_CPlatformView, - "deliverKeyEvent", "(IICII)V"); - JNFCallVoidMethod(env, peer, jm_deliverKeyEvent, - java_awt_event_KeyEvent_KEY_TYPED, - javaModifiers, - theChar, - java_awt_event_KeyEvent_VK_UNDEFINED, - java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN); - } - } - } - } -} - -/* - * There are a couple of extra events that Java expects to get that don't - * actually correspond to a direct NSEvent, KEY_TYPED and MOUSE_CLICKED are - * both extra events that are sort of redundant with ordinary - * key downs and mouse ups. In this extra message, we take the original - * input event and if necessary, cons up a special follow-on event which - * we dispatch over to Java. - * - * For Java, keyDown's generate a KeyPressed (for each hardware key as it - * goes down) and then a "logical KeyTyped" event for the key event. (So - * a shift-a generates two presses, one keytyped of "A", and then two - * releases). The standard event utility function converts a key down to - * a key pressed. When appropriate, we need to cons up another event - * (KEY_TYPED) to follow a keyDown. - * - * Java expects you to send a clicked event if you got a down & up, with no - * intervening drag. So in addition to the MOUSE_RELEASED event that a - * mouseUp is translated to, we also have to cons up a MOUSE_CLICKED event - * for that case. Mike Paquette, god of Window Server event handling, - * confirmed this fact about how to determine if a mouse up event had an - * intervening drag: - * An initial mouse-down gets a click count of 1. Subsequent left or right - * mouse-downs within the space/time tolerance limits increment the click - * count. A mouse-up will have the clickCount of the last mouseDown if - * mouse is not outside the tolerance limits, but 0 otherwise. Thus, a - * down-up sequence without any intervening drag will have a click count - * of 0 in the mouse-up event. NOTE: The problem with this is that - * clickCount goes to zero after some point in time. So a long, click & - * hold without moving and then release the mouse doesn't create a - * MOUSE_CLICK event as it should. Java AWT now tracks the drag state itself. - * - * As another add-on, we also check for the status of mouse-motion events - * after a mouse-down, so we know whether to generate mouse-dragged events - * during this down sequence. - */ -void -SendAdditionalJavaEvents(JNIEnv *env, NSEvent *nsEvent, jobject peer) -{ - AWT_ASSERT_APPKIT_THREAD; - - NSEventType type = [nsEvent type]; - switch (type) { - case NSKeyDown: - break; - - case NSLeftMouseUp: - case NSRightMouseUp: - case NSOtherMouseUp: - // TODO: we may need to pull in changedDragToMove here... - //if (!isDragging && ([NSViewAWT changedDragToMove]==NO)) { - if (!isDragging) { - // got down/up pair with no dragged in between; ignores drag events - // that have been morphed to move events - DeliverMouseClickedEvent(env, nsEvent, peer); - } - break; - -// TODO: to be implemented... -#if 0 - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - // - // During a drag, the AppKit does not send mouseEnter and mouseExit - // events. It turns out that doing a hitTest causes the window's - // view hierarchy to be locked from drawing and that, of course, - // slows everything way down. Synthesize mouseEnter and mouseExit - // then forward. - // - NSView *hitView = [[source model] hitTest:[nsEvent locationInWindow]]; - - if ((hitView != nil) && - ([hitView conformsToProtocol:@protocol(AWTPeerControl)])) - { - if (sLastMouseDraggedView == nil) { - sLastMouseDraggedView = hitView; - } - else if (hitView != sLastMouseDraggedView) { - // We know sLastMouseDraggedView is a AWTPeerControl. - jobject lastPeer = - [(id )sLastMouseDraggedView peer]; - - // Send mouseExit to sLastMouseDraggedView - jobject exitEvent = - makeMouseEvent(env, nsEvent, lastPeer, - sLastMouseDraggedView, - java_awt_event_MouseEvent_MOUSE_EXITED); - pushEventForward(exitEvent, env); - (*env)->DeleteLocalRef(env, exitEvent); - - // Send mouseEnter to hitView - jobject enterEvent = - makeMouseEvent(env, nsEvent, peer, hitView, - java_awt_event_MouseEvent_MOUSE_ENTERED); - pushEventForward(enterEvent, env); - - (*env)->DeleteLocalRef(env, enterEvent); - - // Set sLastMouseDraggedView = hitView - sLastMouseDraggedView = hitView; - } - } - break; -#endif - - default: - break; - } -} - jlong UTC(NSEvent *event) { struct timeval tv; if (gettimeofday(&tv, NULL) == 0) { @@ -1069,3 +674,23 @@ JNF_COCOA_EXIT(env); } + +/* + * Class: sun_lwawt_macosx_event_NSEvent + * Method: nsToJavaChar + * Signature: (CI)C + */ +JNIEXPORT jint JNICALL +Java_sun_lwawt_macosx_event_NSEvent_nsToJavaChar +(JNIEnv *env, jclass cls, char nsChar, jint modifierFlags) +{ + jchar javaChar = 0; + +JNF_COCOA_ENTER(env); + + javaChar = NsCharToJavaChar(nsChar, modifierFlags); + +JNF_COCOA_EXIT(env); + + return javaChar; +} diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/native/sun/awt/AWTWindow.h --- a/jdk/src/macosx/native/sun/awt/AWTWindow.h Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/native/sun/awt/AWTWindow.h Wed Apr 18 10:18:10 2012 -0700 @@ -39,7 +39,6 @@ @private JNFWeakJObjectWrapper *javaPlatformWindow; CMenuBar *javaMenuBar; - NSWindow *growBoxWindow; NSSize javaMinSize; NSSize javaMaxSize; jint styleBits; @@ -47,7 +46,6 @@ @property (nonatomic, retain) JNFWeakJObjectWrapper *javaPlatformWindow; @property (nonatomic, retain) CMenuBar *javaMenuBar; -@property (nonatomic, retain) NSWindow *growBoxWindow; @property (nonatomic) NSSize javaMinSize; @property (nonatomic) NSSize javaMaxSize; @property (nonatomic) jint styleBits; diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/native/sun/awt/AWTWindow.m --- a/jdk/src/macosx/native/sun/awt/AWTWindow.m Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m Wed Apr 18 10:18:10 2012 -0700 @@ -40,7 +40,6 @@ #import "ThreadUtilities.h" #import "OSVersion.h" - #define MASK(KEY) \ (sun_lwawt_macosx_CPlatformWindow_ ## KEY) @@ -50,31 +49,12 @@ #define SET(BITS, KEY, VALUE) \ BITS = VALUE ? BITS | MASK(KEY) : BITS & ~MASK(KEY) - static JNF_CLASS_CACHE(jc_CPlatformWindow, "sun/lwawt/macosx/CPlatformWindow"); -@interface JavaResizeGrowBoxOverlayWindow : NSWindow { } - -@end - -@implementation JavaResizeGrowBoxOverlayWindow - -- (BOOL) accessibilityIsIgnored -{ - return YES; -} - -- (NSArray *)accessibilityChildrenAttribute -{ - return nil; -} -@end - @implementation AWTWindow @synthesize javaPlatformWindow; @synthesize javaMenuBar; -@synthesize growBoxWindow; @synthesize javaMinSize; @synthesize javaMaxSize; @synthesize styleBits; @@ -154,24 +134,6 @@ } -- (BOOL) shouldShowGrowBox { - return isSnowLeopardOrLower() && IS(self.styleBits, RESIZABLE); -} - -- (NSImage *) createGrowBoxImage { - NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(12, 12)]; - JRSUIControlRef growBoxWidget = JRSUIControlCreate(FALSE); - JRSUIControlSetWidget(growBoxWidget, kJRSUI_Widget_growBoxTextured); - JRSUIControlSetWindowType(growBoxWidget, kJRSUI_WindowType_utility); - JRSUIRendererRef renderer = JRSUIRendererCreate(); - [image lockFocus]; // sets current graphics context to that of the image - JRSUIControlDraw(renderer, growBoxWidget, [[NSGraphicsContext currentContext] graphicsPort], CGRectMake(0, 1, 11, 11)); - [image unlockFocus]; - JRSUIRendererRelease(renderer); - JRSUIControlRelease(growBoxWidget); - return image; -} - - (id) initWithPlatformWindow:(JNFWeakJObjectWrapper *)platformWindow styleBits:(jint)bits frameRect:(NSRect)rect @@ -205,28 +167,6 @@ [self setReleasedWhenClosed:NO]; [self setPreservesContentDuringLiveResize:YES]; - if ([self shouldShowGrowBox]) { - NSImage *growBoxImage = [self createGrowBoxImage]; - growBoxWindow = [[JavaResizeGrowBoxOverlayWindow alloc] initWithContentRect:NSMakeRect(0, 0, [growBoxImage size].width, [growBoxImage size].height) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]; - [self.growBoxWindow setIgnoresMouseEvents:YES]; - [self.growBoxWindow setOpaque:NO]; - [self.growBoxWindow setBackgroundColor:[NSColor clearColor]]; - [self.growBoxWindow setHasShadow:NO]; - [self.growBoxWindow setReleasedWhenClosed:NO]; - - NSImageView *imageView = [[NSImageView alloc] initWithFrame:[self.growBoxWindow frame]]; - [imageView setEditable:NO]; - [imageView setAnimates:NO]; - [imageView setAllowsCutCopyPaste:NO]; - [self.growBoxWindow setContentView:imageView]; - [imageView setImage:growBoxImage]; - [growBoxImage release]; - [imageView release]; - - [self addChildWindow:self.growBoxWindow ordered:NSWindowAbove]; - [self adjustGrowBoxWindow]; - } else growBoxWindow = nil; - return self; } @@ -235,7 +175,6 @@ JNIEnv *env = [ThreadUtilities getJNIEnv]; [self.javaPlatformWindow setJObject:nil withEnv:env]; - self.growBoxWindow = nil; [super dealloc]; } @@ -321,14 +260,6 @@ // NSWindowDelegate methods -- (void) adjustGrowBoxWindow { - if (self.growBoxWindow != nil) { - NSRect parentRect = [self frame]; - parentRect.origin.x += (parentRect.size.width - [self.growBoxWindow frame].size.width); - [self.growBoxWindow setFrameOrigin:parentRect.origin]; - } -} - - (void) _deliverMoveResizeEvent { AWT_ASSERT_APPKIT_THREAD; @@ -342,8 +273,6 @@ // TODO: create generic AWT assert } - [self adjustGrowBoxWindow]; - NSRect frame = ConvertNSScreenRect(env, [self frame]); static JNF_MEMBER_CACHE(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIII)V"); @@ -548,6 +477,31 @@ } [super sendEvent:event]; } + +- (void)constrainSize:(NSSize*)size { + float minWidth = 0.f, minHeight = 0.f; + + if (IS(self.styleBits, DECORATED)) { + NSRect frame = [self frame]; + NSRect contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[self styleMask]]; + + float top = frame.size.height - contentRect.size.height; + float left = contentRect.origin.x - frame.origin.x; + float bottom = contentRect.origin.y - frame.origin.y; + float right = frame.size.width - (contentRect.size.width + left); + + // Speculative estimation: 80 - enough for window decorations controls + minWidth += left + right + 80; + minHeight += top + bottom; + } + + minWidth = MAX(1.f, minWidth); + minHeight = MAX(1.f, minHeight); + + size->width = MAX(size->width, minWidth); + size->height = MAX(size->height, minHeight); +} + @end // AWTWindow @@ -703,6 +657,8 @@ AWT_ASSERT_APPKIT_THREAD; NSRect rect = ConvertNSScreenRect(NULL, jrect); + [window constrainSize:&rect.size]; + [window setFrame:rect display:YES]; // only start tracking events if pointer is above the toplevel @@ -734,13 +690,16 @@ if (maxW < 1) maxW = 1; if (maxH < 1) maxH = 1; - NSSize min = { minW, minH }; - NSSize max = { maxW, maxH }; - AWTWindow *window = OBJC(windowPtr); [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){ AWT_ASSERT_APPKIT_THREAD; + NSSize min = { minW, minH }; + NSSize max = { maxW, maxH }; + + [window constrainSize:&min]; + [window constrainSize:&max]; + window.javaMinSize = min; window.javaMaxSize = max; [window updateMinMaxSize:IS(window.styleBits, RESIZABLE)]; @@ -830,7 +789,6 @@ AWT_ASSERT_APPKIT_THREAD; [window setAlphaValue:alpha]; - [window.growBoxWindow setAlphaValue:alpha]; }]; JNF_COCOA_EXIT(env); diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/native/sun/awt/CDropTarget.m --- a/jdk/src/macosx/native/sun/awt/CDropTarget.m Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/native/sun/awt/CDropTarget.m Wed Apr 18 10:18:10 2012 -0700 @@ -648,6 +648,10 @@ if (sDraggingError == FALSE) { sDraggingLocation = [sender draggingLocation]; NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil]; + // The y coordinate that comes in the NSDraggingInfo seems to be reversed - probably + // has to do something with the type of view it comes to. + // This is the earliest place where we can correct it. + javaLocation.y = fView.window.frame.size.height - javaLocation.y; jint actions = [DnDUtilities mapNSDragOperationMaskToJava:[sender draggingSourceOperationMask]]; jint dropAction = sJavaDropOperation; diff -r 2b900319e3ae -r b81249542f14 jdk/src/macosx/native/sun/awt/CImage.m --- a/jdk/src/macosx/native/sun/awt/CImage.m Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/macosx/native/sun/awt/CImage.m Wed Apr 18 10:18:10 2012 -0700 @@ -70,19 +70,8 @@ [oldContext release]; } -/* - * Class: sun_lwawt_macosx_CImage - * Method: nativeCreateNSImageFromArray - * Signature: ([III)J - */ -JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromArray -(JNIEnv *env, jclass klass, jintArray buffer, jint width, jint height) +static NSBitmapImageRep* CImage_CreateImageRep(JNIEnv *env, jintArray buffer, jint width, jint height) { - jlong result = 0L; - -JNF_COCOA_ENTER(env); -AWT_ASSERT_ANY_THREAD; - NSBitmapImageRep* imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:width pixelsHigh:height @@ -105,15 +94,83 @@ (*env)->ReleasePrimitiveArrayCritical(env, buffer, src, JNI_ABORT); - NSImage *nsImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)]; - [nsImage addRepresentation:imageRep]; - [imageRep release]; + return imageRep; +} + +/* + * Class: sun_lwawt_macosx_CImage + * Method: nativeCreateNSImageFromArray + * Signature: ([III)J + */ +JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromArray +(JNIEnv *env, jclass klass, jintArray buffer, jint width, jint height) +{ + jlong result = 0L; - if (nsImage != nil) { - CFRetain(nsImage); // GC +JNF_COCOA_ENTER(env); +AWT_ASSERT_ANY_THREAD; + + NSBitmapImageRep* imageRep = CImage_CreateImageRep(env, buffer, width, height); + if (imageRep) { + NSImage *nsImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)]; + [nsImage addRepresentation:imageRep]; + [imageRep release]; + + if (nsImage != nil) { + CFRetain(nsImage); // GC + } + + result = ptr_to_jlong(nsImage); } - result = ptr_to_jlong(nsImage); +JNF_COCOA_EXIT(env); + + return result; +} + +/* + * Class: sun_lwawt_macosx_CImage + * Method: nativeCreateNSImageFromArrays + * Signature: ([[I[I[I)J + */ +JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromArrays +(JNIEnv *env, jclass klass, jobjectArray buffers, jintArray widths, jintArray heights) +{ + jlong result = 0L; + +JNF_COCOA_ENTER(env); +AWT_ASSERT_ANY_THREAD; + + jsize num = (*env)->GetArrayLength(env, buffers); + NSMutableArray * reps = [NSMutableArray arrayWithCapacity: num]; + + jint * ws = (*env)->GetIntArrayElements(env, widths, NULL); + jint * hs = (*env)->GetIntArrayElements(env, heights, NULL); + + jsize i; + for (i = 0; i < num; i++) { + jintArray buffer = (*env)->GetObjectArrayElement(env, buffers, i); + + NSBitmapImageRep* imageRep = CImage_CreateImageRep(env, buffer, ws[i], hs[i]); + if (imageRep) { + [reps addObject: imageRep]; + } + } + + (*env)->ReleaseIntArrayElements(env, heights, hs, JNI_ABORT); + (*env)->ReleaseIntArrayElements(env, widths, ws, JNI_ABORT); + + if ([reps count]) { + NSImage *nsImage = [[NSImage alloc] initWithSize:NSMakeSize(0, 0)]; + [nsImage addRepresentations: reps]; + [reps release]; + + if (nsImage != nil) { + CFRetain(nsImage); // GC + } + + result = ptr_to_jlong(nsImage); + } JNF_COCOA_EXIT(env); diff -r 2b900319e3ae -r b81249542f14 jdk/src/share/classes/javax/swing/BorderFactory.java --- a/jdk/src/share/classes/javax/swing/BorderFactory.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/share/classes/javax/swing/BorderFactory.java Wed Apr 18 10:18:10 2012 -0700 @@ -371,7 +371,7 @@ /** * Creates a new titled border with the specified title, * the default border type (determined by the current look and feel), - * the default text position (sitting on the top line), + * the default text position (determined by the current look and feel), * the default justification (leading), and the default * font and text color (determined by the current look and feel). * @@ -385,7 +385,7 @@ /** * Creates a new titled border with an empty title, * the specified border object, - * the default text position (sitting on the top line), + * the default text position (determined by the current look and feel), * the default justification (leading), and the default * font and text color (determined by the current look and feel). * @@ -400,7 +400,7 @@ /** * Adds a title to an existing border, - * with default positioning (sitting on the top line), + * with default positioning (determined by the current look and feel), * default justification (leading) and the default * font and text color (determined by the current look and feel). * @@ -439,7 +439,8 @@ *
  • TitledBorder.ABOVE_BOTTOM *
  • TitledBorder.BOTTOM (sitting on the bottom line) *
  • TitledBorder.BELOW_BOTTOM - *
  • TitledBorder.DEFAULT_POSITION (top) + *
  • TitledBorder.DEFAULT_POSITION (the title position + * is determined by the current look and feel) * * @return the TitledBorder object */ @@ -477,7 +478,8 @@ *
  • TitledBorder.ABOVE_BOTTOM *
  • TitledBorder.BOTTOM (sitting on the bottom line) *
  • TitledBorder.BELOW_BOTTOM - *
  • TitledBorder.DEFAULT_POSITION (top) + *
  • TitledBorder.DEFAULT_POSITION (the title position + * is determined by the current look and feel) * * @param titleFont a Font object specifying the title font * @return the TitledBorder object @@ -516,7 +518,8 @@ *
  • TitledBorder.ABOVE_BOTTOM *
  • TitledBorder.BOTTOM (sitting on the bottom line) *
  • TitledBorder.BELOW_BOTTOM - *
  • TitledBorder.DEFAULT_POSITION (top) + *
  • TitledBorder.DEFAULT_POSITION (the title position + * is determined by the current look and feel) * * @param titleFont a Font object specifying the title font * @param titleColor a Color object specifying the title color diff -r 2b900319e3ae -r b81249542f14 jdk/src/share/classes/javax/swing/plaf/synth/SynthComboPopup.java --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthComboPopup.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthComboPopup.java Wed Apr 18 10:18:10 2012 -0700 @@ -26,13 +26,9 @@ package javax.swing.plaf.synth; import javax.swing.*; -import javax.swing.event.*; -import javax.swing.plaf.basic.*; +import javax.swing.plaf.ComboBoxUI; +import javax.swing.plaf.basic.BasicComboPopup; import java.awt.*; -import java.awt.event.*; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeEvent; -import java.io.Serializable; /** @@ -52,6 +48,7 @@ * * @see #createList */ + @Override protected void configureList() { list.setFont( comboBox.getFont() ); list.setCellRenderer( comboBox.getRenderer() ); @@ -67,4 +64,27 @@ } installListListeners(); } + + /** + * @inheritDoc + * + * Overridden to take into account any popup insets specified in + * SynthComboBoxUI + */ + @Override + protected Rectangle computePopupBounds(int px, int py, int pw, int ph) { + ComboBoxUI ui = comboBox.getUI(); + if (ui instanceof SynthComboBoxUI) { + SynthComboBoxUI sui = (SynthComboBoxUI) ui; + if (sui.popupInsets != null) { + Insets i = sui.popupInsets; + return super.computePopupBounds( + px + i.left, + py + i.top, + pw - i.left - i.right, + ph - i.top - i.bottom); + } + } + return super.computePopupBounds(px, py, pw, ph); + } } diff -r 2b900319e3ae -r b81249542f14 jdk/src/share/classes/javax/swing/text/AbstractDocument.java --- a/jdk/src/share/classes/javax/swing/text/AbstractDocument.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/share/classes/javax/swing/text/AbstractDocument.java Wed Apr 18 10:18:10 2012 -0700 @@ -31,7 +31,6 @@ import javax.swing.UIManager; import javax.swing.undo.*; -import javax.swing.event.ChangeListener; import javax.swing.event.*; import javax.swing.tree.TreeNode; @@ -698,28 +697,31 @@ return; } DocumentFilter filter = getDocumentFilter(); + InsertStringResult insertStringResult = null; writeLock(); + try { if (filter != null) { filter.insertString(getFilterBypass(), offs, str, a); - } - else { - handleInsertString(offs, str, a); + } else { + insertStringResult = handleInsertString(offs, str, a); } } finally { writeUnlock(); } + + processInsertStringResult(insertStringResult); } /** * Performs the actual work of inserting the text; it is assumed the * caller has obtained a write lock before invoking this. */ - void handleInsertString(int offs, String str, AttributeSet a) - throws BadLocationException { + private InsertStringResult handleInsertString(int offs, String str, AttributeSet a) + throws BadLocationException { if ((str == null) || (str.length() == 0)) { - return; + return null; } UndoableEdit u = data.insertString(offs, str); DefaultDocumentEvent e = @@ -746,12 +748,29 @@ insertUpdate(e, a); // Mark the edit as done. e.end(); - fireInsertUpdate(e); + + InsertStringResult result = new InsertStringResult(); + + result.documentEvent = e; + // only fire undo if Content implementation supports it // undo for the composed text is not supported for now - if (u != null && - (a == null || !a.isDefined(StyleConstants.ComposedTextAttribute))) { - fireUndoableEditUpdate(new UndoableEditEvent(this, e)); + if (u != null && (a == null || !a.isDefined(StyleConstants.ComposedTextAttribute))) { + result.undoableEditEvent = new UndoableEditEvent(this, e); + } + + return result; + } + + private void processInsertStringResult(InsertStringResult insertStringResult) { + if (insertStringResult == null) { + return; + } + + fireInsertUpdate(insertStringResult.documentEvent); + + if (insertStringResult.undoableEditEvent != null) { + fireUndoableEditUpdate(insertStringResult.undoableEditEvent); } } @@ -2947,12 +2966,10 @@ */ class UndoRedoDocumentEvent implements DocumentEvent { private DefaultDocumentEvent src = null; - private boolean isUndo; private EventType type = null; public UndoRedoDocumentEvent(DefaultDocumentEvent src, boolean isUndo) { this.src = src; - this.isUndo = isUndo; if(isUndo) { if(src.getType().equals(EventType.INSERT)) { type = EventType.REMOVE; @@ -3106,13 +3123,23 @@ public void insertString(int offset, String string, AttributeSet attr) throws BadLocationException { - handleInsertString(offset, string, attr); + InsertStringResult insertStringResult = handleInsertString(offset, string, attr); + + processInsertStringResult(insertStringResult); } public void replace(int offset, int length, String text, AttributeSet attrs) throws BadLocationException { handleRemove(offset, length); - handleInsertString(offset, text, attrs); + + InsertStringResult insertStringResult = handleInsertString(offset, text, attrs); + + processInsertStringResult(insertStringResult); } } + + private static class InsertStringResult { + DefaultDocumentEvent documentEvent; + UndoableEditEvent undoableEditEvent; + } } diff -r 2b900319e3ae -r b81249542f14 jdk/src/share/classes/javax/swing/text/DefaultEditorKit.java --- a/jdk/src/share/classes/javax/swing/text/DefaultEditorKit.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/share/classes/javax/swing/text/DefaultEditorKit.java Wed Apr 18 10:18:10 2012 -0700 @@ -24,6 +24,8 @@ */ package javax.swing.text; +import sun.awt.SunToolkit; + import java.io.*; import java.awt.*; import java.awt.event.ActionEvent; @@ -869,11 +871,18 @@ } String content = e.getActionCommand(); int mod = e.getModifiers(); - if ((content != null) && (content.length() > 0) && - ((mod & ActionEvent.ALT_MASK) == (mod & ActionEvent.CTRL_MASK))) { - char c = content.charAt(0); - if ((c >= 0x20) && (c != 0x7F)) { - target.replaceSelection(content); + if ((content != null) && (content.length() > 0)) { + boolean isPrintableMask = true; + Toolkit tk = Toolkit.getDefaultToolkit(); + if (tk instanceof SunToolkit) { + isPrintableMask = ((SunToolkit)tk).isPrintableCharacterModifiersMask(mod); + } + + if (isPrintableMask) { + char c = content.charAt(0); + if ((c >= 0x20) && (c != 0x7F)) { + target.replaceSelection(content); + } } } } diff -r 2b900319e3ae -r b81249542f14 jdk/src/share/classes/sun/awt/AppContext.java --- a/jdk/src/share/classes/sun/awt/AppContext.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/share/classes/sun/awt/AppContext.java Wed Apr 18 10:18:10 2012 -0700 @@ -46,6 +46,7 @@ import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.atomic.AtomicInteger; /** * The AppContext is a table referenced by ThreadGroup which stores @@ -194,6 +195,15 @@ return isDisposed; } + /* + * The total number of AppContexts, system-wide. This number is + * incremented at the beginning of the constructor, and decremented + * at the end of dispose(). getAppContext() checks to see if this + * number is 1. If so, it returns the sole AppContext without + * checking Thread.currentThread(). + */ + private static final AtomicInteger numAppContexts = new AtomicInteger(0); + static { // On the main Thread, we get the ThreadGroup, make a corresponding // AppContext, and instantiate the Java EventQueue. This way, legacy @@ -209,22 +219,12 @@ parentThreadGroup = currentThreadGroup.getParent(); } mainAppContext = new AppContext(currentThreadGroup); - numAppContexts = 1; return null; } }); } /* - * The total number of AppContexts, system-wide. This number is - * incremented at the beginning of the constructor, and decremented - * at the end of dispose(). getAppContext() checks to see if this - * number is 1. If so, it returns the sole AppContext without - * checking Thread.currentThread(). - */ - private static volatile int numAppContexts; - - /* * The context ClassLoader that was used to create this AppContext. */ private final ClassLoader contextClassLoader; @@ -243,7 +243,7 @@ * @since 1.2 */ AppContext(ThreadGroup threadGroup) { - numAppContexts++; + numAppContexts.incrementAndGet(); this.threadGroup = threadGroup; threadGroup2appContext.put(threadGroup, this); @@ -278,7 +278,7 @@ * @since 1.2 */ public final static AppContext getAppContext() { - if (numAppContexts == 1) // If there's only one system-wide, + if (numAppContexts.get() == 1) // If there's only one system-wide, return mainAppContext; // return the main system AppContext. AppContext appContext = threadAppContext.get(); @@ -513,7 +513,7 @@ this.table.clear(); // Clear out the Hashtable to ease garbage collection } - numAppContexts--; + numAppContexts.decrementAndGet(); mostRecentKeyValue = null; } @@ -804,7 +804,7 @@ return getAppContext().isDisposed(); } public boolean isMainAppContext() { - return (numAppContexts == 1); + return (numAppContexts.get() == 1); } }); } diff -r 2b900319e3ae -r b81249542f14 jdk/src/share/classes/sun/awt/SunToolkit.java --- a/jdk/src/share/classes/sun/awt/SunToolkit.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/share/classes/sun/awt/SunToolkit.java Wed Apr 18 10:18:10 2012 -0700 @@ -1126,6 +1126,16 @@ } /** + * Tests whether specified key modifiers mask can be used to enter a printable + * character. This is a default implementation of this method, which reflects + * the way things work on Windows: here, pressing ctrl + alt allows user to enter + * characters from the extended character set (like euro sign or math symbols) + */ + public boolean isPrintableCharacterModifiersMask(int mods) { + return ((mods & InputEvent.ALT_MASK) == (mods & InputEvent.CTRL_MASK)); + } + + /** * Returns a new input method window, with behavior as specified in * {@link java.awt.im.spi.InputMethodContext#createInputMethodWindow}. * If the inputContext is not null, the window should return it from its diff -r 2b900319e3ae -r b81249542f14 jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java --- a/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java Wed Apr 18 10:18:10 2012 -0700 @@ -82,7 +82,7 @@ boolean paintPending = false; boolean isLayouting = false; - boolean enabled; + private boolean enabled; // Actually used only by XDecoratedPeer protected int boundsOperation; @@ -128,9 +128,6 @@ } void postInit(XCreateWindowParams params) { super.postInit(params); - Color c; - Font f; - Cursor cursor; pSetCursor(target.getCursor()); @@ -143,19 +140,7 @@ reshape(r.x, r.y, r.width, r.height); } - enabled = target.isEnabled(); - - // If any of our heavyweight ancestors are disable, we should be too - // See 6176875 for more information - Component comp = target; - while( !(comp == null || comp instanceof Window) ) { - comp = comp.getParent(); - if( comp != null && !comp.isEnabled() && !comp.isLightweight() ){ - setEnabled(false); - break; - } - } - enableLog.fine("Initial enable state: {0}", Boolean.valueOf(enabled)); + setEnabled(target.isEnabled()); if (target.isVisible()) { setVisible(true); @@ -384,45 +369,48 @@ setVisible(false); } - /** * @see java.awt.peer.ComponentPeer */ - public void setEnabled(boolean value) { - enableLog.fine("{0}ing {1}", (value?"Enabl":"Disabl"), this); - boolean repaintNeeded = (enabled != value); - enabled = value; + public void setEnabled(final boolean value) { + if (enableLog.isLoggable(PlatformLogger.FINE)) { + enableLog.fine("{0}ing {1}", (value ? "Enabl" : "Disabl"), this); + } + boolean status = value; + // If any of our heavyweight ancestors are disable, we should be too + // See 6176875 for more information + final Container cp = SunToolkit.getNativeContainer(target); + if (cp != null) { + status &= ((XComponentPeer) cp.getPeer()).isEnabled(); + } + synchronized (getStateLock()) { + if (enabled == status) { + return; + } + enabled = status; + } + if (target instanceof Container) { - Component list[] = ((Container)target).getComponents(); - for (int i = 0; i < list.length; ++i) { - boolean childEnabled = list[i].isEnabled(); - ComponentPeer p = list[i].getPeer(); - if ( p != null ) { - p.setEnabled(value && childEnabled); + final Component[] list = ((Container) target).getComponents(); + for (final Component child : list) { + final ComponentPeer p = child.getPeer(); + if (p != null) { + p.setEnabled(status && child.isEnabled()); } } } - if (repaintNeeded) { - repaint(); - } + repaint(); } // // public so aw/Window can call it // - public boolean isEnabled() { - return enabled; + public final boolean isEnabled() { + synchronized (getStateLock()) { + return enabled; + } } - - - public void enable() { - setEnabled(true); - } - - public void disable() { - setEnabled(false); - } @Override public void paint(final Graphics g) { super.paint(g); diff -r 2b900319e3ae -r b81249542f14 jdk/test/java/awt/Component/7097771/bug7097771.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/Component/7097771/bug7097771.java Wed Apr 18 10:18:10 2012 -0700 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import sun.awt.SunToolkit; +import test.java.awt.regtesthelpers.Util; + +import java.awt.AWTException; +import java.awt.Button; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/* + @test + @bug 7097771 + @summary setEnabled does not work for components in disabled containers. + @author sergey.bylokhov@oracle.com: area=awt.component + @library ../../regtesthelpers + @build Util + @run main bug7097771 +*/ +public final class bug7097771 extends Frame implements ActionListener { + + private static volatile boolean action; + + public static void main(final String[] args) throws AWTException { + final bug7097771 frame = new bug7097771(); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + final Button button = new Button(); + button.addActionListener(frame); + frame.add(button); + frame.setVisible(true); + sleep(); + frame.setEnabled(false); + button.setEnabled(false); + button.setEnabled(true); + sleep(); + Util.clickOnComp(button, new Robot()); + sleep(); + frame.dispose(); + if (action) { + throw new RuntimeException("Button is not disabled."); + } + } + + @Override + public void actionPerformed(final ActionEvent e) { + action = true; + } + + private static void sleep() { + ((SunToolkit) Toolkit.getDefaultToolkit()).realSync(); + try { + Thread.sleep(1000); + } catch (InterruptedException ignored) { + } + } +} diff -r 2b900319e3ae -r b81249542f14 jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/TestWrapped.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/TestWrapped.java Wed Apr 18 10:18:10 2012 -0700 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * test + * @bug 6282388 + * @summary Tests that AWT use correct toolkit to be wrapped into HeadlessToolkit + * @author artem.ananiev@sun.com: area=awt.headless + * @run shell WrappedToolkitTest.sh + */ + +import java.awt.*; + +import java.lang.reflect.*; + +import sun.awt.*; + +public class TestWrapped +{ + public static void main(String[] args) + { + try + { + if (args.length != 1) { + System.err.println("No correct toolkit class name is specified, test is not run"); + System.exit(0); + } + + String correctToolkitClassName = args[0]; + Toolkit tk = Toolkit.getDefaultToolkit(); + Class tkClass = tk.getClass(); + if (!tkClass.getName().equals("sun.awt.HeadlessToolkit")) + { + System.err.println(tkClass.getName()); + System.err.println("Error: default toolkit is not an instance of HeadlessToolkit"); + System.exit(-1); + } + + Field f = tkClass.getDeclaredField("tk"); + f.setAccessible(true); + Class wrappedClass = f.get(tk).getClass(); + if (!wrappedClass.getName().equals(correctToolkitClassName)) { + System.err.println(wrappedClass.getName()); + System.err.println("Error: wrapped toolkit is not an instance of " + correctToolkitClassName); + System.exit(-1); + } + } + catch (Exception z) + { + z.printStackTrace(System.err); + System.exit(-1); + } + + System.exit(0); + } +} diff -r 2b900319e3ae -r b81249542f14 jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh Wed Apr 18 10:18:10 2012 -0700 @@ -0,0 +1,179 @@ +#!/bin/ksh -p + +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# +# @test +# @bug 6282388 +# @summary Tests that AWT use correct toolkit to be wrapped into HeadlessToolkit +# @author artem.ananiev@sun.com: area=awt.headless +# @compile TestWrapped.java +# @run shell WrappedToolkitTest.sh + +# Beginning of subroutines: +status=1 + +#Call this from anywhere to fail the test with an error message +# usage: fail "reason why the test failed" +fail() + { echo "The test failed :-(" + echo "$*" 1>&2 + echo "exit status was $status" + exit $status + } #end of fail() + +#Call this from anywhere to pass the test with a message +# usage: pass "reason why the test passed if applicable" +pass() + { echo "The test passed!!!" + echo "$*" 1>&2 + exit 0 + } #end of pass() + +# end of subroutines + + +# The beginning of the script proper + +# Checking for proper OS +OS=`uname -s` +case "$OS" in + SunOS ) + VAR="One value for Sun" + DEFAULT_JDK=/usr/local/java/jdk1.2/solaris + FILESEP="/" + ;; + + Linux ) + VAR="A different value for Linux" + DEFAULT_JDK=/usr/local/java/jdk1.4/linux-i386 + FILESEP="/" + ;; + + Windows* | CYGWIN* ) + VAR="A different value for Win32" + DEFAULT_JDK=/usr/local/java/jdk1.2/win32 + FILESEP="\\" + ;; + + # catch all other OSs + * ) + echo "Unrecognized system! $OS" + fail "Unrecognized system! $OS" + ;; +esac + +# check that some executable or other file you need is available, abort if not +# note that the name of the executable is in the fail string as well. +# this is how to check for presence of the compiler, etc. +#RESOURCE=`whence SomeProgramOrFileNeeded` +#if [ "${RESOURCE}" = "" ] ; +# then fail "Need SomeProgramOrFileNeeded to perform the test" ; +#fi + +# Want this test to run standalone as well as in the harness, so do the +# following to copy the test's directory into the harness's scratch directory +# and set all appropriate variables: + +if [ -z "${TESTJAVA}" ] ; then + # TESTJAVA is not set, so the test is running stand-alone. + # TESTJAVA holds the path to the root directory of the build of the JDK + # to be tested. That is, any java files run explicitly in this shell + # should use TESTJAVA in the path to the java interpreter. + # So, we'll set this to the JDK spec'd on the command line. If none + # is given on the command line, tell the user that and use a cheesy + # default. + # THIS IS THE JDK BEING TESTED. + if [ -n "$1" ] ; + then TESTJAVA=$1 + else echo "no JDK specified on command line so using default!" + TESTJAVA=$DEFAULT_JDK + fi + TESTSRC=. + TESTCLASSES=. + STANDALONE=1; +fi +echo "JDK under test is: $TESTJAVA" + +#Deal with .class files: +if [ -n "${STANDALONE}" ] ; then + # then compile all .java files (if there are any) into .class files + if [ -a *.java ]; then + ${TESTJAVA}/bin/javac$ ./*.java ; + fi + # else in harness so copy all the class files from where jtreg put them + # over to the scratch directory this test is running in. + else cp ${TESTCLASSES}/*.class . ; +fi + +#if in test harness, then copy the entire directory that the test is in over +# to the scratch directory. This catches any support files needed by the test. +if [ -z "${STANDALONE}" ] ; + then cp ${TESTSRC}/* . +fi + +#Just before executing anything, make sure it has executable permission! +chmod 777 ./* + +############### YOUR TEST CODE HERE!!!!!!! ############# + +case "$OS" in + Windows* | CYGWIN* ) + ${TESTJAVA}/bin/java -Djava.awt.headless=true \ + TestWrapped sun.awt.windows.WToolkit + status=$? + if [ ! $status -eq "0" ]; then + fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.windows.WToolkit"; + fi + ${TESTJAVA}/bin/java -Djava.awt.headless=true \ + -Dawt.toolkit=sun.awt.windows.WToolkit \ + TestWrapped sun.awt.windows.WToolkit + status=$? + if [ ! $status -eq "0" ]; then + fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.windows.WToolkit"; + fi + ;; + + SunOS | Linux ) + ${TESTJAVA}/bin/java -Djava.awt.headless=true \ + -Dawt.toolkit=sun.awt.X11.XToolkit \ + TestWrapped sun.awt.X11.XToolkit + status=$? + if [ ! $status -eq "0" ]; then + fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.xawt.XToolkit"; + fi + AWT_TOOLKIT=XToolkit ${TESTJAVA}/bin/java -Djava.awt.headless=true \ + TestWrapped sun.awt.X11.XToolkit + status=$? + if [ ! $status -eq "0" ]; then + fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.xawt.XToolkit"; + fi + ;; + +esac + +pass "All the tests are PASSED"; + +#For additional examples of how to write platform independent KSH scripts, +# see the jtreg file itself. It is a KSH script for both Solaris and Win32 diff -r 2b900319e3ae -r b81249542f14 jdk/test/javax/sound/sampled/DirectAudio/bug6400879.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/DirectAudio/bug6400879.java Wed Apr 18 10:18:10 2012 -0700 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 6400879 + @bug 7100140 + @summary Tests that Start/Stop sequence doesn't hang + @author Alexey Menkov + @run main bug6400879 + */ + +import javax.sound.sampled.*; + +public class bug6400879 extends Thread { + + public static void main(String args[]) throws Exception { + bug6400879 pThis = new bug6400879(); + //pThis.init(); + pThis.setDaemon(true); + pThis.start(); + monitor(pThis); + } + + static final long BLOCK_TIMEOUT = 5000; // 5 sec + + // monitors that pThis doesn't hang + public static void monitor(bug6400879 pThis) throws Exception { + long prevLoop = -1; + long prevTime = currentTimeMillis(); + while (pThis.isAlive()) { + if (pThis.loopCounter == prevLoop) { + if (currentTimeMillis() - prevTime > BLOCK_TIMEOUT) { + // block! + log("Test FAILED."); + throw new RuntimeException("Test FAILED: thread has been blocked!"); + } + } else { + prevLoop = pThis.loopCounter; + prevTime = currentTimeMillis(); + } + delay(500); // sleep for 0.5 sec + } + log("Test sucessfully passed."); + } + + volatile long loopCounter = 0; + final long LOOPS_PER_LINE = 100; + + public void run() { + SourceDataLine line = null; + + DataLine.Info line_info = new DataLine.Info(SourceDataLine.class, null); + Line.Info infos[] = AudioSystem.getSourceLineInfo(line_info); + + log("total " + infos.length + " lines"); + + for (int lineNum = 0; lineNum < infos.length; lineNum++) { + try { + line = (SourceDataLine)AudioSystem.getLine(infos[lineNum]); + log("testing line: " + line); + line.open(line.getFormat()); + for (int i=0; istop (" + i + ")"); + line.start(); + line.stop(); + log(" - OK"); + loopCounter++; + } + line.close(); + line = null; + } catch (LineUnavailableException e1) { + log("LineUnavailableException caught, test okay."); + log(e1.getMessage()); + } catch (SecurityException e2) { + log("SecurityException caught, test okay."); + log(e2.getMessage()); + } catch (IllegalArgumentException e3) { + log("IllegalArgumentException caught, test okay."); + log(e3.getMessage()); + } + if (line != null) { + line.close(); + line = null; + } + } + + } + + + // helper routines + static long startTime = currentTimeMillis(); + static long currentTimeMillis() { + //return System.nanoTime() / 1000000L; + return System.currentTimeMillis(); + } + static void log(String s) { + long time = currentTimeMillis() - startTime; + long ms = time % 1000; + time /= 1000; + long sec = time % 60; + time /= 60; + long min = time % 60; + time /= 60; + System.out.println("" + + (time < 10 ? "0" : "") + time + + ":" + (min < 10 ? "0" : "") + min + + ":" + (sec < 10 ? "0" : "") + sec + + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms + + " (" + Thread.currentThread().getName() + ") " + s); + } + static void delay(int millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) {} + } +} diff -r 2b900319e3ae -r b81249542f14 jdk/test/javax/sound/sampled/FileWriter/AlawEncoderSync.java --- a/jdk/test/javax/sound/sampled/FileWriter/AlawEncoderSync.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/test/javax/sound/sampled/FileWriter/AlawEncoderSync.java Wed Apr 18 10:18:10 2012 -0700 @@ -1,6 +1,32 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + /** * @test * @bug 6938426 + * @bug 7058852 * @summary Tests that Alaw encoder works properly in multithreaded environment * @author Alex Menkov */ @@ -34,7 +60,7 @@ threads[i].start(); } - for (int i=1; i borders = new ArrayList<>(); + + borders.add(BorderFactory.createTitledBorder(new EmptyBorder(0, 0, 0, 0), "Title")); + + try { + Method getPositionMethod = TitledBorder.class.getDeclaredMethod("getPosition"); + + getPositionMethod.setAccessible(true); + + for (TitledBorder border : borders) { + int position = (Integer) getPositionMethod.invoke(border); + + if (position != expectedPosition) { + throw new RuntimeException("Invalid title position"); + } + } + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + }); + + System.out.println("Test passed for LookAndFeel " + lookAndFeel.getName()); + } + } + } + } +} diff -r 2b900319e3ae -r b81249542f14 jdk/test/javax/swing/plaf/synth/7158712/bug7158712.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/plaf/synth/7158712/bug7158712.java Wed Apr 18 10:18:10 2012 -0700 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 7158712 + @summary Synth Property "ComboBox.popupInsets" is ignored + @library ../../../regtesthelpers + @author Pavel Porvatov +*/ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import javax.swing.plaf.basic.BasicComboPopup; +import javax.swing.plaf.synth.SynthLookAndFeel; +import java.awt.*; +import java.awt.event.InputEvent; +import java.io.ByteArrayInputStream; +import java.util.concurrent.Callable; + +public class bug7158712 { + private static final String SYNTH_XML = "" + + " " + + " " + + " " + + " " + + " " + + " " + + ""; + + private static JComboBox comboBox; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + + robot.setAutoDelay(500); + + SynthLookAndFeel laf = new SynthLookAndFeel(); + + laf.load(new ByteArrayInputStream(SYNTH_XML.getBytes("UTF8")), bug7158712.class); + + UIManager.setLookAndFeel(laf); + + EventQueue.invokeAndWait(new Runnable() { + public void run() { + comboBox = new JComboBox<>( + new String[]{"Very Looooooooooooooooooooong Text Item 1", "Item 2"}); + + JFrame frame = new JFrame(); + + frame.add(comboBox, BorderLayout.NORTH); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setSize(new Dimension(400, 300)); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + }); + + ((SunToolkit) Toolkit.getDefaultToolkit()).realSync(); + + Point comboBoxLocation = Util.invokeOnEDT(new Callable() { + @Override + public Point call() throws Exception { + return comboBox.getLocationOnScreen(); + } + }); + + robot.mouseMove(comboBoxLocation.x, comboBoxLocation.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + BasicComboPopup popup = (BasicComboPopup) comboBox.getAccessibleContext().getAccessibleChild(0); + + Point popupPoint = popup.getLocationOnScreen(); + Point comboBoxPoint = comboBox.getLocationOnScreen(); + + if (comboBoxPoint.x - 5 != popupPoint.x || + comboBoxPoint.y + comboBox.getHeight() - 5 != popupPoint.y) { + throw new RuntimeException("Invalid popup coordinates. Popup location: " + popupPoint + + ", comboBox location: " + comboBoxPoint); + } + + System.out.println("Test bug7158712 passed"); + } + }); + } +} diff -r 2b900319e3ae -r b81249542f14 jdk/test/javax/swing/regtesthelpers/Util.java --- a/jdk/test/javax/swing/regtesthelpers/Util.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/test/javax/swing/regtesthelpers/Util.java Wed Apr 18 10:18:10 2012 -0700 @@ -24,8 +24,10 @@ import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.Callable; /** *

    This class contains utilities useful for regression testing. @@ -153,4 +155,31 @@ robot.keyRelease(keys[i]); } } + + /** + * Invokes the task on the EDT thread. + * + * @return result of the task + */ + public static T invokeOnEDT(final Callable task) throws Exception { + final List result = new ArrayList<>(1); + final Exception[] exception = new Exception[1]; + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + result.add(task.call()); + } catch (Exception e) { + exception[0] = e; + } + } + }); + + if (exception[0] != null) { + throw exception[0]; + } + + return result.get(0); + } } diff -r 2b900319e3ae -r b81249542f14 jdk/test/javax/swing/text/AbstractDocument/7146146/bug7146146.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/text/AbstractDocument/7146146/bug7146146.java Wed Apr 18 10:18:10 2012 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 7146146 + @summary Deadlock between subclass of AbstractDocument and UndoManager + @author Pavel Porvatov +*/ + +import javax.swing.text.BadLocationException; +import javax.swing.text.PlainDocument; +import javax.swing.text.StringContent; +import javax.swing.undo.UndoManager; + +public class bug7146146 { + public static void main(String[] args) throws Exception { + for (int i = 0; i < 1000; i++) { + System.out.print("Iteration " + i); + + test(); + + System.out.print(" passed"); + } + } + + private static void test() throws Exception { + final PlainDocument doc = new PlainDocument(new StringContent()); + final UndoManager undoManager = new UndoManager(); + + doc.addUndoableEditListener(undoManager); + doc.insertString(0, "", null); + + Thread t1 = new Thread("Thread 1") { + @Override + public void run() { + try { + doc.insertString(0, "", null); + } catch (BadLocationException e) { + throw new RuntimeException(e); + } + } + }; + + Thread t2 = new Thread("Thread 2") { + @Override + public void run() { + undoManager.undo(); + } + }; + + t1.start(); + t2.start(); + + t1.join(); + t2.join(); + } +} diff -r 2b900319e3ae -r b81249542f14 jdk/test/sun/java2d/X11SurfaceData/SharedMemoryPixmapsTest/SharedMemoryPixmapsTest.java --- a/jdk/test/sun/java2d/X11SurfaceData/SharedMemoryPixmapsTest/SharedMemoryPixmapsTest.java Wed Apr 18 10:16:23 2012 -0700 +++ b/jdk/test/sun/java2d/X11SurfaceData/SharedMemoryPixmapsTest/SharedMemoryPixmapsTest.java Wed Apr 18 10:18:10 2012 -0700 @@ -54,8 +54,12 @@ public SharedMemoryPixmapsTest() { testFrame = new Frame("SharedMemoryPixmapsTest"); testFrame.add(new TestComponent()); + testFrame.setUndecorated(true); + testFrame.setResizable(false); testFrame.pack(); + testFrame.setLocationRelativeTo(null); testFrame.setVisible(true); + testFrame.toFront(); } public static void main(String[] args) {