提交 433c74a6 编写于 作者: L lana

Merge

......@@ -213,16 +213,8 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
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 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
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 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
// 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.");
// Create a new drop target:
fDropTarget = CDropTarget.createDropTarget(dt, target, this);
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);
}
}
}
}
......@@ -999,17 +1009,24 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
// 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.");
}
}
}
}
......
......@@ -36,32 +36,34 @@ import sun.awt.SunToolkit;
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 @@ public abstract class LWCursorManager {
}
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);
}
......@@ -39,12 +39,8 @@ final class LWRepaintArea extends RepaintArea {
@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());
}
}
......
......@@ -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;
......@@ -71,6 +72,15 @@ final class LWTextAreaPeer
return getDelegate().getView();
}
@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();
......
......@@ -31,6 +31,7 @@ import java.awt.Point;
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 @@ final class LWTextFieldPeer
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
......
......@@ -784,9 +784,8 @@ public class LWWindowPeer
}
mouseClickButtons &= ~eventButtonMask;
}
notifyUpdateCursor();
}
notifyUpdateCursor();
}
public void dispatchMouseWheelEvent(long when, int x, int y, int modifiers,
......@@ -1057,6 +1056,10 @@ public class LWWindowPeer
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);
......
......@@ -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 @@ public class CCursorManager extends LWCursorManager {
}
@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 @@ public class CCursorManager extends LWCursorManager {
}
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 @@ public class CCursorManager extends LWCursorManager {
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 @@ public class CCursorManager extends LWCursorManager {
if (isDragging) {
throw new RuntimeException("Invalid Drag state in CCursorManager!");
}
isDragging = true;
dragPos = new Point(x, y);
}
......
......@@ -88,13 +88,20 @@ public class CEmbeddedFrame extends EmbeddedFrame {
responder.handleScrollEvent(x, y, modifierFlags, deltaX, deltaY);
}
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) {
......
......@@ -29,10 +29,14 @@ import java.awt.*;
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 @@ public class CImage extends CFRetainedResource {
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 @@ public class CImage extends CFRetainedResource {
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<Image> 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) {
......
......@@ -117,7 +117,7 @@ final class CPlatformResponder {
* 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 @@ final class CPlatformResponder {
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 @@ final class CPlatformResponder {
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++;
}
}
}
}
......@@ -199,7 +199,7 @@ public class CPlatformView extends CFRetainedResource {
private void deliverKeyEvent(NSEvent event) {
responder.handleKeyEvent(event.getType(), event.getModifierFlags(),
event.getCharactersIgnoringModifiers(), event.getKeyCode());
event.getCharactersIgnoringModifiers(), event.getKeyCode(), true);
}
private void deliverWindowDidExposeEvent() {
......
......@@ -661,11 +661,19 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
@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 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
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);
}
/*
......
......@@ -647,6 +647,15 @@ public class LWCToolkit extends LWToolkit {
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 {
......
......@@ -245,6 +245,12 @@ public final class NSEvent {
*/
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);
......
......@@ -124,7 +124,7 @@ const keyTable[] =
{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 @@ const nsKeyToJavaModifierTable[] =
* 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 @@ static struct _char {
}
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 @@ static unichar
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 @@ NsKeyModifiersToJavaModifiers(NSUInteger nsFlags)
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 @@ jint GetJavaMouseModifiers(NSInteger button, NSUInteger modifierFlags)
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 <AWTPeerControl>)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_ENTER(env);
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;
}
......@@ -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;
......
......@@ -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 @@ static JNF_CLASS_CACHE(jc_CPlatformWindow, "sun/lwawt/macosx/CPlatformWindow");
}
- (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 @@ AWT_ASSERT_APPKIT_THREAD;
[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 @@ AWT_ASSERT_APPKIT_THREAD;
JNIEnv *env = [ThreadUtilities getJNIEnv];
[self.javaPlatformWindow setJObject:nil withEnv:env];
self.growBoxWindow = nil;
[super dealloc];
}
......@@ -321,14 +260,6 @@ AWT_ASSERT_APPKIT_THREAD;
// 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 @@ AWT_ASSERT_APPKIT_THREAD;
// 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 @@ AWT_ASSERT_APPKIT_THREAD;
}
[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_NOT_APPKIT_THREAD;
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 @@ AWT_ASSERT_NOT_APPKIT_THREAD;
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_NOT_APPKIT_THREAD;
AWT_ASSERT_APPKIT_THREAD;
[window setAlphaValue:alpha];
[window.growBoxWindow setAlphaValue:alpha];
}];
JNF_COCOA_EXIT(env);
......
......@@ -648,6 +648,10 @@ extern JNFClassInfo jc_CDropTargetContextPeer;
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;
......
......@@ -70,19 +70,8 @@ static void CImage_CopyNSImageIntoArray
[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 @@ AWT_ASSERT_ANY_THREAD;
(*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;
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
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);
......
......@@ -371,7 +371,7 @@ public class BorderFactory
/**
* 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 @@ public class BorderFactory
/**
* 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 @@ public class BorderFactory
/**
* 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 @@ public class BorderFactory
*<li><code>TitledBorder.ABOVE_BOTTOM</code>
*<li><code>TitledBorder.BOTTOM</code> (sitting on the bottom line)
*<li><code>TitledBorder.BELOW_BOTTOM</code>
*<li><code>TitledBorder.DEFAULT_POSITION</code> (top)
*<li><code>TitledBorder.DEFAULT_POSITION</code> (the title position
* is determined by the current look and feel)
*</ul>
* @return the <code>TitledBorder</code> object
*/
......@@ -477,7 +478,8 @@ public class BorderFactory
*<li><code>TitledBorder.ABOVE_BOTTOM</code>
*<li><code>TitledBorder.BOTTOM</code> (sitting on the bottom line)
*<li><code>TitledBorder.BELOW_BOTTOM</code>
*<li><code>TitledBorder.DEFAULT_POSITION</code> (top)
*<li><code>TitledBorder.DEFAULT_POSITION</code> (the title position
* is determined by the current look and feel)
*</ul>
* @param titleFont a Font object specifying the title font
* @return the TitledBorder object
......@@ -516,7 +518,8 @@ public class BorderFactory
*<li><code>TitledBorder.ABOVE_BOTTOM</code>
*<li><code>TitledBorder.BOTTOM</code> (sitting on the bottom line)
*<li><code>TitledBorder.BELOW_BOTTOM</code>
*<li><code>TitledBorder.DEFAULT_POSITION</code> (top)
*<li><code>TitledBorder.DEFAULT_POSITION</code> (the title position
* is determined by the current look and feel)
*</ul>
* @param titleFont a <code>Font</code> object specifying the title font
* @param titleColor a <code>Color</code> object specifying the title color
......
......@@ -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 @@ class SynthComboPopup extends BasicComboPopup {
*
* @see #createList
*/
@Override
protected void configureList() {
list.setFont( comboBox.getFont() );
list.setCellRenderer( comboBox.getRenderer() );
......@@ -67,4 +64,27 @@ class SynthComboPopup extends BasicComboPopup {
}
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);
}
}
......@@ -31,7 +31,6 @@ import java.text.Bidi;
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 @@ public abstract class AbstractDocument implements Document, Serializable {
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 @@ public abstract class AbstractDocument implements Document, Serializable {
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 @@ public abstract class AbstractDocument implements Document, Serializable {
*/
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 abstract class AbstractDocument implements Document, Serializable {
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;
}
}
......@@ -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 @@ public class DefaultEditorKit extends EditorKit {
}
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);
}
}
}
}
......
......@@ -46,6 +46,7 @@ import sun.util.logging.PlatformLogger;
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 @@ public final class AppContext {
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,21 +219,11 @@ public final class AppContext {
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.
*/
......@@ -243,7 +243,7 @@ public final class AppContext {
* @since 1.2
*/
AppContext(ThreadGroup threadGroup) {
numAppContexts++;
numAppContexts.incrementAndGet();
this.threadGroup = threadGroup;
threadGroup2appContext.put(threadGroup, this);
......@@ -278,7 +278,7 @@ public final class AppContext {
* @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 @@ public final class AppContext {
this.table.clear(); // Clear out the Hashtable to ease garbage collection
}
numAppContexts--;
numAppContexts.decrementAndGet();
mostRecentKeyValue = null;
}
......@@ -804,7 +804,7 @@ public final class AppContext {
return getAppContext().isDisposed();
}
public boolean isMainAppContext() {
return (numAppContexts == 1);
return (numAppContexts.get() == 1);
}
});
}
......
......@@ -1125,6 +1125,16 @@ public abstract class SunToolkit extends Toolkit
return InputEvent.ALT_MASK;
}
/**
* 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}.
......
......@@ -82,7 +82,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
boolean paintPending = false;
boolean isLayouting = false;
boolean enabled;
private boolean enabled;
// Actually used only by XDecoratedPeer
protected int boundsOperation;
......@@ -128,9 +128,6 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
}
void postInit(XCreateWindowParams params) {
super.postInit(params);
Color c;
Font f;
Cursor cursor;
pSetCursor(target.getCursor());
......@@ -143,19 +140,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
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 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
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 void enable() {
setEnabled(true);
public final boolean isEnabled() {
synchronized (getStateLock()) {
return enabled;
}
}
public void disable() {
setEnabled(false);
}
@Override
public void paint(final Graphics g) {
super.paint(g);
......
/*
* 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) {
}
}
}
/*
* 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);
}
}
#!/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
/*
* 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; i<LOOPS_PER_LINE; i++) {
log("start->stop (" + 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) {}
}
}
/*
* 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 @@ public class AlawEncoderSync {
threads[i].start();
}
for (int i=1; i<THREAD_COUNT; i++) {
for (int i=0; i<THREAD_COUNT; i++) {
try {
threads[i].join();
} catch (InterruptedException ex) {
......
/*
* 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 7149090
@summary Nimbus:BorderFactory.createTitledBorder() the DEFAULT position of a title is not the same as the TOP
@author Pavel Porvatov
*/
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class Test7149090 {
private static final Object[][] DEFAULT_TITLE_POSITIONS = {
{"Metal", TitledBorder.TOP},
{"Motif", TitledBorder.TOP},
{"Windows", TitledBorder.TOP},
{"Nimbus", TitledBorder.ABOVE_TOP},
};
public static void main(String[] args) throws Exception {
for (UIManager.LookAndFeelInfo lookAndFeel : UIManager.getInstalledLookAndFeels()) {
for (Object[] defaultTitlePosition : DEFAULT_TITLE_POSITIONS) {
if (defaultTitlePosition[0].equals(lookAndFeel.getName())) {
UIManager.setLookAndFeel(lookAndFeel.getClassName());
final int expectedPosition = (Integer) defaultTitlePosition[1];
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
List<TitledBorder> 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());
}
}
}
}
}
/*
* 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 = "<synth>" +
" <style id=\"all\">" +
" <font name=\"Dialog\" size=\"12\"/>" +
" </style>" +
" <bind style=\"all\" type=\"REGION\" key=\".*\"/>" +
" <style id=\"arrowButton\">" +
" <property key=\"ArrowButton.size\" type=\"integer\" value=\"18\"/>" +
" </style>" +
" <bind style=\"arrowButton\" type=\"region\" key=\"ArrowButton\"/>" +
" <style id=\"comboBox\">" +
" <property key=\"ComboBox.popupInsets\" type=\"insets\" value=\"-5 -5 5 -5\"/>" +
" </style>" +
" <bind style=\"comboBox\" type=\"region\" key=\"ComboBox\"/>" +
"</synth>";
private static JComboBox<String> 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<Point>() {
@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");
}
});
}
}
......@@ -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;
/**
* <p>This class contains utilities useful for regression testing.
......@@ -153,4 +155,31 @@ public class Util {
robot.keyRelease(keys[i]);
}
}
/**
* Invokes the <code>task</code> on the EDT thread.
*
* @return result of the <code>task</code>
*/
public static <T> T invokeOnEDT(final Callable<T> task) throws Exception {
final List<T> 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);
}
}
/*
* 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, "<Test 1>", null);
Thread t1 = new Thread("Thread 1") {
@Override
public void run() {
try {
doc.insertString(0, "<Test 2>", 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();
}
}
......@@ -54,8 +54,12 @@ public class SharedMemoryPixmapsTest {
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) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册